@pleri/olam-cli 0.1.128 → 0.1.132
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/bootstrap.d.ts +8 -0
- package/dist/commands/bootstrap.d.ts.map +1 -1
- package/dist/commands/bootstrap.js +14 -0
- package/dist/commands/bootstrap.js.map +1 -1
- package/dist/commands/kg-build.d.ts.map +1 -1
- package/dist/commands/kg-build.js +10 -0
- package/dist/commands/kg-build.js.map +1 -1
- package/dist/commands/kg-classify.d.ts +10 -0
- package/dist/commands/kg-classify.d.ts.map +1 -0
- package/dist/commands/kg-classify.js +51 -0
- package/dist/commands/kg-classify.js.map +1 -0
- package/dist/commands/kg-doctor.d.ts +15 -0
- package/dist/commands/kg-doctor.d.ts.map +1 -0
- package/dist/commands/kg-doctor.js +182 -0
- package/dist/commands/kg-doctor.js.map +1 -0
- package/dist/commands/kg-install-hook.d.ts +14 -0
- package/dist/commands/kg-install-hook.d.ts.map +1 -0
- package/dist/commands/kg-install-hook.js +92 -0
- package/dist/commands/kg-install-hook.js.map +1 -0
- package/dist/commands/kg-service-container.d.ts +68 -0
- package/dist/commands/kg-service-container.d.ts.map +1 -0
- package/dist/commands/kg-service-container.js +181 -0
- package/dist/commands/kg-service-container.js.map +1 -0
- package/dist/commands/kg-uninstall-hook.d.ts +12 -0
- package/dist/commands/kg-uninstall-hook.d.ts.map +1 -0
- package/dist/commands/kg-uninstall-hook.js +121 -0
- package/dist/commands/kg-uninstall-hook.js.map +1 -0
- package/dist/commands/memory/index.d.ts.map +1 -1
- package/dist/commands/memory/index.js +2 -0
- package/dist/commands/memory/index.js.map +1 -1
- package/dist/commands/memory/mode.d.ts +47 -0
- package/dist/commands/memory/mode.d.ts.map +1 -0
- package/dist/commands/memory/mode.js +181 -0
- package/dist/commands/memory/mode.js.map +1 -0
- package/dist/commands/rekey.d.ts +84 -0
- package/dist/commands/rekey.d.ts.map +1 -0
- package/dist/commands/rekey.js +209 -0
- package/dist/commands/rekey.js.map +1 -0
- package/dist/commands/services.d.ts +5 -5
- package/dist/commands/services.d.ts.map +1 -1
- package/dist/commands/services.js +70 -6
- package/dist/commands/services.js.map +1 -1
- package/dist/image-digests.json +3 -3
- package/dist/index.js +2091 -667
- package/dist/index.js.map +1 -1
- package/dist/lib/memory-secret.d.ts +22 -0
- package/dist/lib/memory-secret.d.ts.map +1 -1
- package/dist/lib/memory-secret.js +38 -0
- package/dist/lib/memory-secret.js.map +1 -1
- package/dist/mcp-server.js +18499 -17383
- package/package.json +1 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KgServiceContainerController — lifecycle for olam-kg-service.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors McpAuthContainerController (./services.ts) since kg-service, like
|
|
5
|
+
* mcp-auth-service, is not a @olam/core package. The persistent HTTP classifier
|
|
6
|
+
* inside the container holds bge-small-en-v1.5 in memory; we pre-warm at
|
|
7
|
+
* start() to eliminate the first-call cold cliff (see Phase A latency bench at
|
|
8
|
+
* ~/kg-benchmark/kg-service-poc/latency-results.json).
|
|
9
|
+
*/
|
|
10
|
+
export declare const KG_SERVICE_PORT = 9997;
|
|
11
|
+
export declare const KG_SERVICE_CONTAINER = "olam-kg-service";
|
|
12
|
+
export declare const KG_SERVICE_LOCAL_TAG = "olam-kg-service:local";
|
|
13
|
+
export declare const KG_SERVICE_PUBLISHED_TAG = "ghcr.io/pleri/olam-kg-service:latest";
|
|
14
|
+
export declare const KG_SERVICE_DEV_TAG = "olam-kg-service:dev";
|
|
15
|
+
export declare const KG_SERVICE_HEALTH_URL = "http://127.0.0.1:9997/health";
|
|
16
|
+
export declare const KG_SERVICE_CLASSIFY_URL = "http://127.0.0.1:9997/classify";
|
|
17
|
+
export declare const KG_SERVICE_HEALTH_TIMEOUT_MS = 60000;
|
|
18
|
+
type ContainerState = 'running' | 'stopped' | 'missing';
|
|
19
|
+
export interface KgServiceStatus {
|
|
20
|
+
readonly state: ContainerState;
|
|
21
|
+
readonly port: number;
|
|
22
|
+
readonly containerId?: string;
|
|
23
|
+
readonly ready?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare class KgServiceContainerController {
|
|
26
|
+
private imageTag;
|
|
27
|
+
status(): KgServiceStatus;
|
|
28
|
+
private imageExists;
|
|
29
|
+
/**
|
|
30
|
+
* Resolve the first available image tag: local → dev → published.
|
|
31
|
+
* Throws if none exist (operator should run `olam bootstrap` to pull).
|
|
32
|
+
*/
|
|
33
|
+
private resolveImage;
|
|
34
|
+
/**
|
|
35
|
+
* Idempotent start. If already running → return. If stopped → docker start.
|
|
36
|
+
* If missing → docker run with port-forward + kg-data volume mount + restart
|
|
37
|
+
* policy. The container's CMD is `python -u /app/src/server.py` which begins
|
|
38
|
+
* loading bge-small immediately; the model is warm by the time /health
|
|
39
|
+
* returns ready=true. We additionally fire a synthetic /classify after
|
|
40
|
+
* readiness to JIT-warm the embedding hot path.
|
|
41
|
+
*/
|
|
42
|
+
start(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Returns true when no kg-service image exists locally — useful for callers
|
|
45
|
+
* (e.g. servicesUp) to distinguish "operator opted out of kg-service" from
|
|
46
|
+
* "kg-service was supposed to work but is broken". The opted-out case
|
|
47
|
+
* should be silent; the broken case should warn.
|
|
48
|
+
*/
|
|
49
|
+
imageMissingEverywhere(): boolean;
|
|
50
|
+
stop(): void;
|
|
51
|
+
remove(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Poll /health until ready=true OR timeoutMs elapses. The container reports
|
|
54
|
+
* ready=true only after the bge-small model + 31 exemplars have loaded
|
|
55
|
+
* (~1.3s on a warm machine; longer on first pull where the image needs to
|
|
56
|
+
* unpack).
|
|
57
|
+
*/
|
|
58
|
+
waitForReady(timeoutMs?: number): Promise<boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* Fire a synthetic classify against the warm server. Called by `servicesUp`
|
|
61
|
+
* after `waitForReady` succeeds — extra insurance that the embedding
|
|
62
|
+
* inference hot path is JITted before the first operator-driven call.
|
|
63
|
+
* Errors are swallowed; pre-warm is best-effort.
|
|
64
|
+
*/
|
|
65
|
+
prewarm(): Promise<void>;
|
|
66
|
+
}
|
|
67
|
+
export {};
|
|
68
|
+
//# sourceMappingURL=kg-service-container.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kg-service-container.d.ts","sourceRoot":"","sources":["../../src/commands/kg-service-container.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,eAAO,MAAM,eAAe,OAAO,CAAC;AACpC,eAAO,MAAM,oBAAoB,oBAAoB,CAAC;AACtD,eAAO,MAAM,oBAAoB,0BAA0B,CAAC;AAC5D,eAAO,MAAM,wBAAwB,yCAAyC,CAAC;AAC/E,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AACxD,eAAO,MAAM,qBAAqB,iCAA+C,CAAC;AAClF,eAAO,MAAM,uBAAuB,mCAAiD,CAAC;AAMtF,eAAO,MAAM,4BAA4B,QAAS,CAAC;AAMnD,KAAK,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAoBD,qBAAa,4BAA4B;IACvC,OAAO,CAAC,QAAQ,CAAgC;IAEhD,MAAM,IAAI,eAAe;IAiBzB,OAAO,CAAC,WAAW;IAInB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAUpB;;;;;;;OAOG;IACH,KAAK,IAAI,IAAI;IAsCb;;;;;OAKG;IACH,sBAAsB,IAAI,OAAO;IAQjC,IAAI,IAAI,IAAI;IAMZ,MAAM,IAAI,IAAI;IAId;;;;;OAKG;IACG,YAAY,CAAC,SAAS,SAA+B,GAAG,OAAO,CAAC,OAAO,CAAC;IAiB9E;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAY/B"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KgServiceContainerController — lifecycle for olam-kg-service.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors McpAuthContainerController (./services.ts) since kg-service, like
|
|
5
|
+
* mcp-auth-service, is not a @olam/core package. The persistent HTTP classifier
|
|
6
|
+
* inside the container holds bge-small-en-v1.5 in memory; we pre-warm at
|
|
7
|
+
* start() to eliminate the first-call cold cliff (see Phase A latency bench at
|
|
8
|
+
* ~/kg-benchmark/kg-service-poc/latency-results.json).
|
|
9
|
+
*/
|
|
10
|
+
import { execFileSync, spawnSync } from 'node:child_process';
|
|
11
|
+
import * as fs from 'node:fs';
|
|
12
|
+
import { KG_PATHS_INTERNALS } from '@olam/core/src/kg/storage-paths.js';
|
|
13
|
+
export const KG_SERVICE_PORT = 9997;
|
|
14
|
+
export const KG_SERVICE_CONTAINER = 'olam-kg-service';
|
|
15
|
+
export const KG_SERVICE_LOCAL_TAG = 'olam-kg-service:local';
|
|
16
|
+
export const KG_SERVICE_PUBLISHED_TAG = 'ghcr.io/pleri/olam-kg-service:latest';
|
|
17
|
+
export const KG_SERVICE_DEV_TAG = 'olam-kg-service:dev';
|
|
18
|
+
export const KG_SERVICE_HEALTH_URL = `http://127.0.0.1:${KG_SERVICE_PORT}/health`;
|
|
19
|
+
export const KG_SERVICE_CLASSIFY_URL = `http://127.0.0.1:${KG_SERVICE_PORT}/classify`;
|
|
20
|
+
// Cold-start path measured at ~1.3s (bge-small load + warmup probe). On flaky
|
|
21
|
+
// CI runners with no Docker layer cache we've seen 60s+; mirror McpAuth's
|
|
22
|
+
// 60s timeout so the failure mode is the same operator-visible "took too long"
|
|
23
|
+
// rather than spurious flake.
|
|
24
|
+
export const KG_SERVICE_HEALTH_TIMEOUT_MS = 60_000;
|
|
25
|
+
// kg-data is the host-mounted `~/.olam/kg/` so the container's /build can
|
|
26
|
+
// write graphs back to the operator's pristine workspace KG store.
|
|
27
|
+
const KG_SERVICE_VOLUME_TARGET = '/kg-data';
|
|
28
|
+
/**
|
|
29
|
+
* Resolves the operator's KG storage root for the host bind-mount.
|
|
30
|
+
*
|
|
31
|
+
* Consumes `KG_PATHS_INTERNALS.kgRoot()` from @olam/core/src/kg/storage-paths.js
|
|
32
|
+
* so this controller honours OLAM_HOME redirection (tests, per-world
|
|
33
|
+
* overrides). Naively reading $HOME would cause split-brain: kg-service's
|
|
34
|
+
* /build endpoint would write to ~/.olam/kg while host-side `olam kg
|
|
35
|
+
* status` (which DOES consult OLAM_HOME via kgPristinePath) reports the
|
|
36
|
+
* KG as missing.
|
|
37
|
+
*
|
|
38
|
+
* Caller is responsible for ensuring the directory exists pre-bind-mount
|
|
39
|
+
* (Linux dockerd auto-creates as root:root if absent, which breaks
|
|
40
|
+
* subsequent host-side writes from the operator's UID).
|
|
41
|
+
*/
|
|
42
|
+
function kgDataHostPath() {
|
|
43
|
+
return KG_PATHS_INTERNALS.kgRoot();
|
|
44
|
+
}
|
|
45
|
+
export class KgServiceContainerController {
|
|
46
|
+
imageTag = KG_SERVICE_LOCAL_TAG;
|
|
47
|
+
status() {
|
|
48
|
+
const r = spawnSync('docker', ['inspect', '--format', '{{.State.Status}}|{{.Id}}', KG_SERVICE_CONTAINER], { encoding: 'utf-8' });
|
|
49
|
+
if (r.status === 0) {
|
|
50
|
+
const [stateRaw, id] = r.stdout.trim().split('|');
|
|
51
|
+
return {
|
|
52
|
+
state: stateRaw === 'running' ? 'running' : 'stopped',
|
|
53
|
+
port: KG_SERVICE_PORT,
|
|
54
|
+
containerId: id,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return { state: 'missing', port: KG_SERVICE_PORT };
|
|
58
|
+
}
|
|
59
|
+
imageExists(tag = this.imageTag) {
|
|
60
|
+
return spawnSync('docker', ['image', 'inspect', tag], { encoding: 'utf-8' }).status === 0;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Resolve the first available image tag: local → dev → published.
|
|
64
|
+
* Throws if none exist (operator should run `olam bootstrap` to pull).
|
|
65
|
+
*/
|
|
66
|
+
resolveImage() {
|
|
67
|
+
for (const tag of [KG_SERVICE_LOCAL_TAG, KG_SERVICE_DEV_TAG, KG_SERVICE_PUBLISHED_TAG]) {
|
|
68
|
+
if (this.imageExists(tag))
|
|
69
|
+
return tag;
|
|
70
|
+
}
|
|
71
|
+
throw new Error(`kg-service image not found. Tried: ${KG_SERVICE_LOCAL_TAG}, ${KG_SERVICE_DEV_TAG}, ${KG_SERVICE_PUBLISHED_TAG}. ` +
|
|
72
|
+
'Run `olam bootstrap` to pull the published image, or `npm --workspace @olam/kg-service run build` to build locally.');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Idempotent start. If already running → return. If stopped → docker start.
|
|
76
|
+
* If missing → docker run with port-forward + kg-data volume mount + restart
|
|
77
|
+
* policy. The container's CMD is `python -u /app/src/server.py` which begins
|
|
78
|
+
* loading bge-small immediately; the model is warm by the time /health
|
|
79
|
+
* returns ready=true. We additionally fire a synthetic /classify after
|
|
80
|
+
* readiness to JIT-warm the embedding hot path.
|
|
81
|
+
*/
|
|
82
|
+
start() {
|
|
83
|
+
const current = this.status();
|
|
84
|
+
if (current.state === 'running')
|
|
85
|
+
return;
|
|
86
|
+
if (current.state === 'stopped') {
|
|
87
|
+
execFileSync('docker', ['start', KG_SERVICE_CONTAINER], { stdio: 'pipe' });
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this.imageTag = this.resolveImage();
|
|
91
|
+
const kgData = kgDataHostPath();
|
|
92
|
+
// Pre-create the host path with the operator's UID. Without this,
|
|
93
|
+
// dockerd on Linux auto-creates the bind-mount target as root:root,
|
|
94
|
+
// which breaks subsequent host-side `olam kg build` writes from the
|
|
95
|
+
// operator's UID (EACCES). macOS Docker Desktop's user-mapped binds
|
|
96
|
+
// don't bite here but the explicit mkdir is portable + cheap.
|
|
97
|
+
fs.mkdirSync(kgData, { recursive: true });
|
|
98
|
+
execFileSync('docker', [
|
|
99
|
+
'run',
|
|
100
|
+
'--detach',
|
|
101
|
+
'--name', KG_SERVICE_CONTAINER,
|
|
102
|
+
'--restart', 'unless-stopped',
|
|
103
|
+
// Bind to 127.0.0.1 ONLY at the host port level — local-only by design.
|
|
104
|
+
'--publish', `127.0.0.1:${KG_SERVICE_PORT}:${KG_SERVICE_PORT}`,
|
|
105
|
+
// host-gateway lets this container reach the host (e.g. for diagnostic
|
|
106
|
+
// probes). Worlds reach kg-service via the published 127.0.0.1:9997
|
|
107
|
+
// PLUS their OWN --add-host flag configured in the world-create code path.
|
|
108
|
+
'--add-host', 'host.docker.internal:host-gateway',
|
|
109
|
+
// Mount the operator's KG root (OLAM_HOME-aware) so /build can persist graphs.
|
|
110
|
+
'--volume', `${kgData}:${KG_SERVICE_VOLUME_TARGET}`,
|
|
111
|
+
this.imageTag,
|
|
112
|
+
], { stdio: 'pipe' });
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Returns true when no kg-service image exists locally — useful for callers
|
|
116
|
+
* (e.g. servicesUp) to distinguish "operator opted out of kg-service" from
|
|
117
|
+
* "kg-service was supposed to work but is broken". The opted-out case
|
|
118
|
+
* should be silent; the broken case should warn.
|
|
119
|
+
*/
|
|
120
|
+
imageMissingEverywhere() {
|
|
121
|
+
return (!this.imageExists(KG_SERVICE_LOCAL_TAG) &&
|
|
122
|
+
!this.imageExists(KG_SERVICE_DEV_TAG) &&
|
|
123
|
+
!this.imageExists(KG_SERVICE_PUBLISHED_TAG));
|
|
124
|
+
}
|
|
125
|
+
stop() {
|
|
126
|
+
const current = this.status();
|
|
127
|
+
if (current.state !== 'running')
|
|
128
|
+
return;
|
|
129
|
+
execFileSync('docker', ['stop', KG_SERVICE_CONTAINER], { stdio: 'pipe' });
|
|
130
|
+
}
|
|
131
|
+
remove() {
|
|
132
|
+
spawnSync('docker', ['rm', '-f', KG_SERVICE_CONTAINER], { stdio: 'pipe' });
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Poll /health until ready=true OR timeoutMs elapses. The container reports
|
|
136
|
+
* ready=true only after the bge-small model + 31 exemplars have loaded
|
|
137
|
+
* (~1.3s on a warm machine; longer on first pull where the image needs to
|
|
138
|
+
* unpack).
|
|
139
|
+
*/
|
|
140
|
+
async waitForReady(timeoutMs = KG_SERVICE_HEALTH_TIMEOUT_MS) {
|
|
141
|
+
const deadline = Date.now() + timeoutMs;
|
|
142
|
+
while (Date.now() < deadline) {
|
|
143
|
+
try {
|
|
144
|
+
const res = await fetch(KG_SERVICE_HEALTH_URL, { signal: AbortSignal.timeout(1_500) });
|
|
145
|
+
if (res.ok) {
|
|
146
|
+
const body = (await res.json());
|
|
147
|
+
if (body.ready === true)
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// not ready yet
|
|
153
|
+
}
|
|
154
|
+
await sleep(500);
|
|
155
|
+
}
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Fire a synthetic classify against the warm server. Called by `servicesUp`
|
|
160
|
+
* after `waitForReady` succeeds — extra insurance that the embedding
|
|
161
|
+
* inference hot path is JITted before the first operator-driven call.
|
|
162
|
+
* Errors are swallowed; pre-warm is best-effort.
|
|
163
|
+
*/
|
|
164
|
+
async prewarm() {
|
|
165
|
+
try {
|
|
166
|
+
await fetch(KG_SERVICE_CLASSIFY_URL, {
|
|
167
|
+
method: 'POST',
|
|
168
|
+
headers: { 'Content-Type': 'application/json' },
|
|
169
|
+
body: JSON.stringify({ q: 'prewarm probe' }),
|
|
170
|
+
signal: AbortSignal.timeout(5_000),
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
// best-effort
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function sleep(ms) {
|
|
179
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=kg-service-container.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kg-service-container.js","sourceRoot":"","sources":["../../src/commands/kg-service-container.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `olam kg uninstall-hook [--scope project|user]` — surgical removal of the
|
|
3
|
+
* kg-service PreToolUse hook from .claude/settings.json.
|
|
4
|
+
*
|
|
5
|
+
* Matches by sentinel — only removes hook entries whose command contains
|
|
6
|
+
* KG_HOOK_SENTINEL. Other PreToolUse entries (e.g. operator-installed
|
|
7
|
+
* custom hooks) are left intact. Idempotent: running on a non-installed
|
|
8
|
+
* file is a no-op.
|
|
9
|
+
*/
|
|
10
|
+
import type { Command } from 'commander';
|
|
11
|
+
export declare function registerKgUninstallHookCommand(kg: Command): void;
|
|
12
|
+
//# sourceMappingURL=kg-uninstall-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kg-uninstall-hook.d.ts","sourceRoot":"","sources":["../../src/commands/kg-uninstall-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiEzC,wBAAgB,8BAA8B,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAsEhE"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `olam kg uninstall-hook [--scope project|user]` — surgical removal of the
|
|
3
|
+
* kg-service PreToolUse hook from .claude/settings.json.
|
|
4
|
+
*
|
|
5
|
+
* Matches by sentinel — only removes hook entries whose command contains
|
|
6
|
+
* KG_HOOK_SENTINEL. Other PreToolUse entries (e.g. operator-installed
|
|
7
|
+
* custom hooks) are left intact. Idempotent: running on a non-installed
|
|
8
|
+
* file is a no-op.
|
|
9
|
+
*/
|
|
10
|
+
import * as fs from 'node:fs';
|
|
11
|
+
import * as path from 'node:path';
|
|
12
|
+
import * as os from 'node:os';
|
|
13
|
+
import { KG_HOOK_SENTINEL } from '@olam/core/src/kg/hook-template.js';
|
|
14
|
+
import { printError, printInfo, printSuccess } from '../output.js';
|
|
15
|
+
function settingsPathFor(scope) {
|
|
16
|
+
if (scope === 'user') {
|
|
17
|
+
return path.join(os.homedir(), '.claude', 'settings.json');
|
|
18
|
+
}
|
|
19
|
+
return path.join(process.cwd(), '.claude', 'settings.json');
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Walk a PreToolUse matcher array and drop:
|
|
23
|
+
* - inner hook entries whose `command` contains the sentinel
|
|
24
|
+
* - outer matcher entries left empty after the inner-drop
|
|
25
|
+
* Returns the filtered array + a boolean "did anything change".
|
|
26
|
+
*/
|
|
27
|
+
function dropSentinel(matchers) {
|
|
28
|
+
let changed = false;
|
|
29
|
+
const out = [];
|
|
30
|
+
for (const matcher of matchers) {
|
|
31
|
+
const innerHooks = matcher.hooks ?? [];
|
|
32
|
+
const keptInner = innerHooks.filter((h) => {
|
|
33
|
+
if (typeof h.command === 'string' && h.command.includes(KG_HOOK_SENTINEL)) {
|
|
34
|
+
changed = true;
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
38
|
+
});
|
|
39
|
+
if (keptInner.length === 0 && innerHooks.length > 0) {
|
|
40
|
+
// The matcher had hooks but they were all kg-service; drop the matcher entirely.
|
|
41
|
+
changed = true;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (keptInner.length === innerHooks.length) {
|
|
45
|
+
out.push(matcher);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
out.push({ ...matcher, hooks: keptInner });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return { matchers: out, changed };
|
|
52
|
+
}
|
|
53
|
+
export function registerKgUninstallHookCommand(kg) {
|
|
54
|
+
kg.command('uninstall-hook')
|
|
55
|
+
.description('Remove kg-service PreToolUse hook from .claude/settings.json (sentinel-matched; surgical)')
|
|
56
|
+
.option('--scope <scope>', 'project (default) or user', 'project')
|
|
57
|
+
.action((opts) => {
|
|
58
|
+
const scope = opts.scope === 'user' ? 'user' : 'project';
|
|
59
|
+
const filePath = settingsPathFor(scope);
|
|
60
|
+
if (!fs.existsSync(filePath)) {
|
|
61
|
+
printInfo('kg-service hook', `no settings.json at ${filePath} — nothing to remove`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
let settings;
|
|
65
|
+
try {
|
|
66
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
67
|
+
settings = raw.trim() ? JSON.parse(raw) : {};
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
printError(`could not parse ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
71
|
+
process.exitCode = 1;
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const preToolUse = settings.hooks?.PreToolUse;
|
|
75
|
+
if (!Array.isArray(preToolUse) || preToolUse.length === 0) {
|
|
76
|
+
printInfo('kg-service hook', `no PreToolUse hooks at ${filePath} — nothing to remove`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const { matchers, changed } = dropSentinel(preToolUse);
|
|
80
|
+
if (!changed) {
|
|
81
|
+
printInfo('kg-service hook', `not found in ${filePath} — already uninstalled`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// Back up before writing the filtered result.
|
|
85
|
+
const ts = new Date().toISOString().replace(/[:.]/g, '-');
|
|
86
|
+
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
87
|
+
try {
|
|
88
|
+
fs.copyFileSync(filePath, backupPath);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// best-effort backup
|
|
92
|
+
}
|
|
93
|
+
const next = {
|
|
94
|
+
...settings,
|
|
95
|
+
hooks: {
|
|
96
|
+
...settings.hooks,
|
|
97
|
+
PreToolUse: matchers,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
// If PreToolUse is now empty AND there are no other hook stages, drop the key entirely.
|
|
101
|
+
if (matchers.length === 0) {
|
|
102
|
+
const otherStages = Object.keys(next.hooks ?? {}).filter((k) => k !== 'PreToolUse');
|
|
103
|
+
if (otherStages.length === 0) {
|
|
104
|
+
delete next.hooks;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
delete next.hooks.PreToolUse;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
fs.writeFileSync(filePath, JSON.stringify(next, null, 2) + '\n');
|
|
112
|
+
printSuccess(`kg-service hook removed from ${filePath}`);
|
|
113
|
+
printInfo('backup', backupPath);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
printError(`could not write ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
117
|
+
process.exitCode = 1;
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=kg-uninstall-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kg-uninstall-hook.js","sourceRoot":"","sources":["../../src/commands/kg-uninstall-hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/memory/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/memory/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAerD"}
|
|
@@ -19,6 +19,7 @@ import { registerMemoryLogs } from './logs.js';
|
|
|
19
19
|
import { registerMemorySecret } from './secret.js';
|
|
20
20
|
import { registerMemoryInstall } from './install.js';
|
|
21
21
|
import { registerMemoryUninstall } from './uninstall.js';
|
|
22
|
+
import { registerMemoryMode } from './mode.js';
|
|
22
23
|
export function registerMemory(program) {
|
|
23
24
|
const memory = program
|
|
24
25
|
.command('memory')
|
|
@@ -30,5 +31,6 @@ export function registerMemory(program) {
|
|
|
30
31
|
registerMemorySecret(memory);
|
|
31
32
|
registerMemoryInstall(memory);
|
|
32
33
|
registerMemoryUninstall(memory);
|
|
34
|
+
registerMemoryMode(memory);
|
|
33
35
|
}
|
|
34
36
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/memory/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/memory/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,MAAM,MAAM,GAAG,OAAO;SACnB,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CACV,8GAA8G,CAC/G,CAAC;IAEJ,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* olam memory mode <local|cloud> — flip the workspace's agent-memory
|
|
3
|
+
* source between the host-process (Phase A) and a remote agentmemory
|
|
4
|
+
* deployment (Phase C).
|
|
5
|
+
*
|
|
6
|
+
* Reads + rewrites `.olam/config.yaml`'s `memory:` block via the schema
|
|
7
|
+
* defined in C1. Idempotent: re-running the same mode is a noop.
|
|
8
|
+
*
|
|
9
|
+
* mode local → memory.mode = "local"; ensures host-process running
|
|
10
|
+
* mode cloud [--url ...] → prompts for URL + bearer secret, writes both to
|
|
11
|
+
* config + ~/.olam/cloud-memory-secret, stops the
|
|
12
|
+
* local host-process. Operator must re-create
|
|
13
|
+
* active worlds for the new env to take effect.
|
|
14
|
+
*
|
|
15
|
+
* Plan reference: docs/plans/olam-agent-memory-distributed/phase-c-tasks.md C3
|
|
16
|
+
*/
|
|
17
|
+
import type { Command } from 'commander';
|
|
18
|
+
/** Test seam: prompts + IO injection. */
|
|
19
|
+
export interface ModeDeps {
|
|
20
|
+
readonly cwd?: string;
|
|
21
|
+
/** Returns a string (or null on EOF). Defaults to readline.question. */
|
|
22
|
+
readonly promptText?: (q: string) => Promise<string>;
|
|
23
|
+
/** Returns the bearer secret. Default: readline (NOT echoed by terminal). */
|
|
24
|
+
readonly promptSecret?: (q: string) => Promise<string>;
|
|
25
|
+
/** Default: writeCloudMemorySecret. Lets tests redirect to a tmpdir. */
|
|
26
|
+
readonly writeSecret?: (value: string) => void;
|
|
27
|
+
/** Bypass interactive prompts. */
|
|
28
|
+
readonly url?: string;
|
|
29
|
+
/** Bypass interactive prompts. */
|
|
30
|
+
readonly secret?: string;
|
|
31
|
+
/** Test seam: replace start/stop invocations. */
|
|
32
|
+
readonly runStart?: () => Promise<number>;
|
|
33
|
+
readonly runStop?: () => Promise<number>;
|
|
34
|
+
}
|
|
35
|
+
export type ModeOutcome = {
|
|
36
|
+
outcome: 'noop';
|
|
37
|
+
mode: 'local' | 'cloud';
|
|
38
|
+
} | {
|
|
39
|
+
outcome: 'flipped-to-local';
|
|
40
|
+
} | {
|
|
41
|
+
outcome: 'flipped-to-cloud';
|
|
42
|
+
url: string;
|
|
43
|
+
};
|
|
44
|
+
export declare function runMemoryModeLocal(deps?: ModeDeps): Promise<ModeOutcome>;
|
|
45
|
+
export declare function runMemoryModeCloud(deps?: ModeDeps): Promise<ModeOutcome>;
|
|
46
|
+
export declare function registerMemoryMode(cmd: Command): void;
|
|
47
|
+
//# sourceMappingURL=mode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mode.d.ts","sourceRoot":"","sources":["../../../src/commands/memory/mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,yCAAyC;AACzC,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,6EAA6E;IAC7E,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,wEAAwE;IACxE,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,kCAAkC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1C;AAoDD,MAAM,MAAM,WAAW,GACnB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;CAAE,GAC5C;IAAE,OAAO,EAAE,kBAAkB,CAAA;CAAE,GAC/B;IAAE,OAAO,EAAE,kBAAkB,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,wBAAsB,kBAAkB,CAAC,IAAI,GAAE,QAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CA0BlF;AAED,wBAAsB,kBAAkB,CAAC,IAAI,GAAE,QAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CA2ElF;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CA+BrD"}
|