@dudousxd/nestjs-agent-core 0.1.0 → 0.3.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.cjs +30 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -34
- package/dist/index.d.ts +66 -34
- package/dist/index.js +28 -44
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -89,6 +89,18 @@ interface QuotaState {
|
|
|
89
89
|
limitTokens: number;
|
|
90
90
|
withinLimit: boolean;
|
|
91
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* The read-model the quota-today endpoint returns to a client — a superset of {@link QuotaState}
|
|
94
|
+
* for rendering a usage badge. `limitTokens` is `null` when no quota is configured (unlimited, so
|
|
95
|
+
* `withinLimit` is always true); `costUsd` is the day's summed provider-reported USD spend (`0`
|
|
96
|
+
* when only tokens were reported).
|
|
97
|
+
*/
|
|
98
|
+
interface QuotaView {
|
|
99
|
+
usedTokens: number;
|
|
100
|
+
limitTokens: number | null;
|
|
101
|
+
withinLimit: boolean;
|
|
102
|
+
costUsd: number;
|
|
103
|
+
}
|
|
92
104
|
/** A human decision on a pending action tool call. */
|
|
93
105
|
interface Decision {
|
|
94
106
|
approved: boolean;
|
|
@@ -107,37 +119,35 @@ interface PageContext {
|
|
|
107
119
|
[key: string]: unknown;
|
|
108
120
|
}
|
|
109
121
|
/**
|
|
110
|
-
* Inputs a {@link PromptBuilder} may use to compose the
|
|
111
|
-
*
|
|
112
|
-
*
|
|
122
|
+
* Inputs a {@link PromptBuilder} or {@link PromptContributor} may use to compose the system prompt
|
|
123
|
+
* for a turn. Resolved once per turn from stable inputs (actor / agent / pageContext) so it stays
|
|
124
|
+
* replay-safe.
|
|
113
125
|
*/
|
|
114
126
|
interface PromptContext {
|
|
115
127
|
actor: Actor;
|
|
116
|
-
|
|
128
|
+
/** The selected agent's name. */
|
|
129
|
+
agentName: string;
|
|
117
130
|
pageContext?: PageContext;
|
|
118
|
-
basePrompt: string;
|
|
119
131
|
}
|
|
120
132
|
/**
|
|
121
|
-
*
|
|
122
|
-
* e.g. injecting the actor, the current page, or a data-shape description.
|
|
123
|
-
*
|
|
133
|
+
* An agent's base system prompt. Return a string (optionally async) built from the turn's context —
|
|
134
|
+
* e.g. injecting the actor, the current page, or a data-shape description. Set on an `@Agent` class
|
|
135
|
+
* via a `@SystemPrompt()` method (or a flat string).
|
|
124
136
|
*/
|
|
125
137
|
type PromptBuilder = (ctx: PromptContext) => string | Promise<string>;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
138
|
+
/**
|
|
139
|
+
* A cross-agent system-prompt contributor. Returns an ordered section to APPEND to the composed
|
|
140
|
+
* prompt (after the agent's base), or `null` to contribute nothing this turn — so conditional
|
|
141
|
+
* sections (base-scope, a mentions legend, schema hints) stay clean when they don't apply.
|
|
142
|
+
* Registered app-wide via `@SystemPromptContributor()`; the loop runs every contributor in order.
|
|
143
|
+
*/
|
|
144
|
+
type PromptContributor = (ctx: PromptContext) => string | null | Promise<string | null>;
|
|
134
145
|
/** Everything needed to run one agent turn. */
|
|
135
146
|
interface AgentRunInput {
|
|
136
147
|
threadId: string;
|
|
137
148
|
actor: Actor;
|
|
138
149
|
/** The latest user message text. */
|
|
139
150
|
userText: string;
|
|
140
|
-
persona?: Persona;
|
|
141
151
|
pageContext?: PageContext;
|
|
142
152
|
/** YYYY-MM-DD stamped by the runner so quota/day stays deterministic under durable replay. */
|
|
143
153
|
day?: string;
|
|
@@ -163,10 +173,11 @@ interface AgentRunInput {
|
|
|
163
173
|
regenerate?: boolean;
|
|
164
174
|
}
|
|
165
175
|
/**
|
|
166
|
-
* A named agent: its prompt, the tools it may use, and
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
176
|
+
* A named agent: its prompt, the tools it may use, and who it can hand off to. This is the
|
|
177
|
+
* internal record the loop and `AgentDepsFactory` consume; in an app it is authored as an
|
|
178
|
+
* `@Agent`-decorated class and populated into the `AgentRegistry` by discovery (name, base prompt
|
|
179
|
+
* from `@SystemPrompt`, tool allow-list, handoff targets). An orchestrator hands off to others via
|
|
180
|
+
* `ctx.handoff(OtherAgent)`. Model/store/sink/governance are shared from the module.
|
|
170
181
|
*/
|
|
171
182
|
interface AgentDefinition {
|
|
172
183
|
name: string;
|
|
@@ -174,17 +185,14 @@ interface AgentDefinition {
|
|
|
174
185
|
systemPrompt?: string | PromptBuilder;
|
|
175
186
|
/** Allow-list of tool names this agent may use (subset of all registered tools). */
|
|
176
187
|
tools?: string[];
|
|
177
|
-
/** Names of other agents this agent may
|
|
188
|
+
/** Names of other agents this agent may hand off to (auto-registered as `agent`-kind tools). */
|
|
178
189
|
delegatesTo?: string[];
|
|
179
|
-
personas?: Persona[];
|
|
180
|
-
defaultPersona?: string;
|
|
181
190
|
modelId?: string;
|
|
182
191
|
maxSteps?: number;
|
|
183
192
|
}
|
|
184
193
|
interface ThreadSummary {
|
|
185
194
|
id: string;
|
|
186
195
|
title: string;
|
|
187
|
-
persona: string;
|
|
188
196
|
transient: boolean;
|
|
189
197
|
createdAt: string;
|
|
190
198
|
updatedAt: string;
|
|
@@ -194,6 +202,8 @@ interface StoredMessage {
|
|
|
194
202
|
id: string;
|
|
195
203
|
role: MessageRole;
|
|
196
204
|
content: string;
|
|
205
|
+
/** Which agent produced this message (assistant messages) — provenance for replay / UI / telescope. */
|
|
206
|
+
agentName?: string;
|
|
197
207
|
toolCalls?: ToolCallRequest[];
|
|
198
208
|
toolResults?: ToolResult[];
|
|
199
209
|
followUps?: string[];
|
|
@@ -242,6 +252,8 @@ declare const AGENT_RETRIEVER: unique symbol;
|
|
|
242
252
|
/** The embedding provider (`EmbeddingProvider`) — text→vector for retrieval + ingestion. */
|
|
243
253
|
declare const AGENT_EMBEDDING_PROVIDER: unique symbol;
|
|
244
254
|
declare const AGENT_DEPS_FACTORY: unique symbol;
|
|
255
|
+
/** App-wide, ordered `@SystemPromptContributor()` functions the loop appends after the agent base. */
|
|
256
|
+
declare const AGENT_PROMPT_CONTRIBUTORS: unique symbol;
|
|
245
257
|
|
|
246
258
|
/**
|
|
247
259
|
* Per-invocation context handed to a tool handler. Host-supplied bits are optional. Identity lives
|
|
@@ -253,7 +265,8 @@ interface AiToolCtx {
|
|
|
253
265
|
threadId: string;
|
|
254
266
|
runId: string;
|
|
255
267
|
requestId: string;
|
|
256
|
-
|
|
268
|
+
/** The name of the agent running this turn — provenance a tool can scope on (e.g. capability sets). */
|
|
269
|
+
agentName?: string;
|
|
257
270
|
pageContext?: PageContext;
|
|
258
271
|
/** Optional host handle (e.g. an ORM EntityManager) the app threads through options. */
|
|
259
272
|
host?: unknown;
|
|
@@ -348,7 +361,6 @@ interface ModelProvider {
|
|
|
348
361
|
|
|
349
362
|
interface CreateThreadInput {
|
|
350
363
|
actor: Actor;
|
|
351
|
-
persona: string;
|
|
352
364
|
transient?: boolean;
|
|
353
365
|
title?: string;
|
|
354
366
|
}
|
|
@@ -356,7 +368,8 @@ interface AppendMessageInput {
|
|
|
356
368
|
threadId: string;
|
|
357
369
|
role: StoredMessage['role'];
|
|
358
370
|
content: string;
|
|
359
|
-
|
|
371
|
+
/** Which agent produced this message (assistant messages) — provenance. */
|
|
372
|
+
agentName?: string;
|
|
360
373
|
toolCalls?: ToolCallRequest[];
|
|
361
374
|
toolResults?: ToolResult[];
|
|
362
375
|
followUps?: string[];
|
|
@@ -396,6 +409,12 @@ interface AgentStore {
|
|
|
396
409
|
softDeleteThread(threadId: string): Promise<void>;
|
|
397
410
|
forkThread(threadId: string, fromMessageId: string): Promise<ThreadSummary>;
|
|
398
411
|
setTitle(threadId: string, title: string): Promise<void>;
|
|
412
|
+
/**
|
|
413
|
+
* Promote a transient thread to a persistent one so it shows up in {@link listThreads}. A
|
|
414
|
+
* transient thread is a scratch conversation the caller has not chosen to keep; "saving" it
|
|
415
|
+
* clears the flag. Idempotent — promoting an already-persistent thread is a no-op.
|
|
416
|
+
*/
|
|
417
|
+
promoteThread(threadId: string): Promise<void>;
|
|
399
418
|
setActiveStream(threadId: string, runId: string | null): Promise<void>;
|
|
400
419
|
/**
|
|
401
420
|
* The `actorRef` that owns a thread, or `null` if no such thread exists. The authorization seam
|
|
@@ -427,8 +446,14 @@ interface AgentStore {
|
|
|
427
446
|
recordToolCall(input: RecordToolCallInput): Promise<void>;
|
|
428
447
|
updateToolCall(input: UpdateToolCallInput): Promise<void>;
|
|
429
448
|
recordUsage(input: RecordUsageInput): Promise<void>;
|
|
449
|
+
/**
|
|
450
|
+
* The actor's spend for `day` (UTC): total tokens plus the summed provider-reported USD cost.
|
|
451
|
+
* `costUsd` is `0` when no turn on that day reported a cost (token-only providers). Feeds both
|
|
452
|
+
* quota enforcement (via {@link QuotaStore}) and the quota-today view.
|
|
453
|
+
*/
|
|
430
454
|
quotaToday(actorRef: string, day: string): Promise<{
|
|
431
455
|
usedTokens: number;
|
|
456
|
+
costUsd: number;
|
|
432
457
|
}>;
|
|
433
458
|
}
|
|
434
459
|
|
|
@@ -646,8 +671,8 @@ interface AgentGovernanceQueries {
|
|
|
646
671
|
|
|
647
672
|
/** First filter layer: drop tools the actor's role may not invoke. `can` may be async (authz). */
|
|
648
673
|
declare function filterToolsByRole(tools: ToolSpec[], actor: Actor, policy: RolesPolicy): Promise<ToolSpec[]>;
|
|
649
|
-
/** Second filter layer: if the
|
|
650
|
-
declare function
|
|
674
|
+
/** Second filter layer: if the agent pins an allow-list, keep only those tool names. */
|
|
675
|
+
declare function filterToolsByAllowList(tools: ToolSpec[], allowedTools: string[] | undefined): ToolSpec[];
|
|
651
676
|
|
|
652
677
|
/** Holds the named agent definitions registered via `AgentModule.forFeature([...])`. */
|
|
653
678
|
declare class AgentRegistry {
|
|
@@ -687,7 +712,7 @@ declare class ToolRegistry {
|
|
|
687
712
|
has(name: string): boolean;
|
|
688
713
|
spec(name: string): ToolSpec | undefined;
|
|
689
714
|
allSpecs(): ToolSpec[];
|
|
690
|
-
/** The tools to offer the model for this actor+
|
|
715
|
+
/** The tools to offer the model for this actor+agent, after the two filter layers. */
|
|
691
716
|
definitionsFor(actor: Actor, policy: RolesPolicy, allowedTools?: string[]): Promise<ToolDefinition[]>;
|
|
692
717
|
/** Run a tool. Re-checks the role (defense-in-depth) and re-parses the input via Zod. */
|
|
693
718
|
invoke(name: string, input: unknown, ctx: AiToolCtx, policy: RolesPolicy): Promise<unknown>;
|
|
@@ -714,10 +739,16 @@ interface AgentLoopDeps {
|
|
|
714
739
|
day: string;
|
|
715
740
|
/** The agent's base prompt. A flat string, or a {@link PromptBuilder} resolved per turn. */
|
|
716
741
|
systemPrompt: string | PromptBuilder;
|
|
742
|
+
/**
|
|
743
|
+
* Cross-agent system-prompt contributors, applied in order AFTER the agent's base prompt. Each
|
|
744
|
+
* returns a section to append (or `null` to skip this turn). The app registers them via
|
|
745
|
+
* `@SystemPromptContributor()`; the loop composes base + contributors into the effective prompt.
|
|
746
|
+
*/
|
|
747
|
+
promptContributors?: PromptContributor[];
|
|
717
748
|
maxSteps?: number;
|
|
718
749
|
/** Optional host handle threaded to tool ctx (e.g. an ORM EntityManager). */
|
|
719
750
|
host?: unknown;
|
|
720
|
-
/** Agent-level tool allow-list
|
|
751
|
+
/** Agent-level tool allow-list. Undefined → all tools (after role filtering). */
|
|
721
752
|
toolAllowList?: string[];
|
|
722
753
|
/**
|
|
723
754
|
* Per-tool execution timeout in ms. A tool that runs longer is aborted and recorded as failed
|
|
@@ -777,7 +808,8 @@ interface AgentRunStarted {
|
|
|
777
808
|
runId: string;
|
|
778
809
|
threadId: string;
|
|
779
810
|
actorId: string;
|
|
780
|
-
|
|
811
|
+
/** Which agent is handling the run. */
|
|
812
|
+
agentName?: string;
|
|
781
813
|
}
|
|
782
814
|
interface AgentMessageEvent {
|
|
783
815
|
runId: string;
|
|
@@ -845,4 +877,4 @@ declare function publishAgentRunFailed(payload: AgentRunFailed): void;
|
|
|
845
877
|
declare function publishAgentDelegated(payload: AgentDelegated): void;
|
|
846
878
|
declare function publishAgentRetrieved(payload: AgentRetrieved): void;
|
|
847
879
|
|
|
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
|
|
880
|
+
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 QuotaView, 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
|
@@ -89,6 +89,18 @@ interface QuotaState {
|
|
|
89
89
|
limitTokens: number;
|
|
90
90
|
withinLimit: boolean;
|
|
91
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* The read-model the quota-today endpoint returns to a client — a superset of {@link QuotaState}
|
|
94
|
+
* for rendering a usage badge. `limitTokens` is `null` when no quota is configured (unlimited, so
|
|
95
|
+
* `withinLimit` is always true); `costUsd` is the day's summed provider-reported USD spend (`0`
|
|
96
|
+
* when only tokens were reported).
|
|
97
|
+
*/
|
|
98
|
+
interface QuotaView {
|
|
99
|
+
usedTokens: number;
|
|
100
|
+
limitTokens: number | null;
|
|
101
|
+
withinLimit: boolean;
|
|
102
|
+
costUsd: number;
|
|
103
|
+
}
|
|
92
104
|
/** A human decision on a pending action tool call. */
|
|
93
105
|
interface Decision {
|
|
94
106
|
approved: boolean;
|
|
@@ -107,37 +119,35 @@ interface PageContext {
|
|
|
107
119
|
[key: string]: unknown;
|
|
108
120
|
}
|
|
109
121
|
/**
|
|
110
|
-
* Inputs a {@link PromptBuilder} may use to compose the
|
|
111
|
-
*
|
|
112
|
-
*
|
|
122
|
+
* Inputs a {@link PromptBuilder} or {@link PromptContributor} may use to compose the system prompt
|
|
123
|
+
* for a turn. Resolved once per turn from stable inputs (actor / agent / pageContext) so it stays
|
|
124
|
+
* replay-safe.
|
|
113
125
|
*/
|
|
114
126
|
interface PromptContext {
|
|
115
127
|
actor: Actor;
|
|
116
|
-
|
|
128
|
+
/** The selected agent's name. */
|
|
129
|
+
agentName: string;
|
|
117
130
|
pageContext?: PageContext;
|
|
118
|
-
basePrompt: string;
|
|
119
131
|
}
|
|
120
132
|
/**
|
|
121
|
-
*
|
|
122
|
-
* e.g. injecting the actor, the current page, or a data-shape description.
|
|
123
|
-
*
|
|
133
|
+
* An agent's base system prompt. Return a string (optionally async) built from the turn's context —
|
|
134
|
+
* e.g. injecting the actor, the current page, or a data-shape description. Set on an `@Agent` class
|
|
135
|
+
* via a `@SystemPrompt()` method (or a flat string).
|
|
124
136
|
*/
|
|
125
137
|
type PromptBuilder = (ctx: PromptContext) => string | Promise<string>;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
138
|
+
/**
|
|
139
|
+
* A cross-agent system-prompt contributor. Returns an ordered section to APPEND to the composed
|
|
140
|
+
* prompt (after the agent's base), or `null` to contribute nothing this turn — so conditional
|
|
141
|
+
* sections (base-scope, a mentions legend, schema hints) stay clean when they don't apply.
|
|
142
|
+
* Registered app-wide via `@SystemPromptContributor()`; the loop runs every contributor in order.
|
|
143
|
+
*/
|
|
144
|
+
type PromptContributor = (ctx: PromptContext) => string | null | Promise<string | null>;
|
|
134
145
|
/** Everything needed to run one agent turn. */
|
|
135
146
|
interface AgentRunInput {
|
|
136
147
|
threadId: string;
|
|
137
148
|
actor: Actor;
|
|
138
149
|
/** The latest user message text. */
|
|
139
150
|
userText: string;
|
|
140
|
-
persona?: Persona;
|
|
141
151
|
pageContext?: PageContext;
|
|
142
152
|
/** YYYY-MM-DD stamped by the runner so quota/day stays deterministic under durable replay. */
|
|
143
153
|
day?: string;
|
|
@@ -163,10 +173,11 @@ interface AgentRunInput {
|
|
|
163
173
|
regenerate?: boolean;
|
|
164
174
|
}
|
|
165
175
|
/**
|
|
166
|
-
* A named agent: its prompt, the tools it may use, and
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
176
|
+
* A named agent: its prompt, the tools it may use, and who it can hand off to. This is the
|
|
177
|
+
* internal record the loop and `AgentDepsFactory` consume; in an app it is authored as an
|
|
178
|
+
* `@Agent`-decorated class and populated into the `AgentRegistry` by discovery (name, base prompt
|
|
179
|
+
* from `@SystemPrompt`, tool allow-list, handoff targets). An orchestrator hands off to others via
|
|
180
|
+
* `ctx.handoff(OtherAgent)`. Model/store/sink/governance are shared from the module.
|
|
170
181
|
*/
|
|
171
182
|
interface AgentDefinition {
|
|
172
183
|
name: string;
|
|
@@ -174,17 +185,14 @@ interface AgentDefinition {
|
|
|
174
185
|
systemPrompt?: string | PromptBuilder;
|
|
175
186
|
/** Allow-list of tool names this agent may use (subset of all registered tools). */
|
|
176
187
|
tools?: string[];
|
|
177
|
-
/** Names of other agents this agent may
|
|
188
|
+
/** Names of other agents this agent may hand off to (auto-registered as `agent`-kind tools). */
|
|
178
189
|
delegatesTo?: string[];
|
|
179
|
-
personas?: Persona[];
|
|
180
|
-
defaultPersona?: string;
|
|
181
190
|
modelId?: string;
|
|
182
191
|
maxSteps?: number;
|
|
183
192
|
}
|
|
184
193
|
interface ThreadSummary {
|
|
185
194
|
id: string;
|
|
186
195
|
title: string;
|
|
187
|
-
persona: string;
|
|
188
196
|
transient: boolean;
|
|
189
197
|
createdAt: string;
|
|
190
198
|
updatedAt: string;
|
|
@@ -194,6 +202,8 @@ interface StoredMessage {
|
|
|
194
202
|
id: string;
|
|
195
203
|
role: MessageRole;
|
|
196
204
|
content: string;
|
|
205
|
+
/** Which agent produced this message (assistant messages) — provenance for replay / UI / telescope. */
|
|
206
|
+
agentName?: string;
|
|
197
207
|
toolCalls?: ToolCallRequest[];
|
|
198
208
|
toolResults?: ToolResult[];
|
|
199
209
|
followUps?: string[];
|
|
@@ -242,6 +252,8 @@ declare const AGENT_RETRIEVER: unique symbol;
|
|
|
242
252
|
/** The embedding provider (`EmbeddingProvider`) — text→vector for retrieval + ingestion. */
|
|
243
253
|
declare const AGENT_EMBEDDING_PROVIDER: unique symbol;
|
|
244
254
|
declare const AGENT_DEPS_FACTORY: unique symbol;
|
|
255
|
+
/** App-wide, ordered `@SystemPromptContributor()` functions the loop appends after the agent base. */
|
|
256
|
+
declare const AGENT_PROMPT_CONTRIBUTORS: unique symbol;
|
|
245
257
|
|
|
246
258
|
/**
|
|
247
259
|
* Per-invocation context handed to a tool handler. Host-supplied bits are optional. Identity lives
|
|
@@ -253,7 +265,8 @@ interface AiToolCtx {
|
|
|
253
265
|
threadId: string;
|
|
254
266
|
runId: string;
|
|
255
267
|
requestId: string;
|
|
256
|
-
|
|
268
|
+
/** The name of the agent running this turn — provenance a tool can scope on (e.g. capability sets). */
|
|
269
|
+
agentName?: string;
|
|
257
270
|
pageContext?: PageContext;
|
|
258
271
|
/** Optional host handle (e.g. an ORM EntityManager) the app threads through options. */
|
|
259
272
|
host?: unknown;
|
|
@@ -348,7 +361,6 @@ interface ModelProvider {
|
|
|
348
361
|
|
|
349
362
|
interface CreateThreadInput {
|
|
350
363
|
actor: Actor;
|
|
351
|
-
persona: string;
|
|
352
364
|
transient?: boolean;
|
|
353
365
|
title?: string;
|
|
354
366
|
}
|
|
@@ -356,7 +368,8 @@ interface AppendMessageInput {
|
|
|
356
368
|
threadId: string;
|
|
357
369
|
role: StoredMessage['role'];
|
|
358
370
|
content: string;
|
|
359
|
-
|
|
371
|
+
/** Which agent produced this message (assistant messages) — provenance. */
|
|
372
|
+
agentName?: string;
|
|
360
373
|
toolCalls?: ToolCallRequest[];
|
|
361
374
|
toolResults?: ToolResult[];
|
|
362
375
|
followUps?: string[];
|
|
@@ -396,6 +409,12 @@ interface AgentStore {
|
|
|
396
409
|
softDeleteThread(threadId: string): Promise<void>;
|
|
397
410
|
forkThread(threadId: string, fromMessageId: string): Promise<ThreadSummary>;
|
|
398
411
|
setTitle(threadId: string, title: string): Promise<void>;
|
|
412
|
+
/**
|
|
413
|
+
* Promote a transient thread to a persistent one so it shows up in {@link listThreads}. A
|
|
414
|
+
* transient thread is a scratch conversation the caller has not chosen to keep; "saving" it
|
|
415
|
+
* clears the flag. Idempotent — promoting an already-persistent thread is a no-op.
|
|
416
|
+
*/
|
|
417
|
+
promoteThread(threadId: string): Promise<void>;
|
|
399
418
|
setActiveStream(threadId: string, runId: string | null): Promise<void>;
|
|
400
419
|
/**
|
|
401
420
|
* The `actorRef` that owns a thread, or `null` if no such thread exists. The authorization seam
|
|
@@ -427,8 +446,14 @@ interface AgentStore {
|
|
|
427
446
|
recordToolCall(input: RecordToolCallInput): Promise<void>;
|
|
428
447
|
updateToolCall(input: UpdateToolCallInput): Promise<void>;
|
|
429
448
|
recordUsage(input: RecordUsageInput): Promise<void>;
|
|
449
|
+
/**
|
|
450
|
+
* The actor's spend for `day` (UTC): total tokens plus the summed provider-reported USD cost.
|
|
451
|
+
* `costUsd` is `0` when no turn on that day reported a cost (token-only providers). Feeds both
|
|
452
|
+
* quota enforcement (via {@link QuotaStore}) and the quota-today view.
|
|
453
|
+
*/
|
|
430
454
|
quotaToday(actorRef: string, day: string): Promise<{
|
|
431
455
|
usedTokens: number;
|
|
456
|
+
costUsd: number;
|
|
432
457
|
}>;
|
|
433
458
|
}
|
|
434
459
|
|
|
@@ -646,8 +671,8 @@ interface AgentGovernanceQueries {
|
|
|
646
671
|
|
|
647
672
|
/** First filter layer: drop tools the actor's role may not invoke. `can` may be async (authz). */
|
|
648
673
|
declare function filterToolsByRole(tools: ToolSpec[], actor: Actor, policy: RolesPolicy): Promise<ToolSpec[]>;
|
|
649
|
-
/** Second filter layer: if the
|
|
650
|
-
declare function
|
|
674
|
+
/** Second filter layer: if the agent pins an allow-list, keep only those tool names. */
|
|
675
|
+
declare function filterToolsByAllowList(tools: ToolSpec[], allowedTools: string[] | undefined): ToolSpec[];
|
|
651
676
|
|
|
652
677
|
/** Holds the named agent definitions registered via `AgentModule.forFeature([...])`. */
|
|
653
678
|
declare class AgentRegistry {
|
|
@@ -687,7 +712,7 @@ declare class ToolRegistry {
|
|
|
687
712
|
has(name: string): boolean;
|
|
688
713
|
spec(name: string): ToolSpec | undefined;
|
|
689
714
|
allSpecs(): ToolSpec[];
|
|
690
|
-
/** The tools to offer the model for this actor+
|
|
715
|
+
/** The tools to offer the model for this actor+agent, after the two filter layers. */
|
|
691
716
|
definitionsFor(actor: Actor, policy: RolesPolicy, allowedTools?: string[]): Promise<ToolDefinition[]>;
|
|
692
717
|
/** Run a tool. Re-checks the role (defense-in-depth) and re-parses the input via Zod. */
|
|
693
718
|
invoke(name: string, input: unknown, ctx: AiToolCtx, policy: RolesPolicy): Promise<unknown>;
|
|
@@ -714,10 +739,16 @@ interface AgentLoopDeps {
|
|
|
714
739
|
day: string;
|
|
715
740
|
/** The agent's base prompt. A flat string, or a {@link PromptBuilder} resolved per turn. */
|
|
716
741
|
systemPrompt: string | PromptBuilder;
|
|
742
|
+
/**
|
|
743
|
+
* Cross-agent system-prompt contributors, applied in order AFTER the agent's base prompt. Each
|
|
744
|
+
* returns a section to append (or `null` to skip this turn). The app registers them via
|
|
745
|
+
* `@SystemPromptContributor()`; the loop composes base + contributors into the effective prompt.
|
|
746
|
+
*/
|
|
747
|
+
promptContributors?: PromptContributor[];
|
|
717
748
|
maxSteps?: number;
|
|
718
749
|
/** Optional host handle threaded to tool ctx (e.g. an ORM EntityManager). */
|
|
719
750
|
host?: unknown;
|
|
720
|
-
/** Agent-level tool allow-list
|
|
751
|
+
/** Agent-level tool allow-list. Undefined → all tools (after role filtering). */
|
|
721
752
|
toolAllowList?: string[];
|
|
722
753
|
/**
|
|
723
754
|
* Per-tool execution timeout in ms. A tool that runs longer is aborted and recorded as failed
|
|
@@ -777,7 +808,8 @@ interface AgentRunStarted {
|
|
|
777
808
|
runId: string;
|
|
778
809
|
threadId: string;
|
|
779
810
|
actorId: string;
|
|
780
|
-
|
|
811
|
+
/** Which agent is handling the run. */
|
|
812
|
+
agentName?: string;
|
|
781
813
|
}
|
|
782
814
|
interface AgentMessageEvent {
|
|
783
815
|
runId: string;
|
|
@@ -845,4 +877,4 @@ declare function publishAgentRunFailed(payload: AgentRunFailed): void;
|
|
|
845
877
|
declare function publishAgentDelegated(payload: AgentDelegated): void;
|
|
846
878
|
declare function publishAgentRetrieved(payload: AgentRetrieved): void;
|
|
847
879
|
|
|
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
|
|
880
|
+
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 QuotaView, 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/
|
|
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
|
|
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(
|
|
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+
|
|
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
|
|
141
|
-
return
|
|
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
|
|
243
|
+
const ctx = {
|
|
254
244
|
actor: input.actor,
|
|
255
|
-
|
|
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
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
|
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
|
-
...
|
|
411
|
-
|
|
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,
|
|
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
|
-
...
|
|
494
|
-
|
|
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
|
-
...
|
|
546
|
-
|
|
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,
|