38 lines
2.1 KiB
TypeScript
38 lines
2.1 KiB
TypeScript
/** System context from the effective cwd, project instructions, and discoverable world skills. */
|
|
import { defineExtension, section } from '@earendil-works/pi-durable'
|
|
import { parseFrontmatter } from '../core/agents.ts'
|
|
import { optional, parent, repoRoot } from '../models/files.ts'
|
|
export const order = -100
|
|
export default function prompt(host: any) {
|
|
const cwd = (input: any) => input.env?.cwd ?? input.agent.cwd ?? '/'
|
|
return defineExtension({name:'prompt',sections:[
|
|
section('cwd', input=>cwd(input)),
|
|
section('tools', input=>(input.agent.tools ?? []).map(tool=>`- ${tool.name}: ${tool.description}`).join('\n')),
|
|
section('project_context', async input=>{
|
|
const current = cwd(input), root = await repoRoot(host.fs,current), paths = []
|
|
for (let at = current; ; at = parent(at)) { paths.unshift(at); if(at === root || at === '/') break }
|
|
const parts = []
|
|
for (const path of paths) {
|
|
const file = `${path === '/' ? '' : path}/AGENTS.md`, text = await optional(host.fs,file)
|
|
if (text !== undefined) parts.push(`<project_instructions path="${file}">\n${text}\n</project_instructions>`)
|
|
}
|
|
return parts.join('\n\n')
|
|
}),
|
|
section('skills', async input=>{
|
|
const root = await repoRoot(host.fs,cwd(input)), skills = new Map()
|
|
for (const folder of ['/src/sausage/skills',`${root}/.sausage/skills`]) {
|
|
let entries
|
|
try { entries = await host.fs.list(folder) } catch(error) { if(error.code !== 'not_found') throw error; entries = [] }
|
|
for (const entry of entries.toSorted((a,b)=>a.name.localeCompare(b.name))) if(entry.kind === 'directory') {
|
|
const path = `${folder}/${entry.name}/SKILL.md`, text = await optional(host.fs,path)
|
|
if(text === undefined) continue
|
|
const {frontmatter} = parseFrontmatter(text)
|
|
if(typeof frontmatter.name !== 'string' || typeof frontmatter.description !== 'string') throw new Error(`Invalid skill ${path}`)
|
|
skills.set(frontmatter.name, `- ${frontmatter.name}: ${frontmatter.description}\n Path: ${path}`)
|
|
}
|
|
}
|
|
return [...skills.values()].join('\n')
|
|
}),
|
|
]})
|
|
}
|