-
Notifications
You must be signed in to change notification settings - Fork 0
feat(persona-registry): load a repo's personas from any subdirectory of it #319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -103,6 +103,11 @@ export type PersonaSource = string; | |||||
| * - `cwd:agents` → same — `<cwd>/.agentworkforce/workforce/agents/<name>/persona.json`, | ||||||
| * agents that keep their persona next to their handler. | ||||||
| * Also a precise pointer, so also kept as-is. | ||||||
| * - `repo` → `repo` — `<repo root>/.agentworkforce/workforce/personas/`, | ||||||
| * the repository's own personas, visible from any | ||||||
| * subdirectory of it. Present only when cwd is below the | ||||||
| * root and the directory exists. `repo:agents` is its | ||||||
| * nested counterpart. | ||||||
| * - `dir:N` → `dir:N` — extra configurable persona dirs (passed | ||||||
| * through unchanged so position is still legible). | ||||||
| * | ||||||
|
|
@@ -212,6 +217,27 @@ export function defaultCwdAgentDir(cwd: string): string { | |||||
| return join(cwd, '.agentworkforce', 'workforce', 'agents'); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * The repository root at or above `cwd`, or `undefined` outside a repository. | ||||||
| * | ||||||
| * A repo's personas live at its root, but commands are typically run from a | ||||||
| * package or source subdirectory. Without this the cascade looks only at the | ||||||
| * exact cwd, so the same repo yields different personas depending on which | ||||||
| * directory you happen to be standing in. The walk stops at the home directory | ||||||
| * — `~/.agentworkforce/workforce/personas/` is already the `user` layer. | ||||||
| */ | ||||||
| export function findRepoRoot(cwd: string): string | undefined { | ||||||
| const home = resolvePath(homedir()); | ||||||
| let dir = resolvePath(cwd); | ||||||
| while (true) { | ||||||
| if (existsSync(join(dir, '.git'))) return dir; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: When Prompt for AI agents
Suggested change
|
||||||
| if (dir === home) return undefined; | ||||||
|
Comment on lines
+233
to
+234
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a user's home directory itself contains Useful? React with 👍 / 👎. |
||||||
| const parent = dirname(dir); | ||||||
| if (parent === dir) return undefined; | ||||||
| dir = parent; | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| /** Persona filename read from each subdirectory of a nested source dir. */ | ||||||
| export const NESTED_PERSONA_FILENAME = 'persona.json'; | ||||||
|
|
||||||
|
|
@@ -360,6 +386,30 @@ function sourceForPersonaDir( | |||||
| return dir === userPersonaDir ? 'user' : `dir:${idx + 1}`; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Persona directories contributed by the repository root when the command runs | ||||||
| * from a subdirectory. Ranked directly below the cwd layers: the directory you | ||||||
| * are standing in stays the most specific, and the repo answers for everywhere | ||||||
| * else inside it. | ||||||
| */ | ||||||
| function repoSourceDirectories(cwd: string): PersonaSourceDirectory[] { | ||||||
| const root = findRepoRoot(cwd); | ||||||
| if (!root || resolvePath(root) === resolvePath(cwd)) return []; | ||||||
| // Unlike the cwd layers — which are always listed because they are where | ||||||
| // `create` writes — a repo layer is only worth naming when it exists. Most | ||||||
| // repositories keep no personas, and listing a path nobody created is noise. | ||||||
| const dirs: PersonaSourceDirectory[] = []; | ||||||
| const personas = defaultCwdPersonaDir(root); | ||||||
| if (existsSync(personas)) { | ||||||
| dirs.push({ source: 'repo', dir: personas, configurable: false }); | ||||||
| } | ||||||
| const agents = defaultCwdAgentDir(root); | ||||||
| if (existsSync(agents)) { | ||||||
| dirs.push({ source: 'repo:agents', dir: agents, configurable: false, nested: true }); | ||||||
| } | ||||||
| return dirs; | ||||||
| } | ||||||
|
|
||||||
| export function buildPersonaSourceDirectories( | ||||||
| options: LoadOptions = {} | ||||||
| ): { directories: PersonaSourceDirectory[]; config: PersonaSourceConfig } { | ||||||
|
|
@@ -379,6 +429,7 @@ export function buildPersonaSourceDirectories( | |||||
| configurable: false, | ||||||
| nested: true | ||||||
| }, | ||||||
| ...repoSourceDirectories(cwd), | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the repo persona directory is already present in Useful? React with 👍 / 👎.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: When the repository persona directory is already listed in Prompt for AI agents
Suggested change
|
||||||
| ...config.personaDirs.map((dir, idx) => ({ | ||||||
| source: sourceForPersonaDir(dir, idx, config.userPersonaDir), | ||||||
| dir, | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: The
findRepoRoot(loose) === undefinedassertion assumes no directory between the temp dir and the walk's stop point is a git repository.findRepoRootchecks.gitat every ancestor until it reacheshomedir(), so if a runner overridesTMPDIRto point inside a checked-out repo (or beneath a git-initialized home for dotfiles), the walk returns that ancestor instead ofundefinedand this test fails spuriously. Making the assertion robust to the ambient temp dir would prevent an environment-dependent failure.Prompt for AI agents