@ai-sdk/harness 1.0.100 → 1.0.102

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,35 @@
1
1
  # @ai-sdk/harness
2
2
 
3
+ ## 1.0.102
4
+
5
+ ### Patch Changes
6
+
7
+ - fe86f8f: feat(harness): support established lifecycle callbacks from `ToolLoopAgent` on `HarnessAgent` too
8
+ - 255cccf: feat(harness): add `writeInstructions` helper and support filesystem based `instructionsMapping` in ACP backed harness adapters
9
+ - eeed977: feat(harness): allow passing arbitrary headers with inference requests via `headers` property in `HarnessAgentSettings`
10
+ - a39c8bf: chore(harness): clarify `writeSkills` helper intent to require materializing skills in HOME directory
11
+ - Updated dependencies [df6c009]
12
+ - Updated dependencies [6ee74a3]
13
+ - Updated dependencies [f13d371]
14
+ - Updated dependencies [d4485fe]
15
+ - Updated dependencies [4f201cc]
16
+ - Updated dependencies [8cdb2a7]
17
+ - Updated dependencies [0f2281e]
18
+ - Updated dependencies [fc8e8ac]
19
+ - Updated dependencies [ee8391e]
20
+ - ai@7.0.93
21
+
22
+ ## 1.0.101
23
+
24
+ ### Patch Changes
25
+
26
+ - 951c54d: feat(harness): support `askUserQuestions` tool including support for normalization across harness adapters
27
+ - Updated dependencies [a51cc94]
28
+ - Updated dependencies [d1904d3]
29
+ - Updated dependencies [84e5a79]
30
+ - Updated dependencies [a8e8ad0]
31
+ - ai@7.0.92
32
+
3
33
  ## 1.0.100
4
34
 
5
35
  ### Patch Changes
package/agent/index.ts CHANGED
@@ -28,14 +28,8 @@ export type {
28
28
  HarnessAgentToolSpec,
29
29
  } from '../src/agent/harness-agent-types';
30
30
  export { HarnessAgentSession } from '../src/agent/harness-agent-session';
31
- export {
32
- collectHarnessAgentToolApprovalContinuations,
33
- type HarnessAgentToolApprovalContinuation,
34
- } from '../src/agent/harness-agent-tool-approval-continuation';
35
- export {
36
- collectHarnessAgentToolResultContinuations,
37
- type HarnessAgentToolResultContinuation,
38
- } from '../src/agent/harness-agent-tool-result-continuation';
31
+ export { collectHarnessAgentToolApprovalContinuations } from '../src/agent/harness-agent-tool-approval-continuation';
32
+ export { collectHarnessAgentToolResultContinuations } from '../src/agent/harness-agent-tool-result-continuation';
39
33
  export {
40
34
  prepareHarnessSandboxTemplate,
41
35
  prewarmHarness,
@@ -1,6 +1,6 @@
1
1
  import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
2
- import { Experimental_SandboxSession, UserModelMessage, ToolSet, FlexibleSchema, Tool, Context, MaybePromiseLike, Arrayable, ToolApprovalResponse, ModelMessage } from '@ai-sdk/provider-utils';
3
- import { OutputInterface, AgentCallParameters, Prompt, StopCondition, ToolApprovalStatus, TelemetryOptions, ActiveTools, StreamTextResult, Agent, GenerateTextResult, AgentStreamParameters, Telemetry } from 'ai';
2
+ import { Experimental_SandboxSession, UserModelMessage, ToolResultPart, ProviderOptions, ToolSet, FlexibleSchema, Tool, Context, MaybePromiseLike, Arrayable, ToolApprovalResponse, ModelMessage } from '@ai-sdk/provider-utils';
3
+ import { OutputInterface, AgentCallParameters, Prompt, StopCondition, GenerateTextOnStartCallback, GenerateTextOnStepStartCallback, OnLanguageModelCallStartCallback, OnLanguageModelCallEndCallback, OnToolExecutionStartCallback, OnToolExecutionEndCallback, GenerateTextOnStepEndCallback, GenerateTextOnEndCallback, ToolApprovalStatus, TelemetryOptions, ActiveTools, StreamTextResult, Agent, GenerateTextResult, AgentStreamParameters, Telemetry } from 'ai';
4
4
  import { z } from 'zod/v4';
5
5
  import { JSONSchema7, JSONValue, LanguageModelV4StreamPart, LanguageModelV4ToolCall, LanguageModelV4ToolApprovalRequest, LanguageModelV4ToolResult, LanguageModelV4FinishReason, LanguageModelV4Usage, AISDKError } from '@ai-sdk/provider';
6
6
 
@@ -347,6 +347,7 @@ type HarnessV1PromptControl = {
347
347
  toolCallId: string;
348
348
  output: unknown;
349
349
  isError?: boolean;
350
+ toolResult?: ToolResultPart;
350
351
  }): PromiseLike<void>;
351
352
  /**
352
353
  * Respond to a `tool-approval-request` the adapter emitted.
@@ -465,6 +466,7 @@ type HarnessV1PendingToolResult = {
465
466
  readonly toolCallId: string;
466
467
  readonly toolName: string;
467
468
  readonly input: string;
469
+ readonly providerOptions?: ProviderOptions;
468
470
  };
469
471
  /**
470
472
  * Framework-owned settings captured when a turn begins. The same settings are
@@ -695,6 +697,10 @@ type HarnessV1BuiltinToolFiltering = {
695
697
  * calling the adapter, so adapters never need to derive provider-specific paths.
696
698
  */
697
699
  type HarnessV1StartOptions = {
700
+ /**
701
+ * Additional normalized HTTP headers to send with model requests.
702
+ */
703
+ readonly headers?: Readonly<Record<string, string>>;
698
704
  /**
699
705
  * Stable identifier for this harness session. Used as the underlying
700
706
  * resource name where the adapter has a notion of a named session
@@ -1015,6 +1021,40 @@ declare const HARNESS_V1_BUILTIN_TOOLS: {
1015
1021
  readonly webSearch: Tool<{
1016
1022
  query: string;
1017
1023
  }, unknown, _ai_sdk_provider_utils.Context>;
1024
+ readonly askUserQuestions: _ai_sdk_provider_utils.FunctionTool<{
1025
+ allowPartialAnswers: boolean;
1026
+ questions: {
1027
+ id: string;
1028
+ question: string;
1029
+ header?: string | undefined;
1030
+ options?: {
1031
+ id: string;
1032
+ label: string;
1033
+ description?: string | undefined;
1034
+ preview?: string | undefined;
1035
+ }[] | undefined;
1036
+ allowMultiple?: boolean | undefined;
1037
+ allowFreeForm?: boolean | {
1038
+ secret: boolean;
1039
+ } | undefined;
1040
+ }[];
1041
+ }, {
1042
+ action: "answered";
1043
+ answers: Record<string, {
1044
+ optionIds: string[];
1045
+ freeform?: string | undefined;
1046
+ }>;
1047
+ } | {
1048
+ action: "partially-answered";
1049
+ answers: Record<string, {
1050
+ optionIds: string[];
1051
+ freeform?: string | undefined;
1052
+ }>;
1053
+ } | {
1054
+ action: "declined";
1055
+ } | {
1056
+ action: "cancelled";
1057
+ }>;
1018
1058
  };
1019
1059
  type HarnessV1BuiltinToolName = keyof typeof HARNESS_V1_BUILTIN_TOOLS;
1020
1060
  type HarnessV1BuiltinToolUseKind = 'readonly' | 'edit' | 'bash';
@@ -1248,10 +1288,12 @@ type HarnessTools<TOOLS extends ToolSet> = ActiveTools<NoInfer<TOOLS>>;
1248
1288
  /**
1249
1289
  * Construction-time settings for a `HarnessAgent`.
1250
1290
  *
1251
- * Prompt, abortSignal, callbacks, and custom call options belong on the
1291
+ * Prompt, abortSignal, and custom call options belong on the
1252
1292
  * `AgentCallParameters` / `AgentStreamParameters` passed to `generate` /
1253
- * `stream`. `prepareCall` can derive turn-scoped model, skills, instructions,
1254
- * and tools from those custom call options.
1293
+ * `stream`. Lifecycle callbacks can be configured here for every call, while
1294
+ * the callbacks supported by `AgentCallParameters` can also be added per call.
1295
+ * `prepareCall` can derive turn-scoped model, skills, instructions, and tools
1296
+ * from custom call options.
1255
1297
  */
1256
1298
  type HarnessAgentToolFilteringSettings<TOOLS extends ToolSet> = {
1257
1299
  /**
@@ -1308,6 +1350,13 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
1308
1350
  * turns.
1309
1351
  */
1310
1352
  readonly instructions?: string;
1353
+ /**
1354
+ * Additional HTTP headers to be sent with every model request.
1355
+ *
1356
+ * `authorization`, `x-api-key`, `user-agent`, and `x-client-app` are
1357
+ * managed by the harness and are not allowed.
1358
+ */
1359
+ readonly headers?: Record<string, string | undefined>;
1311
1360
  /**
1312
1361
  * Schema for validating the custom options passed to each agent call.
1313
1362
  */
@@ -1343,6 +1392,39 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
1343
1392
  * When omitted, the harness runs until the turn naturally finishes or pauses.
1344
1393
  */
1345
1394
  readonly stopWhen?: Arrayable<StopCondition<NoInfer<HarnessAllTools<THarness, TUserTools>>, RUNTIME_CONTEXT>>;
1395
+ /**
1396
+ * Called when an agent call begins, before any model steps.
1397
+ */
1398
+ readonly onStart?: GenerateTextOnStartCallback<NoInfer<HarnessAllTools<THarness, TUserTools>>, RUNTIME_CONTEXT, NoInfer<OUTPUT>>;
1399
+ /**
1400
+ * Called when a model step begins.
1401
+ */
1402
+ readonly onStepStart?: GenerateTextOnStepStartCallback<NoInfer<HarnessAllTools<THarness, TUserTools>>, NoInfer<RUNTIME_CONTEXT>, NoInfer<OUTPUT>>;
1403
+ /**
1404
+ * Called immediately before the harness begins emitting a model response.
1405
+ */
1406
+ readonly onLanguageModelCallStart?: OnLanguageModelCallStartCallback;
1407
+ /**
1408
+ * Called after a model response is complete and before its tool execution
1409
+ * lifecycle callbacks are delivered.
1410
+ */
1411
+ readonly onLanguageModelCallEnd?: OnLanguageModelCallEndCallback<NoInfer<HarnessAllTools<THarness, TUserTools>>>;
1412
+ /**
1413
+ * Called before each harness or host tool execution is reported.
1414
+ */
1415
+ readonly onToolExecutionStart?: OnToolExecutionStartCallback<NoInfer<HarnessAllTools<THarness, TUserTools>>>;
1416
+ /**
1417
+ * Called after each harness or host tool execution is reported.
1418
+ */
1419
+ readonly onToolExecutionEnd?: OnToolExecutionEndCallback<NoInfer<HarnessAllTools<THarness, TUserTools>>>;
1420
+ /**
1421
+ * Called after each completed model step.
1422
+ */
1423
+ readonly onStepEnd?: GenerateTextOnStepEndCallback<NoInfer<HarnessAllTools<THarness, TUserTools>>, NoInfer<RUNTIME_CONTEXT>>;
1424
+ /**
1425
+ * Called when an agent call completes successfully.
1426
+ */
1427
+ readonly onEnd?: GenerateTextOnEndCallback<NoInfer<HarnessAllTools<THarness, TUserTools>>, NoInfer<RUNTIME_CONTEXT>>;
1346
1428
  /**
1347
1429
  * Built-in tool permission mode. Defaults to `'allow-all'`, preserving the
1348
1430
  * existing bypass-permissions behavior unless users opt in.
@@ -1391,43 +1473,16 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
1391
1473
  readonly onLog?: (event: HarnessDiagnostic) => void;
1392
1474
  } & HarnessAgentToolFilteringSettings<HarnessAllTools<THarness, TUserTools>>;
1393
1475
 
1394
- type HarnessAgentToolApprovalContinuation = {
1395
- readonly approvalResponse: ToolApprovalResponse;
1396
- readonly toolCall: {
1397
- readonly type: 'tool-call';
1398
- readonly toolCallId: string;
1399
- readonly toolName: string;
1400
- readonly input: unknown;
1401
- readonly providerExecuted?: boolean;
1402
- };
1403
- };
1404
- /**
1405
- * Extract approval decisions that should continue a suspended harness turn.
1406
- *
1407
- * AI SDK clients send approval decisions as a trailing `role: "tool"` message
1408
- * containing `tool-approval-response` parts. The response only carries the
1409
- * approval id, so the harness has to recover the matching approval request
1410
- * locally to find the original tool call before it can resume the paused turn.
1411
- * Responses that already have a tool result are ignored, because those
1412
- * approvals were already consumed by a prior continuation.
1413
- */
1414
- declare function collectHarnessAgentToolApprovalContinuations(input: {
1415
- messages: readonly ModelMessage[];
1416
- }): readonly HarnessAgentToolApprovalContinuation[];
1417
-
1418
- type HarnessAgentToolResultContinuation = {
1419
- readonly toolCallId: string;
1420
- readonly output: unknown;
1421
- readonly isError?: boolean;
1476
+ type HarnessAgentLifecycleCallbacks<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Context, OUTPUT extends OutputInterface> = {
1477
+ onStart?: GenerateTextOnStartCallback<TOOLS, RUNTIME_CONTEXT, OUTPUT>;
1478
+ onStepStart?: GenerateTextOnStepStartCallback<TOOLS, RUNTIME_CONTEXT, OUTPUT>;
1479
+ onLanguageModelCallStart?: OnLanguageModelCallStartCallback;
1480
+ onLanguageModelCallEnd?: OnLanguageModelCallEndCallback<TOOLS>;
1481
+ onToolExecutionStart?: OnToolExecutionStartCallback<TOOLS>;
1482
+ onToolExecutionEnd?: OnToolExecutionEndCallback<TOOLS>;
1483
+ onStepEnd?: GenerateTextOnStepEndCallback<TOOLS, RUNTIME_CONTEXT>;
1484
+ onEnd?: GenerateTextOnEndCallback<TOOLS, RUNTIME_CONTEXT>;
1422
1485
  };
1423
- /**
1424
- * Extract client-provided tool results from the trailing tool message and
1425
- * convert AI SDK model-output wrappers back into values a harness runtime can
1426
- * return from its pending host-tool invocation.
1427
- */
1428
- declare function collectHarnessAgentToolResultContinuations(input: {
1429
- messages: readonly ModelMessage[];
1430
- }): readonly HarnessAgentToolResultContinuation[];
1431
1486
 
1432
1487
  type HarnessAgentTurnResult<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Context, OUTPUT extends OutputInterface> = {
1433
1488
  result: StreamTextResult<TOOLS, RUNTIME_CONTEXT, OUTPUT>;
@@ -1503,6 +1558,7 @@ declare class HarnessAgentSession {
1503
1558
  responseFormat: HarnessV1ResponseFormat | undefined;
1504
1559
  output: OUTPUT | undefined;
1505
1560
  telemetry: TelemetryOptions | undefined;
1561
+ callbacks: HarnessAgentLifecycleCallbacks<TOOLS, RUNTIME_CONTEXT, OUTPUT>;
1506
1562
  stopConditions: ReadonlyArray<StopCondition<TOOLS, RUNTIME_CONTEXT>>;
1507
1563
  }): HarnessAgentTurnResult<TOOLS, RUNTIME_CONTEXT, OUTPUT>;
1508
1564
  continueTurn<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Context, OUTPUT extends OutputInterface>(options: {
@@ -1518,9 +1574,10 @@ declare class HarnessAgentSession {
1518
1574
  responseFormat: HarnessV1ResponseFormat | undefined;
1519
1575
  output: OUTPUT | undefined;
1520
1576
  telemetry: TelemetryOptions | undefined;
1577
+ callbacks: HarnessAgentLifecycleCallbacks<TOOLS, RUNTIME_CONTEXT, OUTPUT>;
1521
1578
  stopConditions: ReadonlyArray<StopCondition<TOOLS, RUNTIME_CONTEXT>>;
1522
- toolApprovalContinuations?: readonly HarnessAgentToolApprovalContinuation[] | undefined;
1523
- toolResultContinuations?: readonly HarnessAgentToolResultContinuation[] | undefined;
1579
+ toolApprovalContinuations?: readonly ToolApprovalResponse[] | undefined;
1580
+ toolResultContinuations?: readonly ToolResultPart[] | undefined;
1524
1581
  }): HarnessAgentTurnResult<TOOLS, RUNTIME_CONTEXT, OUTPUT>;
1525
1582
  /**
1526
1583
  * Ask the underlying runtime to compact its context. The runtime performs
@@ -1656,6 +1713,7 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
1656
1713
  private readonly sandboxConfig;
1657
1714
  private readonly builtinToolFiltering;
1658
1715
  private readonly permissionMode;
1716
+ private readonly headers;
1659
1717
  constructor(settings: HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT, OUTPUT, CALL_OPTIONS>);
1660
1718
  /** Identifier of the harness backing this agent. */
1661
1719
  get harnessId(): string;
@@ -1703,8 +1761,8 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
1703
1761
  */
1704
1762
  continueGenerate(options: {
1705
1763
  session: HarnessAgentSession;
1706
- toolApprovalContinuations?: readonly HarnessAgentToolApprovalContinuation[];
1707
- toolResultContinuations?: readonly HarnessAgentToolResultContinuation[];
1764
+ toolApprovalContinuations?: readonly ToolApprovalResponse[];
1765
+ toolResultContinuations?: readonly ToolResultPart[];
1708
1766
  abortSignal?: AbortSignal;
1709
1767
  }): Promise<GenerateTextResult<HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT, OUTPUT>>;
1710
1768
  /**
@@ -1717,8 +1775,8 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
1717
1775
  */
1718
1776
  continueStream(options: {
1719
1777
  session: HarnessAgentSession;
1720
- toolApprovalContinuations?: readonly HarnessAgentToolApprovalContinuation[];
1721
- toolResultContinuations?: readonly HarnessAgentToolResultContinuation[];
1778
+ toolApprovalContinuations?: readonly ToolApprovalResponse[];
1779
+ toolResultContinuations?: readonly ToolResultPart[];
1722
1780
  abortSignal?: AbortSignal;
1723
1781
  }): Promise<StreamTextResult<HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT, OUTPUT>>;
1724
1782
  /**
@@ -1735,6 +1793,7 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
1735
1793
  private _startPromptTurn;
1736
1794
  private _startContinueTurn;
1737
1795
  private _buildTurnOptions;
1796
+ private _resolveLifecycleCallbacks;
1738
1797
  private _resolveContinueTurnInput;
1739
1798
  private _resolvePromptTurnInput;
1740
1799
  private _preparePromptTurnInput;
@@ -1745,6 +1804,27 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
1745
1804
  private _resolveResponseFormat;
1746
1805
  }
1747
1806
 
1807
+ /**
1808
+ * Extract approval decisions that should continue a suspended harness turn.
1809
+ *
1810
+ * AI SDK clients send approval decisions as a trailing `role: "tool"` message
1811
+ * containing `tool-approval-response` parts. The response only carries the
1812
+ * approval id, so the harness has to recover the matching approval request
1813
+ * locally to find the original tool call before it can resume the paused turn.
1814
+ * Responses that already have a tool result are ignored, because those
1815
+ * approvals were already consumed by a prior continuation.
1816
+ */
1817
+ declare function collectHarnessAgentToolApprovalContinuations(input: {
1818
+ messages: readonly ModelMessage[];
1819
+ }): readonly ToolApprovalResponse[];
1820
+
1821
+ /**
1822
+ * Extract client-provided tool results from the trailing tool message.
1823
+ */
1824
+ declare function collectHarnessAgentToolResultContinuations(input: {
1825
+ messages: readonly ModelMessage[];
1826
+ }): readonly ToolResultPart[];
1827
+
1748
1828
  type SandboxBootstrapSettings = Omit<HarnessAgentSandboxConfig, 'onSession'>;
1749
1829
  /**
1750
1830
  * Prepare a harness's sandbox template without running an agent. Idempotent: if
@@ -1902,4 +1982,4 @@ interface TraceTreeReporterOptions {
1902
1982
  }
1903
1983
  declare function createTraceTreeReporter(options?: TraceTreeReporterOptions): Telemetry;
1904
1984
 
1905
- export { type FileReporter, type FileReporterOptions, HarnessAgent, type HarnessAgentAdapter, type HarnessAgentAdapterSession, type HarnessAgentBuiltinTool, type HarnessAgentBuiltinToolName, type HarnessAgentBuiltinToolUseKind, type HarnessAgentBuiltinTools, type HarnessAgentContinueTurnOptions, type HarnessAgentContinueTurnState, type HarnessAgentLifecycleState, type HarnessAgentPendingToolApproval, type HarnessAgentPendingToolResult, type HarnessAgentPermissionMode, type HarnessAgentPrompt, type HarnessAgentPromptControl, type HarnessAgentPromptTurnOptions, type HarnessAgentResumeSessionState, type HarnessAgentSandboxConfig, HarnessAgentSession, type HarnessAgentSettings, type HarnessAgentSkill, type HarnessAgentStartOptions, type HarnessAgentStreamPart, type HarnessAgentToolApprovalConfiguration, type HarnessAgentToolApprovalContinuation, type HarnessAgentToolResultContinuation, type HarnessAgentToolSpec, type HarnessAllTools, HarnessCapabilityUnsupportedError, type HarnessDebugConfig, type HarnessDebugLevel, type HarnessDiagnostic, type HarnessDiagnosticConsumer, HarnessError, HarnessSandboxAuthenticationError, type PrepareSandboxForHarnessResult, type TraceTreeReporterOptions, collectHarnessAgentToolApprovalContinuations, collectHarnessAgentToolResultContinuations, createFileReporter, createTraceTreeReporter, getHarnessErrorMessage, prepareHarnessSandboxTemplate, prepareSandboxForHarness, prewarmHarness };
1985
+ export { type FileReporter, type FileReporterOptions, HarnessAgent, type HarnessAgentAdapter, type HarnessAgentAdapterSession, type HarnessAgentBuiltinTool, type HarnessAgentBuiltinToolName, type HarnessAgentBuiltinToolUseKind, type HarnessAgentBuiltinTools, type HarnessAgentContinueTurnOptions, type HarnessAgentContinueTurnState, type HarnessAgentLifecycleState, type HarnessAgentPendingToolApproval, type HarnessAgentPendingToolResult, type HarnessAgentPermissionMode, type HarnessAgentPrompt, type HarnessAgentPromptControl, type HarnessAgentPromptTurnOptions, type HarnessAgentResumeSessionState, type HarnessAgentSandboxConfig, HarnessAgentSession, type HarnessAgentSettings, type HarnessAgentSkill, type HarnessAgentStartOptions, type HarnessAgentStreamPart, type HarnessAgentToolApprovalConfiguration, type HarnessAgentToolSpec, type HarnessAllTools, HarnessCapabilityUnsupportedError, type HarnessDebugConfig, type HarnessDebugLevel, type HarnessDiagnostic, type HarnessDiagnosticConsumer, HarnessError, HarnessSandboxAuthenticationError, type PrepareSandboxForHarnessResult, type TraceTreeReporterOptions, collectHarnessAgentToolApprovalContinuations, collectHarnessAgentToolResultContinuations, createFileReporter, createTraceTreeReporter, getHarnessErrorMessage, prepareHarnessSandboxTemplate, prepareSandboxForHarness, prewarmHarness };