@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
82 lines • 3.89 kB
JavaScript
import { storedMessageToUiMessage } from '../stored-message-to-ui-message.js';
export function proposalNeedsPolling(proposal) {
return (proposal.decision === 'pending' ||
proposal.execution?.status === 'queued' ||
proposal.execution?.status === 'executing' ||
proposal.outcomeDelivery?.status === 'pending');
}
/** Patch proposal metadata and append outcome facts; never replace live text with stored rows. */
export function reconcileProposalMessages(current, proposals, facts) {
const messages = current.map((message) => {
const relevant = proposals.filter((proposal) => message.parts.some((part) => {
if ('data' in part &&
record(part.data) &&
record(part.data.target) &&
part.data.target.kind === 'proposal')
return part.data.target.proposalId === proposal.id;
if ('toolCallId' in part && part.toolCallId === proposal.originToolCallId) {
if ('output' in part && record(part.output) && typeof part.output.proposalId === 'string')
return part.output.proposalId === proposal.id;
return record(message.metadata) && message.metadata.runId === proposal.originRunId;
}
return false;
}));
if (relevant.length === 0)
return message;
const ids = new Set(relevant.map((proposal) => proposal.originToolCallId));
const parts = message.parts.filter((part) => !(part.type === 'data-action-proposal' &&
'id' in part &&
typeof part.id === 'string' &&
ids.has(part.id)));
for (const proposal of relevant)
parts.push({
type: 'data-action-proposal',
id: proposal.originToolCallId,
data: {
id: proposal.originToolCallId,
target: { kind: 'proposal', proposalId: proposal.id, threadId: proposal.threadId },
approver: proposal.approver,
confirmation: proposal.confirmation,
expiresAt: proposal.expiresAt === null
? null
: Math.abs(proposal.expiresAt) <= 8.64e15
? new Date(proposal.expiresAt).toISOString()
: null,
status: proposal.decision,
executionStatus: proposal.execution?.status ?? null,
remember: proposal.decisionAudit?.remember === true,
decidedBy: proposal.decisionAudit?.actorRef ?? null,
decidedVia: proposal.decisionAudit?.via ?? null,
reason: proposal.decisionAudit?.reason ?? null,
},
});
return { ...message, parts };
});
const knownMessages = new Set(messages.map((message) => message.id));
const knownOutcomes = new Set(messages.map((message) => outcomeId(message.metadata)).filter(Boolean));
for (const fact of facts) {
const id = fact.actionProposalOutcome?.id;
if (id === undefined || knownMessages.has(fact.id) || knownOutcomes.has(id))
continue;
const message = storedMessageToUiMessage(fact);
messages.push({
...message,
metadata: {
...(record(message.metadata) ? message.metadata : {}),
actionProposalOutcomeId: id,
},
});
knownMessages.add(fact.id);
knownOutcomes.add(id);
}
return messages;
}
function record(value) {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
function outcomeId(value) {
return record(value) && typeof value.actionProposalOutcomeId === 'string'
? value.actionProposalOutcomeId
: undefined;
}
//# sourceMappingURL=proposals.js.map