Files
sausage/extensions/prompt/server.ts
T

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')
}),
]})
}