total-recall-brain 3.41.4 → 3.41.5
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/bin/total-recall.mjs +3 -2
- package/docs/reference/cli-reference.md +18 -0
- package/frontend/dist/assets/{index-CRzjQLu7.js → index-WT3gs-x6.js} +24 -24
- package/frontend/dist/index.html +1 -1
- package/package.json +2 -2
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +3114 -36
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +3114 -36
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +3121 -33
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package-lock.json +3122 -34
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +3165 -87
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package-lock.json +3121 -33
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/documentation.mjs +32 -12
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +294 -46
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +367 -41
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +2 -2
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +190 -9
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/config.mjs +2 -2
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/generate.mjs +159 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/graph.mjs +197 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/lint.mjs +153 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/mesh-vaults.mjs +261 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh.mjs +151 -4
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/search.mjs +114 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/token.mjs +96 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/card.js +899 -662
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/vendor/openwiki.mjs +8987 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +3087 -71
- package/scaffold/.agent/skills/total-recall/plugins/security/package.json +1 -1
- package/src/cli/compact.mjs +108 -0
- package/src/cli/context.mjs +52 -23
- package/src/cli/forget.mjs +2 -0
- package/src/cli/release.mjs +386 -0
- package/src/core/cli-commands.mjs +2 -0
- package/src/core/context-compactor.mjs +143 -0
- package/src/core/preflight-gate.mjs +2 -2
- package/src/core/preflight-receipt.mjs +1 -1
- package/src/core/surface.mjs +1 -1
- package/src/server/invoke-durability.mjs +39 -0
- package/src/server/invoke-write-child.mjs +25 -0
- package/src/server/routes/invoke.mjs +7 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenWiki Evidence Search & Query Engine.
|
|
3
|
+
*
|
|
4
|
+
* Searches knowledge hubs across local workspace, all registered project vaults,
|
|
5
|
+
* or remote mesh nodes. Extracts evidence passages and linked concepts.
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { discoverAllHubs, execOnMeshNode } from './mesh-vaults.mjs';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Searches for query terms across markdown files.
|
|
13
|
+
*/
|
|
14
|
+
export async function searchWikiHubs(query, {
|
|
15
|
+
allVaults = false,
|
|
16
|
+
node = null,
|
|
17
|
+
limit = 20,
|
|
18
|
+
cwd = process.cwd(),
|
|
19
|
+
} = {}) {
|
|
20
|
+
if (!query || typeof query !== 'string' || !query.trim()) {
|
|
21
|
+
throw new Error('Search query must be a non-empty string');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// If remote mesh node specified, dispatch via mesh
|
|
25
|
+
if (node && node !== 'local' && node !== 'self') {
|
|
26
|
+
const escapedQuery = query.replace(/"/g, '\\"');
|
|
27
|
+
const meshRes = execOnMeshNode(
|
|
28
|
+
node,
|
|
29
|
+
`total-recall openwiki search "${escapedQuery}" ${allVaults ? '--all-vaults' : ''} --json`
|
|
30
|
+
);
|
|
31
|
+
if (meshRes.ok) {
|
|
32
|
+
try {
|
|
33
|
+
return JSON.parse(meshRes.stdout);
|
|
34
|
+
} catch {
|
|
35
|
+
throw new Error(`Invalid JSON from mesh node ${node}: ${meshRes.stdout}`);
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
throw new Error(`Mesh search failed on node ${node}: ${meshRes.stderr || meshRes.error}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const hubsResult = await discoverAllHubs({ allVaults, cwd });
|
|
43
|
+
const rawTerms = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
44
|
+
const terms = rawTerms.map((t) => t.replace(/[^\w-]/g, ''));
|
|
45
|
+
|
|
46
|
+
const matches = [];
|
|
47
|
+
|
|
48
|
+
for (const hub of hubsResult.hubs) {
|
|
49
|
+
let content;
|
|
50
|
+
try {
|
|
51
|
+
content = fs.readFileSync(hub.path, 'utf8');
|
|
52
|
+
} catch {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const lines = content.split('\n');
|
|
57
|
+
let currentHeading = hub.title;
|
|
58
|
+
|
|
59
|
+
for (let i = 0; i < lines.length; i++) {
|
|
60
|
+
const line = lines[i];
|
|
61
|
+
const headingMatch = line.match(/^#{1,6}\s+(.+)$/);
|
|
62
|
+
if (headingMatch) {
|
|
63
|
+
currentHeading = headingMatch[1].trim();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const lowerLine = line.toLowerCase();
|
|
67
|
+
let termHits = 0;
|
|
68
|
+
for (const term of terms) {
|
|
69
|
+
if (lowerLine.includes(term)) termHits++;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (termHits > 0) {
|
|
73
|
+
// Build surrounding snippet (1 line before, matched line, 1 line after)
|
|
74
|
+
const start = Math.max(0, i - 1);
|
|
75
|
+
const end = Math.min(lines.length, i + 2);
|
|
76
|
+
const snippetLines = lines.slice(start, end).map((l) => l.trim()).filter(Boolean);
|
|
77
|
+
const snippet = snippetLines.join(' ');
|
|
78
|
+
|
|
79
|
+
// Score: exact full phrase match bonus, heading bonus, multiple term bonus
|
|
80
|
+
let score = termHits * 10;
|
|
81
|
+
if (lowerLine.includes(query.toLowerCase())) score += 30;
|
|
82
|
+
if (headingMatch) score += 20;
|
|
83
|
+
|
|
84
|
+
matches.push({
|
|
85
|
+
title: hub.title,
|
|
86
|
+
section: currentHeading,
|
|
87
|
+
fileName: hub.fileName,
|
|
88
|
+
repoName: hub.repoName,
|
|
89
|
+
path: hub.path,
|
|
90
|
+
line: i + 1,
|
|
91
|
+
snippet: snippet.length > 280 ? snippet.slice(0, 277) + '...' : snippet,
|
|
92
|
+
score,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Skip forward so overlapping lines don't spam identical snippets
|
|
96
|
+
i += 1;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Sort descending by relevance score
|
|
102
|
+
matches.sort((a, b) => b.score - a.score);
|
|
103
|
+
const truncated = matches.slice(0, limit);
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
ok: true,
|
|
107
|
+
query,
|
|
108
|
+
scope: hubsResult.scope,
|
|
109
|
+
totalHubsScanned: hubsResult.count,
|
|
110
|
+
count: truncated.length,
|
|
111
|
+
totalHits: matches.length,
|
|
112
|
+
results: truncated,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenWiki Token & Secret Management.
|
|
3
|
+
*
|
|
4
|
+
* Implements [invariants-473efe83]:
|
|
5
|
+
* Directly checks and sets credentials in Total Recall auth secrets store.
|
|
6
|
+
* Never echoes raw secrets to stdout/stderr.
|
|
7
|
+
*/
|
|
8
|
+
import { spawnSync } from 'node:child_process';
|
|
9
|
+
|
|
10
|
+
const PROVIDER_KEY_MAP = {
|
|
11
|
+
openrouter: 'OPENROUTER_API_KEY',
|
|
12
|
+
google: 'GOOGLE_API_KEY',
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Checks token readiness across supported providers.
|
|
17
|
+
*/
|
|
18
|
+
export function getTokenStatus() {
|
|
19
|
+
const result = spawnSync('total-recall', ['auth', 'secret', 'list', '--json'], {
|
|
20
|
+
encoding: 'utf8',
|
|
21
|
+
timeout: 5000,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const configured = {
|
|
25
|
+
openrouter: false,
|
|
26
|
+
google: false,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
if (result.status === 0 && result.stdout) {
|
|
30
|
+
try {
|
|
31
|
+
const parsed = JSON.parse(result.stdout);
|
|
32
|
+
const keys = Array.isArray(parsed)
|
|
33
|
+
? parsed.map((k) => (typeof k === 'string' ? k : k.key || k.name))
|
|
34
|
+
: (parsed.keys || []);
|
|
35
|
+
|
|
36
|
+
configured.openrouter = keys.includes('OPENROUTER_API_KEY') || Boolean(process.env.OPENROUTER_API_KEY);
|
|
37
|
+
configured.google = keys.includes('GOOGLE_API_KEY') || Boolean(process.env.GOOGLE_API_KEY);
|
|
38
|
+
} catch {
|
|
39
|
+
configured.openrouter = Boolean(process.env.OPENROUTER_API_KEY);
|
|
40
|
+
configured.google = Boolean(process.env.GOOGLE_API_KEY);
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
configured.openrouter = Boolean(process.env.OPENROUTER_API_KEY);
|
|
44
|
+
configured.google = Boolean(process.env.GOOGLE_API_KEY);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
ok: true,
|
|
49
|
+
tokens: {
|
|
50
|
+
openrouter: {
|
|
51
|
+
key: 'OPENROUTER_API_KEY',
|
|
52
|
+
configured: configured.openrouter,
|
|
53
|
+
status: configured.openrouter ? 'configured' : 'missing',
|
|
54
|
+
},
|
|
55
|
+
google: {
|
|
56
|
+
key: 'GOOGLE_API_KEY',
|
|
57
|
+
configured: configured.google,
|
|
58
|
+
status: configured.google ? 'configured' : 'missing',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Securely writes a token into Total Recall auth secrets store using --stdin.
|
|
66
|
+
*/
|
|
67
|
+
export function setTokenValue(provider, secretValue) {
|
|
68
|
+
const keyName = PROVIDER_KEY_MAP[provider?.toLowerCase()] || provider;
|
|
69
|
+
if (!keyName) {
|
|
70
|
+
throw new Error(`Unsupported token provider '${provider}'. Allowed: openrouter, google`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!secretValue || typeof secretValue !== 'string' || !secretValue.trim()) {
|
|
74
|
+
throw new Error(`Token value for ${keyName} must be a non-empty string`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const trimmed = secretValue.trim();
|
|
78
|
+
|
|
79
|
+
// Pipe into total-recall auth secret set <KEY> --stdin
|
|
80
|
+
const child = spawnSync('total-recall', ['auth', 'secret', 'set', keyName, '--stdin'], {
|
|
81
|
+
input: trimmed,
|
|
82
|
+
encoding: 'utf8',
|
|
83
|
+
timeout: 5000,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (child.status !== 0) {
|
|
87
|
+
throw new Error(child.stderr || child.error?.message || `Failed to set ${keyName} in secrets store`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
ok: true,
|
|
92
|
+
provider,
|
|
93
|
+
key: keyName,
|
|
94
|
+
message: `Secret ${keyName} securely recorded in Total Recall secrets store.`,
|
|
95
|
+
};
|
|
96
|
+
}
|