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
package/package.json ADDED
@@ -0,0 +1,142 @@
1
+ {
2
+ "name": "pi-para",
3
+ "version": "0.5.2",
4
+ "description": "PARA Knowledge Base Extension for pi \u2014 persistent, LLM-curated personal wiki",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./wiki": {
14
+ "types": "./dist/wiki.d.ts",
15
+ "import": "./dist/wiki.js"
16
+ },
17
+ "./store": {
18
+ "types": "./dist/store.d.ts",
19
+ "import": "./dist/store.js"
20
+ },
21
+ "./frontmatter": {
22
+ "types": "./dist/frontmatter.d.ts",
23
+ "import": "./dist/frontmatter.js"
24
+ },
25
+ "./raw": {
26
+ "types": "./dist/raw.d.ts",
27
+ "import": "./dist/raw.js"
28
+ },
29
+ "./scope": {
30
+ "types": "./dist/scope.d.ts",
31
+ "import": "./dist/scope.js"
32
+ },
33
+ "./lint": {
34
+ "types": "./dist/lint.d.ts",
35
+ "import": "./dist/lint.js"
36
+ },
37
+ "./query": {
38
+ "types": "./dist/query.d.ts",
39
+ "import": "./dist/query.js"
40
+ },
41
+ "./ingest": {
42
+ "types": "./dist/ingest.d.ts",
43
+ "import": "./dist/ingest.js"
44
+ },
45
+ "./summarize": {
46
+ "types": "./dist/summarize.d.ts",
47
+ "import": "./dist/summarize.js"
48
+ },
49
+ "./link-utils": {
50
+ "types": "./dist/link-utils.d.ts",
51
+ "import": "./dist/link-utils.js"
52
+ },
53
+ "./tag-registry": {
54
+ "types": "./dist/tag-registry.d.ts",
55
+ "import": "./dist/tag-registry.js"
56
+ },
57
+ "./link-discovery": {
58
+ "types": "./dist/link-discovery.d.ts",
59
+ "import": "./dist/link-discovery.js"
60
+ },
61
+ "./redact": {
62
+ "types": "./dist/redact.d.ts",
63
+ "import": "./dist/redact.js"
64
+ },
65
+ "./context": {
66
+ "types": "./dist/context.d.ts",
67
+ "import": "./dist/context.js"
68
+ }
69
+ },
70
+ "pi": {
71
+ "extensions": [
72
+ "./src/index.ts"
73
+ ],
74
+ "skills": [
75
+ "./skills"
76
+ ]
77
+ },
78
+ "files": [
79
+ "dist",
80
+ "src",
81
+ "scripts",
82
+ "CHANGELOG.md",
83
+ "README.md",
84
+ "skills",
85
+ "SETUP.md"
86
+ ],
87
+ "scripts": {
88
+ "clean": "rm -rf dist",
89
+ "build": "tsc -p tsconfig.json && mkdir -p dist/webui/client/dist && cp src/webui/client/dist/index.html dist/webui/client/dist/index.html && mkdir -p dist/gepa/optimized && cp -r src/gepa/optimized/*.txt dist/gepa/optimized/ 2>/dev/null || true",
90
+ "check": "tsc --noEmit",
91
+ "test": "vitest --run",
92
+ "fix-links": "tsx src/scripts/bulk-link-fix.ts",
93
+ "fix-links:dry": "tsx src/scripts/bulk-link-fix.ts --dry-run"
94
+ },
95
+ "dependencies": {
96
+ "qmd-engine": "^2.3.3",
97
+ "@types/better-sqlite3": "^7.6.13",
98
+ "better-sqlite3": "^11.9.1",
99
+ "yaml": "^2.8.2"
100
+ },
101
+ "peerDependencies": {
102
+ "@mariozechner/pi-agent-core": "^0.70.2",
103
+ "@mariozechner/pi-ai": "^0.70.2",
104
+ "@mariozechner/pi-coding-agent": "^0.70.2",
105
+ "@mariozechner/pi-tui": "^0.70.2",
106
+ "typebox": "^1.1.24"
107
+ },
108
+ "peerDependenciesMeta": {},
109
+ "devDependencies": {
110
+ "@mariozechner/pi-agent-core": "^0.70.2",
111
+ "@mariozechner/pi-ai": "^0.70.2",
112
+ "@mariozechner/pi-coding-agent": "^0.70.2",
113
+ "@mariozechner/pi-tui": "^0.70.2",
114
+ "@types/node": "^24.3.0",
115
+ "tsx": "^4.21.0",
116
+ "typebox": "^1.1.34",
117
+ "typescript": "^5.7.3",
118
+ "vitest": "^3.2.4"
119
+ },
120
+ "keywords": [
121
+ "pi",
122
+ "extension",
123
+ "para",
124
+ "knowledge-base",
125
+ "wiki"
126
+ ],
127
+ "license": "MIT",
128
+ "repository": {
129
+ "type": "git",
130
+ "url": "git+https://github.com/picassio/pi-para.git"
131
+ },
132
+ "homepage": "https://github.com/picassio/pi-para#readme",
133
+ "bugs": {
134
+ "url": "https://github.com/picassio/pi-para/issues"
135
+ },
136
+ "publishConfig": {
137
+ "access": "public"
138
+ },
139
+ "bin": {
140
+ "pi-para-daemon": "./dist/cli.js"
141
+ }
142
+ }
@@ -0,0 +1,192 @@
1
+ """Build trainset/valset from real wiki pages.
2
+
3
+ Each example pairs a synthetic task context (derived from the page topic)
4
+ with the actual page body as expected output. The proxy module runs the
5
+ instruction on the task context; the metric scores how well the output
6
+ matches the gold page.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import random
12
+ from typing import Any
13
+
14
+ import dspy
15
+
16
+ from wiki_reader import WikiPage, load_all_pages, get_wiki_stats
17
+
18
+
19
+ # -- Task context generators --------------------------------------------------
20
+
21
+ def _capture_context(page: WikiPage) -> str:
22
+ """Generate a synthetic capture-style task context from a wiki page."""
23
+ scope_str = ", ".join(page.scope) if page.scope else "unknown"
24
+ tags_str = ", ".join(page.tags[:5]) if page.tags else ""
25
+ # Simulate what a session about this topic would look like
26
+ return (
27
+ f"A coding session about '{page.title}' in the {scope_str} project. "
28
+ f"Topics covered: {tags_str}. "
29
+ f"Extract and organize the key knowledge from this session into a wiki page."
30
+ )
31
+
32
+
33
+ def _ingest_context(page: WikiPage) -> str:
34
+ """Generate a synthetic ingest-style task context."""
35
+ return (
36
+ f"Ingest the following source material about '{page.title}' "
37
+ f"into the PARA wiki. Organize into a structured page with "
38
+ f"proper frontmatter, sections, and cross-references."
39
+ )
40
+
41
+
42
+ def _query_context(page: WikiPage) -> str:
43
+ """Generate a synthetic query-style task context."""
44
+ return (
45
+ f"The user asked about '{page.title}'. "
46
+ f"Search results returned pages related to: {', '.join(page.scope)}. "
47
+ f"Synthesize a helpful answer citing specific wiki pages."
48
+ )
49
+
50
+
51
+ def _maintenance_context(page: WikiPage) -> str:
52
+ """Generate a synthetic maintenance-style task context."""
53
+ link_count = len(page.links)
54
+ return (
55
+ f"Review the wiki page '{page.title}' ({page.category}/{page.slug}). "
56
+ f"It has {link_count} outgoing links, scope [{', '.join(page.scope)}], "
57
+ f"tags [{', '.join(page.tags[:5])}]. "
58
+ f"Check for correct categorization, missing links, and content quality."
59
+ )
60
+
61
+
62
+ def _tool_context(page: WikiPage) -> str:
63
+ """Generate a task context for tool instruction optimization."""
64
+ return (
65
+ f"A user wants to work with the wiki page '{page.title}' "
66
+ f"in category '{page.category}', scope [{', '.join(page.scope)}]. "
67
+ f"Guide them on how to use wiki tools effectively."
68
+ )
69
+
70
+
71
+ def _skill_context(page: WikiPage) -> str:
72
+ """Generate a task context for skill optimization."""
73
+ return (
74
+ f"Working on a task related to '{page.title}' in the {', '.join(page.scope)} project. "
75
+ f"Apply the PARA knowledge management methodology to this work."
76
+ )
77
+
78
+
79
+ # Target type → context generator
80
+ CONTEXT_GENERATORS = {
81
+ "capture": _capture_context,
82
+ "ingest": _ingest_context,
83
+ "query": _query_context,
84
+ "maintenance": _maintenance_context,
85
+ "tool": _tool_context,
86
+ "skill": _skill_context,
87
+ "system": _capture_context, # system prompts use capture-style context
88
+ }
89
+
90
+
91
+ # -- Dataset builder -----------------------------------------------------------
92
+
93
+ def build_dataset(
94
+ wiki_dir: str,
95
+ target_type: str = "capture",
96
+ max_examples: int = 50,
97
+ val_ratio: float = 0.4,
98
+ seed: int = 42,
99
+ ) -> tuple[list[dspy.Example], list[dspy.Example]]:
100
+ """Build train/val datasets from real wiki pages.
101
+
102
+ Args:
103
+ wiki_dir: Path to wiki directory (e.g. ~/.pi/wiki)
104
+ target_type: Type of target being optimized (capture, ingest, query, etc.)
105
+ max_examples: Maximum total examples
106
+ val_ratio: Fraction of examples for validation
107
+ seed: Random seed for reproducible splits
108
+
109
+ Returns:
110
+ (trainset, valset) — lists of dspy.Example
111
+ """
112
+ pages = load_all_pages(wiki_dir)
113
+
114
+ if not pages:
115
+ raise ValueError(f"No wiki pages found in {wiki_dir}")
116
+
117
+ # Filter to pages with substantial content (at least 200 chars body)
118
+ good_pages = [p for p in pages if len(p.body) >= 200]
119
+
120
+ if len(good_pages) < 4:
121
+ raise ValueError(f"Need at least 4 pages with content, found {len(good_pages)}")
122
+
123
+ # Shuffle deterministically
124
+ rng = random.Random(seed)
125
+ rng.shuffle(good_pages)
126
+
127
+ # Limit to max_examples
128
+ good_pages = good_pages[:max_examples]
129
+
130
+ # Get context generator for this target type
131
+ gen_context = CONTEXT_GENERATORS.get(target_type, _capture_context)
132
+
133
+ # Build examples
134
+ examples = []
135
+ for page in good_pages:
136
+ task_context = gen_context(page)
137
+
138
+ # Gold output: the actual page body (truncated to keep examples manageable)
139
+ expected_output = page.body[:3000] if len(page.body) > 3000 else page.body
140
+
141
+ example = dspy.Example(
142
+ task_context=task_context,
143
+ expected_output=expected_output,
144
+ # Metadata for the metric
145
+ expected_category=page.category,
146
+ expected_scope=",".join(page.scope),
147
+ expected_slug=page.slug,
148
+ expected_title=page.title,
149
+ page_link_count=str(len(page.links)),
150
+ ).with_inputs("task_context")
151
+
152
+ examples.append(example)
153
+
154
+ # Split into train/val
155
+ split_idx = max(1, int(len(examples) * (1 - val_ratio)))
156
+ trainset = examples[:split_idx]
157
+ valset = examples[split_idx:]
158
+
159
+ # Ensure minimum sizes
160
+ if len(trainset) < 2:
161
+ trainset = examples[:max(2, len(examples) // 2)]
162
+ valset = examples[len(trainset):]
163
+ if len(valset) < 2:
164
+ valset = trainset[-2:] # share a few from train if needed
165
+
166
+ return trainset, valset
167
+
168
+
169
+ def get_wiki_context(wiki_dir: str) -> str:
170
+ """Build a wiki context string for the metric/evaluator."""
171
+ stats = get_wiki_stats(wiki_dir)
172
+ pages = load_all_pages(wiki_dir)
173
+
174
+ # Build a brief summary of existing pages for context
175
+ page_summaries = []
176
+ for p in pages[:30]: # Top 30 pages
177
+ first_line = ""
178
+ for line in p.body.split("\n"):
179
+ line = line.strip()
180
+ if line and not line.startswith("#"):
181
+ first_line = line[:100]
182
+ break
183
+ page_summaries.append(f" - [[{p.slug}]] ({p.category}): {p.title}")
184
+
185
+ context = f"""Wiki has {stats['total_pages']} pages across categories: {stats['categories']}.
186
+ Scopes: {', '.join(stats['unique_scopes'][:10])}.
187
+ Avg links/page: {stats['avg_links_per_page']}.
188
+
189
+ Existing pages:
190
+ {chr(10).join(page_summaries)}"""
191
+
192
+ return context