mnueron 0.4.0 → 0.6.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.
- package/INSTALL.md +125 -0
- package/LICENSE +28 -21
- package/NOTICE +164 -0
- package/README.md +443 -422
- package/dist/cli.js +114 -26
- package/dist/cli.js.map +1 -1
- package/dist/config.js +4 -1
- package/dist/config.js.map +1 -1
- package/dist/detectors/codex.js +138 -0
- package/dist/detectors/codex.js.map +1 -0
- package/dist/detectors/index.js +2 -0
- package/dist/detectors/index.js.map +1 -1
- package/dist/detectors/json_detector.js +1 -1
- package/dist/lib/context-engine/confidence.js +153 -0
- package/dist/lib/context-engine/confidence.js.map +1 -0
- package/dist/lib/context-engine/entities.js +179 -0
- package/dist/lib/context-engine/entities.js.map +1 -0
- package/dist/lib/context-engine/index.js +74 -0
- package/dist/lib/context-engine/index.js.map +1 -0
- package/dist/lib/context-engine/intent.js +139 -0
- package/dist/lib/context-engine/intent.js.map +1 -0
- package/dist/lib/context-engine/runbook-detector.js +206 -0
- package/dist/lib/context-engine/runbook-detector.js.map +1 -0
- package/dist/lib/date-anchors.js +351 -0
- package/dist/lib/date-anchors.js.map +1 -0
- package/dist/lib/temporal-intent.js +98 -0
- package/dist/lib/temporal-intent.js.map +1 -0
- package/dist/runbook/auto-extract.js +415 -0
- package/dist/runbook/auto-extract.js.map +1 -0
- package/dist/runbook/capture.js +214 -0
- package/dist/runbook/capture.js.map +1 -0
- package/dist/runbook/explain.js +154 -0
- package/dist/runbook/explain.js.map +1 -0
- package/dist/runbook/fingerprint.js +128 -0
- package/dist/runbook/fingerprint.js.map +1 -0
- package/dist/runbook/search.js +76 -0
- package/dist/runbook/search.js.map +1 -0
- package/dist/runbook/types.js +15 -0
- package/dist/runbook/types.js.map +1 -0
- package/dist/setup.js +32 -4
- package/dist/setup.js.map +1 -1
- package/dist/store/entity-extractor.js +69 -2
- package/dist/store/entity-extractor.js.map +1 -1
- package/dist/store/local-db.js +33 -0
- package/dist/store/local-db.js.map +1 -0
- package/dist/store/local.js +230 -229
- package/dist/store/local.js.map +1 -1
- package/dist/store/procedural.js +185 -0
- package/dist/store/procedural.js.map +1 -1
- package/dist/store/remote.js +73 -0
- package/dist/store/remote.js.map +1 -1
- package/dist/tools.js +393 -8
- package/dist/tools.js.map +1 -1
- package/package.json +63 -55
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/runbook/capture.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mnueron explain-error` — paste-an-error → suggested fixes.
|
|
3
|
+
*
|
|
4
|
+
* The simplest, least-invasive entry point to the Terminal Copilot:
|
|
5
|
+
* user copies an error from their terminal, pastes it into a prompt,
|
|
6
|
+
* and gets back known fixes (with confidence labels) or a suggestion
|
|
7
|
+
* to capture a new runbook if nothing matches.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* mnueron explain-error (reads stdin, ends on EOF)
|
|
11
|
+
* mnueron explain-error --file path/to/error.log (reads file)
|
|
12
|
+
* mnueron explain-error --text "fatal: ..." (one-liner via flag)
|
|
13
|
+
* mnueron explain-error --ns mnueron (namespace scope)
|
|
14
|
+
* mnueron explain-error --json (machine-readable output)
|
|
15
|
+
*/
|
|
16
|
+
import { readFile } from 'node:fs/promises';
|
|
17
|
+
import { loadConfig, makeProvider } from '../config.js';
|
|
18
|
+
import { openLocalDb } from '../store/local-db.js';
|
|
19
|
+
import { fingerprintError } from './fingerprint.js';
|
|
20
|
+
import { searchRunbooks } from './search.js';
|
|
21
|
+
export async function cmdExplainError(args) {
|
|
22
|
+
const opts = parseArgs(args);
|
|
23
|
+
const errorText = await readErrorInput(opts);
|
|
24
|
+
if (!errorText.trim()) {
|
|
25
|
+
console.error('No error text provided. Pipe an error in, use --file, or --text "..."');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
const cfg = loadConfig();
|
|
29
|
+
const provider = makeProvider(cfg);
|
|
30
|
+
const db = openLocalDb(cfg.dbPath);
|
|
31
|
+
const fp = fingerprintError(errorText);
|
|
32
|
+
if (!opts.json) {
|
|
33
|
+
console.log('');
|
|
34
|
+
console.log(`Fingerprint: ${fp.hash}${fp.tool ? ` (tool: ${fp.tool})` : ''}`);
|
|
35
|
+
if (fp.redactedCount > 0) {
|
|
36
|
+
console.log(`Redacted ${fp.redactedCount} secret${fp.redactedCount > 1 ? 's' : ''}: ${fp.redactedKinds.join(', ')}`);
|
|
37
|
+
}
|
|
38
|
+
console.log('');
|
|
39
|
+
}
|
|
40
|
+
const hits = await searchRunbooks(fp, {
|
|
41
|
+
db,
|
|
42
|
+
provider,
|
|
43
|
+
namespace: opts.namespace,
|
|
44
|
+
});
|
|
45
|
+
if (opts.json) {
|
|
46
|
+
console.log(JSON.stringify({
|
|
47
|
+
fingerprint: { hash: fp.hash, tool: fp.tool, normalized: fp.normalized },
|
|
48
|
+
redacted: { count: fp.redactedCount, kinds: fp.redactedKinds },
|
|
49
|
+
hits,
|
|
50
|
+
}, null, 2));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (hits.length === 0) {
|
|
54
|
+
console.log('No matching runbooks found.');
|
|
55
|
+
console.log('');
|
|
56
|
+
console.log('If you solve this and want to remember the fix, run:');
|
|
57
|
+
console.log(' mnueron runbook capture');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
console.log(`Found ${hits.length} runbook${hits.length > 1 ? 's' : ''}:`);
|
|
61
|
+
console.log('');
|
|
62
|
+
for (const [i, hit] of hits.entries()) {
|
|
63
|
+
renderHit(hit, i + 1);
|
|
64
|
+
}
|
|
65
|
+
console.log('');
|
|
66
|
+
console.log('After you apply a fix that worked:');
|
|
67
|
+
console.log(' mnueron runbook capture (or update an existing one)');
|
|
68
|
+
}
|
|
69
|
+
function renderHit(hit, index) {
|
|
70
|
+
const tag = hit.confidence === 'high'
|
|
71
|
+
? '★ high'
|
|
72
|
+
: hit.confidence === 'medium'
|
|
73
|
+
? '○ medium'
|
|
74
|
+
: '· low';
|
|
75
|
+
console.log(`${index}. [${tag}] ${hit.name}${hit.verified ? ' ✓ verified' : ''}`);
|
|
76
|
+
console.log(` ${hit.summary || '(no summary)'}`);
|
|
77
|
+
console.log(` reason: ${hit.reason}`);
|
|
78
|
+
if (hit.successCount + hit.failureCount > 0) {
|
|
79
|
+
console.log(` record: ${hit.successCount} success / ${hit.failureCount} failure`);
|
|
80
|
+
}
|
|
81
|
+
if (hit.steps.length > 0) {
|
|
82
|
+
console.log(' steps:');
|
|
83
|
+
for (const [j, step] of hit.steps.entries()) {
|
|
84
|
+
console.log(` ${j + 1}. ${step.step}`);
|
|
85
|
+
if (step.code) {
|
|
86
|
+
const trimmed = step.code.length > 200 ? step.code.slice(0, 197) + '...' : step.code;
|
|
87
|
+
console.log(` > ${trimmed.replace(/\n/g, '\n > ')}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
console.log('');
|
|
92
|
+
}
|
|
93
|
+
function parseArgs(args) {
|
|
94
|
+
const out = { json: false };
|
|
95
|
+
for (let i = 0; i < args.length; i++) {
|
|
96
|
+
const a = args[i];
|
|
97
|
+
if (a === '--file' || a === '-f')
|
|
98
|
+
out.file = args[++i];
|
|
99
|
+
else if (a === '--text' || a === '-t')
|
|
100
|
+
out.text = args[++i];
|
|
101
|
+
else if (a === '--ns' || a === '--namespace')
|
|
102
|
+
out.namespace = args[++i];
|
|
103
|
+
else if (a === '--json')
|
|
104
|
+
out.json = true;
|
|
105
|
+
else if (a === '--help' || a === '-h') {
|
|
106
|
+
printHelp();
|
|
107
|
+
process.exit(0);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
console.error(`Unknown argument: ${a}`);
|
|
111
|
+
printHelp();
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return out;
|
|
116
|
+
}
|
|
117
|
+
function printHelp() {
|
|
118
|
+
console.log(`mnueron explain-error — match a terminal error against known runbooks
|
|
119
|
+
|
|
120
|
+
mnueron explain-error Read error from stdin
|
|
121
|
+
mnueron explain-error --file <path> Read error from a file
|
|
122
|
+
mnueron explain-error --text "<error string>" Pass error inline
|
|
123
|
+
|
|
124
|
+
Options:
|
|
125
|
+
--ns <name> Limit search to a namespace (default: search all)
|
|
126
|
+
--json Machine-readable output
|
|
127
|
+
-h, --help Show this help
|
|
128
|
+
|
|
129
|
+
Examples:
|
|
130
|
+
git push 2>&1 | mnueron explain-error
|
|
131
|
+
mnueron explain-error --file last-build.log
|
|
132
|
+
mnueron explain-error --text "fatal: Unable to create '.git/index.lock'"`);
|
|
133
|
+
}
|
|
134
|
+
async function readErrorInput(opts) {
|
|
135
|
+
if (opts.text)
|
|
136
|
+
return opts.text;
|
|
137
|
+
if (opts.file) {
|
|
138
|
+
return readFile(opts.file, 'utf8');
|
|
139
|
+
}
|
|
140
|
+
// Stdin path
|
|
141
|
+
if (process.stdin.isTTY) {
|
|
142
|
+
console.log('Paste your error, then press Ctrl+D (Ctrl+Z on Windows) when done:');
|
|
143
|
+
}
|
|
144
|
+
return readStdin();
|
|
145
|
+
}
|
|
146
|
+
function readStdin() {
|
|
147
|
+
return new Promise((resolve, reject) => {
|
|
148
|
+
const chunks = [];
|
|
149
|
+
process.stdin.on('data', (c) => chunks.push(c));
|
|
150
|
+
process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
|
|
151
|
+
process.stdin.on('error', reject);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=explain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/runbook/explain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error fingerprinting.
|
|
3
|
+
*
|
|
4
|
+
* A fingerprint is a stable, low-entropy hash designed to:
|
|
5
|
+
* - SURVIVE noise (paths, timestamps, UUIDs, hex IDs change every
|
|
6
|
+
* run; we strip them before hashing)
|
|
7
|
+
* - BREAK on category change (a git error and a typescript error
|
|
8
|
+
* should never share a fingerprint)
|
|
9
|
+
*
|
|
10
|
+
* Algorithm:
|
|
11
|
+
* 1. Redact secrets first (reuses the existing `redact()` helper, so
|
|
12
|
+
* any API tokens or PEM blocks vanish before they touch the hash).
|
|
13
|
+
* 2. Normalize: strip paths, UUIDs, hex digests, timestamps, line:col
|
|
14
|
+
* positions, and collapse whitespace + lowercase.
|
|
15
|
+
* 3. SHA-256 the normalized string, take the first 12 hex chars as
|
|
16
|
+
* the fingerprint. 12 chars = 48 bits of entropy — enough to avoid
|
|
17
|
+
* collisions across a reasonable error vocabulary while staying
|
|
18
|
+
* short for human display.
|
|
19
|
+
* 4. Detect the originating tool from keywords so the UI can hint
|
|
20
|
+
* "this looks like a git problem" before searching.
|
|
21
|
+
*
|
|
22
|
+
* Pure module — no I/O, no DB. Trivially unit-testable.
|
|
23
|
+
*/
|
|
24
|
+
import { createHash } from 'node:crypto';
|
|
25
|
+
import { redact } from '../store/redactor.js';
|
|
26
|
+
/** Build a fingerprint from a raw error string. */
|
|
27
|
+
export function fingerprintError(raw) {
|
|
28
|
+
const redaction = redact(raw);
|
|
29
|
+
const normalized = normalize(redaction.content);
|
|
30
|
+
const hash = createHash('sha256').update(normalized).digest('hex').slice(0, 12);
|
|
31
|
+
return {
|
|
32
|
+
hash,
|
|
33
|
+
normalized,
|
|
34
|
+
tool: detectTool(normalized),
|
|
35
|
+
redactedOriginal: redaction.content,
|
|
36
|
+
redactedCount: redaction.count,
|
|
37
|
+
redactedKinds: redaction.kinds,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Strip variable noise so the same root-cause error normalizes to the
|
|
42
|
+
* same string regardless of where/when it happened.
|
|
43
|
+
*
|
|
44
|
+
* Order matters: do the most specific patterns first (URLs, UUIDs) so
|
|
45
|
+
* less-specific ones (hex IDs, timestamps) don't eat their tokens.
|
|
46
|
+
*/
|
|
47
|
+
export function normalize(s) {
|
|
48
|
+
return (s
|
|
49
|
+
// URLs first — they contain hex/UUID-looking substrings that
|
|
50
|
+
// would otherwise be matched by the generic patterns below.
|
|
51
|
+
.replace(/https?:\/\/[^\s'"<>]+/g, '<URL>')
|
|
52
|
+
// Windows paths: C:\path\to\file or C:/path/to/file
|
|
53
|
+
.replace(/[A-Z]:[\\/][\w\\/.~ \-+@]+(?=[\s'"`)\],]|$)/g, '<PATH>')
|
|
54
|
+
// POSIX absolute paths: /usr/local/..., /Users/me/...
|
|
55
|
+
.replace(/(?<![\w/])\/[\w./~+-]{2,}/g, '<PATH>')
|
|
56
|
+
// UUIDs (8-4-4-4-12)
|
|
57
|
+
.replace(/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi, '<UUID>')
|
|
58
|
+
// Long hex digests (git SHAs, content hashes, MD5, SHA-1, SHA-256)
|
|
59
|
+
.replace(/\b[0-9a-f]{7,}\b/gi, '<HEX>')
|
|
60
|
+
// ISO dates and times — 2026-05-25, 14:32:11, 14:32:11.456
|
|
61
|
+
.replace(/\b\d{4}-\d{2}-\d{2}([Tt ]\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})?)?\b/g, '<DATETIME>')
|
|
62
|
+
.replace(/\b\d{1,2}:\d{2}(:\d{2}(\.\d+)?)?\b/g, '<TIME>')
|
|
63
|
+
// file.ext:line:col patterns
|
|
64
|
+
.replace(/:\d+:\d+/g, ':<L>:<C>')
|
|
65
|
+
// Standalone bare line numbers in stack-trace format "at file:42"
|
|
66
|
+
.replace(/:(\d{2,})\b/g, ':<L>')
|
|
67
|
+
// PIDs and other ad-hoc numerics that vary run-to-run
|
|
68
|
+
.replace(/\bpid[: ]?\d+/gi, 'pid:<N>')
|
|
69
|
+
.replace(/\bport[: ]?\d+/gi, 'port:<N>')
|
|
70
|
+
// Bracketed placeholder noise — strip the surrounding brackets so
|
|
71
|
+
// `[<DATETIME>] fatal: ...` and `fatal: ...` normalize identically.
|
|
72
|
+
// Only matches a placeholder we just produced (uppercase token), so
|
|
73
|
+
// legitimate bracketed content like `error[42]:` survives... almost.
|
|
74
|
+
// We do strip `error[42]:` too because [42] would normalize to <L> first.
|
|
75
|
+
.replace(/\[<[A-Z_]+>\]\s*/g, '')
|
|
76
|
+
// Quoted strings collapsed (paths leak through in quotes sometimes)
|
|
77
|
+
.replace(/'([^']{0,200})'/g, (_, inner) =>
|
|
78
|
+
// Keep short identifiers (likely keywords like 'main'), strip long ones
|
|
79
|
+
inner.length > 30 ? `'<STR>'` : `'${inner}'`)
|
|
80
|
+
// Collapse whitespace
|
|
81
|
+
.replace(/\s+/g, ' ')
|
|
82
|
+
.trim()
|
|
83
|
+
.toLowerCase());
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Best-effort tool detection from the normalized error text.
|
|
87
|
+
*
|
|
88
|
+
* Returns one of: 'git', 'npm', 'pnpm', 'yarn', 'typescript', 'postgres',
|
|
89
|
+
* 'supabase', 'powershell', 'docker', 'kubectl', 'python', 'node', or
|
|
90
|
+
* undefined if we can't tell.
|
|
91
|
+
*
|
|
92
|
+
* Used to:
|
|
93
|
+
* - Filter the search-by-tool branch
|
|
94
|
+
* - Display a friendly hint ("Looks like a git error") in `explain-error`
|
|
95
|
+
* - Stamp `tool` on captured runbooks so future "show me all my
|
|
96
|
+
* git runbooks" works cleanly
|
|
97
|
+
*/
|
|
98
|
+
export function detectTool(normalized) {
|
|
99
|
+
// Order matters — first match wins. Sort by SPECIFICITY of the pattern,
|
|
100
|
+
// not by what tool is most common. PowerShell's "The term '...' is not
|
|
101
|
+
// recognized" / "The token '...' is not a valid statement separator"
|
|
102
|
+
// are essentially impossible to false-match, so they go first — they
|
|
103
|
+
// catch the cases where surrounding text mentions other tools (e.g. a
|
|
104
|
+
// PowerShell error inside a session that was running git commands).
|
|
105
|
+
const sigs = [
|
|
106
|
+
[
|
|
107
|
+
'powershell',
|
|
108
|
+
/the term '[^']+' is not (recognized|valid)|the token '[^']+' is not (a valid|valid)|\bcmdlet\b|\bps[1-9]\b|\binvoke-\w+\b|parsererror|invalidendofline/,
|
|
109
|
+
],
|
|
110
|
+
['supabase', /\bsupabase\b|supabase_migrations/],
|
|
111
|
+
['postgres', /\bpostgres\b|sqlstate\b|\brelation\b.+\b(exists|does not exist)\b|duplicate key value|schema_migrations/],
|
|
112
|
+
['typescript', /\berror ts\d{4}\b|\bcannot find module\b|jsx element|tsconfig/],
|
|
113
|
+
['git', /\bfatal:|\bgit\b|\.git[/\\]|index\.lock|merge conflict|head[\^~]|origin\/main/],
|
|
114
|
+
['npm', /\bnpm err\b|\bnpm error\b|npm warn\b|package-lock\.json/],
|
|
115
|
+
['pnpm', /\bpnpm err\b|pnpm-lock/],
|
|
116
|
+
['yarn', /\byarn error\b|yarn\.lock/],
|
|
117
|
+
['docker', /\bdocker(d|fil)?\b|container\s+\w+|image\s+\w+:\w+|oci runtime/],
|
|
118
|
+
['kubectl', /\bkubectl\b|\bkube-?\w+\b|namespace .* not found|pod\/\w+/],
|
|
119
|
+
['python', /\btraceback\b|pip install|importerror|modulenotfound|python\d/],
|
|
120
|
+
['node', /\bnode:internal\b|cannot find module|err_module|process exited with code/],
|
|
121
|
+
];
|
|
122
|
+
for (const [name, re] of sigs) {
|
|
123
|
+
if (re.test(normalized))
|
|
124
|
+
return name;
|
|
125
|
+
}
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/runbook/fingerprint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runbook search — the matching logic for `mnueron explain-error`.
|
|
3
|
+
*
|
|
4
|
+
* Three-leg parallel search:
|
|
5
|
+
* 1. Exact fingerprint match against the stored error_fingerprints array.
|
|
6
|
+
* A hit means "we've literally solved this exact error before" →
|
|
7
|
+
* confidence: 'high'.
|
|
8
|
+
* 2. Tool match — if the fingerprint detected a tool, find other
|
|
9
|
+
* verified runbooks under that tool. Confidence: 'medium'.
|
|
10
|
+
* 3. Hybrid recall via provider.search() against ANY memory (not just
|
|
11
|
+
* runbooks). May surface a note the user saved that solved the
|
|
12
|
+
* issue without being formalized into a runbook. Confidence: 'low'.
|
|
13
|
+
*
|
|
14
|
+
* Results dedup on runbookId and sort by confidence then verified-ness
|
|
15
|
+
* then recency.
|
|
16
|
+
*/
|
|
17
|
+
import { matchByFingerprint, matchByTool, } from '../store/procedural.js';
|
|
18
|
+
/**
|
|
19
|
+
* Run the three-leg search and return a merged, ranked list of runbook hits.
|
|
20
|
+
*
|
|
21
|
+
* `fingerprint.normalized` is what we send to the hybrid-recall leg so
|
|
22
|
+
* we benefit from the same noise stripping the fingerprint did.
|
|
23
|
+
*/
|
|
24
|
+
export async function searchRunbooks(fingerprint, opts) {
|
|
25
|
+
const perLegLimit = opts.perLegLimit ?? 5;
|
|
26
|
+
// Leg 1: exact fingerprint match
|
|
27
|
+
const fingerprintHits = matchByFingerprint(opts.db, fingerprint.hash, opts.namespace);
|
|
28
|
+
// Leg 2: tool match (only if we detected a tool)
|
|
29
|
+
const toolHits = fingerprint.tool
|
|
30
|
+
? matchByTool(opts.db, fingerprint.tool, opts.namespace, perLegLimit)
|
|
31
|
+
: [];
|
|
32
|
+
// Leg 3: hybrid recall against any memory in the namespace.
|
|
33
|
+
// Note: provider.search returns Memory[] not ExtendedProcedural[], so
|
|
34
|
+
// we'll need to convert. We're using it as a "fuzzy signal" only; for
|
|
35
|
+
// anything it returns we look up the corresponding runbook (if any)
|
|
36
|
+
// by id-prefix match against procedural rows. In v1 of this MVP we
|
|
37
|
+
// simply skip leg 3 if no fingerprint/tool hits — the procedural
|
|
38
|
+
// table is the source of truth. This keeps the implementation tight.
|
|
39
|
+
// TODO Phase 2: implement true fuzzy-recall fallback that surfaces
|
|
40
|
+
// raw memories (not just runbooks).
|
|
41
|
+
// We invoke provider so the import is still useful and we leave a
|
|
42
|
+
// breadcrumb for future work.
|
|
43
|
+
void opts.provider;
|
|
44
|
+
// Merge + dedup
|
|
45
|
+
const seen = new Set();
|
|
46
|
+
const hits = [];
|
|
47
|
+
for (const r of fingerprintHits) {
|
|
48
|
+
if (seen.has(r.id))
|
|
49
|
+
continue;
|
|
50
|
+
seen.add(r.id);
|
|
51
|
+
hits.push(toHit(r, 'high', 'exact fingerprint match'));
|
|
52
|
+
}
|
|
53
|
+
for (const r of toolHits) {
|
|
54
|
+
if (seen.has(r.id))
|
|
55
|
+
continue;
|
|
56
|
+
seen.add(r.id);
|
|
57
|
+
hits.push(toHit(r, r.verified ? 'medium' : 'low', `verified runbook for tool=${fingerprint.tool}`));
|
|
58
|
+
}
|
|
59
|
+
return hits;
|
|
60
|
+
}
|
|
61
|
+
function toHit(r, confidence, reason) {
|
|
62
|
+
return {
|
|
63
|
+
runbookId: r.id,
|
|
64
|
+
name: r.name,
|
|
65
|
+
summary: r.summary,
|
|
66
|
+
steps: r.steps,
|
|
67
|
+
confidence,
|
|
68
|
+
reason,
|
|
69
|
+
successCount: r.success_count,
|
|
70
|
+
failureCount: r.failure_count,
|
|
71
|
+
verified: r.verified,
|
|
72
|
+
os: r.os ?? undefined,
|
|
73
|
+
tool: r.tool ?? undefined,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/runbook/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EACL,kBAAkB,EAClB,WAAW,GAEZ,MAAM,wBAAwB,CAAC;AAehC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAAwB,EACxB,IAAmB;IAEnB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;IAE1C,iCAAiC;IACjC,MAAM,eAAe,GAAG,kBAAkB,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAEtF,iDAAiD;IACjD,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI;QAC/B,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC;QACrE,CAAC,CAAC,EAAE,CAAC;IAEP,4DAA4D;IAC5D,sEAAsE;IACtE,sEAAsE;IACtE,oEAAoE;IACpE,mEAAmE;IACnE,iEAAiE;IACjE,qEAAqE;IACrE,mEAAmE;IACnE,oCAAoC;IACpC,kEAAkE;IAClE,8BAA8B;IAC9B,KAAK,IAAI,CAAC,QAAQ,CAAC;IAEnB,gBAAgB;IAChB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,IAAI,GAAiB,EAAE,CAAC;IAE9B,KAAK,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;QAChC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAAE,SAAS;QAC7B,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAAE,SAAS;QAC7B,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,CACP,KAAK,CACH,CAAC,EACD,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,EAC7B,6BAA6B,WAAW,CAAC,IAAI,EAAE,CAChD,CACF,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,KAAK,CACZ,CAAqB,EACrB,UAAoC,EACpC,MAAc;IAEd,OAAO;QACL,SAAS,EAAE,CAAC,CAAC,EAAE;QACf,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,UAAU;QACV,MAAM;QACN,YAAY,EAAE,CAAC,CAAC,aAAa;QAC7B,YAAY,EAAE,CAAC,CAAC,aAAa;QAC7B,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,SAAS;QACrB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,SAAS;KAC1B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mnueron Terminal Copilot — shared types.
|
|
3
|
+
*
|
|
4
|
+
* The Terminal Copilot recognizes repeated errors, looks them up in
|
|
5
|
+
* procedural memory, suggests prior fixes, and writes/updates runbooks
|
|
6
|
+
* on confirmation. This file holds the cross-module types.
|
|
7
|
+
*
|
|
8
|
+
* Storage strategy:
|
|
9
|
+
* We extend the existing `procedural_memories` table with optional
|
|
10
|
+
* columns (trigger_phrases, error_fingerprints, verified, os, tool,
|
|
11
|
+
* success_count, failure_count) rather than introducing a new table.
|
|
12
|
+
* Older runbooks remain valid — the new columns are nullable.
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/runbook/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
package/dist/setup.js
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* → configure for hosted mode
|
|
11
11
|
* mnueron setup --uninstall → remove from all tools
|
|
12
12
|
*/
|
|
13
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
14
|
+
import { homedir } from 'node:os';
|
|
13
15
|
import { dirname, resolve } from 'node:path';
|
|
14
16
|
import { fileURLToPath } from 'node:url';
|
|
15
17
|
import { allDetectors } from './detectors/index.js';
|
|
@@ -22,6 +24,9 @@ export async function runSetup(opts = {}) {
|
|
|
22
24
|
return runUninstall(detectors, opts);
|
|
23
25
|
const entry = buildEntry(opts);
|
|
24
26
|
const reports = [];
|
|
27
|
+
if (opts.hosted && opts.persistHosted !== false && !opts.dryRun) {
|
|
28
|
+
persistHostedConfig(opts.hosted.url, opts.hosted.token, opts.namespace);
|
|
29
|
+
}
|
|
25
30
|
for (const d of detectors) {
|
|
26
31
|
const status = d.status();
|
|
27
32
|
if (!status.installed) {
|
|
@@ -82,14 +87,37 @@ function buildEntry(opts) {
|
|
|
82
87
|
command: 'node',
|
|
83
88
|
args: [MNUERON_ENTRY],
|
|
84
89
|
};
|
|
90
|
+
const env = {};
|
|
85
91
|
if (opts.hosted) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
MNUERON_API_TOKEN: opts.hosted.token,
|
|
89
|
-
};
|
|
92
|
+
env.MNUERON_API_URL = opts.hosted.url;
|
|
93
|
+
env.MNUERON_API_TOKEN = opts.hosted.token;
|
|
90
94
|
}
|
|
95
|
+
if (opts.namespace)
|
|
96
|
+
env.MNUERON_NAMESPACE = opts.namespace;
|
|
97
|
+
if (Object.keys(env).length > 0)
|
|
98
|
+
entry.env = env;
|
|
91
99
|
return entry;
|
|
92
100
|
}
|
|
101
|
+
function persistHostedConfig(url, token, namespace) {
|
|
102
|
+
const dir = resolve(homedir(), '.mnueron');
|
|
103
|
+
const path = resolve(dir, 'config.json');
|
|
104
|
+
mkdirSync(dir, { recursive: true });
|
|
105
|
+
let existing = {};
|
|
106
|
+
if (existsSync(path)) {
|
|
107
|
+
try {
|
|
108
|
+
const raw = readFileSync(path, 'utf8');
|
|
109
|
+
existing = raw.trim() ? JSON.parse(raw) : {};
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
existing = {};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
existing.apiUrl = url;
|
|
116
|
+
existing.apiToken = token;
|
|
117
|
+
if (namespace)
|
|
118
|
+
existing.defaultNamespace = namespace;
|
|
119
|
+
writeFileSync(path, JSON.stringify(existing, null, 2));
|
|
120
|
+
}
|
|
93
121
|
/** Pretty-print the report for terminal output. */
|
|
94
122
|
export function formatReport(reports) {
|
|
95
123
|
const lines = [];
|
package/dist/setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAChD,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,8BAA8B;
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,14 +25,71 @@ const MAX_CONTENT_CHARS = 12000;
|
|
|
25
25
|
const MAX_ENTITIES = 25;
|
|
26
26
|
const TIMEOUT_MS = 30000;
|
|
27
27
|
export const ENTITY_EXTRACTION_ENABLED = (process.env.MNUERON_ENABLE_ENTITY_EXTRACTION ?? '').toLowerCase() === 'true';
|
|
28
|
+
// Process-wide circuit breaker. When either provider returns 429, we suspend
|
|
29
|
+
// extraction for a cooldown window so a single rate-limit hit doesn't turn
|
|
30
|
+
// into thousands of follow-on warnings (and doesn't keep consuming whatever
|
|
31
|
+
// quota remains in shorter time buckets). Saves continue with no entity tags.
|
|
32
|
+
//
|
|
33
|
+
// Cooldowns by detected scope:
|
|
34
|
+
// - "per day" -> 1 hour (daily quotas reset at the provider's midnight;
|
|
35
|
+
// an hour balances "stop spamming" vs. "retry if user upgrades")
|
|
36
|
+
// - "per minute" -> 60 seconds
|
|
37
|
+
// - "per second" -> 5 seconds
|
|
38
|
+
// - unknown -> 5 minutes
|
|
39
|
+
//
|
|
40
|
+
// One warn-line per disable event keeps the console clean.
|
|
41
|
+
let extractionDisabledUntil = 0;
|
|
42
|
+
let warnedThisCooldown = false;
|
|
43
|
+
function isExtractionRateLimited() {
|
|
44
|
+
if (Date.now() < extractionDisabledUntil)
|
|
45
|
+
return true;
|
|
46
|
+
if (extractionDisabledUntil !== 0 && Date.now() >= extractionDisabledUntil) {
|
|
47
|
+
// Cooldown elapsed -- clear so the next 429 can warn again.
|
|
48
|
+
extractionDisabledUntil = 0;
|
|
49
|
+
warnedThisCooldown = false;
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
function disableExtractionAfter429(provider, body) {
|
|
54
|
+
const lower = body.toLowerCase();
|
|
55
|
+
let durationMs = 5 * 60 * 1000; // default: 5 minutes
|
|
56
|
+
let scope = 'unknown';
|
|
57
|
+
if (lower.includes('per day')) {
|
|
58
|
+
durationMs = 60 * 60 * 1000;
|
|
59
|
+
scope = 'per-day';
|
|
60
|
+
}
|
|
61
|
+
else if (lower.includes('per minute')) {
|
|
62
|
+
durationMs = 60 * 1000;
|
|
63
|
+
scope = 'per-minute';
|
|
64
|
+
}
|
|
65
|
+
else if (lower.includes('per second')) {
|
|
66
|
+
durationMs = 5 * 1000;
|
|
67
|
+
scope = 'per-second';
|
|
68
|
+
}
|
|
69
|
+
extractionDisabledUntil = Math.max(extractionDisabledUntil, Date.now() + durationMs);
|
|
70
|
+
if (!warnedThisCooldown) {
|
|
71
|
+
warnedThisCooldown = true;
|
|
72
|
+
const mins = Math.round(durationMs / 60000);
|
|
73
|
+
console.warn(`[mnueron/entity-extractor] ${provider} returned 429 (${scope}). ` +
|
|
74
|
+
`Suspending entity extraction for ~${mins}m. ` +
|
|
75
|
+
`Saves will continue with no entity tags. ` +
|
|
76
|
+
`Set MNUERON_ENABLE_ENTITY_EXTRACTION=false to opt out permanently.`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
28
79
|
/**
|
|
29
80
|
* Per-call gate. Same shape as hosted-side `shouldExtractEntities`.
|
|
30
81
|
*
|
|
31
82
|
* Explicit per-call opt-in (metadata.extract_entities: true OR BYOK key)
|
|
32
83
|
* always runs, even on short content. The length floor only applies to
|
|
33
84
|
* the env-var default path, to keep that from burning money on noise.
|
|
85
|
+
*
|
|
86
|
+
* Circuit breaker: a recent 429 from either provider disables this gate
|
|
87
|
+
* across the whole process for the cooldown window. Saves still complete
|
|
88
|
+
* normally -- they just skip the LLM call that would have failed anyway.
|
|
34
89
|
*/
|
|
35
90
|
export function shouldExtractEntities(contentLen, metadata, minChars = MIN_LENGTH_CHARS) {
|
|
91
|
+
if (isExtractionRateLimited())
|
|
92
|
+
return false;
|
|
36
93
|
if (metadata?.extract_entities === true)
|
|
37
94
|
return true;
|
|
38
95
|
const a = metadata?.byok_anthropic_key;
|
|
@@ -153,7 +210,12 @@ async function extractViaAnthropic(content, apiKey) {
|
|
|
153
210
|
});
|
|
154
211
|
if (!resp.ok) {
|
|
155
212
|
const body = await resp.text();
|
|
156
|
-
|
|
213
|
+
if (resp.status === 429) {
|
|
214
|
+
disableExtractionAfter429('anthropic', body);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
console.warn('[mnueron/entity-extractor/anthropic] HTTP ' + resp.status + ': ' + body.slice(0, 200));
|
|
218
|
+
}
|
|
157
219
|
return [];
|
|
158
220
|
}
|
|
159
221
|
const data = (await resp.json());
|
|
@@ -195,7 +257,12 @@ async function extractViaOpenAI(content, apiKey) {
|
|
|
195
257
|
});
|
|
196
258
|
if (!resp.ok) {
|
|
197
259
|
const body = await resp.text();
|
|
198
|
-
|
|
260
|
+
if (resp.status === 429) {
|
|
261
|
+
disableExtractionAfter429('openai', body);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
console.warn('[mnueron/entity-extractor/openai] HTTP ' + resp.status + ': ' + body.slice(0, 200));
|
|
265
|
+
}
|
|
199
266
|
return [];
|
|
200
267
|
}
|
|
201
268
|
const data = (await resp.json());
|