@ai-sdk/harness 1.0.71 → 1.0.73
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 +18 -0
- package/README.md +23 -0
- package/dist/agent/index.d.ts +148 -23
- package/dist/agent/index.js +185 -37
- package/dist/agent/index.js.map +1 -1
- package/dist/bridge/index.js +14 -20
- package/dist/bridge/index.js.map +1 -1
- package/dist/index.d.ts +124 -10
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/index.d.ts +59 -7
- package/dist/utils/index.js +47 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +3 -3
- package/src/agent/harness-agent-session.ts +27 -7
- package/src/agent/harness-agent-settings.ts +8 -0
- package/src/agent/harness-agent.ts +74 -23
- package/src/agent/internal/harness-stream-text-result.ts +251 -59
- package/src/agent/internal/run-prompt.ts +10 -2
- package/src/agent/prepare-sandbox-for-harness.ts +8 -18
- package/src/bridge/index.ts +41 -37
- package/src/errors/harness-capability-unsupported-error.ts +2 -2
- package/src/utils/index.ts +5 -0
- package/src/utils/sandbox-credential-brokering.ts +41 -0
- package/src/v1/harness-v1-bridge-protocol.ts +13 -0
- package/src/v1/harness-v1-network-sandbox-session.ts +87 -5
- package/src/v1/harness-v1-response-format.ts +32 -0
- package/src/v1/harness-v1-session.ts +17 -2
- package/src/v1/index.ts +10 -0
package/dist/agent/index.js
CHANGED
|
@@ -250,6 +250,7 @@ var HarnessStreamTextResult = class {
|
|
|
250
250
|
this.toolsContext = options.toolsContext;
|
|
251
251
|
this.providerName = `harness:${options.harnessId}`;
|
|
252
252
|
this.modelId = options.sessionId;
|
|
253
|
+
this.outputSpecification = options.output;
|
|
253
254
|
let controllerRef;
|
|
254
255
|
const baseStream = new ReadableStream({
|
|
255
256
|
start(c) {
|
|
@@ -258,18 +259,13 @@ var HarnessStreamTextResult = class {
|
|
|
258
259
|
}
|
|
259
260
|
});
|
|
260
261
|
this.fullStreamController = controllerRef;
|
|
261
|
-
|
|
262
|
-
this.stream = forFull;
|
|
263
|
-
this.fullStream = this.stream;
|
|
264
|
-
this.textStream = forText.pipeThrough(
|
|
262
|
+
this.baseStream = options.output == null ? baseStream.pipeThrough(
|
|
265
263
|
new TransformStream({
|
|
266
264
|
transform(part, controller) {
|
|
267
|
-
|
|
268
|
-
controller.enqueue(part.text);
|
|
269
|
-
}
|
|
265
|
+
controller.enqueue({ part, partialOutput: void 0 });
|
|
270
266
|
}
|
|
271
267
|
})
|
|
272
|
-
);
|
|
268
|
+
) : baseStream.pipeThrough(createOutputTransformStream(options.output));
|
|
273
269
|
}
|
|
274
270
|
// ─── Writer-side methods used by the driver ────────────────────────
|
|
275
271
|
/**
|
|
@@ -525,6 +521,38 @@ var HarnessStreamTextResult = class {
|
|
|
525
521
|
}
|
|
526
522
|
}
|
|
527
523
|
// ─── Reader-side public surface (StreamTextResult contract) ────────
|
|
524
|
+
teeStream() {
|
|
525
|
+
const [stream, remainingStream] = this.baseStream.tee();
|
|
526
|
+
this.baseStream = remainingStream;
|
|
527
|
+
return stream;
|
|
528
|
+
}
|
|
529
|
+
get stream() {
|
|
530
|
+
return createAsyncIterableStream(
|
|
531
|
+
this.teeStream().pipeThrough(
|
|
532
|
+
new TransformStream({
|
|
533
|
+
transform({ part }, controller) {
|
|
534
|
+
controller.enqueue(part);
|
|
535
|
+
}
|
|
536
|
+
})
|
|
537
|
+
)
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
get fullStream() {
|
|
541
|
+
return this.stream;
|
|
542
|
+
}
|
|
543
|
+
get textStream() {
|
|
544
|
+
return createAsyncIterableStream(
|
|
545
|
+
this.stream.pipeThrough(
|
|
546
|
+
new TransformStream({
|
|
547
|
+
transform(part, controller) {
|
|
548
|
+
if (part.type === "text-delta") {
|
|
549
|
+
controller.enqueue(part.text);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
})
|
|
553
|
+
)
|
|
554
|
+
);
|
|
555
|
+
}
|
|
528
556
|
get content() {
|
|
529
557
|
return this._content.promise;
|
|
530
558
|
}
|
|
@@ -594,18 +622,48 @@ var HarnessStreamTextResult = class {
|
|
|
594
622
|
get providerMetadata() {
|
|
595
623
|
return this._providerMetadata.promise;
|
|
596
624
|
}
|
|
597
|
-
// Output-specification surfaces are not yet supported.
|
|
598
625
|
get experimental_partialOutputStream() {
|
|
599
|
-
|
|
626
|
+
return this.partialOutputStream;
|
|
600
627
|
}
|
|
601
628
|
get partialOutputStream() {
|
|
602
|
-
|
|
629
|
+
return createAsyncIterableStream(
|
|
630
|
+
this.teeStream().pipeThrough(
|
|
631
|
+
new TransformStream({
|
|
632
|
+
transform({ partialOutput }, controller) {
|
|
633
|
+
if (partialOutput != null) {
|
|
634
|
+
controller.enqueue(partialOutput);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
})
|
|
638
|
+
)
|
|
639
|
+
);
|
|
603
640
|
}
|
|
604
641
|
get elementStream() {
|
|
605
|
-
|
|
642
|
+
var _a4, _b4, _c;
|
|
643
|
+
const transform = (_a4 = this.outputSpecification) == null ? void 0 : _a4.createElementStreamTransform();
|
|
644
|
+
if (transform == null) {
|
|
645
|
+
throw notSupportedYet(
|
|
646
|
+
`element streams in ${(_c = (_b4 = this.outputSpecification) == null ? void 0 : _b4.name) != null ? _c : "text"} mode`
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
return createAsyncIterableStream(
|
|
650
|
+
this.teeStream().pipeThrough(transform)
|
|
651
|
+
);
|
|
606
652
|
}
|
|
607
653
|
get output() {
|
|
608
|
-
|
|
654
|
+
return this.finalStep.then((step) => {
|
|
655
|
+
if (this.outputSpecification == null) {
|
|
656
|
+
throw notSupportedYet("structured output");
|
|
657
|
+
}
|
|
658
|
+
return this.outputSpecification.parseCompleteOutput(
|
|
659
|
+
{ text: step.text },
|
|
660
|
+
{
|
|
661
|
+
response: step.response,
|
|
662
|
+
usage: step.usage,
|
|
663
|
+
finishReason: step.finishReason
|
|
664
|
+
}
|
|
665
|
+
);
|
|
666
|
+
});
|
|
609
667
|
}
|
|
610
668
|
async consumeStream() {
|
|
611
669
|
const reader = this.fullStream.getReader();
|
|
@@ -725,6 +783,73 @@ var HarnessStreamTextResult = class {
|
|
|
725
783
|
}
|
|
726
784
|
}
|
|
727
785
|
};
|
|
786
|
+
function createOutputTransformStream(output) {
|
|
787
|
+
let firstTextChunkId;
|
|
788
|
+
let text = "";
|
|
789
|
+
let textChunk = "";
|
|
790
|
+
let textProviderMetadata;
|
|
791
|
+
let lastPublishedValue = "";
|
|
792
|
+
const publishTextChunk = (options) => {
|
|
793
|
+
options.controller.enqueue({
|
|
794
|
+
part: {
|
|
795
|
+
type: "text-delta",
|
|
796
|
+
id: firstTextChunkId,
|
|
797
|
+
text: textChunk,
|
|
798
|
+
providerMetadata: textProviderMetadata
|
|
799
|
+
},
|
|
800
|
+
partialOutput: options.partialOutput
|
|
801
|
+
});
|
|
802
|
+
textChunk = "";
|
|
803
|
+
};
|
|
804
|
+
return new TransformStream({
|
|
805
|
+
async transform(chunk, controller) {
|
|
806
|
+
var _a4;
|
|
807
|
+
if (chunk.type === "finish-step" && textChunk.length > 0) {
|
|
808
|
+
publishTextChunk({ controller });
|
|
809
|
+
}
|
|
810
|
+
if (chunk.type !== "text-delta" && chunk.type !== "text-start" && chunk.type !== "text-end") {
|
|
811
|
+
controller.enqueue({ part: chunk, partialOutput: void 0 });
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
if (firstTextChunkId == null) {
|
|
815
|
+
firstTextChunkId = chunk.id;
|
|
816
|
+
} else if (chunk.id !== firstTextChunkId) {
|
|
817
|
+
controller.enqueue({ part: chunk, partialOutput: void 0 });
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
if (chunk.type === "text-start") {
|
|
821
|
+
controller.enqueue({ part: chunk, partialOutput: void 0 });
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
if (chunk.type === "text-end") {
|
|
825
|
+
if (textChunk.length > 0) {
|
|
826
|
+
publishTextChunk({ controller });
|
|
827
|
+
}
|
|
828
|
+
controller.enqueue({ part: chunk, partialOutput: void 0 });
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
text += chunk.text;
|
|
832
|
+
textChunk += chunk.text;
|
|
833
|
+
textProviderMetadata = (_a4 = chunk.providerMetadata) != null ? _a4 : textProviderMetadata;
|
|
834
|
+
if (chunk.text.length === 0 && chunk.providerMetadata != null) {
|
|
835
|
+
controller.enqueue({ part: chunk, partialOutput: void 0 });
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
const result = await output.parsePartialOutput({ text });
|
|
839
|
+
if (result === void 0) {
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
const currentValue = typeof result.partial === "string" ? result.partial : JSON.stringify(result.partial);
|
|
843
|
+
if (currentValue !== lastPublishedValue) {
|
|
844
|
+
publishTextChunk({
|
|
845
|
+
controller,
|
|
846
|
+
partialOutput: result.partial
|
|
847
|
+
});
|
|
848
|
+
lastPublishedValue = currentValue;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
});
|
|
852
|
+
}
|
|
728
853
|
function createEmptyPerformance() {
|
|
729
854
|
return {
|
|
730
855
|
effectiveOutputTokensPerSecond: 0,
|
|
@@ -1372,7 +1497,8 @@ function runPrompt(input) {
|
|
|
1372
1497
|
// toolsContext is not configurable for harnesses; pass undefined cast.
|
|
1373
1498
|
toolsContext: void 0,
|
|
1374
1499
|
harnessId: input.harness.harnessId,
|
|
1375
|
-
sessionId: input.session.sessionId
|
|
1500
|
+
sessionId: input.session.sessionId,
|
|
1501
|
+
output: input.output
|
|
1376
1502
|
});
|
|
1377
1503
|
const pendingToolApprovals = (_a4 = input.pendingToolApprovals) != null ? _a4 : [];
|
|
1378
1504
|
const pendingToolResults = (_b4 = input.pendingToolResults) != null ? _b4 : [];
|
|
@@ -1413,6 +1539,7 @@ function runPrompt(input) {
|
|
|
1413
1539
|
try {
|
|
1414
1540
|
bridge = await toHarnessStream({
|
|
1415
1541
|
invoke: input.mode === "continue" ? (emit) => input.session.doContinueTurn({
|
|
1542
|
+
responseFormat: input.responseFormat,
|
|
1416
1543
|
tools: input.toolSpecs,
|
|
1417
1544
|
instructions: input.instructions,
|
|
1418
1545
|
abortSignal: input.abortSignal,
|
|
@@ -1425,6 +1552,7 @@ function runPrompt(input) {
|
|
|
1425
1552
|
}
|
|
1426
1553
|
return input.session.doPromptTurn({
|
|
1427
1554
|
prompt: input.prompt,
|
|
1555
|
+
responseFormat: input.responseFormat,
|
|
1428
1556
|
tools: input.toolSpecs,
|
|
1429
1557
|
instructions: input.instructions,
|
|
1430
1558
|
abortSignal: input.abortSignal,
|
|
@@ -2273,6 +2401,8 @@ var HarnessAgentSession = class {
|
|
|
2273
2401
|
sessionWorkDir: this.sessionWorkDir,
|
|
2274
2402
|
runtimeContext: options.runtimeContext,
|
|
2275
2403
|
abortSignal: options.abortSignal,
|
|
2404
|
+
responseFormat: options.responseFormat,
|
|
2405
|
+
output: options.output,
|
|
2276
2406
|
telemetry: options.telemetry,
|
|
2277
2407
|
stopConditions: options.stopConditions,
|
|
2278
2408
|
toolApproval: this.toolApproval,
|
|
@@ -2326,6 +2456,8 @@ var HarnessAgentSession = class {
|
|
|
2326
2456
|
sessionWorkDir: this.sessionWorkDir,
|
|
2327
2457
|
runtimeContext: options.runtimeContext,
|
|
2328
2458
|
abortSignal: options.abortSignal,
|
|
2459
|
+
responseFormat: options.responseFormat,
|
|
2460
|
+
output: options.output,
|
|
2329
2461
|
telemetry: options.telemetry,
|
|
2330
2462
|
stopConditions: options.stopConditions,
|
|
2331
2463
|
toolApproval: this.toolApproval,
|
|
@@ -3342,11 +3474,13 @@ var HarnessAgent = class {
|
|
|
3342
3474
|
async generate(options) {
|
|
3343
3475
|
const turnInput = this._resolveTurnInput(options);
|
|
3344
3476
|
const runtimeContext = {};
|
|
3477
|
+
const responseFormat = await this._resolveResponseFormat();
|
|
3345
3478
|
const { result, done } = this._startTurn({
|
|
3346
3479
|
session: options.session,
|
|
3347
3480
|
turnInput,
|
|
3348
3481
|
runtimeContext,
|
|
3349
|
-
abortSignal: options.abortSignal
|
|
3482
|
+
abortSignal: options.abortSignal,
|
|
3483
|
+
responseFormat
|
|
3350
3484
|
});
|
|
3351
3485
|
await done;
|
|
3352
3486
|
return this._toGenerateResult(result);
|
|
@@ -3354,11 +3488,13 @@ var HarnessAgent = class {
|
|
|
3354
3488
|
async stream(options) {
|
|
3355
3489
|
const turnInput = this._resolveTurnInput(options);
|
|
3356
3490
|
const runtimeContext = {};
|
|
3491
|
+
const responseFormat = await this._resolveResponseFormat();
|
|
3357
3492
|
const { result } = this._startTurn({
|
|
3358
3493
|
session: options.session,
|
|
3359
3494
|
turnInput,
|
|
3360
3495
|
runtimeContext,
|
|
3361
|
-
abortSignal: options.abortSignal
|
|
3496
|
+
abortSignal: options.abortSignal,
|
|
3497
|
+
responseFormat
|
|
3362
3498
|
});
|
|
3363
3499
|
return result;
|
|
3364
3500
|
}
|
|
@@ -3370,6 +3506,7 @@ var HarnessAgent = class {
|
|
|
3370
3506
|
async continueGenerate(options) {
|
|
3371
3507
|
var _a4, _b4;
|
|
3372
3508
|
const runtimeContext = {};
|
|
3509
|
+
const responseFormat = await this._resolveResponseFormat();
|
|
3373
3510
|
const { result, done } = this._startTurn({
|
|
3374
3511
|
session: options.session,
|
|
3375
3512
|
turnInput: {
|
|
@@ -3378,7 +3515,8 @@ var HarnessAgent = class {
|
|
|
3378
3515
|
toolResultContinuations: (_b4 = options.toolResultContinuations) != null ? _b4 : []
|
|
3379
3516
|
},
|
|
3380
3517
|
runtimeContext,
|
|
3381
|
-
abortSignal: options.abortSignal
|
|
3518
|
+
abortSignal: options.abortSignal,
|
|
3519
|
+
responseFormat
|
|
3382
3520
|
});
|
|
3383
3521
|
await done;
|
|
3384
3522
|
return this._toGenerateResult(result);
|
|
@@ -3394,6 +3532,7 @@ var HarnessAgent = class {
|
|
|
3394
3532
|
async continueStream(options) {
|
|
3395
3533
|
var _a4, _b4;
|
|
3396
3534
|
const runtimeContext = {};
|
|
3535
|
+
const responseFormat = await this._resolveResponseFormat();
|
|
3397
3536
|
const { result } = this._startTurn({
|
|
3398
3537
|
session: options.session,
|
|
3399
3538
|
turnInput: {
|
|
@@ -3402,7 +3541,8 @@ var HarnessAgent = class {
|
|
|
3402
3541
|
toolResultContinuations: (_b4 = options.toolResultContinuations) != null ? _b4 : []
|
|
3403
3542
|
},
|
|
3404
3543
|
runtimeContext,
|
|
3405
|
-
abortSignal: options.abortSignal
|
|
3544
|
+
abortSignal: options.abortSignal,
|
|
3545
|
+
responseFormat
|
|
3406
3546
|
});
|
|
3407
3547
|
return result;
|
|
3408
3548
|
}
|
|
@@ -3417,6 +3557,8 @@ var HarnessAgent = class {
|
|
|
3417
3557
|
builtinToolFiltering: this.builtinToolFiltering,
|
|
3418
3558
|
runtimeContext: input.runtimeContext,
|
|
3419
3559
|
abortSignal: input.abortSignal,
|
|
3560
|
+
responseFormat: input.responseFormat,
|
|
3561
|
+
output: this.settings.output,
|
|
3420
3562
|
telemetry: this.settings.telemetry,
|
|
3421
3563
|
stopConditions: this.stopConditions,
|
|
3422
3564
|
toolApprovalContinuations: input.turnInput.toolApprovalContinuations,
|
|
@@ -3432,6 +3574,8 @@ var HarnessAgent = class {
|
|
|
3432
3574
|
builtinToolFiltering: this.builtinToolFiltering,
|
|
3433
3575
|
runtimeContext: input.runtimeContext,
|
|
3434
3576
|
abortSignal: input.abortSignal,
|
|
3577
|
+
responseFormat: input.responseFormat,
|
|
3578
|
+
output: this.settings.output,
|
|
3435
3579
|
telemetry: this.settings.telemetry,
|
|
3436
3580
|
stopConditions: this.stopConditions
|
|
3437
3581
|
});
|
|
@@ -3516,20 +3660,34 @@ var HarnessAgent = class {
|
|
|
3516
3660
|
return specs;
|
|
3517
3661
|
}
|
|
3518
3662
|
async _toGenerateResult(streamResult) {
|
|
3519
|
-
const [steps, usage, responseMessages] = await Promise.all([
|
|
3663
|
+
const [steps, usage, responseMessages, output] = await Promise.all([
|
|
3520
3664
|
streamResult.steps,
|
|
3521
3665
|
streamResult.usage,
|
|
3522
|
-
streamResult.responseMessages
|
|
3666
|
+
streamResult.responseMessages,
|
|
3667
|
+
this.settings.output == null ? Promise.resolve(void 0) : streamResult.output
|
|
3523
3668
|
]);
|
|
3524
|
-
return new HarnessGenerateTextResult({ steps, usage, responseMessages });
|
|
3669
|
+
return new HarnessGenerateTextResult({ steps, usage, responseMessages, output });
|
|
3670
|
+
}
|
|
3671
|
+
async _resolveResponseFormat() {
|
|
3672
|
+
var _a4;
|
|
3673
|
+
const responseFormat = await ((_a4 = this.settings.output) == null ? void 0 : _a4.responseFormat);
|
|
3674
|
+
if (responseFormat == null || responseFormat.type === "text") {
|
|
3675
|
+
return responseFormat == null ? void 0 : { type: "text" };
|
|
3676
|
+
}
|
|
3677
|
+
return {
|
|
3678
|
+
type: "json",
|
|
3679
|
+
...responseFormat.schema == null ? {} : { schema: responseFormat.schema },
|
|
3680
|
+
...responseFormat.name == null ? {} : { name: responseFormat.name },
|
|
3681
|
+
...responseFormat.description == null ? {} : { description: responseFormat.description }
|
|
3682
|
+
};
|
|
3525
3683
|
}
|
|
3526
3684
|
};
|
|
3527
3685
|
var HarnessGenerateTextResult = class {
|
|
3528
3686
|
constructor(options) {
|
|
3529
|
-
this.output = void 0;
|
|
3530
3687
|
this.steps = options.steps;
|
|
3531
3688
|
this.usage = options.usage;
|
|
3532
3689
|
this.responseMessages = options.responseMessages;
|
|
3690
|
+
this.output = options.output;
|
|
3533
3691
|
}
|
|
3534
3692
|
get finalStep() {
|
|
3535
3693
|
return this.steps.at(-1);
|
|
@@ -3691,10 +3849,11 @@ async function prepareSandboxForHarness(options) {
|
|
|
3691
3849
|
"prepareSandboxForHarness: at least one harness must be provided."
|
|
3692
3850
|
);
|
|
3693
3851
|
}
|
|
3694
|
-
const harnesses = [
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3852
|
+
const harnesses = [
|
|
3853
|
+
...new Map(
|
|
3854
|
+
options.harnesses.map((harness) => [harness.harnessId, harness])
|
|
3855
|
+
).values()
|
|
3856
|
+
].sort((a, b) => a.harnessId.localeCompare(b.harnessId));
|
|
3698
3857
|
const workDir = sandboxConfig.workDir == null ? void 0 : normalizeSandboxWorkDir(sandboxConfig.workDir);
|
|
3699
3858
|
const recipeIdentities = {};
|
|
3700
3859
|
const skippedHarnessIds = [];
|
|
@@ -3741,17 +3900,6 @@ async function prepareSandboxForHarness(options) {
|
|
|
3741
3900
|
skippedHarnessIds
|
|
3742
3901
|
};
|
|
3743
3902
|
}
|
|
3744
|
-
function assertUniqueHarnessIds(harnesses) {
|
|
3745
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3746
|
-
for (const harness of harnesses) {
|
|
3747
|
-
if (seen.has(harness.harnessId)) {
|
|
3748
|
-
throw new Error(
|
|
3749
|
-
`prepareSandboxForHarness: duplicate harness id "${harness.harnessId}".`
|
|
3750
|
-
);
|
|
3751
|
-
}
|
|
3752
|
-
seen.add(harness.harnessId);
|
|
3753
|
-
}
|
|
3754
|
-
}
|
|
3755
3903
|
async function resolvePreparedSandboxIdentity({
|
|
3756
3904
|
recipeIdentities,
|
|
3757
3905
|
bootstrapHash,
|