pi-vault-mind 0.16.30 → 0.16.32
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 +39 -0
- package/README.md +59 -45
- package/dist/src/commands.js +7 -7
- package/dist/src/context-capture.d.ts +11 -6
- package/dist/src/context-capture.js +12 -7
- package/dist/src/events.d.ts +2 -2
- package/dist/src/events.js +109 -132
- package/dist/src/extension-packages.d.ts +4 -4
- package/dist/src/extension-packages.js +4 -4
- package/dist/src/index.js +9 -8
- package/dist/src/personalize.js +2 -2
- package/dist/src/settings-ui.js +1 -1
- package/dist/src/types.d.ts +1 -1
- package/dist/src/types.js +1 -1
- package/dist/src/utils.js +3 -3
- package/dist/test/check-deps-script.test.js +102 -0
- package/dist/test/context-capture.test.js +34 -14
- package/dist/test/events.test.js +210 -132
- package/dist/test/pvm-cli.test.js +30 -0
- package/dist/test/pvm-setup.test.js +251 -0
- package/dist/test/utils.test.js +26 -4
- package/dist/test/vault-pi-script.test.js +87 -3
- package/package.json +19 -7
- package/pi-vault-mind.config.example.json +1 -1
- package/runtime/pvm-extensions.json +11 -0
- package/runtime/skills/LICENSE +21 -0
- package/runtime/skills/json-canvas/SKILL.md +244 -0
- package/runtime/skills/json-canvas/references/EXAMPLES.md +329 -0
- package/runtime/skills/nlm-skill/LICENSE +21 -0
- package/runtime/skills/nlm-skill/SKILL.md +936 -0
- package/runtime/skills/nlm-skill/references/command_reference.md +1072 -0
- package/runtime/skills/nlm-skill/references/remote-mcp.md +83 -0
- package/runtime/skills/nlm-skill/references/studio-prompt-examples.md +420 -0
- package/runtime/skills/nlm-skill/references/studio-prompting-guide.md +399 -0
- package/runtime/skills/nlm-skill/references/troubleshooting.md +427 -0
- package/runtime/skills/nlm-skill/references/workflows.md +572 -0
- package/runtime/skills/obsidian-bases/SKILL.md +499 -0
- package/runtime/skills/obsidian-bases/references/FUNCTIONS_REFERENCE.md +173 -0
- package/runtime/skills/obsidian-cli/SKILL.md +106 -0
- package/runtime/skills/obsidian-markdown/SKILL.md +196 -0
- package/runtime/skills/obsidian-markdown/references/CALLOUTS.md +58 -0
- package/runtime/skills/obsidian-markdown/references/EMBEDS.md +70 -0
- package/runtime/skills/obsidian-markdown/references/PROPERTIES.md +61 -0
- package/scripts/check-deps.sh +182 -118
- package/scripts/generate-extension-packages-json.mjs +5 -5
- package/scripts/pvm-setup.mjs +289 -0
- package/scripts/pvm.mjs +96 -3
- package/scripts/setup-vault-pi.sh +2 -66
- package/scripts/vault-pi.sh +56 -3
- package/skills/github-release-notes-file/SKILL.md +0 -42
- package/skills/obsidian-guided-test-session/SKILL.md +0 -110
- package/skills/obsidian-interactive-test/SKILL.md +0 -88
- package/skills/obsidian-plugin-publish/SKILL.md +0 -58
- package/skills/pi-vault-mind-release/SKILL.md +0 -141
- package/skills/pre-test-release/SKILL.md +0 -116
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.16.32 — 2026-08-28
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **Concise setup progress.** `pvm setup` now reports one bounded progress line per extension and curated skill while preserving captured installer diagnostics on failure.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **Vault-isolated main sessions.** `pvm run` disables implicit skill and prompt-template discovery, then explicitly loads only curated and package skills rooted in the vault-local agent directory. Specialist skill availability can no longer select a specialist identity for the interactive main session.
|
|
12
|
+
- **Escaping package paths.** Setup removes local package paths that resolve outside the vault-local agent directory while preserving npm packages and in-runtime custom packages.
|
|
13
|
+
|
|
14
|
+
## 0.16.31 — 2026-08-28
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **One-command vault setup.** `pvm setup [vault-path]` installs the complete vault-local extension, task/subagent, NotebookLM, and curated skill profile before merge-safely scaffolding Vault Mind, model-router, and main-agent configuration.
|
|
19
|
+
- **Resource-only repair.** `pvm setup --resources-only [vault-path]` refreshes extensions, tools, and skills without changing vault configuration.
|
|
20
|
+
- **Dependency audit and repair.** `pvm check-deps [--fix] [--strict] [--obsidian] [vault-path]` verifies the host runtime, vault-local extensions, curated skills, and optional content or Obsidian tooling.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- **Pi 0.84.3 runtime.** Development and compatibility checks now target `@earendil-works/pi-coding-agent` and `@earendil-works/pi-tui` 0.84.3.
|
|
25
|
+
- **Node.js 22.19 runtime floor.** Package metadata, dependency audits, and setup documentation now match the minimum Node version required by Pi 0.84.3.
|
|
26
|
+
- **Current task and subagent extensions.** New vault setup installs `@juicesharp/rpiv-todo` 2.7.1 and `pi-subagents` 0.58.0, while removing the obsolete `@tintinweb/pi-tasks` package.
|
|
27
|
+
- **Pi Context 2.1.2 integration.** Session-start and turn-end capture now use the current checkpoint and context-event APIs.
|
|
28
|
+
- **Curated package surface.** Published Pi discovery exposes only Vault Mind usage, setup, and specialist content skills; internal release, plugin-development, and test workflows are no longer shipped as runtime skills.
|
|
29
|
+
- **Reproducible package tooling.** The repository now pins pnpm 10.34.5 so Corepack does not select an incompatible pnpm major during clean release builds.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- **Quiet main-agent startup.** Automatic context management initializes without injecting a synthetic `/acm` user message into a new session.
|
|
34
|
+
- **Stable Pi launcher selection.** Setup avoids transient `npx` binaries and consistently provisions the vault-local agent directory with the installed Pi runtime.
|
|
35
|
+
|
|
36
|
+
### Verification
|
|
37
|
+
|
|
38
|
+
- Node 24.19.0 with pnpm 10.34.5: dependency install, core build, and package-scoped Biome check completed successfully.
|
|
39
|
+
- Full core test suite: 937/937 passing.
|
|
40
|
+
- Packed `pi-vault-mind-0.16.31.tgz` successfully; the packaged `pvm --help` executable ran and exposed the `run`, `setup`, and `check-deps` commands.
|
|
41
|
+
|
|
3
42
|
## 0.16.30 — 2026-08-27
|
|
4
43
|
|
|
5
44
|
### Added
|
package/README.md
CHANGED
|
@@ -123,37 +123,32 @@ obsidian plugin:install id=obsidian42-brat enable
|
|
|
123
123
|
# In Obsidian: Settings → BRAT → Beta Plugin List → Add
|
|
124
124
|
```
|
|
125
125
|
|
|
126
|
-
###
|
|
126
|
+
### Curated vault-local skills
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
`pvm setup` installs the supported Obsidian and NotebookLM skills into the
|
|
129
|
+
vault-local Pi agent directory:
|
|
130
130
|
|
|
131
131
|
```bash
|
|
132
|
-
|
|
133
|
-
DISABLE_TELEMETRY=1 yes y | npx -y skills add https://github.com/kepano/obsidian-skills \
|
|
134
|
-
--skill obsidian-markdown --skill obsidian-bases \
|
|
135
|
-
--skill json-canvas --skill obsidian-cli --skill defuddle \
|
|
136
|
-
-g -a pi --copy -y
|
|
132
|
+
pvm setup /path/to/your/vault
|
|
137
133
|
```
|
|
138
134
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
and
|
|
135
|
+
The skills live under
|
|
136
|
+
`<vault>/.vault-mind/.pi/agent/skills/<name>/SKILL.md`. `pvm run` disables
|
|
137
|
+
Pi's implicit global/project skill discovery and explicitly loads only these
|
|
138
|
+
curated skills plus skills provided by packages installed in the same
|
|
139
|
+
vault-local agent directory. Do not install these skills globally for a Vault
|
|
140
|
+
Mind session; global copies defeat vault isolation and can create skill-name
|
|
141
|
+
conflicts.
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
- `obsidian-markdown` — Obsidian-flavored Markdown syntax
|
|
144
|
+
- `obsidian-bases` — valid `.base` database views
|
|
145
|
+
- `json-canvas` — Canvas JSON used by graph sync
|
|
146
|
+
- `obsidian-cli` — Obsidian CLI operation
|
|
147
|
+
- `nlm-skill` — NotebookLM CLI and MCP workflows
|
|
144
148
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
done
|
|
149
|
-
```
|
|
150
|
-
- `obsidian-markdown` — agent learns Obsidian-flavored markdown syntax
|
|
151
|
-
- `obsidian-bases` — agent learns to generate valid `.base` files (database views)
|
|
152
|
-
- `json-canvas` — agent learns Canvas JSON format (used for our graph sync)
|
|
153
|
-
- `obsidian-cli` — agent learns to use the Obsidian CLI
|
|
154
|
-
- `defuddle` — cleaner markdown extraction from web pages
|
|
155
|
-
|
|
156
|
-
These skills let the **Miner, Broadcaster, and Heavy-Lifter agents** produce valid Obsidian content.
|
|
149
|
+
These skills let the **Miner, Broadcaster, and Heavy-Lifter agents** produce
|
|
150
|
+
valid Obsidian content without changing the identity of the interactive main
|
|
151
|
+
agent.
|
|
157
152
|
|
|
158
153
|
### Built-in Obsidian features used
|
|
159
154
|
|
|
@@ -176,7 +171,7 @@ The Broadcaster agent can generate podcasts, study guides, and slide decks from
|
|
|
176
171
|
|
|
177
172
|
### Prerequisites
|
|
178
173
|
|
|
179
|
-
- **Node.js**
|
|
174
|
+
- **Node.js** 22.19.0+ (matches `engines` in `package.json`)
|
|
180
175
|
- **Embedding Provider** — choose one:
|
|
181
176
|
- `@xenova/transformers` — built-in, no external deps (uses all-MiniLM-L6-v2, offline-capable)
|
|
182
177
|
- `ollama` — requires Ollama running locally with `embeddinggemma` (higher quality)
|
|
@@ -190,47 +185,66 @@ The Broadcaster agent can generate podcasts, study guides, and slide decks from
|
|
|
190
185
|
> bearer token are private to whoever owns it. (A standalone PyPI package for the
|
|
191
186
|
> server may come later.)
|
|
192
187
|
|
|
193
|
-
### 1. Install
|
|
194
|
-
|
|
195
|
-
```bash
|
|
196
|
-
pi install npm:pi-vault-mind # latest
|
|
197
|
-
pi install npm:pi-vault-mind@0.16.30 # pinned release
|
|
198
|
-
pi -e npm:pi-vault-mind # try without installing
|
|
199
|
-
```
|
|
188
|
+
### 1. Install and set up the vault-local runtime
|
|
200
189
|
|
|
201
|
-
|
|
202
|
-
shell `PATH`. Install the first-class launcher once when you want the bare
|
|
203
|
-
`pvm` command:
|
|
190
|
+
Install the first-class `pvm` CLI once, then run setup against a vault:
|
|
204
191
|
|
|
205
192
|
```bash
|
|
206
193
|
npm install --global pi-vault-mind
|
|
194
|
+
pvm setup /path/to/your/vault
|
|
207
195
|
pvm run /path/to/your/vault
|
|
208
196
|
```
|
|
209
197
|
|
|
210
|
-
|
|
198
|
+
`pvm setup` is safe to repeat. It installs or updates the required Vault Mind,
|
|
199
|
+
context, model-routing, task, and subagent extensions inside
|
|
200
|
+
`<vault>/.vault-mind/.pi/agent/`; installs the curated `obsidian-cli`,
|
|
201
|
+
`obsidian-markdown`, `obsidian-bases`, and `json-canvas` skills; and
|
|
202
|
+
merge-safely scaffolds Vault Mind, model-router, and main-agent configuration.
|
|
203
|
+
Existing user configuration, collections, model choices, and `system.md` are
|
|
204
|
+
preserved.
|
|
205
|
+
|
|
206
|
+
Refresh only extensions, tools, and skills without touching vault
|
|
207
|
+
configuration:
|
|
211
208
|
|
|
212
209
|
```bash
|
|
213
|
-
|
|
210
|
+
pvm setup --resources-only /path/to/your/vault
|
|
214
211
|
```
|
|
215
212
|
|
|
216
|
-
|
|
213
|
+
Audit the isolated runtime without changing it, or repair it in place:
|
|
217
214
|
|
|
218
215
|
```bash
|
|
219
|
-
|
|
216
|
+
pvm check-deps /path/to/your/vault
|
|
217
|
+
pvm check-deps --fix /path/to/your/vault
|
|
220
218
|
```
|
|
221
219
|
|
|
222
|
-
|
|
220
|
+
Add `--strict` to fail when optional tools are missing and `--obsidian` to
|
|
221
|
+
include recommended Obsidian plugin checks.
|
|
222
|
+
|
|
223
|
+
Run either mode without a global installation:
|
|
223
224
|
|
|
225
|
+
```bash
|
|
226
|
+
npx --yes pi-vault-mind setup /path/to/your/vault
|
|
227
|
+
npx --yes pi-vault-mind run /path/to/your/vault
|
|
224
228
|
```
|
|
225
|
-
|
|
229
|
+
|
|
230
|
+
Installing only the Pi extension remains supported:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
pi install npm:pi-vault-mind
|
|
234
|
+
pi -e npm:pi-vault-mind
|
|
226
235
|
```
|
|
227
236
|
|
|
228
|
-
|
|
229
|
-
provider details, folder layout, and scaffolding.
|
|
237
|
+
### 2. Configure interactively when needed
|
|
230
238
|
|
|
231
|
-
|
|
239
|
+
Inside Pi, use the wizard to choose or change embedding providers, folder
|
|
240
|
+
layout, and other user-facing settings:
|
|
232
241
|
|
|
233
|
-
```
|
|
242
|
+
```text
|
|
243
|
+
/vm setup
|
|
244
|
+
```
|
|
245
|
+
For a non-interactive repair inside Pi:
|
|
246
|
+
|
|
247
|
+
```text
|
|
234
248
|
/vm setup --vault /home/you/Obsidian/MyVault --remoteUrl https://your-embedding-service-url.example.com --model embeddinggemma
|
|
235
249
|
```
|
|
236
250
|
|
package/dist/src/commands.js
CHANGED
|
@@ -259,7 +259,7 @@ const handleInit = async (_args, ctx, pi) => {
|
|
|
259
259
|
const existing = JSON.parse(fs.readFileSync(cfgDest, "utf-8"));
|
|
260
260
|
existing.extensionCompatibility = existing.extensionCompatibility || {};
|
|
261
261
|
existing.extensionCompatibility["pi-context"] = {
|
|
262
|
-
|
|
262
|
+
checkpointPatterns: [],
|
|
263
263
|
enhanceInjectors: false,
|
|
264
264
|
autoEnableAcm: true,
|
|
265
265
|
indexContextEvents: true,
|
|
@@ -314,7 +314,7 @@ const handleValidate = async (_args, ctx, pi) => {
|
|
|
314
314
|
const contextCfg = getPiContextConfig(cfg);
|
|
315
315
|
const willCapture = hasContext && contextCfg.enabled;
|
|
316
316
|
lines.push("", "🧩 Extension Integrations:", " • pi-context:");
|
|
317
|
-
lines.push(` - Tools installed: ${hasContext ? "✅ Yes (
|
|
317
|
+
lines.push(` - Tools installed: ${hasContext ? "✅ Yes (context_checkpoint, context_timeline, context_compact)" : "❌ No"}`);
|
|
318
318
|
lines.push(` - Config enabled: ${contextCfg.enabled ? "✅ Yes" : "❌ No"}`);
|
|
319
319
|
lines.push(` - Will capture events: ${willCapture ? "✅ Yes — on next turn" : "❌ No"}`);
|
|
320
320
|
if (hasContext && !contextCfg.enabled)
|
|
@@ -1122,10 +1122,10 @@ const handleContext = async (args, ctx, pi) => {
|
|
|
1122
1122
|
` - Config enabled: ${piContextCfg.enabled ? "✅" : "❌"}`,
|
|
1123
1123
|
` - Will capture on next turn: ${willCapture ? "✅ Yes" : "❌ No"}`,
|
|
1124
1124
|
"",
|
|
1125
|
-
`
|
|
1126
|
-
...(piContextCfg.
|
|
1127
|
-
? piContextCfg.
|
|
1128
|
-
: [" (none — no
|
|
1125
|
+
`Checkpoint Patterns: ${piContextCfg.checkpointPatterns?.length || 0}`,
|
|
1126
|
+
...(piContextCfg.checkpointPatterns?.length
|
|
1127
|
+
? piContextCfg.checkpointPatterns.map((p) => ` • "${p}"`)
|
|
1128
|
+
: [" (none — no checkpoint-based lookups)"]),
|
|
1129
1129
|
"",
|
|
1130
1130
|
`Enhance Injectors: ${piContextCfg.enhanceInjectors ? "Yes" : "No"}`,
|
|
1131
1131
|
`autoEnableAcm: ${piContextCfg.autoEnableAcm ? "Yes" : "No"}`,
|
|
@@ -1163,7 +1163,7 @@ const _toggleContext = (cfgPath, enabled) => {
|
|
|
1163
1163
|
const existing = JSON.parse(fs.readFileSync(cfgPath, "utf-8"));
|
|
1164
1164
|
existing.extensionCompatibility = existing.extensionCompatibility || {};
|
|
1165
1165
|
existing.extensionCompatibility["pi-context"] = {
|
|
1166
|
-
|
|
1166
|
+
checkpointPatterns: [],
|
|
1167
1167
|
enhanceInjectors: false,
|
|
1168
1168
|
autoEnableAcm: true,
|
|
1169
1169
|
indexContextEvents: true,
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Context Capture — Layer 4
|
|
2
|
+
* Context Capture — Layer 4 pi-context /acm reminder.
|
|
3
|
+
*
|
|
4
|
+
* On extension load, reminds the human to run /acm to enable agentic context
|
|
5
|
+
* management. Does NOT inject /acm as a user or model message; the reminder
|
|
6
|
+
* is an unobtrusive UI notification only.
|
|
3
7
|
*
|
|
4
|
-
* On extension load, auto-sends /acm to enable agentic context management.
|
|
5
8
|
* Injects context_checkpoint instructions into agent task prompts.
|
|
6
9
|
*
|
|
7
10
|
* Note: context_compact requires CommandCtx (only in main session, not
|
|
8
11
|
* subagent forks). Subagent forks use context_checkpoint and context_timeline.
|
|
9
12
|
*/
|
|
10
|
-
import type {
|
|
13
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
11
14
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
15
|
+
* Notify the human to run /acm to enable agentic context management.
|
|
16
|
+
*
|
|
17
|
+
* Uses ctx.ui.notify — a transient TUI notification that never enters the
|
|
18
|
+
* session history and is never delivered to the model.
|
|
14
19
|
*/
|
|
15
|
-
export declare function
|
|
20
|
+
export declare function notifyAcmReminder(ctx: ExtensionContext): void;
|
|
16
21
|
/**
|
|
17
22
|
* Build context_checkpoint instructions to inject into a dispatch task prompt.
|
|
18
23
|
*
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Context Capture — Layer 4
|
|
2
|
+
* Context Capture — Layer 4 pi-context /acm reminder.
|
|
3
|
+
*
|
|
4
|
+
* On extension load, reminds the human to run /acm to enable agentic context
|
|
5
|
+
* management. Does NOT inject /acm as a user or model message; the reminder
|
|
6
|
+
* is an unobtrusive UI notification only.
|
|
3
7
|
*
|
|
4
|
-
* On extension load, auto-sends /acm to enable agentic context management.
|
|
5
8
|
* Injects context_checkpoint instructions into agent task prompts.
|
|
6
9
|
*
|
|
7
10
|
* Note: context_compact requires CommandCtx (only in main session, not
|
|
8
11
|
* subagent forks). Subagent forks use context_checkpoint and context_timeline.
|
|
9
12
|
*/
|
|
10
|
-
// ── ACM
|
|
13
|
+
// ── ACM reminder notification ─────────────────────────────────────────────────
|
|
11
14
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
15
|
+
* Notify the human to run /acm to enable agentic context management.
|
|
16
|
+
*
|
|
17
|
+
* Uses ctx.ui.notify — a transient TUI notification that never enters the
|
|
18
|
+
* session history and is never delivered to the model.
|
|
14
19
|
*/
|
|
15
|
-
export function
|
|
16
|
-
|
|
20
|
+
export function notifyAcmReminder(ctx) {
|
|
21
|
+
ctx.ui.notify("Run /acm to enable agentic context management for this session.", "info");
|
|
17
22
|
}
|
|
18
23
|
// ── Checkpoint instructions for agent task prompts ────────────────────────────
|
|
19
24
|
/**
|
package/dist/src/events.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { BeforeAgentStartEvent, ExtensionAPI, ExtensionContext, TurnEndEvent } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
/**
|
|
3
|
-
* Handles before_agent_start to inject collection entries and pi-context
|
|
3
|
+
* Handles before_agent_start to inject collection entries and pi-context checkpoint matches
|
|
4
4
|
* into the system prompt.
|
|
5
5
|
*/
|
|
6
6
|
export declare const handleBeforeAgentStart: (pi: ExtensionAPI, event: BeforeAgentStartEvent, ctx: ExtensionContext) => Promise<{
|
|
7
7
|
systemPrompt?: string;
|
|
8
8
|
} | undefined>;
|
|
9
9
|
/**
|
|
10
|
-
* Handles turn_end to capture pi-context
|
|
10
|
+
* Handles turn_end to capture pi-context checkpoints and summaries in the
|
|
11
11
|
* context_events collection.
|
|
12
12
|
*/
|
|
13
13
|
export declare const handleTurnEnd: (pi: ExtensionAPI, _event: TurnEndEvent, ctx: ExtensionContext) => Promise<void>;
|
package/dist/src/events.js
CHANGED
|
@@ -2,7 +2,7 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import { getActiveCollection } from "./state.js";
|
|
3
3
|
import { ensureDir, getPiContextConfig, hasPiContextTools, loadConfig } from "./utils.js";
|
|
4
4
|
/**
|
|
5
|
-
* Handles before_agent_start to inject collection entries and pi-context
|
|
5
|
+
* Handles before_agent_start to inject collection entries and pi-context checkpoint matches
|
|
6
6
|
* into the system prompt.
|
|
7
7
|
*/
|
|
8
8
|
export const handleBeforeAgentStart = async (pi, event, ctx) => {
|
|
@@ -46,81 +46,71 @@ export const handleBeforeAgentStart = async (pi, event, ctx) => {
|
|
|
46
46
|
.replace(/\{\{entries\}\}/g, entriesText || "(none)")
|
|
47
47
|
.replace(/\{\{artifact\}\}/g, artifactText || "(none)");
|
|
48
48
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// 2. pi-context integration: auto-ACM and tag-based triggers
|
|
49
|
+
// 2. pi-context integration: checkpoint-based triggers via sessionManager labels.
|
|
50
|
+
// context_checkpoint calls pi.setLabel(targetId, name); we read those labels directly
|
|
51
|
+
// from ctx.sessionManager — no cross-extension tool execution required.
|
|
53
52
|
const piContextCfg = getPiContextConfig(cfg);
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
for (const [collectionName, collectionDef] of Object.entries(cfg.collections)) {
|
|
81
|
-
if (collectionDef.schema.includes("tag") &&
|
|
82
|
-
fs.existsSync(collectionDef.path)) {
|
|
83
|
-
const lines = fs
|
|
84
|
-
.readFileSync(collectionDef.path, "utf-8")
|
|
85
|
-
.split("\n")
|
|
86
|
-
.filter(Boolean);
|
|
87
|
-
const hits = lines
|
|
88
|
-
.map((l) => {
|
|
89
|
-
try {
|
|
90
|
-
return JSON.parse(l);
|
|
91
|
-
}
|
|
92
|
-
catch {
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
95
|
-
})
|
|
96
|
-
.filter((e) => e && e.tag === tagValue);
|
|
97
|
-
if (hits.length > 0) {
|
|
98
|
-
additions += `\n\n=== pi-context tag [${tagValue}] matched ${collectionName} ===\n${JSON.stringify(hits, null, 2)}\n`;
|
|
99
|
-
tagInjections += hits.length;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
53
|
+
if (piContextCfg.enabled &&
|
|
54
|
+
hasPiContextTools(pi) &&
|
|
55
|
+
piContextCfg.checkpointPatterns &&
|
|
56
|
+
piContextCfg.checkpointPatterns.length > 0) {
|
|
57
|
+
try {
|
|
58
|
+
const sm = ctx.sessionManager;
|
|
59
|
+
// Inspect only the current branch (root-to-leaf path) for labels.
|
|
60
|
+
// getBranch() excludes entries on abandoned forks; getEntries() would span
|
|
61
|
+
// all forks and wrongly trigger injection for off-branch checkpoints.
|
|
62
|
+
const branchEntries = sm.getBranch();
|
|
63
|
+
// Collect all distinct labels present on the active branch
|
|
64
|
+
const checkpointNames = new Set();
|
|
65
|
+
for (const entry of branchEntries) {
|
|
66
|
+
const label = sm.getLabel(entry.id);
|
|
67
|
+
if (label)
|
|
68
|
+
checkpointNames.add(label);
|
|
69
|
+
}
|
|
70
|
+
let checkpointInjections = 0;
|
|
71
|
+
for (const pattern of piContextCfg.checkpointPatterns) {
|
|
72
|
+
const checkpointRegex = new RegExp(pattern, "i");
|
|
73
|
+
for (const checkpointName of checkpointNames) {
|
|
74
|
+
if (!checkpointRegex.test(checkpointName))
|
|
75
|
+
continue;
|
|
76
|
+
for (const [collectionName, collectionDef] of Object.entries(cfg.collections)) {
|
|
77
|
+
if (!collectionDef.schema.includes("tag") || !fs.existsSync(collectionDef.path)) {
|
|
78
|
+
continue;
|
|
106
79
|
}
|
|
107
|
-
|
|
108
|
-
|
|
80
|
+
const hits = fs
|
|
81
|
+
.readFileSync(collectionDef.path, "utf-8")
|
|
82
|
+
.split("\n")
|
|
83
|
+
.filter(Boolean)
|
|
84
|
+
.map((line) => {
|
|
85
|
+
try {
|
|
86
|
+
return JSON.parse(line);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
.filter((e) => e?.tag === checkpointName);
|
|
93
|
+
if (hits.length > 0) {
|
|
94
|
+
additions += `\n\n=== pi-context checkpoint [${checkpointName}] matched ${collectionName} ===\n${JSON.stringify(hits, null, 2)}\n`;
|
|
95
|
+
checkpointInjections += hits.length;
|
|
109
96
|
}
|
|
110
97
|
}
|
|
111
98
|
}
|
|
112
99
|
}
|
|
113
|
-
|
|
114
|
-
|
|
100
|
+
if (checkpointInjections > 0) {
|
|
101
|
+
ctx.ui?.notify?.(`pi-context: injected ${checkpointInjections} entries from matching checkpoints`, "info");
|
|
115
102
|
}
|
|
116
103
|
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.warn("[pi-vault-mind] pi-context checkpoint integration error:", error);
|
|
106
|
+
}
|
|
117
107
|
}
|
|
118
108
|
if (additions) {
|
|
119
109
|
return { systemPrompt: event.systemPrompt + additions };
|
|
120
110
|
}
|
|
121
111
|
};
|
|
122
112
|
/**
|
|
123
|
-
* Handles turn_end to capture pi-context
|
|
113
|
+
* Handles turn_end to capture pi-context checkpoints and summaries in the
|
|
124
114
|
* context_events collection.
|
|
125
115
|
*/
|
|
126
116
|
export const handleTurnEnd = async (pi, _event, ctx) => {
|
|
@@ -131,96 +121,83 @@ export const handleTurnEnd = async (pi, _event, ctx) => {
|
|
|
131
121
|
return;
|
|
132
122
|
}
|
|
133
123
|
try {
|
|
134
|
-
if (!hasPiContextTools(pi)) {
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
const allTools = pi.getAllTools();
|
|
138
|
-
const contextLogTool = allTools.find((t) => t.name === "context_log");
|
|
139
|
-
const contextCheckoutTool = allTools.find((t) => t.name === "context_checkout");
|
|
140
|
-
if (!contextLogTool || !contextCheckoutTool) {
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
124
|
const collectionDef = cfg.collections.context_events;
|
|
144
125
|
if (!collectionDef) {
|
|
145
126
|
console.warn("[pi-vault-mind] 'context_events' collection not defined in config. Cannot index pi-context events.");
|
|
146
127
|
return;
|
|
147
128
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
const logText = logs.content[0].text;
|
|
129
|
+
const sm = ctx.sessionManager;
|
|
130
|
+
// Inspect the most recent 100 entries (100-entry bound matches prior behavior)
|
|
131
|
+
const recentEntries = sm.getEntries().slice(-100);
|
|
154
132
|
const capturedEvents = [];
|
|
155
|
-
const
|
|
156
|
-
for (const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const
|
|
160
|
-
if (
|
|
161
|
-
|
|
162
|
-
id: `
|
|
163
|
-
type: "
|
|
164
|
-
session_entry_id:
|
|
165
|
-
content: `
|
|
133
|
+
const timestamp = new Date().toISOString();
|
|
134
|
+
for (const entry of recentEntries) {
|
|
135
|
+
// Checkpoint: pi-context stores checkpoints as Pi labels on session entries.
|
|
136
|
+
// context_checkpoint calls pi.setLabel(entryId, name); we read via sm.getLabel.
|
|
137
|
+
const label = sm.getLabel(entry.id);
|
|
138
|
+
if (label) {
|
|
139
|
+
capturedEvents.push({
|
|
140
|
+
id: `checkpoint-${entry.id}-${label}`,
|
|
141
|
+
type: "checkpoint_created",
|
|
142
|
+
session_entry_id: entry.id,
|
|
143
|
+
content: `Checkpoint '${label}' created at ${entry.id}`,
|
|
166
144
|
timestamp,
|
|
167
|
-
tags: [
|
|
145
|
+
tags: [label, "pi-context", "checkpoint"],
|
|
168
146
|
details: {
|
|
169
|
-
|
|
170
|
-
entry_id:
|
|
171
|
-
entry_type:
|
|
172
|
-
entry_summary: tagMatch[4].trim(),
|
|
147
|
+
checkpoint_name: label,
|
|
148
|
+
entry_id: entry.id,
|
|
149
|
+
entry_type: entry.type.toUpperCase(),
|
|
173
150
|
},
|
|
174
|
-
};
|
|
151
|
+
});
|
|
175
152
|
}
|
|
176
|
-
|
|
177
|
-
if (
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
153
|
+
// Summary: compaction and branch_summary entries carry a real `.summary` string.
|
|
154
|
+
if ((entry.type === "compaction" || entry.type === "branch_summary") &&
|
|
155
|
+
"summary" in entry &&
|
|
156
|
+
typeof entry.summary === "string") {
|
|
157
|
+
capturedEvents.push({
|
|
158
|
+
id: `context-summary-${entry.id}`,
|
|
159
|
+
type: "context_summary",
|
|
160
|
+
session_entry_id: entry.id,
|
|
161
|
+
content: entry.summary,
|
|
183
162
|
timestamp,
|
|
184
|
-
tags: ["pi-context", "
|
|
163
|
+
tags: ["pi-context", "summary"],
|
|
185
164
|
details: {
|
|
186
|
-
|
|
187
|
-
summary_message:
|
|
188
|
-
entry_id: summaryMatch[1],
|
|
165
|
+
entry_id: entry.id,
|
|
166
|
+
summary_message: entry.summary,
|
|
189
167
|
},
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
if (event) {
|
|
193
|
-
capturedEvents.push(event);
|
|
168
|
+
});
|
|
194
169
|
}
|
|
195
170
|
}
|
|
196
|
-
// Append events
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
/* ignore malformed */
|
|
208
|
-
}
|
|
171
|
+
// Append events to the context_events collection with dedup
|
|
172
|
+
ensureDir(collectionDef.path);
|
|
173
|
+
const existingIds = new Set();
|
|
174
|
+
if (collectionDef.dedupField && fs.existsSync(collectionDef.path)) {
|
|
175
|
+
const data = fs.readFileSync(collectionDef.path, "utf-8");
|
|
176
|
+
for (const line of data.split("\n").filter(Boolean)) {
|
|
177
|
+
try {
|
|
178
|
+
existingIds.add(JSON.parse(line)[collectionDef.dedupField]);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
/* ignore malformed */
|
|
209
182
|
}
|
|
210
183
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
184
|
+
}
|
|
185
|
+
let appended = 0;
|
|
186
|
+
for (const capturedEvent of capturedEvents) {
|
|
187
|
+
if (collectionDef.dedupField) {
|
|
188
|
+
const dedupVal = capturedEvent[collectionDef.dedupField];
|
|
189
|
+
if (existingIds.has(dedupVal))
|
|
214
190
|
continue;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (collectionDef.dedupField)
|
|
218
|
-
existingIds.add(event[collectionDef.dedupField]);
|
|
219
|
-
appended++;
|
|
191
|
+
fs.appendFileSync(collectionDef.path, `${JSON.stringify(capturedEvent)}\n`);
|
|
192
|
+
existingIds.add(dedupVal);
|
|
220
193
|
}
|
|
221
|
-
|
|
222
|
-
|
|
194
|
+
else {
|
|
195
|
+
fs.appendFileSync(collectionDef.path, `${JSON.stringify(capturedEvent)}\n`);
|
|
223
196
|
}
|
|
197
|
+
appended++;
|
|
198
|
+
}
|
|
199
|
+
if (appended > 0 && ctx.ui?.notify) {
|
|
200
|
+
ctx.ui.notify(`pi-context: captured ${appended} event(s) → ${collectionDef.path}`, "info");
|
|
224
201
|
}
|
|
225
202
|
}
|
|
226
203
|
catch (e) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Canonical list
|
|
2
|
+
* Canonical extension list for the legacy `/vm setup` and Obsidian setup
|
|
3
|
+
* surfaces. The standalone `pvm` CLI has a broader package-managed runtime
|
|
4
|
+
* contract in `runtime/pvm-extensions.json`.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
* consume generated JSON (see scripts/generate-extension-packages-json.mjs).
|
|
6
|
-
* When adding/removing a package, edit ONLY this file and regenerate.
|
|
6
|
+
* Generate this surface with scripts/generate-extension-packages-json.mjs.
|
|
7
7
|
*/
|
|
8
8
|
export declare const PI_REQUIRED_EXTENSIONS: readonly ["npm:pi-vault-mind", "npm:pi-context", "npm:@kylebrodeur/pi-model-discovery", "npm:@kylebrodeur/pi-model-router"];
|
|
9
9
|
export declare const PI_OPTIONAL_EXTENSIONS: readonly ["npm:pi-1password"];
|