@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/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @ai-sdk/harness
2
2
 
3
+ ## 1.0.130
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [b032d70]
8
+ - Updated dependencies [e21b98b]
9
+ - ai@7.0.120
10
+
11
+ ## 1.0.129
12
+
13
+ ### Patch Changes
14
+
15
+ - e5aeb11: feat(harness): allow setting `HarnessAgent`'s `workDir` to "." to use the sandbox's default working directory
16
+ - d99d6dc: fix(harness): forward configured runtime context to callbacks and telemetry
17
+ - Updated dependencies [33e94ba]
18
+ - Updated dependencies [34d869e]
19
+ - Updated dependencies [e3605f6]
20
+ - Updated dependencies [def4df8]
21
+ - Updated dependencies [525efc5]
22
+ - ai@7.0.119
23
+ - @ai-sdk/provider-utils@5.0.50
24
+ - @ai-sdk/provider@4.0.19
25
+
3
26
  ## 1.0.128
4
27
 
5
28
  ### Patch Changes
@@ -1259,8 +1259,9 @@ type HarnessAgentToolApprovalConfiguration = Readonly<Record<string, ToolApprova
1259
1259
  type HarnessAgentSandboxConfig = {
1260
1260
  /**
1261
1261
  * Optional fixed working directory for all sessions, relative to the
1262
- * sandbox's default working directory. When omitted, sessions keep the
1263
- * existing `<harnessId>-<sessionId>` work directory.
1262
+ * sandbox's default working directory. Use `'.'` to use the default
1263
+ * working directory itself. When omitted, sessions keep the existing
1264
+ * `<harnessId>-<sessionId>` work directory.
1264
1265
  */
1265
1266
  readonly workDir?: string;
1266
1267
  /**
@@ -1354,6 +1355,11 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
1354
1355
  * `prepareCall` can replace it for each new turn.
1355
1356
  */
1356
1357
  readonly toolsContext?: InferToolSetContext<TUserTools>;
1358
+ /**
1359
+ * Runtime context passed to lifecycle callbacks and telemetry.
1360
+ * `prepareCall` can replace it for each new turn.
1361
+ */
1362
+ readonly runtimeContext?: RUNTIME_CONTEXT;
1357
1363
  /**
1358
1364
  * Skills made available to the underlying runtime. Each adapter decides how
1359
1365
  * to surface skills. `prepareCall` can replace them between completed turns.
@@ -1393,9 +1399,9 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
1393
1399
  * })
1394
1400
  * ```
1395
1401
  */
1396
- readonly prepareCall?: (options: Omit<AgentCallParameters<CALL_OPTIONS, HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT>, 'abortSignal' | 'timeout' | 'onStart' | 'experimental_onStart' | 'onStepStart' | 'experimental_onStepStart' | 'onToolExecutionStart' | 'experimental_onToolCallStart' | 'onToolExecutionEnd' | 'experimental_onToolCallFinish' | 'onStepEnd' | 'onStepFinish' | 'onEnd' | 'onFinish' | 'experimental_sandbox'> & Pick<HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT, NoInfer<OUTPUT>, CALL_OPTIONS>, 'model' | 'skills' | 'instructions' | 'tools'> & {
1402
+ readonly prepareCall?: (options: Omit<AgentCallParameters<CALL_OPTIONS, HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT>, 'abortSignal' | 'timeout' | 'onStart' | 'experimental_onStart' | 'onStepStart' | 'experimental_onStepStart' | 'onToolExecutionStart' | 'experimental_onToolCallStart' | 'onToolExecutionEnd' | 'experimental_onToolCallFinish' | 'onStepEnd' | 'onStepFinish' | 'onEnd' | 'onFinish' | 'experimental_sandbox'> & Pick<HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT, NoInfer<OUTPUT>, CALL_OPTIONS>, 'model' | 'skills' | 'instructions' | 'tools' | 'runtimeContext'> & {
1397
1403
  toolsContext: InferToolSetContext<TUserTools>;
1398
- }) => MaybePromiseLike<Pick<HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT, NoInfer<OUTPUT>, CALL_OPTIONS>, 'model' | 'skills' | 'instructions' | 'tools'> & {
1404
+ }) => MaybePromiseLike<Pick<HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT, NoInfer<OUTPUT>, CALL_OPTIONS>, 'model' | 'skills' | 'instructions' | 'tools' | 'runtimeContext'> & {
1399
1405
  toolsContext: InferToolSetContext<TUserTools>;
1400
1406
  } & Omit<Prompt, 'system' | 'instructions' | 'allowSystemInMessages'>>;
1401
1407
  /**
@@ -1549,6 +1555,7 @@ declare class HarnessAgentSession {
1549
1555
  private activeTurnSettings;
1550
1556
  private persistedTurnSettings;
1551
1557
  private readonly resumedToolsContext;
1558
+ private readonly resumedRuntimeContext;
1552
1559
  /**
1553
1560
  * Whether this session was created from `resumeFrom` or `continueFrom`.
1554
1561
  * Captured at construction so it survives lifecycle cleanup.
@@ -1566,6 +1573,7 @@ declare class HarnessAgentSession {
1566
1573
  pendingToolResults?: readonly HarnessAgentPendingToolResult[];
1567
1574
  turnSettings?: HarnessV1TurnSettings;
1568
1575
  resumedToolsContext?: Record<string, Context | undefined>;
1576
+ resumedRuntimeContext?: Context;
1569
1577
  turnState?: HarnessAgentTurnState;
1570
1578
  });
1571
1579
  hasUnfinishedTurn(): boolean;
@@ -1783,6 +1791,12 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
1783
1791
  * non-serializable host objects.
1784
1792
  */
1785
1793
  toolsContext?: ToolsContextSettings<TUserTools>['toolsContext'];
1794
+ /**
1795
+ * Rebinds host-only runtime context for an unfinished turn resumed with
1796
+ * `continueFrom` (directly or through `resumeFrom`). Runtime context is
1797
+ * not serialized into lifecycle state.
1798
+ */
1799
+ runtimeContext?: RUNTIME_CONTEXT;
1786
1800
  /**
1787
1801
  * Existing sandbox session to run the harness in. When provided, the
1788
1802
  * caller retains ownership of the sandbox lifecycle.
@@ -1223,7 +1223,7 @@ function stripDeep(value, workDir) {
1223
1223
  }
1224
1224
 
1225
1225
  // src/agent/internal/turn-telemetry.ts
1226
- import { createTelemetryDispatcher } from "ai/internal";
1226
+ import { createRestrictedTelemetryDispatcher } from "ai/internal";
1227
1227
  async function notify(event, ...callbacks) {
1228
1228
  await Promise.allSettled(
1229
1229
  callbacks.map(async (callback) => {
@@ -1232,7 +1232,11 @@ async function notify(event, ...callbacks) {
1232
1232
  );
1233
1233
  }
1234
1234
  function createTurnLifecycle(options) {
1235
- const telemetry = options.telemetry == null ? {} : createTelemetryDispatcher({ telemetry: options.telemetry });
1235
+ const telemetry = options.telemetry == null ? {} : createRestrictedTelemetryDispatcher({
1236
+ telemetry: options.telemetry,
1237
+ includeRuntimeContext: options.telemetry.includeRuntimeContext,
1238
+ includeToolsContext: options.telemetry.includeToolsContext
1239
+ });
1236
1240
  const provider = `harness:${options.harnessId}`;
1237
1241
  let modelId = options.modelId ?? "";
1238
1242
  let started = false;
@@ -2777,6 +2781,7 @@ var HarnessAgentSession = class {
2777
2781
  }
2778
2782
  this.persistedTurnSettings = options.turnSettings;
2779
2783
  this.resumedToolsContext = options.resumedToolsContext;
2784
+ this.resumedRuntimeContext = options.resumedRuntimeContext;
2780
2785
  this.turnState = options.turnState ?? (this.pendingToolApprovals.size > 0 ? "awaiting-approval" : this.pendingToolResults.size > 0 ? "awaiting-tool-result" : "idle");
2781
2786
  this.isResume = options.underlyingSession.isResume;
2782
2787
  }
@@ -2818,6 +2823,7 @@ var HarnessAgentSession = class {
2818
2823
  persisted: this.persistedTurnSettings,
2819
2824
  tools: options.tools,
2820
2825
  toolsContext: options.toolsContext,
2826
+ runtimeContext: options.runtimeContext,
2821
2827
  activeTools: options.activeTools,
2822
2828
  builtinToolFiltering: options.builtinToolFiltering
2823
2829
  };
@@ -2893,6 +2899,7 @@ var HarnessAgentSession = class {
2893
2899
  instructions: options.instructions,
2894
2900
  tools: options.tools,
2895
2901
  toolsContext: options.toolsContext,
2902
+ runtimeContext: options.runtimeContext,
2896
2903
  activeTools: options.activeTools,
2897
2904
  toolSpecs: options.toolSpecs,
2898
2905
  builtinToolFiltering: options.builtinToolFiltering
@@ -2914,7 +2921,7 @@ var HarnessAgentSession = class {
2914
2921
  builtinToolFiltering: turnSettings.builtinToolFiltering,
2915
2922
  sandboxSession: getRestrictedSandboxSession(sandboxSession),
2916
2923
  sessionWorkDir: this.sessionWorkDir,
2917
- runtimeContext: options.runtimeContext,
2924
+ runtimeContext: turnSettings.runtimeContext,
2918
2925
  abortSignal: options.abortSignal,
2919
2926
  responseFormat: options.responseFormat,
2920
2927
  output: options.output,
@@ -3296,6 +3303,7 @@ var HarnessAgentSession = class {
3296
3303
  persisted,
3297
3304
  tools: options.tools,
3298
3305
  toolsContext: this.resumedToolsContext ?? options.toolsContext,
3306
+ runtimeContext: this.resumedRuntimeContext ?? options.runtimeContext,
3299
3307
  activeTools,
3300
3308
  builtinToolFiltering: options.builtinToolFiltering
3301
3309
  };
@@ -3620,7 +3628,7 @@ function normalizeSandboxWorkDir(workDir) {
3620
3628
  throw new Error("HarnessAgent: `sandboxConfig.workDir` must be relative.");
3621
3629
  }
3622
3630
  const normalized = posix6.normalize(workDir);
3623
- if (normalized === "." || normalized === ".." || normalized.startsWith("../")) {
3631
+ if ((normalized === "." || normalized === "./") && workDir !== "." || normalized === ".." || normalized.startsWith("../")) {
3624
3632
  throw new Error(
3625
3633
  "HarnessAgent: `sandboxConfig.workDir` must stay inside the sandbox default working directory."
3626
3634
  );
@@ -4310,6 +4318,7 @@ var HarnessAgent = class {
4310
4318
  pendingToolResults: effectiveContinueFrom?.pendingToolResults,
4311
4319
  turnSettings: effectiveContinueFrom?.turnSettings,
4312
4320
  resumedToolsContext: options?.toolsContext,
4321
+ resumedRuntimeContext: options?.runtimeContext,
4313
4322
  turnState: effectiveContinueFrom == null ? "idle" : effectiveContinueFrom.pendingToolApprovals != null && effectiveContinueFrom.pendingToolApprovals.length > 0 ? "awaiting-approval" : effectiveContinueFrom.pendingToolResults != null && effectiveContinueFrom.pendingToolResults.length > 0 ? "awaiting-tool-result" : "suspended"
4314
4323
  });
4315
4324
  } catch (error) {
@@ -4322,8 +4331,8 @@ var HarnessAgent = class {
4322
4331
  }
4323
4332
  async generate(options) {
4324
4333
  const continueTurnInput = this._resolveContinueTurnInput(options);
4325
- const runtimeContext = {};
4326
- const { result, done } = continueTurnInput == null ? await this._startPromptTurn({ options, runtimeContext }) : await this._startContinueTurn({
4334
+ const runtimeContext = this.settings.runtimeContext ?? {};
4335
+ const { result, done } = continueTurnInput == null ? await this._startPromptTurn({ options }) : await this._startContinueTurn({
4327
4336
  session: options.session,
4328
4337
  turnInput: continueTurnInput,
4329
4338
  runtimeContext,
@@ -4334,8 +4343,8 @@ var HarnessAgent = class {
4334
4343
  }
4335
4344
  async stream(options) {
4336
4345
  const continueTurnInput = this._resolveContinueTurnInput(options);
4337
- const runtimeContext = {};
4338
- const { result, ready } = continueTurnInput == null ? await this._startPromptTurn({ options, runtimeContext }) : await this._startContinueTurn({
4346
+ const runtimeContext = this.settings.runtimeContext ?? {};
4347
+ const { result, ready } = continueTurnInput == null ? await this._startPromptTurn({ options }) : await this._startContinueTurn({
4339
4348
  session: options.session,
4340
4349
  turnInput: continueTurnInput,
4341
4350
  runtimeContext,
@@ -4350,7 +4359,7 @@ var HarnessAgent = class {
4350
4359
  * consuming a turn that crossed a process boundary.
4351
4360
  */
4352
4361
  async continueGenerate(options) {
4353
- const runtimeContext = {};
4362
+ const runtimeContext = this.settings.runtimeContext ?? {};
4354
4363
  const { result, done } = await this._startContinueTurn({
4355
4364
  session: options.session,
4356
4365
  turnInput: {
@@ -4372,7 +4381,7 @@ var HarnessAgent = class {
4372
4381
  * follows from how the adapter resumed the session.
4373
4382
  */
4374
4383
  async continueStream(options) {
4375
- const runtimeContext = {};
4384
+ const runtimeContext = this.settings.runtimeContext ?? {};
4376
4385
  const { result, ready } = await this._startContinueTurn({
4377
4386
  session: options.session,
4378
4387
  turnInput: {
@@ -4402,7 +4411,7 @@ var HarnessAgent = class {
4402
4411
  return input.options.session.promptTurn({
4403
4412
  ...this._buildTurnOptions({
4404
4413
  turnSettings: turnInput,
4405
- runtimeContext: input.runtimeContext,
4414
+ runtimeContext: turnInput.runtimeContext,
4406
4415
  abortSignal: input.options.abortSignal,
4407
4416
  responseFormat,
4408
4417
  callbacks: this._resolveLifecycleCallbacks(input.options)
@@ -4548,6 +4557,7 @@ var HarnessAgent = class {
4548
4557
  skills: this.settings.skills,
4549
4558
  instructions: this.settings.instructions,
4550
4559
  tools: this.settings.tools,
4560
+ runtimeContext: this.settings.runtimeContext,
4551
4561
  toolsContext: this.settings.toolsContext ?? {},
4552
4562
  ...promptOptions
4553
4563
  };
@@ -4561,6 +4571,7 @@ var HarnessAgent = class {
4561
4571
  }
4562
4572
  return {
4563
4573
  prompt: this._resolvePromptTurnInput(preparedCallArgs),
4574
+ runtimeContext: preparedCallArgs.runtimeContext ?? {},
4564
4575
  ...this._prepareTurnSettings({
4565
4576
  model: preparedCallArgs.model,
4566
4577
  skills: preparedCallArgs.skills,