@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
155 lines • 8.54 kB
TypeScript
import type { ActionApprovalMode } from './action-proposal-receipt.js';
import type { AgentDeps } from './agent-deps.js';
import type { AgentRegistry } from './agent-registry.js';
import type { MemoryConfig } from './memory.js';
import type { MessageTimestampsConfig } from './message-timestamps.js';
import type { ResolveToolUiCatalog, ToolUiChannelGuide } from './negotiated-tool-ui.js';
import type { SkillsConfig } from './skills.js';
import type { AgentStore } from './spi/agent-store.js';
import type { ApprovalPolicy } from './spi/approval-policy.js';
import type { HistoryWindow } from './spi/history-window.js';
import type { ModelProvider } from './spi/model-provider.js';
import type { AgentPricingStore } from './spi/pricing-store.js';
import type { InputProcessor, OutputProcessor } from './spi/processors.js';
import type { QuotaStore } from './spi/quota-store.js';
import type { Retriever } from './spi/retriever.js';
import type { RolesPolicy } from './spi/roles-policy.js';
import type { TokenStreamSink } from './spi/token-stream-sink.js';
import type { PresentationErrorHandler } from './spi/tool.js';
import type { ToolRegistry } from './tool-registry.js';
import type { ToolTransientRetrySetting } from './tool-retry.js';
import type { Actor, AgentDefinition, DelegateEdge, PersonaCatalogEntry } from './types.js';
/** The synthesized `agent`-kind tool name for an edge to `target`: `ask_<target>`, or `start_<target>` for a detached one. */
export declare function delegateToolName(target: string, options?: {
detached?: boolean;
}): string;
/** Normalize a `delegatesTo` entry: a bare string is the edge with no authorization annotation. */
export declare function normalizeDelegateEdge(edge: string | DelegateEdge): DelegateEdge;
/**
* Synthesize an `agent`-kind delegate tool for each `agent→agent` edge declared via `delegatesTo`, so
* an orchestrator can call `ask_<target>({ task })` to hand work to another registered agent. The loop
* handles delegation itself (never the handler), so the handler is a no-op. Skips names already taken.
* Returns the number of delegate tools registered.
*
* Authorization: the synthesized spec carries the edge's `roles`/`ability` verbatim, so delegation is
* gated by the SAME `RolesPolicy` as every other tool — no special case, no implicit grant. An edge
* declared as a bare string carries neither, which means ADMIN-only under `DefaultToolAuthorizer` and
* an outright deny under the ability-aware authz adapter. That is deliberate (fail-closed), and the
* {@link DelegateEdge} object form is how an app opens the edge to the actors it intends.
*/
export declare function registerDelegateTools(registry: ToolRegistry, agents: AgentRegistry): number;
/** The shared infrastructure the factory hands to every per-agent deps bundle. */
export interface AgentDepsFactoryConfig {
actionApprovalMode?: ActionApprovalMode;
resolveUiCatalog?: ResolveToolUiCatalog;
/** genui `channels`: the channel's prompt block, and what tool pushes were delivered as. */
uiChannelGuide?: ToolUiChannelGuide;
/** Where a tool's failed `present` is reported. Undefined → a console warning. */
onPresentationError?: PresentationErrorHandler;
model: ModelProvider;
store: AgentStore;
sink: TokenStreamSink;
rolesPolicy: RolesPolicy;
registry: ToolRegistry;
agents: AgentRegistry;
quota?: QuotaStore;
/** Shared approval policy for every agent's `action` calls. Undefined → the requester, no expiry. */
approvalPolicy?: ApprovalPolicy;
/** Shared pricing store so every agent's turns are priced from one table. Omit → cost stays `null`. */
pricingStore?: AgentPricingStore;
/**
* Shared inject-mode retriever. When set, every agent's loop retrieves passages for the user message
* and folds them into its system prompt (replay-safe under durable). Omit → no injection.
*/
retriever?: Retriever;
/** How many passages inject-mode retrieval requests. Undefined → 5. */
retrievalTopK?: number;
/**
* Shared hook deriving the inject-mode retrieval filter from the run's actor, applied for every
* agent. Without it, retrieval is UNSCOPED. See the doc comment on `AgentConfig.retrievalFilter`.
*/
retrievalFilter?: (actor: Actor) => Record<string, unknown>;
/**
* Shared in-place transient-retry policy applied to every agent's tool invocations (DB deadlock /
* lock-wait timeout / serialization failure). Undefined → the loop default; `false` disables it.
*/
toolTransientRetry?: ToolTransientRetrySetting;
/**
* Shared ceiling on how much of a thread rides into every agent's turn. Omit → the full thread
* history rides every turn.
*/
historyWindow?: HistoryWindow;
/**
* Shared: show every agent's model when each user message was sent. Omit → messages reach the
* model as stored.
*/
messageTimestamps?: MessageTimestampsConfig;
/**
* Shared skills seam: the provider a turn lists its catalog from, the resolver that orders an
* actor's scope tokens, and the catalog ceiling. One deployment, one answer to "which scopes does
* this actor have". Omit → no catalog block and no `skill` tool for any agent.
*/
skills?: SkillsConfig;
/**
* Shared memory seam: the provider holding the rows, the resolver that orders an actor's scope
* tokens, and the block's ceilings. Wired next to {@link AgentDepsFactoryConfig.skills} and
* normally sharing its resolver. Omit → no memory block and no `remember` tool for any agent.
*/
memory?: MemoryConfig;
/** Shared input processors, run for every agent's turn — see `AgentLoopDeps.inputProcessors`. */
inputProcessors?: InputProcessor[];
/** Shared output processors, run for every agent's turn — see `AgentLoopDeps.outputProcessors`. */
outputProcessors?: OutputProcessor[];
/** Name of the implicit default agent. Defaults to `'default'`. */
defaultAgentName?: string;
}
/**
* Builds the per-agent {@link AgentDeps} the runner feeds `runAgentLoop`. The single-agent case is
* just the `default` definition; a named agent (registered in the {@link AgentRegistry}) supplies its
* own prompt, personas, tool allow-list and step budget. Model/store/sink/roles are shared.
*/
export declare class AgentDepsFactory {
private readonly config;
constructor(config: AgentDepsFactoryConfig);
/** Every registered agent definition, in registration order. */
agentDefinitions(): AgentDefinition[];
actionApprovalMode(): ActionApprovalMode;
defaultAgentName(): string;
private effectiveTools;
/** Is `name` a registered agent — or the implicit default one? */
isAgent(name: string): boolean;
/**
* The agent a name stands for: itself when it is a registered agent (or unknown — the bare
* assistant), else the agent whose persona took the name over ({@link Persona.aliases}) and that
* persona.
*/
resolveAgent(name: string): {
agentName: string;
persona?: string;
};
/** `agentName`'s personas as a picker reads them. Empty when it declares none. */
personaCatalog(agentName: string): PersonaCatalogEntry[];
/** The persona `agentName` runs under when nothing names one. Undefined → none. */
defaultPersona(agentName: string): string | undefined;
/** Does `agentName` declare a persona `id`? */
hasPersona(agentName: string, id: string): boolean;
/**
* The persona a turn of `agentName` runs under, most specific first: the one the send names
* (refused with {@link PersonaNotFoundError} when the agent does not declare it), else the thread's
* pinned one when this agent declares it, else the agent's default. Undefined → none.
*/
resolvePersona(args: {
agentName: string;
requested?: string;
threadPersona?: string | null;
}): string | undefined;
forAgent(agentName?: string): AgentDeps;
/**
* A persona baked into an agent's deps — how a run journaled under an agent name that a persona has
* since taken over ({@link Persona.aliases}) is served. That run names no persona of its own (it
* predates the fold, and its input cannot change), so the persona applies the way the old agent's
* own config did: as config, re-read on every replay, with no checkpoint of its own.
*/
private withPersona;
}
//# sourceMappingURL=agent-deps-factory.d.ts.map