@mnemom/mnemom 0.17.7-next.2 → 0.17.7
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 +13 -31
- package/dist/commands/agent-doctor.d.ts +4 -21
- package/dist/commands/agent-doctor.js +5 -51
- package/dist/commands/agent-goal.d.ts +1 -1
- package/dist/commands/agent-goal.js +3 -6
- package/dist/commands/agent-setup.d.ts +5 -16
- package/dist/commands/agent-setup.js +12 -29
- package/dist/commands/agent.d.ts +9 -32
- package/dist/commands/agent.js +50 -160
- package/dist/commands/wrap.d.ts +0 -8
- package/dist/commands/wrap.js +3 -36
- package/dist/index.js +1 -1
- package/dist/lib/agent-ledger.d.ts +3 -22
- package/dist/lib/agent-ledger.js +0 -23
- package/dist/lib/agent.d.ts +44 -100
- package/dist/lib/agent.js +44 -110
- package/dist/lib/api.d.ts +2 -27
- package/dist/lib/api.js +2 -64
- package/dist/lib/launcher-config.d.ts +4 -5
- package/dist/lib/launcher-config.js +1 -1
- package/dist/lib/subscription-login.d.ts +20 -152
- package/dist/lib/subscription-login.js +28 -215
- package/dist/mcp/handoff-server.mjs +13 -35
- package/dist/rc-proxy.mjs +3 -6
- package/package.json +1 -1
package/dist/lib/agent.d.ts
CHANGED
|
@@ -294,44 +294,22 @@ export declare const CONTEXT_TAIL_BUDGET_KEY = "CONTEXT_RUNTIME_TAIL_BUDGET_TOKE
|
|
|
294
294
|
export declare const CONTEXT_READ_CACHE_KEY = "CONTEXT_RUNTIME_READ_CACHE_TOKENS";
|
|
295
295
|
export declare const CONTEXT_HEAD_RECLAIM_KEY = "CONTEXT_RUNTIME_HEAD_BREAKPOINT_RECLAIM";
|
|
296
296
|
/**
|
|
297
|
-
* The gateway key
|
|
298
|
-
* Only the literal `banded` enables it;
|
|
299
|
-
*
|
|
300
|
-
* gateway's own defaults.
|
|
297
|
+
* The gateway key the `adaptive` context profile sets (allow-listed per session): turns on the
|
|
298
|
+
* size-banded fold policy. Only the literal `banded` enables it; the band thresholds and budgets
|
|
299
|
+
* stay at the gateway's own defaults.
|
|
301
300
|
*/
|
|
302
301
|
export declare const CONTEXT_SIZE_POLICY_KEY = "CONTEXT_RUNTIME_SIZE_POLICY";
|
|
303
|
-
/**
|
|
304
|
-
* The two gateway env keys the `compaction_intercept` setting turns on for a single session
|
|
305
|
-
* (payload-bound fix; both default OFF on the gateway, both read from the per-session overlay):
|
|
306
|
-
* - `GATEWAY_USAGE_REAL_SIZE` — report the size of the body the client actually sent (the
|
|
307
|
-
* REAL, unfolded context) in the last `usage.iterations` entry, so Claude Code's own
|
|
308
|
-
* auto-compact threshold (its 1M default, or the user's `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` /
|
|
309
|
-
* `CLAUDE_CODE_AUTO_COMPACT_WINDOW` / `autoCompactWindow`) fires as it would without the fold;
|
|
310
|
-
* - `GATEWAY_COMPACTION_INTERCEPT` — answer the client's compaction request at once from the
|
|
311
|
-
* gateway's own fold digest (no model call), so the compaction never blocks the user.
|
|
312
|
-
* Sent together, value `"on"`, when the `compaction_intercept` setting is on
|
|
313
|
-
* (`resolveCompactionIntercept`) OR when `--compact-at` arms a target below 1M (below) — a
|
|
314
|
-
* target cannot be honored without both. The `off` context profile sends both as `"off"`.
|
|
315
|
-
*/
|
|
316
|
-
export declare const USAGE_REAL_SIZE_KEY = "GATEWAY_USAGE_REAL_SIZE";
|
|
317
|
-
export declare const COMPACTION_INTERCEPT_KEY = "GATEWAY_COMPACTION_INTERCEPT";
|
|
318
302
|
/**
|
|
319
303
|
* The named presets for how the gateway folds a session's context (`--context-profile`,
|
|
320
|
-
* launcher.toml `context_profile`, `MNEMOM_AGENT_CONTEXT_PROFILE`)
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
* - `
|
|
324
|
-
*
|
|
325
|
-
* and
|
|
326
|
-
* The gateway already skips the intercept with the fold off, but the real-size
|
|
327
|
-
* usage rewrite is not gated on the fold, so `off` turns both off by name.
|
|
328
|
-
* - `balanced` → `CONTEXT_RUNTIME_SIZE_POLICY: "off"` — the cell's own fold budgets, never
|
|
329
|
-
* the size bands, even on a cell whose default is adaptive.
|
|
330
|
-
* - `aggressive` → a smaller tail budget + read cache and head-breakpoint reclaim on, size
|
|
331
|
-
* policy off: folds earlier and keeps a tighter working set at every size.
|
|
304
|
+
* launcher.toml `context_profile`, `MNEMOM_AGENT_CONTEXT_PROFILE`):
|
|
305
|
+
* - `off` → `CONTEXT_RUNTIME_ENABLED: "false"` — compaction is left to the coding agent
|
|
306
|
+
* (the same bytes `--no-context` has always sent).
|
|
307
|
+
* - `balanced` → NO fold keys: the gateway's own defaults stand. The default.
|
|
308
|
+
* - `aggressive` → a smaller tail budget + read cache and head-breakpoint reclaim on: folds
|
|
309
|
+
* earlier and keeps a tighter working set.
|
|
332
310
|
* - `adaptive` → `CONTEXT_RUNTIME_SIZE_POLICY: "banded"` — the gateway picks the fold by the
|
|
333
311
|
* conversation's original size: no fold below 200k tokens, the aggressive
|
|
334
|
-
* budgets from 200k to 1M, balanced above.
|
|
312
|
+
* budgets from 200k to 1M, balanced above. Opt-in; never the default.
|
|
335
313
|
*/
|
|
336
314
|
export declare const CONTEXT_PROFILES: readonly ["off", "balanced", "aggressive", "adaptive"];
|
|
337
315
|
export type ContextProfile = (typeof CONTEXT_PROFILES)[number];
|
|
@@ -344,6 +322,21 @@ export type ContextProfile = (typeof CONTEXT_PROFILES)[number];
|
|
|
344
322
|
* header without the tool.
|
|
345
323
|
*/
|
|
346
324
|
export declare const CONTEXT_HANDOFF_KEY = "CONTEXT_HANDOFF_ENABLED";
|
|
325
|
+
/**
|
|
326
|
+
* The two gateway env keys the `compaction_intercept` setting turns on for a single session
|
|
327
|
+
* (payload-bound fix; both default OFF on the gateway, both read from the per-session overlay):
|
|
328
|
+
* - `GATEWAY_USAGE_REAL_SIZE` — report the size of the body the client actually sent (the
|
|
329
|
+
* REAL, unfolded context) in the last `usage.iterations` entry, so Claude Code's own
|
|
330
|
+
* auto-compact threshold (its 1M default, or the user's `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` /
|
|
331
|
+
* `CLAUDE_CODE_AUTO_COMPACT_WINDOW` / `autoCompactWindow`) fires as it would without the fold;
|
|
332
|
+
* - `GATEWAY_COMPACTION_INTERCEPT` — answer the client's compaction request at once from the
|
|
333
|
+
* gateway's own fold digest (no model call), so the compaction never blocks the user.
|
|
334
|
+
* Sent together, value `"on"`, when the `compaction_intercept` setting is on
|
|
335
|
+
* (`resolveCompactionIntercept`) OR when `--compact-at` arms a target below 1M (below) — a
|
|
336
|
+
* target cannot be honored without both.
|
|
337
|
+
*/
|
|
338
|
+
export declare const USAGE_REAL_SIZE_KEY = "GATEWAY_USAGE_REAL_SIZE";
|
|
339
|
+
export declare const COMPACTION_INTERCEPT_KEY = "GATEWAY_COMPACTION_INTERCEPT";
|
|
347
340
|
export declare const GATEWAY_COMPACTION_UPLOAD_TARGET_KEY = "GATEWAY_COMPACTION_UPLOAD_TARGET_TOKENS";
|
|
348
341
|
/** The lowest token count `--compact-at` / `compact_at` / `MNEMOM_COMPACT_AT` will accept. */
|
|
349
342
|
export declare const COMPACT_AT_MIN_TOKENS = 50000;
|
|
@@ -419,19 +412,6 @@ export declare function assertCompactAtCompatible(opts: {
|
|
|
419
412
|
compactionIntercept?: boolean;
|
|
420
413
|
compactAt: number | null;
|
|
421
414
|
}): void;
|
|
422
|
-
/**
|
|
423
|
-
* The `off` context profile turns the fold off, and the compaction intercept answers a compaction
|
|
424
|
-
* from that fold, so `off` sends the intercept and real-size keys as `"off"`. An explicit
|
|
425
|
-
* `--compaction-intercept` or `--compact-at <N>` in the same launch asks for the opposite —
|
|
426
|
-
* refuse rather than silently drop the flag. A standing intercept or target (environment or
|
|
427
|
-
* launcher.toml) is not refused: the session's `off` wins and `buildSessionConfig` leaves it out.
|
|
428
|
-
* `compactionIntercept` / `compactAt` here are the raw flag values (`undefined` when not passed).
|
|
429
|
-
*/
|
|
430
|
-
export declare function assertOffProfileCompatible(opts: {
|
|
431
|
-
profile: ContextProfile | null;
|
|
432
|
-
compactionIntercept?: boolean;
|
|
433
|
-
compactAt?: number | null;
|
|
434
|
-
}): void;
|
|
435
415
|
/** The launch-banner line for the resolved compaction target (always printed). */
|
|
436
416
|
export declare function describeCompactAt(compactAt: number | null): string;
|
|
437
417
|
/**
|
|
@@ -491,10 +471,8 @@ export declare function launchPreferenceExplicit(opts: {
|
|
|
491
471
|
* Has an orchestrator already run the session + µ-balance preflight for this
|
|
492
472
|
* launch? `MNEMOM_AGENT_PREFLIGHTED=1` is for orchestrators (the ADW fleet) that
|
|
493
473
|
* checked sign-in and balance themselves before spawning many launches; it skips
|
|
494
|
-
* the per-launch session
|
|
495
|
-
*
|
|
496
|
-
* Mnemom key is minted for it), and the Mnemom Agent entitlement (which also
|
|
497
|
-
* gates Remote Control, fail-closed) is still fetched for it.
|
|
474
|
+
* the per-launch session/personal-org/balance round trips. The Mnemom Agent
|
|
475
|
+
* entitlement (which also gates Remote Control, fail-closed) is still fetched.
|
|
498
476
|
* Only the exact value `1` counts — anything else, including `true` or ` 1`, is
|
|
499
477
|
* a normal launch.
|
|
500
478
|
*/
|
|
@@ -543,11 +521,7 @@ export declare function resolveRemoteControlShape(args: {
|
|
|
543
521
|
export declare function buildCustomHeaders(opts: {
|
|
544
522
|
/** Absent on a subscription-login launch: Claude Code then sends its own claude.ai login. */
|
|
545
523
|
anthropicKey?: string;
|
|
546
|
-
/**
|
|
547
|
-
* The Mnemom key every `mnemom agent` launch sends (lib/subscription-login.ts
|
|
548
|
-
* resolveLaunchMnemomKey) — the gateway refuses the session without it, and on a subscription
|
|
549
|
-
* login it is also the governed-identity anchor.
|
|
550
|
-
*/
|
|
524
|
+
/** The governed-identity anchor on a subscription-login launch (lib/subscription-login.ts). */
|
|
551
525
|
mnemomKey?: string;
|
|
552
526
|
agent: string;
|
|
553
527
|
conversationId: string;
|
|
@@ -576,45 +550,36 @@ export declare function resolveContextFold(opts: {
|
|
|
576
550
|
*/
|
|
577
551
|
export declare function parseContextProfile(raw: string, source: string): ContextProfile;
|
|
578
552
|
/**
|
|
579
|
-
* Which context profile this launch runs under,
|
|
580
|
-
* no fold key is sent and the cell's own default decides. Precedence, highest wins:
|
|
553
|
+
* Which context profile this launch runs under. Precedence, highest wins:
|
|
581
554
|
* 1. `--no-context` — always `off`. Combined with an explicit `--context-profile
|
|
582
555
|
* balanced|aggressive|adaptive` it is a CONFLICT and the launch refuses (never a silent override);
|
|
583
556
|
* `--context-profile off` agrees with it.
|
|
584
557
|
* 2. an explicit `--context-profile <profile>` flag (`--context` alongside it is fine — the
|
|
585
558
|
* profile wins);
|
|
586
|
-
* 3. `
|
|
587
|
-
* ledger), so a resume keeps that session's own choice over the saved default;
|
|
588
|
-
* 4. `MNEMOM_AGENT_CONTEXT_PROFILE` (which `applyConfigToEnv` sets from the `context_profile`
|
|
559
|
+
* 3. `MNEMOM_AGENT_CONTEXT_PROFILE` (which `applyConfigToEnv` sets from the `context_profile`
|
|
589
560
|
* config key) — an invalid value is an error, never a silent default;
|
|
590
|
-
*
|
|
561
|
+
* 4. the folding boolean when NO profile is set anywhere: `context = false` in launcher.toml
|
|
591
562
|
* (→ `MNEMOM_AGENT_CONTEXT`, see `resolveContextFold`) means `off`;
|
|
592
|
-
*
|
|
563
|
+
* 5. `balanced` (the default).
|
|
593
564
|
*/
|
|
594
565
|
export declare function resolveContextProfile(opts: {
|
|
595
566
|
contextProfile?: ContextProfile;
|
|
596
567
|
context?: boolean;
|
|
597
|
-
resumed?: ContextProfile | null;
|
|
598
568
|
env?: NodeJS.ProcessEnv;
|
|
599
|
-
}): ContextProfile
|
|
569
|
+
}): ContextProfile;
|
|
600
570
|
/**
|
|
601
571
|
* The decoded per-session env overlay for this launch — the `config` object of the
|
|
602
572
|
* `x-mnemom-session-config` payload, in wire order: the profile's keys first
|
|
603
|
-
* (`CONTEXT_RUNTIME_ENABLED
|
|
604
|
-
* `
|
|
605
|
-
* no profile was chosen), then `CONTEXT_HANDOFF_ENABLED: "true"` when context handoff is ON, then
|
|
573
|
+
* (`CONTEXT_RUNTIME_ENABLED` for `off`; the three fold-tuning keys for `aggressive`;
|
|
574
|
+
* `CONTEXT_RUNTIME_SIZE_POLICY` for `adaptive`; nothing for `balanced`), then `CONTEXT_HANDOFF_ENABLED: "true"` when context handoff is ON, then
|
|
606
575
|
* `GATEWAY_USAGE_REAL_SIZE: "on"` + `GATEWAY_COMPACTION_INTERCEPT: "on"` when EITHER the
|
|
607
576
|
* `compaction_intercept` setting is ON OR `--compact-at` arms a target below 1M (the target
|
|
608
577
|
* cannot be honored without the intercept), then `GATEWAY_COMPACTION_UPLOAD_TARGET_TOKENS: "<N>"`
|
|
609
|
-
* when a target is set.
|
|
610
|
-
*
|
|
611
|
-
* flag pair; a standing intercept or target from the environment or launcher.toml is dropped).
|
|
612
|
-
* Empty with no profile chosen and everything off — the common case, where
|
|
613
|
-
* no header is sent at all. Exported so `--dry-run` can list exactly what the header carries.
|
|
578
|
+
* when a target is set. Empty for `balanced` with everything off — the common case, where no
|
|
579
|
+
* header is sent at all. Exported so `--dry-run` can list exactly what the header carries.
|
|
614
580
|
*/
|
|
615
581
|
export declare function buildSessionConfig(opts: {
|
|
616
|
-
|
|
617
|
-
profile: ContextProfile | null;
|
|
582
|
+
profile: ContextProfile;
|
|
618
583
|
contextHandoff: boolean;
|
|
619
584
|
compactionIntercept?: boolean;
|
|
620
585
|
/** `resolveCompactAt` output: `null` (or absent) ⇒ no target, send nothing new. */
|
|
@@ -626,7 +591,7 @@ export declare function buildSessionConfig(opts: {
|
|
|
626
591
|
* gateway's allow-list never sees them as env keys; it ignores unknown envelope fields.
|
|
627
592
|
*/
|
|
628
593
|
export declare function buildSessionConfigPayload(opts: {
|
|
629
|
-
profile: ContextProfile
|
|
594
|
+
profile: ContextProfile;
|
|
630
595
|
contextHandoff: boolean;
|
|
631
596
|
compactionIntercept?: boolean;
|
|
632
597
|
compactAt?: number | null;
|
|
@@ -638,12 +603,11 @@ export declare function buildSessionConfigPayload(opts: {
|
|
|
638
603
|
} | undefined;
|
|
639
604
|
/**
|
|
640
605
|
* The `x-mnemom-session-config` value for this launch, or `undefined` when there is
|
|
641
|
-
* nothing to override (the
|
|
642
|
-
*
|
|
606
|
+
* nothing to override (the gateway's own defaults stand — `balanced` with everything else off,
|
|
607
|
+
* byte-identical to a launch before profiles existed). Independent overlays:
|
|
643
608
|
* - the context profile (`buildSessionConfig`): `off` → `CONTEXT_RUNTIME_ENABLED: "false"`,
|
|
644
|
-
* `aggressive` → the three fold-tuning keys
|
|
645
|
-
*
|
|
646
|
-
* `CONTEXT_RUNTIME_SIZE_POLICY: "banded"`, none chosen → nothing;
|
|
609
|
+
* `aggressive` → the three fold-tuning keys, `adaptive` → `CONTEXT_RUNTIME_SIZE_POLICY:
|
|
610
|
+
* "banded"`, `balanced` → nothing;
|
|
647
611
|
* - `compactionIntercept: true` → `GATEWAY_USAGE_REAL_SIZE` + `GATEWAY_COMPACTION_INTERCEPT`
|
|
648
612
|
* `"on"` (the `compaction_intercept` setting);
|
|
649
613
|
* - `compactAt: <N>` (`--compact-at`, below 1M) → the SAME two intercept keys plus
|
|
@@ -656,20 +620,12 @@ export declare function buildSessionConfigPayload(opts: {
|
|
|
656
620
|
* base64url so it survives the gateway's inbound strip.
|
|
657
621
|
*/
|
|
658
622
|
export declare function buildSessionConfigB64(opts: {
|
|
659
|
-
profile: ContextProfile
|
|
623
|
+
profile: ContextProfile;
|
|
660
624
|
contextHandoff: boolean;
|
|
661
625
|
compactionIntercept?: boolean;
|
|
662
626
|
compactAt?: number | null;
|
|
663
627
|
experimental?: readonly string[];
|
|
664
628
|
}): string | undefined;
|
|
665
|
-
/**
|
|
666
|
-
* A no-op `x-mnemom-session-config` value: `{ v: 1, config: {} }` overrides nothing (the gateway
|
|
667
|
-
* applies an empty set, exactly its own defaults). buildSessionConfigB64 returns `undefined` for
|
|
668
|
-
* the defaults — no header at all; this is for a call that must be Mnemom agent traffic (the
|
|
669
|
-
* gateway's agent-traffic gate keys on the header's presence) without changing any setting: the
|
|
670
|
-
* launcher's birth probe (commands/wrap.ts birthThroughGateway).
|
|
671
|
-
*/
|
|
672
|
-
export declare const NOOP_SESSION_CONFIG_B64: string;
|
|
673
629
|
/**
|
|
674
630
|
* Is the `handoff` MCP tool + `CONTEXT_HANDOFF_ENABLED` session-config header ON for
|
|
675
631
|
* this launch? OFF by default (operator directive, curation 2026-09-25): an absent flag
|
|
@@ -705,12 +661,6 @@ export declare const HANDOFF_MCP_SERVER_NAME = "mnemom-handoff";
|
|
|
705
661
|
* it the same way it inherits `ANTHROPIC_CUSTOM_HEADERS` under the terminal shape.
|
|
706
662
|
*/
|
|
707
663
|
export declare const HANDOFF_RC_KEY_ENV_NAME = "MNEMOM_HANDOFF_KEY";
|
|
708
|
-
/**
|
|
709
|
-
* Beside `HANDOFF_RC_KEY_ENV_NAME`: the non-`ANTHROPIC_*` var `spawnRcCli` sets to the launch's
|
|
710
|
-
* Mnemom key when context handoff is on, so the handoff call carries the `x-mnemom-api-key` the
|
|
711
|
-
* gateway requires on every `mnemom agent` request.
|
|
712
|
-
*/
|
|
713
|
-
export declare const HANDOFF_RC_MNEMOM_KEY_ENV_NAME = "MNEMOM_HANDOFF_MNEMOM_KEY";
|
|
714
664
|
/**
|
|
715
665
|
* How the `handoff` MCP server (cli/src/mcp/handoff-server.mjs) recovers the Anthropic key
|
|
716
666
|
* WITHOUT it ever being written into the `--mcp-config` file on disk: `envName` is the NAME of a
|
|
@@ -742,12 +692,6 @@ export interface HandoffMcpParams {
|
|
|
742
692
|
/** The gateway ORIGIN (e.g. https://gateway.mnemom.ai) — see `resolveHandoffGatewayHost`. */
|
|
743
693
|
gatewayHost: string;
|
|
744
694
|
anthropicKeySource: HandoffAnthropicKeySource;
|
|
745
|
-
/**
|
|
746
|
-
* Where the server reads the Mnemom key (`x-mnemom-api-key`) from — same contract as
|
|
747
|
-
* `anthropicKeySource`: `ANTHROPIC_CUSTOM_HEADERS` (its `x-mnemom-api-key:` line) on a terminal
|
|
748
|
-
* launch, `HANDOFF_RC_MNEMOM_KEY_ENV_NAME` under Remote Control. Absent ⇒ no Mnemom key header.
|
|
749
|
-
*/
|
|
750
|
-
mnemomKeySource?: HandoffAnthropicKeySource;
|
|
751
695
|
agent: string;
|
|
752
696
|
conversationId: string;
|
|
753
697
|
/** `buildSessionConfigB64` output — forwarded so the route resolves the SAME per-session flag. */
|
package/dist/lib/agent.js
CHANGED
|
@@ -452,59 +452,32 @@ export const CONTEXT_TAIL_BUDGET_KEY = "CONTEXT_RUNTIME_TAIL_BUDGET_TOKENS";
|
|
|
452
452
|
export const CONTEXT_READ_CACHE_KEY = "CONTEXT_RUNTIME_READ_CACHE_TOKENS";
|
|
453
453
|
export const CONTEXT_HEAD_RECLAIM_KEY = "CONTEXT_RUNTIME_HEAD_BREAKPOINT_RECLAIM";
|
|
454
454
|
/**
|
|
455
|
-
* The gateway key
|
|
456
|
-
* Only the literal `banded` enables it;
|
|
457
|
-
*
|
|
458
|
-
* gateway's own defaults.
|
|
455
|
+
* The gateway key the `adaptive` context profile sets (allow-listed per session): turns on the
|
|
456
|
+
* size-banded fold policy. Only the literal `banded` enables it; the band thresholds and budgets
|
|
457
|
+
* stay at the gateway's own defaults.
|
|
459
458
|
*/
|
|
460
459
|
export const CONTEXT_SIZE_POLICY_KEY = "CONTEXT_RUNTIME_SIZE_POLICY";
|
|
461
|
-
/**
|
|
462
|
-
* The two gateway env keys the `compaction_intercept` setting turns on for a single session
|
|
463
|
-
* (payload-bound fix; both default OFF on the gateway, both read from the per-session overlay):
|
|
464
|
-
* - `GATEWAY_USAGE_REAL_SIZE` — report the size of the body the client actually sent (the
|
|
465
|
-
* REAL, unfolded context) in the last `usage.iterations` entry, so Claude Code's own
|
|
466
|
-
* auto-compact threshold (its 1M default, or the user's `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` /
|
|
467
|
-
* `CLAUDE_CODE_AUTO_COMPACT_WINDOW` / `autoCompactWindow`) fires as it would without the fold;
|
|
468
|
-
* - `GATEWAY_COMPACTION_INTERCEPT` — answer the client's compaction request at once from the
|
|
469
|
-
* gateway's own fold digest (no model call), so the compaction never blocks the user.
|
|
470
|
-
* Sent together, value `"on"`, when the `compaction_intercept` setting is on
|
|
471
|
-
* (`resolveCompactionIntercept`) OR when `--compact-at` arms a target below 1M (below) — a
|
|
472
|
-
* target cannot be honored without both. The `off` context profile sends both as `"off"`.
|
|
473
|
-
*/
|
|
474
|
-
export const USAGE_REAL_SIZE_KEY = "GATEWAY_USAGE_REAL_SIZE";
|
|
475
|
-
export const COMPACTION_INTERCEPT_KEY = "GATEWAY_COMPACTION_INTERCEPT";
|
|
476
460
|
/**
|
|
477
461
|
* The named presets for how the gateway folds a session's context (`--context-profile`,
|
|
478
|
-
* launcher.toml `context_profile`, `MNEMOM_AGENT_CONTEXT_PROFILE`)
|
|
479
|
-
*
|
|
480
|
-
*
|
|
481
|
-
* - `
|
|
482
|
-
*
|
|
483
|
-
* and
|
|
484
|
-
* The gateway already skips the intercept with the fold off, but the real-size
|
|
485
|
-
* usage rewrite is not gated on the fold, so `off` turns both off by name.
|
|
486
|
-
* - `balanced` → `CONTEXT_RUNTIME_SIZE_POLICY: "off"` — the cell's own fold budgets, never
|
|
487
|
-
* the size bands, even on a cell whose default is adaptive.
|
|
488
|
-
* - `aggressive` → a smaller tail budget + read cache and head-breakpoint reclaim on, size
|
|
489
|
-
* policy off: folds earlier and keeps a tighter working set at every size.
|
|
462
|
+
* launcher.toml `context_profile`, `MNEMOM_AGENT_CONTEXT_PROFILE`):
|
|
463
|
+
* - `off` → `CONTEXT_RUNTIME_ENABLED: "false"` — compaction is left to the coding agent
|
|
464
|
+
* (the same bytes `--no-context` has always sent).
|
|
465
|
+
* - `balanced` → NO fold keys: the gateway's own defaults stand. The default.
|
|
466
|
+
* - `aggressive` → a smaller tail budget + read cache and head-breakpoint reclaim on: folds
|
|
467
|
+
* earlier and keeps a tighter working set.
|
|
490
468
|
* - `adaptive` → `CONTEXT_RUNTIME_SIZE_POLICY: "banded"` — the gateway picks the fold by the
|
|
491
469
|
* conversation's original size: no fold below 200k tokens, the aggressive
|
|
492
|
-
* budgets from 200k to 1M, balanced above.
|
|
470
|
+
* budgets from 200k to 1M, balanced above. Opt-in; never the default.
|
|
493
471
|
*/
|
|
494
472
|
export const CONTEXT_PROFILES = ["off", "balanced", "aggressive", "adaptive"];
|
|
495
473
|
/** The per-session env overlay each profile expands to (key order is the wire order). */
|
|
496
474
|
const CONTEXT_PROFILE_CONFIG = {
|
|
497
|
-
off: [
|
|
498
|
-
|
|
499
|
-
[USAGE_REAL_SIZE_KEY, "off"],
|
|
500
|
-
[COMPACTION_INTERCEPT_KEY, "off"],
|
|
501
|
-
],
|
|
502
|
-
balanced: [[CONTEXT_SIZE_POLICY_KEY, "off"]],
|
|
475
|
+
off: [[CONTEXT_RUNTIME_KEY, "false"]],
|
|
476
|
+
balanced: [],
|
|
503
477
|
aggressive: [
|
|
504
478
|
[CONTEXT_TAIL_BUDGET_KEY, "60000"],
|
|
505
479
|
[CONTEXT_READ_CACHE_KEY, "8000"],
|
|
506
480
|
[CONTEXT_HEAD_RECLAIM_KEY, "true"],
|
|
507
|
-
[CONTEXT_SIZE_POLICY_KEY, "off"],
|
|
508
481
|
],
|
|
509
482
|
adaptive: [[CONTEXT_SIZE_POLICY_KEY, "banded"]],
|
|
510
483
|
};
|
|
@@ -517,6 +490,21 @@ const CONTEXT_PROFILE_CONFIG = {
|
|
|
517
490
|
* header without the tool.
|
|
518
491
|
*/
|
|
519
492
|
export const CONTEXT_HANDOFF_KEY = "CONTEXT_HANDOFF_ENABLED";
|
|
493
|
+
/**
|
|
494
|
+
* The two gateway env keys the `compaction_intercept` setting turns on for a single session
|
|
495
|
+
* (payload-bound fix; both default OFF on the gateway, both read from the per-session overlay):
|
|
496
|
+
* - `GATEWAY_USAGE_REAL_SIZE` — report the size of the body the client actually sent (the
|
|
497
|
+
* REAL, unfolded context) in the last `usage.iterations` entry, so Claude Code's own
|
|
498
|
+
* auto-compact threshold (its 1M default, or the user's `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` /
|
|
499
|
+
* `CLAUDE_CODE_AUTO_COMPACT_WINDOW` / `autoCompactWindow`) fires as it would without the fold;
|
|
500
|
+
* - `GATEWAY_COMPACTION_INTERCEPT` — answer the client's compaction request at once from the
|
|
501
|
+
* gateway's own fold digest (no model call), so the compaction never blocks the user.
|
|
502
|
+
* Sent together, value `"on"`, when the `compaction_intercept` setting is on
|
|
503
|
+
* (`resolveCompactionIntercept`) OR when `--compact-at` arms a target below 1M (below) — a
|
|
504
|
+
* target cannot be honored without both.
|
|
505
|
+
*/
|
|
506
|
+
export const USAGE_REAL_SIZE_KEY = "GATEWAY_USAGE_REAL_SIZE";
|
|
507
|
+
export const COMPACTION_INTERCEPT_KEY = "GATEWAY_COMPACTION_INTERCEPT";
|
|
520
508
|
// ---------------------------------------------------------------------------
|
|
521
509
|
// Compaction target (`--compact-at`, launcher.toml `compact_at`, MNEMOM_COMPACT_AT)
|
|
522
510
|
// ---------------------------------------------------------------------------
|
|
@@ -663,28 +651,6 @@ export function assertCompactAtCompatible(opts) {
|
|
|
663
651
|
"enable compaction-intercept`), or pass --compact-at off.");
|
|
664
652
|
}
|
|
665
653
|
}
|
|
666
|
-
/**
|
|
667
|
-
* The `off` context profile turns the fold off, and the compaction intercept answers a compaction
|
|
668
|
-
* from that fold, so `off` sends the intercept and real-size keys as `"off"`. An explicit
|
|
669
|
-
* `--compaction-intercept` or `--compact-at <N>` in the same launch asks for the opposite —
|
|
670
|
-
* refuse rather than silently drop the flag. A standing intercept or target (environment or
|
|
671
|
-
* launcher.toml) is not refused: the session's `off` wins and `buildSessionConfig` leaves it out.
|
|
672
|
-
* `compactionIntercept` / `compactAt` here are the raw flag values (`undefined` when not passed).
|
|
673
|
-
*/
|
|
674
|
-
export function assertOffProfileCompatible(opts) {
|
|
675
|
-
if (opts.profile !== "off")
|
|
676
|
-
return;
|
|
677
|
-
const flag = opts.compactionIntercept === true
|
|
678
|
-
? "--compaction-intercept"
|
|
679
|
-
: typeof opts.compactAt === "number"
|
|
680
|
-
? "--compact-at"
|
|
681
|
-
: null;
|
|
682
|
-
if (flag === null)
|
|
683
|
-
return;
|
|
684
|
-
throw new Error(`mnemom agent: context profile off and ${flag} disagree — with the fold off the gateway has ` +
|
|
685
|
-
`no fold to answer a compaction from, so off sends the compaction intercept off. Drop ` +
|
|
686
|
-
`${flag}, or choose another --context-profile.`);
|
|
687
|
-
}
|
|
688
654
|
/**
|
|
689
655
|
* `200000` → `"200k"`, anything not k-aligned → the bare digits. Every real caller only ever
|
|
690
656
|
* passes a `parseCompactAt`-validated value, which is bounded to
|
|
@@ -842,10 +808,8 @@ export function launchPreferenceExplicit(opts, env = process.env) {
|
|
|
842
808
|
* Has an orchestrator already run the session + µ-balance preflight for this
|
|
843
809
|
* launch? `MNEMOM_AGENT_PREFLIGHTED=1` is for orchestrators (the ADW fleet) that
|
|
844
810
|
* checked sign-in and balance themselves before spawning many launches; it skips
|
|
845
|
-
* the per-launch session
|
|
846
|
-
*
|
|
847
|
-
* Mnemom key is minted for it), and the Mnemom Agent entitlement (which also
|
|
848
|
-
* gates Remote Control, fail-closed) is still fetched for it.
|
|
811
|
+
* the per-launch session/personal-org/balance round trips. The Mnemom Agent
|
|
812
|
+
* entitlement (which also gates Remote Control, fail-closed) is still fetched.
|
|
849
813
|
* Only the exact value `1` counts — anything else, including `true` or ` 1`, is
|
|
850
814
|
* a normal launch.
|
|
851
815
|
*/
|
|
@@ -946,20 +910,17 @@ export function parseContextProfile(raw, source) {
|
|
|
946
910
|
throw new Error(`${source} must be one of ${CONTEXT_PROFILES.join(", ")} (got '${raw}').`);
|
|
947
911
|
}
|
|
948
912
|
/**
|
|
949
|
-
* Which context profile this launch runs under,
|
|
950
|
-
* no fold key is sent and the cell's own default decides. Precedence, highest wins:
|
|
913
|
+
* Which context profile this launch runs under. Precedence, highest wins:
|
|
951
914
|
* 1. `--no-context` — always `off`. Combined with an explicit `--context-profile
|
|
952
915
|
* balanced|aggressive|adaptive` it is a CONFLICT and the launch refuses (never a silent override);
|
|
953
916
|
* `--context-profile off` agrees with it.
|
|
954
917
|
* 2. an explicit `--context-profile <profile>` flag (`--context` alongside it is fine — the
|
|
955
918
|
* profile wins);
|
|
956
|
-
* 3. `
|
|
957
|
-
* ledger), so a resume keeps that session's own choice over the saved default;
|
|
958
|
-
* 4. `MNEMOM_AGENT_CONTEXT_PROFILE` (which `applyConfigToEnv` sets from the `context_profile`
|
|
919
|
+
* 3. `MNEMOM_AGENT_CONTEXT_PROFILE` (which `applyConfigToEnv` sets from the `context_profile`
|
|
959
920
|
* config key) — an invalid value is an error, never a silent default;
|
|
960
|
-
*
|
|
921
|
+
* 4. the folding boolean when NO profile is set anywhere: `context = false` in launcher.toml
|
|
961
922
|
* (→ `MNEMOM_AGENT_CONTEXT`, see `resolveContextFold`) means `off`;
|
|
962
|
-
*
|
|
923
|
+
* 5. `balanced` (the default).
|
|
963
924
|
*/
|
|
964
925
|
export function resolveContextProfile(opts) {
|
|
965
926
|
if (opts.context === false) {
|
|
@@ -970,44 +931,34 @@ export function resolveContextProfile(opts) {
|
|
|
970
931
|
}
|
|
971
932
|
if (opts.contextProfile !== undefined)
|
|
972
933
|
return opts.contextProfile;
|
|
973
|
-
if (opts.resumed)
|
|
974
|
-
return opts.resumed;
|
|
975
934
|
const raw = (opts.env?.MNEMOM_AGENT_CONTEXT_PROFILE ?? "").trim();
|
|
976
935
|
if (raw !== "")
|
|
977
936
|
return parseContextProfile(raw, "MNEMOM_AGENT_CONTEXT_PROFILE");
|
|
978
937
|
if (!resolveContextFold({ context: opts.context, env: opts.env }))
|
|
979
938
|
return "off";
|
|
980
|
-
return
|
|
939
|
+
return "balanced";
|
|
981
940
|
}
|
|
982
941
|
/**
|
|
983
942
|
* The decoded per-session env overlay for this launch — the `config` object of the
|
|
984
943
|
* `x-mnemom-session-config` payload, in wire order: the profile's keys first
|
|
985
|
-
* (`CONTEXT_RUNTIME_ENABLED
|
|
986
|
-
* `
|
|
987
|
-
* no profile was chosen), then `CONTEXT_HANDOFF_ENABLED: "true"` when context handoff is ON, then
|
|
944
|
+
* (`CONTEXT_RUNTIME_ENABLED` for `off`; the three fold-tuning keys for `aggressive`;
|
|
945
|
+
* `CONTEXT_RUNTIME_SIZE_POLICY` for `adaptive`; nothing for `balanced`), then `CONTEXT_HANDOFF_ENABLED: "true"` when context handoff is ON, then
|
|
988
946
|
* `GATEWAY_USAGE_REAL_SIZE: "on"` + `GATEWAY_COMPACTION_INTERCEPT: "on"` when EITHER the
|
|
989
947
|
* `compaction_intercept` setting is ON OR `--compact-at` arms a target below 1M (the target
|
|
990
948
|
* cannot be honored without the intercept), then `GATEWAY_COMPACTION_UPLOAD_TARGET_TOKENS: "<N>"`
|
|
991
|
-
* when a target is set.
|
|
992
|
-
*
|
|
993
|
-
* flag pair; a standing intercept or target from the environment or launcher.toml is dropped).
|
|
994
|
-
* Empty with no profile chosen and everything off — the common case, where
|
|
995
|
-
* no header is sent at all. Exported so `--dry-run` can list exactly what the header carries.
|
|
949
|
+
* when a target is set. Empty for `balanced` with everything off — the common case, where no
|
|
950
|
+
* header is sent at all. Exported so `--dry-run` can list exactly what the header carries.
|
|
996
951
|
*/
|
|
997
952
|
export function buildSessionConfig(opts) {
|
|
998
953
|
const config = {};
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
config[k] = v;
|
|
1002
|
-
}
|
|
954
|
+
for (const [k, v] of CONTEXT_PROFILE_CONFIG[opts.profile])
|
|
955
|
+
config[k] = v;
|
|
1003
956
|
if (opts.contextHandoff)
|
|
1004
957
|
config[CONTEXT_HANDOFF_KEY] = "true";
|
|
1005
958
|
const hasCompactionTarget = opts.compactAt !== undefined && opts.compactAt !== null;
|
|
1006
959
|
// A target needs the compaction intercept + real-size rewrite to arm (#2216) — without them
|
|
1007
960
|
// the upload-target key is silently inert (compaction-align.ts: "armed only inside the
|
|
1008
961
|
// intercept"). Deliberately NOT GATEWAY_COMPACTION_REFOLD — a separate, costlier opt-in.
|
|
1009
|
-
if (opts.profile === "off")
|
|
1010
|
-
return config;
|
|
1011
962
|
if (opts.compactionIntercept || hasCompactionTarget) {
|
|
1012
963
|
config[USAGE_REAL_SIZE_KEY] = "on";
|
|
1013
964
|
config[COMPACTION_INTERCEPT_KEY] = "on";
|
|
@@ -1033,12 +984,11 @@ export function buildSessionConfigPayload(opts) {
|
|
|
1033
984
|
}
|
|
1034
985
|
/**
|
|
1035
986
|
* The `x-mnemom-session-config` value for this launch, or `undefined` when there is
|
|
1036
|
-
* nothing to override (the
|
|
1037
|
-
*
|
|
987
|
+
* nothing to override (the gateway's own defaults stand — `balanced` with everything else off,
|
|
988
|
+
* byte-identical to a launch before profiles existed). Independent overlays:
|
|
1038
989
|
* - the context profile (`buildSessionConfig`): `off` → `CONTEXT_RUNTIME_ENABLED: "false"`,
|
|
1039
|
-
* `aggressive` → the three fold-tuning keys
|
|
1040
|
-
*
|
|
1041
|
-
* `CONTEXT_RUNTIME_SIZE_POLICY: "banded"`, none chosen → nothing;
|
|
990
|
+
* `aggressive` → the three fold-tuning keys, `adaptive` → `CONTEXT_RUNTIME_SIZE_POLICY:
|
|
991
|
+
* "banded"`, `balanced` → nothing;
|
|
1042
992
|
* - `compactionIntercept: true` → `GATEWAY_USAGE_REAL_SIZE` + `GATEWAY_COMPACTION_INTERCEPT`
|
|
1043
993
|
* `"on"` (the `compaction_intercept` setting);
|
|
1044
994
|
* - `compactAt: <N>` (`--compact-at`, below 1M) → the SAME two intercept keys plus
|
|
@@ -1056,14 +1006,6 @@ export function buildSessionConfigB64(opts) {
|
|
|
1056
1006
|
return undefined;
|
|
1057
1007
|
return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
|
|
1058
1008
|
}
|
|
1059
|
-
/**
|
|
1060
|
-
* A no-op `x-mnemom-session-config` value: `{ v: 1, config: {} }` overrides nothing (the gateway
|
|
1061
|
-
* applies an empty set, exactly its own defaults). buildSessionConfigB64 returns `undefined` for
|
|
1062
|
-
* the defaults — no header at all; this is for a call that must be Mnemom agent traffic (the
|
|
1063
|
-
* gateway's agent-traffic gate keys on the header's presence) without changing any setting: the
|
|
1064
|
-
* launcher's birth probe (commands/wrap.ts birthThroughGateway).
|
|
1065
|
-
*/
|
|
1066
|
-
export const NOOP_SESSION_CONFIG_B64 = Buffer.from(JSON.stringify({ v: 1, config: {} }), "utf8").toString("base64url");
|
|
1067
1009
|
/**
|
|
1068
1010
|
* Is the `handoff` MCP tool + `CONTEXT_HANDOFF_ENABLED` session-config header ON for
|
|
1069
1011
|
* this launch? OFF by default (operator directive, curation 2026-09-25): an absent flag
|
|
@@ -1107,12 +1049,6 @@ export const HANDOFF_MCP_SERVER_NAME = "mnemom-handoff";
|
|
|
1107
1049
|
* it the same way it inherits `ANTHROPIC_CUSTOM_HEADERS` under the terminal shape.
|
|
1108
1050
|
*/
|
|
1109
1051
|
export const HANDOFF_RC_KEY_ENV_NAME = "MNEMOM_HANDOFF_KEY";
|
|
1110
|
-
/**
|
|
1111
|
-
* Beside `HANDOFF_RC_KEY_ENV_NAME`: the non-`ANTHROPIC_*` var `spawnRcCli` sets to the launch's
|
|
1112
|
-
* Mnemom key when context handoff is on, so the handoff call carries the `x-mnemom-api-key` the
|
|
1113
|
-
* gateway requires on every `mnemom agent` request.
|
|
1114
|
-
*/
|
|
1115
|
-
export const HANDOFF_RC_MNEMOM_KEY_ENV_NAME = "MNEMOM_HANDOFF_MNEMOM_KEY";
|
|
1116
1052
|
/** The `--mcp-config` document registering exactly the `handoff` tool. Pure — no I/O. */
|
|
1117
1053
|
export function buildHandoffMcpConfig(p) {
|
|
1118
1054
|
const env = {
|
|
@@ -1121,8 +1057,6 @@ export function buildHandoffMcpConfig(p) {
|
|
|
1121
1057
|
MNEMOM_HANDOFF_AGENT: p.agent,
|
|
1122
1058
|
MNEMOM_HANDOFF_CONVERSATION_ID: p.conversationId,
|
|
1123
1059
|
};
|
|
1124
|
-
if (p.mnemomKeySource)
|
|
1125
|
-
env.MNEMOM_HANDOFF_MNEMOM_KEY_ENV_NAME = p.mnemomKeySource.envName;
|
|
1126
1060
|
if (p.sessionConfigB64)
|
|
1127
1061
|
env.MNEMOM_HANDOFF_SESSION_CONFIG = p.sessionConfigB64;
|
|
1128
1062
|
return {
|
package/dist/lib/api.d.ts
CHANGED
|
@@ -1069,27 +1069,6 @@ export declare function listApiKeys(): Promise<ApiKeyListItem[]>;
|
|
|
1069
1069
|
* for non-staff, admin:org for users not in any org-admin role).
|
|
1070
1070
|
*/
|
|
1071
1071
|
export declare function createApiKey(name: string, scopes: ApiKeyScope[]): Promise<ApiKeyCreated>;
|
|
1072
|
-
/**
|
|
1073
|
-
* POST /v1/orgs/{org_id}/api-keys — mint an ORG-owned key (its `org_id` is that org, so the
|
|
1074
|
-
* gateway births a new agent there). Owners and admins may mint any scopes; a member may mint a
|
|
1075
|
-
* key whose scopes are exactly ["gateway"]. A refusal (viewer/auditor, a non-member, or an API
|
|
1076
|
-
* that predates member org keys) is thrown as MnemomApiError with its status (403/404).
|
|
1077
|
-
*/
|
|
1078
|
-
export declare function createOrgApiKey(orgId: string, name: string, scopes: ApiKeyScope[]): Promise<ApiKeyCreated>;
|
|
1079
|
-
/**
|
|
1080
|
-
* GET /v1/api-keys/whoami authenticated by `key` ALONE (`X-Mnemom-Api-Key`, no session): does
|
|
1081
|
-
* the API accept this key? true = 200. false = 401/403 — revoked, rotated or unknown, OR a valid
|
|
1082
|
-
* `gateway`-only key: the API refuses every key without an `api:*` scope (ADR-049), so false
|
|
1083
|
-
* alone never proves a key dead. Throws on anything else (network, timeout, 429, 5xx): the
|
|
1084
|
-
* caller reads that as "could not check".
|
|
1085
|
-
*/
|
|
1086
|
-
export declare function apiAcceptsMnemomKey(key: string, timeoutMs: number): Promise<boolean>;
|
|
1087
|
-
/**
|
|
1088
|
-
* GET /v1/api-keys with a timeout, for checking a key: the signed-in caller's ACTIVE keys (a
|
|
1089
|
-
* revoked or rotated key is absent). null when there is no usable session (no credential, or
|
|
1090
|
-
* 401/403 after the refresh retry). Throws on anything else (network, timeout, 5xx).
|
|
1091
|
-
*/
|
|
1092
|
-
export declare function listOwnApiKeysForCheck(timeoutMs: number): Promise<ApiKeyListItem[] | null>;
|
|
1093
1072
|
/**
|
|
1094
1073
|
* POST /v1/api-keys/{key_id}/rotate — atomic mint-new + revoke-old.
|
|
1095
1074
|
* Returns the full new secret only on this call. The new key inherits
|
|
@@ -1099,13 +1078,9 @@ export declare function listOwnApiKeysForCheck(timeoutMs: number): Promise<ApiKe
|
|
|
1099
1078
|
export declare function rotateApiKey(keyId: string): Promise<ApiKeyCreated>;
|
|
1100
1079
|
/**
|
|
1101
1080
|
* DELETE /v1/api-keys/{key_id} — soft-revoke. The key row stays for
|
|
1102
|
-
* audit; `is_active` flips to false and `revoked_at` is timestamped.
|
|
1103
|
-
* a key the signed-in user created (an org key they minted included) is
|
|
1104
|
-
* found; anything else is a 404. `timeoutMs` bounds the call.
|
|
1081
|
+
* audit; `is_active` flips to false and `revoked_at` is timestamped.
|
|
1105
1082
|
*/
|
|
1106
|
-
export declare function revokeApiKey(keyId: string
|
|
1107
|
-
timeoutMs?: number;
|
|
1108
|
-
}): Promise<void>;
|
|
1083
|
+
export declare function revokeApiKey(keyId: string): Promise<void>;
|
|
1109
1084
|
export interface LicenseValidationResult {
|
|
1110
1085
|
valid: boolean;
|
|
1111
1086
|
license_id?: string;
|