UNPKG

@adonis-agora/agent

Version:

Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.

61 lines • 2.57 kB
import { AgentBackendUnsupportedError } from '../backend.js'; /** * `GET /agent/skills` as an autocomplete source — the concrete one behind `/`, and an example of * the shape any other takes. `position: 'start'` because a skill is a command: `/deploy` is one and * `src/foo` is a path. */ export function createSkillsSource(options) { // One read per thread. The endpoint answers with the whole scope-resolved list rather than a // search, so asking again per keystroke would fetch identical rows only to filter them locally. // A failed read is forgotten, so the next keystroke retries instead of caching the outage. // // The order it arrives in IS the precedence — most specific scope first, then alphabetical — and // is passed through untouched. The type-ahead filter narrows this list by what the user typed; it // never re-derives which skills apply, which is the server's answer and the model's too. const byThread = new Map(); return { id: 'skills', label: options.label ?? 'Skills', trigger: options.trigger ?? '/', position: 'start', getItems: () => { const threadId = options.getThreadId?.(); const key = threadId ?? ''; const cached = byThread.get(key); if (cached) { return cached; } const listSkills = options.backend.listSkills; if (listSkills === undefined) { return Promise.reject(new AgentBackendUnsupportedError('listSkills')); } const pending = listSkills .call(options.backend, threadId) .then((entries) => entries.map(toItem)) .catch((error) => { byThread.delete(key); throw error; }); byThread.set(key, pending); return pending; }, }; } function toItem(entry) { const data = { scope: entry.scope, ...(entry.shadows !== undefined ? { shadows: entry.shadows } : {}), }; return { id: entry.name, label: entry.name, description: entry.description, // `shadows` is present only on a conflict, so saying "overrides" is never noise: without it a // user cannot tell "there is no org default" from "there is one and mine wins". hint: entry.shadows === undefined ? entry.scope : `${entry.scope} · overrides ${entry.shadows.join(', ')}`, data, }; } //# sourceMappingURL=skills-source.js.map