pi-local-agents-only 0.1.15 → 0.1.17

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 CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.1.17 - 2026-05-27
6
+
7
+ - updated the local pi development baseline to `@earendil-works/pi-coding-agent` `0.76.0` and regenerated the npm lockfile
8
+ - reviewed the pi `0.76.0` changelog and package guidance; the extension remains compatible with current system-prompt and package-loading behavior
9
+
10
+ ## 0.1.16 - 2026-05-23
11
+
12
+ - updated the local pi development baseline to `@earendil-works/pi-coding-agent` `0.75.5`, refreshed Node tooling, and regenerated the npm lockfile
13
+ - reviewed the pi `0.75.5` changelog and package guidance; the extension remains compatible with current system-prompt and package-loading behavior
14
+
5
15
  ## 0.1.15 - 2026-05-18
6
16
 
7
17
  - updated the local pi development baseline to `@earendil-works/pi-coding-agent` `0.75.3` and refreshed the npm lockfile
@@ -5,7 +5,7 @@
5
5
  * Responsibilities: Detect repo and worktree opt-in state, manage repo and global toggles, add a local-only guardrail, and remove matching global context blocks before model calls.
6
6
  * Scope: Works as a pi extension package. It changes only the prompt the model sees, not pi's startup header.
7
7
  * Usage: Install the package, then use `/local-agents-only on|off|status|global-on|global-off`.
8
- * Invariants/Assumptions: pi injects context files as `## /absolute/path\n\n<file contents>\n\n`; git worktrees that share a common git dir should share local-agents-only state.
8
+ * Invariants/Assumptions: pi injects context files as XML `<project_instructions path="...">` blocks in current releases and previously used Markdown `## /absolute/path` blocks; git worktrees that share a common git dir should share local-agents-only state.
9
9
  */
10
10
 
11
11
  import { execFileSync } from "node:child_process";
@@ -38,9 +38,13 @@ const GLOBAL_CONTEXT_FILES = ["AGENTS.md", "CLAUDE.md"];
38
38
  const ENV_TRUE = ["1", "true", "yes", "on"];
39
39
  const ENV_FALSE = ["0", "false", "no", "off"];
40
40
  const PROJECT_CONTEXT_HEADER = "\n\n# Project Context\n\nProject-specific instructions and guidelines:\n\n";
41
+ const PROJECT_CONTEXT_XML_START = "<project_context>";
42
+ const PROJECT_CONTEXT_XML_END = "</project_context>";
43
+ const PROJECT_CONTEXT_XML_PREFIX = "<project_context>\n\nProject-specific instructions and guidelines:\n\n";
41
44
  const SKILLS_HEADER = "\n\nThe following skills provide specialized instructions for specific tasks.";
42
45
  const DATE_HEADER = "\nCurrent date:";
43
46
  const CONTEXT_BLOCK_HEADER = /^## ([^\n]+(?:AGENTS|CLAUDE)\.md)\n\n/gm;
47
+ const CONTEXT_XML_BLOCK = /<project_instructions path="([^"]+(?:AGENTS|CLAUDE)\.md)">\n[\s\S]*?<\/project_instructions>\n*/g;
44
48
  const emptyConfig = () => ({ projects: [], repositories: [] });
45
49
 
46
50
  /** @returns {string} */
@@ -282,7 +286,55 @@ const getContextBlocks = (contextSection) => {
282
286
  * @param {string[]} [globalPaths]
283
287
  * @returns {StripResult}
284
288
  */
285
- const stripGlobalContext = (prompt, globalPaths = getGlobalContextPaths()) => {
289
+ const stripXmlGlobalContext = (prompt, globalPaths = getGlobalContextPaths()) => {
290
+ const contextTagStart = prompt.lastIndexOf(PROJECT_CONTEXT_XML_START);
291
+ if (contextTagStart === -1) {
292
+ return { prompt, removedPaths: [] };
293
+ }
294
+ const contextTagEnd = prompt.indexOf(PROJECT_CONTEXT_XML_END, contextTagStart);
295
+ if (contextTagEnd === -1) {
296
+ return { prompt, removedPaths: [] };
297
+ }
298
+ const sectionEnd = contextTagEnd + PROJECT_CONTEXT_XML_END.length;
299
+ const contextSection = prompt.slice(contextTagStart, sectionEnd);
300
+ const blocks = [...contextSection.matchAll(CONTEXT_XML_BLOCK)];
301
+ if (blocks.length === 0) {
302
+ return { prompt, removedPaths: [] };
303
+ }
304
+ const globalPathKeys = new Set(globalPaths.map(normalizePath));
305
+ /** @type {string[]} */
306
+ const keptBlocks = [];
307
+ /** @type {string[]} */
308
+ const removedPaths = [];
309
+ for (const block of blocks) {
310
+ const path = block[1];
311
+ const blockText = block[0];
312
+ if (globalPathKeys.has(normalizePath(path))) {
313
+ removedPaths.push(path);
314
+ } else {
315
+ keptBlocks.push(blockText.endsWith("\n\n") ? blockText : `${blockText}\n`);
316
+ }
317
+ }
318
+ if (removedPaths.length === 0) {
319
+ return { prompt, removedPaths: [] };
320
+ }
321
+ const prefix = prompt.slice(0, contextTagStart).replace(/\n\n$/u, "\n");
322
+ const suffix = prompt.slice(sectionEnd);
323
+ if (keptBlocks.length === 0) {
324
+ return { prompt: `${prefix}${suffix}`, removedPaths: uniqueSorted(removedPaths) };
325
+ }
326
+ return {
327
+ prompt: `${prefix}${PROJECT_CONTEXT_XML_PREFIX}${keptBlocks.join("\n")}${PROJECT_CONTEXT_XML_END}${suffix}`,
328
+ removedPaths: uniqueSorted(removedPaths),
329
+ };
330
+ };
331
+
332
+ /**
333
+ * @param {string} prompt
334
+ * @param {string[]} [globalPaths]
335
+ * @returns {StripResult}
336
+ */
337
+ const stripMarkdownGlobalContext = (prompt, globalPaths = getGlobalContextPaths()) => {
286
338
  const sectionStart = prompt.lastIndexOf(PROJECT_CONTEXT_HEADER);
287
339
  if (sectionStart === -1) {
288
340
  return { prompt, removedPaths: [] };
@@ -321,6 +373,16 @@ const stripGlobalContext = (prompt, globalPaths = getGlobalContextPaths()) => {
321
373
  };
322
374
  };
323
375
 
376
+ /**
377
+ * @param {string} prompt
378
+ * @param {string[]} [globalPaths]
379
+ * @returns {StripResult}
380
+ */
381
+ const stripGlobalContext = (prompt, globalPaths = getGlobalContextPaths()) => {
382
+ const xmlResult = stripXmlGlobalContext(prompt, globalPaths);
383
+ return xmlResult.removedPaths.length > 0 ? xmlResult : stripMarkdownGlobalContext(prompt, globalPaths);
384
+ };
385
+
324
386
  /**
325
387
  * @param {string} start
326
388
  * @returns {string | undefined}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-local-agents-only",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "Pi extension that strips global AGENTS.md and CLAUDE.md from the effective prompt for selected projects.",
5
5
  "author": "Mitch Fultz (https://github.com/fitchmultz)",
6
6
  "license": "MIT",
@@ -37,13 +37,13 @@
37
37
  "prepublishOnly": "npm run check"
38
38
  },
39
39
  "devDependencies": {
40
- "@earendil-works/pi-coding-agent": "^0.75.3",
41
- "@types/node": "^25.6.1",
40
+ "@earendil-works/pi-coding-agent": "^0.76.0",
41
+ "@types/node": "^25.9.1",
42
42
  "typescript": "^6.0.3"
43
43
  },
44
- "packageManager": "npm@11.14.0",
44
+ "packageManager": "npm@11.0.0",
45
45
  "engines": {
46
- "node": ">=22.19.0"
46
+ "node": ">=22 <25"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@earendil-works/pi-coding-agent": "*"