@mnemom/mnemom 0.17.21 → 0.17.23
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 +51 -15
- package/dist/commands/agent-export.d.ts +53 -0
- package/dist/commands/agent-export.js +127 -0
- package/dist/commands/agent.d.ts +13 -4
- package/dist/commands/agent.js +23 -10
- package/dist/commands/experimental.js +8 -1
- package/dist/index.js +24 -25
- package/dist/lib/agent-export.d.ts +133 -0
- package/dist/lib/agent-export.js +293 -0
- package/dist/lib/agent.d.ts +30 -17
- package/dist/lib/agent.js +42 -30
- package/dist/lib/api.d.ts +12 -0
- package/dist/lib/api.js +17 -0
- package/dist/lib/experimental.d.ts +13 -10
- package/dist/lib/experimental.js +19 -38
- package/dist/lib/launcher-config.d.ts +5 -6
- package/dist/lib/launcher-config.js +4 -11
- package/package.json +1 -1
package/dist/lib/agent.js
CHANGED
|
@@ -503,16 +503,24 @@ export const CONTEXT_HEAD_RECLAIM_KEY = "CONTEXT_RUNTIME_HEAD_BREAKPOINT_RECLAIM
|
|
|
503
503
|
export const CONTEXT_SIZE_POLICY_KEY = "CONTEXT_RUNTIME_SIZE_POLICY";
|
|
504
504
|
/**
|
|
505
505
|
* The two gateway env keys the `compaction_intercept` setting turns on for a single session
|
|
506
|
-
* (payload-bound fix; both
|
|
506
|
+
* (payload-bound fix; both read from the per-session overlay). The us-2 prod cell runs both on in
|
|
507
|
+
* its own cell env; the test and us-1 preview cells leave them at the gateway default (off). Since
|
|
508
|
+
* 0.17.23 the CLI asks for them on every launch — a deliberate, authorized rollout decision
|
|
509
|
+
* (MNE-8532, CTO 2026-10-12): every cell a `mnemom agent` session runs on then behaves like
|
|
510
|
+
* prod, rather than the CLI deferring to a non-prod cell's off default. The keys are TUNE-tier
|
|
511
|
+
* (gateway session-config allowlist, honored for any authenticated agent), so a cell without
|
|
512
|
+
* the companion support drops them and the session behaves as before.
|
|
507
513
|
* - `GATEWAY_USAGE_REAL_SIZE` — report the size of the body the client actually sent (the
|
|
508
514
|
* REAL, unfolded context) in the last `usage.iterations` entry, so Claude Code's own
|
|
509
515
|
* auto-compact threshold (its 1M default, or the user's `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` /
|
|
510
516
|
* `CLAUDE_CODE_AUTO_COMPACT_WINDOW` / `autoCompactWindow`) fires as it would without the fold;
|
|
511
517
|
* - `GATEWAY_COMPACTION_INTERCEPT` — answer the client's compaction request at once from the
|
|
512
518
|
* gateway's own fold digest (no model call), so the compaction never blocks the user.
|
|
513
|
-
* Sent together, value `"on"`, when the `compaction_intercept` setting is on
|
|
514
|
-
* (`resolveCompactionIntercept`) OR when `--compact-at` arms a target below 1M (below)
|
|
515
|
-
* target cannot be honored without both.
|
|
519
|
+
* Sent together, value `"on"`, when the `compaction_intercept` setting is on — the DEFAULT since
|
|
520
|
+
* 0.17.23 (`resolveCompactionIntercept`) — OR when `--compact-at` arms a target below 1M (below):
|
|
521
|
+
* a target cannot be honored without both. An opt-out (`--no-compaction-intercept`,
|
|
522
|
+
* `compaction_intercept = false`, `MNEMOM_AGENT_COMPACTION_INTERCEPT=0`) and the `off` context
|
|
523
|
+
* profile send both as `"off"`, so the opt-out holds on a cell whose own default is on.
|
|
516
524
|
*/
|
|
517
525
|
export const USAGE_REAL_SIZE_KEY = "GATEWAY_USAGE_REAL_SIZE";
|
|
518
526
|
export const COMPACTION_INTERCEPT_KEY = "GATEWAY_COMPACTION_INTERCEPT";
|
|
@@ -576,12 +584,12 @@ export const CONTEXT_HANDOFF_KEY = "CONTEXT_HANDOFF_ENABLED";
|
|
|
576
584
|
// Lets an operator play with WHEN the gateway pulls this session's own client-visible
|
|
577
585
|
// compaction point forward (GATEWAY_COMPACTION_UPLOAD_TARGET_TOKENS, #2251), instead of
|
|
578
586
|
// leaving Claude Code to compact on its own 1M-window schedule. Unset / `1m` / `off` all
|
|
579
|
-
// mean the SAME thing — no target — so
|
|
580
|
-
//
|
|
581
|
-
//
|
|
582
|
-
//
|
|
583
|
-
//
|
|
584
|
-
//
|
|
587
|
+
// mean the SAME thing — no target — so no target key is sent: Claude Code's own 1M window, no
|
|
588
|
+
// gateway-triggered compaction. A value strictly below 1,000,000 sends the target itself and
|
|
589
|
+
// arms the compaction intercept (USAGE_REAL_SIZE_KEY + COMPACTION_INTERCEPT_KEY, above — on by
|
|
590
|
+
// default since 0.17.23; #2216: both are required for the upload pull to be honored instead of
|
|
591
|
+
// silently inert), even over a standing opt-out in launcher.toml or the environment; only an
|
|
592
|
+
// explicit --no-compaction-intercept in the same launch is refused (assertCompactAtCompatible). Refold (GATEWAY_COMPACTION_REFOLD)
|
|
585
593
|
// is a SEPARATE, costlier opt-in (+9.5pts measured) — this setting never touches it. This never
|
|
586
594
|
// sets a Claude Code autocompact env/window: Claude Code's own compaction math is untouched;
|
|
587
595
|
// only what the GATEWAY reports back changes.
|
|
@@ -704,15 +712,13 @@ export function resolveCompactAt(opts) {
|
|
|
704
712
|
* (either silently re-arming the intercept the user just turned off, or silently sending an
|
|
705
713
|
* inert upload-target the gateway can never act on). `compactionIntercept` here is the raw,
|
|
706
714
|
* pre-`resolveCompactionIntercept` flag value: `false` only when `--no-compaction-intercept`
|
|
707
|
-
* was explicitly passed
|
|
708
|
-
* past either — see index.ts's `assertEnabled`), never the mere absence of `--compaction-intercept`.
|
|
715
|
+
* was explicitly passed, never the mere absence of `--compaction-intercept`.
|
|
709
716
|
*/
|
|
710
717
|
export function assertCompactAtCompatible(opts) {
|
|
711
718
|
if (opts.compactionIntercept === false && opts.compactAt !== null) {
|
|
712
|
-
throw new Error("mnemom agent: --compact-at needs the compaction intercept to arm, but
|
|
713
|
-
"
|
|
714
|
-
"
|
|
715
|
-
"enable compaction-intercept`), or pass --compact-at off.");
|
|
719
|
+
throw new Error("mnemom agent: --compact-at needs the compaction intercept to arm, but " +
|
|
720
|
+
"--no-compaction-intercept turns it off for this launch. Drop --no-compaction-intercept, " +
|
|
721
|
+
"or pass --compact-at off.");
|
|
716
722
|
}
|
|
717
723
|
}
|
|
718
724
|
/**
|
|
@@ -1039,13 +1045,14 @@ export function resolveContextProfile(opts) {
|
|
|
1039
1045
|
* no profile was chosen), then `CONTEXT_HANDOFF_ENABLED: "true"` when context handoff is ON, then
|
|
1040
1046
|
* `GATEWAY_USAGE_SAVINGS: "on"` when measured savings is ON (under every profile), then
|
|
1041
1047
|
* `GATEWAY_USAGE_REAL_SIZE: "on"` + `GATEWAY_COMPACTION_INTERCEPT: "on"` when EITHER the
|
|
1042
|
-
* `compaction_intercept` setting is ON OR `--compact-at` arms a target below 1M (the
|
|
1043
|
-
* cannot be honored without the intercept)
|
|
1044
|
-
*
|
|
1048
|
+
* `compaction_intercept` setting is ON (the default) OR `--compact-at` arms a target below 1M (the
|
|
1049
|
+
* target cannot be honored without the intercept) — or both as `"off"` when the setting is
|
|
1050
|
+
* explicitly `false` (an opt-out) and no target is armed, so the opt-out holds on a cell whose own
|
|
1051
|
+
* env turns them on — then `GATEWAY_COMPACTION_UPLOAD_TARGET_TOKENS: "<N>"` when a target is set. The `off` profile wins over the intercept and the target: a session with
|
|
1045
1052
|
* no fold never has its compaction intercepted (`assertOffProfileCompatible` refuses the explicit
|
|
1046
1053
|
* flag pair; a standing intercept or target from the environment or launcher.toml is dropped).
|
|
1047
|
-
* Empty with no profile chosen
|
|
1048
|
-
* no header is sent at all. Exported so `--dry-run` can list exactly what the header carries.
|
|
1054
|
+
* Empty with no profile chosen, everything else off and `compactionIntercept` absent (callers
|
|
1055
|
+
* that do not resolve it) — then no header is sent at all. Exported so `--dry-run` can list exactly what the header carries.
|
|
1049
1056
|
*/
|
|
1050
1057
|
export function buildSessionConfig(opts) {
|
|
1051
1058
|
const config = {};
|
|
@@ -1068,6 +1075,12 @@ export function buildSessionConfig(opts) {
|
|
|
1068
1075
|
config[USAGE_REAL_SIZE_KEY] = "on";
|
|
1069
1076
|
config[COMPACTION_INTERCEPT_KEY] = "on";
|
|
1070
1077
|
}
|
|
1078
|
+
else if (opts.compactionIntercept === false) {
|
|
1079
|
+
// An opt-out says "off" by name: sending nothing would leave a cell whose own env turns the
|
|
1080
|
+
// intercept on (us-2) intercepting anyway.
|
|
1081
|
+
config[USAGE_REAL_SIZE_KEY] = "off";
|
|
1082
|
+
config[COMPACTION_INTERCEPT_KEY] = "off";
|
|
1083
|
+
}
|
|
1071
1084
|
if (hasCompactionTarget) {
|
|
1072
1085
|
config[GATEWAY_COMPACTION_UPLOAD_TARGET_KEY] = String(opts.compactAt);
|
|
1073
1086
|
}
|
|
@@ -1095,8 +1108,8 @@ export function buildSessionConfigPayload(opts) {
|
|
|
1095
1108
|
* `aggressive` → the three fold-tuning keys + `CONTEXT_RUNTIME_SIZE_POLICY: "off"`,
|
|
1096
1109
|
* `balanced` → `CONTEXT_RUNTIME_SIZE_POLICY: "off"`, `adaptive` →
|
|
1097
1110
|
* `CONTEXT_RUNTIME_SIZE_POLICY: "banded"`, none chosen → nothing;
|
|
1098
|
-
* - `compactionIntercept: true` → `GATEWAY_USAGE_REAL_SIZE` +
|
|
1099
|
-
* `"on"` (
|
|
1111
|
+
* - `compactionIntercept: true` (the default) → `GATEWAY_USAGE_REAL_SIZE` +
|
|
1112
|
+
* `GATEWAY_COMPACTION_INTERCEPT` `"on"`; `false` (an opt-out) → both `"off"`;
|
|
1100
1113
|
* - `compactAt: <N>` (`--compact-at`, below 1M) → the SAME two intercept keys plus
|
|
1101
1114
|
* `GATEWAY_COMPACTION_UPLOAD_TARGET_TOKENS: "<N>"`; unset, `1m` or `off` → nothing beyond
|
|
1102
1115
|
* what `compactionIntercept` already sent (Claude Code's own 1M window, untouched);
|
|
@@ -1131,18 +1144,17 @@ export function resolveContextHandoff(opts) {
|
|
|
1131
1144
|
}
|
|
1132
1145
|
/**
|
|
1133
1146
|
* Is the compaction intercept (`GATEWAY_USAGE_REAL_SIZE` + `GATEWAY_COMPACTION_INTERCEPT` in the
|
|
1134
|
-
* session-config header) ON for this launch?
|
|
1135
|
-
* `
|
|
1136
|
-
* wins, else `MNEMOM_AGENT_COMPACTION_INTERCEPT` (which
|
|
1137
|
-
* `compaction_intercept` config key
|
|
1147
|
+
* session-config header) ON for this launch? ON by default since 0.17.23 (it graduated from the
|
|
1148
|
+
* `compaction-intercept` experimental feature). An explicit `--compaction-intercept` /
|
|
1149
|
+
* `--no-compaction-intercept` wins, else `MNEMOM_AGENT_COMPACTION_INTERCEPT` (which
|
|
1150
|
+
* `applyConfigToEnv` sets from the `compaction_intercept` config key: `0`/`false`/`off`/`no`
|
|
1151
|
+
* opt out), else ON.
|
|
1138
1152
|
*/
|
|
1139
1153
|
export function resolveCompactionIntercept(opts) {
|
|
1140
1154
|
if (opts.compactionIntercept !== undefined)
|
|
1141
1155
|
return opts.compactionIntercept;
|
|
1142
1156
|
const raw = (opts.env?.MNEMOM_AGENT_COMPACTION_INTERCEPT ?? "").trim().toLowerCase();
|
|
1143
|
-
|
|
1144
|
-
return false;
|
|
1145
|
-
return raw === "1" || raw === "true" || raw === "on" || raw === "yes";
|
|
1157
|
+
return !(raw === "0" || raw === "false" || raw === "off" || raw === "no");
|
|
1146
1158
|
}
|
|
1147
1159
|
/**
|
|
1148
1160
|
* Does the gateway measure this launch's saving (`GATEWAY_USAGE_SAVINGS` in the header, and the
|
package/dist/lib/api.d.ts
CHANGED
|
@@ -371,6 +371,18 @@ export interface MoveAgentResult {
|
|
|
371
371
|
export declare function moveAgent(agentId: string, destOrgId: string, opts?: {
|
|
372
372
|
idempotencyKey?: string;
|
|
373
373
|
}): Promise<MoveAgentResult>;
|
|
374
|
+
/**
|
|
375
|
+
* GET /v1/agents/:id/compliance-export — the agent's full record (JSON or CSV).
|
|
376
|
+
*
|
|
377
|
+
* Returns the raw body bytes (written to disk verbatim so the checksum the CLI
|
|
378
|
+
* prints matches what the server sent) plus the response headers (CSV carries
|
|
379
|
+
* its per-section counts in `X-Mnemom-Export-Counts`). `query` is the full
|
|
380
|
+
* `?format=…&from=…&to=…` string (see lib/agent-export.ts buildExportQuery).
|
|
381
|
+
*/
|
|
382
|
+
export declare function getComplianceExport(agentId: string, query: string): Promise<{
|
|
383
|
+
body: Uint8Array;
|
|
384
|
+
headers: Headers;
|
|
385
|
+
}>;
|
|
374
386
|
/**
|
|
375
387
|
* GET /v1/auth/me/personal-org — accessor for the user's personal org.
|
|
376
388
|
* Idempotent: lazily provisions for legacy accounts that pre-date the
|
package/dist/lib/api.js
CHANGED
|
@@ -367,6 +367,23 @@ export async function moveAgent(agentId, destOrgId, opts = {}) {
|
|
|
367
367
|
to_org_id: data.to_org_id ?? null,
|
|
368
368
|
};
|
|
369
369
|
}
|
|
370
|
+
/**
|
|
371
|
+
* GET /v1/agents/:id/compliance-export — the agent's full record (JSON or CSV).
|
|
372
|
+
*
|
|
373
|
+
* Returns the raw body bytes (written to disk verbatim so the checksum the CLI
|
|
374
|
+
* prints matches what the server sent) plus the response headers (CSV carries
|
|
375
|
+
* its per-section counts in `X-Mnemom-Export-Counts`). `query` is the full
|
|
376
|
+
* `?format=…&from=…&to=…` string (see lib/agent-export.ts buildExportQuery).
|
|
377
|
+
*/
|
|
378
|
+
export async function getComplianceExport(agentId, query) {
|
|
379
|
+
const url = validateUrl(`${API_BASE}/v1/agents/${encodeURIComponent(agentId)}/compliance-export${query}`);
|
|
380
|
+
const response = await fetchWithAuthRetry(url, async () => ({
|
|
381
|
+
headers: { ...(await authHeaders()), Accept: "application/json, text/csv" },
|
|
382
|
+
}));
|
|
383
|
+
if (!response.ok)
|
|
384
|
+
throw await readApiError(response, "Failed to export the agent record");
|
|
385
|
+
return { body: new Uint8Array(await response.arrayBuffer()), headers: response.headers };
|
|
386
|
+
}
|
|
370
387
|
/**
|
|
371
388
|
* GET /v1/auth/me/personal-org — accessor for the user's personal org.
|
|
372
389
|
* Idempotent: lazily provisions for legacy accounts that pre-date the
|
|
@@ -12,16 +12,20 @@
|
|
|
12
12
|
* Everything here is pure or dependency-injected; index.ts and the command
|
|
13
13
|
* modules are the thin drivers.
|
|
14
14
|
*/
|
|
15
|
-
export type ExperimentalId = "context-handoff" | "slack" | "implicit" | "
|
|
15
|
+
export type ExperimentalId = "context-handoff" | "slack" | "implicit" | "measured-savings";
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* admitting a value the real parser would reject anyway.
|
|
17
|
+
* Features that used to be experimental and are now on by default for everyone. Their ids are
|
|
18
|
+
* no longer in the registry, but `mnemom experimental enable|disable <id>` still accepts them
|
|
19
|
+
* as a no-op (with a one-line note naming the release and the real opt-out) instead of failing
|
|
20
|
+
* on an id a user, a script or an old README still names. Value: the release that graduated it
|
|
21
|
+
* and how to turn it off now.
|
|
23
22
|
*/
|
|
24
|
-
export declare
|
|
23
|
+
export declare const GRADUATED_FEATURES: Readonly<Record<string, {
|
|
24
|
+
since: string;
|
|
25
|
+
optOut: string;
|
|
26
|
+
}>>;
|
|
27
|
+
/** The one-line note for `mnemom experimental enable|disable <graduated id>`; null otherwise. */
|
|
28
|
+
export declare function graduatedNote(id: string): string | null;
|
|
25
29
|
export interface ExperimentalFeature {
|
|
26
30
|
id: ExperimentalId;
|
|
27
31
|
summary: string;
|
|
@@ -82,8 +86,7 @@ export declare function assertEnabled(uses: ReadonlyArray<{
|
|
|
82
86
|
export declare function experimentalIdForConfigKey(key: string, value: string): ExperimentalId | undefined;
|
|
83
87
|
/**
|
|
84
88
|
* The stderr lines for experimental settings a launch ignores because their feature
|
|
85
|
-
* is off: launcher.toml keys (`entries` as `[key, value]`)
|
|
86
|
-
* MNEMOM_AGENT_COMPACTION_INTERCEPT and MNEMOM_COMPACT_AT (an armed target only).
|
|
89
|
+
* is off: launcher.toml keys (`entries` as `[key, value]`) and MNEMOM_AGENT_CONTEXT_HANDOFF.
|
|
87
90
|
*/
|
|
88
91
|
export declare function ignoredSettingLines(opts: {
|
|
89
92
|
entries: ReadonlyArray<[string, string]>;
|
package/dist/lib/experimental.js
CHANGED
|
@@ -13,16 +13,24 @@
|
|
|
13
13
|
* modules are the thin drivers.
|
|
14
14
|
*/
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* admitting a value the real parser would reject anyway.
|
|
16
|
+
* Features that used to be experimental and are now on by default for everyone. Their ids are
|
|
17
|
+
* no longer in the registry, but `mnemom experimental enable|disable <id>` still accepts them
|
|
18
|
+
* as a no-op (with a one-line note naming the release and the real opt-out) instead of failing
|
|
19
|
+
* on an id a user, a script or an old README still names. Value: the release that graduated it
|
|
20
|
+
* and how to turn it off now.
|
|
22
21
|
*/
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
export const GRADUATED_FEATURES = {
|
|
23
|
+
"compaction-intercept": {
|
|
24
|
+
since: "0.17.23",
|
|
25
|
+
optOut: "--no-compaction-intercept, `compaction_intercept = false` in launcher.toml, or MNEMOM_AGENT_COMPACTION_INTERCEPT=0",
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
/** The one-line note for `mnemom experimental enable|disable <graduated id>`; null otherwise. */
|
|
29
|
+
export function graduatedNote(id) {
|
|
30
|
+
const g = GRADUATED_FEATURES[id];
|
|
31
|
+
if (!g)
|
|
32
|
+
return null;
|
|
33
|
+
return `${id} is no longer experimental: it is on by default since ${g.since}, so this changes nothing. To turn it off: ${g.optOut}.`;
|
|
26
34
|
}
|
|
27
35
|
export const EXPERIMENTAL_FEATURES = [
|
|
28
36
|
{
|
|
@@ -58,17 +66,6 @@ export const EXPERIMENTAL_FEATURES = [
|
|
|
58
66
|
env: [],
|
|
59
67
|
},
|
|
60
68
|
},
|
|
61
|
-
{
|
|
62
|
-
id: "compaction-intercept",
|
|
63
|
-
summary: "Have the gateway report the real context size (so Claude Code compacts at its own threshold) and answer the compaction at once from its fold",
|
|
64
|
-
since: "0.17.4",
|
|
65
|
-
gates: {
|
|
66
|
-
flags: ["--compaction-intercept"],
|
|
67
|
-
configKeys: ["compaction_intercept"],
|
|
68
|
-
commands: [],
|
|
69
|
-
env: ["MNEMOM_AGENT_COMPACTION_INTERCEPT"],
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
69
|
{
|
|
73
70
|
// No flag, launcher.toml key or env of its own: `mnemom experimental enable` is the switch.
|
|
74
71
|
id: "measured-savings",
|
|
@@ -162,25 +159,19 @@ export function experimentalIdForConfigKey(key, value) {
|
|
|
162
159
|
return value === "true" ? "slack" : undefined;
|
|
163
160
|
case "context_handoff":
|
|
164
161
|
return value === "true" ? "context-handoff" : undefined;
|
|
165
|
-
case "compaction_intercept":
|
|
166
|
-
return value === "true" ? "compaction-intercept" : undefined;
|
|
167
|
-
case "compact_at":
|
|
168
|
-
// Arms the SAME gateway keys compaction_intercept does — same gate.
|
|
169
|
-
return compactAtArmed(value) ? "compaction-intercept" : undefined;
|
|
170
162
|
case "goal_mode":
|
|
171
163
|
return value === "implicit" ? "implicit" : undefined;
|
|
172
164
|
default:
|
|
173
165
|
return undefined;
|
|
174
166
|
}
|
|
175
167
|
}
|
|
176
|
-
/** Is an env value one of the truthy spellings resolveContextHandoff
|
|
168
|
+
/** Is an env value one of the truthy spellings resolveContextHandoff accepts? */
|
|
177
169
|
function truthy(raw) {
|
|
178
170
|
return ["1", "true", "on", "yes"].includes((raw ?? "").trim().toLowerCase());
|
|
179
171
|
}
|
|
180
172
|
/**
|
|
181
173
|
* The stderr lines for experimental settings a launch ignores because their feature
|
|
182
|
-
* is off: launcher.toml keys (`entries` as `[key, value]`)
|
|
183
|
-
* MNEMOM_AGENT_COMPACTION_INTERCEPT and MNEMOM_COMPACT_AT (an armed target only).
|
|
174
|
+
* is off: launcher.toml keys (`entries` as `[key, value]`) and MNEMOM_AGENT_CONTEXT_HANDOFF.
|
|
184
175
|
*/
|
|
185
176
|
export function ignoredSettingLines(opts) {
|
|
186
177
|
const lines = [];
|
|
@@ -193,14 +184,6 @@ export function ignoredSettingLines(opts) {
|
|
|
193
184
|
if (truthy(opts.env.MNEMOM_AGENT_CONTEXT_HANDOFF) && !opts.enabled.includes("context-handoff")) {
|
|
194
185
|
lines.push(`mnemom agent: ignoring ${gatedMessage("MNEMOM_AGENT_CONTEXT_HANDOFF", "context-handoff")}`);
|
|
195
186
|
}
|
|
196
|
-
if (truthy(opts.env.MNEMOM_AGENT_COMPACTION_INTERCEPT) &&
|
|
197
|
-
!opts.enabled.includes("compaction-intercept")) {
|
|
198
|
-
lines.push(`mnemom agent: ignoring ${gatedMessage("MNEMOM_AGENT_COMPACTION_INTERCEPT", "compaction-intercept")}`);
|
|
199
|
-
}
|
|
200
|
-
if (compactAtArmed(opts.env.MNEMOM_COMPACT_AT) &&
|
|
201
|
-
!opts.enabled.includes("compaction-intercept")) {
|
|
202
|
-
lines.push(`mnemom agent: ignoring ${gatedMessage("MNEMOM_COMPACT_AT", "compaction-intercept")}`);
|
|
203
|
-
}
|
|
204
187
|
return lines;
|
|
205
188
|
}
|
|
206
189
|
/** The features an existing launcher.toml already uses (the one-time migration). */
|
|
@@ -250,8 +233,6 @@ export function configKeyFeature(key) {
|
|
|
250
233
|
return "slack";
|
|
251
234
|
if (key === "context_handoff")
|
|
252
235
|
return "context-handoff";
|
|
253
|
-
if (key === "compaction_intercept")
|
|
254
|
-
return "compaction-intercept";
|
|
255
236
|
if (key === "goal_mode")
|
|
256
237
|
return "implicit";
|
|
257
238
|
return undefined;
|
|
@@ -50,9 +50,9 @@ export interface LauncherConfig {
|
|
|
50
50
|
*/
|
|
51
51
|
contextHandoff?: boolean;
|
|
52
52
|
/**
|
|
53
|
-
* Compaction-intercept default (
|
|
53
|
+
* Compaction-intercept default (ON when unset, since 0.17.23): `true` sends
|
|
54
54
|
* `GATEWAY_USAGE_REAL_SIZE: "on"` + `GATEWAY_COMPACTION_INTERCEPT: "on"` in the per-session
|
|
55
|
-
* config header for every launch
|
|
55
|
+
* config header for every launch; `false` opts out and sends both as `"off"`.
|
|
56
56
|
*/
|
|
57
57
|
compactionIntercept?: boolean;
|
|
58
58
|
/**
|
|
@@ -121,9 +121,8 @@ export declare function launcherEntries(cfg: LauncherConfig): Array<[string, str
|
|
|
121
121
|
/**
|
|
122
122
|
* `cfg` without the settings of experimental features that are off (a copy; `cfg` is
|
|
123
123
|
* untouched): `slack_*` while `slack` is off, `context_handoff` while `context-handoff` is
|
|
124
|
-
* off, `
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* off (`goal_mode = off` is kept).
|
|
124
|
+
* off, and `goal_mode = implicit` while `implicit` is off (`goal_mode = off` is kept).
|
|
125
|
+
* `compaction_intercept` / `compact_at` are not experimental (on by default since 0.17.23) and
|
|
126
|
+
* always pass through.
|
|
128
127
|
*/
|
|
129
128
|
export declare function withoutDisabledExperimental(cfg: LauncherConfig, enabled: readonly ExperimentalId[]): LauncherConfig;
|
|
@@ -20,7 +20,6 @@ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "
|
|
|
20
20
|
import { dirname, join } from "node:path";
|
|
21
21
|
import { parse as parseToml, stringify as stringifyToml, TomlError } from "smol-toml";
|
|
22
22
|
import { MNEMOM_DIR } from "./config.js";
|
|
23
|
-
import { compactAtArmed } from "./experimental.js";
|
|
24
23
|
import { CONTEXT_PROFILES, isPositiveInt, isPositiveNumber, parseCompactAt, parseContextProfile, } from "./agent.js";
|
|
25
24
|
/** The human-editable settings file. Secret key lives elsewhere (launcher.json). */
|
|
26
25
|
export const LAUNCHER_CONFIG_PATH = join(MNEMOM_DIR, "launcher.toml");
|
|
@@ -207,7 +206,7 @@ export const CONFIG_KEYS = [
|
|
|
207
206
|
},
|
|
208
207
|
{
|
|
209
208
|
key: "compaction_intercept",
|
|
210
|
-
describe: "
|
|
209
|
+
describe: "Compaction intercept: the gateway reports the real context size and answers Claude Code's compaction from its fold (GATEWAY_USAGE_REAL_SIZE + GATEWAY_COMPACTION_INTERCEPT; on by default, false opts out)",
|
|
211
210
|
get: (c) => c.compactionIntercept,
|
|
212
211
|
set: (c, v) => {
|
|
213
212
|
c.compactionIntercept = coerceBool("compaction_intercept", v);
|
|
@@ -467,10 +466,9 @@ export function launcherEntries(cfg) {
|
|
|
467
466
|
/**
|
|
468
467
|
* `cfg` without the settings of experimental features that are off (a copy; `cfg` is
|
|
469
468
|
* untouched): `slack_*` while `slack` is off, `context_handoff` while `context-handoff` is
|
|
470
|
-
* off, `
|
|
471
|
-
*
|
|
472
|
-
*
|
|
473
|
-
* off (`goal_mode = off` is kept).
|
|
469
|
+
* off, and `goal_mode = implicit` while `implicit` is off (`goal_mode = off` is kept).
|
|
470
|
+
* `compaction_intercept` / `compact_at` are not experimental (on by default since 0.17.23) and
|
|
471
|
+
* always pass through.
|
|
474
472
|
*/
|
|
475
473
|
export function withoutDisabledExperimental(cfg, enabled) {
|
|
476
474
|
const out = { ...cfg };
|
|
@@ -481,11 +479,6 @@ export function withoutDisabledExperimental(cfg, enabled) {
|
|
|
481
479
|
}
|
|
482
480
|
if (!enabled.includes("context-handoff"))
|
|
483
481
|
delete out.contextHandoff;
|
|
484
|
-
if (!enabled.includes("compaction-intercept")) {
|
|
485
|
-
delete out.compactionIntercept;
|
|
486
|
-
if (compactAtArmed(out.compactAt))
|
|
487
|
-
delete out.compactAt;
|
|
488
|
-
}
|
|
489
482
|
if (!enabled.includes("implicit") && out.goalMode === "implicit")
|
|
490
483
|
delete out.goalMode;
|
|
491
484
|
return out;
|