@tekmidian/pai 0.8.4 → 0.9.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 (33) hide show
  1. package/ARCHITECTURE.md +121 -0
  2. package/FEATURE.md +5 -0
  3. package/README.md +54 -0
  4. package/dist/cli/index.mjs +11 -11
  5. package/dist/daemon/index.mjs +3 -3
  6. package/dist/{daemon-nXyhvdzz.mjs → daemon-VIFoKc_z.mjs} +31 -6
  7. package/dist/daemon-VIFoKc_z.mjs.map +1 -0
  8. package/dist/daemon-mcp/index.mjs +51 -0
  9. package/dist/daemon-mcp/index.mjs.map +1 -1
  10. package/dist/{factory-Ygqe_bVZ.mjs → factory-e0k1HWuc.mjs} +2 -2
  11. package/dist/{factory-Ygqe_bVZ.mjs.map → factory-e0k1HWuc.mjs.map} +1 -1
  12. package/dist/hooks/load-project-context.mjs +276 -89
  13. package/dist/hooks/load-project-context.mjs.map +4 -4
  14. package/dist/hooks/stop-hook.mjs +152 -2
  15. package/dist/hooks/stop-hook.mjs.map +3 -3
  16. package/dist/{postgres-CKf-EDtS.mjs → postgres-DvEPooLO.mjs} +45 -10
  17. package/dist/postgres-DvEPooLO.mjs.map +1 -0
  18. package/dist/query-feedback-Dv43XKHM.mjs +76 -0
  19. package/dist/query-feedback-Dv43XKHM.mjs.map +1 -0
  20. package/dist/tools-C4SBZHga.mjs +1731 -0
  21. package/dist/tools-C4SBZHga.mjs.map +1 -0
  22. package/dist/{vault-indexer-Bi2cRmn7.mjs → vault-indexer-B-aJpRZC.mjs} +3 -2
  23. package/dist/{vault-indexer-Bi2cRmn7.mjs.map → vault-indexer-B-aJpRZC.mjs.map} +1 -1
  24. package/dist/{zettelkasten-cdajbnPr.mjs → zettelkasten-DhBKZQHF.mjs} +358 -3
  25. package/dist/zettelkasten-DhBKZQHF.mjs.map +1 -0
  26. package/package.json +1 -1
  27. package/src/hooks/ts/session-start/load-project-context.ts +36 -0
  28. package/src/hooks/ts/stop/stop-hook.ts +203 -1
  29. package/dist/daemon-nXyhvdzz.mjs.map +0 -1
  30. package/dist/postgres-CKf-EDtS.mjs.map +0 -1
  31. package/dist/tools-DcaJlYDN.mjs +0 -869
  32. package/dist/tools-DcaJlYDN.mjs.map +0 -1
  33. package/dist/zettelkasten-cdajbnPr.mjs.map +0 -1
package/ARCHITECTURE.md CHANGED
@@ -250,6 +250,127 @@ Restart Claude Code after installation for the tools to appear.
250
250
 
251
251
  ---
252
252
 
253
+ ## Memory Intelligence Layer
254
+
255
+ These features extend the core memory engine with structured, time-aware, and cross-project intelligence. They ship in PAI v0.8.6, inspired by patterns from [mempalace](https://github.com/milla-jovovich/mempalace).
256
+
257
+ ### 4-Layer Wake-Up Context
258
+
259
+ The `memory_wakeup` MCP tool loads context progressively at session start. The goal is a meaningful cold-start without flooding the context window.
260
+
261
+ | Layer | Source | Content |
262
+ |-------|--------|---------|
263
+ | L0 | `~/.pai/identity.txt` | Stable identity: who you are, your style, your key projects |
264
+ | L1 | Recent session notes (registry + filesystem) | Essential story: what you were doing, decisions made, where things stand |
265
+ | L2 | On-demand `memory_search` query | Topic-specific context fetched when needed |
266
+ | L3 | Full `memory_search` with reranking | Deep retrieval for complex questions |
267
+
268
+ L0 and L1 are injected automatically via the `SessionStart` hook. L2 and L3 are triggered by the model during the session as needed.
269
+
270
+ **File locations:**
271
+
272
+ ```
273
+ ~/.pai/identity.txt # L0 identity — edit this to describe yourself
274
+ Notes/ # L1 source — the most recent session notes are read here
275
+ ~/.config/pai/config.json # wakeupL1Count: N controls how many notes are read for L1
276
+ ```
277
+
278
+ ### Temporal Knowledge Graph
279
+
280
+ The `kg_triples` table stores knowledge as typed, time-bounded triples. This allows facts to evolve over time rather than accumulating as a flat, undated collection.
281
+
282
+ **Schema:**
283
+
284
+ ```sql
285
+ CREATE TABLE kg_triples (
286
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
287
+ tenant_id UUID NOT NULL,
288
+ subject TEXT NOT NULL,
289
+ predicate TEXT NOT NULL,
290
+ object TEXT NOT NULL,
291
+ valid_from TIMESTAMPTZ NOT NULL DEFAULT now(),
292
+ valid_to TIMESTAMPTZ, -- NULL means currently valid
293
+ confidence REAL DEFAULT 1.0,
294
+ source TEXT, -- where this fact came from
295
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now()
296
+ );
297
+
298
+ CREATE INDEX kg_triples_subject_idx ON kg_triples (tenant_id, subject);
299
+ CREATE INDEX kg_triples_valid_idx ON kg_triples (tenant_id, valid_from, valid_to);
300
+ ```
301
+
302
+ **MCP tools:**
303
+
304
+ | Tool | Description |
305
+ |------|-------------|
306
+ | `kg_add` | Add a subject-predicate-object triple with `valid_from` (defaults to now) and optional `valid_to` |
307
+ | `kg_query` | Query triples by subject, predicate, or object; filter by point-in-time (defaults to now) |
308
+ | `kg_invalidate` | Set `valid_to = now()` on a triple, marking it as no longer true |
309
+ | `kg_contradictions` | Surface triples that share a subject and predicate but have conflicting objects within overlapping validity windows |
310
+
311
+ Contradiction detection uses predicate inversion rules (`uses → not_uses`, `works_at → not_works_at`, etc.) to identify direct contradictions. Fuzzy contradictions (same subject/predicate, different object without an explicit inversion rule) are flagged with lower confidence.
312
+
313
+ ### Memory Taxonomy
314
+
315
+ `memory_taxonomy` returns a structured overview of the current state of indexed memory:
316
+
317
+ ```json
318
+ {
319
+ "projects": [
320
+ { "slug": "pai", "sessions": 142, "chunks": 89341, "last_active": "2026-04-07" }
321
+ ],
322
+ "totals": {
323
+ "projects": 77,
324
+ "sessions": 1204,
325
+ "chunks": 449000,
326
+ "embeddings_coverage": 0.94
327
+ },
328
+ "recent_activity": [
329
+ { "project": "pai", "session": "0142", "date": "2026-04-07", "topic": "Memory Intelligence Layer" }
330
+ ]
331
+ }
332
+ ```
333
+
334
+ This is used both as a user-facing status tool and as a model-facing context signal — the model can call `memory_taxonomy` to understand what is indexed before deciding how to search.
335
+
336
+ ### Mid-Session Auto-Save
337
+
338
+ The Stop hook normally fires once at the end of a session. The auto-save feature extends this: the Stop hook also fires every N human messages during a session, pushing a `session-summary` work item to the daemon and blocking the Stop event so the session continues.
339
+
340
+ **Configuration:**
341
+
342
+ ```bash
343
+ PAI_AUTO_SAVE_INTERVAL=15 # default: 15 human messages between saves
344
+ ```
345
+
346
+ Set in `~/.config/pai/config.json` as `autoSaveInterval` or via the environment variable. Set to `0` to disable mid-session saves.
347
+
348
+ **Loop prevention:** The hook sets a `stop_hook_active` flag in the work item. The daemon checks this flag before re-queuing save work. This prevents an auto-save from triggering another auto-save in a feedback loop.
349
+
350
+ ### Cross-Project Tunnel Detection
351
+
352
+ `memory_tunnels` detects concepts that appear across multiple projects by comparing the vocabulary of each project's indexed content.
353
+
354
+ **SQLite mode:** Uses the FTS5 vocabulary virtual table to extract term frequencies per project, then identifies terms that appear significantly in three or more projects.
355
+
356
+ **PostgreSQL mode:** Uses `ts_stat()` on each project's `tsvector` content to extract term frequencies, then compares across projects using the same multi-project threshold.
357
+
358
+ **Output:** A ranked list of concept-tunnel pairs:
359
+
360
+ ```json
361
+ [
362
+ {
363
+ "concept": "rate limiting",
364
+ "projects": ["pai-daemon", "whazaa-mcp", "ringsaday-backend"],
365
+ "tunnel_strength": 0.87
366
+ }
367
+ ]
368
+ ```
369
+
370
+ Tunnel strength is a normalized score based on term frequency across projects, IDF weighting, and the number of projects involved. Higher is more significant.
371
+
372
+ ---
373
+
253
374
  ## Search Modes
254
375
 
255
376
  Three modes, selectable via the `--mode` flag on the CLI or the `mode` parameter in MCP tool calls.
package/FEATURE.md CHANGED
@@ -40,6 +40,11 @@ different direction: persistent memory, session continuity, and deep Claude Code
40
40
  | **Automatic session notes** | No | Yes — AI-generated via daemon worker (Opus/Sonnet), topic-based splitting |
41
41
  | **Topic-based note splitting** | No | Yes — Jaccard similarity detects topic shifts, creates separate notes |
42
42
  | **Whisper rules** | No | Yes — injects critical rules on every prompt, survives compaction and /clear |
43
+ | **4-layer wake-up context** | No | Yes — `memory_wakeup` tool loads identity (L0), recent story (L1), on-demand topic (L2), deep search (L3) |
44
+ | **Temporal knowledge graph** | No | Yes — `kg_add`, `kg_query`, `kg_invalidate`, `kg_contradictions` tools; facts have `valid_from`/`valid_to` timestamps |
45
+ | **Memory taxonomy tool** | No | Yes — `memory_taxonomy` surfaces project/session/chunk counts and recent activity at a glance |
46
+ | **Mid-session auto-save** | No | Yes — Stop hook fires every 15 human messages (configurable via `PAI_AUTO_SAVE_INTERVAL`), saves without ending session |
47
+ | **Cross-project tunnel detection** | No | Yes — `memory_tunnels` finds concepts shared across multiple projects via FTS vocabulary comparison |
43
48
  | **Session note reconstruction** | No | Yes — /reconstruct skill retroactively creates notes from JSONL + git history |
44
49
  | **Backup / restore** | No | Yes — timestamped pg_dump + registry export |
45
50
  | **Multi-session concurrency** | n/a | Yes — daemon multiplexes Claude sessions |
package/README.md CHANGED
@@ -190,6 +190,60 @@ When spawning headless Claude CLI processes for summarization, the daemon strips
190
190
 
191
191
  ---
192
192
 
193
+ ## Progressive Memory Loading
194
+
195
+ PAI loads context in layers at session start rather than all at once. This keeps early-session latency low while giving Claude everything it needs to be useful immediately.
196
+
197
+ ### The Four Layers
198
+
199
+ | Layer | What it loads | When |
200
+ |-------|---------------|------|
201
+ | **L0 — Identity** | Your identity file (`~/.pai/identity.txt`) — who you are, your working style, key preferences | Always, at every session start |
202
+ | **L1 — Essential story** | Summaries from the most recent session notes — what you were doing, what decisions were made, where things stand | Always, at session start |
203
+ | **L2 — Topic queries** | On-demand retrieval for the current topic — fetched when a specific question or task is identified | On demand, during the session |
204
+ | **L3 — Deep search** | Full `memory_search` across all indexed content — for when L2 is not enough | On demand, when explicitly needed |
205
+
206
+ L0 and L1 fire automatically via the `memory_wakeup` MCP tool, which is called by the `SessionStart` hook. L2 and L3 are invoked as needed — the model decides when to go deeper based on the question at hand.
207
+
208
+ ### Configuring Your Identity File
209
+
210
+ Create `~/.pai/identity.txt` with a short description of yourself and your working style. Claude will see this at every session start. Example:
211
+
212
+ ```
213
+ Matthias. Principal engineer. Work across TypeScript, Dart, and shell scripting.
214
+ Projects: PAI (AI infrastructure), RingsADay (Flutter app), Scribe (MCP server).
215
+ Prefer concise explanations, hate unnecessary hedging.
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Advanced Memory Tools
221
+
222
+ ### Temporal Knowledge Graph
223
+
224
+ Facts change over time. The `kg_triples` table stores knowledge as subject-predicate-object triples with `valid_from` and `valid_to` timestamps, so facts can expire and contradict each other rather than accumulating in an undated blob.
225
+
226
+ Four MCP tools cover the full lifecycle:
227
+
228
+ - `kg_add` — Add a fact with a start date (and optional end date)
229
+ - `kg_query` — Query the graph, filtered to facts valid at a given point in time
230
+ - `kg_invalidate` — Mark a fact as no longer true (sets `valid_to`)
231
+ - `kg_contradictions` — Surface facts that directly contradict each other, using predicate inversion rules
232
+
233
+ Example: "Matthias uses PostgreSQL" added in March; "Matthias uses SQLite" added in April with the March fact invalidated. `kg_query` in April sees only the current fact; `kg_query` for March sees the historical one.
234
+
235
+ ### Memory Taxonomy
236
+
237
+ `memory_taxonomy` gives a shape-of-memory overview: projects, session counts, chunk counts, embedding coverage, and recent activity. Think of it as a dashboard for your knowledge base — useful both for the model (to understand what it knows) and for you (to audit what is indexed).
238
+
239
+ ### Cross-Project Tunnels
240
+
241
+ `memory_tunnels` detects concepts that appear across multiple projects. It works by comparing FTS vocabulary in SQLite mode or `ts_stat` output in PostgreSQL mode. When a concept — a library name, a design pattern, a person's name — shows up in three separate projects, PAI surfaces that connection as a tunnel.
242
+
243
+ This reveals unexpected intellectual bridges: the same concurrency pattern used in PAI's daemon showing up in your Flutter app's state management, or a vendor name appearing in both your notes and your job applications.
244
+
245
+ ---
246
+
193
247
  ## Automatic Observation Capture
194
248
 
195
249
  PAI automatically classifies and stores every significant tool call during your sessions. When you edit a file, run a command, or make a decision, PAI captures it as a structured observation — building a searchable timeline of everything you've done across all projects.
@@ -13,7 +13,7 @@ import { n as formatDetection, r as formatDetectionJson, t as detectProject } fr
13
13
  import "../indexer-D53l5d1U.mjs";
14
14
  import { t as PaiClient } from "../ipc-client-CoyUHPod.mjs";
15
15
  import { a as expandHome, i as ensureConfigDir, n as CONFIG_FILE$2, o as loadConfig, t as CONFIG_DIR } from "../config-BuhHWyOK.mjs";
16
- import { t as createStorageBackend } from "../factory-Ygqe_bVZ.mjs";
16
+ import { t as createStorageBackend } from "../factory-e0k1HWuc.mjs";
17
17
  import { appendFileSync, chmodSync, copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, readlinkSync, renameSync, statSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
18
18
  import { homedir, platform, tmpdir } from "node:os";
19
19
  import { basename, dirname, join, relative, resolve } from "node:path";
@@ -1683,7 +1683,7 @@ function cmdActive(db, opts) {
1683
1683
  async function cmdAutoRoute(opts) {
1684
1684
  const { autoRoute, formatAutoRoute, formatAutoRouteJson } = await import("../auto-route-C-DrW6BL.mjs");
1685
1685
  const { openRegistry } = await import("../db-BtuN768f.mjs").then((n) => n.t);
1686
- const { createStorageBackend } = await import("../factory-Ygqe_bVZ.mjs").then((n) => n.n);
1686
+ const { createStorageBackend } = await import("../factory-e0k1HWuc.mjs").then((n) => n.n);
1687
1687
  const { loadConfig } = await import("../config-BuhHWyOK.mjs").then((n) => n.r);
1688
1688
  const config = loadConfig();
1689
1689
  const registryDb = openRegistry();
@@ -2302,7 +2302,7 @@ async function countVectorDbPaths(oldPaths) {
2302
2302
  if (oldPaths.length === 0) return 0;
2303
2303
  try {
2304
2304
  const { loadConfig } = await import("../config-BuhHWyOK.mjs").then((n) => n.r);
2305
- const { PostgresBackend } = await import("../postgres-CKf-EDtS.mjs");
2305
+ const { PostgresBackend } = await import("../postgres-DvEPooLO.mjs");
2306
2306
  const config = loadConfig();
2307
2307
  if (config.storageBackend !== "postgres") return 0;
2308
2308
  const pgBackend = new PostgresBackend(config.postgres ?? {});
@@ -2323,7 +2323,7 @@ async function updateVectorDbPaths(moves) {
2323
2323
  if (moves.length === 0) return 0;
2324
2324
  try {
2325
2325
  const { loadConfig } = await import("../config-BuhHWyOK.mjs").then((n) => n.r);
2326
- const { PostgresBackend } = await import("../postgres-CKf-EDtS.mjs");
2326
+ const { PostgresBackend } = await import("../postgres-DvEPooLO.mjs");
2327
2327
  const config = loadConfig();
2328
2328
  if (config.storageBackend !== "postgres") return 0;
2329
2329
  const pgBackend = new PostgresBackend(config.postgres ?? {});
@@ -3793,7 +3793,7 @@ function cmdLogs(opts) {
3793
3793
  }
3794
3794
  function registerDaemonCommands(daemonCmd) {
3795
3795
  daemonCmd.command("serve").description("Start the PAI daemon in the foreground").action(async () => {
3796
- const { serve } = await import("../daemon-nXyhvdzz.mjs").then((n) => n.t);
3796
+ const { serve } = await import("../daemon-VIFoKc_z.mjs").then((n) => n.t);
3797
3797
  const { loadConfig: lc, ensureConfigDir } = await import("../config-BuhHWyOK.mjs").then((n) => n.r);
3798
3798
  ensureConfigDir();
3799
3799
  await serve(lc());
@@ -6411,7 +6411,7 @@ async function cmdExplore(note, opts) {
6411
6411
  const depth = parseInt(opts.depth ?? "3", 10);
6412
6412
  const direction = opts.direction ?? "both";
6413
6413
  const mode = opts.mode ?? "all";
6414
- const { zettelExplore } = await import("../zettelkasten-cdajbnPr.mjs");
6414
+ const { zettelExplore } = await import("../zettelkasten-DhBKZQHF.mjs");
6415
6415
  const result = zettelExplore(getFedDb(), {
6416
6416
  startNote: note,
6417
6417
  depth,
@@ -6475,7 +6475,7 @@ async function cmdHealth(opts) {
6475
6475
  const projectPath = opts.project;
6476
6476
  const recentDays = parseInt(opts.days ?? "30", 10);
6477
6477
  const includeTypes = opts.include ? opts.include.split(",").map((s) => s.trim()) : void 0;
6478
- const { zettelHealth } = await import("../zettelkasten-cdajbnPr.mjs");
6478
+ const { zettelHealth } = await import("../zettelkasten-DhBKZQHF.mjs");
6479
6479
  const result = zettelHealth(getFedDb(), {
6480
6480
  scope,
6481
6481
  projectPath,
@@ -6544,7 +6544,7 @@ async function cmdSurprise(note, opts) {
6544
6544
  const limit = parseInt(opts.limit ?? "10", 10);
6545
6545
  const minSimilarity = parseFloat(opts.minSimilarity ?? "0.3");
6546
6546
  const minGraphDistance = parseInt(opts.minDistance ?? "3", 10);
6547
- const { zettelSurprise } = await import("../zettelkasten-cdajbnPr.mjs");
6547
+ const { zettelSurprise } = await import("../zettelkasten-DhBKZQHF.mjs");
6548
6548
  const db = getFedDb();
6549
6549
  console.log();
6550
6550
  console.log(header(" PAI Zettel Surprise"));
@@ -6597,7 +6597,7 @@ async function cmdSuggest(note, opts) {
6597
6597
  const vaultProjectId = parseInt(opts.vaultProjectId, 10);
6598
6598
  const limit = parseInt(opts.limit ?? "5", 10);
6599
6599
  const excludeLinked = opts.excludeLinked !== false;
6600
- const { zettelSuggest } = await import("../zettelkasten-cdajbnPr.mjs");
6600
+ const { zettelSuggest } = await import("../zettelkasten-DhBKZQHF.mjs");
6601
6601
  const db = getFedDb();
6602
6602
  console.log();
6603
6603
  console.log(header(" PAI Zettel Suggest"));
@@ -6648,7 +6648,7 @@ async function cmdConverse(question, opts) {
6648
6648
  const vaultProjectId = parseInt(opts.vaultProjectId, 10);
6649
6649
  const depth = parseInt(opts.depth ?? "2", 10);
6650
6650
  const limit = parseInt(opts.limit ?? "15", 10);
6651
- const { zettelConverse } = await import("../zettelkasten-cdajbnPr.mjs");
6651
+ const { zettelConverse } = await import("../zettelkasten-DhBKZQHF.mjs");
6652
6652
  const db = getFedDb();
6653
6653
  console.log();
6654
6654
  console.log(header(" PAI Zettel Converse"));
@@ -6709,7 +6709,7 @@ async function cmdThemes(opts) {
6709
6709
  const minClusterSize = parseInt(opts.minSize ?? "3", 10);
6710
6710
  const maxThemes = parseInt(opts.maxThemes ?? "10", 10);
6711
6711
  const similarityThreshold = parseFloat(opts.threshold ?? "0.65");
6712
- const { zettelThemes } = await import("../zettelkasten-cdajbnPr.mjs");
6712
+ const { zettelThemes } = await import("../zettelkasten-DhBKZQHF.mjs");
6713
6713
  const db = getFedDb();
6714
6714
  console.log();
6715
6715
  console.log(header(" PAI Zettel Themes"));
@@ -7,10 +7,10 @@ import "../search-DC1qhkKn.mjs";
7
7
  import "../indexer-D53l5d1U.mjs";
8
8
  import { t as PaiClient } from "../ipc-client-CoyUHPod.mjs";
9
9
  import { i as ensureConfigDir, o as loadConfig } from "../config-BuhHWyOK.mjs";
10
- import "../factory-Ygqe_bVZ.mjs";
11
- import { n as serve } from "../daemon-nXyhvdzz.mjs";
10
+ import "../factory-e0k1HWuc.mjs";
11
+ import { n as serve } from "../daemon-VIFoKc_z.mjs";
12
12
  import "../state-C6_vqz7w.mjs";
13
- import "../tools-DcaJlYDN.mjs";
13
+ import "../tools-C4SBZHga.mjs";
14
14
  import "../detector-jGBuYQJM.mjs";
15
15
  import { Command } from "commander";
16
16
 
@@ -4,9 +4,9 @@ import { d as sha256 } from "./helpers-BEST-4Gx.mjs";
4
4
  import { n as indexAll } from "./sync-BOsnEj2-.mjs";
5
5
  import { t as configureEmbeddingModel } from "./embeddings-DGRAPAYb.mjs";
6
6
  import { n as CONFIG_FILE, s as DEFAULT_NOTIFICATION_CONFIG, t as CONFIG_DIR } from "./config-BuhHWyOK.mjs";
7
- import { t as createStorageBackend } from "./factory-Ygqe_bVZ.mjs";
7
+ import { t as createStorageBackend } from "./factory-e0k1HWuc.mjs";
8
8
  import { C as setStorageBackend, E as startTime, O as storageBackend, S as setStartTime, T as shutdownRequested, _ as setLastIndexTime, a as indexSchedulerTimer, b as setRegistryDb, c as lastVaultIndexTime, d as setDaemonConfig, f as setEmbedInProgress, g as setLastEmbedTime, h as setIndexSchedulerTimer, i as indexInProgress, k as vaultIndexInProgress, l as notificationConfig, m as setIndexInProgress, n as embedInProgress, o as lastEmbedTime, p as setEmbedSchedulerTimer, r as embedSchedulerTimer, s as lastIndexTime, t as daemonConfig, u as registryDb, v as setLastVaultIndexTime, w as setVaultIndexInProgress, x as setShutdownRequested, y as setNotificationConfig } from "./state-C6_vqz7w.mjs";
9
- import { a as toolProjectDetect, c as toolProjectList, d as toolMemorySearch, i as toolSessionRoute, l as toolProjectTodo, n as toolRegistrySearch, o as toolProjectHealth, r as toolSessionList, s as toolProjectInfo, u as toolMemoryGet } from "./tools-DcaJlYDN.mjs";
9
+ import { a as toolSessionList, c as toolProjectHealth, d as toolProjectTodo, f as toolMemoryGet, i as toolRegistrySearch, l as toolProjectInfo, n as toolMemoryTaxonomy, o as toolSessionRoute, p as toolMemorySearch, r as toolMemoryWakeup, s as toolProjectDetect, u as toolProjectList } from "./tools-C4SBZHga.mjs";
10
10
  import { t as detectTopicShift } from "./detector-jGBuYQJM.mjs";
11
11
  import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
12
12
  import { homedir, setPriority } from "node:os";
@@ -161,7 +161,7 @@ async function runVaultIndex() {
161
161
  const t0 = Date.now();
162
162
  process.stderr.write("[pai-daemon] Starting vault index run...\n");
163
163
  try {
164
- const { indexVault } = await import("./vault-indexer-Bi2cRmn7.mjs");
164
+ const { indexVault } = await import("./vault-indexer-B-aJpRZC.mjs");
165
165
  const r = await indexVault(storageBackend, vaultProjectId, daemonConfig.vaultPath);
166
166
  const elapsed = Date.now() - t0;
167
167
  setLastVaultIndexTime(Date.now());
@@ -690,6 +690,8 @@ async function dispatchTool(method, params) {
690
690
  case "project_detect": return toolProjectDetect(registryDb, p);
691
691
  case "project_health": return toolProjectHealth(registryDb, p);
692
692
  case "project_todo": return toolProjectTodo(registryDb, p);
693
+ case "memory_wakeup": return toolMemoryWakeup(registryDb, p);
694
+ case "memory_taxonomy": return toolMemoryTaxonomy(registryDb, storageBackend, p);
693
695
  case "topic_check": return detectTopicShift(registryDb, storageBackend, p);
694
696
  case "session_auto_route": return toolSessionRoute(registryDb, storageBackend, p);
695
697
  case "zettel_explore":
@@ -697,8 +699,10 @@ async function dispatchTool(method, params) {
697
699
  case "zettel_surprise":
698
700
  case "zettel_suggest":
699
701
  case "zettel_converse":
700
- case "zettel_themes": {
701
- const { toolZettelExplore, toolZettelHealth, toolZettelSurprise, toolZettelSuggest, toolZettelConverse, toolZettelThemes } = await import("./tools-DcaJlYDN.mjs").then((n) => n.t);
702
+ case "zettel_themes":
703
+ case "zettel_god_notes":
704
+ case "zettel_communities": {
705
+ const { toolZettelExplore, toolZettelHealth, toolZettelSurprise, toolZettelSuggest, toolZettelConverse, toolZettelThemes, toolZettelGodNotes, toolZettelCommunities } = await import("./tools-C4SBZHga.mjs").then((n) => n.t);
702
706
  switch (method) {
703
707
  case "zettel_explore": return toolZettelExplore(storageBackend, p);
704
708
  case "zettel_health": return toolZettelHealth(storageBackend, p);
@@ -706,6 +710,8 @@ async function dispatchTool(method, params) {
706
710
  case "zettel_suggest": return toolZettelSuggest(storageBackend, p);
707
711
  case "zettel_converse": return toolZettelConverse(storageBackend, p);
708
712
  case "zettel_themes": return toolZettelThemes(storageBackend, p);
713
+ case "zettel_god_notes": return toolZettelGodNotes(storageBackend, p);
714
+ case "zettel_communities": return toolZettelCommunities(storageBackend, p);
709
715
  }
710
716
  break;
711
717
  }
@@ -734,6 +740,25 @@ async function dispatchTool(method, params) {
734
740
  if (!daemonConfig.vaultPath) throw new Error("idea_materialize requires vaultPath to be configured in the daemon config");
735
741
  return handleIdeaMaterialize(p, daemonConfig.vaultPath);
736
742
  }
743
+ case "kg_add":
744
+ case "kg_query":
745
+ case "kg_invalidate":
746
+ case "kg_contradictions": {
747
+ const { toolKgAdd, toolKgQuery, toolKgInvalidate, toolKgContradictions } = await import("./tools-C4SBZHga.mjs").then((n) => n.t);
748
+ const pgPool = storageBackend.getPool?.() ?? null;
749
+ if (!pgPool) throw new Error(`${method} requires a Postgres storage backend`);
750
+ switch (method) {
751
+ case "kg_add": return toolKgAdd(pgPool, p);
752
+ case "kg_query": return toolKgQuery(pgPool, p);
753
+ case "kg_invalidate": return toolKgInvalidate(pgPool, p);
754
+ case "kg_contradictions": return toolKgContradictions(pgPool, p);
755
+ }
756
+ break;
757
+ }
758
+ case "memory_tunnels": {
759
+ const { toolMemoryTunnels } = await import("./tools-C4SBZHga.mjs").then((n) => n.t);
760
+ return toolMemoryTunnels(registryDb, storageBackend, p);
761
+ }
737
762
  default: throw new Error(`Unknown method: ${method}`);
738
763
  }
739
764
  }
@@ -3058,4 +3083,4 @@ var daemon_exports = /* @__PURE__ */ __exportAll({ serve: () => serve });
3058
3083
 
3059
3084
  //#endregion
3060
3085
  export { serve as n, daemon_exports as t };
3061
- //# sourceMappingURL=daemon-nXyhvdzz.mjs.map
3086
+ //# sourceMappingURL=daemon-VIFoKc_z.mjs.map