@mnemom/mnemom 0.17.0-next.7 → 0.17.0-next.9
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 +26 -0
- package/dist/commands/agent-config.d.ts +12 -0
- package/dist/commands/agent-config.js +22 -2
- package/dist/commands/agent-session.d.ts +26 -10
- package/dist/commands/agent-session.js +59 -23
- package/dist/commands/agent-sessions.d.ts +99 -0
- package/dist/commands/agent-sessions.js +271 -0
- package/dist/commands/agent.d.ts +55 -0
- package/dist/commands/agent.js +123 -13
- package/dist/commands/validate.js +1 -16
- package/dist/index.js +47 -5
- package/dist/lib/agent-ledger.d.ts +91 -0
- package/dist/lib/agent-ledger.js +126 -0
- package/dist/lib/agent.d.ts +43 -1
- package/dist/lib/agent.js +80 -1
- package/dist/lib/api.d.ts +62 -0
- package/dist/lib/api.js +11 -0
- package/dist/lib/auth.js +21 -1
- package/dist/lib/format.d.ts +6 -0
- package/dist/lib/format.js +20 -0
- package/dist/lib/launcher-config.d.ts +3 -1
- package/dist/lib/launcher-config.js +20 -1
- package/dist/lib/oauth.d.ts +26 -4
- package/dist/lib/oauth.js +98 -29
- package/dist/rc-proxy.mjs +14 -4
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -44,6 +44,32 @@ That's it. `mnemom init` detects your configured AI provider API keys (Anthropic
|
|
|
44
44
|
| `mnemom card publish <file>` | Publish alignment card from JSON file |
|
|
45
45
|
| `mnemom card validate <file>` | Validate card JSON locally |
|
|
46
46
|
| `mnemom usage --org <id>` | Show per-person token and request consumption |
|
|
47
|
+
| `mnemom agent [name]` | Launch a governed coding agent through the gateway |
|
|
48
|
+
|
|
49
|
+
### `mnemom agent` — goal alignment
|
|
50
|
+
|
|
51
|
+
`mnemom agent` launches your coding-agent CLI (Claude Code today) with its model traffic
|
|
52
|
+
routed through the Mnemom gateway under a governed identity. Goal alignment — the judge
|
|
53
|
+
nudging the agent back when it drifts from your goal — comes in three modes; a bare
|
|
54
|
+
`mnemom agent` in a terminal asks which one you want (Enter = off, for now):
|
|
55
|
+
|
|
56
|
+
| Mode | How | What is sent |
|
|
57
|
+
| ------------ | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
|
|
58
|
+
| **Implicit** | `--implicit` — the gateway infers the goal from your own messages and revises it as you steer; nothing to type | `x-mnemom-goal-mode: implicit`, no contract |
|
|
59
|
+
| **Sealed** | `--goal "<statement>"` (+ `--requirement/--allow/--forbid/--goal-id`) — sealed as a contract on the first turn | `x-mnemom-contract` |
|
|
60
|
+
| **Off** | neither | neither header |
|
|
61
|
+
|
|
62
|
+
`--implicit` cannot be combined with the sealed-contract flags: a sealed contract always
|
|
63
|
+
wins on the gateway and would silently switch implicit mode off, so the launch refuses the
|
|
64
|
+
mix. The guardrail ceilings (`--budget`, `--max-turns`, `--stall`, or `guardrails.*` in
|
|
65
|
+
`~/.mnemom/launcher.toml`) apply in both modes — in implicit mode they ride on the mode
|
|
66
|
+
header. In implicit mode the goal lags your steering by one request: a response to a new
|
|
67
|
+
message carries `x-mnemom-goal-steer: queued` and the revision the agent acted under;
|
|
68
|
+
the next request reads the new revision (`x-mnemom-goal-revision`).
|
|
69
|
+
|
|
70
|
+
Make one mode the standing default with `mnemom agent config set goal_mode implicit`
|
|
71
|
+
(or `off`); `--goal` still seals for that launch and `--no-implicit` turns it off for one
|
|
72
|
+
launch. A sealed contract needs a per-launch statement, so it cannot be the default.
|
|
47
73
|
|
|
48
74
|
## How It Works
|
|
49
75
|
|
|
@@ -15,3 +15,15 @@
|
|
|
15
15
|
*/
|
|
16
16
|
/** Entry point for `mnemom agent config <verb> [args...]`. Throws on misuse. */
|
|
17
17
|
export declare function agentConfigCommand(argv: string[]): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* `$VISUAL` / `$EDITOR` is a program plus optional plain flags (`code --wait`, `emacsclient -t`),
|
|
20
|
+
* never shell syntax: the value is split on whitespace and every token must be a bare
|
|
21
|
+
* program name, path, or flag. Anything else (quotes, `;`, `$(`, backticks, redirections, …) is
|
|
22
|
+
* refused with a remediation rather than handed to spawnSync — the editor is launched WITHOUT a
|
|
23
|
+
* shell, so such a value could only ever fail confusingly or, via a lookalike binary on PATH, run
|
|
24
|
+
* something the user did not mean. Exported for the tests.
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseEditorSpec(spec: string): {
|
|
27
|
+
bin: string;
|
|
28
|
+
args: string[];
|
|
29
|
+
};
|
|
@@ -98,8 +98,8 @@ function editConfig() {
|
|
|
98
98
|
// Seed a header-only file so $EDITOR opens something with guidance, not a blank.
|
|
99
99
|
if (!existsSync(LAUNCHER_CONFIG_PATH))
|
|
100
100
|
writeLauncherConfig(loadLauncherConfig());
|
|
101
|
-
const editor = process.env.VISUAL || process.env.EDITOR || fallbackEditor();
|
|
102
|
-
const res = spawnSync(editor, [LAUNCHER_CONFIG_PATH], { stdio: "inherit" });
|
|
101
|
+
const { bin: editor, args: editorArgs } = parseEditorSpec(process.env.VISUAL || process.env.EDITOR || fallbackEditor());
|
|
102
|
+
const res = spawnSync(editor, [...editorArgs, LAUNCHER_CONFIG_PATH], { stdio: "inherit" });
|
|
103
103
|
if (res.error) {
|
|
104
104
|
throw new Error(`mnemom agent config edit: could not launch editor '${editor}': ${res.error.message}\n` +
|
|
105
105
|
` Set $EDITOR, or edit ${LAUNCHER_CONFIG_PATH} directly.`);
|
|
@@ -108,6 +108,23 @@ function editConfig() {
|
|
|
108
108
|
loadLauncherConfig();
|
|
109
109
|
out(`Saved ${LAUNCHER_CONFIG_PATH}.`);
|
|
110
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* `$VISUAL` / `$EDITOR` is a program plus optional plain flags (`code --wait`, `emacsclient -t`),
|
|
113
|
+
* never shell syntax: the value is split on whitespace and every token must be a bare
|
|
114
|
+
* program name, path, or flag. Anything else (quotes, `;`, `$(`, backticks, redirections, …) is
|
|
115
|
+
* refused with a remediation rather than handed to spawnSync — the editor is launched WITHOUT a
|
|
116
|
+
* shell, so such a value could only ever fail confusingly or, via a lookalike binary on PATH, run
|
|
117
|
+
* something the user did not mean. Exported for the tests.
|
|
118
|
+
*/
|
|
119
|
+
export function parseEditorSpec(spec) {
|
|
120
|
+
const tokens = spec.trim().split(/\s+/).filter(Boolean);
|
|
121
|
+
const SAFE = /^[A-Za-z0-9_./+=:@,-]+$/;
|
|
122
|
+
if (tokens.length === 0 || !tokens.every((t) => SAFE.test(t))) {
|
|
123
|
+
throw new Error(`mnemom agent config edit: refusing to run $VISUAL/$EDITOR value '${spec}' — only a program name or path plus plain flags is accepted (no shell syntax).\n` +
|
|
124
|
+
` Set $EDITOR to e.g. 'code --wait', or edit ${LAUNCHER_CONFIG_PATH} directly.`);
|
|
125
|
+
}
|
|
126
|
+
return { bin: tokens[0], args: tokens.slice(1) };
|
|
127
|
+
}
|
|
111
128
|
function fallbackEditor() {
|
|
112
129
|
for (const cand of ["nano", "vim", "vi"]) {
|
|
113
130
|
const r = spawnSync("sh", ["-c", `command -v "$1" >/dev/null 2>&1`, "sh", cand], {
|
|
@@ -158,6 +175,9 @@ function deleteKey(cfg, key) {
|
|
|
158
175
|
case "effort":
|
|
159
176
|
delete cfg.effort;
|
|
160
177
|
break;
|
|
178
|
+
case "goal_mode":
|
|
179
|
+
delete cfg.goalMode;
|
|
180
|
+
break;
|
|
161
181
|
case "cli":
|
|
162
182
|
delete cfg.cli;
|
|
163
183
|
break;
|
|
@@ -7,25 +7,35 @@
|
|
|
7
7
|
*
|
|
8
8
|
* 1. a SESSION NAME — labels the session in traces and the claude.ai session
|
|
9
9
|
* list (defaults to the current folder's name);
|
|
10
|
-
* 2.
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* 2. GOAL ALIGNMENT — one of three:
|
|
11
|
+
* - INFER it from your messages (implicit mode): nothing to type; the
|
|
12
|
+
* gateway reads your own messages, revises the goal as you steer, and the
|
|
13
|
+
* judge nudges the agent back when it drifts (a little µ per new message
|
|
14
|
+
* and per judged turn). Sends `x-mnemom-goal-mode: implicit`, no contract.
|
|
15
|
+
* - TYPE a one-line goal: sealed as a contract for the session; the judge
|
|
16
|
+
* nudges against it (a little µ per turn). Sends `x-mnemom-contract`.
|
|
17
|
+
* - OFF: the session runs governed with goal alignment off — neither header
|
|
18
|
+
* is sent, so the gateway's goal hooks are simply not engaged.
|
|
15
19
|
*
|
|
16
20
|
* Non-interactive runs (pipes, CI) never prompt — they get a clear error asking
|
|
17
|
-
* for a name. `--goal` on the command line always wins over the prompt
|
|
18
|
-
*
|
|
21
|
+
* for a name. `--goal` on the command line always wins over the prompt, and a
|
|
22
|
+
* resolved implicit launch (`--implicit`, or launcher.toml `goal_mode =
|
|
23
|
+
* "implicit"` with no `--no-implicit`) skips it too. Pure apart from the
|
|
24
|
+
* injected `ask` functions, so every arm is unit-tested.
|
|
19
25
|
*/
|
|
20
26
|
export interface SessionAsk {
|
|
21
27
|
askInput(question: string): Promise<string>;
|
|
22
28
|
askYesNo(question: string, defaultYes: boolean): Promise<boolean>;
|
|
29
|
+
/** Numbered single-select; resolves the chosen label, or null on no/invalid choice. */
|
|
30
|
+
askSelect(question: string, options: string[]): Promise<string | null>;
|
|
23
31
|
}
|
|
24
32
|
export interface SessionSetupInput {
|
|
25
33
|
/** The positional `[scenario]` (session name), if given. */
|
|
26
34
|
scenario?: string;
|
|
27
35
|
/** `--goal <statement>`, if given — skips the goal prompt. */
|
|
28
36
|
goal?: string;
|
|
37
|
+
/** Resolved implicit mode (flag or config default) — skips the goal prompt; alignment on without a contract. */
|
|
38
|
+
implicit?: boolean;
|
|
29
39
|
interactive: boolean;
|
|
30
40
|
/** For the default session name (tests inject one). */
|
|
31
41
|
cwd?: string;
|
|
@@ -34,17 +44,23 @@ export interface SessionSetupInput {
|
|
|
34
44
|
}
|
|
35
45
|
export interface SessionSetup {
|
|
36
46
|
scenario: string;
|
|
37
|
-
/** The goal statement to seal, or undefined =
|
|
47
|
+
/** The goal statement to seal, or undefined = no sealed contract (implicit or off). */
|
|
38
48
|
goal?: string;
|
|
39
|
-
goalAlignment: "on" | "off";
|
|
49
|
+
goalAlignment: "on" | "implicit" | "off";
|
|
40
50
|
/** True when the terminal prompts ran. */
|
|
41
51
|
prompted: boolean;
|
|
42
52
|
}
|
|
43
53
|
export declare const NO_SESSION_NAME_MESSAGE: string;
|
|
54
|
+
/** The three goal-alignment choices offered by the interactive prompt (labels are the select options). */
|
|
55
|
+
export declare const GOAL_CHOICE_IMPLICIT = "Infer my goal from my messages \u2014 nothing to type; revised as I steer (implicit mode)";
|
|
56
|
+
export declare const GOAL_CHOICE_TYPED = "Type a one-line goal \u2014 sealed as a contract for this session";
|
|
57
|
+
export declare const GOAL_CHOICE_OFF = "Off \u2014 run governed with goal alignment off (Enter)";
|
|
58
|
+
export declare const GOAL_CHOICES: readonly string[];
|
|
59
|
+
export declare const GOAL_CHOICE_QUESTION = "Goal alignment for this session?";
|
|
44
60
|
/** Current folder name, sanitised like an agent slug; "session" when that is empty. */
|
|
45
61
|
export declare function defaultSessionName(cwd?: string): string;
|
|
46
62
|
/** The one-line status printed at launch so the customer always knows the mode. */
|
|
47
|
-
export declare function goalAlignmentLine(
|
|
63
|
+
export declare function goalAlignmentLine(mode: boolean | "on" | "implicit" | "off"): string;
|
|
48
64
|
/**
|
|
49
65
|
* Resolve the session name + goal for this launch. See the module doc for the
|
|
50
66
|
* rules. Throws NO_SESSION_NAME_MESSAGE when no name was given and we cannot ask.
|
|
@@ -7,29 +7,50 @@
|
|
|
7
7
|
*
|
|
8
8
|
* 1. a SESSION NAME — labels the session in traces and the claude.ai session
|
|
9
9
|
* list (defaults to the current folder's name);
|
|
10
|
-
* 2.
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* 2. GOAL ALIGNMENT — one of three:
|
|
11
|
+
* - INFER it from your messages (implicit mode): nothing to type; the
|
|
12
|
+
* gateway reads your own messages, revises the goal as you steer, and the
|
|
13
|
+
* judge nudges the agent back when it drifts (a little µ per new message
|
|
14
|
+
* and per judged turn). Sends `x-mnemom-goal-mode: implicit`, no contract.
|
|
15
|
+
* - TYPE a one-line goal: sealed as a contract for the session; the judge
|
|
16
|
+
* nudges against it (a little µ per turn). Sends `x-mnemom-contract`.
|
|
17
|
+
* - OFF: the session runs governed with goal alignment off — neither header
|
|
18
|
+
* is sent, so the gateway's goal hooks are simply not engaged.
|
|
15
19
|
*
|
|
16
20
|
* Non-interactive runs (pipes, CI) never prompt — they get a clear error asking
|
|
17
|
-
* for a name. `--goal` on the command line always wins over the prompt
|
|
18
|
-
*
|
|
21
|
+
* for a name. `--goal` on the command line always wins over the prompt, and a
|
|
22
|
+
* resolved implicit launch (`--implicit`, or launcher.toml `goal_mode =
|
|
23
|
+
* "implicit"` with no `--no-implicit`) skips it too. Pure apart from the
|
|
24
|
+
* injected `ask` functions, so every arm is unit-tested.
|
|
19
25
|
*/
|
|
20
26
|
import { basename } from "node:path";
|
|
21
27
|
import { sanitizeAgentName } from "../lib/agent.js";
|
|
22
28
|
export const NO_SESSION_NAME_MESSAGE = "mnemom agent: a session name is required here (e.g. `mnemom agent onboarding`). " +
|
|
23
29
|
"In a terminal, plain `mnemom agent` asks for one.";
|
|
30
|
+
/** The three goal-alignment choices offered by the interactive prompt (labels are the select options). */
|
|
31
|
+
export const GOAL_CHOICE_IMPLICIT = "Infer my goal from my messages — nothing to type; revised as I steer (implicit mode)";
|
|
32
|
+
export const GOAL_CHOICE_TYPED = "Type a one-line goal — sealed as a contract for this session";
|
|
33
|
+
export const GOAL_CHOICE_OFF = "Off — run governed with goal alignment off (Enter)";
|
|
34
|
+
export const GOAL_CHOICES = [
|
|
35
|
+
GOAL_CHOICE_IMPLICIT,
|
|
36
|
+
GOAL_CHOICE_TYPED,
|
|
37
|
+
GOAL_CHOICE_OFF,
|
|
38
|
+
];
|
|
39
|
+
export const GOAL_CHOICE_QUESTION = "Goal alignment for this session?";
|
|
24
40
|
/** Current folder name, sanitised like an agent slug; "session" when that is empty. */
|
|
25
41
|
export function defaultSessionName(cwd = process.cwd()) {
|
|
26
42
|
return sanitizeAgentName(basename(cwd)) || "session";
|
|
27
43
|
}
|
|
28
44
|
/** The one-line status printed at launch so the customer always knows the mode. */
|
|
29
|
-
export function goalAlignmentLine(
|
|
30
|
-
|
|
45
|
+
export function goalAlignmentLine(mode) {
|
|
46
|
+
const m = mode === true ? "on" : mode === false ? "off" : mode;
|
|
47
|
+
if (m === "implicit") {
|
|
48
|
+
return ("mnemom agent: goal alignment: on, implicit (no sealed contract — the gateway infers your goal " +
|
|
49
|
+
"from your own messages, revises it as you steer, and the judge nudges the agent back when it drifts)");
|
|
50
|
+
}
|
|
51
|
+
return m === "on"
|
|
31
52
|
? "mnemom agent: goal alignment: on (the judge nudges the agent back when it drifts from your goal)"
|
|
32
|
-
: "mnemom agent: goal alignment: off (no goal set — pass --goal or set one when prompted)";
|
|
53
|
+
: "mnemom agent: goal alignment: off (no goal set — pass --goal or --implicit, or set one when prompted)";
|
|
33
54
|
}
|
|
34
55
|
const defaultSay = (line = "") => console.error(line);
|
|
35
56
|
/**
|
|
@@ -39,12 +60,13 @@ const defaultSay = (line = "") => console.error(line);
|
|
|
39
60
|
export async function resolveSessionSetup(input, ask) {
|
|
40
61
|
const say = input.say ?? defaultSay;
|
|
41
62
|
const flagGoal = (input.goal ?? "").trim();
|
|
63
|
+
const implicit = input.implicit === true;
|
|
42
64
|
const given = (input.scenario ?? "").trim();
|
|
43
65
|
if (given) {
|
|
44
66
|
return {
|
|
45
67
|
scenario: given,
|
|
46
68
|
goal: flagGoal || undefined,
|
|
47
|
-
goalAlignment: flagGoal ? "on" : "off",
|
|
69
|
+
goalAlignment: flagGoal ? "on" : implicit ? "implicit" : "off",
|
|
48
70
|
prompted: false,
|
|
49
71
|
};
|
|
50
72
|
}
|
|
@@ -57,22 +79,36 @@ export async function resolveSessionSetup(input, ask) {
|
|
|
57
79
|
say(` (Next time you can pass it directly: mnemom agent <name>.)`);
|
|
58
80
|
const typed = await ask.askInput(`Session name [${fallback}]:`);
|
|
59
81
|
const scenario = sanitizeAgentName(typed.trim()) || fallback;
|
|
60
|
-
// ── 2. goal (skipped when --goal was
|
|
82
|
+
// ── 2. goal alignment (skipped when --goal or implicit mode was resolved) ──
|
|
61
83
|
if (flagGoal) {
|
|
62
84
|
return { scenario, goal: flagGoal, goalAlignment: "on", prompted: true };
|
|
63
85
|
}
|
|
86
|
+
if (implicit) {
|
|
87
|
+
return { scenario, goalAlignment: "implicit", prompted: true };
|
|
88
|
+
}
|
|
64
89
|
say();
|
|
65
|
-
say("Goal alignment —
|
|
66
|
-
say("
|
|
67
|
-
say("
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
90
|
+
say("Goal alignment — how Mnemom keeps this session on track. Three choices:");
|
|
91
|
+
say(" Infer: nothing to type — the gateway reads your own messages, revises the goal as you");
|
|
92
|
+
say(" steer, and the judge nudges the agent back when it drifts (a little µ per message + turn).");
|
|
93
|
+
say(" Type a goal: one line, sealed as a contract; the judge nudges against it (a little µ per turn).");
|
|
94
|
+
say(" Off: the session runs governed with goal alignment off (the default — just press Enter).");
|
|
95
|
+
say(" (Make one the default: mnemom agent config set goal_mode implicit|off.)");
|
|
96
|
+
const choice = await ask.askSelect(GOAL_CHOICE_QUESTION, [...GOAL_CHOICES]);
|
|
97
|
+
if (choice === GOAL_CHOICE_IMPLICIT) {
|
|
98
|
+
return { scenario, goalAlignment: "implicit", prompted: true };
|
|
99
|
+
}
|
|
100
|
+
if (choice === GOAL_CHOICE_TYPED) {
|
|
101
|
+
const goal = (await ask.askInput("Goal (one line):")).trim();
|
|
102
|
+
if (!goal) {
|
|
103
|
+
say(" No goal entered — continuing with goal alignment off.");
|
|
104
|
+
return { scenario, goalAlignment: "off", prompted: true };
|
|
105
|
+
}
|
|
106
|
+
return { scenario, goal, goalAlignment: "on", prompted: true };
|
|
71
107
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
108
|
+
// Enter (no pick) and any invalid pick both resolve to null → off. Off is the
|
|
109
|
+
// deliberate default for now: a µ-costing mode is never picked by a bare Enter.
|
|
110
|
+
if (choice !== GOAL_CHOICE_OFF) {
|
|
111
|
+
say(" Goal alignment off (press 1 or 2 next time to turn it on).");
|
|
76
112
|
}
|
|
77
|
-
return { scenario,
|
|
113
|
+
return { scenario, goalAlignment: "off", prompted: true };
|
|
78
114
|
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mnemom agent sessions [--all] [--json]` and `mnemom agent show [ref] [--json]`
|
|
3
|
+
* — the read side of the local session ledger (`~/.mnemom/sessions.jsonl`, one
|
|
4
|
+
* line per real launch) merged with the gateway's live goal state for one
|
|
5
|
+
* session (`GET /v1/agent/sessions/{conversationId}` via mnemom-api).
|
|
6
|
+
*
|
|
7
|
+
* Pure apart from the injected deps (`readRecords`, `fetchSession`, `out`,
|
|
8
|
+
* `err`), so every arm is unit-tested; `liveSessionDeps` is the thin driver
|
|
9
|
+
* index.ts wires in.
|
|
10
|
+
*
|
|
11
|
+
* Hash note: the CLI's launch-time envelope sha will NOT equal the gateway's
|
|
12
|
+
* sealed hash in general (the gateway normalises absent arrays to `[]`), so the
|
|
13
|
+
* local sha is never printed as "the sealed hash" and no mismatch is flagged —
|
|
14
|
+
* only the server's hash is shown, labelled "sealed hash".
|
|
15
|
+
*/
|
|
16
|
+
import { type SessionRecord } from "../lib/agent-ledger.js";
|
|
17
|
+
import { type AgentSessionResponse } from "../lib/api.js";
|
|
18
|
+
export interface SessionCommandDeps {
|
|
19
|
+
/** The ledger, newest first. */
|
|
20
|
+
readRecords: () => SessionRecord[];
|
|
21
|
+
/** The live state from mnemom-api; rejects when unreachable / not found. */
|
|
22
|
+
fetchSession: (conversationId: string, agentId: string, orgId: string) => Promise<AgentSessionResponse>;
|
|
23
|
+
out: (line: string) => void;
|
|
24
|
+
err: (line: string) => void;
|
|
25
|
+
}
|
|
26
|
+
/** The production wiring (index.ts). Lazy so a test that mocks lib/api without
|
|
27
|
+
* this export can still import index.ts. */
|
|
28
|
+
export declare const liveSessionDeps: SessionCommandDeps;
|
|
29
|
+
export declare const NO_SESSIONS_MESSAGE = "No sessions yet \u2014 run `mnemom agent` to start one.";
|
|
30
|
+
export declare const DEFAULT_SESSIONS_LIMIT = 20;
|
|
31
|
+
export interface SessionRefMatch {
|
|
32
|
+
record: SessionRecord;
|
|
33
|
+
/** Older records sharing the same session name (only for name matches). */
|
|
34
|
+
others: SessionRecord[];
|
|
35
|
+
}
|
|
36
|
+
export interface SessionRefAmbiguous {
|
|
37
|
+
record: null;
|
|
38
|
+
/** Every record whose conversation id starts with the ref. */
|
|
39
|
+
candidates: SessionRecord[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resolve `[ref]` against the ledger (newest first):
|
|
43
|
+
* - no ref → the newest record;
|
|
44
|
+
* - an exact session name → the newest record with that name, older ones in `others`;
|
|
45
|
+
* - else a conversation-id prefix → the unique match, or `{record: null, candidates}`
|
|
46
|
+
* when several share the prefix;
|
|
47
|
+
* - nothing matches (or the ledger is empty) → null.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveSessionRef(records: SessionRecord[], ref?: string): SessionRefMatch | SessionRefAmbiguous | null;
|
|
50
|
+
/** Goal alignment as the ledger recorded it: a contract at launch ⇒ on. */
|
|
51
|
+
export declare function localGoalFlag(record: SessionRecord): "on" | "off";
|
|
52
|
+
/**
|
|
53
|
+
* Render the ledger as a table, newest first — the newest
|
|
54
|
+
* `DEFAULT_SESSIONS_LIMIT` rows unless `all`, with a footer naming the rest.
|
|
55
|
+
*/
|
|
56
|
+
export declare function formatSessionsTable(rows: SessionRecord[], opts: {
|
|
57
|
+
all?: boolean;
|
|
58
|
+
}): string[];
|
|
59
|
+
/** `turns 3/10 (crossed)` — value against its ceiling (none ⇒ just the value). */
|
|
60
|
+
export declare function gauge(label: string, value: number, ceiling: number | null, fired: boolean | undefined): string;
|
|
61
|
+
/**
|
|
62
|
+
* The human view for `mnemom agent show`: the local record, then the live
|
|
63
|
+
* gateway state (or a dim "live state unavailable (<reason>)" line when
|
|
64
|
+
* `remote` is null).
|
|
65
|
+
*/
|
|
66
|
+
export declare function buildShowView(local: SessionRecord, remote: AgentSessionResponse | null, reason?: string): string[];
|
|
67
|
+
/** The `--json` shape: the local record and the live section each tagged with its source. */
|
|
68
|
+
export interface ShowJson {
|
|
69
|
+
session: SessionRecord & {
|
|
70
|
+
source: "local";
|
|
71
|
+
};
|
|
72
|
+
goal_alignment: "on" | "off";
|
|
73
|
+
live: {
|
|
74
|
+
source: "gateway";
|
|
75
|
+
available: true;
|
|
76
|
+
sealed: AgentSessionResponse["sealed"];
|
|
77
|
+
verdict: AgentSessionResponse["verdict"];
|
|
78
|
+
turn: AgentSessionResponse["turn"];
|
|
79
|
+
guardrails: AgentSessionResponse["guardrails"];
|
|
80
|
+
} | {
|
|
81
|
+
source: "gateway";
|
|
82
|
+
available: false;
|
|
83
|
+
reason: string;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export declare function buildShowJson(local: SessionRecord, remote: AgentSessionResponse | null, reason?: string): ShowJson;
|
|
87
|
+
export interface AgentSessionsOptions {
|
|
88
|
+
all?: boolean;
|
|
89
|
+
json?: boolean;
|
|
90
|
+
}
|
|
91
|
+
/** `mnemom agent sessions [--all] [--json]` */
|
|
92
|
+
export declare function agentSessionsCommand(opts: AgentSessionsOptions, deps: SessionCommandDeps): Promise<void>;
|
|
93
|
+
export interface AgentShowOptions {
|
|
94
|
+
json?: boolean;
|
|
95
|
+
}
|
|
96
|
+
/** Why the live read could not happen, from the thrown error. */
|
|
97
|
+
export declare function unavailableReason(err: unknown): string;
|
|
98
|
+
/** `mnemom agent show [ref] [--json]` */
|
|
99
|
+
export declare function agentShowCommand(ref: string | undefined, opts: AgentShowOptions, deps: SessionCommandDeps): Promise<void>;
|