@mnemom/mnemom 0.17.7-next.1 → 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 +11 -23
- 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 +43 -131
- 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 +27 -64
- package/dist/lib/agent.js +26 -58
- 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,26 +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
302
|
/**
|
|
304
303
|
* The named presets for how the gateway folds a session's context (`--context-profile`,
|
|
305
|
-
* launcher.toml `context_profile`, `MNEMOM_AGENT_CONTEXT_PROFILE`)
|
|
306
|
-
* key at all and the cell's own default decides (see `resolveContextProfile`). A chosen profile
|
|
307
|
-
* is complete on its own, so a change to a cell's default can never change what it means:
|
|
304
|
+
* launcher.toml `context_profile`, `MNEMOM_AGENT_CONTEXT_PROFILE`):
|
|
308
305
|
* - `off` → `CONTEXT_RUNTIME_ENABLED: "false"` — compaction is left to the coding agent
|
|
309
306
|
* (the same bytes `--no-context` has always sent).
|
|
310
|
-
* - `balanced` →
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
* policy off: folds earlier and keeps a tighter working set at every size.
|
|
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.
|
|
314
310
|
* - `adaptive` → `CONTEXT_RUNTIME_SIZE_POLICY: "banded"` — the gateway picks the fold by the
|
|
315
311
|
* conversation's original size: no fold below 200k tokens, the aggressive
|
|
316
|
-
* budgets from 200k to 1M, balanced above.
|
|
312
|
+
* budgets from 200k to 1M, balanced above. Opt-in; never the default.
|
|
317
313
|
*/
|
|
318
314
|
export declare const CONTEXT_PROFILES: readonly ["off", "balanced", "aggressive", "adaptive"];
|
|
319
315
|
export type ContextProfile = (typeof CONTEXT_PROFILES)[number];
|
|
@@ -475,10 +471,8 @@ export declare function launchPreferenceExplicit(opts: {
|
|
|
475
471
|
* Has an orchestrator already run the session + µ-balance preflight for this
|
|
476
472
|
* launch? `MNEMOM_AGENT_PREFLIGHTED=1` is for orchestrators (the ADW fleet) that
|
|
477
473
|
* checked sign-in and balance themselves before spawning many launches; it skips
|
|
478
|
-
* the per-launch session
|
|
479
|
-
*
|
|
480
|
-
* Mnemom key is minted for it), and the Mnemom Agent entitlement (which also
|
|
481
|
-
* 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.
|
|
482
476
|
* Only the exact value `1` counts — anything else, including `true` or ` 1`, is
|
|
483
477
|
* a normal launch.
|
|
484
478
|
*/
|
|
@@ -527,11 +521,7 @@ export declare function resolveRemoteControlShape(args: {
|
|
|
527
521
|
export declare function buildCustomHeaders(opts: {
|
|
528
522
|
/** Absent on a subscription-login launch: Claude Code then sends its own claude.ai login. */
|
|
529
523
|
anthropicKey?: string;
|
|
530
|
-
/**
|
|
531
|
-
* The Mnemom key every `mnemom agent` launch sends (lib/subscription-login.ts
|
|
532
|
-
* resolveLaunchMnemomKey) — the gateway refuses the session without it, and on a subscription
|
|
533
|
-
* login it is also the governed-identity anchor.
|
|
534
|
-
*/
|
|
524
|
+
/** The governed-identity anchor on a subscription-login launch (lib/subscription-login.ts). */
|
|
535
525
|
mnemomKey?: string;
|
|
536
526
|
agent: string;
|
|
537
527
|
conversationId: string;
|
|
@@ -560,42 +550,36 @@ export declare function resolveContextFold(opts: {
|
|
|
560
550
|
*/
|
|
561
551
|
export declare function parseContextProfile(raw: string, source: string): ContextProfile;
|
|
562
552
|
/**
|
|
563
|
-
* Which context profile this launch runs under,
|
|
564
|
-
* 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:
|
|
565
554
|
* 1. `--no-context` — always `off`. Combined with an explicit `--context-profile
|
|
566
555
|
* balanced|aggressive|adaptive` it is a CONFLICT and the launch refuses (never a silent override);
|
|
567
556
|
* `--context-profile off` agrees with it.
|
|
568
557
|
* 2. an explicit `--context-profile <profile>` flag (`--context` alongside it is fine — the
|
|
569
558
|
* profile wins);
|
|
570
|
-
* 3. `
|
|
571
|
-
* ledger), so a resume keeps that session's own choice over the saved default;
|
|
572
|
-
* 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`
|
|
573
560
|
* config key) — an invalid value is an error, never a silent default;
|
|
574
|
-
*
|
|
561
|
+
* 4. the folding boolean when NO profile is set anywhere: `context = false` in launcher.toml
|
|
575
562
|
* (→ `MNEMOM_AGENT_CONTEXT`, see `resolveContextFold`) means `off`;
|
|
576
|
-
*
|
|
563
|
+
* 5. `balanced` (the default).
|
|
577
564
|
*/
|
|
578
565
|
export declare function resolveContextProfile(opts: {
|
|
579
566
|
contextProfile?: ContextProfile;
|
|
580
567
|
context?: boolean;
|
|
581
|
-
resumed?: ContextProfile | null;
|
|
582
568
|
env?: NodeJS.ProcessEnv;
|
|
583
|
-
}): ContextProfile
|
|
569
|
+
}): ContextProfile;
|
|
584
570
|
/**
|
|
585
571
|
* The decoded per-session env overlay for this launch — the `config` object of the
|
|
586
572
|
* `x-mnemom-session-config` payload, in wire order: the profile's keys first
|
|
587
|
-
* (`CONTEXT_RUNTIME_ENABLED` for `off`; the three fold-tuning keys
|
|
588
|
-
* `
|
|
589
|
-
* 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
|
|
590
575
|
* `GATEWAY_USAGE_REAL_SIZE: "on"` + `GATEWAY_COMPACTION_INTERCEPT: "on"` when EITHER the
|
|
591
576
|
* `compaction_intercept` setting is ON OR `--compact-at` arms a target below 1M (the target
|
|
592
577
|
* cannot be honored without the intercept), then `GATEWAY_COMPACTION_UPLOAD_TARGET_TOKENS: "<N>"`
|
|
593
|
-
* when a target is set. Empty
|
|
594
|
-
*
|
|
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.
|
|
595
580
|
*/
|
|
596
581
|
export declare function buildSessionConfig(opts: {
|
|
597
|
-
|
|
598
|
-
profile: ContextProfile | null;
|
|
582
|
+
profile: ContextProfile;
|
|
599
583
|
contextHandoff: boolean;
|
|
600
584
|
compactionIntercept?: boolean;
|
|
601
585
|
/** `resolveCompactAt` output: `null` (or absent) ⇒ no target, send nothing new. */
|
|
@@ -607,7 +591,7 @@ export declare function buildSessionConfig(opts: {
|
|
|
607
591
|
* gateway's allow-list never sees them as env keys; it ignores unknown envelope fields.
|
|
608
592
|
*/
|
|
609
593
|
export declare function buildSessionConfigPayload(opts: {
|
|
610
|
-
profile: ContextProfile
|
|
594
|
+
profile: ContextProfile;
|
|
611
595
|
contextHandoff: boolean;
|
|
612
596
|
compactionIntercept?: boolean;
|
|
613
597
|
compactAt?: number | null;
|
|
@@ -619,12 +603,11 @@ export declare function buildSessionConfigPayload(opts: {
|
|
|
619
603
|
} | undefined;
|
|
620
604
|
/**
|
|
621
605
|
* The `x-mnemom-session-config` value for this launch, or `undefined` when there is
|
|
622
|
-
* nothing to override (the
|
|
623
|
-
*
|
|
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:
|
|
624
608
|
* - the context profile (`buildSessionConfig`): `off` → `CONTEXT_RUNTIME_ENABLED: "false"`,
|
|
625
|
-
* `aggressive` → the three fold-tuning keys
|
|
626
|
-
*
|
|
627
|
-
* `CONTEXT_RUNTIME_SIZE_POLICY: "banded"`, none chosen → nothing;
|
|
609
|
+
* `aggressive` → the three fold-tuning keys, `adaptive` → `CONTEXT_RUNTIME_SIZE_POLICY:
|
|
610
|
+
* "banded"`, `balanced` → nothing;
|
|
628
611
|
* - `compactionIntercept: true` → `GATEWAY_USAGE_REAL_SIZE` + `GATEWAY_COMPACTION_INTERCEPT`
|
|
629
612
|
* `"on"` (the `compaction_intercept` setting);
|
|
630
613
|
* - `compactAt: <N>` (`--compact-at`, below 1M) → the SAME two intercept keys plus
|
|
@@ -637,20 +620,12 @@ export declare function buildSessionConfigPayload(opts: {
|
|
|
637
620
|
* base64url so it survives the gateway's inbound strip.
|
|
638
621
|
*/
|
|
639
622
|
export declare function buildSessionConfigB64(opts: {
|
|
640
|
-
profile: ContextProfile
|
|
623
|
+
profile: ContextProfile;
|
|
641
624
|
contextHandoff: boolean;
|
|
642
625
|
compactionIntercept?: boolean;
|
|
643
626
|
compactAt?: number | null;
|
|
644
627
|
experimental?: readonly string[];
|
|
645
628
|
}): string | undefined;
|
|
646
|
-
/**
|
|
647
|
-
* A no-op `x-mnemom-session-config` value: `{ v: 1, config: {} }` overrides nothing (the gateway
|
|
648
|
-
* applies an empty set, exactly its own defaults). buildSessionConfigB64 returns `undefined` for
|
|
649
|
-
* the defaults — no header at all; this is for a call that must be Mnemom agent traffic (the
|
|
650
|
-
* gateway's agent-traffic gate keys on the header's presence) without changing any setting: the
|
|
651
|
-
* launcher's birth probe (commands/wrap.ts birthThroughGateway).
|
|
652
|
-
*/
|
|
653
|
-
export declare const NOOP_SESSION_CONFIG_B64: string;
|
|
654
629
|
/**
|
|
655
630
|
* Is the `handoff` MCP tool + `CONTEXT_HANDOFF_ENABLED` session-config header ON for
|
|
656
631
|
* this launch? OFF by default (operator directive, curation 2026-09-25): an absent flag
|
|
@@ -686,12 +661,6 @@ export declare const HANDOFF_MCP_SERVER_NAME = "mnemom-handoff";
|
|
|
686
661
|
* it the same way it inherits `ANTHROPIC_CUSTOM_HEADERS` under the terminal shape.
|
|
687
662
|
*/
|
|
688
663
|
export declare const HANDOFF_RC_KEY_ENV_NAME = "MNEMOM_HANDOFF_KEY";
|
|
689
|
-
/**
|
|
690
|
-
* Beside `HANDOFF_RC_KEY_ENV_NAME`: the non-`ANTHROPIC_*` var `spawnRcCli` sets to the launch's
|
|
691
|
-
* Mnemom key when context handoff is on, so the handoff call carries the `x-mnemom-api-key` the
|
|
692
|
-
* gateway requires on every `mnemom agent` request.
|
|
693
|
-
*/
|
|
694
|
-
export declare const HANDOFF_RC_MNEMOM_KEY_ENV_NAME = "MNEMOM_HANDOFF_MNEMOM_KEY";
|
|
695
664
|
/**
|
|
696
665
|
* How the `handoff` MCP server (cli/src/mcp/handoff-server.mjs) recovers the Anthropic key
|
|
697
666
|
* WITHOUT it ever being written into the `--mcp-config` file on disk: `envName` is the NAME of a
|
|
@@ -723,12 +692,6 @@ export interface HandoffMcpParams {
|
|
|
723
692
|
/** The gateway ORIGIN (e.g. https://gateway.mnemom.ai) — see `resolveHandoffGatewayHost`. */
|
|
724
693
|
gatewayHost: string;
|
|
725
694
|
anthropicKeySource: HandoffAnthropicKeySource;
|
|
726
|
-
/**
|
|
727
|
-
* Where the server reads the Mnemom key (`x-mnemom-api-key`) from — same contract as
|
|
728
|
-
* `anthropicKeySource`: `ANTHROPIC_CUSTOM_HEADERS` (its `x-mnemom-api-key:` line) on a terminal
|
|
729
|
-
* launch, `HANDOFF_RC_MNEMOM_KEY_ENV_NAME` under Remote Control. Absent ⇒ no Mnemom key header.
|
|
730
|
-
*/
|
|
731
|
-
mnemomKeySource?: HandoffAnthropicKeySource;
|
|
732
695
|
agent: string;
|
|
733
696
|
conversationId: string;
|
|
734
697
|
/** `buildSessionConfigB64` output — forwarded so the route resolves the SAME per-session flag. */
|
package/dist/lib/agent.js
CHANGED
|
@@ -452,37 +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
460
|
/**
|
|
462
461
|
* The named presets for how the gateway folds a session's context (`--context-profile`,
|
|
463
|
-
* launcher.toml `context_profile`, `MNEMOM_AGENT_CONTEXT_PROFILE`)
|
|
464
|
-
* key at all and the cell's own default decides (see `resolveContextProfile`). A chosen profile
|
|
465
|
-
* is complete on its own, so a change to a cell's default can never change what it means:
|
|
462
|
+
* launcher.toml `context_profile`, `MNEMOM_AGENT_CONTEXT_PROFILE`):
|
|
466
463
|
* - `off` → `CONTEXT_RUNTIME_ENABLED: "false"` — compaction is left to the coding agent
|
|
467
464
|
* (the same bytes `--no-context` has always sent).
|
|
468
|
-
* - `balanced` →
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
* policy off: folds earlier and keeps a tighter working set at every size.
|
|
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.
|
|
472
468
|
* - `adaptive` → `CONTEXT_RUNTIME_SIZE_POLICY: "banded"` — the gateway picks the fold by the
|
|
473
469
|
* conversation's original size: no fold below 200k tokens, the aggressive
|
|
474
|
-
* budgets from 200k to 1M, balanced above.
|
|
470
|
+
* budgets from 200k to 1M, balanced above. Opt-in; never the default.
|
|
475
471
|
*/
|
|
476
472
|
export const CONTEXT_PROFILES = ["off", "balanced", "aggressive", "adaptive"];
|
|
477
473
|
/** The per-session env overlay each profile expands to (key order is the wire order). */
|
|
478
474
|
const CONTEXT_PROFILE_CONFIG = {
|
|
479
475
|
off: [[CONTEXT_RUNTIME_KEY, "false"]],
|
|
480
|
-
balanced: [
|
|
476
|
+
balanced: [],
|
|
481
477
|
aggressive: [
|
|
482
478
|
[CONTEXT_TAIL_BUDGET_KEY, "60000"],
|
|
483
479
|
[CONTEXT_READ_CACHE_KEY, "8000"],
|
|
484
480
|
[CONTEXT_HEAD_RECLAIM_KEY, "true"],
|
|
485
|
-
[CONTEXT_SIZE_POLICY_KEY, "off"],
|
|
486
481
|
],
|
|
487
482
|
adaptive: [[CONTEXT_SIZE_POLICY_KEY, "banded"]],
|
|
488
483
|
};
|
|
@@ -813,10 +808,8 @@ export function launchPreferenceExplicit(opts, env = process.env) {
|
|
|
813
808
|
* Has an orchestrator already run the session + µ-balance preflight for this
|
|
814
809
|
* launch? `MNEMOM_AGENT_PREFLIGHTED=1` is for orchestrators (the ADW fleet) that
|
|
815
810
|
* checked sign-in and balance themselves before spawning many launches; it skips
|
|
816
|
-
* the per-launch session
|
|
817
|
-
*
|
|
818
|
-
* Mnemom key is minted for it), and the Mnemom Agent entitlement (which also
|
|
819
|
-
* 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.
|
|
820
813
|
* Only the exact value `1` counts — anything else, including `true` or ` 1`, is
|
|
821
814
|
* a normal launch.
|
|
822
815
|
*/
|
|
@@ -917,20 +910,17 @@ export function parseContextProfile(raw, source) {
|
|
|
917
910
|
throw new Error(`${source} must be one of ${CONTEXT_PROFILES.join(", ")} (got '${raw}').`);
|
|
918
911
|
}
|
|
919
912
|
/**
|
|
920
|
-
* Which context profile this launch runs under,
|
|
921
|
-
* 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:
|
|
922
914
|
* 1. `--no-context` — always `off`. Combined with an explicit `--context-profile
|
|
923
915
|
* balanced|aggressive|adaptive` it is a CONFLICT and the launch refuses (never a silent override);
|
|
924
916
|
* `--context-profile off` agrees with it.
|
|
925
917
|
* 2. an explicit `--context-profile <profile>` flag (`--context` alongside it is fine — the
|
|
926
918
|
* profile wins);
|
|
927
|
-
* 3. `
|
|
928
|
-
* ledger), so a resume keeps that session's own choice over the saved default;
|
|
929
|
-
* 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`
|
|
930
920
|
* config key) — an invalid value is an error, never a silent default;
|
|
931
|
-
*
|
|
921
|
+
* 4. the folding boolean when NO profile is set anywhere: `context = false` in launcher.toml
|
|
932
922
|
* (→ `MNEMOM_AGENT_CONTEXT`, see `resolveContextFold`) means `off`;
|
|
933
|
-
*
|
|
923
|
+
* 5. `balanced` (the default).
|
|
934
924
|
*/
|
|
935
925
|
export function resolveContextProfile(opts) {
|
|
936
926
|
if (opts.context === false) {
|
|
@@ -941,33 +931,28 @@ export function resolveContextProfile(opts) {
|
|
|
941
931
|
}
|
|
942
932
|
if (opts.contextProfile !== undefined)
|
|
943
933
|
return opts.contextProfile;
|
|
944
|
-
if (opts.resumed)
|
|
945
|
-
return opts.resumed;
|
|
946
934
|
const raw = (opts.env?.MNEMOM_AGENT_CONTEXT_PROFILE ?? "").trim();
|
|
947
935
|
if (raw !== "")
|
|
948
936
|
return parseContextProfile(raw, "MNEMOM_AGENT_CONTEXT_PROFILE");
|
|
949
937
|
if (!resolveContextFold({ context: opts.context, env: opts.env }))
|
|
950
938
|
return "off";
|
|
951
|
-
return
|
|
939
|
+
return "balanced";
|
|
952
940
|
}
|
|
953
941
|
/**
|
|
954
942
|
* The decoded per-session env overlay for this launch — the `config` object of the
|
|
955
943
|
* `x-mnemom-session-config` payload, in wire order: the profile's keys first
|
|
956
|
-
* (`CONTEXT_RUNTIME_ENABLED` for `off`; the three fold-tuning keys
|
|
957
|
-
* `
|
|
958
|
-
* 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
|
|
959
946
|
* `GATEWAY_USAGE_REAL_SIZE: "on"` + `GATEWAY_COMPACTION_INTERCEPT: "on"` when EITHER the
|
|
960
947
|
* `compaction_intercept` setting is ON OR `--compact-at` arms a target below 1M (the target
|
|
961
948
|
* cannot be honored without the intercept), then `GATEWAY_COMPACTION_UPLOAD_TARGET_TOKENS: "<N>"`
|
|
962
|
-
* when a target is set. Empty
|
|
963
|
-
*
|
|
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.
|
|
964
951
|
*/
|
|
965
952
|
export function buildSessionConfig(opts) {
|
|
966
953
|
const config = {};
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
config[k] = v;
|
|
970
|
-
}
|
|
954
|
+
for (const [k, v] of CONTEXT_PROFILE_CONFIG[opts.profile])
|
|
955
|
+
config[k] = v;
|
|
971
956
|
if (opts.contextHandoff)
|
|
972
957
|
config[CONTEXT_HANDOFF_KEY] = "true";
|
|
973
958
|
const hasCompactionTarget = opts.compactAt !== undefined && opts.compactAt !== null;
|
|
@@ -999,12 +984,11 @@ export function buildSessionConfigPayload(opts) {
|
|
|
999
984
|
}
|
|
1000
985
|
/**
|
|
1001
986
|
* The `x-mnemom-session-config` value for this launch, or `undefined` when there is
|
|
1002
|
-
* nothing to override (the
|
|
1003
|
-
*
|
|
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:
|
|
1004
989
|
* - the context profile (`buildSessionConfig`): `off` → `CONTEXT_RUNTIME_ENABLED: "false"`,
|
|
1005
|
-
* `aggressive` → the three fold-tuning keys
|
|
1006
|
-
*
|
|
1007
|
-
* `CONTEXT_RUNTIME_SIZE_POLICY: "banded"`, none chosen → nothing;
|
|
990
|
+
* `aggressive` → the three fold-tuning keys, `adaptive` → `CONTEXT_RUNTIME_SIZE_POLICY:
|
|
991
|
+
* "banded"`, `balanced` → nothing;
|
|
1008
992
|
* - `compactionIntercept: true` → `GATEWAY_USAGE_REAL_SIZE` + `GATEWAY_COMPACTION_INTERCEPT`
|
|
1009
993
|
* `"on"` (the `compaction_intercept` setting);
|
|
1010
994
|
* - `compactAt: <N>` (`--compact-at`, below 1M) → the SAME two intercept keys plus
|
|
@@ -1022,14 +1006,6 @@ export function buildSessionConfigB64(opts) {
|
|
|
1022
1006
|
return undefined;
|
|
1023
1007
|
return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
|
|
1024
1008
|
}
|
|
1025
|
-
/**
|
|
1026
|
-
* A no-op `x-mnemom-session-config` value: `{ v: 1, config: {} }` overrides nothing (the gateway
|
|
1027
|
-
* applies an empty set, exactly its own defaults). buildSessionConfigB64 returns `undefined` for
|
|
1028
|
-
* the defaults — no header at all; this is for a call that must be Mnemom agent traffic (the
|
|
1029
|
-
* gateway's agent-traffic gate keys on the header's presence) without changing any setting: the
|
|
1030
|
-
* launcher's birth probe (commands/wrap.ts birthThroughGateway).
|
|
1031
|
-
*/
|
|
1032
|
-
export const NOOP_SESSION_CONFIG_B64 = Buffer.from(JSON.stringify({ v: 1, config: {} }), "utf8").toString("base64url");
|
|
1033
1009
|
/**
|
|
1034
1010
|
* Is the `handoff` MCP tool + `CONTEXT_HANDOFF_ENABLED` session-config header ON for
|
|
1035
1011
|
* this launch? OFF by default (operator directive, curation 2026-09-25): an absent flag
|
|
@@ -1073,12 +1049,6 @@ export const HANDOFF_MCP_SERVER_NAME = "mnemom-handoff";
|
|
|
1073
1049
|
* it the same way it inherits `ANTHROPIC_CUSTOM_HEADERS` under the terminal shape.
|
|
1074
1050
|
*/
|
|
1075
1051
|
export const HANDOFF_RC_KEY_ENV_NAME = "MNEMOM_HANDOFF_KEY";
|
|
1076
|
-
/**
|
|
1077
|
-
* Beside `HANDOFF_RC_KEY_ENV_NAME`: the non-`ANTHROPIC_*` var `spawnRcCli` sets to the launch's
|
|
1078
|
-
* Mnemom key when context handoff is on, so the handoff call carries the `x-mnemom-api-key` the
|
|
1079
|
-
* gateway requires on every `mnemom agent` request.
|
|
1080
|
-
*/
|
|
1081
|
-
export const HANDOFF_RC_MNEMOM_KEY_ENV_NAME = "MNEMOM_HANDOFF_MNEMOM_KEY";
|
|
1082
1052
|
/** The `--mcp-config` document registering exactly the `handoff` tool. Pure — no I/O. */
|
|
1083
1053
|
export function buildHandoffMcpConfig(p) {
|
|
1084
1054
|
const env = {
|
|
@@ -1087,8 +1057,6 @@ export function buildHandoffMcpConfig(p) {
|
|
|
1087
1057
|
MNEMOM_HANDOFF_AGENT: p.agent,
|
|
1088
1058
|
MNEMOM_HANDOFF_CONVERSATION_ID: p.conversationId,
|
|
1089
1059
|
};
|
|
1090
|
-
if (p.mnemomKeySource)
|
|
1091
|
-
env.MNEMOM_HANDOFF_MNEMOM_KEY_ENV_NAME = p.mnemomKeySource.envName;
|
|
1092
1060
|
if (p.sessionConfigB64)
|
|
1093
1061
|
env.MNEMOM_HANDOFF_SESSION_CONFIG = p.sessionConfigB64;
|
|
1094
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;
|
package/dist/lib/api.js
CHANGED
|
@@ -1385,65 +1385,6 @@ export async function createApiKey(name, scopes) {
|
|
|
1385
1385
|
}
|
|
1386
1386
|
return (await response.json());
|
|
1387
1387
|
}
|
|
1388
|
-
/**
|
|
1389
|
-
* POST /v1/orgs/{org_id}/api-keys — mint an ORG-owned key (its `org_id` is that org, so the
|
|
1390
|
-
* gateway births a new agent there). Owners and admins may mint any scopes; a member may mint a
|
|
1391
|
-
* key whose scopes are exactly ["gateway"]. A refusal (viewer/auditor, a non-member, or an API
|
|
1392
|
-
* that predates member org keys) is thrown as MnemomApiError with its status (403/404).
|
|
1393
|
-
*/
|
|
1394
|
-
export async function createOrgApiKey(orgId, name, scopes) {
|
|
1395
|
-
const url = validateUrl(`${API_BASE}/v1/orgs/${encodeURIComponent(sanitizeForHttp(orgId))}/api-keys`);
|
|
1396
|
-
const response = await fetchWithAuthRetry(url, async () => ({
|
|
1397
|
-
method: "POST",
|
|
1398
|
-
headers: { ...(await authHeaders()), "Content-Type": "application/json" },
|
|
1399
|
-
body: JSON.stringify({ name, scopes }),
|
|
1400
|
-
}));
|
|
1401
|
-
if (!response.ok) {
|
|
1402
|
-
if (response.status === 401)
|
|
1403
|
-
throw new MnemomApiError(401, NOT_AUTHENTICATED_MSG);
|
|
1404
|
-
throw await readApiError(response, "Failed to create org api key");
|
|
1405
|
-
}
|
|
1406
|
-
return (await response.json());
|
|
1407
|
-
}
|
|
1408
|
-
/**
|
|
1409
|
-
* GET /v1/api-keys/whoami authenticated by `key` ALONE (`X-Mnemom-Api-Key`, no session): does
|
|
1410
|
-
* the API accept this key? true = 200. false = 401/403 — revoked, rotated or unknown, OR a valid
|
|
1411
|
-
* `gateway`-only key: the API refuses every key without an `api:*` scope (ADR-049), so false
|
|
1412
|
-
* alone never proves a key dead. Throws on anything else (network, timeout, 429, 5xx): the
|
|
1413
|
-
* caller reads that as "could not check".
|
|
1414
|
-
*/
|
|
1415
|
-
export async function apiAcceptsMnemomKey(key, timeoutMs) {
|
|
1416
|
-
const url = validateUrl(`${API_BASE}/v1/api-keys/whoami`);
|
|
1417
|
-
const response = await mnemomFetch(url, {
|
|
1418
|
-
headers: { "X-Mnemom-Api-Key": sanitizeForHttp(key), Accept: "application/json" },
|
|
1419
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
1420
|
-
});
|
|
1421
|
-
if (response.ok)
|
|
1422
|
-
return true;
|
|
1423
|
-
if (response.status === 401 || response.status === 403)
|
|
1424
|
-
return false;
|
|
1425
|
-
throw new MnemomApiError(response.status, `api-key whoami: HTTP ${response.status}`);
|
|
1426
|
-
}
|
|
1427
|
-
/**
|
|
1428
|
-
* GET /v1/api-keys with a timeout, for checking a key: the signed-in caller's ACTIVE keys (a
|
|
1429
|
-
* revoked or rotated key is absent). null when there is no usable session (no credential, or
|
|
1430
|
-
* 401/403 after the refresh retry). Throws on anything else (network, timeout, 5xx).
|
|
1431
|
-
*/
|
|
1432
|
-
export async function listOwnApiKeysForCheck(timeoutMs) {
|
|
1433
|
-
if ((await resolveAuth()).type === "none")
|
|
1434
|
-
return null;
|
|
1435
|
-
const url = validateUrl(`${API_BASE}/v1/api-keys`);
|
|
1436
|
-
const response = await fetchWithAuthRetry(url, async () => ({
|
|
1437
|
-
headers: { ...(await authHeaders()), Accept: "application/json" },
|
|
1438
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
1439
|
-
}));
|
|
1440
|
-
if (response.status === 401 || response.status === 403)
|
|
1441
|
-
return null;
|
|
1442
|
-
if (!response.ok) {
|
|
1443
|
-
throw new MnemomApiError(response.status, `list api keys: HTTP ${response.status}`);
|
|
1444
|
-
}
|
|
1445
|
-
return (await response.json()).keys ?? [];
|
|
1446
|
-
}
|
|
1447
1388
|
/**
|
|
1448
1389
|
* POST /v1/api-keys/{key_id}/rotate — atomic mint-new + revoke-old.
|
|
1449
1390
|
* Returns the full new secret only on this call. The new key inherits
|
|
@@ -1469,16 +1410,13 @@ export async function rotateApiKey(keyId) {
|
|
|
1469
1410
|
}
|
|
1470
1411
|
/**
|
|
1471
1412
|
* DELETE /v1/api-keys/{key_id} — soft-revoke. The key row stays for
|
|
1472
|
-
* audit; `is_active` flips to false and `revoked_at` is timestamped.
|
|
1473
|
-
* a key the signed-in user created (an org key they minted included) is
|
|
1474
|
-
* found; anything else is a 404. `timeoutMs` bounds the call.
|
|
1413
|
+
* audit; `is_active` flips to false and `revoked_at` is timestamped.
|
|
1475
1414
|
*/
|
|
1476
|
-
export async function revokeApiKey(keyId
|
|
1415
|
+
export async function revokeApiKey(keyId) {
|
|
1477
1416
|
const url = validateUrl(`${API_BASE}/v1/api-keys/${encodeURIComponent(keyId)}`);
|
|
1478
1417
|
const response = await fetchWithAuthRetry(url, async () => ({
|
|
1479
1418
|
method: "DELETE",
|
|
1480
1419
|
headers: await authHeaders(),
|
|
1481
|
-
signal: opts.timeoutMs ? AbortSignal.timeout(opts.timeoutMs) : undefined,
|
|
1482
1420
|
}));
|
|
1483
1421
|
if (!response.ok) {
|
|
1484
1422
|
if (response.status === 401) {
|
|
@@ -56,11 +56,10 @@ export interface LauncherConfig {
|
|
|
56
56
|
*/
|
|
57
57
|
compactionIntercept?: boolean;
|
|
58
58
|
/**
|
|
59
|
-
* How the gateway folds each session's context (unset:
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* above). `--context-profile` overrides it for one launch without saving anything.
|
|
59
|
+
* How the gateway folds each session's context (`balanced` when unset): `off` leaves
|
|
60
|
+
* compaction to the coding agent, `balanced` keeps more earlier work verbatim, `aggressive`
|
|
61
|
+
* folds earlier with a tighter working set, `adaptive` sizes the fold to the conversation
|
|
62
|
+
* (none below 200k tokens, aggressive up to 1M, balanced above). `--context-profile` overrides it per launch.
|
|
64
63
|
*/
|
|
65
64
|
contextProfile?: ContextProfile;
|
|
66
65
|
/**
|
|
@@ -215,7 +215,7 @@ export const CONFIG_KEYS = [
|
|
|
215
215
|
},
|
|
216
216
|
{
|
|
217
217
|
key: "context_profile",
|
|
218
|
-
describe: `How the gateway folds each session's context (${CONTEXT_PROFILES.join("|")};
|
|
218
|
+
describe: `How the gateway folds each session's context (${CONTEXT_PROFILES.join("|")}; balanced by default)`,
|
|
219
219
|
get: (c) => c.contextProfile,
|
|
220
220
|
set: (c, v) => {
|
|
221
221
|
c.contextProfile = parseContextProfile(v, "context_profile");
|