@ai-sdk/harness 1.0.128 → 1.0.130

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.128",
3
+ "version": "1.0.130",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -44,9 +44,9 @@
44
44
  }
45
45
  },
46
46
  "dependencies": {
47
- "@ai-sdk/provider": "4.0.18",
48
- "@ai-sdk/provider-utils": "5.0.49",
49
- "ai": "7.0.118"
47
+ "@ai-sdk/provider": "4.0.19",
48
+ "@ai-sdk/provider-utils": "5.0.50",
49
+ "ai": "7.0.120"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "ws": "^8.21.0",
@@ -58,7 +58,7 @@
58
58
  }
59
59
  },
60
60
  "devDependencies": {
61
- "@ai-sdk/otel": "1.0.118",
61
+ "@ai-sdk/otel": "1.0.120",
62
62
  "@opentelemetry/sdk-trace-base": "2.7.1",
63
63
  "@types/node": "22.19.19",
64
64
  "@types/ws": "^8.5.13",
@@ -67,6 +67,7 @@ type ActiveTurnSettings = {
67
67
  readonly persisted: HarnessV1TurnSettings;
68
68
  readonly tools: ToolSet;
69
69
  readonly toolsContext: Record<string, Context | undefined>;
70
+ readonly runtimeContext: Context;
70
71
  readonly activeTools: ToolSet;
71
72
  readonly builtinToolFiltering: HarnessV1BuiltinToolFiltering | undefined;
72
73
  };
@@ -124,6 +125,7 @@ export class HarnessAgentSession {
124
125
  private readonly resumedToolsContext:
125
126
  | Record<string, Context | undefined>
126
127
  | undefined;
128
+ private readonly resumedRuntimeContext: Context | undefined;
127
129
 
128
130
  /**
129
131
  * Whether this session was created from `resumeFrom` or `continueFrom`.
@@ -143,6 +145,7 @@ export class HarnessAgentSession {
143
145
  pendingToolResults?: readonly HarnessAgentPendingToolResult[];
144
146
  turnSettings?: HarnessV1TurnSettings;
145
147
  resumedToolsContext?: Record<string, Context | undefined>;
148
+ resumedRuntimeContext?: Context;
146
149
  turnState?: HarnessAgentTurnState;
147
150
  }) {
148
151
  this.sessionId = options.sessionId;
@@ -160,6 +163,7 @@ export class HarnessAgentSession {
160
163
  }
161
164
  this.persistedTurnSettings = options.turnSettings;
162
165
  this.resumedToolsContext = options.resumedToolsContext;
166
+ this.resumedRuntimeContext = options.resumedRuntimeContext;
163
167
  this.turnState =
164
168
  options.turnState ??
165
169
  (this.pendingToolApprovals.size > 0
@@ -234,6 +238,7 @@ export class HarnessAgentSession {
234
238
  persisted: this.persistedTurnSettings,
235
239
  tools: options.tools,
236
240
  toolsContext: options.toolsContext,
241
+ runtimeContext: options.runtimeContext,
237
242
  activeTools: options.activeTools,
238
243
  builtinToolFiltering: options.builtinToolFiltering,
239
244
  };
@@ -334,6 +339,7 @@ export class HarnessAgentSession {
334
339
  instructions: options.instructions,
335
340
  tools: options.tools,
336
341
  toolsContext: options.toolsContext,
342
+ runtimeContext: options.runtimeContext,
337
343
  activeTools: options.activeTools,
338
344
  toolSpecs: options.toolSpecs,
339
345
  builtinToolFiltering: options.builtinToolFiltering,
@@ -355,7 +361,7 @@ export class HarnessAgentSession {
355
361
  builtinToolFiltering: turnSettings.builtinToolFiltering,
356
362
  sandboxSession: getRestrictedSandboxSession(sandboxSession),
357
363
  sessionWorkDir: this.sessionWorkDir,
358
- runtimeContext: options.runtimeContext,
364
+ runtimeContext: turnSettings.runtimeContext as RUNTIME_CONTEXT,
359
365
  abortSignal: options.abortSignal,
360
366
  responseFormat: options.responseFormat,
361
367
  output: options.output,
@@ -792,6 +798,7 @@ export class HarnessAgentSession {
792
798
  instructions: string | undefined;
793
799
  tools: ToolSet;
794
800
  toolsContext: Record<string, Context | undefined>;
801
+ runtimeContext: Context;
795
802
  activeTools: ToolSet;
796
803
  toolSpecs: HarnessAgentToolSpec[];
797
804
  builtinToolFiltering: HarnessV1BuiltinToolFiltering | undefined;
@@ -826,6 +833,7 @@ export class HarnessAgentSession {
826
833
  persisted,
827
834
  tools: options.tools,
828
835
  toolsContext: this.resumedToolsContext ?? options.toolsContext,
836
+ runtimeContext: this.resumedRuntimeContext ?? options.runtimeContext,
829
837
  activeTools,
830
838
  builtinToolFiltering: options.builtinToolFiltering,
831
839
  };
@@ -45,8 +45,9 @@ export type HarnessAgentToolApprovalConfiguration = Readonly<
45
45
  export type HarnessAgentSandboxConfig = {
46
46
  /**
47
47
  * Optional fixed working directory for all sessions, relative to the
48
- * sandbox's default working directory. When omitted, sessions keep the
49
- * existing `<harnessId>-<sessionId>` work directory.
48
+ * sandbox's default working directory. Use `'.'` to use the default
49
+ * working directory itself. When omitted, sessions keep the existing
50
+ * `<harnessId>-<sessionId>` work directory.
50
51
  */
51
52
  readonly workDir?: string;
52
53
 
@@ -159,6 +160,12 @@ export type HarnessAgentSettings<
159
160
  */
160
161
  readonly toolsContext?: InferToolSetContext<TUserTools>;
161
162
 
163
+ /**
164
+ * Runtime context passed to lifecycle callbacks and telemetry.
165
+ * `prepareCall` can replace it for each new turn.
166
+ */
167
+ readonly runtimeContext?: RUNTIME_CONTEXT;
168
+
162
169
  /**
163
170
  * Skills made available to the underlying runtime. Each adapter decides how
164
171
  * to surface skills. `prepareCall` can replace them between completed turns.
@@ -233,7 +240,7 @@ export type HarnessAgentSettings<
233
240
  NoInfer<OUTPUT>,
234
241
  CALL_OPTIONS
235
242
  >,
236
- 'model' | 'skills' | 'instructions' | 'tools'
243
+ 'model' | 'skills' | 'instructions' | 'tools' | 'runtimeContext'
237
244
  > & {
238
245
  toolsContext: InferToolSetContext<TUserTools>;
239
246
  },
@@ -246,7 +253,7 @@ export type HarnessAgentSettings<
246
253
  NoInfer<OUTPUT>,
247
254
  CALL_OPTIONS
248
255
  >,
249
- 'model' | 'skills' | 'instructions' | 'tools'
256
+ 'model' | 'skills' | 'instructions' | 'tools' | 'runtimeContext'
250
257
  > & {
251
258
  toolsContext: InferToolSetContext<TUserTools>;
252
259
  } & Omit<Prompt, 'system' | 'instructions' | 'allowSystemInMessages'>
@@ -114,8 +114,10 @@ type PreparedHarnessAgentTurnSettings<
114
114
  type PreparedHarnessAgentPromptTurnInput<
115
115
  THarness extends HarnessAgentAdapter<any>,
116
116
  TUserTools extends ToolSet,
117
+ RUNTIME_CONTEXT extends Context,
117
118
  > = PreparedHarnessAgentTurnSettings<THarness, TUserTools> & {
118
119
  prompt: HarnessAgentPrompt;
120
+ runtimeContext: RUNTIME_CONTEXT;
119
121
  };
120
122
 
121
123
  type PreparedHarnessAgentContinueTurnInput<
@@ -340,6 +342,12 @@ export class HarnessAgent<
340
342
  * non-serializable host objects.
341
343
  */
342
344
  toolsContext?: ToolsContextSettings<TUserTools>['toolsContext'];
345
+ /**
346
+ * Rebinds host-only runtime context for an unfinished turn resumed with
347
+ * `continueFrom` (directly or through `resumeFrom`). Runtime context is
348
+ * not serialized into lifecycle state.
349
+ */
350
+ runtimeContext?: RUNTIME_CONTEXT;
343
351
  /**
344
352
  * Existing sandbox session to run the harness in. When provided, the
345
353
  * caller retains ownership of the sandbox lifecycle.
@@ -611,6 +619,7 @@ export class HarnessAgent<
611
619
  pendingToolResults: effectiveContinueFrom?.pendingToolResults,
612
620
  turnSettings: effectiveContinueFrom?.turnSettings,
613
621
  resumedToolsContext: options?.toolsContext,
622
+ resumedRuntimeContext: options?.runtimeContext,
614
623
  turnState:
615
624
  effectiveContinueFrom == null
616
625
  ? 'idle'
@@ -646,10 +655,11 @@ export class HarnessAgent<
646
655
  >
647
656
  > {
648
657
  const continueTurnInput = this._resolveContinueTurnInput(options);
649
- const runtimeContext = {} as RUNTIME_CONTEXT;
658
+ const runtimeContext =
659
+ this.settings.runtimeContext ?? ({} as RUNTIME_CONTEXT);
650
660
  const { result, done } =
651
661
  continueTurnInput == null
652
- ? await this._startPromptTurn({ options, runtimeContext })
662
+ ? await this._startPromptTurn({ options })
653
663
  : await this._startContinueTurn({
654
664
  session: options.session,
655
665
  turnInput: continueTurnInput,
@@ -675,10 +685,11 @@ export class HarnessAgent<
675
685
  >
676
686
  > {
677
687
  const continueTurnInput = this._resolveContinueTurnInput(options);
678
- const runtimeContext = {} as RUNTIME_CONTEXT;
688
+ const runtimeContext =
689
+ this.settings.runtimeContext ?? ({} as RUNTIME_CONTEXT);
679
690
  const { result, ready } =
680
691
  continueTurnInput == null
681
- ? await this._startPromptTurn({ options, runtimeContext })
692
+ ? await this._startPromptTurn({ options })
682
693
  : await this._startContinueTurn({
683
694
  session: options.session,
684
695
  turnInput: continueTurnInput,
@@ -706,7 +717,8 @@ export class HarnessAgent<
706
717
  OUTPUT
707
718
  >
708
719
  > {
709
- const runtimeContext = {} as RUNTIME_CONTEXT;
720
+ const runtimeContext =
721
+ this.settings.runtimeContext ?? ({} as RUNTIME_CONTEXT);
710
722
  const { result, done } = await this._startContinueTurn({
711
723
  session: options.session,
712
724
  turnInput: {
@@ -740,7 +752,8 @@ export class HarnessAgent<
740
752
  OUTPUT
741
753
  >
742
754
  > {
743
- const runtimeContext = {} as RUNTIME_CONTEXT;
755
+ const runtimeContext =
756
+ this.settings.runtimeContext ?? ({} as RUNTIME_CONTEXT);
744
757
  const { result, ready } = await this._startContinueTurn({
745
758
  session: options.session,
746
759
  turnInput: {
@@ -777,7 +790,6 @@ export class HarnessAgent<
777
790
  RUNTIME_CONTEXT
778
791
  > &
779
792
  HarnessAgentCallExtensions;
780
- runtimeContext: RUNTIME_CONTEXT;
781
793
  }): Promise<
782
794
  HarnessAgentTurnResult<THarness, TUserTools, RUNTIME_CONTEXT, OUTPUT>
783
795
  > {
@@ -791,7 +803,7 @@ export class HarnessAgent<
791
803
  >({
792
804
  ...this._buildTurnOptions({
793
805
  turnSettings: turnInput,
794
- runtimeContext: input.runtimeContext,
806
+ runtimeContext: turnInput.runtimeContext,
795
807
  abortSignal: input.options.abortSignal,
796
808
  responseFormat,
797
809
  callbacks: this._resolveLifecycleCallbacks(input.options),
@@ -960,7 +972,9 @@ export class HarnessAgent<
960
972
  RUNTIME_CONTEXT
961
973
  > &
962
974
  HarnessAgentCallExtensions,
963
- ): Promise<PreparedHarnessAgentPromptTurnInput<THarness, TUserTools>> {
975
+ ): Promise<
976
+ PreparedHarnessAgentPromptTurnInput<THarness, TUserTools, RUNTIME_CONTEXT>
977
+ > {
964
978
  let callOptions = options;
965
979
  if (
966
980
  this.settings.callOptionsSchema != null &&
@@ -1002,6 +1016,7 @@ export class HarnessAgent<
1002
1016
  skills: this.settings.skills,
1003
1017
  instructions: this.settings.instructions,
1004
1018
  tools: this.settings.tools,
1019
+ runtimeContext: this.settings.runtimeContext,
1005
1020
  toolsContext:
1006
1021
  this.settings.toolsContext ?? ({} as InferToolSetContext<TUserTools>),
1007
1022
  ...promptOptions,
@@ -1028,6 +1043,8 @@ export class HarnessAgent<
1028
1043
 
1029
1044
  return {
1030
1045
  prompt: this._resolvePromptTurnInput(preparedCallArgs),
1046
+ runtimeContext:
1047
+ preparedCallArgs.runtimeContext ?? ({} as RUNTIME_CONTEXT),
1031
1048
  ...this._prepareTurnSettings({
1032
1049
  model: preparedCallArgs.model,
1033
1050
  skills: preparedCallArgs.skills,
@@ -60,7 +60,7 @@ export function normalizeSandboxWorkDir(workDir: string): string {
60
60
 
61
61
  const normalized = posix.normalize(workDir);
62
62
  if (
63
- normalized === '.' ||
63
+ ((normalized === '.' || normalized === './') && workDir !== '.') ||
64
64
  normalized === '..' ||
65
65
  normalized.startsWith('../')
66
66
  ) {
@@ -4,7 +4,7 @@ import type {
4
4
  ModelMessage,
5
5
  ToolSet,
6
6
  } from '@ai-sdk/provider-utils';
7
- import { createTelemetryDispatcher } from 'ai/internal';
7
+ import { createRestrictedTelemetryDispatcher } from 'ai/internal';
8
8
  import type {
9
9
  ContentPart,
10
10
  GenerateTextOnEndCallback,
@@ -42,7 +42,7 @@ export type HarnessAgentLifecycleCallbacks<
42
42
  onEnd?: GenerateTextOnEndCallback<TOOLS, RUNTIME_CONTEXT>;
43
43
  };
44
44
 
45
- type Dispatcher = ReturnType<typeof createTelemetryDispatcher>;
45
+ type Dispatcher = ReturnType<typeof createRestrictedTelemetryDispatcher>;
46
46
 
47
47
  export interface TurnLifecycle<
48
48
  TOOLS extends ToolSet,
@@ -107,7 +107,11 @@ export function createTurnLifecycle<
107
107
  const telemetry =
108
108
  options.telemetry == null
109
109
  ? ({} as Dispatcher)
110
- : createTelemetryDispatcher({ telemetry: options.telemetry });
110
+ : createRestrictedTelemetryDispatcher<TOOLS, RUNTIME_CONTEXT, OUTPUT>({
111
+ telemetry: options.telemetry,
112
+ includeRuntimeContext: options.telemetry.includeRuntimeContext,
113
+ includeToolsContext: options.telemetry.includeToolsContext,
114
+ });
111
115
  const provider = `harness:${options.harnessId}`;
112
116
  let modelId = options.modelId ?? '';
113
117
  let started = false;