pi-lazy-extensions 0.1.2 → 0.1.4

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.
Files changed (3) hide show
  1. package/config.ts +4 -2
  2. package/index.ts +33 -9
  3. package/package.json +10 -9
package/config.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  import { existsSync, readFileSync } from "node:fs";
9
9
  import { homedir } from "node:os";
10
10
  import { dirname, isAbsolute, join, resolve } from "node:path";
11
+ import { CONFIG_DIR_NAME } from "@earendil-works/pi-coding-agent";
11
12
  import type { LazyExtensionConfig, LazyExtensionsManifest, LazyExtensionsState, LoadedExtensionState } from "./types.js";
12
13
 
13
14
  /**
@@ -26,8 +27,9 @@ export function loadManifest(cwd: string, agentDir: string): { manifest: LazyExt
26
27
  if (manifest) return { manifest, path: resolve(envPath) };
27
28
  }
28
29
 
29
- // Project .pi dir
30
- const projectPi = join(cwd, ".pi", "lazy-extensions.json");
30
+ // Project "dot-pi" dir (uses CONFIG_DIR_NAME so rebranded pi distributions
31
+ // use their configured config dir name instead of hardcoded .pi)
32
+ const projectPi = join(cwd, CONFIG_DIR_NAME, "lazy-extensions.json");
31
33
  if (existsSync(projectPi)) {
32
34
  const manifest = parseManifest(projectPi);
33
35
  if (manifest) return { manifest, path: projectPi };
package/index.ts CHANGED
@@ -27,24 +27,48 @@ export default function lazyExtensions(pi: ExtensionAPI) {
27
27
  let initPromise: Promise<void> | null = null;
28
28
  let lifecycleGeneration = 0;
29
29
 
30
- const getPiTools = (): ToolInfo[] => pi.getAllTools();
30
+ // pi >= 0.81.1 throws from action methods while the extension runtime is
31
+ // still uninitialized during extension loading, so degrade to an empty list.
32
+ const getPiTools = (): ToolInfo[] => {
33
+ try {
34
+ return pi.getAllTools();
35
+ } catch {
36
+ return [];
37
+ }
38
+ };
31
39
  const agentDir = getAgentDir();
32
40
 
33
41
  // Check for tool name collision before registering the proxy tool.
34
42
  // Pi uses "first registration wins" — if another extension already
35
43
  // registered a tool named "ext", our proxy would be silently skipped.
36
- const existingTools = pi.getAllTools();
37
- if (existingTools.some(t => t.name === "ext")) {
38
- console.error(
39
- "pi-lazy-extensions: another extension already registered a tool named 'ext'. " +
40
- "The proxy tool will not be available. Use the /ext command instead, " +
41
- "or remove the conflicting extension."
42
- );
43
- }
44
+ // The runtime may not be bound yet at factory time (pi >= 0.81.1), in which
45
+ // case the check is retried on session_start once the runtime is ready.
46
+ let collisionChecked = false;
47
+ const checkExtCollision = () => {
48
+ if (collisionChecked) return;
49
+ let existingTools: ToolInfo[];
50
+ try {
51
+ existingTools = pi.getAllTools();
52
+ } catch {
53
+ return;
54
+ }
55
+ collisionChecked = true;
56
+ if (existingTools.some(t => t.name === "ext")) {
57
+ console.error(
58
+ "pi-lazy-extensions: another extension already registered a tool named 'ext'. " +
59
+ "The proxy tool will not be available. Use the /ext command instead, " +
60
+ "or remove the conflicting extension."
61
+ );
62
+ }
63
+ };
64
+ checkExtCollision();
44
65
 
45
66
  pi.on("session_start", async (_event, ctx) => {
46
67
  const generation = ++lifecycleGeneration;
47
68
 
69
+ // Retry the collision check now that the extension runtime is bound.
70
+ checkExtCollision();
71
+
48
72
  // Clear previous state
49
73
  if (state) {
50
74
  clearAllTimers(state);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-lazy-extensions",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Lazy-load pi extensions on demand via a ToolSearch-style proxy tool",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,6 +34,13 @@
34
34
  "peerDependencies": {
35
35
  "@earendil-works/pi-coding-agent": ">=0.74.0"
36
36
  },
37
+ "scripts": {
38
+ "test": "vitest run",
39
+ "test:watch": "vitest",
40
+ "test:coverage": "vitest run --coverage",
41
+ "typecheck": "tsc --noEmit",
42
+ "lint:dead": "knip --no-gitignore"
43
+ },
37
44
  "devDependencies": {
38
45
  "@commitlint/cli": "21.0.1",
39
46
  "@commitlint/config-conventional": "21.0.1",
@@ -49,11 +56,5 @@
49
56
  "protobufjs": "8.4.0",
50
57
  "ws": "8.20.1"
51
58
  },
52
- "scripts": {
53
- "test": "vitest run",
54
- "test:watch": "vitest",
55
- "test:coverage": "vitest run --coverage",
56
- "typecheck": "tsc --noEmit",
57
- "lint:dead": "knip --no-gitignore"
58
- }
59
- }
59
+ "packageManager": "pnpm@11.20.0"
60
+ }