robrain 2.4.11 → 2.5.0

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.
@@ -0,0 +1,96 @@
1
+ export declare const DEFAULT_CAPTURE_KIND = "decision";
2
+ export interface CaptureKind {
3
+ name: string;
4
+ description: string;
5
+ }
6
+ export interface CaptureSettings {
7
+ instructions: string | null;
8
+ mode: 'strict' | 'broad';
9
+ confidence_min: number | null;
10
+ kinds: CaptureKind[];
11
+ }
12
+ export declare const DEFAULT_CAPTURE_SETTINGS: CaptureSettings;
13
+ export interface CaptureSettingsPatch {
14
+ instructions?: string | null;
15
+ mode?: string;
16
+ confidence_min?: number | null;
17
+ kinds?: CaptureKind[];
18
+ }
19
+ interface ExtractedDecision {
20
+ decision: string | null;
21
+ rationale: string | null;
22
+ rejected: Array<{
23
+ option: string;
24
+ reason: string;
25
+ }>;
26
+ confidence: number;
27
+ kind?: string;
28
+ subject?: string | null;
29
+ }
30
+ /** Same folding Perception applies to kind names, so add/remove match what is stored. */
31
+ export declare function normalizeKindName(name: string): string;
32
+ /** Tolerant reader for the settings Perception returns; bad fields fall back to the defaults. */
33
+ export declare function readCaptureSettings(raw: unknown): CaptureSettings;
34
+ export interface CaptureSetOptions {
35
+ projectId?: string;
36
+ instructions?: string;
37
+ instructionsFile?: string;
38
+ clearInstructions?: boolean;
39
+ mode?: string;
40
+ minConfidence?: string;
41
+ resetMinConfidence?: boolean;
42
+ addKind?: string[];
43
+ removeKind?: string[];
44
+ clearKinds?: boolean;
45
+ }
46
+ export interface CaptureTestOptions extends CaptureSetOptions {
47
+ file?: string;
48
+ user?: string;
49
+ reply?: string;
50
+ compare?: boolean;
51
+ }
52
+ export interface PreviewTurn {
53
+ user_message: string;
54
+ claude_reply: string;
55
+ }
56
+ export interface PreviewResult {
57
+ gate: 'keyword' | 'implicit' | 'broad' | 'none';
58
+ reaches_model: boolean;
59
+ extracted: ExtractedDecision | null;
60
+ stored: boolean;
61
+ reason?: string;
62
+ }
63
+ /** "name: description" (or "name = description") → a kind, or an error message. */
64
+ export declare function parseKindFlag(raw: string): {
65
+ kind: CaptureKind;
66
+ } | {
67
+ error: string;
68
+ };
69
+ /**
70
+ * One turn per line, as JSON: {"user_message": "...", "claude_reply": "..."}.
71
+ * Blank lines and comment lines starting with # are skipped.
72
+ */
73
+ export declare function parseTurnsJsonl(text: string): {
74
+ turns: PreviewTurn[];
75
+ } | {
76
+ error: string;
77
+ };
78
+ /**
79
+ * Turn CLI flags into the patch Perception's PUT accepts. Kind flags are
80
+ * resolved against the current list so add/remove compose; anything the
81
+ * user did not mention is left out of the patch and so unchanged.
82
+ */
83
+ export declare function buildCapturePatch(opts: CaptureSetOptions, current: CaptureSettings, readFile?: (path: string) => string): {
84
+ patch: CaptureSettingsPatch;
85
+ } | {
86
+ error: string;
87
+ };
88
+ export declare function formatCaptureSettings(settings: CaptureSettings, effectiveConfidenceMin: number): string[];
89
+ export declare function formatPreview(turns: PreviewTurn[], results: PreviewResult[], current?: PreviewResult[]): string[];
90
+ export declare function captureShowCommand(opts: {
91
+ projectId?: string;
92
+ }): Promise<void>;
93
+ export declare function captureSetCommand(opts: CaptureSetOptions): Promise<void>;
94
+ export declare function captureTestCommand(opts: CaptureTestOptions): Promise<void>;
95
+ export {};
96
+ //# sourceMappingURL=capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/commands/capture.ts"],"names":[],"mappings":"AA0BA,eAAO,MAAM,oBAAoB,aAAa,CAAA;AAE9C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAI,MAAM,GAAG,IAAI,CAAA;IAC7B,IAAI,EAAY,QAAQ,GAAG,OAAO,CAAA;IAClC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,KAAK,EAAW,WAAW,EAAE,CAAA;CAC9B;AAED,eAAO,MAAM,wBAAwB,EAAE,eAKtC,CAAA;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,CAAC,EAAI,MAAM,GAAG,IAAI,CAAA;IAC9B,IAAI,CAAC,EAAY,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,KAAK,CAAC,EAAW,WAAW,EAAE,CAAA;CAC/B;AAED,UAAU,iBAAiB;IACzB,QAAQ,EAAI,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,EAAG,MAAM,GAAG,IAAI,CAAA;IACzB,QAAQ,EAAI,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACrD,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAO,MAAM,CAAA;IAClB,OAAO,CAAC,EAAI,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,yFAAyF;AACzF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,iGAAiG;AACjG,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,CAajE;AAID,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAW,MAAM,CAAA;IAC3B,YAAY,CAAC,EAAQ,MAAM,CAAA;IAC3B,gBAAgB,CAAC,EAAI,MAAM,CAAA;IAC3B,iBAAiB,CAAC,EAAG,OAAO,CAAA;IAC5B,IAAI,CAAC,EAAgB,MAAM,CAAA;IAC3B,aAAa,CAAC,EAAO,MAAM,CAAA;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,OAAO,CAAC,EAAa,MAAM,EAAE,CAAA;IAC7B,UAAU,CAAC,EAAU,MAAM,EAAE,CAAA;IAC7B,UAAU,CAAC,EAAU,OAAO,CAAA;CAC7B;AAED,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,IAAI,CAAC,EAAK,MAAM,CAAA;IAChB,IAAI,CAAC,EAAK,MAAM,CAAA;IAChB,KAAK,CAAC,EAAI,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAW,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAA;IACxD,aAAa,EAAE,OAAO,CAAA;IACtB,SAAS,EAAM,iBAAiB,GAAG,IAAI,CAAA;IACvC,MAAM,EAAS,OAAO,CAAA;IACtB,MAAM,CAAC,EAAQ,MAAM,CAAA;CACtB;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAQpF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,WAAW,EAAE,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAoB1F;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,eAAe,EACxB,QAAQ,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAuC,GAClE;IAAE,KAAK,EAAE,oBAAoB,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAiDrD;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,GAAG,MAAM,EAAE,CAmBzG;AAmBD,wBAAgB,aAAa,CAC3B,KAAK,EAAE,WAAW,EAAE,EACpB,OAAO,EAAE,aAAa,EAAE,EACxB,OAAO,CAAC,EAAE,aAAa,EAAE,GACxB,MAAM,EAAE,CAmBV;AAkDD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CASpF;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgC9E;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgEhF"}
@@ -0,0 +1,356 @@
1
+ // packages/cli/src/commands/capture.ts
2
+ // ─────────────────────────────────────────────────────────────
3
+ // robrain capture show
4
+ // robrain capture set [--instructions "..." | --instructions-file <path> | --clear-instructions]
5
+ // [--mode strict|broad] [--min-confidence <0..1> | --reset-min-confidence]
6
+ // [--add-kind "name: description"]... [--remove-kind <name>]... [--clear-kinds]
7
+ // robrain capture test (--file <turns.jsonl> | --user "..." --reply "...") [same flags as set] [--compare]
8
+ //
9
+ // Tells the classifier, in plain language, what to store for this
10
+ // project: narrower or wider than the stock "decisions and their
11
+ // rejected alternatives", plus extra kinds of memory. Settings live on
12
+ // Perception (projects table) so every teammate's Sensing and the
13
+ // server-side re-extraction read the same ones. `test` is a dry run
14
+ // against sample turns: nothing is stored.
15
+ // ─────────────────────────────────────────────────────────────
16
+ import chalk from 'chalk';
17
+ import { readFileSync } from 'fs';
18
+ import { cwd } from 'process';
19
+ import { gatherProjectInfo } from '../lib/project.js';
20
+ import { exitUnreachable, perceptionEndpoint } from './projects.js';
21
+ // The CLI ships without @robrain/shared on purpose (self-contained tarball),
22
+ // so the wire shapes of GET/PUT /projects/:id/capture are restated here.
23
+ // Validation is Perception's job; the CLI prints the `errors` it returns.
24
+ export const DEFAULT_CAPTURE_KIND = 'decision';
25
+ export const DEFAULT_CAPTURE_SETTINGS = {
26
+ instructions: null,
27
+ mode: 'strict',
28
+ confidence_min: null,
29
+ kinds: [],
30
+ };
31
+ /** Same folding Perception applies to kind names, so add/remove match what is stored. */
32
+ export function normalizeKindName(name) {
33
+ return name.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '');
34
+ }
35
+ /** Tolerant reader for the settings Perception returns; bad fields fall back to the defaults. */
36
+ export function readCaptureSettings(raw) {
37
+ const r = (raw && typeof raw === 'object' ? raw : {});
38
+ const kinds = Array.isArray(r.kinds)
39
+ ? r.kinds.filter((k) => Boolean(k) && typeof k === 'object' &&
40
+ typeof k.name === 'string' && typeof k.description === 'string')
41
+ : [];
42
+ return {
43
+ instructions: typeof r.instructions === 'string' && r.instructions.trim() ? r.instructions : null,
44
+ mode: r.mode === 'broad' ? 'broad' : 'strict',
45
+ confidence_min: typeof r.confidence_min === 'number' ? r.confidence_min : null,
46
+ kinds,
47
+ };
48
+ }
49
+ /** "name: description" (or "name = description") → a kind, or an error message. */
50
+ export function parseKindFlag(raw) {
51
+ const match = raw.match(/^\s*([^:=]+?)\s*[:=]\s*(.+?)\s*$/s);
52
+ if (!match) {
53
+ return { error: `--add-kind expects "name: description", got "${raw}"` };
54
+ }
55
+ const name = normalizeKindName(match[1]);
56
+ if (!name)
57
+ return { error: `--add-kind: "${match[1]}" is not a usable kind name (letters, digits, - or _)` };
58
+ return { kind: { name, description: match[2].trim() } };
59
+ }
60
+ /**
61
+ * One turn per line, as JSON: {"user_message": "...", "claude_reply": "..."}.
62
+ * Blank lines and comment lines starting with # are skipped.
63
+ */
64
+ export function parseTurnsJsonl(text) {
65
+ const turns = [];
66
+ const lines = text.split('\n');
67
+ for (let i = 0; i < lines.length; i++) {
68
+ const line = lines[i].trim();
69
+ if (!line || line.startsWith('#'))
70
+ continue;
71
+ let parsed;
72
+ try {
73
+ parsed = JSON.parse(line);
74
+ }
75
+ catch {
76
+ return { error: `line ${i + 1} is not JSON` };
77
+ }
78
+ const t = parsed;
79
+ if (typeof t?.user_message !== 'string' || typeof t?.claude_reply !== 'string') {
80
+ return { error: `line ${i + 1} needs "user_message" and "claude_reply" strings` };
81
+ }
82
+ turns.push({ user_message: t.user_message, claude_reply: t.claude_reply });
83
+ }
84
+ if (turns.length === 0)
85
+ return { error: 'no turns found in the file' };
86
+ return { turns };
87
+ }
88
+ /**
89
+ * Turn CLI flags into the patch Perception's PUT accepts. Kind flags are
90
+ * resolved against the current list so add/remove compose; anything the
91
+ * user did not mention is left out of the patch and so unchanged.
92
+ */
93
+ export function buildCapturePatch(opts, current, readFile = (p) => readFileSync(p, 'utf8')) {
94
+ const patch = {};
95
+ const instructionSources = [opts.instructions !== undefined, opts.instructionsFile !== undefined, opts.clearInstructions === true]
96
+ .filter(Boolean).length;
97
+ if (instructionSources > 1) {
98
+ return { error: 'use only one of --instructions, --instructions-file, --clear-instructions' };
99
+ }
100
+ if (opts.clearInstructions)
101
+ patch.instructions = null;
102
+ else if (opts.instructions !== undefined)
103
+ patch.instructions = opts.instructions;
104
+ else if (opts.instructionsFile !== undefined) {
105
+ try {
106
+ patch.instructions = readFile(opts.instructionsFile);
107
+ }
108
+ catch (err) {
109
+ return { error: `could not read ${opts.instructionsFile}: ${err instanceof Error ? err.message : String(err)}` };
110
+ }
111
+ }
112
+ if (opts.mode !== undefined)
113
+ patch.mode = opts.mode;
114
+ if (opts.minConfidence !== undefined && opts.resetMinConfidence) {
115
+ return { error: 'use either --min-confidence or --reset-min-confidence' };
116
+ }
117
+ if (opts.resetMinConfidence)
118
+ patch.confidence_min = null;
119
+ else if (opts.minConfidence !== undefined) {
120
+ const n = Number(opts.minConfidence);
121
+ if (!Number.isFinite(n))
122
+ return { error: `--min-confidence must be a number between 0 and 1, got "${opts.minConfidence}"` };
123
+ patch.confidence_min = n;
124
+ }
125
+ const touchesKinds = opts.clearKinds || (opts.addKind?.length ?? 0) > 0 || (opts.removeKind?.length ?? 0) > 0;
126
+ if (touchesKinds) {
127
+ let kinds = opts.clearKinds ? [] : [...current.kinds];
128
+ for (const raw of opts.removeKind ?? []) {
129
+ const name = normalizeKindName(raw);
130
+ if (!kinds.some(k => k.name === name)) {
131
+ return { error: `--remove-kind: no kind named "${name}" (current: ${kinds.map(k => k.name).join(', ') || 'none'})` };
132
+ }
133
+ kinds = kinds.filter(k => k.name !== name);
134
+ }
135
+ for (const raw of opts.addKind ?? []) {
136
+ const parsed = parseKindFlag(raw);
137
+ if ('error' in parsed)
138
+ return { error: parsed.error };
139
+ kinds = [...kinds.filter(k => k.name !== parsed.kind.name), parsed.kind];
140
+ }
141
+ patch.kinds = kinds;
142
+ }
143
+ return { patch };
144
+ }
145
+ export function formatCaptureSettings(settings, effectiveConfidenceMin) {
146
+ const lines = [];
147
+ const modeNote = settings.mode === 'broad'
148
+ ? 'every non-trivial turn reaches the model (one extraction call per turn)'
149
+ : 'keyword gate; roughly 1 turn in 20 reaches the model';
150
+ lines.push(` Mode: ${chalk.cyan(settings.mode)} ${chalk.dim(modeNote)}`);
151
+ const thresholdNote = settings.confidence_min === null ? chalk.dim('(stock)') : chalk.dim('(project override)');
152
+ lines.push(` Threshold: ${chalk.cyan(effectiveConfidenceMin.toFixed(2))} ${thresholdNote}`);
153
+ lines.push(` Kinds: ${chalk.cyan(DEFAULT_CAPTURE_KIND)} ${chalk.dim('(built-in: decisions and their rejected alternatives)')}`);
154
+ for (const k of settings.kinds) {
155
+ lines.push(` ${chalk.cyan(k.name)} ${chalk.dim(k.description)}`);
156
+ }
157
+ if (settings.instructions) {
158
+ lines.push(' Instructions:');
159
+ for (const l of settings.instructions.split('\n'))
160
+ lines.push(` ${l}`);
161
+ }
162
+ else {
163
+ lines.push(` Instructions: ${chalk.dim('(none)')}`);
164
+ }
165
+ return lines;
166
+ }
167
+ function excerpt(text, max = 70) {
168
+ const flat = text.replace(/\s+/g, ' ').trim();
169
+ return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
170
+ }
171
+ function describeResult(r) {
172
+ if (!r.reaches_model)
173
+ return chalk.dim(`gate: ${r.gate} → skipped before the model`);
174
+ const e = r.extracted;
175
+ if (!e?.decision)
176
+ return chalk.dim(`gate: ${r.gate} → model saw it → nothing to store`);
177
+ const kind = e.kind && e.kind !== DEFAULT_CAPTURE_KIND ? `${e.kind}${e.subject ? ` (${e.subject})` : ''}` : DEFAULT_CAPTURE_KIND;
178
+ const head = r.stored
179
+ ? chalk.green(`stored as ${kind} (${e.confidence.toFixed(2)})`)
180
+ : chalk.yellow(`not stored: ${r.reason ?? 'below threshold'}`);
181
+ const rejected = e.rejected.length ? chalk.dim(` | rejected: ${e.rejected.map((x) => x.option).join(', ')}`) : '';
182
+ return `gate: ${r.gate} → ${head}: "${e.decision}"${rejected}`;
183
+ }
184
+ export function formatPreview(turns, results, current) {
185
+ const lines = [];
186
+ turns.forEach((turn, i) => {
187
+ const r = results[i];
188
+ if (!r)
189
+ return;
190
+ lines.push(` ${i + 1}. "${excerpt(turn.user_message)}"`);
191
+ lines.push(` ${describeResult(r)}`);
192
+ const c = current?.[i];
193
+ if (c)
194
+ lines.push(` ${chalk.dim('today:')} ${describeResult(c)}`);
195
+ });
196
+ const stored = results.filter(r => r.stored).length;
197
+ const reached = results.filter(r => r.reaches_model).length;
198
+ lines.push('');
199
+ lines.push(` ${turns.length} turn${turns.length === 1 ? '' : 's'}: ${reached} reached the model, ${stored} would be stored.`);
200
+ if (current) {
201
+ const storedToday = current.filter(r => r.stored).length;
202
+ lines.push(chalk.dim(` With the settings saved today: ${storedToday} would be stored.`));
203
+ }
204
+ return lines;
205
+ }
206
+ function resolveProjectId(override) {
207
+ return override ?? gatherProjectInfo(cwd()).id;
208
+ }
209
+ async function fetchSettings(projectId) {
210
+ const { url, key } = perceptionEndpoint();
211
+ const res = await fetch(`${url}/projects/${encodeURIComponent(projectId)}/capture`, {
212
+ headers: key ? { Authorization: `Bearer ${key}` } : {},
213
+ }).catch((err) => exitUnreachable(url, err));
214
+ if (!res.ok)
215
+ await failWithBody(res, `Could not read capture settings for project ${projectId}`, url);
216
+ const raw = await res.json();
217
+ const settings = readCaptureSettings(raw);
218
+ return { ...settings, effective_confidence_min: typeof raw.effective_confidence_min === 'number' ? raw.effective_confidence_min : 0.6 };
219
+ }
220
+ async function failWithBody(res, title, url) {
221
+ const raw = await res.text().catch(() => '');
222
+ console.log(chalk.red(` ✗ ${title} (${res.status})`));
223
+ try {
224
+ const j = JSON.parse(raw);
225
+ if (j.message)
226
+ console.log(chalk.yellow(` ${j.message}`));
227
+ if (j.hint)
228
+ console.log(chalk.dim(` ${j.hint}`));
229
+ for (const e of j.errors ?? [])
230
+ console.log(chalk.yellow(` • ${e}`));
231
+ if (j.detail)
232
+ console.log(chalk.dim(` ${j.detail}`));
233
+ }
234
+ catch {
235
+ if (raw)
236
+ console.log(chalk.dim(` ${raw.slice(0, 400)}`));
237
+ }
238
+ if (res.status === 404 && /Not Found|Cannot GET|Cannot PUT|Cannot POST/i.test(raw)) {
239
+ console.log(chalk.dim(' This Perception predates capture settings. Upgrade it with ') + chalk.cyan('npx robrain@latest up') + chalk.dim(' (or pnpm docker:up:build from a clone).'));
240
+ }
241
+ console.log(chalk.dim(` Perception: ${url}\n`));
242
+ process.exit(1);
243
+ }
244
+ function printHeader(projectId, url) {
245
+ console.log();
246
+ console.log(chalk.bold(' Capture settings') + chalk.dim(` · project ${projectId}`));
247
+ console.log(chalk.dim(` ${url}\n`));
248
+ }
249
+ // ── Commands ──────────────────────────────────────────────────
250
+ export async function captureShowCommand(opts) {
251
+ const projectId = resolveProjectId(opts.projectId);
252
+ const { url } = perceptionEndpoint();
253
+ const settings = await fetchSettings(projectId);
254
+ printHeader(projectId, url);
255
+ for (const line of formatCaptureSettings(settings, settings.effective_confidence_min))
256
+ console.log(line);
257
+ console.log();
258
+ console.log(chalk.dim(' Change them with ') + chalk.cyan('npx robrain capture set --help') + chalk.dim('; try them first with ') + chalk.cyan('npx robrain capture test') + chalk.dim('.'));
259
+ console.log();
260
+ }
261
+ export async function captureSetCommand(opts) {
262
+ const projectId = resolveProjectId(opts.projectId);
263
+ const { url, key } = perceptionEndpoint();
264
+ const current = await fetchSettings(projectId);
265
+ const built = buildCapturePatch(opts, current);
266
+ if ('error' in built) {
267
+ console.log(chalk.red(`\n ✗ ${built.error}\n`));
268
+ process.exit(1);
269
+ }
270
+ if (Object.keys(built.patch).length === 0) {
271
+ console.log(chalk.yellow('\n Nothing to change. See ') + chalk.cyan('npx robrain capture set --help') + chalk.yellow(' for the flags.\n'));
272
+ process.exit(1);
273
+ }
274
+ const res = await fetch(`${url}/projects/${encodeURIComponent(projectId)}/capture`, {
275
+ method: 'PUT',
276
+ headers: { 'Content-Type': 'application/json', ...(key ? { Authorization: `Bearer ${key}` } : {}) },
277
+ body: JSON.stringify(built.patch),
278
+ }).catch((err) => exitUnreachable(url, err));
279
+ if (!res.ok)
280
+ await failWithBody(res, 'Could not save capture settings', url);
281
+ const saved = await res.json();
282
+ printHeader(projectId, url);
283
+ console.log(chalk.green(' ✓ Saved\n'));
284
+ for (const line of formatCaptureSettings(readCaptureSettings(saved), saved.effective_confidence_min))
285
+ console.log(line);
286
+ console.log();
287
+ if (saved.mode === 'broad' && current.mode !== 'broad') {
288
+ console.log(chalk.yellow(' Broad mode sends every non-trivial turn to the extraction model, on your own LLM key.'));
289
+ }
290
+ console.log(chalk.dim(' Running Sensing servers pick this up within 5 minutes, or on their next session start.'));
291
+ console.log();
292
+ }
293
+ export async function captureTestCommand(opts) {
294
+ const projectId = resolveProjectId(opts.projectId);
295
+ const { url, key } = perceptionEndpoint();
296
+ let turns;
297
+ if (opts.file) {
298
+ let text;
299
+ try {
300
+ text = readFileSync(opts.file, 'utf8');
301
+ }
302
+ catch (err) {
303
+ console.log(chalk.red(`\n ✗ Could not read ${opts.file}: ${err instanceof Error ? err.message : String(err)}\n`));
304
+ process.exit(1);
305
+ }
306
+ const parsed = parseTurnsJsonl(text);
307
+ if ('error' in parsed) {
308
+ console.log(chalk.red(`\n ✗ ${opts.file}: ${parsed.error}\n`));
309
+ process.exit(1);
310
+ }
311
+ turns = parsed.turns;
312
+ }
313
+ else if (opts.user !== undefined && opts.reply !== undefined) {
314
+ turns = [{ user_message: opts.user, claude_reply: opts.reply }];
315
+ }
316
+ else {
317
+ console.log(chalk.red('\n ✗ Give sample turns: ') + chalk.cyan('--file turns.jsonl') + chalk.red(' (one {"user_message","claude_reply"} per line) or ') + chalk.cyan('--user "..." --reply "..."') + '\n');
318
+ process.exit(1);
319
+ }
320
+ if (turns.length > 20) {
321
+ console.log(chalk.red(`\n ✗ At most 20 turns per test (got ${turns.length}); each one that reaches the model costs an extraction call.\n`));
322
+ process.exit(1);
323
+ }
324
+ const current = await fetchSettings(projectId);
325
+ const built = buildCapturePatch(opts, current);
326
+ if ('error' in built) {
327
+ console.log(chalk.red(`\n ✗ ${built.error}\n`));
328
+ process.exit(1);
329
+ }
330
+ const hasCandidate = Object.keys(built.patch).length > 0;
331
+ const res = await fetch(`${url}/projects/${encodeURIComponent(projectId)}/capture/preview`, {
332
+ method: 'POST',
333
+ headers: { 'Content-Type': 'application/json', ...(key ? { Authorization: `Bearer ${key}` } : {}) },
334
+ body: JSON.stringify({
335
+ ...(hasCandidate ? { settings: built.patch } : {}),
336
+ turns,
337
+ compare_with_current: Boolean(opts.compare && hasCandidate),
338
+ }),
339
+ }).catch((err) => exitUnreachable(url, err));
340
+ if (!res.ok)
341
+ await failWithBody(res, 'Capture test failed', url);
342
+ const data = await res.json();
343
+ printHeader(projectId, url);
344
+ console.log(chalk.bold(hasCandidate ? ' Testing these settings (not saved):' : ' Testing the saved settings:'));
345
+ for (const line of formatCaptureSettings(readCaptureSettings(data.settings), data.settings.effective_confidence_min))
346
+ console.log(line);
347
+ console.log();
348
+ for (const line of formatPreview(turns, data.results, data.current))
349
+ console.log(line);
350
+ console.log();
351
+ if (hasCandidate) {
352
+ console.log(chalk.dim(' Nothing was saved. Keep these settings with the same flags on ') + chalk.cyan('npx robrain capture set') + chalk.dim('.'));
353
+ console.log();
354
+ }
355
+ }
356
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/commands/capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=capture.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.test.d.ts","sourceRoot":"","sources":["../../src/commands/capture.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,102 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { DEFAULT_CAPTURE_SETTINGS, buildCapturePatch, formatPreview, parseKindFlag, parseTurnsJsonl, readCaptureSettings, } from './capture.js';
4
+ const withKinds = {
5
+ ...DEFAULT_CAPTURE_SETTINGS,
6
+ kinds: [
7
+ { name: 'run', description: 'The outcome of an agent run.' },
8
+ { name: 'gotcha', description: 'A trap the team hit.' },
9
+ ],
10
+ };
11
+ describe('parseKindFlag', () => {
12
+ it('accepts "name: description" and "name = description"', () => {
13
+ assert.deepEqual(parseKindFlag('run: The outcome of an agent run.'), { kind: { name: 'run', description: 'The outcome of an agent run.' } });
14
+ assert.deepEqual(parseKindFlag('Agent Run = what ran'), { kind: { name: 'agent-run', description: 'what ran' } });
15
+ });
16
+ it('rejects a flag with no description', () => {
17
+ const r = parseKindFlag('run');
18
+ assert.ok('error' in r);
19
+ });
20
+ });
21
+ describe('parseTurnsJsonl', () => {
22
+ it('reads one turn per line and skips blanks and comments', () => {
23
+ const r = parseTurnsJsonl([
24
+ '# sample',
25
+ '{"user_message":"let us use pnpm","claude_reply":"ok"}',
26
+ '',
27
+ '{"user_message":"thanks","claude_reply":"np"}',
28
+ ].join('\n'));
29
+ assert.ok('turns' in r);
30
+ assert.equal(r.turns.length, 2);
31
+ assert.equal(r.turns[0].user_message, 'let us use pnpm');
32
+ });
33
+ it('names the bad line', () => {
34
+ const r = parseTurnsJsonl('{"user_message":"x","claude_reply":"y"}\nnot json');
35
+ assert.ok('error' in r);
36
+ assert.match(r.error, /line 2/);
37
+ const missing = parseTurnsJsonl('{"user_message":"x"}');
38
+ assert.ok('error' in missing);
39
+ assert.match(missing.error, /claude_reply/);
40
+ });
41
+ });
42
+ describe('buildCapturePatch', () => {
43
+ it('leaves untouched fields out of the patch', () => {
44
+ const r = buildCapturePatch({ mode: 'broad' }, DEFAULT_CAPTURE_SETTINGS);
45
+ assert.deepEqual(r, { patch: { mode: 'broad' } });
46
+ });
47
+ it('reads instructions from a file and clears them on request', () => {
48
+ const fromFile = buildCapturePatch({ instructionsFile: 'rules.md' }, DEFAULT_CAPTURE_SETTINGS, () => 'Also store gotchas.');
49
+ assert.deepEqual(fromFile, { patch: { instructions: 'Also store gotchas.' } });
50
+ const cleared = buildCapturePatch({ clearInstructions: true }, DEFAULT_CAPTURE_SETTINGS);
51
+ assert.deepEqual(cleared, { patch: { instructions: null } });
52
+ });
53
+ it('refuses two instruction sources at once', () => {
54
+ const r = buildCapturePatch({ instructions: 'a', clearInstructions: true }, DEFAULT_CAPTURE_SETTINGS);
55
+ assert.ok('error' in r);
56
+ });
57
+ it('parses the threshold and rejects text', () => {
58
+ assert.deepEqual(buildCapturePatch({ minConfidence: '0.75' }, DEFAULT_CAPTURE_SETTINGS), { patch: { confidence_min: 0.75 } });
59
+ assert.deepEqual(buildCapturePatch({ resetMinConfidence: true }, DEFAULT_CAPTURE_SETTINGS), { patch: { confidence_min: null } });
60
+ assert.ok('error' in buildCapturePatch({ minConfidence: 'high' }, DEFAULT_CAPTURE_SETTINGS));
61
+ });
62
+ it('composes kind add/remove over the current list', () => {
63
+ const r = buildCapturePatch({ removeKind: ['gotcha'], addKind: ['owner: Who owns a service right now.'] }, withKinds);
64
+ assert.ok('patch' in r);
65
+ assert.deepEqual(r.patch.kinds, [
66
+ { name: 'run', description: 'The outcome of an agent run.' },
67
+ { name: 'owner', description: 'Who owns a service right now.' },
68
+ ]);
69
+ });
70
+ it('re-adding a kind replaces its description', () => {
71
+ const r = buildCapturePatch({ addKind: ['run: What the last run did.'] }, withKinds);
72
+ assert.ok('patch' in r);
73
+ assert.deepEqual(r.patch.kinds?.map((k) => k.description), ['A trap the team hit.', 'What the last run did.']);
74
+ });
75
+ it('errors when removing a kind that is not there, and clears all on --clear-kinds', () => {
76
+ const missing = buildCapturePatch({ removeKind: ['nope'] }, withKinds);
77
+ assert.ok('error' in missing);
78
+ assert.match(missing.error, /no kind named "nope"/);
79
+ assert.deepEqual(buildCapturePatch({ clearKinds: true }, withKinds), { patch: { kinds: [] } });
80
+ });
81
+ });
82
+ describe('readCaptureSettings', () => {
83
+ it('falls back field by field on a malformed response', () => {
84
+ const s = readCaptureSettings({ instructions: ' ', mode: 'loud', confidence_min: '0.9', kinds: [{ name: 'run' }, { name: 'ok', description: 'd' }] });
85
+ assert.deepEqual(s, { instructions: null, mode: 'strict', confidence_min: null, kinds: [{ name: 'ok', description: 'd' }] });
86
+ });
87
+ });
88
+ describe('formatPreview', () => {
89
+ it('counts what reached the model and what would be stored', () => {
90
+ const turns = [
91
+ { user_message: 'let us use pnpm', claude_reply: 'ok' },
92
+ { user_message: 'thanks', claude_reply: 'np' },
93
+ ];
94
+ const lines = formatPreview(turns, [
95
+ { gate: 'keyword', reaches_model: true, stored: true, extracted: { decision: 'Use pnpm', rationale: null, rejected: [], confidence: 0.9, kind: 'decision', subject: null } },
96
+ { gate: 'none', reaches_model: false, stored: false, extracted: null },
97
+ ]);
98
+ assert.match(lines.join('\n'), /2 turns: 1 reached the model, 1 would be stored/);
99
+ assert.match(lines.join('\n'), /stored as decision \(0\.90\): "Use pnpm"/);
100
+ });
101
+ });
102
+ //# sourceMappingURL=capture.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.test.js","sourceRoot":"","sources":["../../src/commands/capture.test.ts"],"names":[],"mappings":"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"}
@@ -255,7 +255,7 @@ export async function installCommand(opts) {
255
255
  // Display only (status) — the thin client never embeds locally.
256
256
  ...(provisioned.embeddingProvider ? { embeddingProvider: provisioned.embeddingProvider } : {}),
257
257
  installedAt: new Date().toISOString(),
258
- version: '2.4.11',
258
+ version: '2.5.0',
259
259
  });
260
260
  spinner.succeed('MCP servers configured');
261
261
  // ── Done ───────────────────────────────────────────────────
@@ -443,7 +443,7 @@ async function installSelfHosted(opts) {
443
443
  ...(perceptionKey ? { perceptionKey } : {}),
444
444
  embeddingProvider: provider,
445
445
  installedAt: new Date().toISOString(),
446
- version: '2.4.11',
446
+ version: '2.5.0',
447
447
  selfHosted: true,
448
448
  });
449
449
  spinner.succeed('MCP servers configured for self-hosted mode');