total-recall-brain 3.41.3 → 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 +12 -2
- package/docs/reference/cli-reference.md +18 -0
- package/frontend/dist/assets/{index-DFenQQEQ.js → index-WT3gs-x6.js} +75 -70
- package/frontend/dist/index.html +1 -1
- package/package.json +7 -5
- package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +2 -2
- package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-secret.mjs +48 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/login-projections.mjs +42 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/mesh-secrets.mjs +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/routes/secrets.mjs +5 -2
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-carriers.mjs +76 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-prune.mjs +37 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-sync.mjs +53 -17
- 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 +3131 -28
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +6 -2
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package-lock.json +3132 -29
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package.json +5 -1
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +3164 -73
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +5 -3
- package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/grants.mjs +7 -3
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/mesh.mjs +61 -38
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/leader-election.mjs +57 -2
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/mesh.mjs +220 -36
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/server/routes/mesh.mjs +7 -2
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/README.md +65 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/BRICK.md +59 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/index.mjs +534 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/cli.mjs +139 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package-lock.json +5937 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package.json +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/plugin.json +376 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/skills/meta-harness/SKILL.md +37 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/adapters/dsh.mjs +446 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/alerts.mjs +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/coordinator.mjs +398 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/documentation.mjs +172 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/executor.mjs +82 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/learner.mjs +90 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/router.mjs +415 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/runtime.mjs +36 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/setup.mjs +35 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/tracker.mjs +133 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worker.mjs +233 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/DESIGN.md +32 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/card.js +845 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/capability/BRICK.md +64 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/capability/index.mjs +250 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +619 -41
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +3134 -31
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +9 -3
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +413 -14
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/config.mjs +129 -0
- 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 +502 -0
- 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/src/upstream-watcher.mjs +375 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/DESIGN.md +35 -22
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/card.js +1225 -364
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/vendor/openwiki.mjs +8987 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +3114 -83
- package/scaffold/.agent/skills/total-recall/plugins/security/package.json +5 -1
- package/src/cli/compact.mjs +108 -0
- package/src/cli/config.mjs +3 -0
- package/src/cli/connect.mjs +12 -116
- package/src/cli/context.mjs +52 -23
- package/src/cli/forget.mjs +2 -0
- package/src/cli/harness.mjs +0 -1
- package/src/cli/plugin/create.mjs +56 -3
- package/src/cli/plugin/index.mjs +15 -3
- package/src/cli/plugin/monetization.mjs +232 -12
- package/src/cli/preflight.mjs +161 -0
- package/src/cli/release.mjs +386 -0
- package/src/core/cli-commands.mjs +4 -0
- package/src/core/context-compactor.mjs +143 -0
- package/src/core/context-compiler.mjs +8 -1
- package/src/core/default-plugins.mjs +1 -1
- package/src/core/meta-harness.mjs +16 -38
- package/src/core/plugin-dependencies.mjs +6 -1
- package/src/core/preflight-gate.mjs +77 -0
- package/src/core/preflight-receipt.mjs +123 -0
- package/src/core/runtime.mjs +0 -3
- package/src/core/surface.mjs +39 -2
- 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
|
@@ -3,12 +3,164 @@
|
|
|
3
3
|
* OpenWiki CLI Handler
|
|
4
4
|
* Executed via: npx total-recall openwiki <subcommand>
|
|
5
5
|
*/
|
|
6
|
-
// Scaffold: report honestly what exists. Add each real subcommand to
|
|
7
|
-
// IMPLEMENTED and to plugin.json "cli.subcommands" as it is built.
|
|
8
|
-
|
|
9
6
|
import fs from "node:fs";
|
|
10
7
|
import path from "node:path";
|
|
11
8
|
import { runBootstrapCommand } from './src/bootstrap.mjs';
|
|
9
|
+
import { describeRetention, hasWiki, isDue, readProjects, refreshProject, refreshProjectAsync, resolveKey, staleness } from './src/refresh.mjs';
|
|
10
|
+
import { announceNewVersion, checkUpstreamStatus, propagateUpdates, readUpstreamState } from './src/upstream-watcher.mjs';
|
|
11
|
+
import { loadOpenWikiConfig, setOpenWikiConfigValue, resetOpenWikiConfig, resolveConfigPath, ALLOWED_CONFIG_KEYS, ALLOWED_PROVIDERS } from './src/config.mjs';
|
|
12
|
+
import { discoverAllHubs } from './src/mesh-vaults.mjs';
|
|
13
|
+
import { searchWikiHubs } from './src/search.mjs';
|
|
14
|
+
import { buildKnowledgeGraph } from './src/graph.mjs';
|
|
15
|
+
import { getTokenStatus, setTokenValue } from './src/token.mjs';
|
|
16
|
+
import { lintWikiHubs } from './src/lint.mjs';
|
|
17
|
+
import { generateWiki } from './src/generate.mjs';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Regenerate the generated pages of every registered project that carries them.
|
|
21
|
+
*
|
|
22
|
+
* Fleet-wide by design: the plugin ships from the shared brain, so one
|
|
23
|
+
* implementation covers every repository and every node that resolves it.
|
|
24
|
+
* Defaults to a report; --apply performs the refreshes, because regenerating a
|
|
25
|
+
* repository's documentation is a write to that repository.
|
|
26
|
+
*/
|
|
27
|
+
async function refreshCommand(args) {
|
|
28
|
+
const json = args.includes('--json');
|
|
29
|
+
const apply = args.includes('--apply');
|
|
30
|
+
const force = args.includes('--force');
|
|
31
|
+
const repoIndex = args.indexOf('--repo');
|
|
32
|
+
const onlyArg = args.find((a) => a.startsWith('--repo='));
|
|
33
|
+
const only = onlyArg
|
|
34
|
+
? onlyArg.slice('--repo='.length)
|
|
35
|
+
: (repoIndex >= 0 && args[repoIndex + 1] && !args[repoIndex + 1].startsWith('--') ? args[repoIndex + 1] : null);
|
|
36
|
+
|
|
37
|
+
let projects;
|
|
38
|
+
try {
|
|
39
|
+
projects = readProjects();
|
|
40
|
+
} catch (err) {
|
|
41
|
+
if (json) console.log(JSON.stringify({ ok: false, error: err.message }));
|
|
42
|
+
else console.error(`OpenWiki refresh: ${err.message}`);
|
|
43
|
+
process.exitCode = 2;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (only) projects = projects.filter((p) => p.name === only || p.root === only);
|
|
47
|
+
if (!projects.length) {
|
|
48
|
+
if (json) console.log(JSON.stringify({ ok: false, error: only ? `No registered project matches ${only}` : 'No registered projects' }));
|
|
49
|
+
else console.error(`OpenWiki refresh: ${only ? `no registered project matches ${only}` : 'no registered projects'}`);
|
|
50
|
+
process.exitCode = 2;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const reports = [];
|
|
55
|
+
for (const project of projects) {
|
|
56
|
+
let state;
|
|
57
|
+
try {
|
|
58
|
+
state = force ? { due: true, ...staleness(project.root) } : isDue(project);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
reports.push({ ...project, action: 'skipped', reason: err.message });
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (!state.due) {
|
|
64
|
+
if (state.skipped) {
|
|
65
|
+
reports.push({ ...project, action: 'skipped', reason: state.reason });
|
|
66
|
+
} else {
|
|
67
|
+
reports.push({ ...project, action: 'current', generatedAt: state.generatedAt, commitsSince: state.commitsSince });
|
|
68
|
+
}
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
reports.push({
|
|
72
|
+
...project,
|
|
73
|
+
action: 'due',
|
|
74
|
+
uninitialized: Boolean(state.uninitialized),
|
|
75
|
+
generatedAt: state.generatedAt,
|
|
76
|
+
commitsSince: state.commitsSince,
|
|
77
|
+
reason: state.reason
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const due = reports.filter((r) => r.action === 'due');
|
|
82
|
+
let payloadBudgetNote = null;
|
|
83
|
+
if (apply && due.length) {
|
|
84
|
+
const config = loadOpenWikiConfig();
|
|
85
|
+
const { key, from } = resolveKey({ provider: config.provider });
|
|
86
|
+
if (!key) {
|
|
87
|
+
const keyName = config.provider === 'google' ? 'GOOGLE_API_KEY' : 'OPENROUTER_API_KEY';
|
|
88
|
+
const error = `No model credential for provider '${config.provider}'. Save via: total-recall auth secret set ${keyName} --stdin`;
|
|
89
|
+
if (json) console.log(JSON.stringify({ ok: false, error, reports }));
|
|
90
|
+
else console.error(`OpenWiki refresh: ${error}`);
|
|
91
|
+
process.exitCode = 1;
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const concurrencyArg = args.find((a) => a.startsWith('--concurrency='));
|
|
95
|
+
const concurrencyIndex = args.indexOf('--concurrency');
|
|
96
|
+
const concurrency = Math.max(1, parseInt(
|
|
97
|
+
concurrencyArg ? concurrencyArg.slice('--concurrency='.length) : (concurrencyIndex >= 0 ? args[concurrencyIndex + 1] : '8'),
|
|
98
|
+
10
|
|
99
|
+
) || 8);
|
|
100
|
+
|
|
101
|
+
if (!json) {
|
|
102
|
+
console.log(`OpenWiki refresh (apply): dispatching ${due.length} projects with concurrency ${concurrency}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let queueIndex = 0;
|
|
106
|
+
let completedCount = 0;
|
|
107
|
+
const worker = async () => {
|
|
108
|
+
while (queueIndex < due.length) {
|
|
109
|
+
const itemIndex = queueIndex++;
|
|
110
|
+
const entry = due[itemIndex];
|
|
111
|
+
const mode = entry.uninitialized ? 'init' : 'update';
|
|
112
|
+
if (!json) {
|
|
113
|
+
console.log(`[${itemIndex + 1}/${due.length}] ▶ ${entry.name.padEnd(28)} starting ${mode}...`);
|
|
114
|
+
}
|
|
115
|
+
const result = await refreshProjectAsync(
|
|
116
|
+
{ name: entry.name, root: entry.root },
|
|
117
|
+
{ key, model: config.model, provider: config.provider, timeoutMs: config.timeout_ms }
|
|
118
|
+
);
|
|
119
|
+
completedCount++;
|
|
120
|
+
const index = reports.findIndex((r) => r.root === entry.root);
|
|
121
|
+
reports[index] = { ...reports[index], ...result, credential: from };
|
|
122
|
+
if (!json) {
|
|
123
|
+
const duration = Math.round((Date.now() - (result.startedAt || Date.now())) / 1000);
|
|
124
|
+
const icon = result.action === 'failed' ? '✖' : '✔';
|
|
125
|
+
console.log(`[${completedCount}/${due.length}] ${icon} ${entry.name.padEnd(28)} ${result.action} (${duration}s)${result.reason ? ` — ${result.reason}` : ''}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const workers = Array.from({ length: Math.min(concurrency, due.length) }, () => worker());
|
|
131
|
+
await Promise.all(workers);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const failed = reports.filter((r) => r.action === 'failed');
|
|
135
|
+
const payload = {
|
|
136
|
+
ok: failed.length === 0,
|
|
137
|
+
applied: apply,
|
|
138
|
+
retention: describeRetention(),
|
|
139
|
+
note: payloadBudgetNote,
|
|
140
|
+
counts: {
|
|
141
|
+
registered: projects.length,
|
|
142
|
+
withPages: reports.filter((r) => r.action !== 'skipped' && !r.uninitialized).length,
|
|
143
|
+
due: due.length,
|
|
144
|
+
uninitialized: reports.filter((r) => r.uninitialized).length,
|
|
145
|
+
refreshed: reports.filter((r) => r.action === 'refreshed' || r.action === 'initialized').length,
|
|
146
|
+
failed: failed.length,
|
|
147
|
+
current: reports.filter((r) => r.action === 'current').length,
|
|
148
|
+
},
|
|
149
|
+
reports,
|
|
150
|
+
};
|
|
151
|
+
if (json) console.log(JSON.stringify(payload, null, 2));
|
|
152
|
+
else {
|
|
153
|
+
console.log(`OpenWiki refresh (${apply ? 'apply' : 'report'}): ${payload.counts.registered} registered, ${payload.counts.due} due (${payload.counts.uninitialized} uninitialized)`);
|
|
154
|
+
for (const r of reports) {
|
|
155
|
+
if (r.action === 'current') continue;
|
|
156
|
+
const age = r.uninitialized ? 'uninitialized' : (r.generatedAt ? `generated ${r.generatedAt.slice(0, 10)}` : 'never generated');
|
|
157
|
+
console.log(` ${r.action.padEnd(9)} ${r.name.padEnd(28)} ${age}${Number.isFinite(r.commitsSince) && r.commitsSince !== Infinity ? `, ${r.commitsSince} commits since` : ''}${r.reason ? ` — ${r.reason}` : ''}`);
|
|
158
|
+
}
|
|
159
|
+
if (payloadBudgetNote) console.log(payloadBudgetNote);
|
|
160
|
+
if (!apply && due.length) console.log('Re-run with --apply to regenerate. Pages are a projection; vault content is never touched.');
|
|
161
|
+
}
|
|
162
|
+
if (failed.length) process.exitCode = 1;
|
|
163
|
+
}
|
|
12
164
|
|
|
13
165
|
async function probeCommand(args) {
|
|
14
166
|
const json = args.includes("--json");
|
|
@@ -34,39 +186,241 @@ async function probeCommand(args) {
|
|
|
34
186
|
|
|
35
187
|
async function hubsCommand(args) {
|
|
36
188
|
const json = args.includes("--json");
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
189
|
+
const allVaults = args.includes("--all-vaults") || args.includes("--all");
|
|
190
|
+
const nodeArg = args.find((a) => a.startsWith('--node='));
|
|
191
|
+
const nodeIndex = args.indexOf('--node');
|
|
192
|
+
const node = nodeArg
|
|
193
|
+
? nodeArg.slice('--node='.length)
|
|
194
|
+
: (nodeIndex >= 0 && args[nodeIndex + 1] && !args[nodeIndex + 1].startsWith('--') ? args[nodeIndex + 1] : null);
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
const res = await discoverAllHubs({ allVaults, node });
|
|
198
|
+
if (json) {
|
|
199
|
+
console.log(JSON.stringify(res, null, 2));
|
|
200
|
+
} else {
|
|
201
|
+
if (!res.hubs || res.hubs.length === 0) {
|
|
202
|
+
console.log(`No markdown hubs found (${res.scope || 'workspace'})`);
|
|
203
|
+
} else {
|
|
204
|
+
const prefix = res.isRemote ? `[Node ${res.node}] ` : '';
|
|
205
|
+
console.log(`${prefix}Discovered ${res.hubs.length} OpenWiki Hub(s) (${res.scope || 'workspace'}):`);
|
|
206
|
+
for (const h of res.hubs) {
|
|
207
|
+
const repoTag = h.repoName ? `[${h.repoName}] ` : '';
|
|
208
|
+
console.log(` - ${repoTag}${h.title}: ${h.path} (${h.lines} lines, ${h.size_bytes} bytes)`);
|
|
209
|
+
}
|
|
55
210
|
}
|
|
56
211
|
}
|
|
212
|
+
} catch (err) {
|
|
213
|
+
if (json) console.log(JSON.stringify({ ok: false, error: err.message }));
|
|
214
|
+
else console.error(`OpenWiki hubs error: ${err.message}`);
|
|
215
|
+
process.exitCode = 1;
|
|
57
216
|
}
|
|
217
|
+
}
|
|
58
218
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
219
|
+
async function searchCommand(args) {
|
|
220
|
+
const json = args.includes("--json");
|
|
221
|
+
const allVaults = args.includes("--all-vaults") || args.includes("--all");
|
|
222
|
+
const nodeArg = args.find((a) => a.startsWith('--node='));
|
|
223
|
+
const nodeIndex = args.indexOf('--node');
|
|
224
|
+
const node = nodeArg
|
|
225
|
+
? nodeArg.slice('--node='.length)
|
|
226
|
+
: (nodeIndex >= 0 && args[nodeIndex + 1] && !args[nodeIndex + 1].startsWith('--') ? args[nodeIndex + 1] : null);
|
|
227
|
+
|
|
228
|
+
const limitArg = args.find((a) => a.startsWith('--limit='));
|
|
229
|
+
const limitIndex = args.indexOf('--limit');
|
|
230
|
+
const limit = limitArg
|
|
231
|
+
? parseInt(limitArg.slice('--limit='.length), 10)
|
|
232
|
+
: (limitIndex >= 0 && args[limitIndex + 1] ? parseInt(args[limitIndex + 1], 10) : 20);
|
|
233
|
+
|
|
234
|
+
const queryTerms = args.filter((a, idx) => {
|
|
235
|
+
if (a.startsWith('--')) return false;
|
|
236
|
+
if (nodeIndex >= 0 && idx === nodeIndex + 1) return false;
|
|
237
|
+
if (limitIndex >= 0 && idx === limitIndex + 1) return false;
|
|
238
|
+
return true;
|
|
239
|
+
});
|
|
240
|
+
const query = queryTerms.join(' ').trim();
|
|
241
|
+
|
|
242
|
+
if (!query) {
|
|
243
|
+
if (json) console.log(JSON.stringify({ ok: false, error: 'Query argument required: openwiki search <query>' }));
|
|
244
|
+
else console.error('OpenWiki search error: query required. Usage: total-recall openwiki search <query> [--all-vaults] [--node <node>]');
|
|
245
|
+
process.exitCode = 1;
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
try {
|
|
250
|
+
const res = await searchWikiHubs(query, { allVaults, node, limit });
|
|
251
|
+
if (json) {
|
|
252
|
+
console.log(JSON.stringify(res, null, 2));
|
|
253
|
+
} else {
|
|
254
|
+
console.log(`\nOpenWiki Evidence Search: "${query}" (${res.count} match${res.count === 1 ? '' : 'es'} across ${res.totalHubsScanned} hubs, ${res.scope})`);
|
|
255
|
+
if (res.results.length === 0) {
|
|
256
|
+
console.log(' No matching evidence passages found.\n');
|
|
257
|
+
} else {
|
|
258
|
+
for (const r of res.results) {
|
|
259
|
+
console.log(`\n • [${r.repoName}] ${r.title} > ${r.section} (line ${r.line}):`);
|
|
260
|
+
console.log(` "${r.snippet}"`);
|
|
261
|
+
}
|
|
262
|
+
console.log('');
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
} catch (err) {
|
|
266
|
+
if (json) console.log(JSON.stringify({ ok: false, error: err.message }));
|
|
267
|
+
else console.error(`OpenWiki search error: ${err.message}`);
|
|
268
|
+
process.exitCode = 1;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
async function graphCommand(args) {
|
|
273
|
+
const json = args.includes("--json");
|
|
274
|
+
const allVaults = args.includes("--all-vaults") || args.includes("--all");
|
|
275
|
+
const nodeArg = args.find((a) => a.startsWith('--node='));
|
|
276
|
+
const nodeIndex = args.indexOf('--node');
|
|
277
|
+
const node = nodeArg
|
|
278
|
+
? nodeArg.slice('--node='.length)
|
|
279
|
+
: (nodeIndex >= 0 && args[nodeIndex + 1] && !args[nodeIndex + 1].startsWith('--') ? args[nodeIndex + 1] : null);
|
|
280
|
+
|
|
281
|
+
const formatArg = args.find((a) => a.startsWith('--format='));
|
|
282
|
+
const formatIndex = args.indexOf('--format');
|
|
283
|
+
const format = formatArg
|
|
284
|
+
? formatArg.slice('--format='.length)
|
|
285
|
+
: (formatIndex >= 0 && args[formatIndex + 1] ? args[formatIndex + 1] : (args.includes('--mermaid') ? 'mermaid' : (args.includes('--dot') ? 'dot' : 'json')));
|
|
286
|
+
|
|
287
|
+
try {
|
|
288
|
+
const res = await buildKnowledgeGraph({ allVaults, node, format });
|
|
289
|
+
if (json || format === 'json') {
|
|
290
|
+
console.log(JSON.stringify(res, null, 2));
|
|
291
|
+
} else if (format === 'mermaid') {
|
|
292
|
+
console.log(res.mermaid);
|
|
293
|
+
} else if (format === 'dot') {
|
|
294
|
+
console.log(res.dot);
|
|
295
|
+
}
|
|
296
|
+
} catch (err) {
|
|
297
|
+
if (json) console.log(JSON.stringify({ ok: false, error: err.message }));
|
|
298
|
+
else console.error(`OpenWiki graph error: ${err.message}`);
|
|
299
|
+
process.exitCode = 1;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async function tokenCommand(args) {
|
|
304
|
+
const json = args.includes("--json");
|
|
305
|
+
const verb = args.find((a) => !a.startsWith('--')) || 'status';
|
|
306
|
+
|
|
307
|
+
try {
|
|
308
|
+
if (verb === 'status') {
|
|
309
|
+
const res = getTokenStatus();
|
|
310
|
+
if (json) {
|
|
311
|
+
console.log(JSON.stringify(res, null, 2));
|
|
312
|
+
} else {
|
|
313
|
+
console.log('\nOpenWiki Token Status (Total Recall Auth Store):');
|
|
314
|
+
for (const [provider, t] of Object.entries(res.tokens)) {
|
|
315
|
+
const icon = t.configured ? '✔' : '✖';
|
|
316
|
+
console.log(` ${icon} ${provider.padEnd(12)} : ${t.key} (${t.status})`);
|
|
317
|
+
}
|
|
318
|
+
console.log('\nTo set a token: total-recall openwiki token set <openrouter|google> <key>');
|
|
319
|
+
console.log('Or via stdin: echo "$KEY" | total-recall openwiki token set <provider> --stdin\n');
|
|
320
|
+
}
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (verb === 'set') {
|
|
325
|
+
const clean = args.filter((a) => !a.startsWith('--'));
|
|
326
|
+
const provider = clean[1];
|
|
327
|
+
let value = clean[2];
|
|
328
|
+
if (args.includes('--stdin')) {
|
|
329
|
+
value = fs.readFileSync(0, 'utf8').trim();
|
|
330
|
+
}
|
|
331
|
+
if (!provider || !value) {
|
|
332
|
+
throw new Error('Provider and secret value required: openwiki token set <provider> <value> (or --stdin)');
|
|
333
|
+
}
|
|
334
|
+
const res = setTokenValue(provider, value);
|
|
335
|
+
if (json) console.log(JSON.stringify(res, null, 2));
|
|
336
|
+
else console.log(`✔ ${res.message}`);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
throw new Error(`Unknown token action '${verb}'. Supported: status, set`);
|
|
341
|
+
} catch (err) {
|
|
342
|
+
if (json) console.log(JSON.stringify({ ok: false, error: err.message }));
|
|
343
|
+
else console.error(`OpenWiki token error: ${err.message}`);
|
|
344
|
+
process.exitCode = 1;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
async function lintCommand(args) {
|
|
349
|
+
const json = args.includes("--json");
|
|
350
|
+
const allVaults = args.includes("--all-vaults") || args.includes("--all");
|
|
351
|
+
const nodeArg = args.find((a) => a.startsWith('--node='));
|
|
352
|
+
const nodeIndex = args.indexOf('--node');
|
|
353
|
+
const node = nodeArg
|
|
354
|
+
? nodeArg.slice('--node='.length)
|
|
355
|
+
: (nodeIndex >= 0 && args[nodeIndex + 1] && !args[nodeIndex + 1].startsWith('--') ? args[nodeIndex + 1] : null);
|
|
356
|
+
|
|
357
|
+
try {
|
|
358
|
+
const res = await lintWikiHubs({ allVaults, node });
|
|
359
|
+
if (json) {
|
|
360
|
+
console.log(JSON.stringify(res, null, 2));
|
|
64
361
|
} else {
|
|
65
|
-
console.log(
|
|
66
|
-
|
|
67
|
-
|
|
362
|
+
console.log(`\nOpenWiki Documentation Health & Hygiene:`);
|
|
363
|
+
console.log(` Health Score : ${res.healthScore}%`);
|
|
364
|
+
console.log(` Total Hubs Scanned : ${res.totalHubs}`);
|
|
365
|
+
console.log(` Total Links Tested : ${res.totalLinks}`);
|
|
366
|
+
console.log(` Broken Links : ${res.brokenLinksCount}`);
|
|
367
|
+
console.log(` Orphaned Hubs : ${res.orphanCount}`);
|
|
368
|
+
|
|
369
|
+
if (res.issues.length > 0) {
|
|
370
|
+
console.log('\nIssues Found:');
|
|
371
|
+
for (const iss of res.issues) {
|
|
372
|
+
console.log(` ✖ [${iss.type}] in ${path.basename(iss.file)}: ${iss.message}`);
|
|
373
|
+
}
|
|
374
|
+
} else {
|
|
375
|
+
console.log('\n✔ All wiki links and headers verified clean!');
|
|
68
376
|
}
|
|
377
|
+
console.log('');
|
|
378
|
+
}
|
|
379
|
+
if (!res.ok) process.exitCode = 1;
|
|
380
|
+
} catch (err) {
|
|
381
|
+
if (json) console.log(JSON.stringify({ ok: false, error: err.message }));
|
|
382
|
+
else console.error(`OpenWiki lint error: ${err.message}`);
|
|
383
|
+
process.exitCode = 1;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
async function generateCommand(args) {
|
|
388
|
+
const json = args.includes("--json");
|
|
389
|
+
const force = args.includes("--force");
|
|
390
|
+
const dryRun = args.includes("--dry-run");
|
|
391
|
+
const repoIndex = args.indexOf('--repo');
|
|
392
|
+
const repoArg = args.find((a) => a.startsWith('--repo='));
|
|
393
|
+
const repo = repoArg
|
|
394
|
+
? repoArg.slice('--repo='.length)
|
|
395
|
+
: (repoIndex >= 0 && args[repoIndex + 1] && !args[repoIndex + 1].startsWith('--') ? args[repoIndex + 1] : null);
|
|
396
|
+
|
|
397
|
+
const nodeArg = args.find((a) => a.startsWith('--node='));
|
|
398
|
+
const nodeIndex = args.indexOf('--node');
|
|
399
|
+
const node = nodeArg
|
|
400
|
+
? nodeArg.slice('--node='.length)
|
|
401
|
+
: (nodeIndex >= 0 && args[nodeIndex + 1] && !args[nodeIndex + 1].startsWith('--') ? args[nodeIndex + 1] : null);
|
|
402
|
+
|
|
403
|
+
try {
|
|
404
|
+
const res = await generateWiki({
|
|
405
|
+
repo,
|
|
406
|
+
force,
|
|
407
|
+
dryRun,
|
|
408
|
+
node,
|
|
409
|
+
onProgress: (msg) => {
|
|
410
|
+
if (!json) console.log(` ▶ ${msg}`);
|
|
411
|
+
},
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
if (json) {
|
|
415
|
+
console.log(JSON.stringify(res, null, 2));
|
|
416
|
+
} else {
|
|
417
|
+
console.log(`\n✔ Generated documentation for ${res.repoName} (${Math.round((res.durationMs || 0)/1000)}s) via ${res.generatorVia}`);
|
|
418
|
+
console.log(` Output: ${res.outputDir}\n`);
|
|
69
419
|
}
|
|
420
|
+
} catch (err) {
|
|
421
|
+
if (json) console.log(JSON.stringify({ ok: false, error: err.message }));
|
|
422
|
+
else console.error(`OpenWiki generate error: ${err.message}`);
|
|
423
|
+
process.exitCode = 1;
|
|
70
424
|
}
|
|
71
425
|
}
|
|
72
426
|
|
|
@@ -79,24 +433,223 @@ async function ingestCommand(args) {
|
|
|
79
433
|
}
|
|
80
434
|
}
|
|
81
435
|
|
|
436
|
+
/**
|
|
437
|
+
* Surveillance command for monitoring the upstream open-source OpenWiki package.
|
|
438
|
+
*/
|
|
439
|
+
async function watchCommand(args) {
|
|
440
|
+
const json = args.includes('--json');
|
|
441
|
+
const checkOnly = args.includes('--check-only');
|
|
442
|
+
const announce = args.includes('--announce') || (!checkOnly && !args.includes('--no-announce'));
|
|
443
|
+
const propagate = args.includes('--propagate');
|
|
444
|
+
|
|
445
|
+
const status = await checkUpstreamStatus();
|
|
446
|
+
let announcement = null;
|
|
447
|
+
let propagation = null;
|
|
448
|
+
|
|
449
|
+
if (status.ok && status.updateAvailable) {
|
|
450
|
+
if (announce) {
|
|
451
|
+
announcement = await announceNewVersion({
|
|
452
|
+
latestVersion: status.latestVersion,
|
|
453
|
+
currentVersion: status.currentVersion,
|
|
454
|
+
releaseNotesUrl: status.releaseNotesUrl
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
if (propagate) {
|
|
458
|
+
propagation = await propagateUpdates({ force: true });
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const payload = {
|
|
463
|
+
ok: status.ok,
|
|
464
|
+
status,
|
|
465
|
+
announcement,
|
|
466
|
+
propagation
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
if (json) {
|
|
470
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
471
|
+
} else {
|
|
472
|
+
console.log('\nOpenWiki Upstream Watcher:');
|
|
473
|
+
console.log(` Active Recorded Version : v${status.currentVersion}`);
|
|
474
|
+
console.log(` Latest Upstream Version : v${status.latestVersion}`);
|
|
475
|
+
console.log(` Update Available : ${status.updateAvailable ? 'YES (Increment Detected)' : 'No (Current)'}`);
|
|
476
|
+
if (status.releaseNotesUrl) {
|
|
477
|
+
console.log(` Release Notes : ${status.releaseNotesUrl}`);
|
|
478
|
+
}
|
|
479
|
+
if (announcement?.announced) {
|
|
480
|
+
console.log(` Operator Announcement : Dispatched successfully`);
|
|
481
|
+
}
|
|
482
|
+
if (propagation) {
|
|
483
|
+
console.log(` Fleet Propagation : ${propagation.ok ? 'Completed' : 'Failed'} (${propagation.updatedCount} projects updated)`);
|
|
484
|
+
}
|
|
485
|
+
console.log('');
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
if (!status.ok) process.exitCode = 1;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Propagate updated generator across registered repositories.
|
|
493
|
+
*/
|
|
494
|
+
async function propagateCommand(args) {
|
|
495
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
496
|
+
console.log(`
|
|
497
|
+
Usage:
|
|
498
|
+
total-recall openwiki propagate [options]
|
|
499
|
+
|
|
500
|
+
Options:
|
|
501
|
+
--repo <name> Limit propagation to a specific repository
|
|
502
|
+
--force Force regeneration even if not due
|
|
503
|
+
--dry-run Preview propagation actions without writing
|
|
504
|
+
--json Output result as JSON
|
|
505
|
+
--help, -h Show this help
|
|
506
|
+
`);
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
const json = args.includes('--json');
|
|
510
|
+
const force = args.includes('--force');
|
|
511
|
+
const dryRun = args.includes('--dry-run');
|
|
512
|
+
const repoIndex = args.indexOf('--repo');
|
|
513
|
+
const onlyArg = args.find((a) => a.startsWith('--repo='));
|
|
514
|
+
const repo = onlyArg
|
|
515
|
+
? onlyArg.slice('--repo='.length)
|
|
516
|
+
: (repoIndex >= 0 && args[repoIndex + 1] && !args[repoIndex + 1].startsWith('--') ? args[repoIndex + 1] : null);
|
|
517
|
+
|
|
518
|
+
const result = await propagateUpdates({ repo, force, dryRun });
|
|
519
|
+
|
|
520
|
+
if (json) {
|
|
521
|
+
console.log(JSON.stringify(result, null, 2));
|
|
522
|
+
} else {
|
|
523
|
+
console.log(`\nOpenWiki Fleet Propagation (${dryRun ? 'DRY RUN' : 'APPLY'}):`);
|
|
524
|
+
console.log(` Eligible Repositories : ${result.eligibleCount || 0}`);
|
|
525
|
+
console.log(` Updated Repositories : ${result.updatedCount || 0}`);
|
|
526
|
+
console.log(` Failed Repositories : ${result.failedCount || 0}`);
|
|
527
|
+
if (Array.isArray(result.reports)) {
|
|
528
|
+
for (const r of result.reports) {
|
|
529
|
+
console.log(` • ${r.name}: ${r.action}${r.reason ? ` — ${r.reason}` : ''}`);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
console.log('');
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if (!result.ok) process.exitCode = 1;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Configure OpenWiki generation parameters and cheap model routing.
|
|
540
|
+
*/
|
|
541
|
+
async function configCommand(args) {
|
|
542
|
+
const json = args.includes('--json');
|
|
543
|
+
const cleanArgs = args.filter((a) => a !== '--json');
|
|
544
|
+
const verb = cleanArgs[0] || 'show';
|
|
545
|
+
|
|
546
|
+
try {
|
|
547
|
+
if (verb === 'show') {
|
|
548
|
+
const config = loadOpenWikiConfig();
|
|
549
|
+
const configPath = resolveConfigPath();
|
|
550
|
+
const payload = { ok: true, path: configPath, config };
|
|
551
|
+
if (json) console.log(JSON.stringify(payload, null, 2));
|
|
552
|
+
else {
|
|
553
|
+
console.log(`\nOpenWiki Configuration (${configPath}):`);
|
|
554
|
+
console.log(` Provider : ${config.provider}`);
|
|
555
|
+
console.log(` Model : ${config.model}`);
|
|
556
|
+
console.log(` Fallback Model : ${config.fallback_model}`);
|
|
557
|
+
console.log(` Max Tokens : ${config.max_tokens}`);
|
|
558
|
+
console.log(` Timeout (ms) : ${config.timeout_ms}\n`);
|
|
559
|
+
}
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
if (verb === 'get') {
|
|
564
|
+
const key = cleanArgs[1];
|
|
565
|
+
if (!key) {
|
|
566
|
+
throw new Error('Key argument required: openwiki config get <key>');
|
|
567
|
+
}
|
|
568
|
+
if (!ALLOWED_CONFIG_KEYS.includes(key)) {
|
|
569
|
+
throw new Error(`Unknown configuration key '${key}'. Allowed: ${ALLOWED_CONFIG_KEYS.join(', ')}`);
|
|
570
|
+
}
|
|
571
|
+
const config = loadOpenWikiConfig();
|
|
572
|
+
const value = config[key];
|
|
573
|
+
if (json) console.log(JSON.stringify({ ok: true, key, value }));
|
|
574
|
+
else console.log(value);
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
if (verb === 'set') {
|
|
579
|
+
const key = cleanArgs[1];
|
|
580
|
+
const value = cleanArgs[2];
|
|
581
|
+
if (!key || value === undefined) {
|
|
582
|
+
throw new Error('Key and value required: openwiki config set <key> <value>');
|
|
583
|
+
}
|
|
584
|
+
const updated = setOpenWikiConfigValue(key, value);
|
|
585
|
+
const payload = { ok: true, key, value: updated[key], config: updated };
|
|
586
|
+
if (json) console.log(JSON.stringify(payload, null, 2));
|
|
587
|
+
else console.log(`OpenWiki configuration updated: ${key} = ${updated[key]}`);
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
if (verb === 'reset') {
|
|
592
|
+
const reset = resetOpenWikiConfig();
|
|
593
|
+
const payload = { ok: true, message: 'Configuration reset to defaults', config: reset };
|
|
594
|
+
if (json) console.log(JSON.stringify(payload, null, 2));
|
|
595
|
+
else console.log('OpenWiki configuration reset to defaults');
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
throw new Error(`Unknown config action '${verb}'. Supported verbs: show, get, set, reset`);
|
|
600
|
+
} catch (err) {
|
|
601
|
+
if (json) console.log(JSON.stringify({ ok: false, error: err.message }));
|
|
602
|
+
else console.error(`OpenWiki config error: ${err.message}`);
|
|
603
|
+
process.exitCode = 1;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
82
607
|
const IMPLEMENTED = {};
|
|
83
608
|
IMPLEMENTED.probe = probeCommand;
|
|
84
609
|
IMPLEMENTED.hubs = hubsCommand;
|
|
85
610
|
IMPLEMENTED.ingest = ingestCommand;
|
|
86
611
|
IMPLEMENTED.bootstrap = runBootstrapCommand;
|
|
612
|
+
IMPLEMENTED.refresh = refreshCommand;
|
|
613
|
+
IMPLEMENTED.watch = watchCommand;
|
|
614
|
+
IMPLEMENTED.propagate = propagateCommand;
|
|
615
|
+
IMPLEMENTED.config = configCommand;
|
|
616
|
+
IMPLEMENTED.search = searchCommand;
|
|
617
|
+
IMPLEMENTED.graph = graphCommand;
|
|
618
|
+
IMPLEMENTED.token = tokenCommand;
|
|
619
|
+
IMPLEMENTED.lint = lintCommand;
|
|
620
|
+
IMPLEMENTED.generate = generateCommand;
|
|
87
621
|
|
|
622
|
+
export async function run(argv = process.argv) {
|
|
623
|
+
let rawArgs = Array.isArray(argv) && argv.length > 0 ? [...argv] : process.argv.slice(2);
|
|
624
|
+
while (rawArgs.length > 0 && (
|
|
625
|
+
rawArgs[0].endsWith('node') ||
|
|
626
|
+
rawArgs[0].endsWith('total-recall') ||
|
|
627
|
+
rawArgs[0].endsWith('cli.mjs') ||
|
|
628
|
+
rawArgs[0] === 'openwiki'
|
|
629
|
+
)) {
|
|
630
|
+
rawArgs.shift();
|
|
631
|
+
}
|
|
88
632
|
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
const sub = args[0] || "status";
|
|
92
|
-
const json = args.includes("--json");
|
|
633
|
+
const sub = rawArgs[0] || "status";
|
|
634
|
+
const json = rawArgs.includes("--json");
|
|
93
635
|
|
|
94
636
|
if (sub === "status") {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
:
|
|
637
|
+
const upstream = readUpstreamState();
|
|
638
|
+
const status = {
|
|
639
|
+
plugin: "openwiki",
|
|
640
|
+
implemented: Object.keys(IMPLEMENTED),
|
|
641
|
+
upstream: {
|
|
642
|
+
recordedVersion: upstream.currentRecordedVersion,
|
|
643
|
+
latestVersion: upstream.latestKnownVersion,
|
|
644
|
+
lastChecked: upstream.lastCheckedAt,
|
|
645
|
+
lastPropagated: upstream.lastPropagatedAt
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
if (json) console.log(JSON.stringify(status, null, 2));
|
|
649
|
+
else {
|
|
650
|
+
console.log(`OpenWiki: implemented subcommands: ${status.implemented.join(", ")}`);
|
|
651
|
+
console.log(`Upstream Status: recorded v${status.upstream.recordedVersion}, latest v${status.upstream.latestVersion}`);
|
|
652
|
+
}
|
|
100
653
|
return;
|
|
101
654
|
}
|
|
102
655
|
|
|
@@ -108,20 +661,45 @@ export async function run(argv = []) {
|
|
|
108
661
|
total-recall openwiki <subcommand> [options]
|
|
109
662
|
|
|
110
663
|
Subcommands:
|
|
111
|
-
status Show OpenWiki plugin status
|
|
664
|
+
status Show OpenWiki plugin and upstream status
|
|
112
665
|
probe [--json] Check subsystem health
|
|
113
|
-
hubs [--
|
|
666
|
+
hubs [--all-vaults] [--node <node>] [--json]
|
|
667
|
+
List indexed documentation hubs across workspace, all vaults, or mesh
|
|
668
|
+
search <query> [--all-vaults] [--node <node>] [--limit <n>] [--json]
|
|
669
|
+
Evidence passage search across knowledge hubs and vaults
|
|
670
|
+
graph [--all-vaults] [--node <node>] [--format json|mermaid|dot] [--json]
|
|
671
|
+
Extract knowledge graph topology, nodes, and inter-hub links
|
|
672
|
+
generate [--repo <name>] [--path <dir>] [--output <dir>] [--force] [--dry-run] [--node <node>] [--json]
|
|
673
|
+
Targeted on-demand documentation generation
|
|
674
|
+
token [status|set <provider> <value>] [--stdin] [--json]
|
|
675
|
+
Check or securely configure Total Recall secrets store keys
|
|
676
|
+
lint [--all-vaults] [--node <node>] [--json]
|
|
677
|
+
Validate link integrity, dead targets, and orphaned hubs
|
|
114
678
|
ingest <path> [options] Ingest Markdown files into knowledge graph
|
|
115
679
|
bootstrap --brain <path> [--project-root <path>] [--dry-run] [--json]
|
|
116
680
|
Create missing plugin-owned documentation pages
|
|
681
|
+
refresh [--repo <name>] [--apply] [--force] [--json]
|
|
682
|
+
Report which registered projects' generated pages are stale;
|
|
683
|
+
--apply regenerates stale pages (writes openwiki/ only)
|
|
684
|
+
config [show|get <key>|set <key> <value>|reset] [--json]
|
|
685
|
+
Configure generator provider, model, tokens, and timeout
|
|
686
|
+
watch [--check-only] [--announce] [--propagate] [--json]
|
|
687
|
+
Watch upstream OpenWiki repository and announce new versions
|
|
688
|
+
propagate [--repo <name>] [--force] [--dry-run] [--json]
|
|
689
|
+
Propagate updated generator across registered repositories
|
|
117
690
|
`);
|
|
118
691
|
return;
|
|
119
692
|
}
|
|
120
693
|
|
|
121
|
-
if (Object.hasOwn(IMPLEMENTED, sub)) return IMPLEMENTED[sub](
|
|
694
|
+
if (Object.hasOwn(IMPLEMENTED, sub)) return IMPLEMENTED[sub](rawArgs.slice(1));
|
|
122
695
|
|
|
123
696
|
if (json) console.log(JSON.stringify({ ok: false, error: `OpenWiki operation is not implemented: ${sub}` }));
|
|
124
697
|
console.error(`OpenWiki: "${sub}" is not implemented.`);
|
|
125
698
|
process.exitCode = 2;
|
|
126
699
|
}
|
|
700
|
+
|
|
701
|
+
if (process.argv[1] && (process.argv[1].endsWith('cli.mjs') || process.argv[1].endsWith('tr-plugin-openwiki'))) {
|
|
702
|
+
run(process.argv);
|
|
703
|
+
}
|
|
704
|
+
|
|
127
705
|
export default run;
|