pi-vault-mind 0.16.25 → 0.16.28
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 +26 -0
- package/dist/src/scaffold.js +1 -1
- package/dist/src/settings-ui.js +74 -1
- package/dist/src/types.js +1 -1
- package/dist/test/settings-ui.test.js +5 -0
- package/dist/test/utils.test.js +1 -1
- package/package.json +1 -1
- package/scripts/vault-pi.sh +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## 0.16.28 — 2026-08-09
|
|
5
|
+
|
|
6
|
+
### Fixed
|
|
7
|
+
|
|
8
|
+
- **CLI setup no longer invents vault folder structure.** `/vm setup` (and `scaffold.ts`'s fallback scaffolding) used to default `vaultMind.folders` to a guessed `Agent/Inbox`/`Agent/Library`/`Agent/Presentations`/`Agent/Journal` convention. In a real vault with its own organization scheme (PARA-style numbered folders, an existing inbox elsewhere, etc.) this silently created a stray top-level `Agent/` folder and misfiled real auto-synced content into it. The interactive wizard now shows a real folder picker — built from the vault's actual existing directories (walked up to 2 levels deep) — with explicit "Type a custom path..." and "Skip — configure later" options, matching the Obsidian plugin's existing `FoldersStep` folder-browser behavior. Headless `/vm setup` (CLI flags) and `scaffoldVaultConfig()` no longer populate a guessed folders block at all; `folders` stays unset until deliberately configured.
|
|
9
|
+
|
|
10
|
+
### Verification
|
|
11
|
+
|
|
12
|
+
- Full build + `node --test dist/test/**/*.test.js`: 894/894 passing.
|
|
13
|
+
- Added a regression test asserting a fresh headless `/vm setup` leaves `vaultMind.folders` unset rather than reinventing the old default.
|
|
14
|
+
- Reproduced the failure mode live: a real vault's auto-sync wrote 5 real notes into a newly-created `Agent/Inbox/` instead of the vault's actual `00-system/00.01-inbox/`.
|
|
15
|
+
|
|
16
|
+
## 0.16.27 — 2026-08-09
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **CLI setup drift — root cause of a real 404.** `vaultMind.dataDir` defaulted to bare `.lancedb` (leaks outside `.vault-mind/`) in `DEFAULT_CONFIG`/`scaffold.ts`; only the Obsidian plugin's wizard got this fix previously (`a8475d9`). Now `.vault-mind/.lancedb` in both.
|
|
21
|
+
- **Broken local Ollama URL.** The interactive `/vm setup` wizard's "Local (Ollama)" branch wrote `localUrl` as `http://127.0.0.1:11434/v1`; the OpenAI-compatible embedding provider then appends `/v1/embeddings` regardless, producing `.../v1/v1/embeddings` — a deterministic 404 on every embed, not the transient failure it looked like. Now writes the bare host, matching `DEFAULT_CONFIG` and the wizard's own Ollama probe three lines above the bug.
|
|
22
|
+
- **Missing vault folders in CLI setup.** `/vm setup` never asked about or defaulted `vaultMind.folders` (inbox/library/presentations/journal). Added a wizard step (with reconfigure pre-fill) and matching defaults in `scaffold.ts` and the headless CLI-args path, aligned with the Obsidian wizard's defaults.
|
|
23
|
+
- **`vault-pi.sh` Terminal.app detection** on macOS versions where it moved to `/System/Applications/Utilities/`.
|
|
24
|
+
|
|
25
|
+
### Verification
|
|
26
|
+
|
|
27
|
+
- Full build + `node --test dist/test/**/*.test.js`: 894/894 passing.
|
|
28
|
+
- Reproduced the `/v1/v1/embeddings` 404 live against a running Ollama instance before and after the fix.
|
|
29
|
+
|
|
4
30
|
## 0.16.12 / 0.6.16 — 2026-07-20
|
|
5
31
|
|
|
6
32
|
### Fixed
|
package/dist/src/scaffold.js
CHANGED
package/dist/src/settings-ui.js
CHANGED
|
@@ -458,7 +458,7 @@ export const setupWizard = async (ctx, cliArgs) => {
|
|
|
458
458
|
return;
|
|
459
459
|
}
|
|
460
460
|
if (provider.startsWith("Local")) {
|
|
461
|
-
localUrl = "http://127.0.0.1:11434
|
|
461
|
+
localUrl = "http://127.0.0.1:11434";
|
|
462
462
|
// Let user pick from detected Ollama embedding models
|
|
463
463
|
const modelChoice = await ctx.ui.select("Select embedding model:", ollamaModels.map((m) => m.name));
|
|
464
464
|
if (!modelChoice) {
|
|
@@ -514,6 +514,62 @@ export const setupWizard = async (ctx, cliArgs) => {
|
|
|
514
514
|
model = "Xenova/all-MiniLM-L6-v2";
|
|
515
515
|
dim = 384;
|
|
516
516
|
}
|
|
517
|
+
// ── Step 2.5: Vault folders ──────────────────────────────────────────────
|
|
518
|
+
// Lists real existing folders rather than guessing a convention (e.g.
|
|
519
|
+
// "Agent/Inbox") — a blind default silently creates the wrong structure
|
|
520
|
+
// in vaults that already have their own organization scheme.
|
|
521
|
+
const FOLDER_IGNORE = new Set([
|
|
522
|
+
".git",
|
|
523
|
+
".obsidian",
|
|
524
|
+
".vault-mind",
|
|
525
|
+
".pi",
|
|
526
|
+
"node_modules",
|
|
527
|
+
".trash",
|
|
528
|
+
".DS_Store",
|
|
529
|
+
]);
|
|
530
|
+
const listVaultFolders = (root) => {
|
|
531
|
+
const results = [];
|
|
532
|
+
const walk = (dir, rel, depth) => {
|
|
533
|
+
if (depth > 2)
|
|
534
|
+
return;
|
|
535
|
+
let entries;
|
|
536
|
+
try {
|
|
537
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
538
|
+
}
|
|
539
|
+
catch {
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
for (const entry of entries) {
|
|
543
|
+
if (!entry.isDirectory() || entry.name.startsWith(".") || FOLDER_IGNORE.has(entry.name))
|
|
544
|
+
continue;
|
|
545
|
+
const relPath = rel ? `${rel}/${entry.name}` : entry.name;
|
|
546
|
+
results.push(relPath);
|
|
547
|
+
walk(path.join(dir, entry.name), relPath, depth + 1);
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
walk(root, "", 0);
|
|
551
|
+
return results.sort();
|
|
552
|
+
};
|
|
553
|
+
const SKIP_FOLDER = "(skip — configure later)";
|
|
554
|
+
const CUSTOM_FOLDER = "→ Type a custom path...";
|
|
555
|
+
const pickFolder = async (label, current) => {
|
|
556
|
+
const options = [SKIP_FOLDER, CUSTOM_FOLDER, ...vaultFolders];
|
|
557
|
+
const prompt = current ? `${label} (current: ${current})` : label;
|
|
558
|
+
const choice = await ctx.ui.select(prompt, options);
|
|
559
|
+
if (!choice || choice === SKIP_FOLDER)
|
|
560
|
+
return "";
|
|
561
|
+
if (choice === CUSTOM_FOLDER)
|
|
562
|
+
return (await ctx.ui.input(`${label} — path:`, current || "")) || "";
|
|
563
|
+
return choice;
|
|
564
|
+
};
|
|
565
|
+
const existingFolders = existingConfigFile
|
|
566
|
+
? (JSON.parse(fs.readFileSync(getConfigPath(ctx.cwd), "utf-8")).vaultMind?.folders ?? {})
|
|
567
|
+
: {};
|
|
568
|
+
const vaultFolders = fs.existsSync(vaultPath) ? listVaultFolders(vaultPath) : [];
|
|
569
|
+
const inboxFolder = await pickFolder("Inbox folder (agent capture target)", existingFolders.inbox);
|
|
570
|
+
const libraryFolder = await pickFolder("Library folder (durable knowledge notes)", existingFolders.library);
|
|
571
|
+
const presentationsFolder = await pickFolder("Presentations folder", existingFolders.presentations);
|
|
572
|
+
const journalFolder = await pickFolder("Journal folder", existingFolders.journal);
|
|
517
573
|
// ── Step 3: Deterministic runtime settings ──────────────────────────────
|
|
518
574
|
const enableContextAutomation = await ctx.ui.confirm("Context automation", "Enable pi-context integration with auto-/acm trigger and event indexing?");
|
|
519
575
|
const enableAutoStart = await ctx.ui.confirm("Vault auto-start", "Auto-start watcher/server for this vault when pi session starts?");
|
|
@@ -522,6 +578,7 @@ export const setupWizard = async (ctx, cliArgs) => {
|
|
|
522
578
|
`Remote URL: ${remoteUrl || "none"}`,
|
|
523
579
|
`Local URL: ${localUrl || "none"}`,
|
|
524
580
|
`Model: ${model || "(auto/server default)"}`,
|
|
581
|
+
`Folders: inbox=${inboxFolder || "(unset)"}, library=${libraryFolder || "(unset)"}, presentations=${presentationsFolder || "(unset)"}, journal=${journalFolder || "(unset)"}`,
|
|
525
582
|
`Context automation: ${enableContextAutomation ? "enabled" : "disabled"}`,
|
|
526
583
|
`Vault auto-start: ${enableAutoStart ? "enabled" : "disabled"}`,
|
|
527
584
|
].join("\n"));
|
|
@@ -552,6 +609,22 @@ export const setupWizard = async (ctx, cliArgs) => {
|
|
|
552
609
|
autoSync: true,
|
|
553
610
|
autoStart: enableAutoStart,
|
|
554
611
|
};
|
|
612
|
+
const chosenFolders = {};
|
|
613
|
+
if (inboxFolder)
|
|
614
|
+
chosenFolders.inbox = inboxFolder;
|
|
615
|
+
if (libraryFolder)
|
|
616
|
+
chosenFolders.library = libraryFolder;
|
|
617
|
+
if (presentationsFolder)
|
|
618
|
+
chosenFolders.presentations = presentationsFolder;
|
|
619
|
+
if (journalFolder)
|
|
620
|
+
chosenFolders.journal = journalFolder;
|
|
621
|
+
if (Object.keys(chosenFolders).length > 0) {
|
|
622
|
+
config.vaultMind.folders = chosenFolders;
|
|
623
|
+
}
|
|
624
|
+
else if (Object.keys(existingFolders).length > 0) {
|
|
625
|
+
// All skipped during a reconfigure — preserve what was already set.
|
|
626
|
+
config.vaultMind.folders = existingFolders;
|
|
627
|
+
}
|
|
555
628
|
config.vaultMind.graph = config.vaultMind.graph || { enabled: true, canvasSync: true };
|
|
556
629
|
config.vaultMind.ftsEnabled = config.vaultMind.ftsEnabled !== false;
|
|
557
630
|
// Extension-compatibility (pi-context) now lives in the single consolidated
|
package/dist/src/types.js
CHANGED
|
@@ -182,6 +182,11 @@ describe("/vm setup collection scaffolding (regression)", () => {
|
|
|
182
182
|
assert.equal(cfg.vaultMind?.embedding?.remoteUrl, "https://example.test");
|
|
183
183
|
assert.equal(cfg.vaultMind?.embedding?.model, "embeddinggemma");
|
|
184
184
|
assert.ok(cfg.vaultMind?.vaults?.default?.path, "vaults.default.path should be written");
|
|
185
|
+
// Regression: headless setup used to invent an "Agent/Inbox" etc.
|
|
186
|
+
// folders block on a fresh vault. Guessing a folder convention that
|
|
187
|
+
// doesn't match the vault's actual structure silently misfiles
|
|
188
|
+
// content — folders must stay unset until deliberately configured.
|
|
189
|
+
assert.equal(cfg.vaultMind?.folders, undefined, "fresh headless setup should not invent a folders block");
|
|
185
190
|
fs.rmSync(vault, { recursive: true, force: true });
|
|
186
191
|
});
|
|
187
192
|
it("preserves an explicit empty injector array during subsequent setup runs", async () => {
|
package/dist/test/utils.test.js
CHANGED
|
@@ -374,7 +374,7 @@ describe("loadConfig", () => {
|
|
|
374
374
|
assert.equal(cfg.version, 2);
|
|
375
375
|
// mergeConfigLayer overwrites collections with resolved (empty) when no layer provides them
|
|
376
376
|
assert.deepEqual(cfg.collections, {});
|
|
377
|
-
assert.equal(cfg.vaultMind.dataDir, ".lancedb");
|
|
377
|
+
assert.equal(cfg.vaultMind.dataDir, ".vault-mind/.lancedb");
|
|
378
378
|
assert.equal(cfg.vaultMind.embedding.localUrl, "http://127.0.0.1:11434");
|
|
379
379
|
});
|
|
380
380
|
it("merges user config over defaults", () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-vault-mind",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.28",
|
|
4
4
|
"description": "Passive Obsidian vault extension for pi. Watches @agent markers, dispatches forked subagents (Miner, Broadcaster, Heavy-Lifter), stores in LanceDB with vector + FTS + graph. Multi-agent 'Drop & Forget' workflow for the pi agent ecosystem.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/scripts/vault-pi.sh
CHANGED
|
@@ -49,7 +49,7 @@ PI_CMD="PI_CODING_AGENT_DIR='${PI_DIR}' pi ${OP_ENV_ARG}; rm -f '${PID_FILE}'"
|
|
|
49
49
|
|
|
50
50
|
if [ -d "/Applications/iTerm.app" ]; then
|
|
51
51
|
open -a iTerm --args --detach bash -c "echo \$\$ > '${PID_FILE}'; cd '${VAULT}'; ${PI_CMD}"
|
|
52
|
-
elif [ -d "/Applications/Utilities/Terminal.app" ]; then
|
|
52
|
+
elif [ -d "/Applications/Utilities/Terminal.app" ] || [ -d "/System/Applications/Utilities/Terminal.app" ]; then
|
|
53
53
|
osascript -e "tell application \"Terminal\" to do script \"echo \$\$ > '${PID_FILE}'; cd '${VAULT}'; ${PI_CMD}\""
|
|
54
54
|
else
|
|
55
55
|
echo "[vault-pi] No supported terminal found (iTerm or Terminal.app)"
|