@henryqw/pi-add-dir 3.1.2 → 3.1.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/README.md +1 -1
- package/extensions/add-dir-config.ts +5 -34
- package/extensions/add-dir.ts +20 -29
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ Package-owned: `~/.pi/agent/config/pi-add-dir/config.json`
|
|
|
50
50
|
| --- | --- | --- | --- |
|
|
51
51
|
| `directories` | Directories loaded for every workspace. `/dir-add --global` updates this list. | Array of unique absolute paths without control characters. | `[]` |
|
|
52
52
|
|
|
53
|
-
If the file is missing, the extension uses the default.
|
|
53
|
+
If the file is missing, the extension uses the default. At launch, the extension shows a warning for each unknown key and each invalid or duplicate directory entry. It ignores that key or entry and loads the other directories. If the file is malformed or `directories` is not an array, it shows a warning and uses the default. It does not change the file. `/dir-add --global` and global removal with `/dir-ls` fail until you fix the reported issues. Reload Pi after you edit the file manually.
|
|
54
54
|
|
|
55
55
|
## State and storage
|
|
56
56
|
|
|
@@ -1,40 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createConfigStore } from "@henryqw/pi-config-store";
|
|
3
|
-
|
|
4
|
-
export interface AddDirConfig {
|
|
5
|
-
directories: string[];
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function parseConfig(value: unknown): AddDirConfig {
|
|
9
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
10
|
-
throw new Error("Invalid pi-add-dir config: expected an object.");
|
|
11
|
-
}
|
|
12
|
-
const config = value as Record<string, unknown>;
|
|
13
|
-
if (Object.keys(config).length !== 1 || !Array.isArray(config.directories)) {
|
|
14
|
-
throw new Error('Invalid pi-add-dir config: expected only a "directories" array.');
|
|
15
|
-
}
|
|
16
|
-
const directories = config.directories;
|
|
17
|
-
if (
|
|
18
|
-
directories.some(
|
|
19
|
-
(directory) =>
|
|
20
|
-
typeof directory !== "string" ||
|
|
21
|
-
!isAbsolute(directory) ||
|
|
22
|
-
/\p{C}/u.test(directory),
|
|
23
|
-
)
|
|
24
|
-
) {
|
|
25
|
-
throw new Error("Invalid pi-add-dir config: directories must be absolute paths without control characters.");
|
|
26
|
-
}
|
|
27
|
-
if (new Set(directories).size !== directories.length) {
|
|
28
|
-
throw new Error("Invalid pi-add-dir config: directories must be unique.");
|
|
29
|
-
}
|
|
30
|
-
return { directories: [...directories] };
|
|
31
|
-
}
|
|
1
|
+
import { createConfigStore, field, parsers } from "@henryqw/pi-config-store";
|
|
32
2
|
|
|
33
3
|
export function createAddDirConfigStore(agentDir?: string) {
|
|
34
|
-
return createConfigStore
|
|
4
|
+
return createConfigStore({
|
|
35
5
|
extensionId: "pi-add-dir",
|
|
36
6
|
agentDir,
|
|
37
|
-
|
|
38
|
-
|
|
7
|
+
fields: {
|
|
8
|
+
directories: field(parsers.array(parsers.absolutePath(), { unique: (directory) => directory }), []),
|
|
9
|
+
},
|
|
39
10
|
});
|
|
40
11
|
}
|
package/extensions/add-dir.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type AutocompleteSuggestions,
|
|
10
10
|
} from "@earendil-works/pi-tui";
|
|
11
11
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
12
|
+
import { registerConfigReporting } from "@henryqw/pi-config-store";
|
|
12
13
|
import { Type } from "typebox";
|
|
13
14
|
import {
|
|
14
15
|
buildContextInjection,
|
|
@@ -227,6 +228,9 @@ export function createExternalAutocompleteProvider(
|
|
|
227
228
|
|
|
228
229
|
export default function addDirExtension(pi: ExtensionAPI, options: ExtensionOptions = {}): void {
|
|
229
230
|
const globalStore = createAddDirConfigStore(options.agentDir);
|
|
231
|
+
const configReporter = registerConfigReporting(pi, [globalStore]);
|
|
232
|
+
// Report the latest file before a global write, so issues found after launch use the same deduplicated report.
|
|
233
|
+
const reportGlobalConfig = (ctx: ExtensionContext) => configReporter.report(ctx, globalStore, globalStore.loadSync());
|
|
230
234
|
let sessionDirs: SessionDir[] = [];
|
|
231
235
|
let projectPaths: string[] = [];
|
|
232
236
|
let globalPaths: string[] = [];
|
|
@@ -234,17 +238,10 @@ export default function addDirExtension(pi: ExtensionAPI, options: ExtensionOpti
|
|
|
234
238
|
let addedDirs: ScopedDir[] = [];
|
|
235
239
|
let currentCwd = "";
|
|
236
240
|
|
|
237
|
-
|
|
238
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
239
|
-
return new Error(`Cannot load pi-add-dir global config at ${globalStore.path}: ${message}`, { cause: error });
|
|
240
|
-
}
|
|
241
|
-
|
|
241
|
+
// No field disables this config, so a load always has a value; bad entries are dropped and reported at launch.
|
|
242
242
|
function loadGlobalPaths(): string[] {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
} catch (error) {
|
|
246
|
-
throw globalConfigError(error);
|
|
247
|
-
}
|
|
243
|
+
const loaded = globalStore.loadSync();
|
|
244
|
+
return loaded.status === "ok" ? loaded.value.directories : [];
|
|
248
245
|
}
|
|
249
246
|
|
|
250
247
|
function updateWidget(ctx: ExtensionContext): void {
|
|
@@ -391,17 +388,14 @@ export default function addDirExtension(pi: ExtensionAPI, options: ExtensionOpti
|
|
|
391
388
|
|
|
392
389
|
async function writePersistentPath(source: "project" | "global", absolutePath: string, ctx: ExtensionContext): Promise<void> {
|
|
393
390
|
if (source === "global") {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
} catch (error) {
|
|
403
|
-
throw globalConfigError(error);
|
|
404
|
-
}
|
|
391
|
+
reportGlobalConfig(ctx);
|
|
392
|
+
const config = await globalStore.update((current) => ({
|
|
393
|
+
directories: current.directories.includes(absolutePath)
|
|
394
|
+
? current.directories
|
|
395
|
+
: [...current.directories, absolutePath],
|
|
396
|
+
}));
|
|
397
|
+
globalPaths = config.directories;
|
|
398
|
+
return;
|
|
405
399
|
}
|
|
406
400
|
projectPaths = await readProjectPaths(ctx.cwd, true);
|
|
407
401
|
if (projectPaths.some((path) => resolveDir(path, ctx.cwd) === absolutePath)) return;
|
|
@@ -498,14 +492,11 @@ export default function addDirExtension(pi: ExtensionAPI, options: ExtensionOpti
|
|
|
498
492
|
);
|
|
499
493
|
persistState();
|
|
500
494
|
} else if (dir.source === "global") {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
} catch (error) {
|
|
507
|
-
throw globalConfigError(error);
|
|
508
|
-
}
|
|
495
|
+
reportGlobalConfig(ctx);
|
|
496
|
+
const config = await globalStore.update((current) => ({
|
|
497
|
+
directories: current.directories.filter((path) => path !== dir.storedPath),
|
|
498
|
+
}));
|
|
499
|
+
globalPaths = config.directories;
|
|
509
500
|
} else {
|
|
510
501
|
await mutateProjectConfig(
|
|
511
502
|
["--unset-all", "--fixed-value", PROJECT_CONFIG_KEY, dir.storedPath],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@henryqw/pi-add-dir",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.3",
|
|
4
4
|
"description": "Add external directories to a Pi session with context, skills, and file search.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"image": "https://raw.githubusercontent.com/HenryQW/pi-harness/main/extensions/pi-add-dir/example.png"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@henryqw/pi-config-store": "^
|
|
50
|
+
"@henryqw/pi-config-store": "^4.0.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@earendil-works/pi-coding-agent": "1.1.0",
|