@ai-sdk/harness 1.0.40 → 1.0.42

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/harness",
3
- "version": "1.0.40",
3
+ "version": "1.0.42",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -46,7 +46,7 @@
46
46
  "dependencies": {
47
47
  "@ai-sdk/provider": "4.0.3",
48
48
  "@ai-sdk/provider-utils": "5.0.12",
49
- "ai": "7.0.35"
49
+ "ai": "7.0.37"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "ws": "^8.21.0",
@@ -184,7 +184,7 @@ export function runPrompt<
184
184
  },
185
185
  });
186
186
  } catch (err) {
187
- telemetry.error(err);
187
+ await telemetry.error(err);
188
188
  logBridgeError({
189
189
  harnessId: input.harness.harnessId,
190
190
  sessionId: input.session.sessionId,
@@ -278,12 +278,12 @@ export function runPrompt<
278
278
  unified: 'tool-calls',
279
279
  raw: undefined,
280
280
  };
281
- const completeStep = (input: {
281
+ const completeStep = async (input: {
282
282
  finishReason: LanguageModelV4FinishReason;
283
283
  usage: LanguageModelV4Usage;
284
284
  providerMetadata: ProviderMetadata | undefined;
285
- }): StepResult<TOOLS, RUNTIME_CONTEXT> => {
286
- telemetry.stepFinish({
285
+ }): Promise<StepResult<TOOLS, RUNTIME_CONTEXT>> => {
286
+ await telemetry.stepFinish({
287
287
  finishReason: input.finishReason,
288
288
  usage: input.usage,
289
289
  providerMetadata: input.providerMetadata,
@@ -303,13 +303,13 @@ export function runPrompt<
303
303
  completeCurrentStep: boolean;
304
304
  }): Promise<void> => {
305
305
  if (options.completeCurrentStep) {
306
- completeStep({
306
+ await completeStep({
307
307
  finishReason: toolCallsFinishReason,
308
308
  usage: zeroUsage,
309
309
  providerMetadata: undefined,
310
310
  });
311
311
  }
312
- telemetry.end({
312
+ await telemetry.end({
313
313
  finishReason: toolCallsFinishReason,
314
314
  usage: zeroUsage,
315
315
  });
@@ -435,7 +435,7 @@ export function runPrompt<
435
435
  input: approval.input,
436
436
  } satisfies Extract<HarnessV1StreamPart, { type: 'tool-call' }>);
437
437
 
438
- telemetry.start(input.session.modelId);
438
+ await telemetry.start(input.session.modelId);
439
439
  await telemetry.toolStart({
440
440
  toolCallId: rawToolCall.toolCallId,
441
441
  toolName: rawToolCall.toolName,
@@ -476,7 +476,7 @@ export function runPrompt<
476
476
  await finishForHostInputPause({ completeCurrentStep: false });
477
477
  return 'awaiting-tool-result';
478
478
  }
479
- telemetry.toolEnd(rawToolCall.toolCallId, execution.outcome);
479
+ await telemetry.toolEnd(rawToolCall.toolCallId, execution.outcome);
480
480
  return 'continued';
481
481
  };
482
482
 
@@ -528,7 +528,7 @@ export function runPrompt<
528
528
  await input.onStopConditionMet?.();
529
529
  const { finishReason, usage } = pendingStopBoundary;
530
530
  releasePendingStopBoundary();
531
- telemetry.end({ finishReason, usage });
531
+ await telemetry.end({ finishReason, usage });
532
532
  await result.finish();
533
533
  return;
534
534
  } else {
@@ -539,7 +539,7 @@ export function runPrompt<
539
539
  // Begin the operation span on stream-start, using the runtime-resolved
540
540
  // model the adapter reports (falling back to the session's model).
541
541
  if (value.type === 'stream-start') {
542
- telemetry.start(value.modelId ?? input.session.modelId);
542
+ await telemetry.start(value.modelId ?? input.session.modelId);
543
543
  }
544
544
 
545
545
  // Open a step span lazily before the first content of each step.
@@ -549,7 +549,7 @@ export function runPrompt<
549
549
  value.type !== 'finish' &&
550
550
  value.type !== 'error'
551
551
  ) {
552
- telemetry.ensureStepOpen();
552
+ await telemetry.ensureStepOpen();
553
553
  }
554
554
 
555
555
  /*
@@ -620,7 +620,7 @@ export function runPrompt<
620
620
  // Telemetry and stderr diagnostics keep the raw error (absolute
621
621
  // paths help debugging); the consumer-facing settle uses the
622
622
  // workDir-stripped one, like every other forwarded part.
623
- telemetry.error(value.error);
623
+ await telemetry.error(value.error);
624
624
  logBridgeError({
625
625
  harnessId: input.harness.harnessId,
626
626
  sessionId: input.session.sessionId,
@@ -673,7 +673,7 @@ export function runPrompt<
673
673
 
674
674
  // Telemetry: close a tool span when its provider-executed result lands.
675
675
  if (value.type === 'tool-result') {
676
- telemetry.toolEnd(
676
+ await telemetry.toolEnd(
677
677
  value.toolCallId,
678
678
  value.isError
679
679
  ? { ok: false, error: value.result }
@@ -736,7 +736,7 @@ export function runPrompt<
736
736
 
737
737
  // Drive step boundaries.
738
738
  if (value.type === 'finish-step') {
739
- completeStep({
739
+ await completeStep({
740
740
  finishReason: value.finishReason,
741
741
  usage: value.usage,
742
742
  providerMetadata: value.harnessMetadata,
@@ -752,7 +752,7 @@ export function runPrompt<
752
752
 
753
753
  if (value.type === 'finish') {
754
754
  finalFinish = value;
755
- telemetry.end({
755
+ await telemetry.end({
756
756
  finishReason: value.finishReason,
757
757
  usage: value.totalUsage,
758
758
  });
@@ -778,7 +778,7 @@ export function runPrompt<
778
778
  toolCallId: toolCall.toolCallId,
779
779
  output,
780
780
  });
781
- telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
781
+ await telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
782
782
  continue;
783
783
  }
784
784
  const customToolApprovalDecision = resolveCustomToolApproval({
@@ -807,7 +807,7 @@ export function runPrompt<
807
807
  toolCallId: toolCall.toolCallId,
808
808
  output,
809
809
  });
810
- telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
810
+ await telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
811
811
  continue;
812
812
  }
813
813
  const pendingApproval =
@@ -905,7 +905,7 @@ export function runPrompt<
905
905
  await finishForHostInputPause({ completeCurrentStep: true });
906
906
  return;
907
907
  }
908
- telemetry.toolEnd(toolCall.toolCallId, execution.outcome);
908
+ await telemetry.toolEnd(toolCall.toolCallId, execution.outcome);
909
909
  }
910
910
  }
911
911
  if (finalFinish != null) {
@@ -923,7 +923,7 @@ export function runPrompt<
923
923
  : undefined,
924
924
  );
925
925
  } catch (err) {
926
- telemetry.error(err);
926
+ await telemetry.error(err);
927
927
  logBridgeError({
928
928
  harnessId: input.harness.harnessId,
929
929
  sessionId: input.session.sessionId,
@@ -1080,6 +1080,7 @@ export async function validateToolCall<TOOLS extends ToolSet>(args: {
1080
1080
  ...(event.providerExecuted !== undefined
1081
1081
  ? { providerExecuted: event.providerExecuted }
1082
1082
  : {}),
1083
+ ...(event.dynamic !== undefined ? { dynamic: event.dynamic } : {}),
1083
1084
  ...(event.providerMetadata !== undefined
1084
1085
  ? { providerMetadata: event.providerMetadata }
1085
1086
  : {}),
@@ -42,9 +42,9 @@ export interface TurnTelemetry {
42
42
  * model the runtime resolved to (overriding the session's configured id).
43
43
  * Idempotent — the first call wins.
44
44
  */
45
- start(modelId?: string): void;
45
+ start(modelId?: string): Promise<void>;
46
46
  /** Open a step span lazily, before the first content of a step. */
47
- ensureStepOpen(): void;
47
+ ensureStepOpen(): Promise<void>;
48
48
  /** Close the current step (on a harness `finish-step`). */
49
49
  stepFinish(info: {
50
50
  finishReason: unknown;
@@ -52,13 +52,13 @@ export interface TurnTelemetry {
52
52
  providerMetadata?: unknown;
53
53
  /** The model's output content for this step (text/reasoning/tool-calls). */
54
54
  content?: TurnContentPart[];
55
- }): void;
55
+ }): Promise<void>;
56
56
  /** A tool execution began (on a `tool-call`). */
57
57
  toolStart(call: {
58
58
  toolCallId: string;
59
59
  toolName: string;
60
60
  input: unknown;
61
- }): void | Promise<void>;
61
+ }): Promise<void>;
62
62
  /** Execute a host tool through each telemetry integration's context wrapper. */
63
63
  executeTool<T>(input: {
64
64
  toolCallId: string;
@@ -72,24 +72,24 @@ export interface TurnTelemetry {
72
72
  toolEnd(
73
73
  toolCallId: string,
74
74
  output: { ok: true; output: unknown } | { ok: false; error: unknown },
75
- ): void;
75
+ ): Promise<void>;
76
76
  /** The turn ended (on a harness `finish`). */
77
- end(info: { finishReason: unknown; usage: unknown }): void;
77
+ end(info: { finishReason: unknown; usage: unknown }): Promise<void>;
78
78
  /** The turn failed. */
79
- error(err: unknown): void;
79
+ error(err: unknown): Promise<void>;
80
80
  }
81
81
 
82
82
  const NOOP: TurnTelemetry = {
83
- start() {},
84
- ensureStepOpen() {},
85
- stepFinish() {},
83
+ async start() {},
84
+ async ensureStepOpen() {},
85
+ async stepFinish() {},
86
86
  async toolStart() {},
87
87
  async executeTool({ execute }) {
88
88
  return await execute();
89
89
  },
90
- toolEnd() {},
91
- end() {},
92
- error() {},
90
+ async toolEnd() {},
91
+ async end() {},
92
+ async error() {},
93
93
  };
94
94
 
95
95
  export function createTurnTelemetry(opts: {
@@ -130,10 +130,10 @@ export function createTurnTelemetry(opts: {
130
130
 
131
131
  // onStart — open the operation (root) span. Deferred until `start()` so the
132
132
  // runtime-resolved model can be attached to the operation span + trace label.
133
- const fireStart = (): void => {
133
+ const fireStart = async (): Promise<void> => {
134
134
  if (started) return;
135
135
  started = true;
136
- dispatcher.onStart?.(
136
+ await dispatcher.onStart?.(
137
137
  cast<'onStart'>({
138
138
  callId,
139
139
  operationId: 'ai.harness',
@@ -155,17 +155,17 @@ export function createTurnTelemetry(opts: {
155
155
  );
156
156
  };
157
157
 
158
- const start = (overrideModelId?: string): void => {
158
+ const start = async (overrideModelId?: string): Promise<void> => {
159
159
  if (started) return;
160
160
  if (overrideModelId) modelId = overrideModelId;
161
- fireStart();
161
+ await fireStart();
162
162
  };
163
163
 
164
- const ensureStepOpen = (): void => {
165
- if (!started) fireStart();
164
+ const ensureStepOpen = async (): Promise<void> => {
165
+ if (!started) await fireStart();
166
166
  if (stepOpen || ended) return;
167
167
  stepOpen = true;
168
- dispatcher.onStepStart?.(
168
+ await dispatcher.onStepStart?.(
169
169
  cast<'onStepStart'>({
170
170
  callId,
171
171
  provider,
@@ -183,7 +183,7 @@ export function createTurnTelemetry(opts: {
183
183
  );
184
184
  // Open the inference (language-model call) span — the gen_ai home for the
185
185
  // step's input and (on end) output messages.
186
- dispatcher.onLanguageModelCallStart?.(
186
+ await dispatcher.onLanguageModelCallStart?.(
187
187
  cast<'onLanguageModelCallStart'>({
188
188
  callId,
189
189
  provider,
@@ -195,12 +195,12 @@ export function createTurnTelemetry(opts: {
195
195
  };
196
196
 
197
197
  /** Close the inference span with the step's output content. */
198
- const inferenceEnd = (info: {
198
+ const inferenceEnd = async (info: {
199
199
  finishReason: unknown;
200
200
  usage: unknown;
201
201
  content: TurnContentPart[];
202
- }): void => {
203
- dispatcher.onLanguageModelCallEnd?.(
202
+ }): Promise<void> => {
203
+ await dispatcher.onLanguageModelCallEnd?.(
204
204
  cast<'onLanguageModelCallEnd'>({
205
205
  callId,
206
206
  finishReason: info.finishReason,
@@ -211,9 +211,9 @@ export function createTurnTelemetry(opts: {
211
211
  );
212
212
  };
213
213
 
214
- const closeOpenTools = (): void => {
214
+ const closeOpenTools = async (): Promise<void> => {
215
215
  for (const call of openTools.values()) {
216
- dispatcher.onToolExecutionEnd?.(
216
+ await dispatcher.onToolExecutionEnd?.(
217
217
  cast<'onToolExecutionEnd'>({
218
218
  callId,
219
219
  toolExecutionMs: 0,
@@ -237,16 +237,16 @@ export function createTurnTelemetry(opts: {
237
237
  start,
238
238
  ensureStepOpen,
239
239
 
240
- stepFinish(info) {
240
+ async stepFinish(info) {
241
241
  if (!stepOpen) return;
242
242
  const content = info.content ?? [];
243
- closeOpenTools();
244
- inferenceEnd({
243
+ await closeOpenTools();
244
+ await inferenceEnd({
245
245
  finishReason: info.finishReason,
246
246
  usage: info.usage,
247
247
  content,
248
248
  });
249
- dispatcher.onStepEnd?.(
249
+ await dispatcher.onStepEnd?.(
250
250
  cast<'onStepEnd'>({
251
251
  callId,
252
252
  stepNumber,
@@ -267,7 +267,7 @@ export function createTurnTelemetry(opts: {
267
267
  },
268
268
 
269
269
  async toolStart(call) {
270
- ensureStepOpen();
270
+ await ensureStepOpen();
271
271
  if (openTools.has(call.toolCallId)) return;
272
272
  openTools.set(call.toolCallId, call);
273
273
  await dispatcher.onToolExecutionStart?.(
@@ -291,11 +291,11 @@ export function createTurnTelemetry(opts: {
291
291
  return await dispatcher.executeTool({ callId, toolCallId, execute });
292
292
  },
293
293
 
294
- toolEnd(toolCallId, output) {
294
+ async toolEnd(toolCallId, output) {
295
295
  const call = openTools.get(toolCallId);
296
296
  if (call == null) return;
297
297
  openTools.delete(toolCallId);
298
- dispatcher.onToolExecutionEnd?.(
298
+ await dispatcher.onToolExecutionEnd?.(
299
299
  cast<'onToolExecutionEnd'>({
300
300
  callId,
301
301
  toolExecutionMs: 0,
@@ -315,17 +315,17 @@ export function createTurnTelemetry(opts: {
315
315
  );
316
316
  },
317
317
 
318
- end(info) {
318
+ async end(info) {
319
319
  if (ended) return;
320
- if (!started) fireStart();
320
+ if (!started) await fireStart();
321
321
  if (stepOpen) {
322
- closeOpenTools();
323
- inferenceEnd({
322
+ await closeOpenTools();
323
+ await inferenceEnd({
324
324
  finishReason: info.finishReason,
325
325
  usage: info.usage,
326
326
  content: [],
327
327
  });
328
- dispatcher.onStepEnd?.(
328
+ await dispatcher.onStepEnd?.(
329
329
  cast<'onStepEnd'>({
330
330
  callId,
331
331
  stepNumber,
@@ -344,7 +344,7 @@ export function createTurnTelemetry(opts: {
344
344
  stepOpen = false;
345
345
  }
346
346
  ended = true;
347
- dispatcher.onEnd?.(
347
+ await dispatcher.onEnd?.(
348
348
  cast<'onEnd'>({
349
349
  callId,
350
350
  operationId: 'ai.harness',
@@ -364,12 +364,12 @@ export function createTurnTelemetry(opts: {
364
364
  );
365
365
  },
366
366
 
367
- error(err) {
367
+ async error(err) {
368
368
  if (ended) return;
369
- if (!started) fireStart();
370
- closeOpenTools();
369
+ if (!started) await fireStart();
370
+ await closeOpenTools();
371
371
  ended = true;
372
- dispatcher.onError?.(err);
372
+ await dispatcher.onError?.(err);
373
373
  },
374
374
  };
375
375
  }