@gralkor/openclaw 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/.env.example +32 -0
  2. package/README.md +77 -0
  3. package/config.yaml +16 -0
  4. package/dist/config.d.ts +33 -0
  5. package/dist/config.d.ts.map +1 -0
  6. package/dist/config.js +49 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/ctx-to-messages.d.ts +36 -0
  9. package/dist/ctx-to-messages.d.ts.map +1 -0
  10. package/dist/ctx-to-messages.js +120 -0
  11. package/dist/ctx-to-messages.js.map +1 -0
  12. package/dist/ctx-to-turn.d.ts +32 -0
  13. package/dist/ctx-to-turn.d.ts.map +1 -0
  14. package/dist/ctx-to-turn.js +55 -0
  15. package/dist/ctx-to-turn.js.map +1 -0
  16. package/dist/gralkor/client/http.d.ts +55 -0
  17. package/dist/gralkor/client/http.d.ts.map +1 -0
  18. package/dist/gralkor/client/http.js +150 -0
  19. package/dist/gralkor/client/http.js.map +1 -0
  20. package/dist/gralkor/client/in-memory.d.ts +38 -0
  21. package/dist/gralkor/client/in-memory.d.ts.map +1 -0
  22. package/dist/gralkor/client/in-memory.js +72 -0
  23. package/dist/gralkor/client/in-memory.js.map +1 -0
  24. package/dist/gralkor/client.d.ts +64 -0
  25. package/dist/gralkor/client.d.ts.map +1 -0
  26. package/dist/gralkor/client.js +32 -0
  27. package/dist/gralkor/client.js.map +1 -0
  28. package/dist/gralkor/config.d.ts +33 -0
  29. package/dist/gralkor/config.d.ts.map +1 -0
  30. package/dist/gralkor/config.js +58 -0
  31. package/dist/gralkor/config.js.map +1 -0
  32. package/dist/gralkor/connection.d.ts +20 -0
  33. package/dist/gralkor/connection.d.ts.map +1 -0
  34. package/dist/gralkor/connection.js +31 -0
  35. package/dist/gralkor/connection.js.map +1 -0
  36. package/dist/gralkor/index.d.ts +11 -0
  37. package/dist/gralkor/index.d.ts.map +1 -0
  38. package/dist/gralkor/index.js +6 -0
  39. package/dist/gralkor/index.js.map +1 -0
  40. package/dist/gralkor/server-env.d.ts +11 -0
  41. package/dist/gralkor/server-env.d.ts.map +1 -0
  42. package/dist/gralkor/server-env.js +26 -0
  43. package/dist/gralkor/server-env.js.map +1 -0
  44. package/dist/gralkor/server-manager.d.ts +58 -0
  45. package/dist/gralkor/server-manager.d.ts.map +1 -0
  46. package/dist/gralkor/server-manager.js +390 -0
  47. package/dist/gralkor/server-manager.js.map +1 -0
  48. package/dist/gralkor/testing.d.ts +10 -0
  49. package/dist/gralkor/testing.d.ts.map +1 -0
  50. package/dist/gralkor/testing.js +10 -0
  51. package/dist/gralkor/testing.js.map +1 -0
  52. package/dist/hooks/agent-end.d.ts +25 -0
  53. package/dist/hooks/agent-end.d.ts.map +1 -0
  54. package/dist/hooks/agent-end.js +51 -0
  55. package/dist/hooks/agent-end.js.map +1 -0
  56. package/dist/hooks/before-prompt-build.d.ts +12 -0
  57. package/dist/hooks/before-prompt-build.d.ts.map +1 -0
  58. package/dist/hooks/before-prompt-build.js +15 -0
  59. package/dist/hooks/before-prompt-build.js.map +1 -0
  60. package/dist/hooks/session-end.d.ts +18 -0
  61. package/dist/hooks/session-end.d.ts.map +1 -0
  62. package/dist/hooks/session-end.js +19 -0
  63. package/dist/hooks/session-end.js.map +1 -0
  64. package/dist/index.d.ts +130 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +133 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/native-indexer.d.ts +43 -0
  69. package/dist/native-indexer.d.ts.map +1 -0
  70. package/dist/native-indexer.js +107 -0
  71. package/dist/native-indexer.js.map +1 -0
  72. package/dist/register.d.ts +25 -0
  73. package/dist/register.d.ts.map +1 -0
  74. package/dist/register.js +184 -0
  75. package/dist/register.js.map +1 -0
  76. package/dist/session-map.d.ts +13 -0
  77. package/dist/session-map.d.ts.map +1 -0
  78. package/dist/session-map.js +32 -0
  79. package/dist/session-map.js.map +1 -0
  80. package/dist/tools/memory-add.d.ts +15 -0
  81. package/dist/tools/memory-add.d.ts.map +1 -0
  82. package/dist/tools/memory-add.js +15 -0
  83. package/dist/tools/memory-add.js.map +1 -0
  84. package/dist/tools/memory-build-communities.d.ts +19 -0
  85. package/dist/tools/memory-build-communities.d.ts.map +1 -0
  86. package/dist/tools/memory-build-communities.js +18 -0
  87. package/dist/tools/memory-build-communities.js.map +1 -0
  88. package/dist/tools/memory-build-indices.d.ts +12 -0
  89. package/dist/tools/memory-build-indices.d.ts.map +1 -0
  90. package/dist/tools/memory-build-indices.js +11 -0
  91. package/dist/tools/memory-build-indices.js.map +1 -0
  92. package/dist/tools/memory-search.d.ts +20 -0
  93. package/dist/tools/memory-search.d.ts.map +1 -0
  94. package/dist/tools/memory-search.js +18 -0
  95. package/dist/tools/memory-search.js.map +1 -0
  96. package/dist/types.d.ts +62 -0
  97. package/dist/types.d.ts.map +1 -0
  98. package/dist/types.js +8 -0
  99. package/dist/types.js.map +1 -0
  100. package/openclaw.plugin.json +130 -0
  101. package/package.json +75 -0
  102. package/server/server/.python-version +1 -0
  103. package/server/server/main.py +902 -0
  104. package/server/server/pipelines/__init__.py +0 -0
  105. package/server/server/pipelines/capture_buffer.py +170 -0
  106. package/server/server/pipelines/distill.py +122 -0
  107. package/server/server/pipelines/formatting.py +48 -0
  108. package/server/server/pipelines/interpret.py +165 -0
  109. package/server/server/pipelines/messages.py +13 -0
  110. package/server/server/pyproject.toml +19 -0
  111. package/server/server/pytest.ini +4 -0
  112. package/server/server/requirements-dev.txt +3 -0
  113. package/server/server/requirements.txt +5 -0
  114. package/server/server/uv.lock +1162 -0
  115. package/server/wheels/falkordblite-0.9.0-py3-none-manylinux_2_36_aarch64.whl +0 -0
@@ -0,0 +1,58 @@
1
+ import type { ModelConfig, OntologyConfig } from "./config.js";
2
+ /**
3
+ * Path to the Python server source bundled with this package. Resolves at
4
+ * runtime relative to this module's compiled location — at publish time the
5
+ * server is copied into `<pkg>/server/` by `scripts/bundle-server.mjs`, and
6
+ * this module ends up at `<pkg>/dist/server-manager.js`, so `../server`
7
+ * resolves to the bundled directory. Mirrors the Elixir side's
8
+ * `:code.priv_dir(:gralkor_ex) ++ "/server"`.
9
+ */
10
+ export declare function bundledServerDir(): string;
11
+ export interface ServerManagerOptions {
12
+ dataDir: string;
13
+ /**
14
+ * Path to the Python server directory. Defaults to the bundled copy
15
+ * that ships inside this npm package. Override if you want to point
16
+ * at a development checkout of `gralkor/server/`.
17
+ */
18
+ serverDir?: string;
19
+ port: number;
20
+ /** Plugin version — used to fetch the arm64 wheel from GitHub Releases when not bundled. */
21
+ version: string;
22
+ /**
23
+ * GitHub repo (`owner/name`) that hosts the prebuilt `falkordblite` wheel as a release asset.
24
+ * Used on linux/arm64 only; the URL is `https://github.com/${wheelRepo}/releases/download/v${version}/<wheel>`.
25
+ * The consumer is the publisher (the one whose CI uploads the wheel via `gh release upload`),
26
+ * so the consumer must tell us where it published — there is no defensible default here.
27
+ */
28
+ wheelRepo: string;
29
+ env?: Record<string, string>;
30
+ secretEnv?: Record<string, string>;
31
+ llmConfig?: ModelConfig;
32
+ embedderConfig?: ModelConfig;
33
+ ontologyConfig?: OntologyConfig;
34
+ test?: boolean;
35
+ }
36
+ export declare function wheelDownloadUrl(wheelRepo: string, version: string): string;
37
+ export interface ServerManager {
38
+ start(): Promise<void>;
39
+ stop(): Promise<void>;
40
+ isRunning(): boolean;
41
+ }
42
+ export declare function createServerManager(opts: ServerManagerOptions): ServerManager;
43
+ /**
44
+ * Build the `config.yaml` contents for the Python server.
45
+ *
46
+ * Sections are emitted only when the consumer passes that piece of config.
47
+ * When `llmConfig` / `embedderConfig` are omitted, the corresponding blocks
48
+ * are absent from the YAML and the server falls back to its own defaults in
49
+ * `server/main.py` — the single source of truth for model choice.
50
+ */
51
+ export declare function buildConfigYaml(opts: {
52
+ llmConfig?: ModelConfig;
53
+ embedderConfig?: ModelConfig;
54
+ ontologyConfig?: OntologyConfig;
55
+ test?: boolean;
56
+ }): string;
57
+ export declare function serializeOntologyYaml(ontology: OntologyConfig): string;
58
+ //# sourceMappingURL=server-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-manager.d.ts","sourceRoot":"","sources":["../../src/gralkor/server-manager.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAA0B,MAAM,aAAa,CAAC;AAevF;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,4FAA4F;IAC5F,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAMD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,SAAS,IAAI,OAAO,CAAC;CACtB;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,GAAG,aAAa,CA+L7E;AAOD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GAAG,MAAM,CAQT;AAkDD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAwBtE"}
@@ -0,0 +1,390 @@
1
+ import { execFile, spawn } from "node:child_process";
2
+ import { existsSync, readdirSync } from "node:fs";
3
+ import { mkdir, writeFile } from "node:fs/promises";
4
+ import { join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { promisify } from "node:util";
7
+ import { buildSyncEnv, buildPipEnv, buildSpawnEnv } from "./server-env.js";
8
+ const execFileAsync = promisify(execFile);
9
+ const HEALTH_POLL_INTERVAL_MS = 500;
10
+ const HEALTH_TIMEOUT_MS = 120_000;
11
+ const STOP_GRACE_MS = 5_000;
12
+ // OTP default — 3 restarts in 5s; the 4th unexpected exit inside the window
13
+ // escalates by exiting the Node process so the next-level supervisor (Docker
14
+ // restart: unless-stopped in agents/) takes over.
15
+ const RESTART_INTENSITY_LIMIT = 3;
16
+ const RESTART_INTENSITY_WINDOW_MS = 5_000;
17
+ /**
18
+ * Path to the Python server source bundled with this package. Resolves at
19
+ * runtime relative to this module's compiled location — at publish time the
20
+ * server is copied into `<pkg>/server/` by `scripts/bundle-server.mjs`, and
21
+ * this module ends up at `<pkg>/dist/server-manager.js`, so `../server`
22
+ * resolves to the bundled directory. Mirrors the Elixir side's
23
+ * `:code.priv_dir(:gralkor_ex) ++ "/server"`.
24
+ */
25
+ export function bundledServerDir() {
26
+ return fileURLToPath(new URL("../server", import.meta.url));
27
+ }
28
+ // Bundled wheel filename — must match the wheel produced by consumer publish scripts
29
+ // (e.g. openclaw_gralkor's scripts/build-arm64-wheel.sh).
30
+ const WHEEL_FILENAME = "falkordblite-0.9.0-py3-none-manylinux_2_36_aarch64.whl";
31
+ export function wheelDownloadUrl(wheelRepo, version) {
32
+ return `https://github.com/${wheelRepo}/releases/download/v${version}/${WHEEL_FILENAME}`;
33
+ }
34
+ export function createServerManager(opts) {
35
+ const serverDir = opts.serverDir ?? bundledServerDir();
36
+ let proc = null;
37
+ let stopping = false;
38
+ const recentUnexpectedExits = [];
39
+ let spawnEnv = null;
40
+ let venvPython = null;
41
+ let startPromise = null;
42
+ function start() {
43
+ return (startPromise ??= doStart());
44
+ }
45
+ async function doStart() {
46
+ const bootStart = Date.now();
47
+ await mkdir(opts.dataDir, { recursive: true });
48
+ console.log("[gralkor] boot: starting...");
49
+ const venvDir = join(opts.dataDir, "venv");
50
+ venvPython = join(venvDir, "bin", "python");
51
+ // Ensure uv is available
52
+ try {
53
+ await execFileAsync("uv", ["--version"]);
54
+ }
55
+ catch {
56
+ throw new Error("uv is required but not found on PATH. " +
57
+ "Install: curl -LsSf https://astral.sh/uv/install.sh | sh");
58
+ }
59
+ // Sync Python environment.
60
+ // Skip falkordblite when a bundled arch-specific wheel is present — the PyPI
61
+ // arm64 wheel requires manylinux_2_39 (glibc 2.39+) but many linux/arm64 hosts
62
+ // run glibc 2.36 (Debian Bookworm), causing uv to fall back to the sdist which
63
+ // embeds x86-64 binaries. The bundled wheel is built for the correct arch.
64
+ // On linux/arm64, PyPI's falkordblite sdist embeds x86-64 binaries on
65
+ // glibc < 2.39 hosts (e.g. Bookworm), so we must install a prebuilt wheel.
66
+ // Look for it bundled in the install (npm path), else download from
67
+ // GitHub Releases (ClawHub path — wheel exceeds ClawHub's 20 MB limit).
68
+ const useBundledWheels = process.platform === "linux" && process.arch === "arm64";
69
+ const bundledWheels = useBundledWheels
70
+ ? await resolveBundledWheels(serverDir, opts.dataDir, opts.wheelRepo, opts.version)
71
+ : [];
72
+ const syncEnv = buildSyncEnv(venvDir);
73
+ const syncArgs = [
74
+ "sync", "--no-dev", "--frozen", "--directory", serverDir,
75
+ ...(bundledWheels.length > 0 ? ["--no-install-package", "falkordblite"] : []),
76
+ ];
77
+ console.log("[gralkor] boot: syncing python env...");
78
+ await execFileAsync("uv", syncArgs, { env: syncEnv, timeout: 300_000 });
79
+ console.log("[gralkor] boot: python env ready");
80
+ // Install bundled wheels — no PyPI fallback, must succeed.
81
+ const pipEnv = buildPipEnv(venvDir);
82
+ for (const wheelPath of bundledWheels) {
83
+ console.log("[gralkor] Installing bundled wheel:", wheelPath);
84
+ await execFileAsync("uv", ["pip", "install", "--no-deps", wheelPath], { env: pipEnv, timeout: 60_000 });
85
+ }
86
+ const configPath = join(opts.dataDir, "config.yaml");
87
+ await writeFile(configPath, buildConfigYaml(opts), "utf-8");
88
+ spawnEnv = buildSpawnEnv({
89
+ extra: opts.env,
90
+ secretEnv: opts.secretEnv,
91
+ falkordbDataDir: join(opts.dataDir, "falkordb"),
92
+ configPath,
93
+ });
94
+ await spawnAndAwaitHealth();
95
+ const bootDuration = ((Date.now() - bootStart) / 1000).toFixed(1);
96
+ console.log(`[gralkor] boot: ready (${bootDuration}s)`);
97
+ }
98
+ async function spawnAndAwaitHealth() {
99
+ if (venvPython === null || spawnEnv === null) {
100
+ throw new Error("[gralkor] spawnAndAwaitHealth called before start() prepared the env");
101
+ }
102
+ // Reap prior-run orphans before claiming the port. Two paths:
103
+ // (1) anything listening on the bind port — our previous uvicorn after a
104
+ // module re-eval, or a crashed sibling
105
+ // (2) any redislite/bin/redis-server grandchild reparented to PID 1 when
106
+ // a previous uvicorn died — the path is unique to falkordblite, so
107
+ // pre-spawn matches are by definition not ours-yet
108
+ await killHoldersOfPort(opts.port);
109
+ await killOrphanRedisServers();
110
+ console.log("[gralkor] Starting Graphiti server on port", opts.port);
111
+ const child = spawn(venvPython, ["-m", "uvicorn", "main:app", "--host", "127.0.0.1", "--port", String(opts.port), "--no-access-log"], {
112
+ cwd: serverDir,
113
+ env: spawnEnv,
114
+ stdio: ["ignore", "pipe", "pipe"],
115
+ });
116
+ proc = child;
117
+ // Forward stdout/stderr
118
+ child.stdout?.on("data", (data) => {
119
+ for (const line of data.toString().split("\n").filter(Boolean)) {
120
+ console.log("[gralkor] [server]", line);
121
+ }
122
+ });
123
+ child.stderr?.on("data", (data) => {
124
+ for (const line of data.toString().split("\n").filter(Boolean)) {
125
+ console.log("[gralkor] [server]", line);
126
+ }
127
+ });
128
+ child.on("error", (err) => {
129
+ console.error("[gralkor] Server process error:", err.message);
130
+ });
131
+ child.on("exit", (code, signal) => {
132
+ console.log("[gralkor] Server process exited — code:", code, "signal:", signal);
133
+ if (proc === child)
134
+ proc = null;
135
+ if (stopping)
136
+ return;
137
+ const now = Date.now();
138
+ while (recentUnexpectedExits.length > 0 && now - recentUnexpectedExits[0] > RESTART_INTENSITY_WINDOW_MS) {
139
+ recentUnexpectedExits.shift();
140
+ }
141
+ recentUnexpectedExits.push(now);
142
+ if (recentUnexpectedExits.length > RESTART_INTENSITY_LIMIT) {
143
+ console.error(`[gralkor] restart intensity exceeded (${recentUnexpectedExits.length} unexpected exits within ${RESTART_INTENSITY_WINDOW_MS}ms) — escalating via process.exit(1)`);
144
+ process.exit(1);
145
+ }
146
+ console.warn(`[gralkor] respawning after unexpected exit (attempt ${recentUnexpectedExits.length} in current ${RESTART_INTENSITY_WINDOW_MS}ms window)`);
147
+ void spawnAndAwaitHealth().catch((err) => {
148
+ console.error("[gralkor] respawn failed:", err instanceof Error ? err.message : err);
149
+ });
150
+ });
151
+ console.log("[gralkor] boot: server process spawned (pid:", child.pid, "), polling health...");
152
+ await waitForHealth(opts.port);
153
+ console.log("[gralkor] boot: server healthy");
154
+ }
155
+ async function stop() {
156
+ stopping = true;
157
+ if (!proc)
158
+ return;
159
+ const child = proc;
160
+ proc = null;
161
+ // Try graceful SIGTERM first
162
+ child.kill("SIGTERM");
163
+ await new Promise((resolve) => {
164
+ const forceKill = setTimeout(() => {
165
+ child.kill("SIGKILL");
166
+ resolve();
167
+ }, STOP_GRACE_MS);
168
+ child.on("exit", () => {
169
+ clearTimeout(forceKill);
170
+ resolve();
171
+ });
172
+ });
173
+ }
174
+ function isRunning() {
175
+ return proc !== null;
176
+ }
177
+ return { start, stop, isRunning };
178
+ }
179
+ function providerSection(key, cfg) {
180
+ if (!cfg)
181
+ return "";
182
+ return `${key}:\n provider: "${cfg.provider}"\n model: "${cfg.model}"`;
183
+ }
184
+ /**
185
+ * Build the `config.yaml` contents for the Python server.
186
+ *
187
+ * Sections are emitted only when the consumer passes that piece of config.
188
+ * When `llmConfig` / `embedderConfig` are omitted, the corresponding blocks
189
+ * are absent from the YAML and the server falls back to its own defaults in
190
+ * `server/main.py` — the single source of truth for model choice.
191
+ */
192
+ export function buildConfigYaml(opts) {
193
+ const sections = [
194
+ providerSection("llm", opts.llmConfig),
195
+ providerSection("embedder", opts.embedderConfig),
196
+ ].filter((s) => s !== "");
197
+ if (opts.test)
198
+ sections.push("test: true");
199
+ if (opts.ontologyConfig)
200
+ sections.push(serializeOntologyYaml(opts.ontologyConfig).trimEnd());
201
+ return sections.length === 0 ? "" : sections.join("\n") + "\n";
202
+ }
203
+ function yamlQuote(s) {
204
+ if (/[:#{}[\]|>&*!%@`]/.test(s) || s !== s.trim()) {
205
+ return `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
206
+ }
207
+ return `"${s}"`;
208
+ }
209
+ function serializeAttrValue(attr, indent) {
210
+ if (typeof attr === "string") {
211
+ return ` ${yamlQuote(attr)}`;
212
+ }
213
+ if (Array.isArray(attr)) {
214
+ return "\n" + attr.map((v) => `${indent} - ${yamlQuote(v)}`).join("\n");
215
+ }
216
+ if ("enum" in attr) {
217
+ const lines = [
218
+ `\n${indent} enum:`,
219
+ ...attr.enum.map((v) => `${indent} - ${yamlQuote(v)}`),
220
+ `${indent} description: ${yamlQuote(attr.description)}`,
221
+ ];
222
+ return lines.join("\n");
223
+ }
224
+ // { type, description }
225
+ return [
226
+ "",
227
+ `${indent} type: ${yamlQuote(attr.type)}`,
228
+ `${indent} description: ${yamlQuote(attr.description)}`,
229
+ ].join("\n");
230
+ }
231
+ function serializeTypeDefs(defs, indent) {
232
+ const lines = [];
233
+ for (const [name, def] of Object.entries(defs)) {
234
+ lines.push(`${indent}${name}:`);
235
+ lines.push(`${indent} description: ${yamlQuote(def.description)}`);
236
+ if (def.attributes && Object.keys(def.attributes).length > 0) {
237
+ lines.push(`${indent} attributes:`);
238
+ for (const [attr, val] of Object.entries(def.attributes)) {
239
+ lines.push(`${indent} ${attr}:${serializeAttrValue(val, `${indent} `)}`);
240
+ }
241
+ }
242
+ }
243
+ return lines;
244
+ }
245
+ export function serializeOntologyYaml(ontology) {
246
+ const lines = ["ontology:"];
247
+ if (ontology.entities && Object.keys(ontology.entities).length > 0) {
248
+ lines.push(" entities:");
249
+ lines.push(...serializeTypeDefs(ontology.entities, " "));
250
+ }
251
+ if (ontology.edges && Object.keys(ontology.edges).length > 0) {
252
+ lines.push(" edges:");
253
+ lines.push(...serializeTypeDefs(ontology.edges, " "));
254
+ }
255
+ if (ontology.edgeMap && Object.keys(ontology.edgeMap).length > 0) {
256
+ lines.push(" edgeMap:");
257
+ for (const [key, values] of Object.entries(ontology.edgeMap)) {
258
+ lines.push(` ${yamlQuote(key)}:`);
259
+ for (const v of values) {
260
+ lines.push(` - ${yamlQuote(v)}`);
261
+ }
262
+ }
263
+ }
264
+ return lines.join("\n") + "\n";
265
+ }
266
+ async function resolveBundledWheels(serverDir, dataDir, wheelRepo, version) {
267
+ const installed = join(serverDir, "wheels");
268
+ if (existsSync(installed)) {
269
+ const files = readdirSync(installed).filter((f) => f.endsWith(".whl"));
270
+ if (files.length > 0)
271
+ return files.map((f) => join(installed, f));
272
+ }
273
+ const dest = join(dataDir, "wheels", WHEEL_FILENAME);
274
+ if (!existsSync(dest)) {
275
+ await mkdir(join(dataDir, "wheels"), { recursive: true });
276
+ const url = wheelDownloadUrl(wheelRepo, version);
277
+ console.log(`[gralkor] boot: downloading wheel ${url}`);
278
+ const res = await fetch(url, { redirect: "follow" });
279
+ if (!res.ok)
280
+ throw new Error(`bundled wheel download failed: HTTP ${res.status} ${url}`);
281
+ await writeFile(dest, Buffer.from(await res.arrayBuffer()));
282
+ }
283
+ return [dest];
284
+ }
285
+ /**
286
+ * Kill any redislite redis-server process left behind by a prior uvicorn
287
+ * incarnation. falkordblite spawns redis-server as a grandchild; when uvicorn
288
+ * dies, the grandchild reparents to PID 1 and keeps holding the data dir,
289
+ * unix socket, and ~80 MB RSS — and would conflict with the next boot.
290
+ *
291
+ * Mirrors :gralkor_ex's `Gralkor.OrphanReaper`. Identification keys on argv
292
+ * substring (`redislite/bin/redis-server`) — the path is unique to falkordblite
293
+ * with no other plausible owner. Safe to nuke unconditionally because this
294
+ * runs before our own spawn, so anything matching is by definition not
295
+ * ours-yet.
296
+ */
297
+ async function killOrphanRedisServers() {
298
+ let stdout;
299
+ try {
300
+ const result = await execFileAsync("pgrep", ["-f", "redislite/bin/redis-server"]);
301
+ stdout = result.stdout;
302
+ }
303
+ catch {
304
+ // pgrep exits non-zero when nothing matches — treat as empty
305
+ return;
306
+ }
307
+ const pids = stdout.split("\n").map(s => Number(s.trim())).filter(n => Number.isInteger(n) && n > 0);
308
+ if (pids.length === 0)
309
+ return;
310
+ console.log(`[gralkor] boot: orphan redislite redis-server pid(s) ${pids.join(",")} — killing`);
311
+ for (const pid of pids) {
312
+ try {
313
+ process.kill(pid, "SIGKILL");
314
+ }
315
+ catch { /* already gone */ }
316
+ }
317
+ }
318
+ async function killHoldersOfPort(port) {
319
+ const pids = await findPortHolders(port);
320
+ if (pids.length === 0)
321
+ return;
322
+ console.log(`[gralkor] boot: port ${port} held by pid(s) ${pids.join(",")} — killing`);
323
+ for (const pid of pids) {
324
+ try {
325
+ process.kill(pid, "SIGTERM");
326
+ }
327
+ catch { /* already gone */ }
328
+ }
329
+ if (await waitForPortFree(port, 5_000))
330
+ return;
331
+ for (const pid of await findPortHolders(port)) {
332
+ try {
333
+ process.kill(pid, "SIGKILL");
334
+ }
335
+ catch { /* already gone */ }
336
+ }
337
+ if (!(await waitForPortFree(port, 2_000))) {
338
+ throw new Error(`port ${port} still bound after SIGTERM+SIGKILL`);
339
+ }
340
+ }
341
+ async function findPortHolders(port) {
342
+ try {
343
+ const { stdout } = await execFileAsync("lsof", ["-ti", `tcp:${port}`, "-sTCP:LISTEN"]);
344
+ return stdout.split("\n").map(s => Number(s.trim())).filter(n => Number.isInteger(n) && n > 0);
345
+ }
346
+ catch {
347
+ // lsof exits non-zero when nothing matches — treat as empty
348
+ return [];
349
+ }
350
+ }
351
+ async function waitForPortFree(port, timeoutMs) {
352
+ const deadline = Date.now() + timeoutMs;
353
+ while (Date.now() < deadline) {
354
+ if ((await findPortHolders(port)).length === 0)
355
+ return true;
356
+ await new Promise((r) => setTimeout(r, 100));
357
+ }
358
+ return false;
359
+ }
360
+ async function waitForHealth(port) {
361
+ const deadline = Date.now() + HEALTH_TIMEOUT_MS;
362
+ const start = Date.now();
363
+ let polls = 0;
364
+ let lastError = "";
365
+ while (Date.now() < deadline) {
366
+ polls++;
367
+ try {
368
+ const res = await fetch(`http://127.0.0.1:${port}/health`);
369
+ if (res.ok) {
370
+ console.log(`[gralkor] boot: health poll succeeded after ${polls} attempts (${((Date.now() - start) / 1000).toFixed(1)}s)`);
371
+ return;
372
+ }
373
+ const newError = `HTTP ${res.status}`;
374
+ if (newError !== lastError) {
375
+ console.log(`[gralkor] boot: health poll — ${newError}`);
376
+ lastError = newError;
377
+ }
378
+ }
379
+ catch (err) {
380
+ const newError = err instanceof Error ? err.message : String(err);
381
+ if (newError !== lastError) {
382
+ console.log(`[gralkor] boot: health poll — ${newError}`);
383
+ lastError = newError;
384
+ }
385
+ }
386
+ await new Promise((r) => setTimeout(r, HEALTH_POLL_INTERVAL_MS));
387
+ }
388
+ throw new Error(`Graphiti server did not become healthy within ${HEALTH_TIMEOUT_MS / 1000}s (${polls} polls, last error: ${lastError})`);
389
+ }
390
+ //# sourceMappingURL=server-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-manager.js","sourceRoot":"","sources":["../../src/gralkor/server-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Test helpers for `@susulabs/gralkor`.
3
+ *
4
+ * Import from "@susulabs/gralkor/testing" in test files only. Keeps the
5
+ * production bundle free of the in-memory twin (it's ~100 lines; small, but
6
+ * keeping the separation matches what the Elixir side does with
7
+ * `Gralkor.Client.InMemory` shipped as a separately-named module).
8
+ */
9
+ export { GralkorInMemoryClient } from "./client/in-memory.js";
10
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/gralkor/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Test helpers for `@susulabs/gralkor`.
3
+ *
4
+ * Import from "@susulabs/gralkor/testing" in test files only. Keeps the
5
+ * production bundle free of the in-memory twin (it's ~100 lines; small, but
6
+ * keeping the separation matches what the Elixir side does with
7
+ * `Gralkor.Client.InMemory` shipped as a separately-named module).
8
+ */
9
+ export { GralkorInMemoryClient } from "./client/in-memory.js";
10
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../../src/gralkor/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { GralkorClient, Result } from "../gralkor/index.js";
2
+ import { type MessageEntry } from "../ctx-to-messages.js";
3
+ export interface AgentEndCtx {
4
+ sessionKey: string;
5
+ agentName: string;
6
+ messages: MessageEntry[];
7
+ }
8
+ /**
9
+ * `agent_end` hook: OpenClaw fires this at the end of an agent run.
10
+ *
11
+ * In the old architecture this handler buffered the messages client-side
12
+ * via a keyed debouncer and later flushed them as a whole-session episode.
13
+ * In the Python-server-heavy architecture, the server owns the capture
14
+ * buffer — so all this hook does is extract the just-finished turn and
15
+ * POST it to `/capture`. The server appends to its session-keyed buffer
16
+ * and flushes on explicit `session_end` (which OpenClaw fires on
17
+ * idle-rollover or reset) or on lifespan shutdown.
18
+ *
19
+ * Skipped when:
20
+ * - ctx has no messages,
21
+ * - ctx doesn't contain both a user message and a final assistant
22
+ * message (nothing coherent to capture).
23
+ */
24
+ export declare function runAgentEnd(client: GralkorClient, ctx: AgentEndCtx): Promise<Result<true>>;
25
+ //# sourceMappingURL=agent-end.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-end.d.ts","sourceRoot":"","sources":["../../src/hooks/agent-end.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGzE,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAmBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,WAAW,GACf,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAiBvB"}
@@ -0,0 +1,51 @@
1
+ import { ctxToMessages } from "../ctx-to-messages.js";
2
+ import { getSessionGroup } from "../session-map.js";
3
+ /**
4
+ * OpenClaw's `llm-slug-generator` runs an embedded sub-agent with this fixed
5
+ * `sessionKey` to produce a filename for `/new`/`/reset` memory archival. It
6
+ * fires `agent_end` like any other run; without this guard the sub-agent's
7
+ * prompt (which contains an inline dump of the real conversation) would be
8
+ * captured as if it were a user turn.
9
+ */
10
+ const SLUG_GENERATOR_SESSION_KEY = "temp:slug-generator";
11
+ /**
12
+ * OpenClaw's session-reset flow replaces the user's `/new` or `/reset` command
13
+ * with a synthetic meta-prompt instructing the agent to run its startup
14
+ * sequence and greet the user. Stable prefix from
15
+ * `openclaw/src/auto-reply/reply/session-reset-prompt.ts`.
16
+ */
17
+ const SESSION_RESET_PROMPT_PREFIX = "A new session was started via /new or /reset";
18
+ /**
19
+ * `agent_end` hook: OpenClaw fires this at the end of an agent run.
20
+ *
21
+ * In the old architecture this handler buffered the messages client-side
22
+ * via a keyed debouncer and later flushed them as a whole-session episode.
23
+ * In the Python-server-heavy architecture, the server owns the capture
24
+ * buffer — so all this hook does is extract the just-finished turn and
25
+ * POST it to `/capture`. The server appends to its session-keyed buffer
26
+ * and flushes on explicit `session_end` (which OpenClaw fires on
27
+ * idle-rollover or reset) or on lifespan shutdown.
28
+ *
29
+ * Skipped when:
30
+ * - ctx has no messages,
31
+ * - ctx doesn't contain both a user message and a final assistant
32
+ * message (nothing coherent to capture).
33
+ */
34
+ export async function runAgentEnd(client, ctx) {
35
+ if (ctx.messages.length === 0)
36
+ return { ok: true };
37
+ if (ctx.sessionKey === SLUG_GENERATOR_SESSION_KEY)
38
+ return { ok: true };
39
+ const messages = ctxToMessages(ctx.messages);
40
+ if (messages === null)
41
+ return { ok: true };
42
+ const userMessage = messages.find((m) => m.role === "user");
43
+ if (userMessage && userMessage.content.startsWith(SESSION_RESET_PROMPT_PREFIX)) {
44
+ return { ok: true };
45
+ }
46
+ const groupId = getSessionGroup(ctx.sessionKey);
47
+ if (groupId === null)
48
+ return { error: "session_not_registered" };
49
+ return client.capture(ctx.sessionKey, groupId, ctx.agentName, messages);
50
+ }
51
+ //# sourceMappingURL=agent-end.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-end.js","sourceRoot":"","sources":["../../src/hooks/agent-end.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAqB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAQpD;;;;;;GAMG;AACH,MAAM,0BAA0B,GAAG,qBAAqB,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,2BAA2B,GAAG,8CAA8C,CAAC;AAEnF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAqB,EACrB,GAAgB;IAEhB,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IAEnD,IAAI,GAAG,CAAC,UAAU,KAAK,0BAA0B;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IAEvE,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IAE3C,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IAC5D,IAAI,WAAW,IAAI,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,2BAA2B,CAAC,EAAE,CAAC;QAC/E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAChD,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC;IAEjE,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { type GralkorClient, type Result } from "../gralkor/index.js";
2
+ export interface BeforePromptBuildCtx {
3
+ sessionKey: string;
4
+ agentId: string;
5
+ agentName: string;
6
+ prompt: string;
7
+ }
8
+ export interface BeforePromptBuildOutput {
9
+ prependContext?: string;
10
+ }
11
+ export declare function runBeforePromptBuild(client: GralkorClient, ctx: BeforePromptBuildCtx): Promise<Result<BeforePromptBuildOutput>>;
12
+ //# sourceMappingURL=before-prompt-build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"before-prompt-build.d.ts","sourceRoot":"","sources":["../../src/hooks/before-prompt-build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGvF,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,oBAAoB,GACxB,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC,CAqB1C"}
@@ -0,0 +1,15 @@
1
+ import { sanitizeGroupId } from "../gralkor/index.js";
2
+ import { setSessionGroup } from "../session-map.js";
3
+ export async function runBeforePromptBuild(client, ctx) {
4
+ setSessionGroup(ctx.sessionKey, ctx.agentId);
5
+ const query = ctx.prompt.trim();
6
+ if (query === "")
7
+ return { ok: {} };
8
+ const recalled = await client.recall(sanitizeGroupId(ctx.agentId), ctx.sessionKey, query, ctx.agentName);
9
+ if ("error" in recalled) {
10
+ console.warn("[openclaw_gralkor] recall failed — continuing turn without memory context:", recalled.error);
11
+ return { ok: {} };
12
+ }
13
+ return { ok: { prependContext: recalled.ok } };
14
+ }
15
+ //# sourceMappingURL=before-prompt-build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"before-prompt-build.js","sourceRoot":"","sources":["../../src/hooks/before-prompt-build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAmC,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAapD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAqB,EACrB,GAAyB;IAEzB,eAAe,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IAE7C,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;IAEpC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAClC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAC5B,GAAG,CAAC,UAAU,EACd,KAAK,EACL,GAAG,CAAC,SAAS,CACd,CAAC;IACF,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CACV,4EAA4E,EAC5E,QAAQ,CAAC,KAAK,CACf,CAAC;QACF,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;IACpB,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;AACjD,CAAC"}