@mnemom/mnemom 0.17.0-next.6 → 0.17.0-next.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.
@@ -1,147 +0,0 @@
1
- /**
2
- * `mnemom code config …` — read and write the persistent per-customer settings
3
- * for `mnemom code` (see lib/code-config.ts). A sub-verb of `mnemom code`, so a
4
- * customer configures the launcher once and never retypes their flags:
5
- *
6
- * mnemom code config list # show the current settings
7
- * mnemom code config get <key> # print one value
8
- * mnemom code config set <key> <value> # validate + persist one value
9
- * mnemom code config unset <key> # remove one value
10
- * mnemom code config edit # open ~/.mnemom/code.toml in $EDITOR
11
- * mnemom code config path # print the settings file path
12
- *
13
- * Settable keys are the single source of truth in lib/code-config.ts CONFIG_KEYS.
14
- * The secret Anthropic key is NOT a config key — it lives in ~/.mnemom/code.json.
15
- */
16
- import { spawnSync } from "node:child_process";
17
- import { existsSync } from "node:fs";
18
- import { CODE_CONFIG_PATH, CONFIG_KEYS, configKeySpec, loadCodeConfig, writeCodeConfig, } from "../lib/code-config.js";
19
- const out = (line = "") => console.log(line);
20
- const err = (line = "") => console.error(line);
21
- /** Entry point for `mnemom code config <verb> [args...]`. Throws on misuse. */
22
- export async function codeConfigCommand(argv) {
23
- const [verb, ...rest] = argv;
24
- switch (verb) {
25
- case undefined:
26
- case "list":
27
- return listConfig();
28
- case "path":
29
- out(CODE_CONFIG_PATH);
30
- return;
31
- case "get":
32
- return getConfig(rest[0]);
33
- case "set":
34
- return setConfig(rest[0], rest[1]);
35
- case "unset":
36
- return unsetConfig(rest[0]);
37
- case "edit":
38
- return editConfig();
39
- default:
40
- throw new Error(`mnemom code config: unknown verb '${verb}'. Use list | get | set | unset | edit | path.`);
41
- }
42
- }
43
- function listConfig() {
44
- const cfg = loadCodeConfig();
45
- const rows = [];
46
- for (const spec of CONFIG_KEYS) {
47
- const v = spec.get(cfg);
48
- if (v !== undefined)
49
- rows.push([spec.key, String(v)]);
50
- }
51
- if (!rows.length) {
52
- out(`No settings yet at ${CODE_CONFIG_PATH}.`);
53
- out("Set one with: mnemom code config set <key> <value>");
54
- out("");
55
- out("Settable keys:");
56
- for (const spec of CONFIG_KEYS)
57
- out(` ${spec.key.padEnd(22)} ${spec.describe}`);
58
- return;
59
- }
60
- const width = Math.max(...rows.map(([k]) => k.length));
61
- out(`# ${CODE_CONFIG_PATH}`);
62
- for (const [k, v] of rows)
63
- out(`${k.padEnd(width)} ${v}`);
64
- }
65
- function getConfig(key) {
66
- if (!key)
67
- throw new Error("mnemom code config get: a <key> is required.");
68
- const spec = requireSpec(key);
69
- const value = spec.get(loadCodeConfig());
70
- if (value === undefined) {
71
- err(`mnemom code config: '${key}' is not set.`);
72
- process.exitCode = 1;
73
- return;
74
- }
75
- out(String(value));
76
- }
77
- function setConfig(key, value) {
78
- if (!key)
79
- throw new Error("mnemom code config set: a <key> is required.");
80
- if (value === undefined)
81
- throw new Error(`mnemom code config set: a value for '${key}' is required.`);
82
- const spec = requireSpec(key);
83
- const cfg = loadCodeConfig();
84
- spec.set(cfg, value); // validates + coerces; throws on invalid
85
- writeCodeConfig(cfg);
86
- out(`${key} = ${String(spec.get(cfg))} (saved to ${CODE_CONFIG_PATH})`);
87
- }
88
- function unsetConfig(key) {
89
- if (!key)
90
- throw new Error("mnemom code config unset: a <key> is required.");
91
- requireSpec(key);
92
- const cfg = loadCodeConfig();
93
- deleteKey(cfg, key);
94
- writeCodeConfig(cfg);
95
- out(`unset ${key} (saved to ${CODE_CONFIG_PATH})`);
96
- }
97
- function editConfig() {
98
- // Seed a header-only file so $EDITOR opens something with guidance, not a blank.
99
- if (!existsSync(CODE_CONFIG_PATH))
100
- writeCodeConfig(loadCodeConfig());
101
- const editor = process.env.VISUAL || process.env.EDITOR || fallbackEditor();
102
- const res = spawnSync(editor, [CODE_CONFIG_PATH], { stdio: "inherit" });
103
- if (res.error) {
104
- throw new Error(`mnemom code config edit: could not launch editor '${editor}': ${res.error.message}\n` +
105
- ` Set $EDITOR, or edit ${CODE_CONFIG_PATH} directly.`);
106
- }
107
- // Re-parse so a typo surfaces now, not at the next launch.
108
- loadCodeConfig();
109
- out(`Saved ${CODE_CONFIG_PATH}.`);
110
- }
111
- function fallbackEditor() {
112
- for (const cand of ["nano", "vim", "vi"]) {
113
- const r = spawnSync("sh", ["-c", `command -v "$1" >/dev/null 2>&1`, "sh", cand], {
114
- stdio: "ignore",
115
- });
116
- if (r.status === 0)
117
- return cand;
118
- }
119
- return "vi";
120
- }
121
- function requireSpec(key) {
122
- const spec = configKeySpec(key);
123
- if (!spec) {
124
- throw new Error(`mnemom code config: unknown key '${key}'.\n Known keys: ${CONFIG_KEYS.map((k) => k.key).join(", ")}`);
125
- }
126
- return spec;
127
- }
128
- /** Remove a (possibly dotted) key from a config object, pruning an emptied table. */
129
- function deleteKey(cfg, key) {
130
- if (key.startsWith("guardrails.")) {
131
- const g = cfg.guardrails;
132
- if (!g)
133
- return;
134
- const field = key.slice("guardrails.".length);
135
- if (field === "max_turns")
136
- delete g.maxTurns;
137
- if (field === "budget_usd")
138
- delete g.budgetUsd;
139
- if (field === "stall_turns")
140
- delete g.stallTurns;
141
- if (g.maxTurns === undefined && g.budgetUsd === undefined && g.stallTurns === undefined) {
142
- delete cfg.guardrails;
143
- }
144
- return;
145
- }
146
- delete cfg[key === "key_source" ? "keySource" : key];
147
- }