@dudousxd/nestjs-agent-core 0.4.0 → 0.5.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
@@ -275,6 +275,38 @@ interface ThreadDetail extends ThreadSummary {
275
275
  activeStreamId?: string;
276
276
  }
277
277
  type ToolCallStatus = 'auto_executed' | 'pending_approval' | 'executed' | 'rejected' | 'failed';
278
+ /**
279
+ * Serializable input for a dispatched model-turn step. Carries only data — the serving worker
280
+ * re-resolves the model/sink/registry from its own DI via AGENT_DEPS_FACTORY.forAgent(agentName).
281
+ */
282
+ interface LlmStepEnvelope {
283
+ /** Undefined = default agent (same semantics as {@link AgentRunInput.agentName}). */
284
+ agentName?: string;
285
+ system: string;
286
+ messages: ModelMessage[];
287
+ /** The turn's actor — the handler re-derives tool definitions from it (definitionsFor). */
288
+ actor: Actor;
289
+ }
290
+ /**
291
+ * The serializable subset of `AiToolCtx` — everything except `host` (re-attached handler-side
292
+ * from DI).
293
+ */
294
+ interface ToolStepCtx {
295
+ actor: Actor;
296
+ threadId: string;
297
+ runId: string;
298
+ requestId: string;
299
+ agentName?: string;
300
+ pageContext?: PageContext;
301
+ }
302
+ /** Serializable input for a dispatched tool-execution step. */
303
+ interface ToolStepEnvelope {
304
+ toolName: string;
305
+ input: unknown;
306
+ ctx: ToolStepCtx;
307
+ /** Applied INSIDE the handler (`withToolTimeout`) — never as a durable step `timeoutMs`. */
308
+ timeoutMs?: number;
309
+ }
278
310
 
279
311
  /**
280
312
  * Public, cross-lib-discoverable DI tokens.
@@ -541,6 +573,19 @@ interface RecordUsageInput {
541
573
  /** Provider-reported actual USD cost for this turn, when known (gateways report it). */
542
574
  costUsd?: number;
543
575
  }
576
+ interface RecordRunStartInput {
577
+ runId: string;
578
+ threadId: string;
579
+ actorRef: string;
580
+ agentName?: string;
581
+ }
582
+ interface RecordRunEndInput {
583
+ runId: string;
584
+ status: 'completed' | 'failed';
585
+ durationMs?: number;
586
+ errorCode?: string;
587
+ errorMessage?: string;
588
+ }
544
589
  /** ORM-agnostic persistence. Refs are string ids; adapters may add real relations. */
545
590
  interface AgentStore {
546
591
  createThread(input: CreateThreadInput): Promise<ThreadSummary>;
@@ -570,6 +615,15 @@ interface AgentStore {
570
615
  * Absent on a store that predates this — thread read/list payloads report `activeRunId: null`.
571
616
  */
572
617
  activeRunForThread?(threadId: string): Promise<string | null>;
618
+ /**
619
+ * OPTIONAL: persist the start of a run (turn). Replay-safe: called under a durable localStep.
620
+ * Absent on a store that predates run recording — reliability metrics degrade to zeros/empty.
621
+ */
622
+ recordRunStart?(run: RecordRunStartInput): Promise<void>;
623
+ /** OPTIONAL: settle a run's outcome. `errorCode`/`errorMessage` only when status is 'failed'. */
624
+ recordRunEnd?(end: RecordRunEndInput): Promise<void>;
625
+ /** OPTIONAL: bump the run's llm-step retry counter (dispatched-step attempt > 1). */
626
+ bumpRunRetries?(runId: string): Promise<void>;
573
627
  /**
574
628
  * The `actorRef` that owns a thread, or `null` if no such thread exists. The authorization seam
575
629
  * for thread-scoped endpoints (detail / delete / fork): the service compares this against the
@@ -822,6 +876,52 @@ interface ThreadActivityRow {
822
876
  totalTokens: number;
823
877
  lastActivityAt: string;
824
878
  }
879
+ /** Aggregated run reliability over a range. */
880
+ interface RunMetrics {
881
+ runs: number;
882
+ completed: number;
883
+ failed: number;
884
+ /** completed / runs, 0 when runs = 0. */
885
+ successRate: number;
886
+ /** Total llm-step retries across the range's runs. */
887
+ retries: number;
888
+ durationP50Ms: number | null;
889
+ durationP95Ms: number | null;
890
+ }
891
+ /** Run/failure/retry rollup for one agent over a range. */
892
+ interface RunAgentBreakdownRow {
893
+ /** '(default)' when the run had none. */
894
+ agentName: string;
895
+ runs: number;
896
+ failed: number;
897
+ retries: number;
898
+ }
899
+ /** Failed-run count for one error code over a range. */
900
+ interface RunErrorBreakdownRow {
901
+ errorCode: string;
902
+ count: number;
903
+ }
904
+ /** One point on the daily run/failure trend. */
905
+ interface RunTrendPoint {
906
+ day: string;
907
+ runs: number;
908
+ failed: number;
909
+ }
910
+ /** A recent run for the reliability feed. */
911
+ interface RecentRunRow {
912
+ runId: string;
913
+ threadId: string;
914
+ actorRef: string;
915
+ agentName: string | null;
916
+ /** 'running' | 'completed' | 'failed'. */
917
+ status: string;
918
+ durationMs: number | null;
919
+ errorCode: string | null;
920
+ errorMessage: string | null;
921
+ retries: number;
922
+ /** ISO timestamp. */
923
+ startedAt: string;
924
+ }
825
925
  /**
826
926
  * The governance read-model. Cost is `inputTokens/1e6 * inputPricePer1m + outputTokens/1e6 *
827
927
  * outputPricePer1m` against the current pricing row per model; an unpriced model contributes 0 cost
@@ -835,6 +935,11 @@ interface AgentGovernanceQueries {
835
935
  usageTrend(range: GovernanceRange): Promise<UsageTrendPoint[]>;
836
936
  recentToolCalls(limit: number): Promise<ToolCallActivityRow[]>;
837
937
  recentThreads(limit: number): Promise<ThreadActivityRow[]>;
938
+ runMetrics(range: GovernanceRange): Promise<RunMetrics>;
939
+ runsByAgent(range: GovernanceRange): Promise<RunAgentBreakdownRow[]>;
940
+ runErrors(range: GovernanceRange): Promise<RunErrorBreakdownRow[]>;
941
+ runTrend(range: GovernanceRange): Promise<RunTrendPoint[]>;
942
+ recentRuns(limit: number): Promise<RecentRunRow[]>;
838
943
  }
839
944
 
840
945
  /**
@@ -1066,15 +1171,36 @@ interface AgentLoopHooks {
1066
1171
  text: string;
1067
1172
  }>;
1068
1173
  /**
1069
- * Checkpoint wrapper. Inline = call fn directly; durable = ctx.step(name, fn).
1174
+ * Checkpoint wrapper. Inline = call fn directly; durable = ctx.localStep(name, fn) — the
1175
+ * in-process checkpointed primitive (`name` is a checkpoint identity, not a worker group).
1070
1176
  * EVERY side-effect and control-flow read goes through this so durable replay returns
1071
1177
  * cached results (stable ids, no double-write, no re-streaming).
1072
1178
  */
1073
1179
  step<T>(name: string, fn: () => Promise<T>): Promise<T>;
1180
+ /**
1181
+ * Dispatch the model turn as a routed remote step. When present the loop uses it INSTEAD of
1182
+ * running the model inline under hooks.step. Must resolve to exactly what deps.model.runTurn
1183
+ * resolves. The durable runner enriches the envelope with sink routing (sinkRunId/childSink)
1184
+ * on its side — core stays sink-topology-agnostic.
1185
+ */
1186
+ dispatchLlm?(index: number, envelope: LlmStepEnvelope): Promise<ModelTurnResult>;
1187
+ /**
1188
+ * Dispatch one tool execution as a routed remote step. Replaces ONLY the registry.invoke call
1189
+ * (+ its timeout, applied handler-side); all persist steps around it stay local.
1190
+ */
1191
+ dispatchTool?(call: ToolCallRequest, envelope: ToolStepEnvelope): Promise<unknown>;
1192
+ /**
1193
+ * Recognizes the runner's control-flow signals (durable suspend / continue-as-new) so the loop
1194
+ * rethrows them untouched instead of recording a failure. Inline runners omit it — they have no
1195
+ * control-flow exceptions.
1196
+ */
1197
+ isControlFlowError?(error: unknown): boolean;
1074
1198
  }
1075
1199
  declare class QuotaExceededError extends Error {
1076
1200
  constructor();
1077
1201
  }
1202
+ /** Reject if `work` doesn't settle within `ms`. The underlying work is left to finish on its own. */
1203
+ declare function withToolTimeout<T>(work: Promise<T>, ms: number, toolName: string): Promise<T>;
1078
1204
  /**
1079
1205
  * The provider-agnostic agent turn, reused by both the inline and durable runners.
1080
1206
  * It drives the model→tools→model iteration; the runner supplies the `step`/`awaitApproval`
@@ -1158,4 +1284,4 @@ declare function publishAgentRunFailed(payload: AgentRunFailed): void;
1158
1284
  declare function publishAgentDelegated(payload: AgentDelegated): void;
1159
1285
  declare function publishAgentRetrieved(payload: AgentRetrieved): void;
1160
1286
 
1161
- export { AGENT_ACTOR_DIRECTORY, AGENT_ACTOR_RESOLVER, AGENT_ATTACHMENT_STAGING, 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 ActorDirectory, type ActorResolver, type ActorSpendRow, type AgentCatalogEntry, 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 AgentStreamEvent, type AgentToolCallEvent, type AiToolCtx, type AppendMessageInput, type AttachmentStagingStore, type CostUsage, type CreateThreadInput, type CurrentModelPrice, type Decision, DefaultRolesPolicy, type EmbeddingProvider, type GovernanceRange, type GovernanceUsageInput, type MessageAttachment, type MessageRole, type MessageUsage, type ModelMessage, type ModelPrice, 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 StageAttachmentInput, type StoredMessage, type StreamError, type ThreadActivityRow, type ThreadDetail, type ThreadMeta, type ThreadSpendRow, 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 UpdateThreadInput, type UpdateToolCallInput, type UsagePurpose, type UsageTrendPoint, bucketByActor, bucketByModel, bucketByThread, bucketUsageTrend, dayBoundsUtc, encodeStreamEvent, estimateCost, filterToolsByAllowList, filterToolsByRole, publishAgentDelegated, publishAgentMessage, publishAgentQuotaExceeded, publishAgentRetrieved, publishAgentRunFailed, publishAgentRunFinished, publishAgentRunStarted, publishAgentToolCall, runAgentLoop, seedModelPrices };
1287
+ export { AGENT_ACTOR_DIRECTORY, AGENT_ACTOR_RESOLVER, AGENT_ATTACHMENT_STAGING, 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 ActorDirectory, type ActorResolver, type ActorSpendRow, type AgentCatalogEntry, 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 AgentStreamEvent, type AgentToolCallEvent, type AiToolCtx, type AppendMessageInput, type AttachmentStagingStore, type CostUsage, type CreateThreadInput, type CurrentModelPrice, type Decision, DefaultRolesPolicy, type EmbeddingProvider, type GovernanceRange, type GovernanceUsageInput, type LlmStepEnvelope, type MessageAttachment, type MessageRole, type MessageUsage, type ModelMessage, type ModelPrice, 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 RecentRunRow, type RecordRunEndInput, type RecordRunStartInput, type RecordToolCallInput, type RecordUsageInput, type RerankOptions, type Reranker, type RetrieveOptions, type Retriever, type RolesPolicy, type RunAgentBreakdownRow, type RunErrorBreakdownRow, type RunMetrics, type RunTrendPoint, type SinkWriter, type StageAttachmentInput, type StoredMessage, type StreamError, type ThreadActivityRow, type ThreadDetail, type ThreadMeta, type ThreadSpendRow, 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 ToolStepCtx, type ToolStepEnvelope, type UpdateThreadInput, type UpdateToolCallInput, type UsagePurpose, type UsageTrendPoint, bucketByActor, bucketByModel, bucketByThread, bucketUsageTrend, dayBoundsUtc, encodeStreamEvent, estimateCost, filterToolsByAllowList, filterToolsByRole, publishAgentDelegated, publishAgentMessage, publishAgentQuotaExceeded, publishAgentRetrieved, publishAgentRunFailed, publishAgentRunFinished, publishAgentRunStarted, publishAgentToolCall, runAgentLoop, seedModelPrices, withToolTimeout };
package/dist/index.d.ts CHANGED
@@ -275,6 +275,38 @@ interface ThreadDetail extends ThreadSummary {
275
275
  activeStreamId?: string;
276
276
  }
277
277
  type ToolCallStatus = 'auto_executed' | 'pending_approval' | 'executed' | 'rejected' | 'failed';
278
+ /**
279
+ * Serializable input for a dispatched model-turn step. Carries only data — the serving worker
280
+ * re-resolves the model/sink/registry from its own DI via AGENT_DEPS_FACTORY.forAgent(agentName).
281
+ */
282
+ interface LlmStepEnvelope {
283
+ /** Undefined = default agent (same semantics as {@link AgentRunInput.agentName}). */
284
+ agentName?: string;
285
+ system: string;
286
+ messages: ModelMessage[];
287
+ /** The turn's actor — the handler re-derives tool definitions from it (definitionsFor). */
288
+ actor: Actor;
289
+ }
290
+ /**
291
+ * The serializable subset of `AiToolCtx` — everything except `host` (re-attached handler-side
292
+ * from DI).
293
+ */
294
+ interface ToolStepCtx {
295
+ actor: Actor;
296
+ threadId: string;
297
+ runId: string;
298
+ requestId: string;
299
+ agentName?: string;
300
+ pageContext?: PageContext;
301
+ }
302
+ /** Serializable input for a dispatched tool-execution step. */
303
+ interface ToolStepEnvelope {
304
+ toolName: string;
305
+ input: unknown;
306
+ ctx: ToolStepCtx;
307
+ /** Applied INSIDE the handler (`withToolTimeout`) — never as a durable step `timeoutMs`. */
308
+ timeoutMs?: number;
309
+ }
278
310
 
279
311
  /**
280
312
  * Public, cross-lib-discoverable DI tokens.
@@ -541,6 +573,19 @@ interface RecordUsageInput {
541
573
  /** Provider-reported actual USD cost for this turn, when known (gateways report it). */
542
574
  costUsd?: number;
543
575
  }
576
+ interface RecordRunStartInput {
577
+ runId: string;
578
+ threadId: string;
579
+ actorRef: string;
580
+ agentName?: string;
581
+ }
582
+ interface RecordRunEndInput {
583
+ runId: string;
584
+ status: 'completed' | 'failed';
585
+ durationMs?: number;
586
+ errorCode?: string;
587
+ errorMessage?: string;
588
+ }
544
589
  /** ORM-agnostic persistence. Refs are string ids; adapters may add real relations. */
545
590
  interface AgentStore {
546
591
  createThread(input: CreateThreadInput): Promise<ThreadSummary>;
@@ -570,6 +615,15 @@ interface AgentStore {
570
615
  * Absent on a store that predates this — thread read/list payloads report `activeRunId: null`.
571
616
  */
572
617
  activeRunForThread?(threadId: string): Promise<string | null>;
618
+ /**
619
+ * OPTIONAL: persist the start of a run (turn). Replay-safe: called under a durable localStep.
620
+ * Absent on a store that predates run recording — reliability metrics degrade to zeros/empty.
621
+ */
622
+ recordRunStart?(run: RecordRunStartInput): Promise<void>;
623
+ /** OPTIONAL: settle a run's outcome. `errorCode`/`errorMessage` only when status is 'failed'. */
624
+ recordRunEnd?(end: RecordRunEndInput): Promise<void>;
625
+ /** OPTIONAL: bump the run's llm-step retry counter (dispatched-step attempt > 1). */
626
+ bumpRunRetries?(runId: string): Promise<void>;
573
627
  /**
574
628
  * The `actorRef` that owns a thread, or `null` if no such thread exists. The authorization seam
575
629
  * for thread-scoped endpoints (detail / delete / fork): the service compares this against the
@@ -822,6 +876,52 @@ interface ThreadActivityRow {
822
876
  totalTokens: number;
823
877
  lastActivityAt: string;
824
878
  }
879
+ /** Aggregated run reliability over a range. */
880
+ interface RunMetrics {
881
+ runs: number;
882
+ completed: number;
883
+ failed: number;
884
+ /** completed / runs, 0 when runs = 0. */
885
+ successRate: number;
886
+ /** Total llm-step retries across the range's runs. */
887
+ retries: number;
888
+ durationP50Ms: number | null;
889
+ durationP95Ms: number | null;
890
+ }
891
+ /** Run/failure/retry rollup for one agent over a range. */
892
+ interface RunAgentBreakdownRow {
893
+ /** '(default)' when the run had none. */
894
+ agentName: string;
895
+ runs: number;
896
+ failed: number;
897
+ retries: number;
898
+ }
899
+ /** Failed-run count for one error code over a range. */
900
+ interface RunErrorBreakdownRow {
901
+ errorCode: string;
902
+ count: number;
903
+ }
904
+ /** One point on the daily run/failure trend. */
905
+ interface RunTrendPoint {
906
+ day: string;
907
+ runs: number;
908
+ failed: number;
909
+ }
910
+ /** A recent run for the reliability feed. */
911
+ interface RecentRunRow {
912
+ runId: string;
913
+ threadId: string;
914
+ actorRef: string;
915
+ agentName: string | null;
916
+ /** 'running' | 'completed' | 'failed'. */
917
+ status: string;
918
+ durationMs: number | null;
919
+ errorCode: string | null;
920
+ errorMessage: string | null;
921
+ retries: number;
922
+ /** ISO timestamp. */
923
+ startedAt: string;
924
+ }
825
925
  /**
826
926
  * The governance read-model. Cost is `inputTokens/1e6 * inputPricePer1m + outputTokens/1e6 *
827
927
  * outputPricePer1m` against the current pricing row per model; an unpriced model contributes 0 cost
@@ -835,6 +935,11 @@ interface AgentGovernanceQueries {
835
935
  usageTrend(range: GovernanceRange): Promise<UsageTrendPoint[]>;
836
936
  recentToolCalls(limit: number): Promise<ToolCallActivityRow[]>;
837
937
  recentThreads(limit: number): Promise<ThreadActivityRow[]>;
938
+ runMetrics(range: GovernanceRange): Promise<RunMetrics>;
939
+ runsByAgent(range: GovernanceRange): Promise<RunAgentBreakdownRow[]>;
940
+ runErrors(range: GovernanceRange): Promise<RunErrorBreakdownRow[]>;
941
+ runTrend(range: GovernanceRange): Promise<RunTrendPoint[]>;
942
+ recentRuns(limit: number): Promise<RecentRunRow[]>;
838
943
  }
839
944
 
840
945
  /**
@@ -1066,15 +1171,36 @@ interface AgentLoopHooks {
1066
1171
  text: string;
1067
1172
  }>;
1068
1173
  /**
1069
- * Checkpoint wrapper. Inline = call fn directly; durable = ctx.step(name, fn).
1174
+ * Checkpoint wrapper. Inline = call fn directly; durable = ctx.localStep(name, fn) — the
1175
+ * in-process checkpointed primitive (`name` is a checkpoint identity, not a worker group).
1070
1176
  * EVERY side-effect and control-flow read goes through this so durable replay returns
1071
1177
  * cached results (stable ids, no double-write, no re-streaming).
1072
1178
  */
1073
1179
  step<T>(name: string, fn: () => Promise<T>): Promise<T>;
1180
+ /**
1181
+ * Dispatch the model turn as a routed remote step. When present the loop uses it INSTEAD of
1182
+ * running the model inline under hooks.step. Must resolve to exactly what deps.model.runTurn
1183
+ * resolves. The durable runner enriches the envelope with sink routing (sinkRunId/childSink)
1184
+ * on its side — core stays sink-topology-agnostic.
1185
+ */
1186
+ dispatchLlm?(index: number, envelope: LlmStepEnvelope): Promise<ModelTurnResult>;
1187
+ /**
1188
+ * Dispatch one tool execution as a routed remote step. Replaces ONLY the registry.invoke call
1189
+ * (+ its timeout, applied handler-side); all persist steps around it stay local.
1190
+ */
1191
+ dispatchTool?(call: ToolCallRequest, envelope: ToolStepEnvelope): Promise<unknown>;
1192
+ /**
1193
+ * Recognizes the runner's control-flow signals (durable suspend / continue-as-new) so the loop
1194
+ * rethrows them untouched instead of recording a failure. Inline runners omit it — they have no
1195
+ * control-flow exceptions.
1196
+ */
1197
+ isControlFlowError?(error: unknown): boolean;
1074
1198
  }
1075
1199
  declare class QuotaExceededError extends Error {
1076
1200
  constructor();
1077
1201
  }
1202
+ /** Reject if `work` doesn't settle within `ms`. The underlying work is left to finish on its own. */
1203
+ declare function withToolTimeout<T>(work: Promise<T>, ms: number, toolName: string): Promise<T>;
1078
1204
  /**
1079
1205
  * The provider-agnostic agent turn, reused by both the inline and durable runners.
1080
1206
  * It drives the model→tools→model iteration; the runner supplies the `step`/`awaitApproval`
@@ -1158,4 +1284,4 @@ declare function publishAgentRunFailed(payload: AgentRunFailed): void;
1158
1284
  declare function publishAgentDelegated(payload: AgentDelegated): void;
1159
1285
  declare function publishAgentRetrieved(payload: AgentRetrieved): void;
1160
1286
 
1161
- export { AGENT_ACTOR_DIRECTORY, AGENT_ACTOR_RESOLVER, AGENT_ATTACHMENT_STAGING, 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 ActorDirectory, type ActorResolver, type ActorSpendRow, type AgentCatalogEntry, 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 AgentStreamEvent, type AgentToolCallEvent, type AiToolCtx, type AppendMessageInput, type AttachmentStagingStore, type CostUsage, type CreateThreadInput, type CurrentModelPrice, type Decision, DefaultRolesPolicy, type EmbeddingProvider, type GovernanceRange, type GovernanceUsageInput, type MessageAttachment, type MessageRole, type MessageUsage, type ModelMessage, type ModelPrice, 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 StageAttachmentInput, type StoredMessage, type StreamError, type ThreadActivityRow, type ThreadDetail, type ThreadMeta, type ThreadSpendRow, 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 UpdateThreadInput, type UpdateToolCallInput, type UsagePurpose, type UsageTrendPoint, bucketByActor, bucketByModel, bucketByThread, bucketUsageTrend, dayBoundsUtc, encodeStreamEvent, estimateCost, filterToolsByAllowList, filterToolsByRole, publishAgentDelegated, publishAgentMessage, publishAgentQuotaExceeded, publishAgentRetrieved, publishAgentRunFailed, publishAgentRunFinished, publishAgentRunStarted, publishAgentToolCall, runAgentLoop, seedModelPrices };
1287
+ export { AGENT_ACTOR_DIRECTORY, AGENT_ACTOR_RESOLVER, AGENT_ATTACHMENT_STAGING, 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 ActorDirectory, type ActorResolver, type ActorSpendRow, type AgentCatalogEntry, 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 AgentStreamEvent, type AgentToolCallEvent, type AiToolCtx, type AppendMessageInput, type AttachmentStagingStore, type CostUsage, type CreateThreadInput, type CurrentModelPrice, type Decision, DefaultRolesPolicy, type EmbeddingProvider, type GovernanceRange, type GovernanceUsageInput, type LlmStepEnvelope, type MessageAttachment, type MessageRole, type MessageUsage, type ModelMessage, type ModelPrice, 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 RecentRunRow, type RecordRunEndInput, type RecordRunStartInput, type RecordToolCallInput, type RecordUsageInput, type RerankOptions, type Reranker, type RetrieveOptions, type Retriever, type RolesPolicy, type RunAgentBreakdownRow, type RunErrorBreakdownRow, type RunMetrics, type RunTrendPoint, type SinkWriter, type StageAttachmentInput, type StoredMessage, type StreamError, type ThreadActivityRow, type ThreadDetail, type ThreadMeta, type ThreadSpendRow, 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 ToolStepCtx, type ToolStepEnvelope, type UpdateThreadInput, type UpdateToolCallInput, type UsagePurpose, type UsageTrendPoint, bucketByActor, bucketByModel, bucketByThread, bucketUsageTrend, dayBoundsUtc, encodeStreamEvent, estimateCost, filterToolsByAllowList, filterToolsByRole, publishAgentDelegated, publishAgentMessage, publishAgentQuotaExceeded, publishAgentRetrieved, publishAgentRunFailed, publishAgentRunFinished, publishAgentRunStarted, publishAgentToolCall, runAgentLoop, seedModelPrices, withToolTimeout };
package/dist/index.js CHANGED
@@ -436,7 +436,7 @@ var ToolTimeoutError = class ToolTimeoutError2 extends Error {
436
436
  this.name = "ToolTimeoutError";
437
437
  }
438
438
  };
439
- function withTimeout(work, ms, toolName) {
439
+ function withToolTimeout(work, ms, toolName) {
440
440
  return new Promise((resolve, reject) => {
441
441
  const timer = setTimeout(() => reject(new ToolTimeoutError(toolName, ms)), ms);
442
442
  work.then((value) => {
@@ -448,7 +448,7 @@ function withTimeout(work, ms, toolName) {
448
448
  });
449
449
  });
450
450
  }
451
- __name(withTimeout, "withTimeout");
451
+ __name(withToolTimeout, "withToolTimeout");
452
452
  function parseFollowUps(text, count) {
453
453
  const source = text.match(/\[[\s\S]*\]/)?.[0] ?? text;
454
454
  try {
@@ -553,6 +553,17 @@ async function runAgentLoop(deps, input, hooks) {
553
553
  agentName: input.agentName
554
554
  } : {}
555
555
  });
556
+ const startedAt = await hooks.step("run:started-at", () => Promise.resolve(Date.now()));
557
+ await hooks.step("persist:run:start", async () => {
558
+ await deps.store.recordRunStart?.({
559
+ runId: hooks.runId,
560
+ threadId: input.threadId,
561
+ actorRef: input.actor.id,
562
+ ...input.agentName !== void 0 ? {
563
+ agentName: input.agentName
564
+ } : {}
565
+ });
566
+ });
556
567
  let injectedPassages;
557
568
  if (deps.retriever !== void 0) {
558
569
  const retriever = deps.retriever;
@@ -586,13 +597,25 @@ ${buildContextBlock(passages)}`;
586
597
  kind: "step-start"
587
598
  }));
588
599
  });
589
- const tools = await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList);
590
- const turn = await hooks.step(`llm:${i}`, () => deps.model.runTurn({
591
- system,
592
- messages: modelMessages,
593
- tools,
594
- sink: writer
595
- }));
600
+ let turn;
601
+ if (hooks.dispatchLlm) {
602
+ turn = await hooks.dispatchLlm(i, {
603
+ ...input.agentName !== void 0 ? {
604
+ agentName: input.agentName
605
+ } : {},
606
+ system,
607
+ messages: modelMessages,
608
+ actor: input.actor
609
+ });
610
+ } else {
611
+ const tools = await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList);
612
+ turn = await hooks.step(`llm:${i}`, () => deps.model.runTurn({
613
+ system,
614
+ messages: modelMessages,
615
+ tools,
616
+ sink: writer
617
+ }));
618
+ }
596
619
  const resolvedModelId = turn.modelId ?? deps.modelId ?? "unknown";
597
620
  const costUsd = resolveCostUsd(turn.usage, turn.costUsd, priceByModel.get(resolvedModelId));
598
621
  const toolCallsWithKind = turn.toolCalls.map((call) => ({
@@ -812,11 +835,36 @@ ${buildContextBlock(passages)}`;
812
835
  status: "auto_executed"
813
836
  }));
814
837
  }
815
- const startedAt = Date.now();
838
+ const startedAt2 = Date.now();
816
839
  try {
817
- const invocation = hooks.step(`tool:${call.id}`, () => deps.registry.invoke(call.name, call.input, ctx, deps.rolesPolicy));
818
- const output = deps.toolTimeoutMs !== void 0 ? await withTimeout(invocation, deps.toolTimeoutMs, call.name) : await invocation;
819
- const executionMs = Date.now() - startedAt;
840
+ let output;
841
+ if (hooks.dispatchTool) {
842
+ const stepCtx = {
843
+ actor: input.actor,
844
+ threadId: input.threadId,
845
+ runId: hooks.runId,
846
+ requestId: hooks.runId,
847
+ ...input.agentName !== void 0 ? {
848
+ agentName: input.agentName
849
+ } : {},
850
+ ...input.pageContext !== void 0 ? {
851
+ pageContext: input.pageContext
852
+ } : {}
853
+ };
854
+ const envelope = {
855
+ toolName: call.name,
856
+ input: call.input,
857
+ ctx: stepCtx,
858
+ ...deps.toolTimeoutMs !== void 0 ? {
859
+ timeoutMs: deps.toolTimeoutMs
860
+ } : {}
861
+ };
862
+ output = await hooks.dispatchTool(call, envelope);
863
+ } else {
864
+ const invocation = hooks.step(`tool:${call.id}`, () => deps.registry.invoke(call.name, call.input, ctx, deps.rolesPolicy));
865
+ output = deps.toolTimeoutMs !== void 0 ? await withToolTimeout(invocation, deps.toolTimeoutMs, call.name) : await invocation;
866
+ }
867
+ const executionMs = Date.now() - startedAt2;
820
868
  await hooks.step(`persist:toolexec:${call.id}`, () => deps.store.updateToolCall({
821
869
  toolCallId: call.id,
822
870
  status: "executed",
@@ -839,7 +887,10 @@ ${buildContextBlock(passages)}`;
839
887
  durationMs: executionMs
840
888
  });
841
889
  } catch (error) {
842
- const executionMs = Date.now() - startedAt;
890
+ if (hooks.isControlFlowError?.(error) === true) {
891
+ throw error;
892
+ }
893
+ const executionMs = Date.now() - startedAt2;
843
894
  const message = error instanceof Error ? error.message : String(error);
844
895
  await hooks.step(`persist:toolfail:${call.id}`, () => deps.store.updateToolCall({
845
896
  toolCallId: call.id,
@@ -887,6 +938,13 @@ ${buildContextBlock(passages)}`;
887
938
  if (thread !== null && (thread.title === "" || thread.title === "New chat")) {
888
939
  await hooks.step("persist:title", () => deps.store.setTitle(input.threadId, deriveTitle(input.userText)));
889
940
  }
941
+ await hooks.step("persist:run:end", async () => {
942
+ await deps.store.recordRunEnd?.({
943
+ runId: hooks.runId,
944
+ status: "completed",
945
+ durationMs: Date.now() - startedAt
946
+ });
947
+ });
890
948
  await writer.end();
891
949
  publishAgentRunFinished({
892
950
  runId: hooks.runId,
@@ -946,6 +1004,7 @@ export {
946
1004
  publishAgentRunStarted,
947
1005
  publishAgentToolCall,
948
1006
  runAgentLoop,
949
- seedModelPrices
1007
+ seedModelPrices,
1008
+ withToolTimeout
950
1009
  };
951
1010
  //# sourceMappingURL=index.js.map