pi-para 0.5.2

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 (198) hide show
  1. package/CHANGELOG.md +214 -0
  2. package/README.md +305 -0
  3. package/SETUP.md +171 -0
  4. package/dist/capture.d.ts +34 -0
  5. package/dist/capture.d.ts.map +1 -0
  6. package/dist/capture.js +461 -0
  7. package/dist/capture.js.map +1 -0
  8. package/dist/cli.d.ts +15 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +405 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands.d.ts +15 -0
  13. package/dist/commands.d.ts.map +1 -0
  14. package/dist/commands.js +786 -0
  15. package/dist/commands.js.map +1 -0
  16. package/dist/context.d.ts +61 -0
  17. package/dist/context.d.ts.map +1 -0
  18. package/dist/context.js +289 -0
  19. package/dist/context.js.map +1 -0
  20. package/dist/daemon.d.ts +49 -0
  21. package/dist/daemon.d.ts.map +1 -0
  22. package/dist/daemon.js +226 -0
  23. package/dist/daemon.js.map +1 -0
  24. package/dist/frontmatter.d.ts +59 -0
  25. package/dist/frontmatter.d.ts.map +1 -0
  26. package/dist/frontmatter.js +170 -0
  27. package/dist/frontmatter.js.map +1 -0
  28. package/dist/gepa/dataset.d.ts +36 -0
  29. package/dist/gepa/dataset.d.ts.map +1 -0
  30. package/dist/gepa/dataset.js +148 -0
  31. package/dist/gepa/dataset.js.map +1 -0
  32. package/dist/gepa/evaluator.d.ts +51 -0
  33. package/dist/gepa/evaluator.d.ts.map +1 -0
  34. package/dist/gepa/evaluator.js +317 -0
  35. package/dist/gepa/evaluator.js.map +1 -0
  36. package/dist/gepa/index.d.ts +66 -0
  37. package/dist/gepa/index.d.ts.map +1 -0
  38. package/dist/gepa/index.js +240 -0
  39. package/dist/gepa/index.js.map +1 -0
  40. package/dist/gepa/llm.d.ts +35 -0
  41. package/dist/gepa/llm.d.ts.map +1 -0
  42. package/dist/gepa/llm.js +268 -0
  43. package/dist/gepa/llm.js.map +1 -0
  44. package/dist/gepa/optimized/capture-prompt.txt +65 -0
  45. package/dist/gepa/optimizer.d.ts +29 -0
  46. package/dist/gepa/optimizer.d.ts.map +1 -0
  47. package/dist/gepa/optimizer.js +249 -0
  48. package/dist/gepa/optimizer.js.map +1 -0
  49. package/dist/gepa/targets.d.ts +39 -0
  50. package/dist/gepa/targets.d.ts.map +1 -0
  51. package/dist/gepa/targets.js +326 -0
  52. package/dist/gepa/targets.js.map +1 -0
  53. package/dist/gepa/types.d.ts +168 -0
  54. package/dist/gepa/types.d.ts.map +1 -0
  55. package/dist/gepa/types.js +124 -0
  56. package/dist/gepa/types.js.map +1 -0
  57. package/dist/index.d.ts +21 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +294 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/ingest.d.ts +88 -0
  62. package/dist/ingest.d.ts.map +1 -0
  63. package/dist/ingest.js +105 -0
  64. package/dist/ingest.js.map +1 -0
  65. package/dist/link-discovery.d.ts +40 -0
  66. package/dist/link-discovery.d.ts.map +1 -0
  67. package/dist/link-discovery.js +122 -0
  68. package/dist/link-discovery.js.map +1 -0
  69. package/dist/link-utils.d.ts +30 -0
  70. package/dist/link-utils.d.ts.map +1 -0
  71. package/dist/link-utils.js +145 -0
  72. package/dist/link-utils.js.map +1 -0
  73. package/dist/lint.d.ts +39 -0
  74. package/dist/lint.d.ts.map +1 -0
  75. package/dist/lint.js +827 -0
  76. package/dist/lint.js.map +1 -0
  77. package/dist/maintainer.d.ts +24 -0
  78. package/dist/maintainer.d.ts.map +1 -0
  79. package/dist/maintainer.js +358 -0
  80. package/dist/maintainer.js.map +1 -0
  81. package/dist/processor.d.ts +14 -0
  82. package/dist/processor.d.ts.map +1 -0
  83. package/dist/processor.js +361 -0
  84. package/dist/processor.js.map +1 -0
  85. package/dist/query.d.ts +69 -0
  86. package/dist/query.d.ts.map +1 -0
  87. package/dist/query.js +107 -0
  88. package/dist/query.js.map +1 -0
  89. package/dist/raw.d.ts +57 -0
  90. package/dist/raw.d.ts.map +1 -0
  91. package/dist/raw.js +219 -0
  92. package/dist/raw.js.map +1 -0
  93. package/dist/redact.d.ts +21 -0
  94. package/dist/redact.d.ts.map +1 -0
  95. package/dist/redact.js +143 -0
  96. package/dist/redact.js.map +1 -0
  97. package/dist/scope.d.ts +54 -0
  98. package/dist/scope.d.ts.map +1 -0
  99. package/dist/scope.js +161 -0
  100. package/dist/scope.js.map +1 -0
  101. package/dist/scripts/bulk-link-fix.d.ts +9 -0
  102. package/dist/scripts/bulk-link-fix.d.ts.map +1 -0
  103. package/dist/scripts/bulk-link-fix.js +106 -0
  104. package/dist/scripts/bulk-link-fix.js.map +1 -0
  105. package/dist/session-tools.d.ts +33 -0
  106. package/dist/session-tools.d.ts.map +1 -0
  107. package/dist/session-tools.js +211 -0
  108. package/dist/session-tools.js.map +1 -0
  109. package/dist/state.d.ts +54 -0
  110. package/dist/state.d.ts.map +1 -0
  111. package/dist/state.js +176 -0
  112. package/dist/state.js.map +1 -0
  113. package/dist/store.d.ts +56 -0
  114. package/dist/store.d.ts.map +1 -0
  115. package/dist/store.js +227 -0
  116. package/dist/store.js.map +1 -0
  117. package/dist/summarize.d.ts +56 -0
  118. package/dist/summarize.d.ts.map +1 -0
  119. package/dist/summarize.js +231 -0
  120. package/dist/summarize.js.map +1 -0
  121. package/dist/tag-registry.d.ts +56 -0
  122. package/dist/tag-registry.d.ts.map +1 -0
  123. package/dist/tag-registry.js +146 -0
  124. package/dist/tag-registry.js.map +1 -0
  125. package/dist/templates/prompts.d.ts +63 -0
  126. package/dist/templates/prompts.d.ts.map +1 -0
  127. package/dist/templates/prompts.js +260 -0
  128. package/dist/templates/prompts.js.map +1 -0
  129. package/dist/tools.d.ts +26 -0
  130. package/dist/tools.d.ts.map +1 -0
  131. package/dist/tools.js +1033 -0
  132. package/dist/tools.js.map +1 -0
  133. package/dist/watcher.d.ts +25 -0
  134. package/dist/watcher.d.ts.map +1 -0
  135. package/dist/watcher.js +84 -0
  136. package/dist/watcher.js.map +1 -0
  137. package/dist/webui/client/dist/index.html +1885 -0
  138. package/dist/webui/server.d.ts +31 -0
  139. package/dist/webui/server.d.ts.map +1 -0
  140. package/dist/webui/server.js +566 -0
  141. package/dist/webui/server.js.map +1 -0
  142. package/dist/wiki.d.ts +103 -0
  143. package/dist/wiki.d.ts.map +1 -0
  144. package/dist/wiki.js +428 -0
  145. package/dist/wiki.js.map +1 -0
  146. package/package.json +142 -0
  147. package/scripts/gepa/__pycache__/dataset.cpython-313.pyc +0 -0
  148. package/scripts/gepa/__pycache__/lm_providers.cpython-313.pyc +0 -0
  149. package/scripts/gepa/__pycache__/metric.cpython-313.pyc +0 -0
  150. package/scripts/gepa/__pycache__/program.cpython-313.pyc +0 -0
  151. package/scripts/gepa/__pycache__/wiki_reader.cpython-313.pyc +0 -0
  152. package/scripts/gepa/dataset.py +192 -0
  153. package/scripts/gepa/lm_providers.py +472 -0
  154. package/scripts/gepa/metric.py +279 -0
  155. package/scripts/gepa/optimize.py +367 -0
  156. package/scripts/gepa/program.py +99 -0
  157. package/scripts/gepa/pyproject.toml +19 -0
  158. package/scripts/gepa/run-all.sh +53 -0
  159. package/scripts/gepa/uv.lock +2241 -0
  160. package/scripts/gepa/wiki_reader.py +113 -0
  161. package/skills/para/SKILL.md +77 -0
  162. package/skills/setup/SKILL.md +20 -0
  163. package/src/capture.ts +563 -0
  164. package/src/cli.ts +416 -0
  165. package/src/commands.ts +878 -0
  166. package/src/context.ts +390 -0
  167. package/src/daemon.ts +288 -0
  168. package/src/frontmatter.ts +219 -0
  169. package/src/gepa/index.ts +287 -0
  170. package/src/gepa/optimized/capture-prompt.txt +65 -0
  171. package/src/index.ts +384 -0
  172. package/src/ingest.ts +177 -0
  173. package/src/link-discovery.ts +170 -0
  174. package/src/link-utils.ts +169 -0
  175. package/src/lint.ts +1018 -0
  176. package/src/maintainer.ts +404 -0
  177. package/src/processor.ts +415 -0
  178. package/src/python/__pycache__/minimax_lm.cpython-312.pyc +0 -0
  179. package/src/python/minimax_lm.py +198 -0
  180. package/src/python/rlm_capture.py +215 -0
  181. package/src/query.ts +148 -0
  182. package/src/raw.ts +276 -0
  183. package/src/redact.ts +159 -0
  184. package/src/scope.ts +214 -0
  185. package/src/scripts/bulk-link-fix.ts +126 -0
  186. package/src/session-tools.ts +260 -0
  187. package/src/state.ts +271 -0
  188. package/src/store.ts +288 -0
  189. package/src/summarize.ts +273 -0
  190. package/src/tag-registry.ts +157 -0
  191. package/src/templates/index.md +17 -0
  192. package/src/templates/prompts.ts +274 -0
  193. package/src/templates/schema.md +116 -0
  194. package/src/tools.ts +1293 -0
  195. package/src/watcher.ts +101 -0
  196. package/src/webui/client/dist/index.html +1885 -0
  197. package/src/webui/server.ts +765 -0
  198. package/src/wiki.ts +550 -0
@@ -0,0 +1,56 @@
1
+ /**
2
+ * qmd store lifecycle — manages the @picassio/qmd store instance.
3
+ *
4
+ * Handles store creation/opening, search with scope filtering,
5
+ * re-indexing after wiki changes, and embedding lifecycle.
6
+ */
7
+ import type { QMDStore } from "@picassio/qmd";
8
+ import type { PageFrontmatter, PageRef, ParaCategory } from "./wiki.js";
9
+ import type { ProjectScope } from "./scope.js";
10
+ export type { QMDStore } from "@picassio/qmd";
11
+ export interface WikiSearchOptions {
12
+ scope?: ProjectScope;
13
+ category?: ParaCategory;
14
+ limit?: number;
15
+ includeArchives?: boolean;
16
+ graphBoost?: boolean;
17
+ }
18
+ export interface WikiSearchResult {
19
+ page: PageRef;
20
+ score: number;
21
+ snippet: string;
22
+ frontmatter: PageFrontmatter;
23
+ }
24
+ /**
25
+ * Open and configure a qmd store for the wiki directory.
26
+ *
27
+ * Creates the store with two collections:
28
+ * - wiki: all .md files except raw/
29
+ * - raw: .md files under raw/, not included in default queries
30
+ *
31
+ * Adds PARA category contexts, runs update() for BM25,
32
+ * and schedules embed() in the background.
33
+ */
34
+ export declare function openStore(wikiDir: string): Promise<QMDStore>;
35
+ /**
36
+ * Close the store. Awaits any pending embed operation (with timeout) first.
37
+ */
38
+ export declare function closeStore(store: QMDStore): Promise<void>;
39
+ /**
40
+ * Search the wiki with scope and category filtering.
41
+ *
42
+ * Uses BM25 search (searchLex) which requires no LLM. Each result's
43
+ * frontmatter is parsed to apply scope/category/archive filters.
44
+ */
45
+ export declare function searchWiki(store: QMDStore, query: string, opts: WikiSearchOptions): Promise<WikiSearchResult[]>;
46
+ /**
47
+ * Re-index the store (fast filesystem scan). Makes new/changed
48
+ * content BM25-searchable immediately. Call after wiki writes.
49
+ */
50
+ export declare function reindex(store: QMDStore): Promise<void>;
51
+ /**
52
+ * Generate vector embeddings for new/changed pages.
53
+ * Slow — call only at startup (via openStore) or shutdown.
54
+ */
55
+ export declare function embedIfNeeded(store: QMDStore): Promise<void>;
56
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,eAAe,CAAC;AAGhE,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAI9C,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,eAAe,CAAC;CAC9B;AAsCD;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwDlE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAS/D;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,QAAQ,EACf,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAoE7B;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5D;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAElE"}
package/dist/store.js ADDED
@@ -0,0 +1,227 @@
1
+ /**
2
+ * qmd store lifecycle — manages the @picassio/qmd store instance.
3
+ *
4
+ * Handles store creation/opening, search with scope filtering,
5
+ * re-indexing after wiki changes, and embedding lifecycle.
6
+ */
7
+ import { readFileSync, existsSync } from "node:fs";
8
+ import { homedir } from "node:os";
9
+ import { join } from "node:path";
10
+ import { parse as parseYaml } from "yaml";
11
+ import { createStore, extractSnippet } from "@picassio/qmd";
12
+ import { parseFrontmatter } from "./frontmatter.js";
13
+ import { matchesScope } from "./scope.js";
14
+ // -- PARA context descriptions -----------------------------------------------
15
+ const PARA_CONTEXTS = {
16
+ "projects/": "Active projects with defined goals and end dates",
17
+ "areas/": "Ongoing responsibilities and standards",
18
+ "resources/": "Reference material and how-to guides",
19
+ "archives/": "Completed or deprecated items",
20
+ };
21
+ const RAW_CONTEXT = "Immutable source material: articles, documents, notes. Not synthesized.";
22
+ // -- Pending embed tracking --------------------------------------------------
23
+ const pendingEmbeds = new WeakMap();
24
+ // -- qmd config loading ------------------------------------------------------
25
+ /**
26
+ * Read providers from ~/.config/qmd/index.yml.
27
+ * Returns undefined if no config file or no providers configured.
28
+ */
29
+ function loadQmdProviders() {
30
+ const configPath = join(homedir(), ".config", "qmd", "index.yml");
31
+ if (!existsSync(configPath))
32
+ return undefined;
33
+ try {
34
+ const content = readFileSync(configPath, "utf-8");
35
+ const config = parseYaml(content);
36
+ return config?.providers;
37
+ }
38
+ catch {
39
+ return undefined;
40
+ }
41
+ }
42
+ // -- Functions ---------------------------------------------------------------
43
+ /**
44
+ * Open and configure a qmd store for the wiki directory.
45
+ *
46
+ * Creates the store with two collections:
47
+ * - wiki: all .md files except raw/
48
+ * - raw: .md files under raw/, not included in default queries
49
+ *
50
+ * Adds PARA category contexts, runs update() for BM25,
51
+ * and schedules embed() in the background.
52
+ */
53
+ export async function openStore(wikiDir) {
54
+ // Read providers from ~/.config/qmd/index.yml so external API providers
55
+ // (embed, chat, rerank) are used instead of local GGUF models.
56
+ const providers = loadQmdProviders();
57
+ const store = await createStore({
58
+ dbPath: join(wikiDir, ".qmd.sqlite"),
59
+ config: {
60
+ collections: {
61
+ wiki: {
62
+ path: wikiDir,
63
+ pattern: "**/*.md",
64
+ ignore: ["raw/**"],
65
+ },
66
+ raw: {
67
+ path: join(wikiDir, "raw"),
68
+ pattern: "**/*.md",
69
+ includeByDefault: false,
70
+ },
71
+ },
72
+ ...(providers ? { providers: providers } : {}),
73
+ },
74
+ });
75
+ // Add PARA category contexts to the wiki collection
76
+ for (const [prefix, description] of Object.entries(PARA_CONTEXTS)) {
77
+ await store.addContext("wiki", prefix, description);
78
+ }
79
+ // Add context for the raw collection root
80
+ await store.addContext("raw", "/", RAW_CONTEXT);
81
+ // Sync filesystem -> BM25 index (fast, search ready immediately)
82
+ await store.update();
83
+ // Schedule embedding in background (non-blocking).
84
+ // BM25 search works immediately; hybrid search improves once embed completes.
85
+ // Suppress console.error from qmd's internal embed failures.
86
+ const origError = console.error;
87
+ const embedPromise = store.embed().then(() => {
88
+ pendingEmbeds.delete(store);
89
+ }).catch(() => {
90
+ // Embedding failures are non-fatal — hybrid search degrades to BM25
91
+ pendingEmbeds.delete(store);
92
+ }).finally(() => {
93
+ console.error = origError;
94
+ });
95
+ // Temporarily suppress embed error noise during background embed
96
+ console.error = (...args) => {
97
+ const msg = String(args[0] ?? "");
98
+ if (msg.includes("embed error") || msg.includes("fetch failed"))
99
+ return;
100
+ origError(...args);
101
+ };
102
+ pendingEmbeds.set(store, embedPromise);
103
+ return store;
104
+ }
105
+ /**
106
+ * Close the store. Awaits any pending embed operation (with timeout) first.
107
+ */
108
+ export async function closeStore(store) {
109
+ const pending = pendingEmbeds.get(store);
110
+ if (pending) {
111
+ // Wait for pending embed with a short timeout — don't hang forever
112
+ const timeout = new Promise((resolve) => setTimeout(resolve, 5_000));
113
+ await Promise.race([pending, timeout]);
114
+ pendingEmbeds.delete(store);
115
+ }
116
+ await store.close();
117
+ }
118
+ /**
119
+ * Search the wiki with scope and category filtering.
120
+ *
121
+ * Uses BM25 search (searchLex) which requires no LLM. Each result's
122
+ * frontmatter is parsed to apply scope/category/archive filters.
123
+ */
124
+ export async function searchWiki(store, query, opts) {
125
+ const limit = opts.limit ?? 10;
126
+ // Build metadata filter for SQL-level filtering (qmd v2.2.0+)
127
+ // Note: we can only use metadata.category here, NOT scope.
128
+ // Scope filtering must remain as post-filter because:
129
+ // - Pages with scope:["global"] must match ANY project scope
130
+ // - Pages in the scope.include list need OR matching
131
+ // - The exclude list needs post-filter negation
132
+ // SQL-level scope filter would miss global pages.
133
+ const metadata = {};
134
+ if (opts.category) {
135
+ metadata.category = opts.category;
136
+ }
137
+ const fetchLimit = opts.scope ? limit * 3 : limit;
138
+ const rawResults = await store.searchLex(query, {
139
+ limit: fetchLimit,
140
+ collection: "wiki",
141
+ metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
142
+ graphBoost: opts.graphBoost ?? true,
143
+ });
144
+ const results = [];
145
+ for (const result of rawResults) {
146
+ // Parse category and slug from the display path (e.g. "projects/auth-refactor.md")
147
+ const parsed = parseDisplayPath(result.displayPath);
148
+ if (!parsed)
149
+ continue;
150
+ const { category, slug } = parsed;
151
+ // Exclude archives unless explicitly requested (post-filter fallback
152
+ // for pages without frontmatter metadata)
153
+ if (category === "archives" && !opts.includeArchives) {
154
+ continue;
155
+ }
156
+ // Parse frontmatter from body
157
+ const body = result.body ?? "";
158
+ const { frontmatter } = parseFrontmatter(body);
159
+ // Scope post-filter fallback for pages without metadata
160
+ if (opts.scope && !matchesScope(frontmatter.scope, opts.scope)) {
161
+ continue;
162
+ }
163
+ // Extract a snippet for display
164
+ const snippetResult = extractSnippet(body, query);
165
+ const snippet = snippetResult.snippet;
166
+ results.push({
167
+ page: {
168
+ category,
169
+ slug,
170
+ title: frontmatter.title || result.title,
171
+ path: `${category}/${slug}.md`,
172
+ },
173
+ score: result.score,
174
+ snippet,
175
+ frontmatter,
176
+ });
177
+ if (results.length >= limit)
178
+ break;
179
+ }
180
+ return results;
181
+ }
182
+ /**
183
+ * Re-index the store (fast filesystem scan). Makes new/changed
184
+ * content BM25-searchable immediately. Call after wiki writes.
185
+ */
186
+ export async function reindex(store) {
187
+ await store.update();
188
+ }
189
+ /**
190
+ * Generate vector embeddings for new/changed pages.
191
+ * Slow — call only at startup (via openStore) or shutdown.
192
+ */
193
+ export async function embedIfNeeded(store) {
194
+ await store.embed();
195
+ }
196
+ // -- Helpers -----------------------------------------------------------------
197
+ /** Valid PARA categories for path parsing. */
198
+ const VALID_CATEGORIES = new Set([
199
+ "projects",
200
+ "areas",
201
+ "resources",
202
+ "archives",
203
+ ]);
204
+ /**
205
+ * Parse a qmd display path into category + slug.
206
+ * Display paths from searchLex include the collection prefix:
207
+ * "wiki/resources/ssl-certs.md" or "wiki/schema.md"
208
+ * Returns null for root-level files (schema.md, index.md, etc.) — they
209
+ * still appear in search results but aren't PageRef-able.
210
+ */
211
+ function parseDisplayPath(displayPath) {
212
+ const parts = displayPath.split("/");
213
+ // Display paths are: collection/category/slug.md (3+ parts)
214
+ // or collection/file.md (2 parts, root-level files like schema.md)
215
+ if (parts.length < 3)
216
+ return null;
217
+ // Skip collection prefix (parts[0] = "wiki")
218
+ const category = parts[1];
219
+ if (!VALID_CATEGORIES.has(category))
220
+ return null;
221
+ const filename = parts.slice(2).join("/");
222
+ if (!filename.endsWith(".md"))
223
+ return null;
224
+ const slug = filename.slice(0, -3);
225
+ return { category: category, slug };
226
+ }
227
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Wiki summarization — adapts pi's compaction approach for wiki knowledge.
3
+ *
4
+ * Produces structured wiki summaries in the standard format:
5
+ * Topic, Key Facts, Insights, Connections, Open Questions, Sources.
6
+ *
7
+ * Supports ingest, session, page, and iterative summarization modes.
8
+ *
9
+ * Functions here generate prompt strings — they do NOT call the LLM.
10
+ * The caller (capture.ts, tools.ts) passes the prompt to a standalone Agent.
11
+ */
12
+ import type { WikiPage } from "./wiki.js";
13
+ import type { ParaCategory } from "./wiki.js";
14
+ import type { ProjectScope } from "./scope.js";
15
+ export interface SummarizeOptions {
16
+ mode: "ingest" | "session" | "page" | "iterative";
17
+ existingContent?: string;
18
+ scope: ProjectScope;
19
+ category?: ParaCategory;
20
+ }
21
+ /**
22
+ * Serialize session messages for wiki capture.
23
+ *
24
+ * Converts AgentMessage[] to a text representation that prevents the LLM
25
+ * from treating it as a conversation to continue. Uses pi's convertToLlm +
26
+ * serializeConversation when the messages contain pi-specific types
27
+ * (bashExecution, compactionSummary, branchSummary, etc.). Falls back to
28
+ * a compatible reimplementation for plain user/assistant/toolResult messages.
29
+ *
30
+ * @param messages - AgentMessage[] from @mariozechner/pi-agent-core
31
+ * @returns Serialized text in [User]: / [Assistant]: / [Tool result]: format
32
+ */
33
+ export declare function serializeSessionForWiki(messages: unknown[]): string;
34
+ /**
35
+ * Generate a wiki-format summary prompt from raw content.
36
+ *
37
+ * Returns the prompt string to send to the LLM. The caller passes this
38
+ * to a standalone Agent or includes it in a tool result for the session agent.
39
+ *
40
+ * @param content - Source text, serialized conversation, or page content
41
+ * @param options - Summarization mode and context
42
+ * @returns Prompt string for the LLM
43
+ */
44
+ export declare function generateSummary(content: string, options: SummarizeOptions): string;
45
+ /**
46
+ * Generate an overview prompt from multiple wiki pages.
47
+ *
48
+ * Used by /wiki-summarize and wiki_summarize tool to produce high-level
49
+ * overviews of a category or the entire wiki.
50
+ *
51
+ * @param pages - Wiki pages to summarize
52
+ * @param scope - Current project scope for context
53
+ * @returns Prompt string for the LLM
54
+ */
55
+ export declare function generateOverviewPrompt(pages: WikiPage[], scope: ProjectScope): string;
56
+ //# sourceMappingURL=summarize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarize.d.ts","sourceRoot":"","sources":["../src/summarize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAc/C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,CAAC;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,YAAY,CAAC;IACpB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAuGD;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,OAAO,EAAE,GAClB,MAAM,CAYR;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,gBAAgB,GACxB,MAAM,CA2DR;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,QAAQ,EAAE,EACjB,KAAK,EAAE,YAAY,GAClB,MAAM,CAqBR"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Wiki summarization — adapts pi's compaction approach for wiki knowledge.
3
+ *
4
+ * Produces structured wiki summaries in the standard format:
5
+ * Topic, Key Facts, Insights, Connections, Open Questions, Sources.
6
+ *
7
+ * Supports ingest, session, page, and iterative summarization modes.
8
+ *
9
+ * Functions here generate prompt strings — they do NOT call the LLM.
10
+ * The caller (capture.ts, tools.ts) passes the prompt to a standalone Agent.
11
+ */
12
+ import { convertToLlm, serializeConversation, } from "@mariozechner/pi-coding-agent";
13
+ import { SUMMARIZE_SYSTEM_PROMPT, ITERATIVE_UPDATE_PROMPT, OVERVIEW_PROMPT, CAPTURE_PROMPT, } from "./templates/prompts.js";
14
+ // -- Constants ---------------------------------------------------------------
15
+ /** Maximum characters for a tool result in serialized output. */
16
+ const TOOL_RESULT_MAX_CHARS = 2000;
17
+ // -- Fallback serialization --------------------------------------------------
18
+ /**
19
+ * Truncate text to a maximum character length for summarization.
20
+ * Keeps the beginning and appends a truncation marker.
21
+ */
22
+ function truncateForSummary(text, maxChars) {
23
+ if (text.length <= maxChars)
24
+ return text;
25
+ const truncatedChars = text.length - maxChars;
26
+ return `${text.slice(0, maxChars)}\n\n[... ${truncatedChars} more characters truncated]`;
27
+ }
28
+ /**
29
+ * Extract text content from a message content field.
30
+ * Handles both string and array-of-blocks shapes.
31
+ */
32
+ function extractTextContent(content) {
33
+ if (typeof content === "string")
34
+ return content;
35
+ if (!Array.isArray(content))
36
+ return "";
37
+ return content
38
+ .filter((c) => typeof c === "object" &&
39
+ c !== null &&
40
+ "type" in c &&
41
+ c.type === "text" &&
42
+ "text" in c)
43
+ .map((c) => c.text)
44
+ .join("");
45
+ }
46
+ /**
47
+ * Fallback serialization that mirrors pi's serializeConversation format.
48
+ * Used when @mariozechner/pi-coding-agent is not available.
49
+ *
50
+ * Formats: [User]:, [Assistant]:, [Assistant thinking]:,
51
+ * [Assistant tool calls]:, [Tool result]:
52
+ */
53
+ function serializeMessagesFallback(messages) {
54
+ const parts = [];
55
+ for (const msg of messages) {
56
+ if (typeof msg !== "object" || msg === null || !("role" in msg))
57
+ continue;
58
+ const m = msg;
59
+ if (m.role === "user") {
60
+ const text = extractTextContent(m.content);
61
+ if (text)
62
+ parts.push(`[User]: ${text}`);
63
+ }
64
+ else if (m.role === "assistant") {
65
+ const content = m.content;
66
+ if (!Array.isArray(content))
67
+ continue;
68
+ const textParts = [];
69
+ const thinkingParts = [];
70
+ const toolCalls = [];
71
+ for (const block of content) {
72
+ if (typeof block !== "object" || block === null || !("type" in block))
73
+ continue;
74
+ const b = block;
75
+ if (b.type === "text" && typeof b.text === "string") {
76
+ textParts.push(b.text);
77
+ }
78
+ else if (b.type === "thinking" && typeof b.thinking === "string") {
79
+ thinkingParts.push(b.thinking);
80
+ }
81
+ else if (b.type === "toolCall" && typeof b.name === "string") {
82
+ const args = (b.arguments ?? {});
83
+ const argsStr = Object.entries(args)
84
+ .map(([k, v]) => `${k}=${JSON.stringify(v)}`)
85
+ .join(", ");
86
+ toolCalls.push(`${b.name}(${argsStr})`);
87
+ }
88
+ }
89
+ if (thinkingParts.length > 0) {
90
+ parts.push(`[Assistant thinking]: ${thinkingParts.join("\n")}`);
91
+ }
92
+ if (textParts.length > 0) {
93
+ parts.push(`[Assistant]: ${textParts.join("\n")}`);
94
+ }
95
+ if (toolCalls.length > 0) {
96
+ parts.push(`[Assistant tool calls]: ${toolCalls.join("; ")}`);
97
+ }
98
+ }
99
+ else if (m.role === "toolResult") {
100
+ const text = extractTextContent(m.content);
101
+ if (text) {
102
+ parts.push(`[Tool result]: ${truncateForSummary(text, TOOL_RESULT_MAX_CHARS)}`);
103
+ }
104
+ }
105
+ }
106
+ return parts.join("\n\n");
107
+ }
108
+ // -- Public API --------------------------------------------------------------
109
+ /**
110
+ * Serialize session messages for wiki capture.
111
+ *
112
+ * Converts AgentMessage[] to a text representation that prevents the LLM
113
+ * from treating it as a conversation to continue. Uses pi's convertToLlm +
114
+ * serializeConversation when the messages contain pi-specific types
115
+ * (bashExecution, compactionSummary, branchSummary, etc.). Falls back to
116
+ * a compatible reimplementation for plain user/assistant/toolResult messages.
117
+ *
118
+ * @param messages - AgentMessage[] from @mariozechner/pi-agent-core
119
+ * @returns Serialized text in [User]: / [Assistant]: / [Tool result]: format
120
+ */
121
+ export function serializeSessionForWiki(messages) {
122
+ // Use pi's convertToLlm to handle custom message types (bashExecution,
123
+ // compactionSummary, branchSummary, etc.), then serialize the resulting
124
+ // standard LLM messages.
125
+ try {
126
+ const llmMessages = convertToLlm(messages);
127
+ return serializeConversation(llmMessages);
128
+ }
129
+ catch {
130
+ // If convertToLlm fails (e.g., unexpected message shapes), fall back
131
+ // to our reimplementation that handles the base roles.
132
+ return serializeMessagesFallback(messages);
133
+ }
134
+ }
135
+ /**
136
+ * Generate a wiki-format summary prompt from raw content.
137
+ *
138
+ * Returns the prompt string to send to the LLM. The caller passes this
139
+ * to a standalone Agent or includes it in a tool result for the session agent.
140
+ *
141
+ * @param content - Source text, serialized conversation, or page content
142
+ * @param options - Summarization mode and context
143
+ * @returns Prompt string for the LLM
144
+ */
145
+ export function generateSummary(content, options) {
146
+ const scopeInfo = `Current scope: ${options.scope.name} (tags: ${options.scope.include.join(", ")})`;
147
+ const categoryHint = options.category ? `\nSuggested PARA category: ${options.category}` : "";
148
+ switch (options.mode) {
149
+ case "ingest":
150
+ return [
151
+ SUMMARIZE_SYSTEM_PROMPT,
152
+ "",
153
+ scopeInfo,
154
+ categoryHint,
155
+ "",
156
+ "Produce a wiki page from the following source material:",
157
+ "",
158
+ "<source-content>",
159
+ content,
160
+ "</source-content>",
161
+ ].join("\n");
162
+ case "session":
163
+ return [
164
+ CAPTURE_PROMPT,
165
+ content,
166
+ "</session-conversation>",
167
+ ].join("\n");
168
+ case "page":
169
+ return [
170
+ SUMMARIZE_SYSTEM_PROMPT,
171
+ "",
172
+ scopeInfo,
173
+ "",
174
+ "Summarize the following wiki page into a concise overview:",
175
+ "",
176
+ "<page-content>",
177
+ content,
178
+ "</page-content>",
179
+ ].join("\n");
180
+ case "iterative":
181
+ if (!options.existingContent) {
182
+ // No existing content — treat as a fresh page
183
+ return generateSummary(content, { ...options, mode: "ingest" });
184
+ }
185
+ return [
186
+ ITERATIVE_UPDATE_PROMPT,
187
+ "",
188
+ scopeInfo,
189
+ categoryHint,
190
+ "",
191
+ "<existing-page>",
192
+ options.existingContent,
193
+ "</existing-page>",
194
+ "",
195
+ "<new-content>",
196
+ content,
197
+ "</new-content>",
198
+ ].join("\n");
199
+ }
200
+ }
201
+ /**
202
+ * Generate an overview prompt from multiple wiki pages.
203
+ *
204
+ * Used by /wiki-summarize and wiki_summarize tool to produce high-level
205
+ * overviews of a category or the entire wiki.
206
+ *
207
+ * @param pages - Wiki pages to summarize
208
+ * @param scope - Current project scope for context
209
+ * @returns Prompt string for the LLM
210
+ */
211
+ export function generateOverviewPrompt(pages, scope) {
212
+ const scopeInfo = `Current scope: ${scope.name} (tags: ${scope.include.join(", ")})`;
213
+ const pageEntries = pages.map((page) => {
214
+ const fm = page.frontmatter;
215
+ return [
216
+ `### ${fm.title} (${page.category}/${page.slug})`,
217
+ `PARA: ${fm.para} | Scope: ${fm.scope.join(", ")} | Tags: ${fm.tags.join(", ")}`,
218
+ "",
219
+ page.body,
220
+ ].join("\n");
221
+ });
222
+ return [
223
+ OVERVIEW_PROMPT,
224
+ "",
225
+ scopeInfo,
226
+ `Total pages: ${pages.length}`,
227
+ "",
228
+ ...pageEntries,
229
+ ].join("\n");
230
+ }
231
+ //# sourceMappingURL=summarize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarize.js","sourceRoot":"","sources":["../src/summarize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Canonical tag registry — normalizes and deduplicates wiki page tags.
3
+ *
4
+ * Rules:
5
+ * 1. Spaces → hyphens ("session files" → "session-files")
6
+ * 2. Lowercase everything
7
+ * 3. Map aliases → canonical tags
8
+ * 4. Remove tags that duplicate scope values on the same page
9
+ * 5. Deduplicate
10
+ */
11
+ /**
12
+ * Normalize a scope value.
13
+ *
14
+ * Scope should be a project name (kebab-case, single token), not a topic
15
+ * description. The daemon LLM sometimes writes freeform multi-word
16
+ * descriptions like "session exploration" or "mono project" as scope.
17
+ *
18
+ * Rules:
19
+ * 1. Trim + lowercase
20
+ * 2. If the value contains a known project name as a prefix, extract it
21
+ * (e.g. "pi-para daemon" → "pi-para", "pi-mono project" → "pi-mono")
22
+ * 3. If still multi-word after extraction, drop it — it's a topic
23
+ * description, not a project name
24
+ * 4. Return the clean kebab-case scope
25
+ *
26
+ * This is project-agnostic — works for any project, not just pi-para.
27
+ */
28
+ export declare function normalizeScope(scope: string): string | null;
29
+ /**
30
+ * Normalize a full scope list:
31
+ * 1. Normalize each value
32
+ * 2. Deduplicate
33
+ * 3. Ensure at least one scope remains (fallback to "global")
34
+ */
35
+ export declare function normalizeScopes(scopes: string[]): string[];
36
+ /**
37
+ * Normalize a single tag:
38
+ * 1. Trim + lowercase
39
+ * 2. Spaces → hyphens
40
+ * 3. Resolve alias → canonical
41
+ */
42
+ export declare function normalizeTag(tag: string): string;
43
+ /**
44
+ * Normalize a full tag list for a page, given its scope.
45
+ *
46
+ * 1. Normalize each tag
47
+ * 2. Remove tags that exactly match a scope value
48
+ * 3. Deduplicate
49
+ * 4. Sort alphabetically
50
+ */
51
+ export declare function normalizeTags(tags: string[], scope: string[]): string[];
52
+ /**
53
+ * Get the full alias map for external inspection (e.g., lint reporting).
54
+ */
55
+ export declare function getAliasMap(): ReadonlyMap<string, string>;
56
+ //# sourceMappingURL=tag-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag-registry.d.ts","sourceRoot":"","sources":["../src/tag-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmB3D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAQ1D;AAkDD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKhD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAavE;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAEzD"}