@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
84 lines • 5 kB
JavaScript
import { ptBrActionProposalText, } from '../action-proposal-text.js';
import { humanizeToolName, resolveToolConfirmation, } from '../tool-presentation.js';
import { DEFAULT_CHANNEL_QUESTION_TEXTS, ptBrChannelQuestionTexts, } from './questions.js';
/** `20 MB`, `512 KB`. */
const readableSize = (bytes) => bytes >= 1024 * 1024
? `${Math.round(bytes / (1024 * 1024))} MB`
: `${Math.max(1, Math.ceil(bytes / 1024))} KB`;
export const DEFAULT_CHANNEL_TEXTS = {
approve: 'Confirm',
reject: 'Cancel',
proposal: ({ confirmation, toolName }) => confirmation
? `*${confirmation.title}*${confirmation.detail ? `\n${confirmation.detail}` : ''}`
: `*${resolveToolConfirmation(toolName, undefined).title}*`,
instruction: ({ approve, reject }) => `Reply *${approve}* to confirm or *${reject}* to cancel.`,
blockingApproval: 'This action needs an approval that can only be given in the app.',
failed: 'Sorry, something went wrong. Please try again.',
linkInstruction: 'Open the link to continue.',
linkValidity: (minutes) => `The link works for up to ${minutes} minutes.`,
actionSucceeded: 'Done.',
actionFailed: 'The action could not be completed.',
noPendingConfirmation: 'There is nothing waiting for your confirmation here.',
ambiguousDecision: (ids, { approve, reject }) => `Which one? Reply *${approve} #ID* or *${reject} #ID*: ${ids.map((id) => `#${id}`).join(', ')}`,
rememberRefused: 'Here every action needs its own confirmation. Reply without "always".',
mediaRefused: (reason, media, limits) => reason === 'disabled'
? 'I can only read text messages here.'
: reason === 'size'
? `That file is too large${limits ? ` (the limit is ${readableSize(limits.maxBytes)})` : ''}.`
: reason === 'failed'
? 'I could not download that file. Please send it again.'
: media.kind === 'audio'
? 'I cannot listen to audio messages. Please type your message.'
: `I cannot read this kind of file${media.contentType ? ` (${media.contentType})` : ''}.`,
questions: DEFAULT_CHANNEL_QUESTION_TEXTS,
};
/**
* Brazilian Portuguese channel texts — the default when the agent's `actionProposalText` is
* `ptBrActionProposalText`, so the reply words and what the channel says agree.
*/
export const ptBrChannelTexts = {
approve: 'Confirmar',
reject: 'Cancelar',
proposal: ({ confirmation, toolName }) => confirmation
? `*${confirmation.title}*${confirmation.detail ? `\n${confirmation.detail}` : ''}`
: `*Executar: ${humanizeToolName(toolName) || 'ação'}?*`,
instruction: ({ approve, reject }) => `Responda *${approve}* para confirmar ou *${reject}* para cancelar.`,
blockingApproval: 'Esta ação precisa de uma aprovação que só pode ser dada no app.',
failed: 'Desculpe, algo deu errado. Tente de novo, por favor.',
linkInstruction: 'Abra o link para continuar.',
linkValidity: (minutes) => `O link vale por até ${minutes} minutos.`,
actionSucceeded: 'Pronto.',
actionFailed: 'Não foi possível concluir a ação.',
noPendingConfirmation: 'Não há nenhuma confirmação pendente por aqui.',
ambiguousDecision: (ids, { approve, reject }) => `Qual delas? Responda *${approve} #ID* ou *${reject} #ID*: ${ids.map((id) => `#${id}`).join(', ')}`,
rememberRefused: 'Por aqui cada ação precisa da sua própria confirmação. Responda sem o "sempre".',
mediaRefused: (reason, media, limits) => reason === 'disabled'
? 'Por aqui eu só consigo ler mensagens de texto.'
: reason === 'size'
? `Esse arquivo é grande demais${limits ? ` (o limite é ${readableSize(limits.maxBytes)})` : ''}.`
: reason === 'failed'
? 'Não consegui baixar esse arquivo. Envie de novo, por favor.'
: media.kind === 'audio'
? 'Não consigo ouvir mensagens de áudio. Escreva sua mensagem, por favor.'
: `Não consigo ler esse tipo de arquivo${media.contentType ? ` (${media.contentType})` : ''}.`,
questions: ptBrChannelQuestionTexts,
};
/**
* The channel texts that speak the language of the agent's text-decision words: {@link
* ptBrChannelTexts} for `ptBrActionProposalText` (or any vocabulary whose `language` is Portuguese),
* else {@link DEFAULT_CHANNEL_TEXTS}.
*/
export function channelTextsFor(vocabulary) {
if (!vocabulary)
return DEFAULT_CHANNEL_TEXTS;
const portuguese = /^pt(-|$)/i.test(vocabulary.language ?? '') ||
vocabulary.approve === ptBrActionProposalText.vocabulary.approve;
return portuguese ? ptBrChannelTexts : DEFAULT_CHANNEL_TEXTS;
}
/** `overrides` over `base`, `questions` merged too. */
export const mergeTexts = (overrides = {}, base = DEFAULT_CHANNEL_TEXTS) => ({
...base,
...overrides,
questions: { ...base.questions, ...overrides.questions },
});
//# sourceMappingURL=texts.js.map