pi-vault-mind 0.8.0 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +44 -44
- package/agents/broadcaster.agent.md +30 -0
- package/agents/heavy-lifter.agent.md +30 -0
- package/agents/manager.agent.md +29 -0
- package/agents/miner.agent.md +29 -0
- package/dist/src/agent-bus/Agent.d.ts +49 -0
- package/dist/src/agent-bus/Agent.js +97 -0
- package/dist/src/agent-bus/AgentLoader.d.ts +33 -0
- package/dist/src/agent-bus/AgentLoader.js +102 -0
- package/dist/src/agent-bus/AgentRegistry.d.ts +17 -0
- package/dist/src/agent-bus/AgentRegistry.js +20 -0
- package/dist/src/agent-bus/LLMProvider.d.ts +36 -0
- package/dist/src/agent-bus/LLMProvider.js +125 -0
- package/dist/src/agent-bus/MessageBus.d.ts +47 -0
- package/dist/src/agent-bus/MessageBus.js +81 -0
- package/dist/src/agent-bus/TaskQueue.d.ts +27 -0
- package/dist/src/agent-bus/TaskQueue.js +57 -0
- package/dist/src/agent-bus/index.d.ts +6 -0
- package/dist/src/agent-bus/index.js +6 -0
- package/dist/src/agents/BroadcasterAgent.d.ts +19 -0
- package/dist/src/agents/BroadcasterAgent.js +70 -0
- package/dist/src/agents/HeavyLifterAgent.d.ts +26 -0
- package/dist/src/agents/HeavyLifterAgent.js +73 -0
- package/dist/src/agents/ManagerAgent.d.ts +20 -0
- package/dist/src/agents/ManagerAgent.js +71 -0
- package/dist/src/agents/MinerAgent.d.ts +19 -0
- package/dist/src/agents/MinerAgent.js +70 -0
- package/dist/src/agents/index.d.ts +4 -0
- package/dist/src/agents/index.js +4 -0
- package/dist/src/auth.d.ts +49 -2
- package/dist/src/auth.js +149 -7
- package/dist/src/autosync.d.ts +1 -1
- package/dist/src/autosync.js +3 -3
- package/dist/src/bridge.d.ts +45 -0
- package/dist/src/bridge.js +189 -0
- package/dist/src/commands.d.ts +1 -1
- package/dist/src/commands.js +419 -295
- package/dist/src/context-capture.d.ts +22 -0
- package/dist/src/context-capture.js +41 -0
- package/dist/src/discover-schema.d.ts +1 -1
- package/dist/src/discover-schema.js +4 -4
- package/dist/src/embed-queue.d.ts +1 -1
- package/dist/src/embed-queue.js +1 -1
- package/dist/src/engine.d.ts +65 -0
- package/dist/src/engine.js +244 -0
- package/dist/src/events.js +1 -1
- package/dist/src/graph.d.ts +3 -3
- package/dist/src/identity-injector.d.ts +15 -0
- package/dist/src/identity-injector.js +102 -0
- package/dist/src/index.js +88 -49
- package/dist/src/intake.js +4 -4
- package/dist/src/lance.d.ts +11 -37
- package/dist/src/lance.js +183 -240
- package/dist/src/modal-client.d.ts +14 -4
- package/dist/src/modal-client.js +50 -34
- package/dist/src/modal-config.d.ts +26 -10
- package/dist/src/modal-config.js +36 -5
- package/dist/src/personalize.d.ts +47 -0
- package/dist/src/personalize.js +352 -0
- package/dist/src/server.d.ts +30 -4
- package/dist/src/server.js +146 -64
- package/dist/src/settings-ui.d.ts +3 -1
- package/dist/src/settings-ui.js +84 -77
- package/dist/src/status.d.ts +25 -0
- package/dist/src/status.js +49 -0
- package/dist/src/sync.d.ts +1 -1
- package/dist/src/sync.js +19 -19
- package/dist/src/tombstone.js +2 -2
- package/dist/src/tools.js +112 -130
- package/dist/src/types.d.ts +86 -18
- package/dist/src/types.js +7 -4
- package/dist/src/utils.d.ts +5 -1
- package/dist/src/utils.js +24 -8
- package/dist/src/vault-tools.d.ts +29 -0
- package/dist/src/vault-tools.js +314 -0
- package/dist/src/vault-writer.d.ts +4 -5
- package/dist/src/vault-writer.js +13 -13
- package/dist/src/vm-handlers.d.ts +15 -0
- package/dist/src/vm-handlers.js +469 -0
- package/dist/src/watcher.d.ts +18 -4
- package/dist/src/watcher.js +109 -98
- package/dist/test/auth.test.js +57 -7
- package/dist/test/bridge-identity.test.js +388 -0
- package/dist/test/discover-schema.test.js +2 -2
- package/dist/test/engine-identity.test.js +119 -0
- package/dist/test/index.test.js +5 -6
- package/dist/test/lance-modal.test.js +7 -7
- package/dist/test/modal-config.test.js +51 -29
- package/dist/test/personalize.test.js +212 -0
- package/dist/test/rest-queue.test.js +1 -1
- package/dist/test/rest-setup.test.js +21 -21
- package/dist/test/{rest-wiki.test.js → rest-vm.test.js} +27 -23
- package/dist/test/server-ws.test.js +4 -4
- package/dist/test/sync.test.js +2 -2
- package/dist/test/tombstone.test.js +1 -1
- package/dist/test/vault-tools.test.js +224 -0
- package/package.json +2 -1
- package/scripts/check-deps.sh +207 -0
- package/scripts/e2e-ws.mjs +4 -4
- package/scripts/modal-e2e-smoke.mjs +1 -1
- package/scripts/setup-test-config.sh +1 -5
- package/scripts/test-slash-commands.mjs +197 -0
- package/skills/.agents/broadcaster.agent.md +31 -0
- package/skills/.agents/heavy-lifter.agent.md +31 -0
- package/skills/.agents/manager.agent.md +30 -0
- package/skills/.agents/miner.agent.md +30 -0
- package/skills/vault-mind/SKILL.md +50 -50
- package/skills/vault-mind/references/tool-reference.md +25 -25
- package/skills/vault-mind-broadcaster/SKILL.md +1 -1
- package/skills/vault-mind-heavy-lifter/SKILL.md +3 -3
- package/skills/vault-mind-manager/SKILL.md +7 -7
- package/skills/vault-mind-miner/SKILL.md +11 -11
- package/skills/vault-mind-setup/SKILL.md +65 -265
- package/skills/vault-mind-setup/references/obsidian-vault-structure.md +6 -6
- package/skills/vault-mind-setup/references/pi-extension-wiring.md +24 -33
- package/skills/vault-mind-setup/references/troubleshooting-tree.md +25 -26
- package/dist/src/auto-index.d.ts +0 -47
- package/dist/src/auto-index.js +0 -122
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.0 - 2026-06-24
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `discover_schema` tool and `/vm discover-schema` command — infer schema from a `.jsonl` file and register it as a collection.
|
|
8
|
+
- `tombstone_entry` tool and `/vm tombstone` command — redact a JSONL entry in place while preserving the append-only log format.
|
|
9
|
+
- `/vm query` command — hybrid semantic + FTS search over a collection from the slash command tree.
|
|
10
|
+
- `/vm collection list` command — list configured collections without opening the TUI selector.
|
|
11
|
+
- `ask_intake` interactive questionnaire tool with optional persistence to the ledger, vault, or both.
|
|
12
|
+
- Advanced deduping options (`dedupMode`, `dedupThreshold`) and background auto-indexing hooks for collection directories.
|
|
13
|
+
- Always-on capture **Tier A** recipe in `docs/getting-started/CAPTURE_SETUP.md` (iOS Shortcut + Actions for Obsidian, voice memo → Shortcut, desktop Templater hotkey).
|
|
14
|
+
- Vault-specific pi config + TUI launcher in the Obsidian plugin: reads `<vault>/.pi/agent/system.md` and launches pi from setup/status views.
|
|
15
|
+
- Published `pi-vault-mind@0.8.0` and `obsidian-pi-vault-mind@0.1.0` to npm.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- HOME capture path bug: `expandHome()` now falls back to `process.env.USERPROFILE` on Windows and handles bare `~` correctly.
|
|
20
|
+
- Broken internal markdown links after the 0.7.6 docs reorganization.
|
|
21
|
+
- Removed stale `site/` MkDocs build output from git tracking.
|
|
22
|
+
|
|
3
23
|
## 0.7.1 - 2026-06-14
|
|
4
24
|
|
|
5
25
|
### Fixed
|
package/README.md
CHANGED
|
@@ -10,17 +10,17 @@ Passive Obsidian vault extension for the [pi](https://github.com/mariozechner/pi
|
|
|
10
10
|
|
|
11
11
|
> Looking for the legacy ledger-first extension (predecessor project)?
|
|
12
12
|
> See [kylebrodeur/pi-qmd-ledger](https://github.com/kylebrodeur/pi-qmd-ledger).
|
|
13
|
-
> This project was renamed twice: `pi-qmd-ledger` → `pi-
|
|
13
|
+
> This project was renamed twice: `pi-qmd-ledger` → `pi-knowledge-store` (intermediate) → `pi-vault-mind` (current).
|
|
14
14
|
|
|
15
15
|
## Features
|
|
16
16
|
|
|
17
17
|
- **Passive File Watcher** — drop `@agent-Miner`, `@agent-Broadcaster`, etc. in any Obsidian note. Save the file. The watcher detects the marker, groups by role, and dispatches isolated subagent forks (`vault-mind-{role}` agents). No chat pollution, no manual triggers.
|
|
18
18
|
- **Multi-Agent Architecture** — five specialist agents under the `vault-mind-{role}` skill naming: **Manager** (interactive orchestrator), **Miner** (research + entity extraction), **Broadcaster** (NotebookLM artifacts), **Heavy-Lifter** (external delegation), **Watcher** (passive file observer).
|
|
19
19
|
- **LanceDB Vector + FTS + Graph** — hybrid semantic + keyword search with automatic entity extraction and BFS graph traversal. All local, no external binaries.
|
|
20
|
-
- **JSONL Source-of-Truth + LanceDB Index** — every fact lives in a durable, human-readable, version-control-friendly `collections/*.jsonl` file. The LanceDB index is derived and rebuildable via `/
|
|
20
|
+
- **JSONL Source-of-Truth + LanceDB Index** — every fact lives in a durable, human-readable, version-control-friendly `collections/*.jsonl` file. The LanceDB index is derived and rebuildable via `/vm reindex --all --reembed`.
|
|
21
21
|
- **Bidirectional Obsidian Sync** — substantial entries (`>200 chars` or tagged `decision`/`insight`/`requirement`) auto-write to `Vault/Agent/Inbox/`. Graph entities render as Obsidian Canvas files.
|
|
22
22
|
- **Two-Layer Config** — global (`~/.pi/agent/vault-mind.config.json`) for shared settings, project (`./pi-vault-mind.config.json`) for project-specific knowledge. Works across all projects from any directory.
|
|
23
|
-
- **Interactive Setup Wizard** — `/
|
|
23
|
+
- **Interactive Setup Wizard** — `/vm setup` walks through vault path, embedding provider, and model selection. CLI mode: `--vault`, `--provider`, `--model` flags for scripting.
|
|
24
24
|
|
|
25
25
|
## Architecture
|
|
26
26
|
|
|
@@ -70,7 +70,7 @@ See [`docs/architecture/index.md`](docs/architecture/index.md) for the full agen
|
|
|
70
70
|
pi-vault-mind works on any directory, but for the **full Obsidian experience**, you need a few things in Obsidian itself:
|
|
71
71
|
|
|
72
72
|
### Required: An Obsidian vault
|
|
73
|
-
Just point `/
|
|
73
|
+
Just point `/vm setup` at any directory used as an Obsidian vault. pi-vault-mind auto-detects `.obsidian/` and respects `.obsidian/`, `.git/`, `.trash/`.
|
|
74
74
|
|
|
75
75
|
### Recommended: Official Obsidian CLI (1.12+)
|
|
76
76
|
|
|
@@ -165,7 +165,7 @@ These skills let the **Miner, Broadcaster, and Heavy-Lifter agents** produce val
|
|
|
165
165
|
| **Callouts** | `> [!info]`, `> [!warning]` for syntheses and contradictions |
|
|
166
166
|
| **Embeds** | `![[Note]]` to transclude summaries into synthesis docs |
|
|
167
167
|
| **Obsidian Bases (`.base`)** | Agent-generated dynamic tables/boards/kanbans in `Agent/Tasks/` |
|
|
168
|
-
| **JSON Canvas (`.canvas`)** | `
|
|
168
|
+
| **JSON Canvas (`.canvas`)** | `vm_sync(format="canvas")` writes entity graph as Canvas JSON |
|
|
169
169
|
| **Obsidian Sync** | Primary sync mechanism across devices |
|
|
170
170
|
|
|
171
171
|
### Optional: NotebookLM integration (Broadcaster)
|
|
@@ -209,7 +209,7 @@ pi install git:git@github.com:kylebrodeur/pi-vault-mind
|
|
|
209
209
|
### 2. Configure (interactive wizard)
|
|
210
210
|
|
|
211
211
|
```
|
|
212
|
-
/
|
|
212
|
+
/vm setup
|
|
213
213
|
```
|
|
214
214
|
|
|
215
215
|
This walks you through: vault path → embedding provider → Ollama model (if applicable).
|
|
@@ -217,20 +217,20 @@ This walks you through: vault path → embedding provider → Ollama model (if a
|
|
|
217
217
|
Or via CLI for scripting:
|
|
218
218
|
|
|
219
219
|
```bash
|
|
220
|
-
/
|
|
221
|
-
/
|
|
220
|
+
/vm setup --vault /home/you/Obsidian/MyVault --provider transformers
|
|
221
|
+
/vm setup --vault /home/you/Obsidian/MyVault --provider ollama --model embeddinggemma
|
|
222
222
|
```
|
|
223
223
|
|
|
224
224
|
Config is written to `~/.pi/agent/vault-mind.config.json` — it applies globally
|
|
225
225
|
no matter which project directory you open pi from.
|
|
226
226
|
|
|
227
|
-
You can re-run `/
|
|
227
|
+
You can re-run `/vm setup` anytime to view or change settings.
|
|
228
228
|
|
|
229
229
|
### 3. Start using
|
|
230
230
|
|
|
231
231
|
```
|
|
232
|
-
|
|
233
|
-
|
|
232
|
+
vm_append(collection="main", mode="autopilot", entry={"id":"1","domain":"auth","fact":"JWT tokens expire after 1 hour","tag":"security"})
|
|
233
|
+
vm_search(collection="main", query="token expiry")
|
|
234
234
|
```
|
|
235
235
|
|
|
236
236
|
Entries are automatically embedded and stored in LanceDB. If graph is enabled, entities and relations are also extracted.
|
|
@@ -257,7 +257,7 @@ Edit `pi-vault-mind.config.json` to match your domain:
|
|
|
257
257
|
"filterField": "tag"
|
|
258
258
|
}
|
|
259
259
|
],
|
|
260
|
-
"
|
|
260
|
+
"vaultMind": {
|
|
261
261
|
"dataDir": ".lancedb",
|
|
262
262
|
"embedding": {
|
|
263
263
|
"provider": "transformers",
|
|
@@ -329,38 +329,38 @@ Edit `pi-vault-mind.config.json` to match your domain:
|
|
|
329
329
|
|
|
330
330
|
| Tool | Purpose |
|
|
331
331
|
| ------------------ | ------------------------------------------------------- |
|
|
332
|
-
| `
|
|
333
|
-
| `
|
|
334
|
-
| `
|
|
335
|
-
| `
|
|
336
|
-
| `
|
|
337
|
-
| `
|
|
338
|
-
| `
|
|
339
|
-
| `
|
|
340
|
-
| `
|
|
341
|
-
| `
|
|
342
|
-
| `
|
|
332
|
+
| `vm_search` | Semantic search via LanceDB (vector + FTS) |
|
|
333
|
+
| `vm_fts_search` | Exact keyword full-text search (Tantivy BM25) |
|
|
334
|
+
| `vm_graph_query` | Traverse entity connections in the graph layer |
|
|
335
|
+
| `vm_status` | Show LanceDB table sizes and health |
|
|
336
|
+
| `vm_query` | Deterministic JSONL search by collection name |
|
|
337
|
+
| `vm_append` | Append with strict/gated/autopilot modes + dual-write |
|
|
338
|
+
| `vm_configure` | Read or update config at runtime |
|
|
339
|
+
| `vm_describe` | Introspect schema, count, and sample entries |
|
|
340
|
+
| `vm_stats` | Dashboard: counts, sizes, LanceDB status |
|
|
341
|
+
| `vm_export` | Export to JSON, CSV, or Markdown |
|
|
342
|
+
| `vm_promote` | Promote entries between collections via pending queue |
|
|
343
343
|
|
|
344
344
|
## Commands
|
|
345
345
|
|
|
346
346
|
| Command | Purpose |
|
|
347
347
|
| ------------------------------ | -------------------------------------------------------- |
|
|
348
|
-
| `/
|
|
349
|
-
| `/
|
|
350
|
-
| `/
|
|
351
|
-
| `/
|
|
352
|
-
| `/
|
|
353
|
-
| `/
|
|
354
|
-
| `/
|
|
355
|
-
| `/
|
|
356
|
-
| `/
|
|
357
|
-
| `/
|
|
358
|
-
| `/
|
|
359
|
-
| `/
|
|
360
|
-
| `/
|
|
361
|
-
| `/
|
|
362
|
-
| `/
|
|
363
|
-
| `/
|
|
348
|
+
| `/vm help` | Show usage help |
|
|
349
|
+
| `/vm setup` | **Interactive global config wizard** (vault, embedding) |
|
|
350
|
+
| `/vm init` | Scaffold project config + collections |
|
|
351
|
+
| `/vm validate` | Health check LanceDB, config, and all collection paths |
|
|
352
|
+
| `/vm approve [collection]` | Batch-review pending entries |
|
|
353
|
+
| `/vm settings` | Open interactive settings dashboard |
|
|
354
|
+
| `/vm audit` | Audit config for missing defaults |
|
|
355
|
+
| `/vm reindex [--all] [--reembed] [--remote]` | Rebuild FTS + vector indexes; `--remote` offloads to Modal |
|
|
356
|
+
| `/vm collection select` | Select active collection (shortcut: ctrl+alt+l) |
|
|
357
|
+
| `/vm collection create` | Interactive wizard to create a new collection |
|
|
358
|
+
| `/vm injector create` | Interactive wizard to create a new injector |
|
|
359
|
+
| `/vm context enable \| disable \| status` | Manage pi-context integration |
|
|
360
|
+
| `/vm embedding status \| use \| model \| models \| pull` | Manage embedding provider |
|
|
361
|
+
| `/vm modal status \| config \| sync \| jobs \| migrate` | Manage Modal embedding + vector sync |
|
|
362
|
+
| `/vm watcher start \| stop \| status` | Manage the passive file watcher |
|
|
363
|
+
| `/vm server status` | Show HTTP server status, port, and uptime |
|
|
364
364
|
|
|
365
365
|
## Documentation
|
|
366
366
|
|
|
@@ -393,7 +393,7 @@ The local extension now integrates the Modal embedding service as a fully
|
|
|
393
393
|
configurable embedding provider: on-demand `/embed` for search (with an offline
|
|
394
394
|
fallback that degrades to FTS, never crashes), a sync-down path that pulls
|
|
395
395
|
server-side vectors into the local LanceDB with a monotonic `seq` watermark,
|
|
396
|
-
remote bulk re-index (`/
|
|
396
|
+
remote bulk re-index (`/vm reindex --all --reembed --remote`), and debounced +
|
|
397
397
|
batched append embedding via the coalescer. Existing non-modal users see no
|
|
398
398
|
behavior change. See [docs/integrations/MODAL_EMBEDDING.md](docs/integrations/MODAL_EMBEDDING.md) for the
|
|
399
399
|
full design.
|
|
@@ -411,9 +411,9 @@ full design.
|
|
|
411
411
|
| Doc | Description |
|
|
412
412
|
|---|---|
|
|
413
413
|
| [skills/vault-mind/SKILL.md](skills/vault-mind/SKILL.md) | The Manager skill — what pi auto-loads about this extension |
|
|
414
|
-
| [docs/CHANGELOG.md](docs/CHANGELOG.md) | Version history (rename from `pi-
|
|
415
|
-
| [docs/reference/tools.md](docs/reference/tools.md) | The 11 `
|
|
416
|
-
| [docs/reference/commands.md](docs/reference/commands.md) | Full `/
|
|
414
|
+
| [docs/CHANGELOG.md](docs/CHANGELOG.md) | Version history (rename from `pi-knowledge-store` to `pi-vault-mind` was v0.7.0) |
|
|
415
|
+
| [docs/reference/tools.md](docs/reference/tools.md) | The 11 `vm_*` and `vm_query`/`vm_append`/etc. tools — parameters, return shapes |
|
|
416
|
+
| [docs/reference/commands.md](docs/reference/commands.md) | Full `/vm` slash command tree |
|
|
417
417
|
| [docs/reference/configuration.md](docs/reference/configuration.md) | The complete `pi-vault-mind.config.json` schema |
|
|
418
418
|
| [docs/reference/skill.md](docs/reference/skill.md) | Manifest of all bundled skills and their trigger phrases |
|
|
419
419
|
|
|
@@ -444,7 +444,7 @@ full design.
|
|
|
444
444
|
|
|
445
445
|
| Doc | Description |
|
|
446
446
|
|---|---|
|
|
447
|
-
| [docs/_archive/](docs/_archive/) | Historical docs kept for context (e.g. the `pi-
|
|
447
|
+
| [docs/_archive/](docs/_archive/) | Historical docs kept for context (e.g. the `pi-knowledge-store` → `pi-vault-mind` rename audit) |
|
|
448
448
|
| [docs/_archive/legacy-audit.md](docs/_archive/legacy-audit.md) | The 2026-06-08 legacy-terminology audit (139 findings, 13 blockers) and its resolution log. Resolved 2026-06-09; archived 2026-06-16 (in the repo, not on the docs site) |
|
|
449
449
|
|
|
450
450
|
## Contributing
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: BroadcasterAgent
|
|
3
|
+
role: broadcaster
|
|
4
|
+
capabilities: [read, write, edit]
|
|
5
|
+
allowed_tools: [read, write, edit, vm_search, vm_fts_search]
|
|
6
|
+
write_collections: []
|
|
7
|
+
can_publish: false
|
|
8
|
+
llm_provider: ollama
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Broadcaster Agent
|
|
12
|
+
|
|
13
|
+
Content distribution agent for pi-vault-mind. Creates presentations, summaries,
|
|
14
|
+
and external-facing content from vault knowledge.
|
|
15
|
+
|
|
16
|
+
## Capability Boundary
|
|
17
|
+
|
|
18
|
+
- **MAY**: read files, write files, edit files
|
|
19
|
+
- **MAY**: search collections via vm_search, vm_fts_search
|
|
20
|
+
- **MUST NOT**: run bash commands, grep, or find
|
|
21
|
+
- **MUST NOT**: write to the durable knowledge store
|
|
22
|
+
- **MUST NOT**: publish or spawn sub-agents
|
|
23
|
+
- Write output only under Agent/Presentations/
|
|
24
|
+
|
|
25
|
+
## Tool Calling Convention
|
|
26
|
+
|
|
27
|
+
When calling pi-vault-mind tools, always include your role:
|
|
28
|
+
```
|
|
29
|
+
vm_search({ query: "...", role: "broadcaster" })
|
|
30
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: HeavyLifterAgent
|
|
3
|
+
role: heavy-lifter
|
|
4
|
+
capabilities: [read, write, edit, grep, find, ls, bash]
|
|
5
|
+
allowed_tools: [read, write, edit, grep, find, ls, bash, vm_search, vm_fts_search]
|
|
6
|
+
write_collections: []
|
|
7
|
+
can_publish: false
|
|
8
|
+
llm_provider: ollama
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Heavy-Lifter Agent
|
|
12
|
+
|
|
13
|
+
External CLI execution agent for pi-vault-mind. Runs bash commands in an isolated
|
|
14
|
+
worktree. Cannot write to the durable knowledge store — all findings must be
|
|
15
|
+
routed to the Miner for storage.
|
|
16
|
+
|
|
17
|
+
## Capability Boundary
|
|
18
|
+
|
|
19
|
+
- **MAY**: read files, write files, edit files, run bash commands, search with grep/find/ls
|
|
20
|
+
- **MUST NOT**: write to the durable store (vm_append, vm_sync disabled)
|
|
21
|
+
- **MUST NOT**: spawn sub-agents
|
|
22
|
+
- **MUST NOT**: publish to the human-facing vault
|
|
23
|
+
- All bash commands run in an isolated worktree. Do not modify files outside it.
|
|
24
|
+
|
|
25
|
+
## Tool Calling Convention
|
|
26
|
+
|
|
27
|
+
When calling pi-vault-mind tools, always include your role:
|
|
28
|
+
```
|
|
29
|
+
vm_search({ query: "...", role: "heavy-lifter" })
|
|
30
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: ManagerAgent
|
|
3
|
+
role: manager
|
|
4
|
+
capabilities: [read, write, edit, grep, find, ls]
|
|
5
|
+
allowed_tools: [read, write, edit, grep, find, ls, vm_search, vm_fts_search, vm_append, vm_sync, vm_promote, vm_query, vm_configure, vm_describe, vm_stats, vm_export, vm_ingest, vm_status, vm_graph_query]
|
|
6
|
+
write_collections: [main, research, presentations]
|
|
7
|
+
can_publish: true
|
|
8
|
+
llm_provider: ollama
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Manager Agent
|
|
12
|
+
|
|
13
|
+
Final gate and publishing agent for pi-vault-mind. The only role authorized to
|
|
14
|
+
publish to the human-facing vault and dispatch sub-agents.
|
|
15
|
+
|
|
16
|
+
## Capability Boundary
|
|
17
|
+
|
|
18
|
+
- **MAY**: all vm_* tools, read, write, edit, grep, find, ls
|
|
19
|
+
- **MAY**: write to any collection
|
|
20
|
+
- **MAY**: publish to the human-facing vault via vm_sync
|
|
21
|
+
- **MAY**: dispatch sub-agents
|
|
22
|
+
- **MUST NOT**: run bash commands
|
|
23
|
+
|
|
24
|
+
## Tool Calling Convention
|
|
25
|
+
|
|
26
|
+
When calling pi-vault-mind tools, always include your role:
|
|
27
|
+
```
|
|
28
|
+
vm_sync({ collection: "main", role: "manager" })
|
|
29
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: MinerAgent
|
|
3
|
+
role: miner
|
|
4
|
+
capabilities: [read, write, edit, grep, find, ls]
|
|
5
|
+
allowed_tools: [read, write, edit, grep, find, ls, vm_search, vm_fts_search, vm_append]
|
|
6
|
+
write_collections: [main, research]
|
|
7
|
+
can_publish: false
|
|
8
|
+
llm_provider: ollama
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Miner Agent
|
|
12
|
+
|
|
13
|
+
Knowledge extraction and storage agent for pi-vault-mind. Extracts entities and
|
|
14
|
+
relationships from vault content and stores them in the durable knowledge store.
|
|
15
|
+
|
|
16
|
+
## Capability Boundary
|
|
17
|
+
|
|
18
|
+
- **MAY**: read files, write files, edit files, search with grep/find/ls
|
|
19
|
+
- **MAY**: append to collections 'main' and 'research' via vm_append
|
|
20
|
+
- **MUST NOT**: run bash commands
|
|
21
|
+
- **MUST NOT**: publish to the human-facing vault (vm_sync disabled)
|
|
22
|
+
- **MUST NOT**: spawn sub-agents
|
|
23
|
+
|
|
24
|
+
## Tool Calling Convention
|
|
25
|
+
|
|
26
|
+
When calling pi-vault-mind tools, always include your role:
|
|
27
|
+
```
|
|
28
|
+
vm_append({ collection: "main", entry: {...}, role: "miner" })
|
|
29
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { LLMProvider } from "./LLMProvider.js";
|
|
2
|
+
import type { Message, MessageBus } from "./MessageBus.js";
|
|
3
|
+
export interface AgentConfig {
|
|
4
|
+
id: string;
|
|
5
|
+
role: string;
|
|
6
|
+
capabilities: string[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Base Agent
|
|
10
|
+
*
|
|
11
|
+
* Agnostic agent that sits on the MessageBus.
|
|
12
|
+
* Can be extended for Coding Tasks or Physical Manufacturing Tasks.
|
|
13
|
+
*/
|
|
14
|
+
export declare abstract class Agent {
|
|
15
|
+
config: AgentConfig;
|
|
16
|
+
protected bus: MessageBus;
|
|
17
|
+
protected llm?: LLMProvider;
|
|
18
|
+
constructor(config: AgentConfig, bus: MessageBus, llm?: LLMProvider);
|
|
19
|
+
/**
|
|
20
|
+
* Broadcast a message to the environment
|
|
21
|
+
*/
|
|
22
|
+
broadcast(topic: string, payload: Record<string, unknown>): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Direct message another agent
|
|
25
|
+
*/
|
|
26
|
+
sendDirect(targetAgentId: string, payload: Record<string, unknown>): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Hook for handling incoming messages. To be overridden by implementations.
|
|
29
|
+
*/
|
|
30
|
+
protected handleMessage(message: Message): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Perform an LLM-driven decision in JSON mode
|
|
33
|
+
*/
|
|
34
|
+
protected askLLM<T = unknown>(promptText: string, jsonMode?: true): Promise<T | null>;
|
|
35
|
+
protected askLLM(promptText: string, jsonMode: false): Promise<string>;
|
|
36
|
+
/**
|
|
37
|
+
* The main tick or tick-equivalent.
|
|
38
|
+
* If running in an event loop (e.g. manufacturing), override this.
|
|
39
|
+
*/
|
|
40
|
+
abstract tick(): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Helper to invoke a Pi tool via the Pi Tool Bridge.
|
|
43
|
+
* Agent publishes a request and awaits a response on a unique topic.
|
|
44
|
+
* @param toolName The name of the pi.tool to invoke (e.g., 'append_ledger').
|
|
45
|
+
* @param args The arguments to pass to the pi.tool.
|
|
46
|
+
* @param timeoutMs Maximum time to wait for a response from the bridge.
|
|
47
|
+
*/
|
|
48
|
+
protected invokePiTool(toolName: string, args: Record<string, unknown>, timeoutMs?: number): Promise<unknown>;
|
|
49
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
/**
|
|
3
|
+
* Base Agent
|
|
4
|
+
*
|
|
5
|
+
* Agnostic agent that sits on the MessageBus.
|
|
6
|
+
* Can be extended for Coding Tasks or Physical Manufacturing Tasks.
|
|
7
|
+
*/
|
|
8
|
+
export class Agent {
|
|
9
|
+
config;
|
|
10
|
+
bus;
|
|
11
|
+
llm;
|
|
12
|
+
constructor(config, bus, llm) {
|
|
13
|
+
this.config = config;
|
|
14
|
+
this.bus = bus;
|
|
15
|
+
this.llm = llm;
|
|
16
|
+
// Subscribe to direct messages and broadcasts
|
|
17
|
+
this.bus.subscribe(`direct:${this.config.id}`, this.handleMessage.bind(this));
|
|
18
|
+
this.bus.subscribe("broadcast", this.handleMessage.bind(this));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Broadcast a message to the environment
|
|
22
|
+
*/
|
|
23
|
+
async broadcast(topic, payload) {
|
|
24
|
+
await this.bus.publish(topic, this.config.id, payload);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Direct message another agent
|
|
28
|
+
*/
|
|
29
|
+
async sendDirect(targetAgentId, payload) {
|
|
30
|
+
await this.bus.publish(`direct:${targetAgentId}`, this.config.id, payload);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Hook for handling incoming messages. To be overridden by implementations.
|
|
34
|
+
*/
|
|
35
|
+
async handleMessage(message) {
|
|
36
|
+
// Default: Do nothing
|
|
37
|
+
}
|
|
38
|
+
async askLLM(promptText, jsonMode = true) {
|
|
39
|
+
if (!this.llm) {
|
|
40
|
+
throw new Error(`Agent ${this.config.id} has no LLM provider attached.`);
|
|
41
|
+
}
|
|
42
|
+
const response = await this.llm.prompt(promptText, { jsonMode });
|
|
43
|
+
if (jsonMode) {
|
|
44
|
+
try {
|
|
45
|
+
return JSON.parse(response);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
console.error(`Agent ${this.config.id} failed to parse JSON from LLM:`, response);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return response;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Helper to invoke a Pi tool via the Pi Tool Bridge.
|
|
56
|
+
* Agent publishes a request and awaits a response on a unique topic.
|
|
57
|
+
* @param toolName The name of the pi.tool to invoke (e.g., 'append_ledger').
|
|
58
|
+
* @param args The arguments to pass to the pi.tool.
|
|
59
|
+
* @param timeoutMs Maximum time to wait for a response from the bridge.
|
|
60
|
+
*/
|
|
61
|
+
async invokePiTool(toolName, args, timeoutMs = 30000) {
|
|
62
|
+
const requestId = randomUUID();
|
|
63
|
+
const requestTopic = "pi_tool_bridge_requests";
|
|
64
|
+
const responseTopic = `pi_tool_bridge_responses:${this.config.id}:${requestId}`;
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
// biome-ignore lint/style/useConst: assigned after handler/subscribe setup
|
|
67
|
+
let timeout;
|
|
68
|
+
const cleanup = () => {
|
|
69
|
+
clearTimeout(timeout);
|
|
70
|
+
this.bus.unsubscribe(responseTopic, handler);
|
|
71
|
+
};
|
|
72
|
+
const handler = (message) => {
|
|
73
|
+
if (message.payload.requestId === requestId) {
|
|
74
|
+
cleanup();
|
|
75
|
+
if (message.payload.error) {
|
|
76
|
+
reject(new Error(String(message.payload.error)));
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
resolve(message.payload.result);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
this.bus.subscribe(responseTopic, handler);
|
|
84
|
+
timeout = setTimeout(() => {
|
|
85
|
+
cleanup();
|
|
86
|
+
reject(new Error(`Pi tool invocation timed out for tool: '${toolName}', requestId: ${requestId}`));
|
|
87
|
+
}, timeoutMs);
|
|
88
|
+
void this.broadcast(requestTopic, {
|
|
89
|
+
requestId,
|
|
90
|
+
agentId: this.config.id,
|
|
91
|
+
toolName,
|
|
92
|
+
args,
|
|
93
|
+
responseTopic,
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Agent } from "./Agent.js";
|
|
2
|
+
import type { LLMProvider } from "./LLMProvider.js";
|
|
3
|
+
import type { MessageBus } from "./MessageBus.js";
|
|
4
|
+
export interface AgentFileDefinition {
|
|
5
|
+
type: string;
|
|
6
|
+
role: string;
|
|
7
|
+
capabilities: string[];
|
|
8
|
+
llm_provider: string;
|
|
9
|
+
llm_model: string;
|
|
10
|
+
allowed_tools?: string[];
|
|
11
|
+
write_collections?: string[];
|
|
12
|
+
can_publish?: boolean;
|
|
13
|
+
config_dir?: string;
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface AgentLoaderConfig {
|
|
17
|
+
agentsDirectory: string;
|
|
18
|
+
bus: MessageBus;
|
|
19
|
+
llmProviderFactory: (providerName: string, model: string) => Promise<LLMProvider | null>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* AgentLoader reads Markdown files with YAML frontmatter from a directory
|
|
23
|
+
* and instantiates agents using the AgentRegistry.
|
|
24
|
+
*/
|
|
25
|
+
export declare class AgentLoader {
|
|
26
|
+
private config;
|
|
27
|
+
constructor(config: AgentLoaderConfig);
|
|
28
|
+
/**
|
|
29
|
+
* Loads all agents defined in the .agents/ directory.
|
|
30
|
+
*/
|
|
31
|
+
loadAgents(): Promise<Agent[]>;
|
|
32
|
+
private parseMarkdownWithFrontmatter;
|
|
33
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { AgentRegistry } from "./AgentRegistry.js";
|
|
4
|
+
/**
|
|
5
|
+
* AgentLoader reads Markdown files with YAML frontmatter from a directory
|
|
6
|
+
* and instantiates agents using the AgentRegistry.
|
|
7
|
+
*/
|
|
8
|
+
export class AgentLoader {
|
|
9
|
+
config;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Loads all agents defined in the .agents/ directory.
|
|
15
|
+
*/
|
|
16
|
+
async loadAgents() {
|
|
17
|
+
const { agentsDirectory, bus, llmProviderFactory } = this.config;
|
|
18
|
+
const agents = [];
|
|
19
|
+
try {
|
|
20
|
+
if (!fs.existsSync(agentsDirectory)) {
|
|
21
|
+
console.warn(`[AgentLoader] Agents directory ${agentsDirectory} not found. Skipping.`);
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const files = fs.readdirSync(agentsDirectory);
|
|
25
|
+
for (const file of files) {
|
|
26
|
+
if (file.endsWith(".agent.md")) {
|
|
27
|
+
const absolutePath = path.join(agentsDirectory, file);
|
|
28
|
+
const content = fs.readFileSync(absolutePath, "utf8");
|
|
29
|
+
const { frontmatter } = this.parseMarkdownWithFrontmatter(content);
|
|
30
|
+
if (!frontmatter || typeof frontmatter.type !== "string") {
|
|
31
|
+
console.error(`[AgentLoader] Agent file ${file} is missing 'type' in frontmatter. Skipping.`);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const agentType = frontmatter.type;
|
|
35
|
+
const Constructor = AgentRegistry.get(agentType);
|
|
36
|
+
if (!Constructor) {
|
|
37
|
+
console.error(`[AgentLoader] Agent file ${file} specifies type '${agentType}', but no such agent type is registered. Skipping.`);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const agentConfig = {
|
|
41
|
+
id: path.basename(file, ".agent.md"),
|
|
42
|
+
role: frontmatter.role || "General Purpose",
|
|
43
|
+
capabilities: frontmatter.capabilities || [],
|
|
44
|
+
};
|
|
45
|
+
// Create LLM Provider if specified
|
|
46
|
+
let llm = null;
|
|
47
|
+
if (typeof frontmatter.llm_provider === "string" &&
|
|
48
|
+
typeof frontmatter.llm_model === "string") {
|
|
49
|
+
llm = await llmProviderFactory(frontmatter.llm_provider, frontmatter.llm_model);
|
|
50
|
+
}
|
|
51
|
+
// Instantiate the agent
|
|
52
|
+
const agent = new Constructor(agentConfig, bus, llm ?? undefined);
|
|
53
|
+
agents.push(agent);
|
|
54
|
+
console.log(`[AgentLoader] Loaded agent: ${agentConfig.id} (type: ${agentType})`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return agents;
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
61
|
+
console.error(`[AgentLoader] Failed to load agents from ${agentsDirectory}: ${msg}`);
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
parseMarkdownWithFrontmatter(content) {
|
|
66
|
+
const match = content.match(/^---([\s\S]*?)---([\s\S]*)$/);
|
|
67
|
+
if (!match)
|
|
68
|
+
return { frontmatter: null, body: content };
|
|
69
|
+
const yamlContent = match[1];
|
|
70
|
+
const body = match[2];
|
|
71
|
+
try {
|
|
72
|
+
const frontmatter = {};
|
|
73
|
+
for (const line of yamlContent.split(/\r?\n/)) {
|
|
74
|
+
const trimmed = line.trim();
|
|
75
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
76
|
+
continue;
|
|
77
|
+
const colonIdx = trimmed.indexOf(":");
|
|
78
|
+
if (colonIdx === -1)
|
|
79
|
+
continue;
|
|
80
|
+
const key = trimmed.slice(0, colonIdx).trim();
|
|
81
|
+
let value = trimmed.slice(colonIdx + 1).trim();
|
|
82
|
+
// Parse arrays: [a, b, c]
|
|
83
|
+
if (typeof value === "string" && value.startsWith("[") && value.endsWith("]")) {
|
|
84
|
+
value = value
|
|
85
|
+
.slice(1, -1)
|
|
86
|
+
.split(",")
|
|
87
|
+
.map((s) => s.trim().replace(/^["']|["']$/g, ""))
|
|
88
|
+
.filter(Boolean);
|
|
89
|
+
}
|
|
90
|
+
// Unquote strings
|
|
91
|
+
if (typeof value === "string") {
|
|
92
|
+
value = value.replace(/^["']|["']$/g, "");
|
|
93
|
+
}
|
|
94
|
+
frontmatter[key] = value;
|
|
95
|
+
}
|
|
96
|
+
return { frontmatter, body: body.trim() };
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return { frontmatter: null, body: content };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Agent, AgentConfig } from "./Agent.js";
|
|
2
|
+
import type { LLMProvider } from "./LLMProvider.js";
|
|
3
|
+
import type { MessageBus } from "./MessageBus.js";
|
|
4
|
+
export type AgentConstructor = new (config: AgentConfig, bus: MessageBus, llm?: LLMProvider) => Agent;
|
|
5
|
+
/**
|
|
6
|
+
* AgentRegistry maintains a mapping of agent 'types' to their concrete class
|
|
7
|
+
* implementations. This allows the AgentLoader to instantiate the correct class
|
|
8
|
+
* based on the YAML definition.
|
|
9
|
+
*/
|
|
10
|
+
export declare const AgentRegistry: {
|
|
11
|
+
/** Register an agent class for a given type name. */
|
|
12
|
+
register(type: string, agentConstructor: AgentConstructor): void;
|
|
13
|
+
/** Get the constructor for a given agent type. */
|
|
14
|
+
get(type: string): AgentConstructor | undefined;
|
|
15
|
+
/** List all registered agent types. */
|
|
16
|
+
list(): string[];
|
|
17
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const registry = new Map();
|
|
2
|
+
/**
|
|
3
|
+
* AgentRegistry maintains a mapping of agent 'types' to their concrete class
|
|
4
|
+
* implementations. This allows the AgentLoader to instantiate the correct class
|
|
5
|
+
* based on the YAML definition.
|
|
6
|
+
*/
|
|
7
|
+
export const AgentRegistry = {
|
|
8
|
+
/** Register an agent class for a given type name. */
|
|
9
|
+
register(type, agentConstructor) {
|
|
10
|
+
registry.set(type, agentConstructor);
|
|
11
|
+
},
|
|
12
|
+
/** Get the constructor for a given agent type. */
|
|
13
|
+
get(type) {
|
|
14
|
+
return registry.get(type);
|
|
15
|
+
},
|
|
16
|
+
/** List all registered agent types. */
|
|
17
|
+
list() {
|
|
18
|
+
return Array.from(registry.keys());
|
|
19
|
+
},
|
|
20
|
+
};
|