@mnemom/mnemom 0.17.11-next.1 → 0.17.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/agent-doctor.d.ts +2 -0
- package/dist/commands/agent-doctor.js +32 -23
- package/dist/commands/agent-invite.d.ts +7 -0
- package/dist/commands/agent-invite.js +20 -1
- package/dist/commands/agent.d.ts +5 -0
- package/dist/commands/agent.js +31 -17
- package/dist/commands/experimental.d.ts +2 -0
- package/dist/commands/experimental.js +12 -0
- package/dist/index.js +5 -2
- package/dist/lib/experimental.d.ts +5 -0
- package/dist/lib/experimental.js +4 -2
- package/dist/lib/launcher-config.js +1 -1
- package/dist/lib/version-gate.js +1 -2
- package/package.json +1 -1
|
@@ -24,6 +24,8 @@ export interface CodeAccessProbe {
|
|
|
24
24
|
mark: Mark;
|
|
25
25
|
text: string;
|
|
26
26
|
hint?: string;
|
|
27
|
+
/** May this account use Remote Control? Only a determined `remote_control: true` says yes. */
|
|
28
|
+
remoteControl: boolean;
|
|
27
29
|
}
|
|
28
30
|
/**
|
|
29
31
|
* The invited-cohort gate, as the doctor reports it. Signed out → info (we can't
|
|
@@ -23,7 +23,7 @@ import { LAUNCHER_CONFIG_PATH } from "../lib/launcher-config.js";
|
|
|
23
23
|
import { getAgentByName, getCardSources, getCodeEntitlement, MnemomApiError } from "../lib/api.js";
|
|
24
24
|
import { isLoggedIn } from "../lib/auth.js";
|
|
25
25
|
import { getActiveOrg } from "../lib/cli-config.js";
|
|
26
|
-
import { isCodeNotEnabled, sourceLabel } from "./agent-invite.js";
|
|
26
|
+
import { isCodeNotEnabled, REQUEST_ACCESS_URL, sanitizeTerminalText, sourceLabel, withRequestAccess, } from "./agent-invite.js";
|
|
27
27
|
import { probeUpdateStatus } from "../lib/update/doctor.js";
|
|
28
28
|
import { describeModes, GOVERNANCE_OPT_IN_HINT, resolveDefaultSlug } from "./agent-setup.js";
|
|
29
29
|
const MARK = { ok: "[ ok ]", warn: "[warn]", miss: "[MISS]", info: "[info]" };
|
|
@@ -96,26 +96,31 @@ export async function agentDoctorCommand(options = {}) {
|
|
|
96
96
|
else {
|
|
97
97
|
add("warn", `gateway: ${host} [${cell}] unreachable (${health.detail})`, "check the host (MNEMOM_AGENT_GATEWAY / `mnemom agent config set gateway <url>`) and your network");
|
|
98
98
|
}
|
|
99
|
-
// ──
|
|
100
|
-
|
|
99
|
+
// ── Mnemom Agent access (invited cohort gate) ── probed here, before the Remote Control
|
|
100
|
+
// lines, because Remote Control is internal-only: an account the api does not entitle to it
|
|
101
|
+
// (every customer) never sees those lines at all.
|
|
102
|
+
const gate = await probeCodeAccess();
|
|
103
|
+
// ── Remote Control capability (entitled accounts only) ──
|
|
104
|
+
if (cli && gate.remoteControl) {
|
|
101
105
|
const rc = checkRcCapability(cli);
|
|
102
106
|
if (rc.ok)
|
|
103
107
|
add("ok", "Remote Control: available (node + openssl + --remote-control)");
|
|
104
108
|
else
|
|
105
109
|
add("warn", `Remote Control: unavailable — ${rc.missing.join("; ")}`, "launches fall back to terminal-only until these are in place");
|
|
106
|
-
// ── claude.ai login (informational — RC needs it) ──
|
|
107
|
-
if (cli.name === "claude") {
|
|
108
|
-
const login = claudeLoggedIn(cli.bin);
|
|
109
|
-
if (login === true)
|
|
110
|
-
add("ok", "claude.ai login: logged in");
|
|
111
|
-
else if (login === false)
|
|
112
|
-
add("info", "claude.ai login: not logged in", "Remote Control needs a claude.ai login; the terminal-only shape does not");
|
|
113
|
-
else
|
|
114
|
-
add("info", "claude.ai login: could not determine");
|
|
115
|
-
}
|
|
116
110
|
}
|
|
117
|
-
// ──
|
|
118
|
-
|
|
111
|
+
// ── claude.ai login (informational) ── Remote Control needs it, and so does auth =
|
|
112
|
+
// subscription; a terminal launch on an Anthropic key does not, so nobody else sees it.
|
|
113
|
+
if (cli && cli.name === "claude" && (gate.remoteControl || auth === "subscription")) {
|
|
114
|
+
const login = claudeLoggedIn(cli.bin);
|
|
115
|
+
if (login === true)
|
|
116
|
+
add("ok", "claude.ai login: logged in");
|
|
117
|
+
else if (login === false)
|
|
118
|
+
add("info", "claude.ai login: not logged in", auth === "subscription"
|
|
119
|
+
? "auth = subscription launches Claude Code on your claude.ai login — run `claude` and /login"
|
|
120
|
+
: "Remote Control needs a claude.ai login; the terminal-only shape does not");
|
|
121
|
+
else
|
|
122
|
+
add("info", "claude.ai login: could not determine");
|
|
123
|
+
}
|
|
119
124
|
add(gate.mark, gate.text, gate.hint);
|
|
120
125
|
// ── governance (off by default for new agents) ──
|
|
121
126
|
const gov = await probeGovernance(options.agent);
|
|
@@ -192,7 +197,8 @@ export async function probeCodeAccess() {
|
|
|
192
197
|
return {
|
|
193
198
|
mark: "info",
|
|
194
199
|
text: "Mnemom Agent access: sign in to check",
|
|
195
|
-
hint:
|
|
200
|
+
hint: `run \`mnemom login\`; @mnemom.ai accounts are enabled by default, others need an invitation (mnemom agent --invite <token>) — request one at ${REQUEST_ACCESS_URL}`,
|
|
201
|
+
remoteControl: false,
|
|
196
202
|
};
|
|
197
203
|
}
|
|
198
204
|
const org = getActiveOrg();
|
|
@@ -202,9 +208,7 @@ export async function probeCodeAccess() {
|
|
|
202
208
|
return {
|
|
203
209
|
mark: "ok",
|
|
204
210
|
text: `Mnemom Agent access: enabled for ${orgLabel} (${sourceLabel(ent.source)})`,
|
|
205
|
-
|
|
206
|
-
? undefined
|
|
207
|
-
: "Remote Control (steer from claude.ai / the Claude app) is an internal feature — your sessions run terminal-only",
|
|
211
|
+
remoteControl: ent.remote_control === true,
|
|
208
212
|
};
|
|
209
213
|
}
|
|
210
214
|
catch (err) {
|
|
@@ -213,13 +217,18 @@ export async function probeCodeAccess() {
|
|
|
213
217
|
return {
|
|
214
218
|
mark: "miss",
|
|
215
219
|
text: `Mnemom Agent access: not enabled for ${orgLabel}`,
|
|
216
|
-
hint: typeof hint === "string" && hint
|
|
217
|
-
? hint
|
|
218
|
-
: "redeem an invitation: mnemom agent --invite <token>",
|
|
220
|
+
hint: withRequestAccess(typeof hint === "string" && hint
|
|
221
|
+
? sanitizeTerminalText(hint)
|
|
222
|
+
: "redeem an invitation: mnemom agent --invite <token>"),
|
|
223
|
+
remoteControl: false,
|
|
219
224
|
};
|
|
220
225
|
}
|
|
221
226
|
const detail = err instanceof MnemomApiError || err instanceof Error ? err.message : String(err);
|
|
222
|
-
return {
|
|
227
|
+
return {
|
|
228
|
+
mark: "info",
|
|
229
|
+
text: `Mnemom Agent access: could not determine (${detail})`,
|
|
230
|
+
remoteControl: false,
|
|
231
|
+
};
|
|
223
232
|
}
|
|
224
233
|
}
|
|
225
234
|
const OPT_IN_HINT = GOVERNANCE_OPT_IN_HINT.trim();
|
|
@@ -29,6 +29,13 @@ export declare class CodeNotEnabledError extends Error {
|
|
|
29
29
|
/** `pinv_` + base64url — the product-invite token shape the api mints. */
|
|
30
30
|
export declare const INVITE_TOKEN_RE: RegExp;
|
|
31
31
|
export declare function looksLikeInviteToken(value: unknown): value is string;
|
|
32
|
+
/**
|
|
33
|
+
* Where someone without an invitation (or a Mnemom contact) asks for access. Every
|
|
34
|
+
* locked-out message ends with it, so an uninvited customer is never at a dead end.
|
|
35
|
+
*/
|
|
36
|
+
export declare const REQUEST_ACCESS_URL = "https://www.mnemom.ai/contact";
|
|
37
|
+
/** `hint`, plus the request-access pointer unless the hint already carries the URL. */
|
|
38
|
+
export declare function withRequestAccess(hint: string): string;
|
|
32
39
|
/** Drop control characters (ANSI escapes included) from an api-supplied string before
|
|
33
40
|
* it reaches the terminal — defense in depth; the value is first-party but printed raw. */
|
|
34
41
|
export declare function sanitizeTerminalText(s: string): string;
|
|
@@ -39,6 +39,25 @@ export function looksLikeInviteToken(value) {
|
|
|
39
39
|
return typeof value === "string" && INVITE_TOKEN_RE.test(value.trim());
|
|
40
40
|
}
|
|
41
41
|
const FALLBACK_HINT = "Ask your Mnemom contact for a Mnemom Agent invitation, then run: mnemom agent --invite <token>";
|
|
42
|
+
/**
|
|
43
|
+
* Where someone without an invitation (or a Mnemom contact) asks for access. Every
|
|
44
|
+
* locked-out message ends with it, so an uninvited customer is never at a dead end.
|
|
45
|
+
*/
|
|
46
|
+
export const REQUEST_ACCESS_URL = "https://www.mnemom.ai/contact";
|
|
47
|
+
/** Whether `hint` already names the request-access page, as a whole word (trailing
|
|
48
|
+
* punctuation ignored) — a token match, not a substring one. */
|
|
49
|
+
function mentionsRequestAccess(hint) {
|
|
50
|
+
return hint.split(/\s+/).some((w) => w.replace(/[.,;:!?)]+$/, "") === REQUEST_ACCESS_URL);
|
|
51
|
+
}
|
|
52
|
+
/** `hint`, plus the request-access pointer unless the hint already carries the URL. */
|
|
53
|
+
export function withRequestAccess(hint) {
|
|
54
|
+
if (mentionsRequestAccess(hint))
|
|
55
|
+
return hint;
|
|
56
|
+
let end = hint.length;
|
|
57
|
+
while (end > 0 && (hint[end - 1] === "." || hint[end - 1].trim() === ""))
|
|
58
|
+
end--;
|
|
59
|
+
return `${hint.slice(0, end)}. No invitation yet? Request access at ${REQUEST_ACCESS_URL}`;
|
|
60
|
+
}
|
|
42
61
|
/** Drop control characters (ANSI escapes included) from an api-supplied string before
|
|
43
62
|
* it reaches the terminal — defense in depth; the value is first-party but printed raw. */
|
|
44
63
|
export function sanitizeTerminalText(s) {
|
|
@@ -76,7 +95,7 @@ function printNotEnabled(orgLabel, hint) {
|
|
|
76
95
|
say();
|
|
77
96
|
say(" mnemom agent --invite <token>");
|
|
78
97
|
say();
|
|
79
|
-
say(fmt.dim(` ${hint}`));
|
|
98
|
+
say(fmt.dim(` ${withRequestAccess(hint)}`));
|
|
80
99
|
}
|
|
81
100
|
/**
|
|
82
101
|
* Enforce the Mnemom Agent gate for the org the launch targets. Blocks (prints
|
package/dist/commands/agent.d.ts
CHANGED
|
@@ -345,6 +345,11 @@ export declare function logLaunch(ctx: {
|
|
|
345
345
|
goalMode: string | null;
|
|
346
346
|
cli: ResolvedCli;
|
|
347
347
|
}): void;
|
|
348
|
+
/**
|
|
349
|
+
* The agent a signed-out `--dry-run` shows when the caller named none: the real name is
|
|
350
|
+
* `agent-<handle>` from the Mnemom login, which a dry run (no sign-in) cannot know yet.
|
|
351
|
+
*/
|
|
352
|
+
export declare const DRY_RUN_SIGNED_OUT_AGENT = "agent-<your Mnemom login handle>";
|
|
348
353
|
export declare function printPlan(ctx: {
|
|
349
354
|
scenario: string;
|
|
350
355
|
shape: LaunchShape;
|
package/dist/commands/agent.js
CHANGED
|
@@ -36,6 +36,7 @@ import { getApiUrl, getGatewayUrl, MNEMOM_DIR } from "../lib/config.js";
|
|
|
36
36
|
import { createApiKey } from "../lib/api.js";
|
|
37
37
|
import { MNEMOM_KEY_STORE_FIELD, resolveAgentAuth, resolveSubscriptionMnemomKey, subscriptionChildEnv, subscriptionShape, } from "../lib/subscription-login.js";
|
|
38
38
|
import { LEDGER_FILE, appendSessionRecord, findResumeCandidate, readSessionRecords, resolveRetentionDays, resumedContextProfile, toLedgerContract, } from "../lib/agent-ledger.js";
|
|
39
|
+
import { isLoggedIn } from "../lib/auth.js";
|
|
39
40
|
import { loadCliConfig } from "../lib/cli-config.js";
|
|
40
41
|
import { configKeySpec, loadLauncherConfig, writeLauncherConfig } from "../lib/launcher-config.js";
|
|
41
42
|
import { experimentalNotice } from "../lib/experimental.js";
|
|
@@ -261,20 +262,26 @@ export async function agentCommand(scenarioArg, options = {}) {
|
|
|
261
262
|
// which we only know AFTER sign-in. The entitlement-aware decision
|
|
262
263
|
// (`resolveRemoteControlShape`) happens below, right after
|
|
263
264
|
// `ensureSessionAndBalance`. --dry-run prints the plan BEFORE sign-in, so it
|
|
264
|
-
// can't know the entitlement
|
|
265
|
-
//
|
|
266
|
-
//
|
|
265
|
+
// can't know the entitlement: it previews the REQUESTED shape (terminal unless
|
|
266
|
+
// --remote-control/--server or `launch` asked otherwise) and never the RC
|
|
267
|
+
// auto-upgrade, which only an entitled (internal) account gets. An explicit RC
|
|
268
|
+
// request gets the note that the real launch still applies the entitlement gate.
|
|
267
269
|
if (options.dryRun) {
|
|
268
270
|
const planCli = cli ?? {
|
|
269
271
|
bin: "(not found — pass --cli <path> or `mnemom agent config set cli <path>`)",
|
|
270
272
|
name: basename((options.cli || env.MNEMOM_AGENT_CLI || "claude").trim()),
|
|
271
273
|
};
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
274
|
+
// A defaulted slug is `agent-<handle>` from the login (resolved for real after
|
|
275
|
+
// sign-in, below). Signed in: show that name. Signed out, or no usable handle:
|
|
276
|
+
// say where it comes from rather than print the "agent-user" fallback as if it were it.
|
|
277
|
+
if (!options.agent?.trim()) {
|
|
278
|
+
agent =
|
|
279
|
+
((await isLoggedIn()) && sanitizeAgentName(await resolveDefaultSlug())) ||
|
|
280
|
+
DRY_RUN_SIGNED_OUT_AGENT;
|
|
281
|
+
}
|
|
275
282
|
printPlan({
|
|
276
283
|
scenario,
|
|
277
|
-
shape
|
|
284
|
+
shape,
|
|
278
285
|
agent,
|
|
279
286
|
// The org is only known after sign-in, so a dry run never offers a resume (IG5 #1).
|
|
280
287
|
conversationId: resolveConversationId(options.conversationId),
|
|
@@ -298,8 +305,8 @@ export async function agentCommand(scenarioArg, options = {}) {
|
|
|
298
305
|
}
|
|
299
306
|
if (expNotice)
|
|
300
307
|
say(expNotice);
|
|
301
|
-
if (
|
|
302
|
-
say("mnemom agent: the
|
|
308
|
+
if (shape !== "terminal") {
|
|
309
|
+
say("mnemom agent: the real launch uses this shape only if your account is entitled to it, else terminal-only.");
|
|
303
310
|
}
|
|
304
311
|
sayContextProfile(contextProfile);
|
|
305
312
|
sayCompaction(contextProfile, compactionIntercept, compactAt, launchWindow(windowModelFor(options, cli)));
|
|
@@ -314,14 +321,6 @@ export async function agentCommand(scenarioArg, options = {}) {
|
|
|
314
321
|
if (!cli) {
|
|
315
322
|
cli = await promptForCliPath(options.cli, env, cliError);
|
|
316
323
|
}
|
|
317
|
-
// ── resolve the Anthropic key (zero 1Password; never logged) ──
|
|
318
|
-
// Not on a subscription launch: Claude Code then sends its own claude.ai login instead.
|
|
319
|
-
// A Console launch uses the key Claude Code's Console login created, then runs as api-key.
|
|
320
|
-
const anthropicKey = auth === "subscription"
|
|
321
|
-
? undefined
|
|
322
|
-
: auth === "console"
|
|
323
|
-
? requireConsoleKey(defaultConsoleKeyDeps(env))
|
|
324
|
-
: await resolveAnthropicKey(env, { allowPrompt: true, keySource: options.keySource });
|
|
325
324
|
// ── account + µ-balance gate (no free tier) ─────────────────────────────────
|
|
326
325
|
// mnemom agent runs governed and on µ, so before we seal a contract or launch we
|
|
327
326
|
// (1) ensure a Mnemom session — offering the try-me-style sign-in / sign-up when
|
|
@@ -342,6 +341,16 @@ export async function agentCommand(scenarioArg, options = {}) {
|
|
|
342
341
|
process.exit(1); // guidance already printed
|
|
343
342
|
throw err;
|
|
344
343
|
}
|
|
344
|
+
// ── resolve the Anthropic key (zero 1Password; never logged) ──
|
|
345
|
+
// AFTER the account gate above: an account Mnemom Agent is not enabled for learns that
|
|
346
|
+
// (and how to get access) before it is asked for, or refused for want of, a key.
|
|
347
|
+
// Not on a subscription launch: Claude Code then sends its own claude.ai login instead.
|
|
348
|
+
// A Console launch uses the key Claude Code's Console login created, then runs as api-key.
|
|
349
|
+
const anthropicKey = auth === "subscription"
|
|
350
|
+
? undefined
|
|
351
|
+
: auth === "console"
|
|
352
|
+
? requireConsoleKey(defaultConsoleKeyDeps(env))
|
|
353
|
+
: await resolveAnthropicKey(env, { allowPrompt: true, keySource: options.keySource });
|
|
345
354
|
// ── Remote-Control entitlement gate ─────────────────────────────────────────
|
|
346
355
|
// Remote Control (a session steerable from claude.ai / the Claude app) is
|
|
347
356
|
// internal-only. Now that we know the org's entitlement, resolve the final
|
|
@@ -1585,6 +1594,11 @@ export function logLaunch(ctx) {
|
|
|
1585
1594
|
say(`mnemom agent: goal mode: ${ctx.goalMode} (inferred from your messages; watch x-mnemom-goal-revision / x-mnemom-goal-steer on each response)`);
|
|
1586
1595
|
}
|
|
1587
1596
|
}
|
|
1597
|
+
/**
|
|
1598
|
+
* The agent a signed-out `--dry-run` shows when the caller named none: the real name is
|
|
1599
|
+
* `agent-<handle>` from the Mnemom login, which a dry run (no sign-in) cannot know yet.
|
|
1600
|
+
*/
|
|
1601
|
+
export const DRY_RUN_SIGNED_OUT_AGENT = "agent-<your Mnemom login handle>";
|
|
1588
1602
|
export function printPlan(ctx) {
|
|
1589
1603
|
const L = [];
|
|
1590
1604
|
L.push("mnemom agent — launch plan (dry run)");
|
|
@@ -16,3 +16,5 @@ export declare function experimentalEnableCommand(id: string | undefined, deps?:
|
|
|
16
16
|
export declare function experimentalDisableCommand(id: string | undefined, deps?: ExperimentalDeps): void;
|
|
17
17
|
/** The one-time migration (lib/experimental.ts migrateExperimental) against the real files. */
|
|
18
18
|
export declare function runExperimentalMigration(): void;
|
|
19
|
+
/** Does `dir` exist with anything in it? Unreadable counts as yes (an upgrader keeps the notice). */
|
|
20
|
+
export declare function hasPriorState(dir: string): boolean;
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* `mnemom experimental list [--json] | enable <id> | disable <id>` — turn experimental
|
|
3
3
|
* features on and off (registry: lib/experimental.ts; stored in ~/.mnemom/config.json).
|
|
4
4
|
*/
|
|
5
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
5
6
|
import { EXPERIMENTAL_CONTRACT, EXPERIMENTAL_ENV, EXPERIMENTAL_FEATURES, EXPERIMENTAL_IDS, isExperimentalId, migrateExperimental, resolveExperimental, } from "../lib/experimental.js";
|
|
6
7
|
import { loadCliConfig, setExperimentalEnabled } from "../lib/cli-config.js";
|
|
8
|
+
import { MNEMOM_DIR } from "../lib/config.js";
|
|
7
9
|
import { launcherEntries, loadLauncherConfig } from "../lib/launcher-config.js";
|
|
8
10
|
function defaultDeps() {
|
|
9
11
|
return {
|
|
@@ -74,5 +76,15 @@ export function runExperimentalMigration() {
|
|
|
74
76
|
launcherEntries: () => launcherEntries(loadLauncherConfig()),
|
|
75
77
|
persist: (ids) => setExperimentalEnabled(ids),
|
|
76
78
|
writeErr: (line) => void process.stderr.write(line),
|
|
79
|
+
priorInstall: () => hasPriorState(MNEMOM_DIR),
|
|
77
80
|
});
|
|
78
81
|
}
|
|
82
|
+
/** Does `dir` exist with anything in it? Unreadable counts as yes (an upgrader keeps the notice). */
|
|
83
|
+
export function hasPriorState(dir) {
|
|
84
|
+
try {
|
|
85
|
+
return existsSync(dir) && readdirSync(dir).length > 0;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -155,8 +155,11 @@ const agentCmd = program
|
|
|
155
155
|
.option("--conversation-id <id>", "x-mnemom-conversation-id (default: auto-generated)")
|
|
156
156
|
.option("--cli <name|path>", "Coding-agent CLI to launch: a name or full path (default: claude)")
|
|
157
157
|
.option("--gateway <url>", "Gateway host override — must be the same cell as the rest of the CLI (default: that cell's gateway; or MNEMOM_AGENT_GATEWAY)")
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
// Remote Control is internal-only (the launch gates it on the org's entitlement and runs a
|
|
159
|
+
// customer terminal-only), so its two shapes stay out of --help for everyone. The help is
|
|
160
|
+
// built at load, before any sign-in, so it cannot ask the entitlement; the flags still parse.
|
|
161
|
+
.addOption(new Option("--remote-control", "Interactive Remote Control session in THIS terminal (behind a local proxy)").hideHelp())
|
|
162
|
+
.addOption(new Option("--server", "Headless `claude remote-control` dispatcher (behind a local proxy)").hideHelp())
|
|
160
163
|
.option("--auth <mode>", "How Claude Code authenticates: api-key (default) | subscription (your Claude Team/Enterprise login) | console (the API key your Claude Code Anthropic Console login created)")
|
|
161
164
|
.option("--model <alias|id>", "Model to launch (CLI alias or concrete id)")
|
|
162
165
|
.addOption(new Option("--effort <level>", "Reasoning effort").choices([
|
|
@@ -98,6 +98,11 @@ export interface MigrationDeps {
|
|
|
98
98
|
launcherEntries(): Array<[string, string]>;
|
|
99
99
|
persist(ids: ExperimentalId[]): void;
|
|
100
100
|
writeErr(line: string): void;
|
|
101
|
+
/**
|
|
102
|
+
* Did this machine run the CLI before this invocation (~/.mnemom already held something)?
|
|
103
|
+
* A brand-new install never had implicit on, so it gets no "it used to be on" notice.
|
|
104
|
+
*/
|
|
105
|
+
priorInstall(): boolean;
|
|
101
106
|
}
|
|
102
107
|
/** One-time notice for users who had implicit goal alignment by default (no goal_mode set). */
|
|
103
108
|
export declare const IMPLICIT_NOW_OFF_NOTICE: string;
|
package/dist/lib/experimental.js
CHANGED
|
@@ -213,6 +213,7 @@ export function migrateExperimental(deps) {
|
|
|
213
213
|
try {
|
|
214
214
|
if (deps.stored() !== undefined)
|
|
215
215
|
return null;
|
|
216
|
+
const upgrading = deps.priorInstall();
|
|
216
217
|
const entries = deps.launcherEntries();
|
|
217
218
|
const ids = featuresInUse(entries);
|
|
218
219
|
deps.persist(ids);
|
|
@@ -220,9 +221,10 @@ export function migrateExperimental(deps) {
|
|
|
220
221
|
deps.writeErr(`mnemom: ${ids.join(", ")} ${ids.length === 1 ? "is" : "are"} now experimental and kept on because your launcher.toml uses ${ids.length === 1 ? "it" : "them"} — see \`mnemom experimental list\`.\n`);
|
|
221
222
|
}
|
|
222
223
|
// Implicit was the unconfigured DEFAULT, so most users relied on it without a
|
|
223
|
-
// goal_mode entry. Don't let it switch off silently for them: say so once.
|
|
224
|
+
// goal_mode entry. Don't let it switch off silently for them: say so once. A fresh
|
|
225
|
+
// install had no default to lose, so it is told nothing.
|
|
224
226
|
const optedOut = entries.some(([k, v]) => k === "goal_mode" && v === "off");
|
|
225
|
-
if (!ids.includes("implicit") && !optedOut)
|
|
227
|
+
if (upgrading && !ids.includes("implicit") && !optedOut)
|
|
226
228
|
deps.writeErr(IMPLICIT_NOW_OFF_NOTICE);
|
|
227
229
|
return ids;
|
|
228
230
|
}
|
package/dist/lib/version-gate.js
CHANGED
|
@@ -74,8 +74,7 @@ export function enforceMinCliVersion(response, exit = process.exit, write = (chu
|
|
|
74
74
|
write(`\n✓ Updated the Mnemom CLI (was v${CLI_VERSION}; server minimum v${floor}). Re-run your command.\n\n`);
|
|
75
75
|
exit(1);
|
|
76
76
|
}
|
|
77
|
-
write(`\n✖ Your Mnemom CLI (v${CLI_VERSION}) is too old for this server (minimum v${floor}).\n` +
|
|
78
|
-
` Old CLIs can silently drop newer request fields — e.g. \`--org\` on \`mnemom agent claim\`.\n\n` +
|
|
77
|
+
write(`\n✖ Your Mnemom CLI (v${CLI_VERSION}) is too old for this server (minimum v${floor}).\n\n` +
|
|
79
78
|
` Upgrade: npm i -g @mnemom/mnemom@latest\n\n`);
|
|
80
79
|
exit(1);
|
|
81
80
|
}
|