@prestyj/agent 5.6.0 → 5.7.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
@@ -49,11 +49,26 @@ interface AgentToolCallEndEvent {
49
49
  isError: boolean;
50
50
  durationMs: number;
51
51
  }
52
+ interface AgentTurnTiming {
53
+ /** Logical turn start, before context transforms or provider retries. Unix epoch milliseconds. */
54
+ startedAt: number;
55
+ /** First provider event, or full-response arrival for non-streaming fallback. */
56
+ firstProviderEventAt?: number;
57
+ /** Successful provider response completion. Unix epoch milliseconds. */
58
+ completedAt: number;
59
+ /** Time spent awaiting provider attempts, including failed attempts but excluding retry backoff. */
60
+ providerDurationMs: number;
61
+ /** Time from logical turn start to the first provider event. */
62
+ ttftMs?: number;
63
+ /** Output tokens divided by total provider duration. Omitted when no rate is measurable. */
64
+ outputTokensPerSecond?: number;
65
+ }
52
66
  interface AgentTurnEndEvent {
53
67
  type: "turn_end";
54
68
  turn: number;
55
69
  stopReason: StopReason;
56
70
  usage: Usage;
71
+ timing: AgentTurnTiming;
57
72
  }
58
73
  interface AgentDoneEvent {
59
74
  type: "agent_done";
@@ -129,6 +144,8 @@ interface AgentOptions {
129
144
  priorMessages?: Message[];
130
145
  tools?: AgentTool[];
131
146
  serverTools?: ServerToolDefinition[];
147
+ /** Control whether tools may/must be called, or select a named tool when supported. */
148
+ toolChoice?: StreamOptions["toolChoice"];
132
149
  maxTurns?: number;
133
150
  maxTokens?: number;
134
151
  temperature?: number;
@@ -282,4 +299,4 @@ declare function isBillingError(err: unknown): boolean;
282
299
  declare function isUsageLimitError(err: unknown): boolean;
283
300
  declare function agentLoop(messages: Message[], options: AgentOptions): AsyncGenerator<AgentEvent, AgentResult>;
284
301
 
285
- export { Agent, type AgentDoneEvent, type AgentErrorEvent, type AgentEvent, type AgentFollowUpMessageEvent, type AgentOptions, type AgentResult, type AgentRetryEvent, type AgentServerToolCallEvent, type AgentServerToolResultEvent, type AgentSteeringMessageEvent, AgentStream, type AgentTextDeltaEvent, type AgentThinkingDeltaEvent, type AgentTool, type AgentToolCallDeltaEvent, type AgentToolCallEndEvent, type AgentToolCallStartEvent, type AgentToolCallUpdateEvent, type AgentTurnEndEvent, type StreamDiagnosticFn, type StructuredToolResult, type ToolContext, type ToolExecuteResult, type ToolExecutionMode, agentLoop, isAbortError, isBillingError, isContextOverflow, isUsageLimitError, setStreamDiagnostic };
302
+ export { Agent, type AgentDoneEvent, type AgentErrorEvent, type AgentEvent, type AgentFollowUpMessageEvent, type AgentOptions, type AgentResult, type AgentRetryEvent, type AgentServerToolCallEvent, type AgentServerToolResultEvent, type AgentSteeringMessageEvent, AgentStream, type AgentTextDeltaEvent, type AgentThinkingDeltaEvent, type AgentTool, type AgentToolCallDeltaEvent, type AgentToolCallEndEvent, type AgentToolCallStartEvent, type AgentToolCallUpdateEvent, type AgentTurnEndEvent, type AgentTurnTiming, type StreamDiagnosticFn, type StructuredToolResult, type ToolContext, type ToolExecuteResult, type ToolExecutionMode, agentLoop, isAbortError, isBillingError, isContextOverflow, isUsageLimitError, setStreamDiagnostic };
package/dist/index.d.ts CHANGED
@@ -49,11 +49,26 @@ interface AgentToolCallEndEvent {
49
49
  isError: boolean;
50
50
  durationMs: number;
51
51
  }
52
+ interface AgentTurnTiming {
53
+ /** Logical turn start, before context transforms or provider retries. Unix epoch milliseconds. */
54
+ startedAt: number;
55
+ /** First provider event, or full-response arrival for non-streaming fallback. */
56
+ firstProviderEventAt?: number;
57
+ /** Successful provider response completion. Unix epoch milliseconds. */
58
+ completedAt: number;
59
+ /** Time spent awaiting provider attempts, including failed attempts but excluding retry backoff. */
60
+ providerDurationMs: number;
61
+ /** Time from logical turn start to the first provider event. */
62
+ ttftMs?: number;
63
+ /** Output tokens divided by total provider duration. Omitted when no rate is measurable. */
64
+ outputTokensPerSecond?: number;
65
+ }
52
66
  interface AgentTurnEndEvent {
53
67
  type: "turn_end";
54
68
  turn: number;
55
69
  stopReason: StopReason;
56
70
  usage: Usage;
71
+ timing: AgentTurnTiming;
57
72
  }
58
73
  interface AgentDoneEvent {
59
74
  type: "agent_done";
@@ -129,6 +144,8 @@ interface AgentOptions {
129
144
  priorMessages?: Message[];
130
145
  tools?: AgentTool[];
131
146
  serverTools?: ServerToolDefinition[];
147
+ /** Control whether tools may/must be called, or select a named tool when supported. */
148
+ toolChoice?: StreamOptions["toolChoice"];
132
149
  maxTurns?: number;
133
150
  maxTokens?: number;
134
151
  temperature?: number;
@@ -282,4 +299,4 @@ declare function isBillingError(err: unknown): boolean;
282
299
  declare function isUsageLimitError(err: unknown): boolean;
283
300
  declare function agentLoop(messages: Message[], options: AgentOptions): AsyncGenerator<AgentEvent, AgentResult>;
284
301
 
285
- export { Agent, type AgentDoneEvent, type AgentErrorEvent, type AgentEvent, type AgentFollowUpMessageEvent, type AgentOptions, type AgentResult, type AgentRetryEvent, type AgentServerToolCallEvent, type AgentServerToolResultEvent, type AgentSteeringMessageEvent, AgentStream, type AgentTextDeltaEvent, type AgentThinkingDeltaEvent, type AgentTool, type AgentToolCallDeltaEvent, type AgentToolCallEndEvent, type AgentToolCallStartEvent, type AgentToolCallUpdateEvent, type AgentTurnEndEvent, type StreamDiagnosticFn, type StructuredToolResult, type ToolContext, type ToolExecuteResult, type ToolExecutionMode, agentLoop, isAbortError, isBillingError, isContextOverflow, isUsageLimitError, setStreamDiagnostic };
302
+ export { Agent, type AgentDoneEvent, type AgentErrorEvent, type AgentEvent, type AgentFollowUpMessageEvent, type AgentOptions, type AgentResult, type AgentRetryEvent, type AgentServerToolCallEvent, type AgentServerToolResultEvent, type AgentSteeringMessageEvent, AgentStream, type AgentTextDeltaEvent, type AgentThinkingDeltaEvent, type AgentTool, type AgentToolCallDeltaEvent, type AgentToolCallEndEvent, type AgentToolCallStartEvent, type AgentToolCallUpdateEvent, type AgentTurnEndEvent, type AgentTurnTiming, type StreamDiagnosticFn, type StructuredToolResult, type ToolContext, type ToolExecuteResult, type ToolExecutionMode, agentLoop, isAbortError, isBillingError, isContextOverflow, isUsageLimitError, setStreamDiagnostic };
package/dist/index.js CHANGED
@@ -7,7 +7,8 @@ import {
7
7
  stream,
8
8
  EventStream,
9
9
  EZCoderAIError,
10
- isHardBillingMessage
10
+ isHardBillingMessage,
11
+ redactValue
11
12
  } from "@prestyj/ai";
12
13
  var DEFAULT_MAX_TURNS = 300;
13
14
  var _diagFn = null;
@@ -268,10 +269,14 @@ async function* agentLoop(messages, options) {
268
269
  const initialHardTimeoutMs = isSakana ? STREAM_THINKING_HARD_TIMEOUT_MS : STREAM_HARD_TIMEOUT_MS;
269
270
  const MAX_TOOLCALL_DELTA_CHARS = 1e6;
270
271
  const MAX_TOOLCALL_DELTA_EVENTS = 2e4;
272
+ let logicalTurnStartedAt = 0;
273
+ let firstProviderEventAt;
274
+ let providerDurationMs = 0;
271
275
  try {
272
276
  while (turn < maxTurns) {
273
277
  options.signal?.throwIfAborted();
274
278
  turn++;
279
+ if (logicalTurnStartedAt === 0) logicalTurnStartedAt = Date.now();
275
280
  toolMap = new Map((options.tools ?? []).map((t) => [t.name, t]));
276
281
  if (_diagFn) {
277
282
  let msgChars = 0;
@@ -321,6 +326,7 @@ async function* agentLoop(messages, options) {
321
326
  let idleTimer = null;
322
327
  let hardTimer = null;
323
328
  let idleTimedOut = false;
329
+ let providerAttemptStartedAt;
324
330
  let streamEventCount = 0;
325
331
  let lastEventTime = Date.now();
326
332
  let streamCallStart = Date.now();
@@ -366,12 +372,14 @@ async function* agentLoop(messages, options) {
366
372
  try {
367
373
  diag("stream_call", { nonStreaming: useNonStreamingFallback });
368
374
  streamCallStart = Date.now();
375
+ providerAttemptStartedAt = streamCallStart;
369
376
  const result = stream({
370
377
  provider: options.provider,
371
378
  model: options.model,
372
379
  messages,
373
380
  tools: options.tools,
374
381
  serverTools: options.serverTools,
382
+ toolChoice: options.toolChoice,
375
383
  webSearch: options.webSearch,
376
384
  maxTokens: options.maxTokens,
377
385
  temperature: options.temperature,
@@ -414,6 +422,7 @@ async function* agentLoop(messages, options) {
414
422
  maxConsumerLagMs = consumerLag;
415
423
  }
416
424
  streamEventCount++;
425
+ if (firstProviderEventAt === void 0) firstProviderEventAt = pullTime;
417
426
  eventTypeCounts[event.type] = (eventTypeCounts[event.type] ?? 0) + 1;
418
427
  lastEventType = event.type;
419
428
  if ((event.type === "text_delta" || event.type === "server_toolcall" || event.type === "toolcall_delta") && !hasReceivedEvent) {
@@ -506,6 +515,7 @@ async function* agentLoop(messages, options) {
506
515
  eventTypes: eventTypeCounts
507
516
  });
508
517
  response = await abortablePromise(result.response, streamController.signal);
518
+ if (firstProviderEventAt === void 0) firstProviderEventAt = Date.now();
509
519
  } catch (err) {
510
520
  if (streamController.signal.aborted) closeIterator(streamIterator);
511
521
  const errMsg = err instanceof Error ? err.message : String(err);
@@ -730,6 +740,9 @@ async function* agentLoop(messages, options) {
730
740
  });
731
741
  throw err;
732
742
  } finally {
743
+ if (providerAttemptStartedAt !== void 0) {
744
+ providerDurationMs += Date.now() - providerAttemptStartedAt;
745
+ }
733
746
  if (idleTimer) clearTimeout(idleTimer);
734
747
  if (hardTimer) clearTimeout(hardTimer);
735
748
  options.signal?.removeEventListener("abort", forwardAbort);
@@ -773,11 +786,27 @@ async function* agentLoop(messages, options) {
773
786
  totalUsage.cacheWrite = (totalUsage.cacheWrite ?? 0) + response.usage.cacheWrite;
774
787
  }
775
788
  messages.push(response.message);
789
+ const completedAt = Date.now();
790
+ const outputTokensPerSecond = providerDurationMs > 0 && response.usage.outputTokens > 0 ? response.usage.outputTokens / (providerDurationMs / 1e3) : void 0;
791
+ const timing = {
792
+ startedAt: logicalTurnStartedAt,
793
+ ...firstProviderEventAt !== void 0 ? {
794
+ firstProviderEventAt,
795
+ ttftMs: Math.max(0, firstProviderEventAt - logicalTurnStartedAt)
796
+ } : {},
797
+ completedAt,
798
+ providerDurationMs,
799
+ ...outputTokensPerSecond !== void 0 ? { outputTokensPerSecond } : {}
800
+ };
801
+ logicalTurnStartedAt = 0;
802
+ firstProviderEventAt = void 0;
803
+ providerDurationMs = 0;
776
804
  yield {
777
805
  type: "turn_end",
778
806
  turn,
779
807
  stopReason: response.stopReason,
780
- usage: response.usage
808
+ usage: response.usage,
809
+ timing
781
810
  };
782
811
  if (response.stopReason === "pause_turn") {
783
812
  consecutivePauses++;
@@ -961,8 +990,8 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
961
990
  ctx.signal
962
991
  );
963
992
  const normalized = normalizeToolResult(raw);
964
- resultContent = normalized.content;
965
- details = normalized.details;
993
+ resultContent = redactValue(normalized.content);
994
+ details = redactValue(normalized.details);
966
995
  for (const key of options.invalidToolArgumentCounts.keys()) {
967
996
  if (key.startsWith(`${toolCall.name}:`)) options.invalidToolArgumentCounts.delete(key);
968
997
  }
@@ -990,10 +1019,12 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
990
1019
  );
991
1020
  }
992
1021
  } else {
993
- resultContent = err instanceof Error ? err.message : String(err);
1022
+ resultContent = redactValue(err instanceof Error ? err.message : String(err));
994
1023
  }
995
1024
  }
996
1025
  }
1026
+ resultContent = redactValue(resultContent);
1027
+ details = redactValue(details);
997
1028
  const durationMs = Date.now() - startTime;
998
1029
  pushEvent({
999
1030
  type: "tool_call_end",