pi-vault-mind 0.16.30 → 0.16.31
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 +28 -0
- package/README.md +40 -21
- 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/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 +218 -0
- package/dist/test/utils.test.js +26 -4
- package/dist/test/vault-pi-script.test.js +18 -0
- 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 +218 -0
- package/scripts/pvm.mjs +96 -3
- package/scripts/setup-vault-pi.sh +2 -66
- package/scripts/vault-pi.sh +34 -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,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.16.31 — 2026-08-28
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **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.
|
|
8
|
+
- **Resource-only repair.** `pvm setup --resources-only [vault-path]` refreshes extensions, tools, and skills without changing vault configuration.
|
|
9
|
+
- **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.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- **Pi 0.84.3 runtime.** Development and compatibility checks now target `@earendil-works/pi-coding-agent` and `@earendil-works/pi-tui` 0.84.3.
|
|
14
|
+
- **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.
|
|
15
|
+
- **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.
|
|
16
|
+
- **Pi Context 2.1.2 integration.** Session-start and turn-end capture now use the current checkpoint and context-event APIs.
|
|
17
|
+
- **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.
|
|
18
|
+
- **Reproducible package tooling.** The repository now pins pnpm 10.34.5 so Corepack does not select an incompatible pnpm major during clean release builds.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **Quiet main-agent startup.** Automatic context management initializes without injecting a synthetic `/acm` user message into a new session.
|
|
23
|
+
- **Stable Pi launcher selection.** Setup avoids transient `npx` binaries and consistently provisions the vault-local agent directory with the installed Pi runtime.
|
|
24
|
+
|
|
25
|
+
### Verification
|
|
26
|
+
|
|
27
|
+
- Node 24.19.0 with pnpm 10.34.5: dependency install, core build, and package-scoped Biome check completed successfully.
|
|
28
|
+
- Full core test suite: 937/937 passing.
|
|
29
|
+
- Packed `pi-vault-mind-0.16.31.tgz` successfully; the packaged `pvm --help` executable ran and exposed the `run`, `setup`, and `check-deps` commands.
|
|
30
|
+
|
|
3
31
|
## 0.16.30 — 2026-08-27
|
|
4
32
|
|
|
5
33
|
### Added
|
package/README.md
CHANGED
|
@@ -176,7 +176,7 @@ The Broadcaster agent can generate podcasts, study guides, and slide decks from
|
|
|
176
176
|
|
|
177
177
|
### Prerequisites
|
|
178
178
|
|
|
179
|
-
- **Node.js**
|
|
179
|
+
- **Node.js** 22.19.0+ (matches `engines` in `package.json`)
|
|
180
180
|
- **Embedding Provider** — choose one:
|
|
181
181
|
- `@xenova/transformers` — built-in, no external deps (uses all-MiniLM-L6-v2, offline-capable)
|
|
182
182
|
- `ollama` — requires Ollama running locally with `embeddinggemma` (higher quality)
|
|
@@ -190,47 +190,66 @@ The Broadcaster agent can generate podcasts, study guides, and slide decks from
|
|
|
190
190
|
> bearer token are private to whoever owns it. (A standalone PyPI package for the
|
|
191
191
|
> server may come later.)
|
|
192
192
|
|
|
193
|
-
### 1. Install
|
|
193
|
+
### 1. Install and set up the vault-local runtime
|
|
194
194
|
|
|
195
|
-
|
|
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
|
-
```
|
|
200
|
-
|
|
201
|
-
`pi install` loads the extension but does not expose its npm executable on your
|
|
202
|
-
shell `PATH`. Install the first-class launcher once when you want the bare
|
|
203
|
-
`pvm` command:
|
|
195
|
+
Install the first-class `pvm` CLI once, then run setup against a vault:
|
|
204
196
|
|
|
205
197
|
```bash
|
|
206
198
|
npm install --global pi-vault-mind
|
|
199
|
+
pvm setup /path/to/your/vault
|
|
207
200
|
pvm run /path/to/your/vault
|
|
208
201
|
```
|
|
209
202
|
|
|
210
|
-
|
|
203
|
+
`pvm setup` is safe to repeat. It installs or updates the required Vault Mind,
|
|
204
|
+
context, model-routing, task, and subagent extensions inside
|
|
205
|
+
`<vault>/.vault-mind/.pi/agent/`; installs the curated `obsidian-cli`,
|
|
206
|
+
`obsidian-markdown`, `obsidian-bases`, and `json-canvas` skills; and
|
|
207
|
+
merge-safely scaffolds Vault Mind, model-router, and main-agent configuration.
|
|
208
|
+
Existing user configuration, collections, model choices, and `system.md` are
|
|
209
|
+
preserved.
|
|
210
|
+
|
|
211
|
+
Refresh only extensions, tools, and skills without touching vault
|
|
212
|
+
configuration:
|
|
211
213
|
|
|
212
214
|
```bash
|
|
213
|
-
|
|
215
|
+
pvm setup --resources-only /path/to/your/vault
|
|
214
216
|
```
|
|
215
217
|
|
|
216
|
-
|
|
218
|
+
Audit the isolated runtime without changing it, or repair it in place:
|
|
217
219
|
|
|
218
220
|
```bash
|
|
219
|
-
|
|
221
|
+
pvm check-deps /path/to/your/vault
|
|
222
|
+
pvm check-deps --fix /path/to/your/vault
|
|
220
223
|
```
|
|
221
224
|
|
|
222
|
-
|
|
225
|
+
Add `--strict` to fail when optional tools are missing and `--obsidian` to
|
|
226
|
+
include recommended Obsidian plugin checks.
|
|
223
227
|
|
|
228
|
+
Run either mode without a global installation:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
npx --yes pi-vault-mind setup /path/to/your/vault
|
|
232
|
+
npx --yes pi-vault-mind run /path/to/your/vault
|
|
224
233
|
```
|
|
225
|
-
|
|
234
|
+
|
|
235
|
+
Installing only the Pi extension remains supported:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
pi install npm:pi-vault-mind
|
|
239
|
+
pi -e npm:pi-vault-mind
|
|
226
240
|
```
|
|
227
241
|
|
|
228
|
-
|
|
229
|
-
provider details, folder layout, and scaffolding.
|
|
242
|
+
### 2. Configure interactively when needed
|
|
230
243
|
|
|
231
|
-
|
|
244
|
+
Inside Pi, use the wizard to choose or change embedding providers, folder
|
|
245
|
+
layout, and other user-facing settings:
|
|
232
246
|
|
|
233
|
-
```
|
|
247
|
+
```text
|
|
248
|
+
/vm setup
|
|
249
|
+
```
|
|
250
|
+
For a non-interactive repair inside Pi:
|
|
251
|
+
|
|
252
|
+
```text
|
|
234
253
|
/vm setup --vault /home/you/Obsidian/MyVault --remoteUrl https://your-embedding-service-url.example.com --model embeddinggemma
|
|
235
254
|
```
|
|
236
255
|
|
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) {
|
package/dist/src/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { TaskQueue } from "./agent-bus/TaskQueue.js";
|
|
|
5
5
|
import { startAutoSync } from "./autosync.js";
|
|
6
6
|
import { createBridge } from "./bridge.js";
|
|
7
7
|
import { registerCommands, selectActiveCollection, serverState, watcherState } from "./commands.js";
|
|
8
|
-
import {
|
|
8
|
+
import { notifyAcmReminder } from "./context-capture.js";
|
|
9
9
|
import { startEngine, stopEngine } from "./engine.js";
|
|
10
10
|
import { handleBeforeAgentStart, handleTurnEnd } from "./events.js";
|
|
11
11
|
import { registerIdentityInjector } from "./identity-injector.js";
|
|
@@ -13,7 +13,7 @@ import { registerIntakeTool } from "./intake.js";
|
|
|
13
13
|
import { startServer, stopServer } from "./server.js";
|
|
14
14
|
import { clearEngineStatus, clearWatcherStatus, registerStatusCapture, setEngineStatus, } from "./status.js";
|
|
15
15
|
import { registerTools } from "./tools.js";
|
|
16
|
-
import { EXT_ROOT, isVaultMindReady, loadConfig } from "./utils.js";
|
|
16
|
+
import { EXT_ROOT, hasPiContextTools, isVaultMindReady, loadConfig } from "./utils.js";
|
|
17
17
|
import { registerVaultTools } from "./vault-tools.js";
|
|
18
18
|
import { registerAllExtensionTools } from "./vm-handlers.js";
|
|
19
19
|
import { startWatcher, stopWatcher, subscribeJobCompleted } from "./watcher.js";
|
|
@@ -37,14 +37,15 @@ export default function (pi) {
|
|
|
37
37
|
* during extension loading — the runtime must be initialized first. */
|
|
38
38
|
pi.on("session_start", async (_event, ctx) => {
|
|
39
39
|
updateActiveCollectionWidget(ctx);
|
|
40
|
-
/*
|
|
41
|
-
*
|
|
42
|
-
* config, whose DEFAULT_CONFIG always populates embedding.localUrl and
|
|
43
|
-
* would make a fresh vault look ready). */
|
|
40
|
+
/* Remind the human about ACM only when this vault is completely configured,
|
|
41
|
+
* pi-context is available, and the reminder has not been disabled. */
|
|
44
42
|
const sessionCfg = loadConfig(ctx.cwd);
|
|
45
43
|
const piCtxCfg = sessionCfg.extensionCompatibility?.["pi-context"];
|
|
46
|
-
if (isVaultMindReady(ctx.cwd) &&
|
|
47
|
-
|
|
44
|
+
if (isVaultMindReady(ctx.cwd) &&
|
|
45
|
+
piCtxCfg?.enabled &&
|
|
46
|
+
piCtxCfg?.autoEnableAcm !== false &&
|
|
47
|
+
hasPiContextTools(pi)) {
|
|
48
|
+
notifyAcmReminder(ctx);
|
|
48
49
|
}
|
|
49
50
|
/* register shortcut */
|
|
50
51
|
pi.registerShortcut("ctrl+alt+l", {
|
package/dist/src/personalize.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { parseFrontmatter } from "@earendil-works/pi-coding-agent";
|
|
4
|
-
import {
|
|
4
|
+
import { notifyAcmReminder } from "./context-capture.js";
|
|
5
5
|
import { getStatus } from "./lance.js";
|
|
6
6
|
import { scaffoldVaultConfig } from "./scaffold.js";
|
|
7
7
|
import { expandHome, getPersonalizedMarkerPath, hasPiContextTools, isPersonalized, loadConfig, resolveAgentDir, } from "./utils.js";
|
|
@@ -633,7 +633,7 @@ export const runPersonalize = async (ctx, pi) => {
|
|
|
633
633
|
const sessionCfg = loadConfig(ctx.cwd);
|
|
634
634
|
const piCtxCfg = sessionCfg.extensionCompatibility?.["pi-context"];
|
|
635
635
|
if (piCtxCfg?.enabled && piCtxCfg?.autoEnableAcm !== false && hasPiContextTools(pi)) {
|
|
636
|
-
|
|
636
|
+
notifyAcmReminder(ctx);
|
|
637
637
|
}
|
|
638
638
|
if (activePersonalizations.get(vaultKey) === controller) {
|
|
639
639
|
activePersonalizations.delete(vaultKey);
|
package/dist/src/settings-ui.js
CHANGED
|
@@ -631,7 +631,7 @@ export const setupWizard = async (ctx, cliArgs) => {
|
|
|
631
631
|
// config alongside everything else (no separate project file).
|
|
632
632
|
config.extensionCompatibility = config.extensionCompatibility || {};
|
|
633
633
|
config.extensionCompatibility["pi-context"] = {
|
|
634
|
-
|
|
634
|
+
checkpointPatterns: [],
|
|
635
635
|
enhanceInjectors: false,
|
|
636
636
|
autoEnableAcm: true,
|
|
637
637
|
indexContextEvents: true,
|
package/dist/src/types.d.ts
CHANGED
|
@@ -246,7 +246,7 @@ export interface IdentitiesConfig {
|
|
|
246
246
|
}
|
|
247
247
|
export interface PiContextDef {
|
|
248
248
|
enabled?: boolean;
|
|
249
|
-
|
|
249
|
+
checkpointPatterns?: string[];
|
|
250
250
|
enhanceInjectors?: boolean;
|
|
251
251
|
autoEnableAcm?: boolean;
|
|
252
252
|
indexContextEvents?: boolean;
|