@dudousxd/nestjs-agent 1.35.1 → 1.36.1

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.
@@ -69,7 +69,7 @@ var init_kit = __esm({
69
69
  });
70
70
 
71
71
  // src/durable/agent-run.workflow.ts
72
- import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY2, AGENT_STORE, RUN_ENDED_BEFORE_TOOL_CALL, RunCancelledError, agentFailureCode, encodeStreamEvent as encodeStreamEvent2, isReplayIntegrityError as isReplayIntegrityError2, publishAgentRunFailed, releaseThreadRun, runAgentLoop, settleAll, settleDeadRun, settleUnsettledDelegation, streamFailure } from "@dudousxd/nestjs-agent-core";
72
+ import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY2, AGENT_STORE, RUN_ENDED_BEFORE_TOOL_CALL, RunCancelledError, agentFailureCode, agentRunContext, encodeStreamEvent as encodeStreamEvent2, isReplayIntegrityError as isReplayIntegrityError2, publishAgentRunFailed, releaseThreadRun, runAgentLoop, runDurationMs, settleAll, settleDeadRun, settleUnsettledDelegation, streamFailure } from "@dudousxd/nestjs-agent-core";
73
73
  import { RUN_GATEWAY, Workflow, WorkflowService } from "@dudousxd/nestjs-durable";
74
74
  import { isWorkflowControlFlowSignal } from "@dudousxd/nestjs-durable-core";
75
75
  import { Inject as Inject2, Injectable as Injectable2, Logger, Optional } from "@nestjs/common";
@@ -102,7 +102,7 @@ var AGENT_CHAT_QUEUE = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:chat-q
102
102
  // src/durable/agent-run.steps.ts
103
103
  import { createNegotiatedUiCollector } from "@dudousxd/nestjs-agent-core";
104
104
  import { prepareActionProposal, resolveActionProposalApproval } from "@dudousxd/nestjs-agent-core";
105
- import { AGENT_DEPS_FACTORY, announcedToolCalls, createFrameBuffer, createNoopEmitUi, encodeStreamEvent, intersectAllowLists, invokeWithTransientRetry, isControlFlowSignal, isReplayIntegrityError, observeTurnFrames, previewToolInputs, publishAgentToolRetry, registryInputPreviews, stampToolKinds, toolCallContext, traceLlmTurn, traceToolExecution, withAskTool, withChannelDelivery, withMemoryTool, withSkillTool, withToolTimeout, withTurnFrames, wrapToolPreflightDenied, wrapToolStepOutput } from "@dudousxd/nestjs-agent-core";
105
+ import { AGENT_DEPS_FACTORY, announcedToolCalls, createFrameBuffer, createNoopEmitUi, encodeStreamEvent, intersectAllowLists, invokeWithTransientRetry, isControlFlowSignal, isReplayIntegrityError, observeFirstText, observeTurnFrames, previewToolInputs, publishAgentToolRetry, registryInputPreviews, stampToolKinds, toolCallContext, traceLlmTurn, traceToolExecution, withAskTool, withChannelDelivery, withMemoryTool, withSkillTool, withToolTimeout, withTurnFrames, wrapToolPreflightDenied, wrapToolStepOutput } from "@dudousxd/nestjs-agent-core";
106
106
  import { turnChannel } from "@dudousxd/nestjs-agent-core/genui";
107
107
  import { Step } from "@dudousxd/nestjs-durable";
108
108
  import { Inject, Injectable } from "@nestjs/common";
@@ -194,11 +194,13 @@ var AgentRunSteps = class {
194
194
  });
195
195
  const buffer = input.bufferOutput === true ? createFrameBuffer() : void 0;
196
196
  let writer;
197
+ let firstText;
197
198
  if (buffer !== void 0) {
198
199
  writer = buffer.writer;
199
200
  } else {
200
201
  const opened = await deps.sink.open(input.sinkRunId);
201
- writer = input.childSink ? childSinkWriter(opened) : opened;
202
+ firstText = observeFirstText(input.childSink ? childSinkWriter(opened) : opened);
203
+ writer = firstText.writer;
202
204
  }
203
205
  const announced = announcedToolCalls(writer);
204
206
  const previews = previewToolInputs(announced.writer, registryInputPreviews(deps.registry, tools, {
@@ -292,9 +294,16 @@ var AgentRunSteps = class {
292
294
  ...stamped,
293
295
  previews: shown
294
296
  } : stamped;
295
- return buffer === void 0 ? previewed : {
297
+ const firstTextAt = firstText?.firstTextAt();
298
+ if (buffer !== void 0) {
299
+ return {
300
+ ...previewed,
301
+ bufferedFrames: buffer.frames()
302
+ };
303
+ }
304
+ return firstTextAt === void 0 ? previewed : {
296
305
  ...previewed,
297
- bufferedFrames: buffer.frames()
306
+ firstTextAt
298
307
  };
299
308
  }
300
309
  /**
@@ -337,6 +346,7 @@ var AgentRunSteps = class {
337
346
  ...input.allowedTools
338
347
  ]);
339
348
  let output;
349
+ const toolStartedAt = Date.now();
340
350
  try {
341
351
  output = await traceToolExecution(input.ctx.runId, {
342
352
  toolCallId: input.toolCallId,
@@ -364,8 +374,9 @@ var AgentRunSteps = class {
364
374
  }
365
375
  throw error;
366
376
  }
377
+ const executionMs = Date.now() - toolStartedAt;
367
378
  output = await withChannelDelivery(deps, input.ctx, output, ui.components());
368
- return input.collectUi === true ? wrapToolStepOutput(output, ui.components(), ui.text()) : output;
379
+ return input.collectUi === true ? wrapToolStepOutput(output, ui.components(), ui.text(), executionMs) : output;
369
380
  }
370
381
  };
371
382
  _ts_decorate([
@@ -765,21 +776,29 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
765
776
  });
766
777
  throw error;
767
778
  }
779
+ const durationMs = runDurationMs(error);
780
+ const timed = durationMs !== void 0 ? {
781
+ durationMs
782
+ } : {};
768
783
  if (isReplayIntegrityError2(error)) {
769
784
  const detail = error.message;
770
785
  const code2 = agentFailureCode(error);
771
786
  this.logger.error(`agent run ${ctx.runId} failed (${code2}): ${detail}`);
772
787
  publishAgentRunFailed({
773
788
  runId: ctx.runId,
789
+ threadId: input.threadId,
774
790
  code: code2,
775
- message: detail
791
+ message: detail,
792
+ ...timed,
793
+ context: agentRunContext(input)
776
794
  });
777
795
  await settleDeadRun(this.store, {
778
796
  runId: ctx.runId,
779
797
  threadId: input.threadId,
780
798
  failure: {
781
799
  code: code2,
782
- message: detail
800
+ message: detail,
801
+ ...timed
783
802
  }
784
803
  });
785
804
  await (await hooks.openSink()).fail(streamFailure(error));
@@ -790,13 +809,17 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
790
809
  this.logger.error(`agent run ${ctx.runId} failed (${code}): ${message}`);
791
810
  publishAgentRunFailed({
792
811
  runId: ctx.runId,
812
+ threadId: input.threadId,
793
813
  code,
794
- message
814
+ message,
815
+ ...timed,
816
+ context: agentRunContext(input)
795
817
  });
796
818
  await stepOf(ctx)("persist:run:fail", async () => {
797
819
  await this.store.recordRunEnd?.({
798
820
  runId: ctx.runId,
799
821
  status: "failed",
822
+ ...timed,
800
823
  errorCode: code,
801
824
  errorMessage: message
802
825
  });
@@ -846,7 +869,7 @@ __name(isSignalTimeout, "isSignalTimeout");
846
869
 
847
870
  // src/durable/durable-agent-runner.ts
848
871
  import { randomUUID } from "crypto";
849
- import { AGENT_SINK, AGENT_STORE as AGENT_STORE2, encodeStreamEvent as encodeStreamEvent3, releaseThreadRun as releaseThreadRun2, settleUnsettledDelegation as settleUnsettledDelegation2 } from "@dudousxd/nestjs-agent-core";
872
+ import { AGENT_SINK, AGENT_STORE as AGENT_STORE2, encodeStreamEvent as encodeStreamEvent3, publishAgentRunCancelled, releaseThreadRun as releaseThreadRun2, settleUnsettledDelegation as settleUnsettledDelegation2 } from "@dudousxd/nestjs-agent-core";
850
873
  import { RUN_GATEWAY as RUN_GATEWAY2, WorkflowService as WorkflowService2 } from "@dudousxd/nestjs-durable";
851
874
  import { isWorkflowControlFlowSignal as isWorkflowControlFlowSignal2 } from "@dudousxd/nestjs-durable-core";
852
875
  import { Inject as Inject3, Injectable as Injectable3, Logger as Logger2, Optional as Optional2 } from "@nestjs/common";
@@ -971,6 +994,57 @@ function deliveryOf(input) {
971
994
  };
972
995
  }
973
996
  __name(deliveryOf, "deliveryOf");
997
+ function runContextOf(input) {
998
+ if (typeof input !== "object" || input === null) {
999
+ return void 0;
1000
+ }
1001
+ const { actor, agentName, parentRunId } = input;
1002
+ if (typeof actor?.id !== "string") {
1003
+ return void 0;
1004
+ }
1005
+ return {
1006
+ actorId: actor.id,
1007
+ ...typeof agentName === "string" ? {
1008
+ agentName
1009
+ } : {},
1010
+ ...typeof actor.tenantRef === "string" ? {
1011
+ tenantRef: actor.tenantRef
1012
+ } : {},
1013
+ ...typeof parentRunId === "string" ? {
1014
+ parentRunId
1015
+ } : {}
1016
+ };
1017
+ }
1018
+ __name(runContextOf, "runContextOf");
1019
+ function cancelledAfterMs(detail) {
1020
+ const createdAt = detail?.run.createdAt;
1021
+ if (createdAt === void 0) {
1022
+ return {};
1023
+ }
1024
+ const started = new Date(createdAt).getTime();
1025
+ return Number.isFinite(started) ? {
1026
+ durationMs: Math.max(0, Date.now() - started)
1027
+ } : {};
1028
+ }
1029
+ __name(cancelledAfterMs, "cancelledAfterMs");
1030
+ function publishCancelled(runId, detail) {
1031
+ const input = detail?.run.input;
1032
+ const threadId = threadOfRun(input);
1033
+ const context = runContextOf(input);
1034
+ const timed = cancelledAfterMs(detail);
1035
+ publishAgentRunCancelled({
1036
+ runId,
1037
+ ...threadId !== void 0 ? {
1038
+ threadId
1039
+ } : {},
1040
+ ...timed,
1041
+ ...context !== void 0 ? {
1042
+ context
1043
+ } : {}
1044
+ });
1045
+ return timed;
1046
+ }
1047
+ __name(publishCancelled, "publishCancelled");
974
1048
  var DurableAgentRunner = class _DurableAgentRunner {
975
1049
  static {
976
1050
  __name(this, "DurableAgentRunner");
@@ -1084,9 +1158,11 @@ var DurableAgentRunner = class _DurableAgentRunner {
1084
1158
  kind: "cancelled"
1085
1159
  }));
1086
1160
  await writer.end();
1161
+ const timed = publishCancelled(runId, detail);
1087
1162
  await this.store.recordRunEnd?.({
1088
1163
  runId,
1089
- status: "cancelled"
1164
+ status: "cancelled",
1165
+ ...timed
1090
1166
  });
1091
1167
  }
1092
1168
  /**
@@ -1134,9 +1210,11 @@ var DurableAgentRunner = class _DurableAgentRunner {
1134
1210
  kind: "cancelled"
1135
1211
  }));
1136
1212
  await writer.end();
1213
+ const timed = publishCancelled(childId, child);
1137
1214
  await this.store.recordRunEnd?.({
1138
1215
  runId: childId,
1139
- status: "cancelled"
1216
+ status: "cancelled",
1217
+ ...timed
1140
1218
  });
1141
1219
  }
1142
1220
  /**
@@ -6854,7 +6932,7 @@ ActionProposalController = _ts_decorate29([
6854
6932
  ], ActionProposalController);
6855
6933
 
6856
6934
  // src/runner/inline-agent-runner.ts
6857
- import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY8, AGENT_STORE as AGENT_STORE8, RUN_ENDED_BEFORE_TOOL_CALL as RUN_ENDED_BEFORE_TOOL_CALL2, RunCancelledError as RunCancelledError2, agentFailureCode as agentFailureCode2, encodeStreamEvent as encodeStreamEvent5, publishAgentRunFailed as publishAgentRunFailed2, releaseThreadRun as releaseThreadRun3, runAgentLoop as runAgentLoop2, settleAll as settleAll2, settleUnsettledDelegation as settleUnsettledDelegation3, streamFailure as streamFailure3 } from "@dudousxd/nestjs-agent-core";
6935
+ import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY8, AGENT_STORE as AGENT_STORE8, RUN_ENDED_BEFORE_TOOL_CALL as RUN_ENDED_BEFORE_TOOL_CALL2, RunCancelledError as RunCancelledError2, agentFailureCode as agentFailureCode2, agentRunContext as agentRunContext2, encodeStreamEvent as encodeStreamEvent5, publishAgentRunCancelled as publishAgentRunCancelled2, publishAgentRunFailed as publishAgentRunFailed2, releaseThreadRun as releaseThreadRun3, runAgentLoop as runAgentLoop2, runDurationMs as runDurationMs2, settleAll as settleAll2, settleUnsettledDelegation as settleUnsettledDelegation3, streamFailure as streamFailure3 } from "@dudousxd/nestjs-agent-core";
6858
6936
  import { Inject as Inject28, Injectable as Injectable14, Logger as Logger9, Optional as Optional12 } from "@nestjs/common";
6859
6937
  function _ts_decorate30(decorators, target, key, desc) {
6860
6938
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -6947,8 +7025,12 @@ var InlineAgentRunner = class _InlineAgentRunner {
6947
7025
  ...deps,
6948
7026
  day
6949
7027
  }, input, hooks).then(() => releaseThreadRun3(this.store, input.threadId, runId)).catch(async (error) => {
7028
+ const durationMs = runDurationMs2(error);
7029
+ const timed = durationMs !== void 0 ? {
7030
+ durationMs
7031
+ } : {};
6950
7032
  if (error instanceof RunCancelledError2) {
6951
- await this.settleCancelled(runId, input, deps);
7033
+ await this.settleCancelled(runId, input, deps, durationMs);
6952
7034
  return;
6953
7035
  }
6954
7036
  const message = error instanceof Error ? error.message : String(error);
@@ -6956,12 +7038,16 @@ var InlineAgentRunner = class _InlineAgentRunner {
6956
7038
  this.logger.error(`agent run ${runId} failed (${code}): ${message}`);
6957
7039
  publishAgentRunFailed2({
6958
7040
  runId,
7041
+ threadId: input.threadId,
6959
7042
  code,
6960
- message
7043
+ message,
7044
+ ...timed,
7045
+ context: agentRunContext2(input)
6961
7046
  });
6962
7047
  await this.store.recordRunEnd?.({
6963
7048
  runId,
6964
7049
  status: "failed",
7050
+ ...timed,
6965
7051
  errorCode: code,
6966
7052
  errorMessage: message
6967
7053
  });
@@ -7033,8 +7119,17 @@ var InlineAgentRunner = class _InlineAgentRunner {
7033
7119
  * the stream ENDED after a `cancelled` frame rather than failed, so a client that retries failed
7034
7120
  * streams does not retry this one.
7035
7121
  */
7036
- async settleCancelled(runId, input, deps) {
7122
+ async settleCancelled(runId, input, deps, durationMs) {
7037
7123
  this.logger.log(`agent run ${runId} cancelled`);
7124
+ const timed = durationMs !== void 0 ? {
7125
+ durationMs
7126
+ } : {};
7127
+ publishAgentRunCancelled2({
7128
+ runId,
7129
+ threadId: input.threadId,
7130
+ ...timed,
7131
+ context: agentRunContext2(input)
7132
+ });
7038
7133
  const writer = await deps.sink.open(runId);
7039
7134
  await this.settleQueue(writer, input, runId, "cancelled");
7040
7135
  await releaseThreadRun3(this.store, input.threadId, runId);
@@ -7044,7 +7139,8 @@ var InlineAgentRunner = class _InlineAgentRunner {
7044
7139
  await writer.end();
7045
7140
  await this.store.recordRunEnd?.({
7046
7141
  runId,
7047
- status: "cancelled"
7142
+ status: "cancelled",
7143
+ ...timed
7048
7144
  });
7049
7145
  }
7050
7146
  /**
@@ -7230,10 +7326,7 @@ var InlineAgentRunner = class _InlineAgentRunner {
7230
7326
  }
7231
7327
  }), "startAgent")
7232
7328
  };
7233
- void runAgentLoop2({
7234
- ...deps,
7235
- day
7236
- }, {
7329
+ const childInput = {
7237
7330
  threadId: subThread.id,
7238
7331
  actor,
7239
7332
  userText: task,
@@ -7243,13 +7336,29 @@ var InlineAgentRunner = class _InlineAgentRunner {
7243
7336
  delegationPath: path,
7244
7337
  parentRunId,
7245
7338
  deliverTo
7246
- }, hooks).catch(async (error) => {
7339
+ };
7340
+ void runAgentLoop2({
7341
+ ...deps,
7342
+ day
7343
+ }, childInput, hooks).catch(async (error) => {
7247
7344
  const cancelled = error instanceof RunCancelledError2;
7248
7345
  const message = error instanceof Error ? error.message : String(error);
7249
- if (!cancelled) {
7346
+ const durationMs = runDurationMs2(error);
7347
+ const timed = durationMs !== void 0 ? {
7348
+ durationMs
7349
+ } : {};
7350
+ const settled = {
7351
+ runId,
7352
+ threadId: subThread.id,
7353
+ ...timed,
7354
+ context: agentRunContext2(childInput)
7355
+ };
7356
+ if (cancelled) {
7357
+ publishAgentRunCancelled2(settled);
7358
+ } else {
7250
7359
  this.logger.error(`detached agent run ${runId} failed: ${message}`);
7251
7360
  publishAgentRunFailed2({
7252
- runId,
7361
+ ...settled,
7253
7362
  code: agentFailureCode2(error),
7254
7363
  message
7255
7364
  });
@@ -7257,6 +7366,7 @@ var InlineAgentRunner = class _InlineAgentRunner {
7257
7366
  await this.store.recordRunEnd?.({
7258
7367
  runId,
7259
7368
  status: cancelled ? "cancelled" : "failed",
7369
+ ...timed,
7260
7370
  ...cancelled ? {} : {
7261
7371
  errorCode: agentFailureCode2(error),
7262
7372
  errorMessage: message