UNPKG

@adonis-agora/agent

Version:

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

95 lines • 4.42 kB
/** * `GET <base>/tools?agent=*`: every tool the actor reaches through ANY agent, each once — for a * surface that shows several agents' conversations. */ export const ALL_AGENTS = '*'; /** Dotted-path read. `undefined` rather than a throw, so a template can outlive a field. */ export function readPresentationPath(value, path) { return path.split('.').reduce((current, key) => { if (current === null || typeof current !== 'object') return undefined; return current[key]; }, value); } function renderPresentationValue(value) { if (value === null || value === undefined) return ''; if (typeof value === 'string') return value; if (typeof value === 'number' || typeof value === 'boolean') return String(value); if (Array.isArray(value)) return value.map(renderPresentationValue).filter(Boolean).join(', '); return ''; } /** * Fill `{dotted.path}` placeholders from `context`. A placeholder with nothing behind it collapses * along with the whitespace in front of it, so "Reading {key}" degrades to "Reading" rather than * printing braces at a person; a filled one keeps the whitespace the author wrote ("({n} files)"). * The one filler the server (approval prompts) and the React layer (activity lines) share. */ export function fillPresentationTemplate(template, context) { return template .replace(/(\s*)\{([\w.]+)\}/g, (_match, space, path) => { const rendered = renderPresentationValue(readPresentationPath(context, path)); return rendered === '' ? '' : `${space}${rendered}`; }) .replace(/\s{2,}/g, ' ') .trim(); } /** * A tool's `confirm` templates filled from one call's input — the approval prompt a client shows * ("Refund order #1002?"), resolved on the server so every transport (native, AG-UI, A2UI, A2A) * carries the same words, not only a client that has the tool catalog. */ export function fillToolConfirmation(confirm, input) { return { title: fillPresentationTemplate(confirm.title, input), verb: fillPresentationTemplate(confirm.verb, input), ...(confirm.detail !== undefined ? { detail: fillPresentationTemplate(confirm.detail, input) } : {}), ...(confirm.link !== undefined ? { link: confirm.link } : {}), }; } /** * The approve button's words when a tool declared no `confirm.verb`. English, like every other * library default: a localized surface (a text channel's `texts.approve`) shows its own word * instead whenever a confirmation carries exactly this one. */ export const DEFAULT_CONFIRM_VERB = 'Approve'; /** * A tool identifier as words a person can read: `refund_order`, `refundOrder` and `refund-order` * all become "Refund order". For the rare surface that has nothing better — a tool's own * `presentation.label` (or its `confirm` templates) always wins, see {@link resolveToolConfirmation}. */ export function humanizeToolName(name) { const words = name .replace(/([a-z0-9])([A-Z])/g, '$1 $2') .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2') .replace(/[_\-.:/\s]+/g, ' ') .trim() .toLowerCase(); return words.length === 0 ? '' : `${words.charAt(0).toUpperCase()}${words.slice(1)}`; } /** * The approval prompt for one call of `toolName`, as every adapter (native stream, AG-UI, A2UI, * text channels, OpenCode, A2A) shows it: the tool's `confirm` templates filled from `input` when it * declared them; otherwise "<label>?" from its `presentation.label`, else "<humanized name>?" with * {@link DEFAULT_CONFIRM_VERB} — never the raw identifier. The one place that fallback is worded. */ export function resolveToolConfirmation(toolName, input, presentation) { const label = presentation?.label?.trim(); const subject = label !== undefined && label !== '' ? label : humanizeToolName(toolName); const fallbackTitle = subject === '' ? `${DEFAULT_CONFIRM_VERB}?` : `${subject}?`; const declared = presentation?.confirm; if (declared === undefined) return { title: fallbackTitle, verb: DEFAULT_CONFIRM_VERB }; const filled = fillToolConfirmation(declared, input); return { ...filled, title: filled.title === '' ? fallbackTitle : filled.title, verb: filled.verb === '' ? DEFAULT_CONFIRM_VERB : filled.verb, }; } //# sourceMappingURL=tool-presentation.js.map