fix(pi): discover ancestor project resources
This commit was merged in pull request #23.
This commit is contained in:
@@ -32,11 +32,11 @@
|
|||||||
|
|
||||||
- Use produced literals for Herdr key names that include shifted punctuation.
|
- Use produced literals for Herdr key names that include shifted punctuation.
|
||||||
For example, use `prefix+<` instead of `prefix+shift+comma`.
|
For example, use `prefix+<` instead of `prefix+shift+comma`.
|
||||||
- Put global Pi extension sources in `configs/nixos/modules/shell/pi/extensions/`.
|
- Put monorepo Pi extension sources in `.pi/extensions/`.
|
||||||
Home Manager deploys them to `~/.pi/agent/extensions/`.
|
Pi discovers them from subdirectories through the local ancestor-resource patch.
|
||||||
- Treat Home Manager-managed Pi extension, prompt, and skill directories as generated output.
|
- Treat Home Manager-managed Pi settings as generated output.
|
||||||
Do not edit those directories except for throwaway development or local experiments.
|
Do not edit them except for throwaway development or local experiments.
|
||||||
Promote finished work into the NixOS configuration before treating it as deployed.
|
Promote finished settings into the NixOS configuration before treating them as deployed.
|
||||||
|
|
||||||
## Gotchas
|
## Gotchas
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ let
|
|||||||
piDir = "${config.users.users.${user}.home}/.pi/agent";
|
piDir = "${config.users.users.${user}.home}/.pi/agent";
|
||||||
patchedPi = pkgs.pi-coding-agent.overrideAttrs (old: {
|
patchedPi = pkgs.pi-coding-agent.overrideAttrs (old: {
|
||||||
patches = (old.patches or [ ]) ++ [
|
patches = (old.patches or [ ]) ++ [
|
||||||
|
./patches/pi-project-resource-ancestors.patch
|
||||||
./patches/pi-tool-lookup-validation.patch
|
./patches/pi-tool-lookup-validation.patch
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
@@ -44,12 +45,6 @@ in
|
|||||||
# The first declarative rollout replaces the interactive settings file.
|
# The first declarative rollout replaces the interactive settings file.
|
||||||
# Login state stays in auth.json, which this module does not manage.
|
# Login state stays in auth.json, which this module does not manage.
|
||||||
"${piDir}/settings.json".force = true;
|
"${piDir}/settings.json".force = true;
|
||||||
|
|
||||||
"${piDir}/extensions" = {
|
|
||||||
source = ./extensions;
|
|
||||||
recursive = true;
|
|
||||||
force = true;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
diff --git a/packages/coding-agent/src/core/package-manager.ts b/packages/coding-agent/src/core/package-manager.ts
|
||||||
|
--- a/packages/coding-agent/src/core/package-manager.ts
|
||||||
|
+++ b/packages/coding-agent/src/core/package-manager.ts
|
||||||
|
@@ -459,14 +459,14 @@ function findGitRepoRoot(startDir: string): string | null {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-function collectAncestorAgentsSkillDirs(startDir: string): string[] {
|
||||||
|
- const skillDirs: string[] = [];
|
||||||
|
+function collectAncestorConfigDirs(startDir: string, configDirName: string): string[] {
|
||||||
|
+ const configDirs: string[] = [];
|
||||||
|
const resolvedStartDir = resolve(startDir);
|
||||||
|
const gitRepoRoot = findGitRepoRoot(resolvedStartDir);
|
||||||
|
|
||||||
|
let dir = resolvedStartDir;
|
||||||
|
while (true) {
|
||||||
|
- skillDirs.push(join(dir, ".agents", "skills"));
|
||||||
|
+ configDirs.push(join(dir, configDirName));
|
||||||
|
if (gitRepoRoot && dir === gitRepoRoot) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@@ -477,7 +477,7 @@ function collectAncestorAgentsSkillDirs(startDir: string): string[] {
|
||||||
|
dir = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return skillDirs;
|
||||||
|
+ return configDirs;
|
||||||
|
}
|
||||||
|
|
||||||
|
function collectAutoPromptEntries(dir: string): string[] {
|
||||||
|
@@ -2388,16 +2388,13 @@ export class DefaultPackageManager implements PackageManager {
|
||||||
|
prompts: join(globalBaseDir, "prompts"),
|
||||||
|
themes: join(globalBaseDir, "themes"),
|
||||||
|
};
|
||||||
|
- const projectDirs = {
|
||||||
|
- extensions: join(projectBaseDir, "extensions"),
|
||||||
|
- skills: join(projectBaseDir, "skills"),
|
||||||
|
- prompts: join(projectBaseDir, "prompts"),
|
||||||
|
- themes: join(projectBaseDir, "themes"),
|
||||||
|
- };
|
||||||
|
const userAgentsSkillsDir = join(getHomeDir(), ".agents", "skills");
|
||||||
|
const projectTrusted = this.settingsManager.isProjectTrusted();
|
||||||
|
- const projectAgentsSkillDirs = projectTrusted
|
||||||
|
- ? collectAncestorAgentsSkillDirs(this.cwd).filter((dir) => resolve(dir) !== resolve(userAgentsSkillsDir))
|
||||||
|
+ const projectConfigDirs = projectTrusted
|
||||||
|
+ ? collectAncestorConfigDirs(this.cwd, CONFIG_DIR_NAME).filter((dir) => resolve(dir) !== resolve(globalBaseDir))
|
||||||
|
+ : [];
|
||||||
|
+ const projectAgentsDirs = projectTrusted
|
||||||
|
+ ? collectAncestorConfigDirs(this.cwd, ".agents").filter((dir) => resolve(dir) !== resolve(dirname(userAgentsSkillsDir)))
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const addResources = (
|
||||||
|
@@ -2414,56 +2411,54 @@ export class DefaultPackageManager implements PackageManager {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
- if (projectTrusted) {
|
||||||
|
- // Project extensions from .pi/
|
||||||
|
+ // Project resources from .pi/ in cwd and ancestors.
|
||||||
|
+ for (const configDir of projectConfigDirs) {
|
||||||
|
+ const configMetadata: PathMetadata = {
|
||||||
|
+ ...projectMetadata,
|
||||||
|
+ baseDir: configDir,
|
||||||
|
+ };
|
||||||
|
addResources(
|
||||||
|
"extensions",
|
||||||
|
- collectAutoExtensionEntries(projectDirs.extensions),
|
||||||
|
- projectMetadata,
|
||||||
|
+ collectAutoExtensionEntries(join(configDir, "extensions")),
|
||||||
|
+ configMetadata,
|
||||||
|
projectOverrides.extensions,
|
||||||
|
- projectBaseDir,
|
||||||
|
+ configDir,
|
||||||
|
);
|
||||||
|
-
|
||||||
|
- // Project skills from .pi/
|
||||||
|
addResources(
|
||||||
|
"skills",
|
||||||
|
- collectAutoSkillEntries(projectDirs.skills, "pi"),
|
||||||
|
- projectMetadata,
|
||||||
|
+ collectAutoSkillEntries(join(configDir, "skills"), "pi"),
|
||||||
|
+ configMetadata,
|
||||||
|
projectOverrides.skills,
|
||||||
|
- projectBaseDir,
|
||||||
|
+ configDir,
|
||||||
|
+ );
|
||||||
|
+ addResources(
|
||||||
|
+ "prompts",
|
||||||
|
+ collectAutoPromptEntries(join(configDir, "prompts")),
|
||||||
|
+ configMetadata,
|
||||||
|
+ projectOverrides.prompts,
|
||||||
|
+ configDir,
|
||||||
|
+ );
|
||||||
|
+ addResources(
|
||||||
|
+ "themes",
|
||||||
|
+ collectAutoThemeEntries(join(configDir, "themes")),
|
||||||
|
+ configMetadata,
|
||||||
|
+ projectOverrides.themes,
|
||||||
|
+ configDir,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
- // Project skills from .agents/ (each with its own baseDir)
|
||||||
|
- for (const agentsSkillsDir of projectAgentsSkillDirs) {
|
||||||
|
- const agentsBaseDir = dirname(agentsSkillsDir); // the .agents directory
|
||||||
|
+ // Project skills from .agents/ in cwd and ancestors.
|
||||||
|
+ for (const agentsDir of projectAgentsDirs) {
|
||||||
|
const agentsMetadata: PathMetadata = {
|
||||||
|
...projectMetadata,
|
||||||
|
- baseDir: agentsBaseDir,
|
||||||
|
+ baseDir: agentsDir,
|
||||||
|
};
|
||||||
|
addResources(
|
||||||
|
"skills",
|
||||||
|
- collectAutoSkillEntries(agentsSkillsDir, "agents"),
|
||||||
|
+ collectAutoSkillEntries(join(agentsDir, "skills"), "agents"),
|
||||||
|
agentsMetadata,
|
||||||
|
projectOverrides.skills,
|
||||||
|
- agentsBaseDir,
|
||||||
|
- );
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (projectTrusted) {
|
||||||
|
- addResources(
|
||||||
|
- "prompts",
|
||||||
|
- collectAutoPromptEntries(projectDirs.prompts),
|
||||||
|
- projectMetadata,
|
||||||
|
- projectOverrides.prompts,
|
||||||
|
- projectBaseDir,
|
||||||
|
- );
|
||||||
|
- addResources(
|
||||||
|
- "themes",
|
||||||
|
- collectAutoThemeEntries(projectDirs.themes),
|
||||||
|
- projectMetadata,
|
||||||
|
- projectOverrides.themes,
|
||||||
|
- projectBaseDir,
|
||||||
|
+ agentsDir,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user