@fleetagent/pi-coding-agent 0.0.5 → 0.0.7

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 (201) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +28 -5
  3. package/dist/cli/args.d.ts +2 -0
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +9 -0
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/file-processor.d.ts.map +1 -1
  8. package/dist/cli/file-processor.js +2 -3
  9. package/dist/cli/file-processor.js.map +1 -1
  10. package/dist/config.d.ts.map +1 -1
  11. package/dist/config.js +15 -2
  12. package/dist/config.js.map +1 -1
  13. package/dist/core/agent-session.d.ts +13 -3
  14. package/dist/core/agent-session.d.ts.map +1 -1
  15. package/dist/core/agent-session.js +130 -23
  16. package/dist/core/agent-session.js.map +1 -1
  17. package/dist/core/diagnostics.d.ts +1 -1
  18. package/dist/core/diagnostics.d.ts.map +1 -1
  19. package/dist/core/diagnostics.js.map +1 -1
  20. package/dist/core/export-html/template.js +6 -3
  21. package/dist/core/extensions/runner.d.ts +5 -1
  22. package/dist/core/extensions/runner.d.ts.map +1 -1
  23. package/dist/core/extensions/runner.js +13 -3
  24. package/dist/core/extensions/runner.js.map +1 -1
  25. package/dist/core/extensions/types.d.ts +6 -3
  26. package/dist/core/extensions/types.d.ts.map +1 -1
  27. package/dist/core/extensions/types.js.map +1 -1
  28. package/dist/core/model-registry.d.ts.map +1 -1
  29. package/dist/core/model-registry.js +65 -13
  30. package/dist/core/model-registry.js.map +1 -1
  31. package/dist/core/output-guard.d.ts +1 -0
  32. package/dist/core/output-guard.d.ts.map +1 -1
  33. package/dist/core/output-guard.js +52 -22
  34. package/dist/core/output-guard.js.map +1 -1
  35. package/dist/core/package-manager.d.ts +1 -0
  36. package/dist/core/package-manager.d.ts.map +1 -1
  37. package/dist/core/package-manager.js +161 -24
  38. package/dist/core/package-manager.js.map +1 -1
  39. package/dist/core/pi-agent.d.ts.map +1 -1
  40. package/dist/core/pi-agent.js +12 -3
  41. package/dist/core/pi-agent.js.map +1 -1
  42. package/dist/core/resolve-config-value.d.ts +9 -1
  43. package/dist/core/resolve-config-value.d.ts.map +1 -1
  44. package/dist/core/resolve-config-value.js +134 -11
  45. package/dist/core/resolve-config-value.js.map +1 -1
  46. package/dist/core/resource-loader.d.ts +30 -0
  47. package/dist/core/resource-loader.d.ts.map +1 -1
  48. package/dist/core/resource-loader.js +94 -0
  49. package/dist/core/resource-loader.js.map +1 -1
  50. package/dist/core/rules.d.ts +57 -0
  51. package/dist/core/rules.d.ts.map +1 -0
  52. package/dist/core/rules.js +384 -0
  53. package/dist/core/rules.js.map +1 -0
  54. package/dist/core/session/jsonl-helpers.d.ts +2 -1
  55. package/dist/core/session/jsonl-helpers.d.ts.map +1 -1
  56. package/dist/core/session/jsonl-helpers.js +6 -3
  57. package/dist/core/session/jsonl-helpers.js.map +1 -1
  58. package/dist/core/session/local-session-manager.d.ts +1 -0
  59. package/dist/core/session/local-session-manager.d.ts.map +1 -1
  60. package/dist/core/session/local-session-manager.js +12 -4
  61. package/dist/core/session/local-session-manager.js.map +1 -1
  62. package/dist/core/session/session-manager.d.ts +1 -0
  63. package/dist/core/session/session-manager.d.ts.map +1 -1
  64. package/dist/core/session/session-manager.js.map +1 -1
  65. package/dist/core/session/stores/jsonl-session-store.d.ts +2 -1
  66. package/dist/core/session/stores/jsonl-session-store.d.ts.map +1 -1
  67. package/dist/core/session/stores/jsonl-session-store.js +105 -78
  68. package/dist/core/session/stores/jsonl-session-store.js.map +1 -1
  69. package/dist/core/settings-manager.d.ts +7 -0
  70. package/dist/core/settings-manager.d.ts.map +1 -1
  71. package/dist/core/settings-manager.js +28 -9
  72. package/dist/core/settings-manager.js.map +1 -1
  73. package/dist/core/slash-commands.d.ts +1 -1
  74. package/dist/core/slash-commands.d.ts.map +1 -1
  75. package/dist/core/slash-commands.js +1 -1
  76. package/dist/core/slash-commands.js.map +1 -1
  77. package/dist/core/system-prompt.d.ts +3 -0
  78. package/dist/core/system-prompt.d.ts.map +1 -1
  79. package/dist/core/system-prompt.js +11 -3
  80. package/dist/core/system-prompt.js.map +1 -1
  81. package/dist/core/tools/bash.d.ts.map +1 -1
  82. package/dist/core/tools/bash.js +73 -63
  83. package/dist/core/tools/bash.js.map +1 -1
  84. package/dist/core/tools/edit.d.ts.map +1 -1
  85. package/dist/core/tools/edit.js +45 -76
  86. package/dist/core/tools/edit.js.map +1 -1
  87. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  88. package/dist/core/tools/file-mutation-queue.js +27 -12
  89. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  90. package/dist/core/tools/find.d.ts.map +1 -1
  91. package/dist/core/tools/find.js +11 -2
  92. package/dist/core/tools/find.js.map +1 -1
  93. package/dist/core/tools/grep.d.ts.map +1 -1
  94. package/dist/core/tools/grep.js +3 -3
  95. package/dist/core/tools/grep.js.map +1 -1
  96. package/dist/core/tools/ls.d.ts.map +1 -1
  97. package/dist/core/tools/ls.js +13 -4
  98. package/dist/core/tools/ls.js.map +1 -1
  99. package/dist/core/tools/path-utils.d.ts +1 -0
  100. package/dist/core/tools/path-utils.d.ts.map +1 -1
  101. package/dist/core/tools/path-utils.js +37 -0
  102. package/dist/core/tools/path-utils.js.map +1 -1
  103. package/dist/core/tools/read.d.ts.map +1 -1
  104. package/dist/core/tools/read.js +13 -8
  105. package/dist/core/tools/read.js.map +1 -1
  106. package/dist/core/tools/write.d.ts.map +1 -1
  107. package/dist/core/tools/write.js +24 -32
  108. package/dist/core/tools/write.js.map +1 -1
  109. package/dist/index.d.ts +1 -0
  110. package/dist/index.d.ts.map +1 -1
  111. package/dist/index.js +2 -0
  112. package/dist/index.js.map +1 -1
  113. package/dist/main.d.ts.map +1 -1
  114. package/dist/main.js +6 -2
  115. package/dist/main.js.map +1 -1
  116. package/dist/migrations.d.ts.map +1 -1
  117. package/dist/migrations.js +118 -1
  118. package/dist/migrations.js.map +1 -1
  119. package/dist/modes/interactive/components/config-selector.d.ts +1 -1
  120. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  121. package/dist/modes/interactive/components/config-selector.js +12 -3
  122. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  123. package/dist/modes/interactive/components/footer.d.ts +1 -0
  124. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  125. package/dist/modes/interactive/components/footer.js +14 -5
  126. package/dist/modes/interactive/components/footer.js.map +1 -1
  127. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  128. package/dist/modes/interactive/components/settings-selector.js +1 -1
  129. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  130. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  131. package/dist/modes/interactive/components/user-message.js +1 -1
  132. package/dist/modes/interactive/components/user-message.js.map +1 -1
  133. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  134. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  135. package/dist/modes/interactive/interactive-mode.js +64 -9
  136. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  137. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  138. package/dist/modes/interactive/theme/theme.js +10 -0
  139. package/dist/modes/interactive/theme/theme.js.map +1 -1
  140. package/dist/modes/rpc/rpc-client.d.ts +5 -0
  141. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  142. package/dist/modes/rpc/rpc-client.js +91 -18
  143. package/dist/modes/rpc/rpc-client.js.map +1 -1
  144. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  145. package/dist/modes/rpc/rpc-mode.js +23 -3
  146. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  147. package/dist/modes/rpc/rpc-types.d.ts +1 -1
  148. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  149. package/dist/modes/rpc/rpc-types.js.map +1 -1
  150. package/dist/utils/clipboard-native.d.ts +3 -1
  151. package/dist/utils/clipboard-native.d.ts.map +1 -1
  152. package/dist/utils/clipboard-native.js +14 -8
  153. package/dist/utils/clipboard-native.js.map +1 -1
  154. package/dist/utils/deprecation.d.ts +4 -0
  155. package/dist/utils/deprecation.d.ts.map +1 -0
  156. package/dist/utils/deprecation.js +13 -0
  157. package/dist/utils/deprecation.js.map +1 -0
  158. package/dist/utils/image-resize-core.d.ts +30 -0
  159. package/dist/utils/image-resize-core.d.ts.map +1 -0
  160. package/dist/utils/image-resize-core.js +124 -0
  161. package/dist/utils/image-resize-core.js.map +1 -0
  162. package/dist/utils/image-resize-worker.d.ts +2 -0
  163. package/dist/utils/image-resize-worker.d.ts.map +1 -0
  164. package/dist/utils/image-resize-worker.js +31 -0
  165. package/dist/utils/image-resize-worker.js.map +1 -0
  166. package/dist/utils/image-resize.d.ts +6 -27
  167. package/dist/utils/image-resize.d.ts.map +1 -1
  168. package/dist/utils/image-resize.js +60 -116
  169. package/dist/utils/image-resize.js.map +1 -1
  170. package/dist/utils/json.d.ts +3 -0
  171. package/dist/utils/json.d.ts.map +1 -0
  172. package/dist/utils/json.js +7 -0
  173. package/dist/utils/json.js.map +1 -0
  174. package/docs/custom-provider.md +22 -9
  175. package/docs/extensions.md +13 -11
  176. package/docs/index.md +3 -2
  177. package/docs/models.md +34 -12
  178. package/docs/packages.md +11 -8
  179. package/docs/providers.md +13 -5
  180. package/docs/quickstart.md +1 -1
  181. package/docs/rpc.md +4 -2
  182. package/docs/rules.md +102 -0
  183. package/docs/sdk.md +57 -1
  184. package/docs/settings.md +6 -3
  185. package/docs/terminal-setup.md +6 -0
  186. package/docs/usage.md +6 -4
  187. package/examples/extensions/README.md +2 -1
  188. package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
  189. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  190. package/examples/extensions/custom-provider-gitlab-duo/index.ts +54 -3
  191. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  192. package/examples/extensions/dynamic-resources/RULES.md +8 -0
  193. package/examples/extensions/dynamic-resources/index.ts +1 -0
  194. package/examples/extensions/git-merge-and-resolve.ts +115 -0
  195. package/examples/extensions/reload-runtime.ts +2 -2
  196. package/examples/extensions/sandbox/package.json +1 -1
  197. package/examples/extensions/with-deps/package.json +1 -1
  198. package/examples/sdk/12-full-control.ts +1 -0
  199. package/examples/sdk/README.md +1 -1
  200. package/npm-shrinkwrap.json +13 -12
  201. package/package.json +5 -5
@@ -56,10 +56,11 @@ function resourcePrecedenceRank(m) {
56
56
  const scopeBase = m.scope === "project" ? 0 : 2;
57
57
  return scopeBase + (m.source === "local" ? 0 : 1);
58
58
  }
59
- const RESOURCE_TYPES = ["extensions", "skills", "prompts", "themes"];
59
+ const RESOURCE_TYPES = ["extensions", "skills", "rules", "prompts", "themes"];
60
60
  const FILE_PATTERNS = {
61
61
  extensions: /\.(ts|js)$/,
62
62
  skills: /\.md$/,
63
+ rules: /\.md$/,
63
64
  prompts: /\.md$/,
64
65
  themes: /\.json$/,
65
66
  };
@@ -244,6 +245,72 @@ function collectSkillEntries(dir, mode, ignoreMatcher, rootDir) {
244
245
  function collectAutoSkillEntries(dir, mode) {
245
246
  return collectSkillEntries(dir, mode);
246
247
  }
248
+ function collectRuleEntries(dir, mode, ignoreMatcher, rootDir) {
249
+ const entries = [];
250
+ if (!existsSync(dir))
251
+ return entries;
252
+ const root = rootDir ?? dir;
253
+ const ig = ignoreMatcher ?? ignore();
254
+ addIgnoreRules(ig, dir, root);
255
+ try {
256
+ const dirEntries = readdirSync(dir, { withFileTypes: true });
257
+ for (const entry of dirEntries) {
258
+ if (entry.name !== "RULES.md")
259
+ continue;
260
+ const fullPath = join(dir, entry.name);
261
+ let isFile = entry.isFile();
262
+ if (entry.isSymbolicLink()) {
263
+ try {
264
+ isFile = statSync(fullPath).isFile();
265
+ }
266
+ catch {
267
+ continue;
268
+ }
269
+ }
270
+ const relPath = toPosixPath(relative(root, fullPath));
271
+ if (isFile && !ig.ignores(relPath)) {
272
+ entries.push(fullPath);
273
+ return entries;
274
+ }
275
+ }
276
+ for (const entry of dirEntries) {
277
+ if (entry.name.startsWith("."))
278
+ continue;
279
+ if (entry.name === "node_modules")
280
+ continue;
281
+ const fullPath = join(dir, entry.name);
282
+ let isDir = entry.isDirectory();
283
+ let isFile = entry.isFile();
284
+ if (entry.isSymbolicLink()) {
285
+ try {
286
+ const stats = statSync(fullPath);
287
+ isDir = stats.isDirectory();
288
+ isFile = stats.isFile();
289
+ }
290
+ catch {
291
+ continue;
292
+ }
293
+ }
294
+ const relPath = toPosixPath(relative(root, fullPath));
295
+ if (mode === "pi" && dir === root && isFile && entry.name.endsWith(".md") && !ig.ignores(relPath)) {
296
+ entries.push(fullPath);
297
+ continue;
298
+ }
299
+ if (!isDir)
300
+ continue;
301
+ if (ig.ignores(`${relPath}/`))
302
+ continue;
303
+ entries.push(...collectRuleEntries(fullPath, mode, ig, root));
304
+ }
305
+ }
306
+ catch {
307
+ // Ignore errors
308
+ }
309
+ return entries;
310
+ }
311
+ function collectAutoRuleEntries(dir, mode) {
312
+ return collectRuleEntries(dir, mode);
313
+ }
247
314
  function findGitRepoRoot(startDir) {
248
315
  let dir = resolve(startDir);
249
316
  while (true) {
@@ -275,6 +342,24 @@ function collectAncestorAgentsSkillDirs(startDir) {
275
342
  }
276
343
  return skillDirs;
277
344
  }
345
+ function collectAncestorAgentsRuleDirs(startDir) {
346
+ const ruleDirs = [];
347
+ const resolvedStartDir = resolve(startDir);
348
+ const gitRepoRoot = findGitRepoRoot(resolvedStartDir);
349
+ let dir = resolvedStartDir;
350
+ while (true) {
351
+ ruleDirs.push(join(dir, ".agents", "rules"));
352
+ if (gitRepoRoot && dir === gitRepoRoot) {
353
+ break;
354
+ }
355
+ const parent = dirname(dir);
356
+ if (parent === dir) {
357
+ break;
358
+ }
359
+ dir = parent;
360
+ }
361
+ return ruleDirs;
362
+ }
278
363
  function collectAutoPromptEntries(dir) {
279
364
  const entries = [];
280
365
  if (!existsSync(dir))
@@ -444,6 +529,9 @@ function collectResourceFiles(dir, resourceType) {
444
529
  if (resourceType === "skills") {
445
530
  return collectSkillEntries(dir, "pi");
446
531
  }
532
+ if (resourceType === "rules") {
533
+ return collectRuleEntries(dir, "pi");
534
+ }
447
535
  if (resourceType === "extensions") {
448
536
  return collectAutoExtensionEntries(dir);
449
537
  }
@@ -453,11 +541,11 @@ function matchesAnyPattern(filePath, patterns, baseDir) {
453
541
  const rel = toPosixPath(relative(baseDir, filePath));
454
542
  const name = basename(filePath);
455
543
  const filePathPosix = toPosixPath(filePath);
456
- const isSkillFile = name === "SKILL.md";
457
- const parentDir = isSkillFile ? dirname(filePath) : undefined;
458
- const parentRel = isSkillFile ? toPosixPath(relative(baseDir, parentDir)) : undefined;
459
- const parentName = isSkillFile ? basename(parentDir) : undefined;
460
- const parentDirPosix = isSkillFile ? toPosixPath(parentDir) : undefined;
544
+ const isDirectoryResourceFile = name === "SKILL.md" || name === "RULES.md";
545
+ const parentDir = isDirectoryResourceFile ? dirname(filePath) : undefined;
546
+ const parentRel = isDirectoryResourceFile ? toPosixPath(relative(baseDir, parentDir)) : undefined;
547
+ const parentName = isDirectoryResourceFile ? basename(parentDir) : undefined;
548
+ const parentDirPosix = isDirectoryResourceFile ? toPosixPath(parentDir) : undefined;
461
549
  return patterns.some((pattern) => {
462
550
  const normalizedPattern = toPosixPath(pattern);
463
551
  if (minimatch(rel, normalizedPattern) ||
@@ -465,7 +553,7 @@ function matchesAnyPattern(filePath, patterns, baseDir) {
465
553
  minimatch(filePathPosix, normalizedPattern)) {
466
554
  return true;
467
555
  }
468
- if (!isSkillFile)
556
+ if (!isDirectoryResourceFile)
469
557
  return false;
470
558
  return (minimatch(parentRel, normalizedPattern) ||
471
559
  minimatch(parentName, normalizedPattern) ||
@@ -482,16 +570,16 @@ function matchesAnyExactPattern(filePath, patterns, baseDir) {
482
570
  const rel = toPosixPath(relative(baseDir, filePath));
483
571
  const name = basename(filePath);
484
572
  const filePathPosix = toPosixPath(filePath);
485
- const isSkillFile = name === "SKILL.md";
486
- const parentDir = isSkillFile ? dirname(filePath) : undefined;
487
- const parentRel = isSkillFile ? toPosixPath(relative(baseDir, parentDir)) : undefined;
488
- const parentDirPosix = isSkillFile ? toPosixPath(parentDir) : undefined;
573
+ const isDirectoryResourceFile = name === "SKILL.md" || name === "RULES.md";
574
+ const parentDir = isDirectoryResourceFile ? dirname(filePath) : undefined;
575
+ const parentRel = isDirectoryResourceFile ? toPosixPath(relative(baseDir, parentDir)) : undefined;
576
+ const parentDirPosix = isDirectoryResourceFile ? toPosixPath(parentDir) : undefined;
489
577
  return patterns.some((pattern) => {
490
578
  const normalized = normalizeExactPattern(pattern);
491
579
  if (normalized === rel || normalized === filePathPosix) {
492
580
  return true;
493
581
  }
494
- if (!isSkillFile)
582
+ if (!isDirectoryResourceFile)
495
583
  return false;
496
584
  return normalized === parentRel || normalized === parentDirPosix;
497
585
  });
@@ -814,14 +902,16 @@ export class DefaultPackageManager {
814
902
  const gitCandidates = [];
815
903
  for (const entry of sources) {
816
904
  const parsed = this.parseSource(entry.source);
817
- if (parsed.type === "local" || parsed.pinned) {
818
- continue;
819
- }
905
+ // Pinned npm versions are fixed. Pinned git refs are configured checkout targets,
906
+ // so include them to reconcile an existing clone when the configured ref changes.
820
907
  if (parsed.type === "npm") {
821
- npmCandidates.push({ ...entry, parsed });
822
- continue;
908
+ if (!parsed.pinned) {
909
+ npmCandidates.push({ ...entry, parsed });
910
+ }
911
+ }
912
+ else if (parsed.type === "git") {
913
+ gitCandidates.push({ ...entry, parsed });
823
914
  }
824
- gitCandidates.push({ ...entry, parsed });
825
915
  }
826
916
  const npmCheckTasks = npmCandidates.map((entry) => async () => ({
827
917
  entry,
@@ -1396,13 +1486,25 @@ export class DefaultPackageManager {
1396
1486
  }
1397
1487
  getNpmInstallArgs(specs, installRoot) {
1398
1488
  const packageManagerName = this.getPackageManagerName();
1489
+ // Extension packages run inside pi and resolve pi APIs through loader aliases/virtual modules.
1490
+ // Disable peer dependency resolution for managed installs (npm's --legacy-peer-deps, and
1491
+ // equivalent bun/pnpm settings) so package managers do not install or solve host-provided
1492
+ // @earendil-works/pi-* peers. Stale auto-installed pi peers can otherwise block updates.
1399
1493
  if (packageManagerName === "bun") {
1400
- return ["install", ...specs, "--cwd", installRoot];
1494
+ return ["install", ...specs, "--cwd", installRoot, "--omit=peer"];
1401
1495
  }
1402
1496
  if (packageManagerName === "pnpm") {
1403
- return ["install", ...specs, "--prefix", installRoot, "--config.strict-dep-builds=false"];
1404
- }
1405
- return ["install", ...specs, "--prefix", installRoot];
1497
+ return [
1498
+ "install",
1499
+ ...specs,
1500
+ "--prefix",
1501
+ installRoot,
1502
+ "--config.auto-install-peers=false",
1503
+ "--config.strict-peer-dependencies=false",
1504
+ "--config.strict-dep-builds=false",
1505
+ ];
1506
+ }
1507
+ return ["install", ...specs, "--prefix", installRoot, "--legacy-peer-deps"];
1406
1508
  }
1407
1509
  async installNpm(source, scope, temporary) {
1408
1510
  const installRoot = this.getNpmInstallRoot(scope, temporary);
@@ -1451,6 +1553,10 @@ export class DefaultPackageManager {
1451
1553
  await this.installGit(source, scope);
1452
1554
  return;
1453
1555
  }
1556
+ if (source.ref) {
1557
+ await this.ensureGitRef(targetDir, ["fetch", "origin", source.ref], "FETCH_HEAD");
1558
+ return;
1559
+ }
1454
1560
  const target = await this.getLocalGitUpdateTarget(targetDir);
1455
1561
  await this.ensureGitRef(targetDir, target.fetchArgs, target.ref);
1456
1562
  }
@@ -1461,14 +1567,15 @@ export class DefaultPackageManager {
1461
1567
  cwd: targetDir,
1462
1568
  timeoutMs: NETWORK_TIMEOUT_MS,
1463
1569
  });
1464
- const targetHead = await this.runCommandCapture("git", ["rev-parse", ref], {
1570
+ const commitRef = `${ref}^{commit}`;
1571
+ const targetHead = await this.runCommandCapture("git", ["rev-parse", commitRef], {
1465
1572
  cwd: targetDir,
1466
1573
  timeoutMs: NETWORK_TIMEOUT_MS,
1467
1574
  });
1468
1575
  if (localHead.trim() === targetHead.trim()) {
1469
1576
  return;
1470
1577
  }
1471
- await this.runCommand("git", ["reset", "--hard", ref], { cwd: targetDir });
1578
+ await this.runCommand("git", ["reset", "--hard", commitRef], { cwd: targetDir });
1472
1579
  // Clean untracked files (extensions should be pristine)
1473
1580
  await this.runCommand("git", ["clean", "-fdx"], { cwd: targetDir });
1474
1581
  const packageJsonPath = join(targetDir, "package.json");
@@ -1803,29 +1910,35 @@ export class DefaultPackageManager {
1803
1910
  const userOverrides = {
1804
1911
  extensions: (globalSettings.extensions ?? []),
1805
1912
  skills: (globalSettings.skills ?? []),
1913
+ rules: (globalSettings.rules ?? []),
1806
1914
  prompts: (globalSettings.prompts ?? []),
1807
1915
  themes: (globalSettings.themes ?? []),
1808
1916
  };
1809
1917
  const projectOverrides = {
1810
1918
  extensions: (projectSettings.extensions ?? []),
1811
1919
  skills: (projectSettings.skills ?? []),
1920
+ rules: (projectSettings.rules ?? []),
1812
1921
  prompts: (projectSettings.prompts ?? []),
1813
1922
  themes: (projectSettings.themes ?? []),
1814
1923
  };
1815
1924
  const userDirs = {
1816
1925
  extensions: join(globalBaseDir, "extensions"),
1817
1926
  skills: join(globalBaseDir, "skills"),
1927
+ rules: join(globalBaseDir, "rules"),
1818
1928
  prompts: join(globalBaseDir, "prompts"),
1819
1929
  themes: join(globalBaseDir, "themes"),
1820
1930
  };
1821
1931
  const projectDirs = {
1822
1932
  extensions: join(projectBaseDir, "extensions"),
1823
1933
  skills: join(projectBaseDir, "skills"),
1934
+ rules: join(projectBaseDir, "rules"),
1824
1935
  prompts: join(projectBaseDir, "prompts"),
1825
1936
  themes: join(projectBaseDir, "themes"),
1826
1937
  };
1827
1938
  const userAgentsSkillsDir = join(getHomeDir(), ".agents", "skills");
1939
+ const userAgentsRulesDir = join(getHomeDir(), ".agents", "rules");
1828
1940
  const projectAgentsSkillDirs = collectAncestorAgentsSkillDirs(this.cwd).filter((dir) => resolve(dir) !== resolve(userAgentsSkillsDir));
1941
+ const projectAgentsRuleDirs = collectAncestorAgentsRuleDirs(this.cwd).filter((dir) => resolve(dir) !== resolve(userAgentsRulesDir));
1829
1942
  const addResources = (resourceType, paths, metadata, overrides, baseDir) => {
1830
1943
  const target = this.getTargetMap(accumulator, resourceType);
1831
1944
  for (const path of paths) {
@@ -1837,6 +1950,8 @@ export class DefaultPackageManager {
1837
1950
  addResources("extensions", collectAutoExtensionEntries(projectDirs.extensions), projectMetadata, projectOverrides.extensions, projectBaseDir);
1838
1951
  // Project skills from .pi/
1839
1952
  addResources("skills", collectAutoSkillEntries(projectDirs.skills, "pi"), projectMetadata, projectOverrides.skills, projectBaseDir);
1953
+ // Project rules from .pi/
1954
+ addResources("rules", collectAutoRuleEntries(projectDirs.rules, "pi"), projectMetadata, projectOverrides.rules, projectBaseDir);
1840
1955
  // Project skills from .agents/ (each with its own baseDir)
1841
1956
  for (const agentsSkillsDir of projectAgentsSkillDirs) {
1842
1957
  const agentsBaseDir = dirname(agentsSkillsDir); // the .agents directory
@@ -1846,12 +1961,23 @@ export class DefaultPackageManager {
1846
1961
  };
1847
1962
  addResources("skills", collectAutoSkillEntries(agentsSkillsDir, "agents"), agentsMetadata, projectOverrides.skills, agentsBaseDir);
1848
1963
  }
1964
+ // Project rules from .agents/ (each with its own baseDir)
1965
+ for (const agentsRulesDir of projectAgentsRuleDirs) {
1966
+ const agentsBaseDir = dirname(agentsRulesDir); // the .agents directory
1967
+ const agentsMetadata = {
1968
+ ...projectMetadata,
1969
+ baseDir: agentsBaseDir,
1970
+ };
1971
+ addResources("rules", collectAutoRuleEntries(agentsRulesDir, "agents"), agentsMetadata, projectOverrides.rules, agentsBaseDir);
1972
+ }
1849
1973
  addResources("prompts", collectAutoPromptEntries(projectDirs.prompts), projectMetadata, projectOverrides.prompts, projectBaseDir);
1850
1974
  addResources("themes", collectAutoThemeEntries(projectDirs.themes), projectMetadata, projectOverrides.themes, projectBaseDir);
1851
1975
  // User extensions from ~/.pi/agent/
1852
1976
  addResources("extensions", collectAutoExtensionEntries(userDirs.extensions), userMetadata, userOverrides.extensions, globalBaseDir);
1853
1977
  // User skills from ~/.pi/agent/
1854
1978
  addResources("skills", collectAutoSkillEntries(userDirs.skills, "pi"), userMetadata, userOverrides.skills, globalBaseDir);
1979
+ // User rules from ~/.pi/agent/
1980
+ addResources("rules", collectAutoRuleEntries(userDirs.rules, "pi"), userMetadata, userOverrides.rules, globalBaseDir);
1855
1981
  // User skills from ~/.agents/ (with its own baseDir)
1856
1982
  const userAgentsBaseDir = dirname(userAgentsSkillsDir);
1857
1983
  const userAgentsMetadata = {
@@ -1859,6 +1985,13 @@ export class DefaultPackageManager {
1859
1985
  baseDir: userAgentsBaseDir,
1860
1986
  };
1861
1987
  addResources("skills", collectAutoSkillEntries(userAgentsSkillsDir, "agents"), userAgentsMetadata, userOverrides.skills, userAgentsBaseDir);
1988
+ // User rules from ~/.agents/ (with its own baseDir)
1989
+ const userAgentsRulesBaseDir = dirname(userAgentsRulesDir);
1990
+ const userAgentsRulesMetadata = {
1991
+ ...userMetadata,
1992
+ baseDir: userAgentsRulesBaseDir,
1993
+ };
1994
+ addResources("rules", collectAutoRuleEntries(userAgentsRulesDir, "agents"), userAgentsRulesMetadata, userOverrides.rules, userAgentsRulesBaseDir);
1862
1995
  addResources("prompts", collectAutoPromptEntries(userDirs.prompts), userMetadata, userOverrides.prompts, globalBaseDir);
1863
1996
  addResources("themes", collectAutoThemeEntries(userDirs.themes), userMetadata, userOverrides.themes, globalBaseDir);
1864
1997
  }
@@ -1888,6 +2021,8 @@ export class DefaultPackageManager {
1888
2021
  return accumulator.extensions;
1889
2022
  case "skills":
1890
2023
  return accumulator.skills;
2024
+ case "rules":
2025
+ return accumulator.rules;
1891
2026
  case "prompts":
1892
2027
  return accumulator.prompts;
1893
2028
  case "themes":
@@ -1907,6 +2042,7 @@ export class DefaultPackageManager {
1907
2042
  return {
1908
2043
  extensions: new Map(),
1909
2044
  skills: new Map(),
2045
+ rules: new Map(),
1910
2046
  prompts: new Map(),
1911
2047
  themes: new Map(),
1912
2048
  };
@@ -1931,6 +2067,7 @@ export class DefaultPackageManager {
1931
2067
  return {
1932
2068
  extensions: mapToResolved(accumulator.extensions),
1933
2069
  skills: mapToResolved(accumulator.skills),
2070
+ rules: mapToResolved(accumulator.rules),
1934
2071
  prompts: mapToResolved(accumulator.prompts),
1935
2072
  themes: mapToResolved(accumulator.themes),
1936
2073
  };