@pleri/olam-cli 0.1.144 → 0.1.146
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/dist/commands/doctor.d.ts +53 -23
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +117 -46
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/logs.d.ts +17 -3
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +38 -35
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/memory/bridge.d.ts +57 -0
- package/dist/commands/memory/bridge.d.ts.map +1 -0
- package/dist/commands/memory/bridge.js +156 -0
- package/dist/commands/memory/bridge.js.map +1 -0
- package/dist/commands/memory/index.d.ts +3 -0
- package/dist/commands/memory/index.d.ts.map +1 -1
- package/dist/commands/memory/index.js +10 -1
- package/dist/commands/memory/index.js.map +1 -1
- package/dist/commands/memory/reclassify.d.ts +56 -0
- package/dist/commands/memory/reclassify.d.ts.map +1 -0
- package/dist/commands/memory/reclassify.js +177 -0
- package/dist/commands/memory/reclassify.js.map +1 -0
- package/dist/commands/memory/stats.d.ts +69 -0
- package/dist/commands/memory/stats.d.ts.map +1 -0
- package/dist/commands/memory/stats.js +164 -0
- package/dist/commands/memory/stats.js.map +1 -0
- package/dist/commands/skills-doctor.d.ts +14 -0
- package/dist/commands/skills-doctor.d.ts.map +1 -0
- package/dist/commands/skills-doctor.js +126 -0
- package/dist/commands/skills-doctor.js.map +1 -0
- package/dist/commands/skills-hook.d.ts +19 -0
- package/dist/commands/skills-hook.d.ts.map +1 -0
- package/dist/commands/skills-hook.js +99 -0
- package/dist/commands/skills-hook.js.map +1 -0
- package/dist/commands/skills-migrate-back.d.ts +21 -0
- package/dist/commands/skills-migrate-back.d.ts.map +1 -0
- package/dist/commands/skills-migrate-back.js +222 -0
- package/dist/commands/skills-migrate-back.js.map +1 -0
- package/dist/commands/skills-migrate.d.ts +33 -0
- package/dist/commands/skills-migrate.d.ts.map +1 -0
- package/dist/commands/skills-migrate.js +216 -0
- package/dist/commands/skills-migrate.js.map +1 -0
- package/dist/commands/skills-onboard.d.ts +26 -0
- package/dist/commands/skills-onboard.d.ts.map +1 -0
- package/dist/commands/skills-onboard.js +227 -0
- package/dist/commands/skills-onboard.js.map +1 -0
- package/dist/commands/skills-shadow-backups.d.ts +15 -0
- package/dist/commands/skills-shadow-backups.d.ts.map +1 -0
- package/dist/commands/skills-shadow-backups.js +132 -0
- package/dist/commands/skills-shadow-backups.js.map +1 -0
- package/dist/commands/skills-source.d.ts +37 -0
- package/dist/commands/skills-source.d.ts.map +1 -0
- package/dist/commands/skills-source.js +431 -0
- package/dist/commands/skills-source.js.map +1 -0
- package/dist/commands/skills.d.ts +11 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/skills.js +170 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/status.d.ts +27 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +102 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/substrate-audit-log.d.ts +49 -0
- package/dist/commands/substrate-audit-log.d.ts.map +1 -0
- package/dist/commands/substrate-audit-log.js +148 -0
- package/dist/commands/substrate-audit-log.js.map +1 -0
- package/dist/commands/substrate.d.ts +60 -0
- package/dist/commands/substrate.d.ts.map +1 -0
- package/dist/commands/substrate.js +175 -0
- package/dist/commands/substrate.js.map +1 -0
- package/dist/commands/upgrade.d.ts +10 -0
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +30 -0
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/image-digests.json +7 -7
- package/dist/index.js +8394 -3876
- package/dist/index.js.map +1 -1
- package/dist/lib/config.d.ts +69 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +146 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/health-probes.d.ts +72 -0
- package/dist/lib/health-probes.d.ts.map +1 -1
- package/dist/lib/health-probes.js +218 -0
- package/dist/lib/health-probes.js.map +1 -1
- package/dist/lib/instrumentation.d.ts +85 -0
- package/dist/lib/instrumentation.d.ts.map +1 -0
- package/dist/lib/instrumentation.js +104 -0
- package/dist/lib/instrumentation.js.map +1 -0
- package/dist/lib/kubectl-wrap.d.ts +59 -0
- package/dist/lib/kubectl-wrap.d.ts.map +1 -0
- package/dist/lib/kubectl-wrap.js +130 -0
- package/dist/lib/kubectl-wrap.js.map +1 -0
- package/dist/lib/manifest-refresh.d.ts +95 -0
- package/dist/lib/manifest-refresh.d.ts.map +1 -0
- package/dist/lib/manifest-refresh.js +222 -0
- package/dist/lib/manifest-refresh.js.map +1 -0
- package/dist/lib/port-forward.d.ts +101 -0
- package/dist/lib/port-forward.d.ts.map +1 -0
- package/dist/lib/port-forward.js +240 -0
- package/dist/lib/port-forward.js.map +1 -0
- package/dist/lib/upgrade-kubernetes.d.ts +77 -0
- package/dist/lib/upgrade-kubernetes.d.ts.map +1 -0
- package/dist/lib/upgrade-kubernetes.js +277 -0
- package/dist/lib/upgrade-kubernetes.js.map +1 -0
- package/dist/mcp-server.js +3328 -1166
- package/host-cp/k8s/manifests/00-namespace.yaml +7 -0
- package/host-cp/k8s/manifests/10-serviceaccount.yaml +8 -0
- package/host-cp/k8s/manifests/20-rbac.yaml +34 -0
- package/host-cp/k8s/manifests/30-configmap.yaml +30 -0
- package/host-cp/k8s/manifests/45-pvc.yaml +27 -0
- package/host-cp/k8s/manifests/50-deployment.yaml +148 -0
- package/host-cp/k8s/manifests/60-service.yaml +22 -0
- package/host-cp/k8s/templates/40-secret-template.yaml +32 -0
- package/host-cp/src/agent-runtime-trigger.mjs +74 -4
- package/host-cp/src/engine-identity.mjs +32 -0
- package/host-cp/src/plan-chat-service.mjs +31 -7
- package/host-cp/src/server.mjs +219 -9
- package/package.json +3 -2
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* olam memory stats — operator-facing formatter over `/bridge/stats`.
|
|
3
|
+
*
|
|
4
|
+
* $ olam memory stats
|
|
5
|
+
* # human-readable counters + derived cache_error_rate
|
|
6
|
+
*
|
|
7
|
+
* $ olam memory stats --json
|
|
8
|
+
* # raw /bridge/stats response (for jq / monitoring scripts)
|
|
9
|
+
*
|
|
10
|
+
* Config (env vars):
|
|
11
|
+
* AGENTMEMORY_BRIDGE_URL bridge base URL
|
|
12
|
+
* (default: https://olam-agent-memory.ernestcodes.workers.dev)
|
|
13
|
+
* AGENTMEMORY_BRIDGE_SECRET bearer token
|
|
14
|
+
*
|
|
15
|
+
* Derived metric: cache_error_rate =
|
|
16
|
+
* (cache_busted_hash + cache_busted_version) / max(writes_observed, 1)
|
|
17
|
+
*
|
|
18
|
+
* Interpretation: high rates (>5%) mean operators have been forced to
|
|
19
|
+
* reclassify a lot of recent writes — usually a sign that the prompt
|
|
20
|
+
* template / classifier_version is churning. The denominator is
|
|
21
|
+
* classifier_writes_observed (NOT bridge writes_observed).
|
|
22
|
+
*
|
|
23
|
+
* Plan reference:
|
|
24
|
+
* docs/plans/agentmemory-classifier-and-regret/phase-b-tasks.md (B5/B6)
|
|
25
|
+
*/
|
|
26
|
+
import { printError, printHeader, printInfo } from '../../output.js';
|
|
27
|
+
const DEFAULT_BRIDGE_URL = 'https://olam-agent-memory.ernestcodes.workers.dev';
|
|
28
|
+
const STATS_TIMEOUT_MS = 10_000;
|
|
29
|
+
/**
|
|
30
|
+
* Pure helper — separated so it's unit-testable without HTTP.
|
|
31
|
+
* Guards divide-by-zero (returns 0 when writes_observed === 0, even
|
|
32
|
+
* if busts are nonzero — Infinity / NaN would be operator-hostile).
|
|
33
|
+
*/
|
|
34
|
+
export function computeCacheErrorRate(counters) {
|
|
35
|
+
if (counters.writes_observed <= 0)
|
|
36
|
+
return 0;
|
|
37
|
+
const busted = counters.cache_busted_hash + counters.cache_busted_version;
|
|
38
|
+
return busted / counters.writes_observed;
|
|
39
|
+
}
|
|
40
|
+
function resolveBridgeUrl(opts) {
|
|
41
|
+
return opts.bridgeUrl
|
|
42
|
+
?? process.env['AGENTMEMORY_BRIDGE_URL']
|
|
43
|
+
?? DEFAULT_BRIDGE_URL;
|
|
44
|
+
}
|
|
45
|
+
function resolveBearer(opts) {
|
|
46
|
+
const fromOpt = opts.bearer;
|
|
47
|
+
if (fromOpt && fromOpt.length > 0)
|
|
48
|
+
return fromOpt;
|
|
49
|
+
const fromEnv = process.env['AGENTMEMORY_BRIDGE_SECRET'];
|
|
50
|
+
if (fromEnv && fromEnv.length > 0)
|
|
51
|
+
return fromEnv;
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
function intOrZero(v) {
|
|
55
|
+
if (typeof v !== 'number' || !Number.isFinite(v))
|
|
56
|
+
return 0;
|
|
57
|
+
return Math.trunc(v);
|
|
58
|
+
}
|
|
59
|
+
function extractCounters(stats) {
|
|
60
|
+
return {
|
|
61
|
+
writes_observed: intOrZero(stats.classifier_writes_observed),
|
|
62
|
+
writes_deduped_hash: intOrZero(stats.classifier_writes_deduped_hash),
|
|
63
|
+
writes_deduped_semantic: intOrZero(stats.classifier_writes_deduped_semantic),
|
|
64
|
+
recalls_observed: intOrZero(stats.classifier_recalls_observed),
|
|
65
|
+
cache_busted_hash: intOrZero(stats.classifier_cache_busted_hash),
|
|
66
|
+
cache_busted_version: intOrZero(stats.classifier_cache_busted_version),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Run the stats call. Pure-ish: takes opts + fetch (so tests can stub) +
|
|
71
|
+
* returns a structured result. Mirrors `runReclassify` for symmetry.
|
|
72
|
+
*/
|
|
73
|
+
export async function runStats(opts, fetchImpl = fetch) {
|
|
74
|
+
const bridgeUrl = resolveBridgeUrl(opts);
|
|
75
|
+
const bearer = resolveBearer(opts);
|
|
76
|
+
if (!bearer) {
|
|
77
|
+
return {
|
|
78
|
+
ok: false,
|
|
79
|
+
error: 'AGENTMEMORY_BRIDGE_SECRET not set (or --bearer not passed)',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const res = await fetchImpl(`${bridgeUrl}/bridge/stats`, {
|
|
84
|
+
method: 'GET',
|
|
85
|
+
headers: {
|
|
86
|
+
authorization: `Bearer ${bearer}`,
|
|
87
|
+
},
|
|
88
|
+
signal: AbortSignal.timeout(STATS_TIMEOUT_MS),
|
|
89
|
+
});
|
|
90
|
+
if (!res.ok) {
|
|
91
|
+
const detail = await res.text().catch(() => '');
|
|
92
|
+
return {
|
|
93
|
+
ok: false,
|
|
94
|
+
error: `bridge returned ${res.status} ${res.statusText}${detail ? `: ${detail.slice(0, 200)}` : ''}`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const payload = (await res.json());
|
|
98
|
+
if (!payload || typeof payload !== 'object' || !payload.stats || typeof payload.stats !== 'object') {
|
|
99
|
+
return {
|
|
100
|
+
ok: false,
|
|
101
|
+
error: 'bridge response missing stats envelope',
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const counters = extractCounters(payload.stats);
|
|
105
|
+
const cacheErrorRate = computeCacheErrorRate(counters);
|
|
106
|
+
return {
|
|
107
|
+
ok: true,
|
|
108
|
+
counters,
|
|
109
|
+
cacheErrorRate,
|
|
110
|
+
raw: payload,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
return {
|
|
115
|
+
ok: false,
|
|
116
|
+
error: err instanceof Error ? err.message : String(err),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function formatPct(numerator, denominator) {
|
|
121
|
+
if (denominator <= 0)
|
|
122
|
+
return '0.0%';
|
|
123
|
+
return `${((numerator / denominator) * 100).toFixed(1)}%`;
|
|
124
|
+
}
|
|
125
|
+
/** Run + render. Returns the process exit code. */
|
|
126
|
+
export async function runStatsCli(opts) {
|
|
127
|
+
const result = await runStats(opts);
|
|
128
|
+
if (opts.json) {
|
|
129
|
+
// Preserve the raw bridge envelope when possible so jq pipelines
|
|
130
|
+
// see the same shape they'd get from curl. Fall back to the
|
|
131
|
+
// structured result on error so callers can still inspect.
|
|
132
|
+
const out = result.ok && result.raw !== undefined ? result.raw : result;
|
|
133
|
+
process.stdout.write(JSON.stringify(out, null, 2) + '\n');
|
|
134
|
+
return result.ok ? 0 : 1;
|
|
135
|
+
}
|
|
136
|
+
printHeader('olam memory stats — bridge counters');
|
|
137
|
+
if (!result.ok) {
|
|
138
|
+
printError(`stats failed: ${result.error ?? '(unknown error)'}`);
|
|
139
|
+
return 1;
|
|
140
|
+
}
|
|
141
|
+
const c = result.counters;
|
|
142
|
+
printInfo('writes_observed', String(c.writes_observed));
|
|
143
|
+
printInfo('writes_deduped_hash', `${c.writes_deduped_hash} (${formatPct(c.writes_deduped_hash, c.writes_observed)})`);
|
|
144
|
+
printInfo('writes_deduped_semantic', `${c.writes_deduped_semantic} (${formatPct(c.writes_deduped_semantic, c.writes_observed)})`);
|
|
145
|
+
printInfo('recalls_observed', String(c.recalls_observed));
|
|
146
|
+
printInfo('cache_busted_hash', String(c.cache_busted_hash));
|
|
147
|
+
printInfo('cache_busted_version', String(c.cache_busted_version));
|
|
148
|
+
printInfo('cache_error_rate', `${(result.cacheErrorRate * 100).toFixed(1)}%`);
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
export function registerMemoryStats(cmd) {
|
|
152
|
+
cmd
|
|
153
|
+
.command('stats')
|
|
154
|
+
.description('Fetch /bridge/stats from the agent-memory bridge and format classifier counters (writes_observed, dedup rates, recalls, cache busts, derived cache_error_rate)')
|
|
155
|
+
.option('--bridge-url <url>', 'Override AGENTMEMORY_BRIDGE_URL')
|
|
156
|
+
.option('--bearer <token>', 'Override AGENTMEMORY_BRIDGE_SECRET')
|
|
157
|
+
.option('--json', 'Machine-readable JSON output (raw bridge envelope)', false)
|
|
158
|
+
.action(async (opts) => {
|
|
159
|
+
const rc = await runStatsCli(opts);
|
|
160
|
+
if (rc !== 0)
|
|
161
|
+
process.exitCode = rc;
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../src/commands/memory/stats.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* olam skills doctor — diagnostic + auto-repair for the skills surface.
|
|
3
|
+
*
|
|
4
|
+
* olam skills doctor # print report; interactive prompts
|
|
5
|
+
* # per issue when TTY
|
|
6
|
+
* olam skills doctor --auto-fix # apply every repair without prompt
|
|
7
|
+
* olam skills doctor --check-only # exit 1 on any issue; never modify
|
|
8
|
+
* # state (read-only health probe)
|
|
9
|
+
*
|
|
10
|
+
* Mirrors `olam kg doctor`'s shape; per OQ12 [assumed].
|
|
11
|
+
*/
|
|
12
|
+
import type { Command } from 'commander';
|
|
13
|
+
export declare function registerSkillsDoctor(program: Command): void;
|
|
14
|
+
//# sourceMappingURL=skills-doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-doctor.d.ts","sourceRoot":"","sources":["../../src/commands/skills-doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgDzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6E3D"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* olam skills doctor — diagnostic + auto-repair for the skills surface.
|
|
3
|
+
*
|
|
4
|
+
* olam skills doctor # print report; interactive prompts
|
|
5
|
+
* # per issue when TTY
|
|
6
|
+
* olam skills doctor --auto-fix # apply every repair without prompt
|
|
7
|
+
* olam skills doctor --check-only # exit 1 on any issue; never modify
|
|
8
|
+
* # state (read-only health probe)
|
|
9
|
+
*
|
|
10
|
+
* Mirrors `olam kg doctor`'s shape; per OQ12 [assumed].
|
|
11
|
+
*/
|
|
12
|
+
import * as readline from 'node:readline';
|
|
13
|
+
import pc from 'picocolors';
|
|
14
|
+
import { runAllDoctorChecks, } from '@olam/core/src/skill-sources/index.js';
|
|
15
|
+
import { printError, printHeader, printSuccess, printWarning } from '../output.js';
|
|
16
|
+
function asMessage(err) {
|
|
17
|
+
return err instanceof Error ? err.message : String(err);
|
|
18
|
+
}
|
|
19
|
+
function defaultDoctorPrompt(question) {
|
|
20
|
+
return new Promise((resolve) => {
|
|
21
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
22
|
+
rl.question(question, (a) => {
|
|
23
|
+
rl.close();
|
|
24
|
+
resolve(a);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async function confirmRepair(check) {
|
|
29
|
+
const testFn = globalThis.__olamTestDoctorPrompt;
|
|
30
|
+
const prompt = testFn ?? (() => defaultDoctorPrompt(`Apply repair for "${check.name}"? [y/N] `));
|
|
31
|
+
const answer = (await prompt()).trim().toLowerCase();
|
|
32
|
+
return answer === 'y' || answer === 'yes';
|
|
33
|
+
}
|
|
34
|
+
function printCheck(check) {
|
|
35
|
+
if (check.healthy) {
|
|
36
|
+
console.log(` ${pc.green('✓')} ${pc.bold(check.name.padEnd(22))} ${pc.dim(check.description)}`);
|
|
37
|
+
if (check.details && check.details.length > 0) {
|
|
38
|
+
for (const d of check.details)
|
|
39
|
+
console.log(` ${pc.dim(d)}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.log(` ${pc.red('✗')} ${pc.bold(check.name.padEnd(22))} ${pc.yellow(check.issue ?? 'unhealthy')}`);
|
|
44
|
+
console.log(` ${pc.dim(check.description)}`);
|
|
45
|
+
if (check.details) {
|
|
46
|
+
for (const d of check.details.slice(0, 10))
|
|
47
|
+
console.log(` ${pc.dim('· ' + d)}`);
|
|
48
|
+
if (check.details.length > 10)
|
|
49
|
+
console.log(` ${pc.dim(`… and ${check.details.length - 10} more`)}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function registerSkillsDoctor(program) {
|
|
54
|
+
const skills = program.commands.find((c) => c.name() === 'skills') ??
|
|
55
|
+
program.command('skills').description('Manage skill sources and synchronization');
|
|
56
|
+
skills
|
|
57
|
+
.command('doctor')
|
|
58
|
+
.description('Diagnose 4 corruption classes; auto-repair available with --auto-fix')
|
|
59
|
+
.option('--auto-fix', 'Apply each repair without prompting')
|
|
60
|
+
.option('--check-only', 'Report issues + exit non-zero without modifying state')
|
|
61
|
+
.action(async (opts) => {
|
|
62
|
+
if (opts.autoFix && opts.checkOnly) {
|
|
63
|
+
printError('--auto-fix and --check-only are mutually exclusive');
|
|
64
|
+
process.exitCode = 1;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
printHeader('skills doctor');
|
|
68
|
+
let checks;
|
|
69
|
+
try {
|
|
70
|
+
checks = runAllDoctorChecks();
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
printError(`doctor checks crashed: ${asMessage(err)}`);
|
|
74
|
+
process.exitCode = 1;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
for (const c of checks)
|
|
78
|
+
printCheck(c);
|
|
79
|
+
const unhealthy = checks.filter((c) => !c.healthy);
|
|
80
|
+
if (unhealthy.length === 0) {
|
|
81
|
+
console.log();
|
|
82
|
+
printSuccess('all 4 checks PASS');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
console.log();
|
|
86
|
+
printWarning(`${unhealthy.length} of ${checks.length} check(s) report issues`);
|
|
87
|
+
if (opts.checkOnly) {
|
|
88
|
+
console.log(pc.dim('(--check-only — exiting without repair)'));
|
|
89
|
+
process.exitCode = 1;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
let repaired = 0;
|
|
93
|
+
let skipped = 0;
|
|
94
|
+
for (const check of unhealthy) {
|
|
95
|
+
if (!check.repair) {
|
|
96
|
+
console.log(pc.dim(` (no auto-repair for ${check.name} — operator-attention required)`));
|
|
97
|
+
skipped += 1;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const shouldRepair = opts.autoFix ? true : await confirmRepair(check);
|
|
101
|
+
if (!shouldRepair) {
|
|
102
|
+
console.log(pc.dim(` skipped: ${check.name}`));
|
|
103
|
+
skipped += 1;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
await check.repair();
|
|
108
|
+
console.log(pc.green(` repaired: ${check.name}`));
|
|
109
|
+
repaired += 1;
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
printError(` repair failed for ${check.name}: ${asMessage(err)}`);
|
|
113
|
+
skipped += 1;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
console.log();
|
|
117
|
+
if (skipped > 0) {
|
|
118
|
+
printWarning(`repaired ${repaired}; skipped ${skipped}. Re-run doctor to verify.`);
|
|
119
|
+
process.exitCode = skipped > 0 ? 1 : 0;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
printSuccess(`repaired ${repaired} issue(s). Re-run doctor to verify.`);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=skills-doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-doctor.js","sourceRoot":"","sources":["../../src/commands/skills-doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `olam skills install-hook [--scope project|user]` — install the
|
|
3
|
+
* SessionStart hook that runs `olam skills sync --quiet` on every
|
|
4
|
+
* Claude Code session start.
|
|
5
|
+
*
|
|
6
|
+
* `olam skills uninstall-hook [--scope project|user]` — surgical
|
|
7
|
+
* sentinel-matched removal.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors `olam kg install-hook` / `olam kg uninstall-hook` shape:
|
|
10
|
+
* - `--scope project` (default) → <cwd>/.claude/settings.json
|
|
11
|
+
* - `--scope user` → ~/.claude/settings.json
|
|
12
|
+
*
|
|
13
|
+
* Idempotent install via OLAM_SKILLS_HOOK_SENTINEL substring-match.
|
|
14
|
+
* Surgical uninstall: only entries whose command contains the sentinel
|
|
15
|
+
* are dropped; user-authored hooks are preserved.
|
|
16
|
+
*/
|
|
17
|
+
import type { Command } from 'commander';
|
|
18
|
+
export declare function registerSkillsHook(program: Command): void;
|
|
19
|
+
//# sourceMappingURL=skills-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-hook.d.ts","sourceRoot":"","sources":["../../src/commands/skills-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoBzC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuEzD"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `olam skills install-hook [--scope project|user]` — install the
|
|
3
|
+
* SessionStart hook that runs `olam skills sync --quiet` on every
|
|
4
|
+
* Claude Code session start.
|
|
5
|
+
*
|
|
6
|
+
* `olam skills uninstall-hook [--scope project|user]` — surgical
|
|
7
|
+
* sentinel-matched removal.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors `olam kg install-hook` / `olam kg uninstall-hook` shape:
|
|
10
|
+
* - `--scope project` (default) → <cwd>/.claude/settings.json
|
|
11
|
+
* - `--scope user` → ~/.claude/settings.json
|
|
12
|
+
*
|
|
13
|
+
* Idempotent install via OLAM_SKILLS_HOOK_SENTINEL substring-match.
|
|
14
|
+
* Surgical uninstall: only entries whose command contains the sentinel
|
|
15
|
+
* are dropped; user-authored hooks are preserved.
|
|
16
|
+
*/
|
|
17
|
+
import { installSkillsHookToFile, skillsHookSettingsPathFor, uninstallSkillsHookFromFile, } from '@olam/core/src/skill-sources/index.js';
|
|
18
|
+
import * as fs from 'node:fs';
|
|
19
|
+
import { printError, printInfo, printSuccess, printWarning } from '../output.js';
|
|
20
|
+
function backup(filePath) {
|
|
21
|
+
if (!fs.existsSync(filePath))
|
|
22
|
+
return null;
|
|
23
|
+
const ts = new Date().toISOString().replace(/[:.]/g, '-');
|
|
24
|
+
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
25
|
+
fs.copyFileSync(filePath, backupPath);
|
|
26
|
+
return backupPath;
|
|
27
|
+
}
|
|
28
|
+
export function registerSkillsHook(program) {
|
|
29
|
+
const skills = program.commands.find((c) => c.name() === 'skills') ??
|
|
30
|
+
program.command('skills').description('Manage skill sources and synchronization');
|
|
31
|
+
skills
|
|
32
|
+
.command('install-hook')
|
|
33
|
+
.description('Install the SessionStart hook that runs `olam skills sync --quiet` on session start')
|
|
34
|
+
.option('--scope <scope>', 'project (default; <cwd>/.claude/settings.json) or user (~/.claude/settings.json)', 'project')
|
|
35
|
+
.action((opts) => {
|
|
36
|
+
const scope = opts.scope === 'user' ? 'user' : 'project';
|
|
37
|
+
const filePath = skillsHookSettingsPathFor(scope);
|
|
38
|
+
try {
|
|
39
|
+
const result = installSkillsHookToFile(filePath);
|
|
40
|
+
switch (result.status) {
|
|
41
|
+
case 'installed':
|
|
42
|
+
printSuccess(`olam-skills SessionStart hook installed (${scope} scope)`);
|
|
43
|
+
printInfo('settings', filePath);
|
|
44
|
+
if (result.backupPath)
|
|
45
|
+
printInfo('backup', result.backupPath);
|
|
46
|
+
printInfo('next', 'open a new Claude Code session; `olam skills sync --quiet` will run on start');
|
|
47
|
+
return;
|
|
48
|
+
case 'already-present':
|
|
49
|
+
printInfo('olam-skills hook', `already installed at ${filePath}`);
|
|
50
|
+
return;
|
|
51
|
+
case 'no-op':
|
|
52
|
+
printWarning(`no change made to ${filePath}`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
printError(`install-hook failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
58
|
+
process.exitCode = 1;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
skills
|
|
62
|
+
.command('uninstall-hook')
|
|
63
|
+
.description('Remove the olam-skills SessionStart hook from settings.json (sentinel-matched; surgical)')
|
|
64
|
+
.option('--scope <scope>', 'project (default) or user', 'project')
|
|
65
|
+
.action((opts) => {
|
|
66
|
+
const scope = opts.scope === 'user' ? 'user' : 'project';
|
|
67
|
+
const filePath = skillsHookSettingsPathFor(scope);
|
|
68
|
+
const backupPath = backup(filePath);
|
|
69
|
+
try {
|
|
70
|
+
const result = uninstallSkillsHookFromFile(filePath);
|
|
71
|
+
switch (result.status) {
|
|
72
|
+
case 'removed':
|
|
73
|
+
printSuccess(`olam-skills SessionStart hook removed from ${filePath}`);
|
|
74
|
+
if (backupPath)
|
|
75
|
+
printInfo('backup', backupPath);
|
|
76
|
+
return;
|
|
77
|
+
case 'not-found':
|
|
78
|
+
printInfo('olam-skills hook', `not found in ${filePath} — already uninstalled`);
|
|
79
|
+
if (backupPath) {
|
|
80
|
+
try {
|
|
81
|
+
fs.unlinkSync(backupPath);
|
|
82
|
+
}
|
|
83
|
+
catch { /* best-effort */ }
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
case 'no-settings':
|
|
87
|
+
printInfo('olam-skills hook', `no settings.json at ${filePath} — nothing to remove`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
printError(`uninstall-hook failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
93
|
+
if (backupPath)
|
|
94
|
+
printInfo('backup', `settings.json preserved at ${backupPath}`);
|
|
95
|
+
process.exitCode = 1;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=skills-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-hook.js","sourceRoot":"","sources":["../../src/commands/skills-hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `olam skills migrate-back-to-toolbox` — reverse the migration performed
|
|
3
|
+
* by `migrate-from-toolbox`, consuming the pre-migration snapshot written
|
|
4
|
+
* at ~/.olam/state/migration-snapshots/<namespace>-<ISO>.json.
|
|
5
|
+
*
|
|
6
|
+
* Reverse order of migrate-from-toolbox operations:
|
|
7
|
+
* 1. resolve snapshot (latest matching --path / --namespace / --snapshot)
|
|
8
|
+
* 2. uninstall olam-skills SessionStart hook (sentinel-matched)
|
|
9
|
+
* 3. delete olam-managed symlinks under ~/.claude/ (any symlink whose
|
|
10
|
+
* target lives under ~/.olam/state/skill-sources/<id>/)
|
|
11
|
+
* 4. restore the original SessionStart hook block from snapshot
|
|
12
|
+
* 5. restore the toolbox-managed symlinks from snapshot
|
|
13
|
+
* 6. restore ~/.claude/.atlas-user from snapshot (atlas-shape only)
|
|
14
|
+
* 7. unless --keep-source: remove the toolbox olam source registration
|
|
15
|
+
* (skill-sources slice + clone dir)
|
|
16
|
+
*/
|
|
17
|
+
import type { Command } from 'commander';
|
|
18
|
+
/** Stable command identifier — referenced by tests to keep them rename-resilient. */
|
|
19
|
+
export declare const MIGRATE_BACK_TO_TOOLBOX_COMMAND = "migrate-back-to-toolbox";
|
|
20
|
+
export declare function registerSkillsMigrateBack(program: Command): void;
|
|
21
|
+
//# sourceMappingURL=skills-migrate-back.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-migrate-back.d.ts","sourceRoot":"","sources":["../../src/commands/skills-migrate-back.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAezC,qFAAqF;AACrF,eAAO,MAAM,+BAA+B,4BAA4B,CAAC;AAiGzE,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoHhE"}
|