@ai-sdk/harness 1.0.107 → 1.0.108
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 +20 -0
- package/dist/agent/index.d.ts +14 -3
- package/dist/agent/index.js +74 -30
- package/dist/agent/index.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/utils/index.d.ts +62 -1
- package/dist/utils/index.js +241 -7
- package/dist/utils/index.js.map +1 -1
- package/package.json +5 -5
- package/src/agent/harness-agent-session.ts +17 -3
- package/src/agent/harness-agent-settings.ts +4 -2
- package/src/agent/harness-agent.ts +11 -2
- package/src/agent/internal/run-prompt.ts +73 -32
- package/src/utils/index.ts +12 -0
- package/src/utils/native-subscription/jwt.ts +31 -0
- package/src/utils/native-subscription/linux-secret-service.ts +23 -0
- package/src/utils/native-subscription/macos-keychain.ts +26 -0
- package/src/utils/native-subscription/should-resolve-native.ts +18 -0
- package/src/utils/native-subscription/windows-credential-manager.ts +61 -0
- package/src/utils/oauth-access-token.ts +129 -0
- package/src/utils/os.ts +11 -0
- package/src/v1/harness-v1-lifecycle-state.ts +7 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @ai-sdk/harness
|
|
2
2
|
|
|
3
|
+
## 1.0.108
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 4d1bf28: feat(harness): support `instructions` on `HarnessAgent` to be a `SystemModelMessage` for parity with `ToolLoopAgent`
|
|
8
|
+
- cdc12a1: feat(harness): add support for using adapter-native subscriptions where available
|
|
9
|
+
- d70a334: feat(workflow-harness): automatically persist validated `HarnessAgent` output in workflow results
|
|
10
|
+
- 81ba84c: fix(harness): preserve completed host tool results across turn suspension and session finalization
|
|
11
|
+
- Updated dependencies [5ec21a6]
|
|
12
|
+
- Updated dependencies [db59d78]
|
|
13
|
+
- Updated dependencies [7469a3b]
|
|
14
|
+
- Updated dependencies [f87bf07]
|
|
15
|
+
- Updated dependencies [bc5cb7a]
|
|
16
|
+
- Updated dependencies [a5f449a]
|
|
17
|
+
- Updated dependencies [813bb36]
|
|
18
|
+
- Updated dependencies [c43e4b7]
|
|
19
|
+
- @ai-sdk/provider@4.0.14
|
|
20
|
+
- ai@7.0.98
|
|
21
|
+
- @ai-sdk/provider-utils@5.0.40
|
|
22
|
+
|
|
3
23
|
## 1.0.107
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
package/dist/agent/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
|
|
2
|
-
import { Experimental_SandboxSession, UserModelMessage, ToolResultPart, ProviderOptions, ToolSet, FlexibleSchema, Tool, Context, MaybePromiseLike, Arrayable, ToolApprovalResponse, ModelMessage } from '@ai-sdk/provider-utils';
|
|
2
|
+
import { Experimental_SandboxSession, UserModelMessage, ToolResultPart, ProviderOptions, ToolSet, FlexibleSchema, Tool, Context, SystemModelMessage, MaybePromiseLike, Arrayable, ToolApprovalResponse, ModelMessage } from '@ai-sdk/provider-utils';
|
|
3
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';
|
|
@@ -467,6 +467,12 @@ type HarnessV1PendingToolResult = {
|
|
|
467
467
|
readonly toolName: string;
|
|
468
468
|
readonly input: string;
|
|
469
469
|
readonly providerOptions?: ProviderOptions;
|
|
470
|
+
/** Executed while suspending; submit on resume without running the tool again. */
|
|
471
|
+
readonly completedResult?: {
|
|
472
|
+
readonly output: unknown;
|
|
473
|
+
readonly isError?: boolean;
|
|
474
|
+
readonly toolResult?: ToolResultPart;
|
|
475
|
+
};
|
|
470
476
|
};
|
|
471
477
|
/**
|
|
472
478
|
* Framework-owned settings captured when a turn begins. The same settings are
|
|
@@ -1347,9 +1353,10 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
|
|
|
1347
1353
|
* Instructions for the underlying agent runtime. Adapters append these to a
|
|
1348
1354
|
* native system or developer prompt when supported. Otherwise, they prepend
|
|
1349
1355
|
* them to the user message. `prepareCall` can replace them between completed
|
|
1350
|
-
* turns.
|
|
1356
|
+
* turns. When a `SystemModelMessage` is provided, only its `content` is
|
|
1357
|
+
* forwarded to the harness adapter.
|
|
1351
1358
|
*/
|
|
1352
|
-
readonly instructions?: string;
|
|
1359
|
+
readonly instructions?: string | SystemModelMessage;
|
|
1353
1360
|
/**
|
|
1354
1361
|
* Additional HTTP headers to be sent with every model request.
|
|
1355
1362
|
*
|
|
@@ -1521,6 +1528,7 @@ declare class HarnessAgentSession {
|
|
|
1521
1528
|
private turnState;
|
|
1522
1529
|
private turnSequence;
|
|
1523
1530
|
private activeTurnSequence;
|
|
1531
|
+
private activePromptDone;
|
|
1524
1532
|
private activePromptControl;
|
|
1525
1533
|
private suspendedTurnState;
|
|
1526
1534
|
private activeTurnSettings;
|
|
@@ -1633,6 +1641,7 @@ declare class HarnessAgentSession {
|
|
|
1633
1641
|
private getPendingToolResults;
|
|
1634
1642
|
private addPendingToolState;
|
|
1635
1643
|
private suspendCurrentTurn;
|
|
1644
|
+
private finalizeCurrentTurnSuspension;
|
|
1636
1645
|
private captureStopConditionBoundary;
|
|
1637
1646
|
private toResumeStateWithContinuation;
|
|
1638
1647
|
private requirePromptableTurn;
|
|
@@ -1717,6 +1726,8 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
|
|
|
1717
1726
|
constructor(settings: HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT, OUTPUT, CALL_OPTIONS>);
|
|
1718
1727
|
/** Identifier of the harness backing this agent. */
|
|
1719
1728
|
get harnessId(): string;
|
|
1729
|
+
/** Whether this agent parses completed turns with its configured output. */
|
|
1730
|
+
get hasOutput(): boolean;
|
|
1720
1731
|
/**
|
|
1721
1732
|
* Start a fresh session, or resume from state previously returned by
|
|
1722
1733
|
* `session.detach()` or `session.stop()`. The returned
|
package/dist/agent/index.js
CHANGED
|
@@ -1795,22 +1795,6 @@ function runPrompt(input) {
|
|
|
1795
1795
|
onPendingToolResult(pendingResult);
|
|
1796
1796
|
return pendingResult;
|
|
1797
1797
|
};
|
|
1798
|
-
const processPendingToolResultContinuation = async (pendingResult, continuation) => {
|
|
1799
|
-
const result2 = unwrapToolResultOutput(continuation);
|
|
1800
|
-
onToolResultSettled(pendingResult.toolCallId);
|
|
1801
|
-
pendingResultsByToolCallId.delete(pendingResult.toolCallId);
|
|
1802
|
-
settledHostToolCallIds.add(pendingResult.toolCallId);
|
|
1803
|
-
await control.submitToolResult({
|
|
1804
|
-
toolCallId: pendingResult.toolCallId,
|
|
1805
|
-
output: result2.output,
|
|
1806
|
-
isError: result2.isError,
|
|
1807
|
-
toolResult: {
|
|
1808
|
-
...continuation,
|
|
1809
|
-
toolName: pendingResult.toolName,
|
|
1810
|
-
...continuation.providerOptions == null && pendingResult.providerOptions != null ? { providerOptions: pendingResult.providerOptions } : {}
|
|
1811
|
-
}
|
|
1812
|
-
});
|
|
1813
|
-
};
|
|
1814
1798
|
const enqueueHostToolOutcome = (options) => {
|
|
1815
1799
|
if (options.outcome.ok) {
|
|
1816
1800
|
const stripped = stripWorkDir(
|
|
@@ -1839,6 +1823,54 @@ function runPrompt(input) {
|
|
|
1839
1823
|
error: options.outcome.error
|
|
1840
1824
|
});
|
|
1841
1825
|
};
|
|
1826
|
+
const submitToolResult = async (submission) => {
|
|
1827
|
+
var _a6, _b6, _c3;
|
|
1828
|
+
if (!((_a6 = input.isTurnSuspending) == null ? void 0 : _a6.call(input))) {
|
|
1829
|
+
return control.submitToolResult(submission);
|
|
1830
|
+
}
|
|
1831
|
+
const toolCall = (_c3 = (_b6 = rawToolCallsByToolCallId.get(submission.toolCallId)) != null ? _b6 : pendingResultsByToolCallId.get(submission.toolCallId)) != null ? _c3 : pendingToolApprovals.find(
|
|
1832
|
+
(approval) => approval.toolCallId === submission.toolCallId
|
|
1833
|
+
);
|
|
1834
|
+
if (toolCall == null) {
|
|
1835
|
+
throw new Error(
|
|
1836
|
+
`Unknown suspended tool call '${submission.toolCallId}'.`
|
|
1837
|
+
);
|
|
1838
|
+
}
|
|
1839
|
+
const { toolCallId, ...completedResult } = submission;
|
|
1840
|
+
onPendingToolResult({
|
|
1841
|
+
toolCallId,
|
|
1842
|
+
toolName: toolCall.toolName,
|
|
1843
|
+
input: toolCall.input,
|
|
1844
|
+
completedResult
|
|
1845
|
+
});
|
|
1846
|
+
const parsed = toolCallsByToolCallId.get(toolCallId);
|
|
1847
|
+
if (parsed != null && !settledHostToolCallIds.has(toolCallId)) {
|
|
1848
|
+
bufferedToolOutcomes.push(
|
|
1849
|
+
() => enqueueHostToolOutcome({
|
|
1850
|
+
toolCall: parsed,
|
|
1851
|
+
outcome: submission.isError ? { ok: false, error: submission.output } : { ok: true, output: submission.output }
|
|
1852
|
+
})
|
|
1853
|
+
);
|
|
1854
|
+
}
|
|
1855
|
+
};
|
|
1856
|
+
const processPendingToolResultContinuation = async (pendingResult, continuation) => {
|
|
1857
|
+
const submission = continuation == null ? pendingResult.completedResult : {
|
|
1858
|
+
...unwrapToolResultOutput(continuation),
|
|
1859
|
+
toolResult: {
|
|
1860
|
+
...continuation,
|
|
1861
|
+
toolName: pendingResult.toolName,
|
|
1862
|
+
...continuation.providerOptions == null && pendingResult.providerOptions != null ? { providerOptions: pendingResult.providerOptions } : {}
|
|
1863
|
+
}
|
|
1864
|
+
};
|
|
1865
|
+
if (submission == null) return;
|
|
1866
|
+
settledHostToolCallIds.add(pendingResult.toolCallId);
|
|
1867
|
+
onToolResultSettled(pendingResult.toolCallId);
|
|
1868
|
+
await submitToolResult({
|
|
1869
|
+
toolCallId: pendingResult.toolCallId,
|
|
1870
|
+
...submission
|
|
1871
|
+
});
|
|
1872
|
+
pendingResultsByToolCallId.delete(pendingResult.toolCallId);
|
|
1873
|
+
};
|
|
1842
1874
|
const processPendingApprovalContinuation = async (approval, continuation) => {
|
|
1843
1875
|
var _a6;
|
|
1844
1876
|
const rawToolCall = (_a6 = rawToolCallsByToolCallId.get(approval.toolCallId)) != null ? _a6 : {
|
|
@@ -1877,7 +1909,7 @@ function runPrompt(input) {
|
|
|
1877
1909
|
}
|
|
1878
1910
|
settledHostToolCallIds.add(approval.toolCallId);
|
|
1879
1911
|
if (!continuation.approved) {
|
|
1880
|
-
await
|
|
1912
|
+
await submitToolResult({
|
|
1881
1913
|
toolCallId: approval.toolCallId,
|
|
1882
1914
|
output: {
|
|
1883
1915
|
type: "execution-denied",
|
|
@@ -1897,7 +1929,7 @@ function runPrompt(input) {
|
|
|
1897
1929
|
wrappedExecuteTool: lifecycle.executeTool,
|
|
1898
1930
|
sandboxSession: input.sandboxSession,
|
|
1899
1931
|
abortSignal: input.abortSignal,
|
|
1900
|
-
|
|
1932
|
+
submitToolResult,
|
|
1901
1933
|
onPreliminaryResult: (preliminaryOutput) => {
|
|
1902
1934
|
const stripped = stripWorkDir(
|
|
1903
1935
|
{
|
|
@@ -1956,12 +1988,12 @@ function runPrompt(input) {
|
|
|
1956
1988
|
const continuation = continuationsByToolCallId.get(
|
|
1957
1989
|
pendingResult.toolCallId
|
|
1958
1990
|
);
|
|
1959
|
-
if (continuation != null) {
|
|
1991
|
+
if (continuation != null || pendingResult.completedResult != null) {
|
|
1960
1992
|
await processPendingToolResultContinuation(
|
|
1961
1993
|
pendingResult,
|
|
1962
1994
|
continuation
|
|
1963
1995
|
);
|
|
1964
|
-
closingResumedStep = true;
|
|
1996
|
+
if (pendingResult.completedResult == null) closingResumedStep = true;
|
|
1965
1997
|
}
|
|
1966
1998
|
}
|
|
1967
1999
|
while (true) {
|
|
@@ -2218,7 +2250,7 @@ function runPrompt(input) {
|
|
|
2218
2250
|
toolName: toolCall.toolName
|
|
2219
2251
|
})
|
|
2220
2252
|
};
|
|
2221
|
-
await
|
|
2253
|
+
await submitToolResult({
|
|
2222
2254
|
toolCallId: toolCall.toolCallId,
|
|
2223
2255
|
output
|
|
2224
2256
|
});
|
|
@@ -2262,7 +2294,7 @@ function runPrompt(input) {
|
|
|
2262
2294
|
type: "execution-denied",
|
|
2263
2295
|
reason: customToolApprovalDecision.reason
|
|
2264
2296
|
};
|
|
2265
|
-
await
|
|
2297
|
+
await submitToolResult({
|
|
2266
2298
|
toolCallId: toolCall.toolCallId,
|
|
2267
2299
|
output
|
|
2268
2300
|
});
|
|
@@ -2343,7 +2375,7 @@ function runPrompt(input) {
|
|
|
2343
2375
|
wrappedExecuteTool: lifecycle.executeTool,
|
|
2344
2376
|
sandboxSession: input.sandboxSession,
|
|
2345
2377
|
abortSignal: input.abortSignal,
|
|
2346
|
-
|
|
2378
|
+
submitToolResult,
|
|
2347
2379
|
onPreliminaryResult: (preliminaryOutput) => {
|
|
2348
2380
|
const stripped = stripWorkDir(
|
|
2349
2381
|
{
|
|
@@ -2386,6 +2418,7 @@ function runPrompt(input) {
|
|
|
2386
2418
|
await waitForOutstandingHostToolExecutions();
|
|
2387
2419
|
const isTurnSuspending = ((_m = input.isTurnSuspending) == null ? void 0 : _m.call(input)) === true;
|
|
2388
2420
|
if (isTurnSuspending) {
|
|
2421
|
+
await publishToolExecutions();
|
|
2389
2422
|
if (finalFinish == null) {
|
|
2390
2423
|
result.discardCurrentStepContent();
|
|
2391
2424
|
}
|
|
@@ -2476,13 +2509,13 @@ async function maybeExecuteHostTool(input) {
|
|
|
2476
2509
|
return output2;
|
|
2477
2510
|
}
|
|
2478
2511
|
});
|
|
2479
|
-
await input.
|
|
2512
|
+
await input.submitToolResult({
|
|
2480
2513
|
toolCallId: input.event.toolCallId,
|
|
2481
2514
|
output
|
|
2482
2515
|
});
|
|
2483
2516
|
return { executed: true, outcome: { ok: true, output } };
|
|
2484
2517
|
} catch (err) {
|
|
2485
|
-
await input.
|
|
2518
|
+
await input.submitToolResult({
|
|
2486
2519
|
toolCallId: input.event.toolCallId,
|
|
2487
2520
|
output: { error: String(err) },
|
|
2488
2521
|
isError: true
|
|
@@ -2646,6 +2679,7 @@ var HarnessAgentSession = class {
|
|
|
2646
2679
|
isTurnSuspending: () => this.activeTurnSequence === turnId && this.suspendedTurnState != null,
|
|
2647
2680
|
onStopConditionMet: () => this.captureStopConditionBoundary({ session, turnId })
|
|
2648
2681
|
});
|
|
2682
|
+
this.activePromptDone = turn.done;
|
|
2649
2683
|
return {
|
|
2650
2684
|
...turn,
|
|
2651
2685
|
ready: this.waitForPromptControl({ turnId })
|
|
@@ -2721,6 +2755,7 @@ var HarnessAgentSession = class {
|
|
|
2721
2755
|
isTurnSuspending: () => this.activeTurnSequence === turnId && this.suspendedTurnState != null,
|
|
2722
2756
|
onStopConditionMet: () => this.captureStopConditionBoundary({ session, turnId })
|
|
2723
2757
|
});
|
|
2758
|
+
this.activePromptDone = turn.done;
|
|
2724
2759
|
return {
|
|
2725
2760
|
...turn,
|
|
2726
2761
|
ready: this.waitForPromptControl({ turnId })
|
|
@@ -2787,7 +2822,7 @@ var HarnessAgentSession = class {
|
|
|
2787
2822
|
try {
|
|
2788
2823
|
if (this.turnState !== "idle") {
|
|
2789
2824
|
return this.toResumeStateWithContinuation({
|
|
2790
|
-
continueFrom: await this.
|
|
2825
|
+
continueFrom: await this.finalizeCurrentTurnSuspension({ session })
|
|
2791
2826
|
});
|
|
2792
2827
|
}
|
|
2793
2828
|
const raw = await session.doDetach();
|
|
@@ -2818,7 +2853,7 @@ var HarnessAgentSession = class {
|
|
|
2818
2853
|
try {
|
|
2819
2854
|
if (this.turnState !== "idle") {
|
|
2820
2855
|
return this.toResumeStateWithContinuation({
|
|
2821
|
-
continueFrom: await this.
|
|
2856
|
+
continueFrom: await this.finalizeCurrentTurnSuspension({ session })
|
|
2822
2857
|
});
|
|
2823
2858
|
}
|
|
2824
2859
|
const raw = await session.doStop();
|
|
@@ -2880,7 +2915,7 @@ var HarnessAgentSession = class {
|
|
|
2880
2915
|
}
|
|
2881
2916
|
const session = this.underlyingSession;
|
|
2882
2917
|
try {
|
|
2883
|
-
return await this.
|
|
2918
|
+
return await this.finalizeCurrentTurnSuspension({ session });
|
|
2884
2919
|
} finally {
|
|
2885
2920
|
this.endLocalHandle({ sessionState: "detached" });
|
|
2886
2921
|
}
|
|
@@ -2927,6 +2962,11 @@ var HarnessAgentSession = class {
|
|
|
2927
2962
|
this.turnState = "suspended";
|
|
2928
2963
|
return state;
|
|
2929
2964
|
}
|
|
2965
|
+
async finalizeCurrentTurnSuspension(options) {
|
|
2966
|
+
const state = await this.suspendCurrentTurn(options);
|
|
2967
|
+
await this.activePromptDone;
|
|
2968
|
+
return this.addPendingToolState(state);
|
|
2969
|
+
}
|
|
2930
2970
|
async captureStopConditionBoundary(options) {
|
|
2931
2971
|
if (this.sessionState !== "active" || this.activeTurnSequence !== options.turnId) {
|
|
2932
2972
|
return;
|
|
@@ -3639,6 +3679,10 @@ var HarnessAgent = class {
|
|
|
3639
3679
|
get harnessId() {
|
|
3640
3680
|
return this.settings.harness.harnessId;
|
|
3641
3681
|
}
|
|
3682
|
+
/** Whether this agent parses completed turns with its configured output. */
|
|
3683
|
+
get hasOutput() {
|
|
3684
|
+
return this.settings.output != null;
|
|
3685
|
+
}
|
|
3642
3686
|
/**
|
|
3643
3687
|
* Start a fresh session, or resume from state previously returned by
|
|
3644
3688
|
* `session.detach()` or `session.stop()`. The returned
|
|
@@ -4117,7 +4161,7 @@ var HarnessAgent = class {
|
|
|
4117
4161
|
};
|
|
4118
4162
|
}
|
|
4119
4163
|
_prepareTurnSettings(options) {
|
|
4120
|
-
var _a4, _b4;
|
|
4164
|
+
var _a4, _b4, _c;
|
|
4121
4165
|
const userTools = (_a4 = options.tools) != null ? _a4 : {};
|
|
4122
4166
|
assertNoReservedQuestionTool({
|
|
4123
4167
|
harness: this.settings.harness,
|
|
@@ -4137,7 +4181,7 @@ var HarnessAgent = class {
|
|
|
4137
4181
|
return {
|
|
4138
4182
|
model: options.model,
|
|
4139
4183
|
skills: (_b4 = options.skills) != null ? _b4 : [],
|
|
4140
|
-
instructions: options.instructions,
|
|
4184
|
+
instructions: typeof options.instructions === "string" ? options.instructions : (_c = options.instructions) == null ? void 0 : _c.content,
|
|
4141
4185
|
tools,
|
|
4142
4186
|
activeTools: toolFiltering.activeUserTools,
|
|
4143
4187
|
toolSpecs: this._toToolSpecs(toolFiltering.activeUserTools),
|