@fleetagent/pi-coding-agent 0.0.10 → 0.0.11

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 (87) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/core/agent-session.d.ts +1 -0
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +16 -3
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/bash-executor.d.ts +2 -0
  7. package/dist/core/bash-executor.d.ts.map +1 -1
  8. package/dist/core/bash-executor.js +1 -0
  9. package/dist/core/bash-executor.js.map +1 -1
  10. package/dist/core/extensions/index.d.ts +1 -1
  11. package/dist/core/extensions/index.d.ts.map +1 -1
  12. package/dist/core/extensions/index.js.map +1 -1
  13. package/dist/core/extensions/loader.d.ts.map +1 -1
  14. package/dist/core/extensions/loader.js +86 -0
  15. package/dist/core/extensions/loader.js.map +1 -1
  16. package/dist/core/extensions/runner.d.ts +3 -0
  17. package/dist/core/extensions/runner.d.ts.map +1 -1
  18. package/dist/core/extensions/runner.js +27 -0
  19. package/dist/core/extensions/runner.js.map +1 -1
  20. package/dist/core/extensions/types.d.ts +55 -2
  21. package/dist/core/extensions/types.d.ts.map +1 -1
  22. package/dist/core/extensions/types.js.map +1 -1
  23. package/dist/core/pi-agent.d.ts.map +1 -1
  24. package/dist/core/pi-agent.js +1 -0
  25. package/dist/core/pi-agent.js.map +1 -1
  26. package/dist/core/prompt-templates.d.ts +5 -0
  27. package/dist/core/prompt-templates.d.ts.map +1 -1
  28. package/dist/core/prompt-templates.js +115 -0
  29. package/dist/core/prompt-templates.js.map +1 -1
  30. package/dist/core/resource-loader.d.ts +15 -0
  31. package/dist/core/resource-loader.d.ts.map +1 -1
  32. package/dist/core/resource-loader.js +332 -40
  33. package/dist/core/resource-loader.js.map +1 -1
  34. package/dist/core/rules.d.ts +6 -0
  35. package/dist/core/rules.d.ts.map +1 -1
  36. package/dist/core/rules.js +216 -0
  37. package/dist/core/rules.js.map +1 -1
  38. package/dist/core/skills.d.ts +6 -0
  39. package/dist/core/skills.d.ts.map +1 -1
  40. package/dist/core/skills.js +216 -0
  41. package/dist/core/skills.js.map +1 -1
  42. package/dist/core/source-info.d.ts +2 -0
  43. package/dist/core/source-info.d.ts.map +1 -1
  44. package/dist/core/source-info.js +6 -0
  45. package/dist/core/source-info.js.map +1 -1
  46. package/dist/core/tools/bash.d.ts.map +1 -1
  47. package/dist/core/tools/bash.js +5 -5
  48. package/dist/core/tools/bash.js.map +1 -1
  49. package/dist/core/tools/edit.d.ts.map +1 -1
  50. package/dist/core/tools/edit.js +5 -5
  51. package/dist/core/tools/edit.js.map +1 -1
  52. package/dist/core/tools/find.d.ts.map +1 -1
  53. package/dist/core/tools/find.js +2 -2
  54. package/dist/core/tools/find.js.map +1 -1
  55. package/dist/core/tools/grep.d.ts.map +1 -1
  56. package/dist/core/tools/grep.js +2 -2
  57. package/dist/core/tools/grep.js.map +1 -1
  58. package/dist/core/tools/ls.d.ts.map +1 -1
  59. package/dist/core/tools/ls.js +2 -2
  60. package/dist/core/tools/ls.js.map +1 -1
  61. package/dist/core/tools/read.d.ts.map +1 -1
  62. package/dist/core/tools/read.js +3 -2
  63. package/dist/core/tools/read.js.map +1 -1
  64. package/dist/core/tools/render-utils.d.ts +9 -0
  65. package/dist/core/tools/render-utils.d.ts.map +1 -1
  66. package/dist/core/tools/render-utils.js +14 -0
  67. package/dist/core/tools/render-utils.js.map +1 -1
  68. package/dist/core/tools/write.d.ts.map +1 -1
  69. package/dist/core/tools/write.js +3 -2
  70. package/dist/core/tools/write.js.map +1 -1
  71. package/dist/index.d.ts +1 -1
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js.map +1 -1
  74. package/dist/main.d.ts.map +1 -1
  75. package/dist/main.js +7 -5
  76. package/dist/main.js.map +1 -1
  77. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  78. package/dist/modes/interactive/interactive-mode.js +21 -9
  79. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  80. package/docs/extensions.md +82 -3
  81. package/docs/usage.md +2 -0
  82. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  83. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  84. package/examples/extensions/sandbox/package.json +1 -1
  85. package/examples/extensions/with-deps/package.json +1 -1
  86. package/npm-shrinkwrap.json +12 -12
  87. package/package.json +4 -4
@@ -7,12 +7,12 @@ import { canonicalizePath, isLocalPath, resolvePath } from "../utils/paths.js";
7
7
  import { createEventBus } from "./event-bus.js";
8
8
  import { createExtensionRuntime, loadExtensionFromFactory, loadExtensions } from "./extensions/loader.js";
9
9
  import { DefaultPackageManager } from "./package-manager.js";
10
- import { loadPromptTemplates } from "./prompt-templates.js";
11
- import { loadRules } from "./rules.js";
10
+ import { loadPromptTemplates, loadPromptTemplatesWithOperations } from "./prompt-templates.js";
11
+ import { loadRules, loadRulesWithOperations } from "./rules.js";
12
12
  import { SettingsManager } from "./settings-manager.js";
13
- import { loadSkills } from "./skills.js";
13
+ import { loadSkills, loadSkillsWithOperations } from "./skills.js";
14
14
  import { createSourceInfo } from "./source-info.js";
15
- function resolvePromptInput(input, description) {
15
+ async function resolvePromptInput(input, description, operations) {
16
16
  if (!input) {
17
17
  return undefined;
18
18
  }
@@ -25,6 +25,13 @@ function resolvePromptInput(input, description) {
25
25
  return input;
26
26
  }
27
27
  }
28
+ if (operations) {
29
+ try {
30
+ await operations.access(input, "read");
31
+ return (await operations.readFile(input)).toString("utf-8");
32
+ }
33
+ catch { }
34
+ }
28
35
  return input;
29
36
  }
30
37
  function loadContextFileFromDir(dir) {
@@ -74,6 +81,45 @@ export function loadProjectContextFiles(options) {
74
81
  contextFiles.push(...ancestorContextFiles);
75
82
  return contextFiles;
76
83
  }
84
+ async function loadContextFileFromDirWithOperations(operations, dir) {
85
+ const candidates = ["AGENTS.md", "AGENTS.MD", "CLAUDE.md", "CLAUDE.MD"];
86
+ for (const filename of candidates) {
87
+ const filePath = join(dir, filename);
88
+ try {
89
+ await operations.access(filePath, "read");
90
+ return { path: filePath, content: (await operations.readFile(filePath)).toString("utf-8") };
91
+ }
92
+ catch { }
93
+ }
94
+ return null;
95
+ }
96
+ async function loadProjectContextFilesWithOperations(options) {
97
+ const contextFiles = [];
98
+ const seenPaths = new Set();
99
+ const globalContext = loadContextFileFromDir(resolvePath(options.agentDir));
100
+ if (globalContext) {
101
+ contextFiles.push(globalContext);
102
+ seenPaths.add(globalContext.path);
103
+ }
104
+ const ancestorContextFiles = [];
105
+ let currentDir = resolvePath(options.cwd);
106
+ const root = resolve("/");
107
+ while (true) {
108
+ const contextFile = await loadContextFileFromDirWithOperations(options.operations, currentDir);
109
+ if (contextFile && !seenPaths.has(contextFile.path)) {
110
+ ancestorContextFiles.unshift(contextFile);
111
+ seenPaths.add(contextFile.path);
112
+ }
113
+ if (currentDir === root)
114
+ break;
115
+ const parentDir = resolve(currentDir, "..");
116
+ if (parentDir === currentDir)
117
+ break;
118
+ currentDir = parentDir;
119
+ }
120
+ contextFiles.push(...ancestorContextFiles);
121
+ return contextFiles;
122
+ }
77
123
  export class DefaultResourceLoader {
78
124
  cwd;
79
125
  agentDir;
@@ -94,6 +140,7 @@ export class DefaultResourceLoader {
94
140
  noContextFiles;
95
141
  systemPromptSource;
96
142
  appendSystemPromptSource;
143
+ toolOperations;
97
144
  extensionsOverride;
98
145
  skillsOverride;
99
146
  rulesOverride;
@@ -146,6 +193,7 @@ export class DefaultResourceLoader {
146
193
  this.noContextFiles = options.noContextFiles ?? false;
147
194
  this.systemPromptSource = options.systemPrompt;
148
195
  this.appendSystemPromptSource = options.appendSystemPrompt;
196
+ this.toolOperations = options.toolOperations;
149
197
  this.extensionsOverride = options.extensionsOverride;
150
198
  this.skillsOverride = options.skillsOverride;
151
199
  this.rulesOverride = options.rulesOverride;
@@ -198,6 +246,48 @@ export class DefaultResourceLoader {
198
246
  getAppendSystemPrompt() {
199
247
  return this.appendSystemPrompt;
200
248
  }
249
+ getInstructionOperations() {
250
+ const backend = this.toolOperations?.getBackendInfo?.();
251
+ return backend?.type === "ssh" && backend.configured ? this.toolOperations : undefined;
252
+ }
253
+ getRemoteProjectInstructionResourcePaths(cwd) {
254
+ const projectBaseDir = join(cwd, CONFIG_DIR_NAME);
255
+ const projectMetadata = {
256
+ source: "ssh",
257
+ scope: "project",
258
+ origin: "top-level",
259
+ baseDir: projectBaseDir,
260
+ };
261
+ const skills = [
262
+ { path: join(projectBaseDir, "skills"), metadata: projectMetadata },
263
+ ];
264
+ const rules = [
265
+ { path: join(projectBaseDir, "rules"), metadata: projectMetadata },
266
+ ];
267
+ const prompts = [
268
+ { path: join(projectBaseDir, "prompts"), metadata: projectMetadata },
269
+ ];
270
+ let currentDir = resolve(cwd);
271
+ const root = resolve("/");
272
+ while (true) {
273
+ const agentsBaseDir = join(currentDir, ".agents");
274
+ const agentsMetadata = {
275
+ source: "ssh",
276
+ scope: "project",
277
+ origin: "top-level",
278
+ baseDir: agentsBaseDir,
279
+ };
280
+ skills.push({ path: join(agentsBaseDir, "skills"), metadata: agentsMetadata });
281
+ rules.push({ path: join(agentsBaseDir, "rules"), metadata: agentsMetadata });
282
+ if (currentDir === root)
283
+ break;
284
+ const parentDir = resolve(currentDir, "..");
285
+ if (parentDir === currentDir)
286
+ break;
287
+ currentDir = parentDir;
288
+ }
289
+ return { skills, rules, prompts };
290
+ }
201
291
  extendResources(paths) {
202
292
  const skillPaths = this.normalizeExtensionPaths(paths.skillPaths ?? []);
203
293
  const rulePaths = this.normalizeExtensionPaths(paths.rulePaths ?? []);
@@ -253,10 +343,16 @@ export class DefaultResourceLoader {
253
343
  return resources.filter((r) => r.enabled);
254
344
  };
255
345
  const getEnabledPaths = (resources) => getEnabledResources(resources).map((r) => r.path);
346
+ const instructionOperations = this.getInstructionOperations();
347
+ const loadProjectInstructionsRemotely = instructionOperations !== undefined;
348
+ const isLocalProjectInstructionResource = (resource) => loadProjectInstructionsRemotely &&
349
+ resource.metadata.scope === "project" &&
350
+ resource.metadata.origin === "top-level";
256
351
  const enabledExtensions = getEnabledPaths(resolvedPaths.extensions);
257
- const enabledSkillResources = getEnabledResources(resolvedPaths.skills);
258
- const enabledRuleResources = getEnabledResources(resolvedPaths.rules);
259
- const enabledPrompts = getEnabledPaths(resolvedPaths.prompts);
352
+ const enabledSkillResources = getEnabledResources(resolvedPaths.skills).filter((resource) => !isLocalProjectInstructionResource(resource));
353
+ const enabledRuleResources = getEnabledResources(resolvedPaths.rules).filter((resource) => !isLocalProjectInstructionResource(resource));
354
+ const enabledPromptResources = getEnabledResources(resolvedPaths.prompts).filter((resource) => !isLocalProjectInstructionResource(resource));
355
+ const enabledPrompts = enabledPromptResources.map((resource) => resource.path);
260
356
  const enabledThemes = getEnabledPaths(resolvedPaths.themes);
261
357
  const mapSkillPath = (resource) => {
262
358
  if (resource.metadata.source !== "auto" && resource.metadata.origin !== "package") {
@@ -280,7 +376,20 @@ export class DefaultResourceLoader {
280
376
  }
281
377
  return resource.path;
282
378
  };
283
- const enabledSkills = enabledSkillResources.map(mapSkillPath);
379
+ const remoteInstructionResourcePaths = instructionOperations
380
+ ? this.getRemoteProjectInstructionResourcePaths(instructionOperations.cwd)
381
+ : { skills: [], rules: [], prompts: [] };
382
+ for (const entry of [
383
+ ...remoteInstructionResourcePaths.skills,
384
+ ...remoteInstructionResourcePaths.rules,
385
+ ...remoteInstructionResourcePaths.prompts,
386
+ ]) {
387
+ metadataByPath.set(entry.path, entry.metadata);
388
+ }
389
+ const enabledSkills = [
390
+ ...enabledSkillResources.map(mapSkillPath),
391
+ ...remoteInstructionResourcePaths.skills.map((entry) => entry.path),
392
+ ];
284
393
  const mapRulePath = (resource) => {
285
394
  if (resource.metadata.source !== "auto" && resource.metadata.origin !== "package") {
286
395
  return resource.path;
@@ -303,7 +412,10 @@ export class DefaultResourceLoader {
303
412
  }
304
413
  return resource.path;
305
414
  };
306
- const enabledRules = enabledRuleResources.map(mapRulePath);
415
+ const enabledRules = [
416
+ ...enabledRuleResources.map(mapRulePath),
417
+ ...remoteInstructionResourcePaths.rules.map((entry) => entry.path),
418
+ ];
307
419
  // Add CLI paths metadata
308
420
  for (const r of cliExtensionPaths.extensions) {
309
421
  if (!metadataByPath.has(r.path)) {
@@ -352,7 +464,7 @@ export class DefaultResourceLoader {
352
464
  ? this.mergePaths(cliEnabledSkills, this.additionalSkillPaths)
353
465
  : this.mergePaths([...cliEnabledSkills, ...enabledSkills], this.additionalSkillPaths);
354
466
  this.lastSkillPaths = skillPaths;
355
- this.updateSkillsFromPaths(skillPaths, metadataByPath);
467
+ await this.updateSkillsFromPathsForReload(skillPaths, metadataByPath);
356
468
  for (const p of this.additionalSkillPaths) {
357
469
  if (isLocalPath(p)) {
358
470
  const resolved = this.resolveResourcePath(p);
@@ -365,7 +477,7 @@ export class DefaultResourceLoader {
365
477
  ? this.mergePaths(cliEnabledRules, this.additionalRulePaths)
366
478
  : this.mergePaths([...cliEnabledRules, ...enabledRules], this.additionalRulePaths);
367
479
  this.lastRulePaths = rulePaths;
368
- this.updateRulesFromPaths(rulePaths, metadataByPath);
480
+ await this.updateRulesFromPathsForReload(rulePaths, metadataByPath);
369
481
  for (const p of this.additionalRulePaths) {
370
482
  if (isLocalPath(p)) {
371
483
  const resolved = this.resolveResourcePath(p);
@@ -374,11 +486,12 @@ export class DefaultResourceLoader {
374
486
  }
375
487
  }
376
488
  }
489
+ const remotePromptPaths = remoteInstructionResourcePaths.prompts.map((entry) => entry.path);
377
490
  const promptPaths = this.noPromptTemplates
378
491
  ? this.mergePaths(cliEnabledPrompts, this.additionalPromptTemplatePaths)
379
- : this.mergePaths([...cliEnabledPrompts, ...enabledPrompts], this.additionalPromptTemplatePaths);
492
+ : this.mergePaths([...cliEnabledPrompts, ...enabledPrompts, ...remotePromptPaths], this.additionalPromptTemplatePaths);
380
493
  this.lastPromptPaths = promptPaths;
381
- this.updatePromptsFromPaths(promptPaths, metadataByPath);
494
+ await this.updatePromptsFromPathsForReload(promptPaths, metadataByPath);
382
495
  for (const p of this.additionalPromptTemplatePaths) {
383
496
  if (isLocalPath(p)) {
384
497
  const resolved = this.resolveResourcePath(p);
@@ -403,17 +516,23 @@ export class DefaultResourceLoader {
403
516
  }
404
517
  }
405
518
  const agentsFiles = {
406
- agentsFiles: this.noContextFiles ? [] : loadProjectContextFiles({ cwd: this.cwd, agentDir: this.agentDir }),
519
+ agentsFiles: this.noContextFiles
520
+ ? []
521
+ : instructionOperations
522
+ ? await loadProjectContextFilesWithOperations({
523
+ cwd: instructionOperations.cwd,
524
+ agentDir: this.agentDir,
525
+ operations: instructionOperations,
526
+ })
527
+ : loadProjectContextFiles({ cwd: this.cwd, agentDir: this.agentDir }),
407
528
  };
408
529
  const resolvedAgentsFiles = this.agentsFilesOverride ? this.agentsFilesOverride(agentsFiles) : agentsFiles;
409
530
  this.agentsFiles = resolvedAgentsFiles.agentsFiles;
410
- const baseSystemPrompt = resolvePromptInput(this.systemPromptSource ?? this.discoverSystemPromptFile(), "system prompt");
531
+ const baseSystemPrompt = await resolvePromptInput(this.systemPromptSource ?? this.discoverSystemPromptFile(), "system prompt", this.getInstructionOperations());
411
532
  this.systemPrompt = this.systemPromptOverride ? this.systemPromptOverride(baseSystemPrompt) : baseSystemPrompt;
412
533
  const appendSources = this.appendSystemPromptSource ??
413
534
  (this.discoverAppendSystemPromptFile() ? [this.discoverAppendSystemPromptFile()] : []);
414
- const baseAppend = appendSources
415
- .map((s) => resolvePromptInput(s, "append system prompt"))
416
- .filter((s) => s !== undefined);
535
+ const baseAppend = (await Promise.all(appendSources.map((s) => resolvePromptInput(s, "append system prompt", this.getInstructionOperations())))).filter((s) => s !== undefined);
417
536
  this.appendSystemPrompt = this.appendSystemPromptOverride
418
537
  ? this.appendSystemPromptOverride(baseAppend)
419
538
  : baseAppend;
@@ -429,6 +548,31 @@ export class DefaultResourceLoader {
429
548
  };
430
549
  });
431
550
  }
551
+ getExtensionRegisteredSkills() {
552
+ return this.extensionsResult.extensions.flatMap((extension) => Array.from(extension.skills.values()));
553
+ }
554
+ getExtensionRegisteredRules() {
555
+ return this.extensionsResult.extensions.flatMap((extension) => Array.from(extension.rules.values()));
556
+ }
557
+ getExtensionRegisteredPrompts() {
558
+ return this.extensionsResult.extensions.flatMap((extension) => Array.from(extension.prompts.values()));
559
+ }
560
+ applyLoadedSkills(skillsResult, metadataByPath) {
561
+ const extensionSkills = this.getExtensionRegisteredSkills();
562
+ const seenSkillNames = new Set(extensionSkills.map((skill) => skill.name));
563
+ const baseSkillsResult = {
564
+ skills: [...extensionSkills, ...skillsResult.skills.filter((skill) => !seenSkillNames.has(skill.name))],
565
+ diagnostics: skillsResult.diagnostics,
566
+ };
567
+ const resolvedSkills = this.skillsOverride ? this.skillsOverride(baseSkillsResult) : baseSkillsResult;
568
+ this.skills = resolvedSkills.skills.map((skill) => ({
569
+ ...skill,
570
+ sourceInfo: this.findSourceInfoForPath(skill.filePath, this.extensionSkillSourceInfos, metadataByPath) ??
571
+ skill.sourceInfo ??
572
+ this.getDefaultSourceInfoForPath(skill.filePath),
573
+ }));
574
+ this.skillDiagnostics = resolvedSkills.diagnostics;
575
+ }
432
576
  updateSkillsFromPaths(skillPaths, metadataByPath) {
433
577
  let skillsResult;
434
578
  if (this.noSkills && skillPaths.length === 0) {
@@ -442,14 +586,76 @@ export class DefaultResourceLoader {
442
586
  includeDefaults: false,
443
587
  });
444
588
  }
445
- const resolvedSkills = this.skillsOverride ? this.skillsOverride(skillsResult) : skillsResult;
446
- this.skills = resolvedSkills.skills.map((skill) => ({
447
- ...skill,
448
- sourceInfo: this.findSourceInfoForPath(skill.filePath, this.extensionSkillSourceInfos, metadataByPath) ??
449
- skill.sourceInfo ??
450
- this.getDefaultSourceInfoForPath(skill.filePath),
589
+ this.applyLoadedSkills(skillsResult, metadataByPath);
590
+ }
591
+ shouldLoadPathWithInstructionOperations(path, metadataByPath) {
592
+ const operations = this.getInstructionOperations();
593
+ if (!operations)
594
+ return false;
595
+ const sourceInfo = this.findSourceInfoForPath(path, undefined, metadataByPath);
596
+ if (sourceInfo?.source === "ssh")
597
+ return true;
598
+ const cwd = operations.cwd.endsWith(sep) ? operations.cwd : `${operations.cwd}${sep}`;
599
+ return path === operations.cwd || path.startsWith(cwd);
600
+ }
601
+ async updateSkillsFromPathsForReload(skillPaths, metadataByPath) {
602
+ let skillsResult;
603
+ const operations = this.getInstructionOperations();
604
+ if (this.noSkills && skillPaths.length === 0) {
605
+ skillsResult = { skills: [], diagnostics: [] };
606
+ }
607
+ else if (operations) {
608
+ const remotePaths = skillPaths.filter((path) => this.shouldLoadPathWithInstructionOperations(path, metadataByPath));
609
+ const localPaths = skillPaths.filter((path) => !this.shouldLoadPathWithInstructionOperations(path, metadataByPath));
610
+ const remoteResult = await loadSkillsWithOperations({
611
+ cwd: operations.cwd,
612
+ agentDir: this.agentDir,
613
+ skillPaths: remotePaths,
614
+ includeDefaults: false,
615
+ operations,
616
+ });
617
+ const localResult = loadSkills({
618
+ cwd: this.cwd,
619
+ agentDir: this.agentDir,
620
+ skillPaths: localPaths,
621
+ includeDefaults: false,
622
+ });
623
+ const skillsByName = new Map();
624
+ for (const skill of [...remoteResult.skills, ...localResult.skills]) {
625
+ if (!skillsByName.has(skill.name)) {
626
+ skillsByName.set(skill.name, skill);
627
+ }
628
+ }
629
+ skillsResult = {
630
+ skills: Array.from(skillsByName.values()),
631
+ diagnostics: [...remoteResult.diagnostics, ...localResult.diagnostics],
632
+ };
633
+ }
634
+ else {
635
+ skillsResult = loadSkills({
636
+ cwd: this.cwd,
637
+ agentDir: this.agentDir,
638
+ skillPaths,
639
+ includeDefaults: false,
640
+ });
641
+ }
642
+ this.applyLoadedSkills(skillsResult, metadataByPath);
643
+ }
644
+ applyLoadedRules(rulesResult, metadataByPath) {
645
+ const extensionRules = this.getExtensionRegisteredRules();
646
+ const seenRuleNames = new Set(extensionRules.map((rule) => rule.name));
647
+ const baseRulesResult = {
648
+ rules: [...extensionRules, ...rulesResult.rules.filter((rule) => !seenRuleNames.has(rule.name))],
649
+ diagnostics: rulesResult.diagnostics,
650
+ };
651
+ const resolvedRules = this.rulesOverride ? this.rulesOverride(baseRulesResult) : baseRulesResult;
652
+ this.rules = resolvedRules.rules.map((rule) => ({
653
+ ...rule,
654
+ sourceInfo: this.findSourceInfoForPath(rule.filePath, this.extensionRuleSourceInfos, metadataByPath) ??
655
+ rule.sourceInfo ??
656
+ this.getDefaultSourceInfoForPath(rule.filePath),
451
657
  }));
452
- this.skillDiagnostics = resolvedSkills.diagnostics;
658
+ this.ruleDiagnostics = resolvedRules.diagnostics;
453
659
  }
454
660
  updateRulesFromPaths(rulePaths, metadataByPath) {
455
661
  let rulesResult;
@@ -464,14 +670,63 @@ export class DefaultResourceLoader {
464
670
  includeDefaults: false,
465
671
  });
466
672
  }
467
- const resolvedRules = this.rulesOverride ? this.rulesOverride(rulesResult) : rulesResult;
468
- this.rules = resolvedRules.rules.map((rule) => ({
469
- ...rule,
470
- sourceInfo: this.findSourceInfoForPath(rule.filePath, this.extensionRuleSourceInfos, metadataByPath) ??
471
- rule.sourceInfo ??
472
- this.getDefaultSourceInfoForPath(rule.filePath),
673
+ this.applyLoadedRules(rulesResult, metadataByPath);
674
+ }
675
+ async updateRulesFromPathsForReload(rulePaths, metadataByPath) {
676
+ let rulesResult;
677
+ const operations = this.getInstructionOperations();
678
+ if (this.noRules && rulePaths.length === 0) {
679
+ rulesResult = { rules: [], diagnostics: [] };
680
+ }
681
+ else if (operations) {
682
+ const remotePaths = rulePaths.filter((path) => this.shouldLoadPathWithInstructionOperations(path, metadataByPath));
683
+ const localPaths = rulePaths.filter((path) => !this.shouldLoadPathWithInstructionOperations(path, metadataByPath));
684
+ const remoteResult = await loadRulesWithOperations({
685
+ cwd: operations.cwd,
686
+ agentDir: this.agentDir,
687
+ rulePaths: remotePaths,
688
+ includeDefaults: false,
689
+ operations,
690
+ });
691
+ const localResult = loadRules({
692
+ cwd: this.cwd,
693
+ agentDir: this.agentDir,
694
+ rulePaths: localPaths,
695
+ includeDefaults: false,
696
+ });
697
+ const rulesByName = new Map();
698
+ for (const rule of [...remoteResult.rules, ...localResult.rules]) {
699
+ if (!rulesByName.has(rule.name)) {
700
+ rulesByName.set(rule.name, rule);
701
+ }
702
+ }
703
+ rulesResult = {
704
+ rules: Array.from(rulesByName.values()),
705
+ diagnostics: [...remoteResult.diagnostics, ...localResult.diagnostics],
706
+ };
707
+ }
708
+ else {
709
+ rulesResult = loadRules({
710
+ cwd: this.cwd,
711
+ agentDir: this.agentDir,
712
+ rulePaths,
713
+ includeDefaults: false,
714
+ });
715
+ }
716
+ this.applyLoadedRules(rulesResult, metadataByPath);
717
+ }
718
+ applyLoadedPrompts(promptsResult, metadataByPath) {
719
+ const extensionPrompts = this.getExtensionRegisteredPrompts();
720
+ const basePromptsResult = this.dedupePrompts([...extensionPrompts, ...promptsResult.prompts]);
721
+ basePromptsResult.diagnostics.unshift(...promptsResult.diagnostics);
722
+ const resolvedPrompts = this.promptsOverride ? this.promptsOverride(basePromptsResult) : basePromptsResult;
723
+ this.prompts = resolvedPrompts.prompts.map((prompt) => ({
724
+ ...prompt,
725
+ sourceInfo: this.findSourceInfoForPath(prompt.filePath, this.extensionPromptSourceInfos, metadataByPath) ??
726
+ prompt.sourceInfo ??
727
+ this.getDefaultSourceInfoForPath(prompt.filePath),
473
728
  }));
474
- this.ruleDiagnostics = resolvedRules.diagnostics;
729
+ this.promptDiagnostics = resolvedPrompts.diagnostics;
475
730
  }
476
731
  updatePromptsFromPaths(promptPaths, metadataByPath) {
477
732
  let promptsResult;
@@ -487,14 +742,42 @@ export class DefaultResourceLoader {
487
742
  });
488
743
  promptsResult = this.dedupePrompts(allPrompts);
489
744
  }
490
- const resolvedPrompts = this.promptsOverride ? this.promptsOverride(promptsResult) : promptsResult;
491
- this.prompts = resolvedPrompts.prompts.map((prompt) => ({
492
- ...prompt,
493
- sourceInfo: this.findSourceInfoForPath(prompt.filePath, this.extensionPromptSourceInfos, metadataByPath) ??
494
- prompt.sourceInfo ??
495
- this.getDefaultSourceInfoForPath(prompt.filePath),
496
- }));
497
- this.promptDiagnostics = resolvedPrompts.diagnostics;
745
+ this.applyLoadedPrompts(promptsResult, metadataByPath);
746
+ }
747
+ async updatePromptsFromPathsForReload(promptPaths, metadataByPath) {
748
+ let promptsResult;
749
+ const operations = this.getInstructionOperations();
750
+ if (this.noPromptTemplates && promptPaths.length === 0) {
751
+ promptsResult = { prompts: [], diagnostics: [] };
752
+ }
753
+ else if (operations) {
754
+ const remotePaths = promptPaths.filter((path) => this.shouldLoadPathWithInstructionOperations(path, metadataByPath));
755
+ const localPaths = promptPaths.filter((path) => !this.shouldLoadPathWithInstructionOperations(path, metadataByPath));
756
+ const remotePrompts = await loadPromptTemplatesWithOperations({
757
+ cwd: operations.cwd,
758
+ agentDir: this.agentDir,
759
+ promptPaths: remotePaths,
760
+ includeDefaults: false,
761
+ operations,
762
+ });
763
+ const localPrompts = loadPromptTemplates({
764
+ cwd: this.cwd,
765
+ agentDir: this.agentDir,
766
+ promptPaths: localPaths,
767
+ includeDefaults: false,
768
+ });
769
+ promptsResult = this.dedupePrompts([...remotePrompts, ...localPrompts]);
770
+ }
771
+ else {
772
+ const allPrompts = loadPromptTemplates({
773
+ cwd: this.cwd,
774
+ agentDir: this.agentDir,
775
+ promptPaths,
776
+ includeDefaults: false,
777
+ });
778
+ promptsResult = this.dedupePrompts(allPrompts);
779
+ }
780
+ this.applyLoadedPrompts(promptsResult, metadataByPath);
498
781
  }
499
782
  updateThemesFromPaths(themePaths, metadataByPath) {
500
783
  let themesResult;
@@ -529,6 +812,15 @@ export class DefaultResourceLoader {
529
812
  for (const tool of extension.tools.values()) {
530
813
  tool.sourceInfo = extension.sourceInfo;
531
814
  }
815
+ for (const skill of extension.skills.values()) {
816
+ skill.sourceInfo = extension.sourceInfo;
817
+ }
818
+ for (const rule of extension.rules.values()) {
819
+ rule.sourceInfo = extension.sourceInfo;
820
+ }
821
+ for (const prompt of extension.prompts.values()) {
822
+ prompt.sourceInfo = extension.sourceInfo;
823
+ }
532
824
  }
533
825
  }
534
826
  findSourceInfoForPath(resourcePath, extraSourceInfos, metadataByPath) {