@dudousxd/nestjs-agent-core 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -107,37 +107,35 @@ interface PageContext {
107
107
  [key: string]: unknown;
108
108
  }
109
109
  /**
110
- * Inputs a {@link PromptBuilder} may use to compose the effective system prompt for a turn.
111
- * `basePrompt` is the agent's own (already-resolved) base prompt, so a persona builder can wrap
112
- * or extend it rather than replace it.
110
+ * Inputs a {@link PromptBuilder} or {@link PromptContributor} may use to compose the system prompt
111
+ * for a turn. Resolved once per turn from stable inputs (actor / agent / pageContext) so it stays
112
+ * replay-safe.
113
113
  */
114
114
  interface PromptContext {
115
115
  actor: Actor;
116
- persona?: Persona;
116
+ /** The selected agent's name. */
117
+ agentName: string;
117
118
  pageContext?: PageContext;
118
- basePrompt: string;
119
119
  }
120
120
  /**
121
- * A dynamic system prompt. Return a string (optionally async) built from the turn's context —
122
- * e.g. injecting the actor, the current page, or a data-shape description. The loop resolves it
123
- * once per turn from stable inputs (actor/persona/pageContext), so it stays replay-safe.
121
+ * An agent's base system prompt. Return a string (optionally async) built from the turn's context —
122
+ * e.g. injecting the actor, the current page, or a data-shape description. Set on an `@Agent` class
123
+ * via a `@SystemPrompt()` method (or a flat string).
124
124
  */
125
125
  type PromptBuilder = (ctx: PromptContext) => string | Promise<string>;
126
- interface Persona {
127
- id: string;
128
- label: string;
129
- /** A flat prompt, or a {@link PromptBuilder} composed per request from {@link PromptContext}. */
130
- systemPrompt: string | PromptBuilder;
131
- /** If set, only these tool names are offered (after role filtering). */
132
- allowedTools?: string[];
133
- }
126
+ /**
127
+ * A cross-agent system-prompt contributor. Returns an ordered section to APPEND to the composed
128
+ * prompt (after the agent's base), or `null` to contribute nothing this turn — so conditional
129
+ * sections (base-scope, a mentions legend, schema hints) stay clean when they don't apply.
130
+ * Registered app-wide via `@SystemPromptContributor()`; the loop runs every contributor in order.
131
+ */
132
+ type PromptContributor = (ctx: PromptContext) => string | null | Promise<string | null>;
134
133
  /** Everything needed to run one agent turn. */
135
134
  interface AgentRunInput {
136
135
  threadId: string;
137
136
  actor: Actor;
138
137
  /** The latest user message text. */
139
138
  userText: string;
140
- persona?: Persona;
141
139
  pageContext?: PageContext;
142
140
  /** YYYY-MM-DD stamped by the runner so quota/day stays deterministic under durable replay. */
143
141
  day?: string;
@@ -163,10 +161,11 @@ interface AgentRunInput {
163
161
  regenerate?: boolean;
164
162
  }
165
163
  /**
166
- * A named agent: its prompt, the tools it may use, and its personas. Multiple definitions are
167
- * registered via `AgentModule.forFeature([...])`; an orchestrator delegates to others through
168
- * `ctx.runAgent(name, task)`. Model/store/sink/governance are shared from the module unless
169
- * overridden here.
164
+ * A named agent: its prompt, the tools it may use, and who it can hand off to. This is the
165
+ * internal record the loop and `AgentDepsFactory` consume; in an app it is authored as an
166
+ * `@Agent`-decorated class and populated into the `AgentRegistry` by discovery (name, base prompt
167
+ * from `@SystemPrompt`, tool allow-list, handoff targets). An orchestrator hands off to others via
168
+ * `ctx.handoff(OtherAgent)`. Model/store/sink/governance are shared from the module.
170
169
  */
171
170
  interface AgentDefinition {
172
171
  name: string;
@@ -174,17 +173,14 @@ interface AgentDefinition {
174
173
  systemPrompt?: string | PromptBuilder;
175
174
  /** Allow-list of tool names this agent may use (subset of all registered tools). */
176
175
  tools?: string[];
177
- /** Names of other agents this agent may delegate to (auto-registered as `agent`-kind tools). */
176
+ /** Names of other agents this agent may hand off to (auto-registered as `agent`-kind tools). */
178
177
  delegatesTo?: string[];
179
- personas?: Persona[];
180
- defaultPersona?: string;
181
178
  modelId?: string;
182
179
  maxSteps?: number;
183
180
  }
184
181
  interface ThreadSummary {
185
182
  id: string;
186
183
  title: string;
187
- persona: string;
188
184
  transient: boolean;
189
185
  createdAt: string;
190
186
  updatedAt: string;
@@ -194,6 +190,8 @@ interface StoredMessage {
194
190
  id: string;
195
191
  role: MessageRole;
196
192
  content: string;
193
+ /** Which agent produced this message (assistant messages) — provenance for replay / UI / telescope. */
194
+ agentName?: string;
197
195
  toolCalls?: ToolCallRequest[];
198
196
  toolResults?: ToolResult[];
199
197
  followUps?: string[];
@@ -242,6 +240,8 @@ declare const AGENT_RETRIEVER: unique symbol;
242
240
  /** The embedding provider (`EmbeddingProvider`) — text→vector for retrieval + ingestion. */
243
241
  declare const AGENT_EMBEDDING_PROVIDER: unique symbol;
244
242
  declare const AGENT_DEPS_FACTORY: unique symbol;
243
+ /** App-wide, ordered `@SystemPromptContributor()` functions the loop appends after the agent base. */
244
+ declare const AGENT_PROMPT_CONTRIBUTORS: unique symbol;
245
245
 
246
246
  /**
247
247
  * Per-invocation context handed to a tool handler. Host-supplied bits are optional. Identity lives
@@ -253,7 +253,8 @@ interface AiToolCtx {
253
253
  threadId: string;
254
254
  runId: string;
255
255
  requestId: string;
256
- persona?: Persona;
256
+ /** The name of the agent running this turn — provenance a tool can scope on (e.g. capability sets). */
257
+ agentName?: string;
257
258
  pageContext?: PageContext;
258
259
  /** Optional host handle (e.g. an ORM EntityManager) the app threads through options. */
259
260
  host?: unknown;
@@ -348,7 +349,6 @@ interface ModelProvider {
348
349
 
349
350
  interface CreateThreadInput {
350
351
  actor: Actor;
351
- persona: string;
352
352
  transient?: boolean;
353
353
  title?: string;
354
354
  }
@@ -356,7 +356,8 @@ interface AppendMessageInput {
356
356
  threadId: string;
357
357
  role: StoredMessage['role'];
358
358
  content: string;
359
- persona?: string;
359
+ /** Which agent produced this message (assistant messages) — provenance. */
360
+ agentName?: string;
360
361
  toolCalls?: ToolCallRequest[];
361
362
  toolResults?: ToolResult[];
362
363
  followUps?: string[];
@@ -646,8 +647,8 @@ interface AgentGovernanceQueries {
646
647
 
647
648
  /** First filter layer: drop tools the actor's role may not invoke. `can` may be async (authz). */
648
649
  declare function filterToolsByRole(tools: ToolSpec[], actor: Actor, policy: RolesPolicy): Promise<ToolSpec[]>;
649
- /** Second filter layer: if the persona pins an allow-list, keep only those tool names. */
650
- declare function personaFilterTools(tools: ToolSpec[], allowedTools: string[] | undefined): ToolSpec[];
650
+ /** Second filter layer: if the agent pins an allow-list, keep only those tool names. */
651
+ declare function filterToolsByAllowList(tools: ToolSpec[], allowedTools: string[] | undefined): ToolSpec[];
651
652
 
652
653
  /** Holds the named agent definitions registered via `AgentModule.forFeature([...])`. */
653
654
  declare class AgentRegistry {
@@ -687,7 +688,7 @@ declare class ToolRegistry {
687
688
  has(name: string): boolean;
688
689
  spec(name: string): ToolSpec | undefined;
689
690
  allSpecs(): ToolSpec[];
690
- /** The tools to offer the model for this actor+persona, after the two filter layers. */
691
+ /** The tools to offer the model for this actor+agent, after the two filter layers. */
691
692
  definitionsFor(actor: Actor, policy: RolesPolicy, allowedTools?: string[]): Promise<ToolDefinition[]>;
692
693
  /** Run a tool. Re-checks the role (defense-in-depth) and re-parses the input via Zod. */
693
694
  invoke(name: string, input: unknown, ctx: AiToolCtx, policy: RolesPolicy): Promise<unknown>;
@@ -714,10 +715,16 @@ interface AgentLoopDeps {
714
715
  day: string;
715
716
  /** The agent's base prompt. A flat string, or a {@link PromptBuilder} resolved per turn. */
716
717
  systemPrompt: string | PromptBuilder;
718
+ /**
719
+ * Cross-agent system-prompt contributors, applied in order AFTER the agent's base prompt. Each
720
+ * returns a section to append (or `null` to skip this turn). The app registers them via
721
+ * `@SystemPromptContributor()`; the loop composes base + contributors into the effective prompt.
722
+ */
723
+ promptContributors?: PromptContributor[];
717
724
  maxSteps?: number;
718
725
  /** Optional host handle threaded to tool ctx (e.g. an ORM EntityManager). */
719
726
  host?: unknown;
720
- /** Agent-level tool allow-list (intersected with the persona's). Undefined → all tools. */
727
+ /** Agent-level tool allow-list. Undefined → all tools (after role filtering). */
721
728
  toolAllowList?: string[];
722
729
  /**
723
730
  * Per-tool execution timeout in ms. A tool that runs longer is aborted and recorded as failed
@@ -777,7 +784,8 @@ interface AgentRunStarted {
777
784
  runId: string;
778
785
  threadId: string;
779
786
  actorId: string;
780
- persona?: string;
787
+ /** Which agent is handling the run. */
788
+ agentName?: string;
781
789
  }
782
790
  interface AgentMessageEvent {
783
791
  runId: string;
@@ -845,4 +853,4 @@ declare function publishAgentRunFailed(payload: AgentRunFailed): void;
845
853
  declare function publishAgentDelegated(payload: AgentDelegated): void;
846
854
  declare function publishAgentRetrieved(payload: AgentRetrieved): void;
847
855
 
848
- export { AGENT_ACTOR_RESOLVER, AGENT_DEPS_FACTORY, AGENT_DURABLE_RUNNER, AGENT_EMBEDDING_PROVIDER, AGENT_GOVERNANCE_QUERIES, AGENT_MODEL, AGENT_OPTIONS, AGENT_PRICING_STORE, AGENT_QUOTA_STORE, AGENT_REGISTRY, AGENT_RETRIEVER, AGENT_ROLES_POLICY, AGENT_RUNNER, AGENT_SINK, AGENT_STORE, AGENT_TOOL_REGISTRY, type Actor, type ActorResolver, type ActorSpendRow, type AgentDefinition, type AgentDelegated, type AgentGovernanceQueries, type AgentLoopDeps, type AgentLoopHooks, type AgentMessageEvent, type AgentPricingStore, type AgentQuotaExceeded, AgentRegistry, type AgentRetrieved, type AgentRunFailed, type AgentRunFinished, type AgentRunInput, type AgentRunStarted, type AgentRunner, type AgentStore, AgentStreamError, type AgentToolCallEvent, type AiToolCtx, type AppendMessageInput, type CreateThreadInput, type CurrentModelPrice, type Decision, DefaultRolesPolicy, type EmbeddingProvider, type GovernanceRange, type MessageRole, type MessageUsage, type ModelMessage, type ModelPriceInput, type ModelProvider, type ModelSpendRow, type ModelTurnArgs, type ModelTurnResult, type PageContext, type Passage, type Persona, type PromptBuilder, type PromptContext, QuotaExceededError, type QuotaState, type QuotaStore, type RecordToolCallInput, type RecordUsageInput, type RerankOptions, type Reranker, type RetrieveOptions, type Retriever, type RolesPolicy, type SinkWriter, type StoredMessage, type StreamError, type ThreadActivityRow, type ThreadDetail, type ThreadSummary, type TokenStreamSink, type ToolCallActivityRow, type ToolCallRequest, type ToolCallStatus, type ToolDefinition, ToolForbiddenError, type ToolHandler, ToolInputInvalidError, type ToolKind, ToolNotFoundError, ToolRegistry, type ToolResult, type ToolSpec, type UpdateToolCallInput, type UsagePurpose, type UsageTrendPoint, filterToolsByRole, personaFilterTools, publishAgentDelegated, publishAgentMessage, publishAgentQuotaExceeded, publishAgentRetrieved, publishAgentRunFailed, publishAgentRunFinished, publishAgentRunStarted, publishAgentToolCall, runAgentLoop, seedModelPrices };
856
+ export { AGENT_ACTOR_RESOLVER, AGENT_DEPS_FACTORY, AGENT_DURABLE_RUNNER, AGENT_EMBEDDING_PROVIDER, AGENT_GOVERNANCE_QUERIES, AGENT_MODEL, AGENT_OPTIONS, AGENT_PRICING_STORE, AGENT_PROMPT_CONTRIBUTORS, AGENT_QUOTA_STORE, AGENT_REGISTRY, AGENT_RETRIEVER, AGENT_ROLES_POLICY, AGENT_RUNNER, AGENT_SINK, AGENT_STORE, AGENT_TOOL_REGISTRY, type Actor, type ActorResolver, type ActorSpendRow, type AgentDefinition, type AgentDelegated, type AgentGovernanceQueries, type AgentLoopDeps, type AgentLoopHooks, type AgentMessageEvent, type AgentPricingStore, type AgentQuotaExceeded, AgentRegistry, type AgentRetrieved, type AgentRunFailed, type AgentRunFinished, type AgentRunInput, type AgentRunStarted, type AgentRunner, type AgentStore, AgentStreamError, type AgentToolCallEvent, type AiToolCtx, type AppendMessageInput, type CreateThreadInput, type CurrentModelPrice, type Decision, DefaultRolesPolicy, type EmbeddingProvider, type GovernanceRange, type MessageRole, type MessageUsage, type ModelMessage, type ModelPriceInput, type ModelProvider, type ModelSpendRow, type ModelTurnArgs, type ModelTurnResult, type PageContext, type Passage, type PromptBuilder, type PromptContext, type PromptContributor, QuotaExceededError, type QuotaState, type QuotaStore, type RecordToolCallInput, type RecordUsageInput, type RerankOptions, type Reranker, type RetrieveOptions, type Retriever, type RolesPolicy, type SinkWriter, type StoredMessage, type StreamError, type ThreadActivityRow, type ThreadDetail, type ThreadSummary, type TokenStreamSink, type ToolCallActivityRow, type ToolCallRequest, type ToolCallStatus, type ToolDefinition, ToolForbiddenError, type ToolHandler, ToolInputInvalidError, type ToolKind, ToolNotFoundError, ToolRegistry, type ToolResult, type ToolSpec, type UpdateToolCallInput, type UsagePurpose, type UsageTrendPoint, filterToolsByAllowList, filterToolsByRole, publishAgentDelegated, publishAgentMessage, publishAgentQuotaExceeded, publishAgentRetrieved, publishAgentRunFailed, publishAgentRunFinished, publishAgentRunStarted, publishAgentToolCall, runAgentLoop, seedModelPrices };
package/dist/index.d.ts CHANGED
@@ -107,37 +107,35 @@ interface PageContext {
107
107
  [key: string]: unknown;
108
108
  }
109
109
  /**
110
- * Inputs a {@link PromptBuilder} may use to compose the effective system prompt for a turn.
111
- * `basePrompt` is the agent's own (already-resolved) base prompt, so a persona builder can wrap
112
- * or extend it rather than replace it.
110
+ * Inputs a {@link PromptBuilder} or {@link PromptContributor} may use to compose the system prompt
111
+ * for a turn. Resolved once per turn from stable inputs (actor / agent / pageContext) so it stays
112
+ * replay-safe.
113
113
  */
114
114
  interface PromptContext {
115
115
  actor: Actor;
116
- persona?: Persona;
116
+ /** The selected agent's name. */
117
+ agentName: string;
117
118
  pageContext?: PageContext;
118
- basePrompt: string;
119
119
  }
120
120
  /**
121
- * A dynamic system prompt. Return a string (optionally async) built from the turn's context —
122
- * e.g. injecting the actor, the current page, or a data-shape description. The loop resolves it
123
- * once per turn from stable inputs (actor/persona/pageContext), so it stays replay-safe.
121
+ * An agent's base system prompt. Return a string (optionally async) built from the turn's context —
122
+ * e.g. injecting the actor, the current page, or a data-shape description. Set on an `@Agent` class
123
+ * via a `@SystemPrompt()` method (or a flat string).
124
124
  */
125
125
  type PromptBuilder = (ctx: PromptContext) => string | Promise<string>;
126
- interface Persona {
127
- id: string;
128
- label: string;
129
- /** A flat prompt, or a {@link PromptBuilder} composed per request from {@link PromptContext}. */
130
- systemPrompt: string | PromptBuilder;
131
- /** If set, only these tool names are offered (after role filtering). */
132
- allowedTools?: string[];
133
- }
126
+ /**
127
+ * A cross-agent system-prompt contributor. Returns an ordered section to APPEND to the composed
128
+ * prompt (after the agent's base), or `null` to contribute nothing this turn — so conditional
129
+ * sections (base-scope, a mentions legend, schema hints) stay clean when they don't apply.
130
+ * Registered app-wide via `@SystemPromptContributor()`; the loop runs every contributor in order.
131
+ */
132
+ type PromptContributor = (ctx: PromptContext) => string | null | Promise<string | null>;
134
133
  /** Everything needed to run one agent turn. */
135
134
  interface AgentRunInput {
136
135
  threadId: string;
137
136
  actor: Actor;
138
137
  /** The latest user message text. */
139
138
  userText: string;
140
- persona?: Persona;
141
139
  pageContext?: PageContext;
142
140
  /** YYYY-MM-DD stamped by the runner so quota/day stays deterministic under durable replay. */
143
141
  day?: string;
@@ -163,10 +161,11 @@ interface AgentRunInput {
163
161
  regenerate?: boolean;
164
162
  }
165
163
  /**
166
- * A named agent: its prompt, the tools it may use, and its personas. Multiple definitions are
167
- * registered via `AgentModule.forFeature([...])`; an orchestrator delegates to others through
168
- * `ctx.runAgent(name, task)`. Model/store/sink/governance are shared from the module unless
169
- * overridden here.
164
+ * A named agent: its prompt, the tools it may use, and who it can hand off to. This is the
165
+ * internal record the loop and `AgentDepsFactory` consume; in an app it is authored as an
166
+ * `@Agent`-decorated class and populated into the `AgentRegistry` by discovery (name, base prompt
167
+ * from `@SystemPrompt`, tool allow-list, handoff targets). An orchestrator hands off to others via
168
+ * `ctx.handoff(OtherAgent)`. Model/store/sink/governance are shared from the module.
170
169
  */
171
170
  interface AgentDefinition {
172
171
  name: string;
@@ -174,17 +173,14 @@ interface AgentDefinition {
174
173
  systemPrompt?: string | PromptBuilder;
175
174
  /** Allow-list of tool names this agent may use (subset of all registered tools). */
176
175
  tools?: string[];
177
- /** Names of other agents this agent may delegate to (auto-registered as `agent`-kind tools). */
176
+ /** Names of other agents this agent may hand off to (auto-registered as `agent`-kind tools). */
178
177
  delegatesTo?: string[];
179
- personas?: Persona[];
180
- defaultPersona?: string;
181
178
  modelId?: string;
182
179
  maxSteps?: number;
183
180
  }
184
181
  interface ThreadSummary {
185
182
  id: string;
186
183
  title: string;
187
- persona: string;
188
184
  transient: boolean;
189
185
  createdAt: string;
190
186
  updatedAt: string;
@@ -194,6 +190,8 @@ interface StoredMessage {
194
190
  id: string;
195
191
  role: MessageRole;
196
192
  content: string;
193
+ /** Which agent produced this message (assistant messages) — provenance for replay / UI / telescope. */
194
+ agentName?: string;
197
195
  toolCalls?: ToolCallRequest[];
198
196
  toolResults?: ToolResult[];
199
197
  followUps?: string[];
@@ -242,6 +240,8 @@ declare const AGENT_RETRIEVER: unique symbol;
242
240
  /** The embedding provider (`EmbeddingProvider`) — text→vector for retrieval + ingestion. */
243
241
  declare const AGENT_EMBEDDING_PROVIDER: unique symbol;
244
242
  declare const AGENT_DEPS_FACTORY: unique symbol;
243
+ /** App-wide, ordered `@SystemPromptContributor()` functions the loop appends after the agent base. */
244
+ declare const AGENT_PROMPT_CONTRIBUTORS: unique symbol;
245
245
 
246
246
  /**
247
247
  * Per-invocation context handed to a tool handler. Host-supplied bits are optional. Identity lives
@@ -253,7 +253,8 @@ interface AiToolCtx {
253
253
  threadId: string;
254
254
  runId: string;
255
255
  requestId: string;
256
- persona?: Persona;
256
+ /** The name of the agent running this turn — provenance a tool can scope on (e.g. capability sets). */
257
+ agentName?: string;
257
258
  pageContext?: PageContext;
258
259
  /** Optional host handle (e.g. an ORM EntityManager) the app threads through options. */
259
260
  host?: unknown;
@@ -348,7 +349,6 @@ interface ModelProvider {
348
349
 
349
350
  interface CreateThreadInput {
350
351
  actor: Actor;
351
- persona: string;
352
352
  transient?: boolean;
353
353
  title?: string;
354
354
  }
@@ -356,7 +356,8 @@ interface AppendMessageInput {
356
356
  threadId: string;
357
357
  role: StoredMessage['role'];
358
358
  content: string;
359
- persona?: string;
359
+ /** Which agent produced this message (assistant messages) — provenance. */
360
+ agentName?: string;
360
361
  toolCalls?: ToolCallRequest[];
361
362
  toolResults?: ToolResult[];
362
363
  followUps?: string[];
@@ -646,8 +647,8 @@ interface AgentGovernanceQueries {
646
647
 
647
648
  /** First filter layer: drop tools the actor's role may not invoke. `can` may be async (authz). */
648
649
  declare function filterToolsByRole(tools: ToolSpec[], actor: Actor, policy: RolesPolicy): Promise<ToolSpec[]>;
649
- /** Second filter layer: if the persona pins an allow-list, keep only those tool names. */
650
- declare function personaFilterTools(tools: ToolSpec[], allowedTools: string[] | undefined): ToolSpec[];
650
+ /** Second filter layer: if the agent pins an allow-list, keep only those tool names. */
651
+ declare function filterToolsByAllowList(tools: ToolSpec[], allowedTools: string[] | undefined): ToolSpec[];
651
652
 
652
653
  /** Holds the named agent definitions registered via `AgentModule.forFeature([...])`. */
653
654
  declare class AgentRegistry {
@@ -687,7 +688,7 @@ declare class ToolRegistry {
687
688
  has(name: string): boolean;
688
689
  spec(name: string): ToolSpec | undefined;
689
690
  allSpecs(): ToolSpec[];
690
- /** The tools to offer the model for this actor+persona, after the two filter layers. */
691
+ /** The tools to offer the model for this actor+agent, after the two filter layers. */
691
692
  definitionsFor(actor: Actor, policy: RolesPolicy, allowedTools?: string[]): Promise<ToolDefinition[]>;
692
693
  /** Run a tool. Re-checks the role (defense-in-depth) and re-parses the input via Zod. */
693
694
  invoke(name: string, input: unknown, ctx: AiToolCtx, policy: RolesPolicy): Promise<unknown>;
@@ -714,10 +715,16 @@ interface AgentLoopDeps {
714
715
  day: string;
715
716
  /** The agent's base prompt. A flat string, or a {@link PromptBuilder} resolved per turn. */
716
717
  systemPrompt: string | PromptBuilder;
718
+ /**
719
+ * Cross-agent system-prompt contributors, applied in order AFTER the agent's base prompt. Each
720
+ * returns a section to append (or `null` to skip this turn). The app registers them via
721
+ * `@SystemPromptContributor()`; the loop composes base + contributors into the effective prompt.
722
+ */
723
+ promptContributors?: PromptContributor[];
717
724
  maxSteps?: number;
718
725
  /** Optional host handle threaded to tool ctx (e.g. an ORM EntityManager). */
719
726
  host?: unknown;
720
- /** Agent-level tool allow-list (intersected with the persona's). Undefined → all tools. */
727
+ /** Agent-level tool allow-list. Undefined → all tools (after role filtering). */
721
728
  toolAllowList?: string[];
722
729
  /**
723
730
  * Per-tool execution timeout in ms. A tool that runs longer is aborted and recorded as failed
@@ -777,7 +784,8 @@ interface AgentRunStarted {
777
784
  runId: string;
778
785
  threadId: string;
779
786
  actorId: string;
780
- persona?: string;
787
+ /** Which agent is handling the run. */
788
+ agentName?: string;
781
789
  }
782
790
  interface AgentMessageEvent {
783
791
  runId: string;
@@ -845,4 +853,4 @@ declare function publishAgentRunFailed(payload: AgentRunFailed): void;
845
853
  declare function publishAgentDelegated(payload: AgentDelegated): void;
846
854
  declare function publishAgentRetrieved(payload: AgentRetrieved): void;
847
855
 
848
- export { AGENT_ACTOR_RESOLVER, AGENT_DEPS_FACTORY, AGENT_DURABLE_RUNNER, AGENT_EMBEDDING_PROVIDER, AGENT_GOVERNANCE_QUERIES, AGENT_MODEL, AGENT_OPTIONS, AGENT_PRICING_STORE, AGENT_QUOTA_STORE, AGENT_REGISTRY, AGENT_RETRIEVER, AGENT_ROLES_POLICY, AGENT_RUNNER, AGENT_SINK, AGENT_STORE, AGENT_TOOL_REGISTRY, type Actor, type ActorResolver, type ActorSpendRow, type AgentDefinition, type AgentDelegated, type AgentGovernanceQueries, type AgentLoopDeps, type AgentLoopHooks, type AgentMessageEvent, type AgentPricingStore, type AgentQuotaExceeded, AgentRegistry, type AgentRetrieved, type AgentRunFailed, type AgentRunFinished, type AgentRunInput, type AgentRunStarted, type AgentRunner, type AgentStore, AgentStreamError, type AgentToolCallEvent, type AiToolCtx, type AppendMessageInput, type CreateThreadInput, type CurrentModelPrice, type Decision, DefaultRolesPolicy, type EmbeddingProvider, type GovernanceRange, type MessageRole, type MessageUsage, type ModelMessage, type ModelPriceInput, type ModelProvider, type ModelSpendRow, type ModelTurnArgs, type ModelTurnResult, type PageContext, type Passage, type Persona, type PromptBuilder, type PromptContext, QuotaExceededError, type QuotaState, type QuotaStore, type RecordToolCallInput, type RecordUsageInput, type RerankOptions, type Reranker, type RetrieveOptions, type Retriever, type RolesPolicy, type SinkWriter, type StoredMessage, type StreamError, type ThreadActivityRow, type ThreadDetail, type ThreadSummary, type TokenStreamSink, type ToolCallActivityRow, type ToolCallRequest, type ToolCallStatus, type ToolDefinition, ToolForbiddenError, type ToolHandler, ToolInputInvalidError, type ToolKind, ToolNotFoundError, ToolRegistry, type ToolResult, type ToolSpec, type UpdateToolCallInput, type UsagePurpose, type UsageTrendPoint, filterToolsByRole, personaFilterTools, publishAgentDelegated, publishAgentMessage, publishAgentQuotaExceeded, publishAgentRetrieved, publishAgentRunFailed, publishAgentRunFinished, publishAgentRunStarted, publishAgentToolCall, runAgentLoop, seedModelPrices };
856
+ export { AGENT_ACTOR_RESOLVER, AGENT_DEPS_FACTORY, AGENT_DURABLE_RUNNER, AGENT_EMBEDDING_PROVIDER, AGENT_GOVERNANCE_QUERIES, AGENT_MODEL, AGENT_OPTIONS, AGENT_PRICING_STORE, AGENT_PROMPT_CONTRIBUTORS, AGENT_QUOTA_STORE, AGENT_REGISTRY, AGENT_RETRIEVER, AGENT_ROLES_POLICY, AGENT_RUNNER, AGENT_SINK, AGENT_STORE, AGENT_TOOL_REGISTRY, type Actor, type ActorResolver, type ActorSpendRow, type AgentDefinition, type AgentDelegated, type AgentGovernanceQueries, type AgentLoopDeps, type AgentLoopHooks, type AgentMessageEvent, type AgentPricingStore, type AgentQuotaExceeded, AgentRegistry, type AgentRetrieved, type AgentRunFailed, type AgentRunFinished, type AgentRunInput, type AgentRunStarted, type AgentRunner, type AgentStore, AgentStreamError, type AgentToolCallEvent, type AiToolCtx, type AppendMessageInput, type CreateThreadInput, type CurrentModelPrice, type Decision, DefaultRolesPolicy, type EmbeddingProvider, type GovernanceRange, type MessageRole, type MessageUsage, type ModelMessage, type ModelPriceInput, type ModelProvider, type ModelSpendRow, type ModelTurnArgs, type ModelTurnResult, type PageContext, type Passage, type PromptBuilder, type PromptContext, type PromptContributor, QuotaExceededError, type QuotaState, type QuotaStore, type RecordToolCallInput, type RecordUsageInput, type RerankOptions, type Reranker, type RetrieveOptions, type Retriever, type RolesPolicy, type SinkWriter, type StoredMessage, type StreamError, type ThreadActivityRow, type ThreadDetail, type ThreadSummary, type TokenStreamSink, type ToolCallActivityRow, type ToolCallRequest, type ToolCallStatus, type ToolDefinition, ToolForbiddenError, type ToolHandler, ToolInputInvalidError, type ToolKind, ToolNotFoundError, ToolRegistry, type ToolResult, type ToolSpec, type UpdateToolCallInput, type UsagePurpose, type UsageTrendPoint, filterToolsByAllowList, filterToolsByRole, publishAgentDelegated, publishAgentMessage, publishAgentQuotaExceeded, publishAgentRetrieved, publishAgentRunFailed, publishAgentRunFinished, publishAgentRunStarted, publishAgentToolCall, runAgentLoop, seedModelPrices };
package/dist/index.js CHANGED
@@ -18,6 +18,7 @@ var AGENT_PRICING_STORE = Symbol.for("@dudousxd/nestjs-agent:pricing-store");
18
18
  var AGENT_RETRIEVER = Symbol.for("@dudousxd/nestjs-agent:retriever");
19
19
  var AGENT_EMBEDDING_PROVIDER = Symbol.for("@dudousxd/nestjs-agent:embedding-provider");
20
20
  var AGENT_DEPS_FACTORY = Symbol.for("@dudousxd/nestjs-agent:deps-factory");
21
+ var AGENT_PROMPT_CONTRIBUTORS = Symbol.for("@dudousxd/nestjs-agent:prompt-contributors");
21
22
 
22
23
  // src/spi/token-stream-sink.ts
23
24
  var AgentStreamError = class extends Error {
@@ -40,7 +41,7 @@ async function seedModelPrices(store, prices) {
40
41
  }
41
42
  __name(seedModelPrices, "seedModelPrices");
42
43
 
43
- // src/personas.ts
44
+ // src/tool-filters.ts
44
45
  async function filterToolsByRole(tools, actor, policy) {
45
46
  const checked = await Promise.all(tools.map(async (tool) => ({
46
47
  tool,
@@ -49,14 +50,14 @@ async function filterToolsByRole(tools, actor, policy) {
49
50
  return checked.filter((entry) => entry.allowed).map((entry) => entry.tool);
50
51
  }
51
52
  __name(filterToolsByRole, "filterToolsByRole");
52
- function personaFilterTools(tools, allowedTools) {
53
+ function filterToolsByAllowList(tools, allowedTools) {
53
54
  if (allowedTools === void 0) {
54
55
  return tools;
55
56
  }
56
57
  const allowed = new Set(allowedTools);
57
58
  return tools.filter((tool) => allowed.has(tool.name));
58
59
  }
59
- __name(personaFilterTools, "personaFilterTools");
60
+ __name(filterToolsByAllowList, "filterToolsByAllowList");
60
61
 
61
62
  // src/agent-registry.ts
62
63
  var AgentRegistry = class {
@@ -134,11 +135,11 @@ var ToolRegistry = class {
134
135
  ...this.entries.values()
135
136
  ].map((entry) => entry.spec);
136
137
  }
137
- /** The tools to offer the model for this actor+persona, after the two filter layers. */
138
+ /** The tools to offer the model for this actor+agent, after the two filter layers. */
138
139
  async definitionsFor(actor, policy, allowedTools) {
139
140
  const roleScoped = await filterToolsByRole(this.allSpecs(), actor, policy);
140
- const personaScoped = personaFilterTools(roleScoped, allowedTools);
141
- return personaScoped.map((spec) => ({
141
+ const allowScoped = filterToolsByAllowList(roleScoped, allowedTools);
142
+ return allowScoped.map((spec) => ({
142
143
  name: spec.name,
143
144
  kind: spec.kind,
144
145
  description: spec.description,
@@ -224,17 +225,6 @@ ${items}
224
225
  Use the retrieved context above to answer when relevant, and cite sources by their bracket number.`;
225
226
  }
226
227
  __name(buildContextBlock, "buildContextBlock");
227
- function intersectAllow(a, b) {
228
- if (a === void 0) {
229
- return b;
230
- }
231
- if (b === void 0) {
232
- return a;
233
- }
234
- const second = new Set(b);
235
- return a.filter((name) => second.has(name));
236
- }
237
- __name(intersectAllow, "intersectAllow");
238
228
  var QuotaExceededError = class extends Error {
239
229
  static {
240
230
  __name(this, "QuotaExceededError");
@@ -250,26 +240,23 @@ async function resolvePrompt(prompt, ctx) {
250
240
  }
251
241
  __name(resolvePrompt, "resolvePrompt");
252
242
  async function resolveSystemPrompt(deps, input) {
253
- const base = {
243
+ const ctx = {
254
244
  actor: input.actor,
255
- ...input.persona !== void 0 ? {
256
- persona: input.persona
257
- } : {},
245
+ agentName: input.agentName ?? "default",
258
246
  ...input.pageContext !== void 0 ? {
259
247
  pageContext: input.pageContext
260
248
  } : {}
261
249
  };
262
- const basePrompt = await resolvePrompt(deps.systemPrompt, {
263
- ...base,
264
- basePrompt: ""
265
- });
266
- if (input.persona === void 0) {
267
- return basePrompt;
250
+ const sections = [
251
+ await resolvePrompt(deps.systemPrompt, ctx)
252
+ ];
253
+ for (const contribute of deps.promptContributors ?? []) {
254
+ const section = await contribute(ctx);
255
+ if (section !== null && section.length > 0) {
256
+ sections.push(section);
257
+ }
268
258
  }
269
- return resolvePrompt(input.persona.systemPrompt, {
270
- ...base,
271
- basePrompt
272
- });
259
+ return sections.join("\n\n");
273
260
  }
274
261
  __name(resolveSystemPrompt, "resolveSystemPrompt");
275
262
  function extractTask(input) {
@@ -347,7 +334,6 @@ async function generateFollowUps(model, messages, count) {
347
334
  __name(generateFollowUps, "generateFollowUps");
348
335
  async function runAgentLoop(deps, input, hooks) {
349
336
  const maxSteps = deps.maxSteps ?? 8;
350
- const persona = input.persona;
351
337
  let system = await resolveSystemPrompt(deps, input);
352
338
  if (deps.quota !== void 0) {
353
339
  const quota = deps.quota;
@@ -381,10 +367,7 @@ async function runAgentLoop(deps, input, hooks) {
381
367
  await hooks.step("persist:user", () => deps.store.appendMessage({
382
368
  threadId: input.threadId,
383
369
  role: "user",
384
- content: input.userText,
385
- ...persona !== void 0 ? {
386
- persona: persona.id
387
- } : {}
370
+ content: input.userText
388
371
  }));
389
372
  }
390
373
  const thread = await hooks.step("load:thread", () => deps.store.getThread(input.threadId));
@@ -407,8 +390,8 @@ async function runAgentLoop(deps, input, hooks) {
407
390
  runId: hooks.runId,
408
391
  threadId: input.threadId,
409
392
  actorId: input.actor.id,
410
- ...persona !== void 0 ? {
411
- persona: persona.id
393
+ ...input.agentName !== void 0 ? {
394
+ agentName: input.agentName
412
395
  } : {}
413
396
  });
414
397
  let injectedPassages;
@@ -430,7 +413,7 @@ ${buildContextBlock(passages)}`;
430
413
  });
431
414
  }
432
415
  for (let i = 0; i < maxSteps; i += 1) {
433
- const tools = await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, intersectAllow(persona?.allowedTools, deps.toolAllowList));
416
+ const tools = await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList);
434
417
  const turn = await hooks.step(`llm:${i}`, () => deps.model.runTurn({
435
418
  system,
436
419
  messages: modelMessages,
@@ -490,8 +473,8 @@ ${buildContextBlock(passages)}`;
490
473
  role: "assistant",
491
474
  content: turn.text,
492
475
  usage: turn.usage,
493
- ...persona !== void 0 ? {
494
- persona: persona.id
476
+ ...input.agentName !== void 0 ? {
477
+ agentName: input.agentName
495
478
  } : {},
496
479
  ...turn.toolCalls.length > 0 ? {
497
480
  toolCalls: turn.toolCalls
@@ -542,8 +525,8 @@ ${buildContextBlock(passages)}`;
542
525
  threadId: input.threadId,
543
526
  runId: hooks.runId,
544
527
  requestId: hooks.runId,
545
- ...persona !== void 0 ? {
546
- persona
528
+ ...input.agentName !== void 0 ? {
529
+ agentName: input.agentName
547
530
  } : {},
548
531
  ...input.pageContext !== void 0 ? {
549
532
  pageContext: input.pageContext
@@ -721,6 +704,7 @@ export {
721
704
  AGENT_MODEL,
722
705
  AGENT_OPTIONS,
723
706
  AGENT_PRICING_STORE,
707
+ AGENT_PROMPT_CONTRIBUTORS,
724
708
  AGENT_QUOTA_STORE,
725
709
  AGENT_REGISTRY,
726
710
  AGENT_RETRIEVER,
@@ -737,8 +721,8 @@ export {
737
721
  ToolInputInvalidError,
738
722
  ToolNotFoundError,
739
723
  ToolRegistry,
724
+ filterToolsByAllowList,
740
725
  filterToolsByRole,
741
- personaFilterTools,
742
726
  publishAgentDelegated,
743
727
  publishAgentMessage,
744
728
  publishAgentQuotaExceeded,