@granular-software/sdk 0.4.41 → 0.4.43
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/dist/agent-evals.d.mts +137 -3
- package/dist/agent-evals.d.ts +137 -3
- package/dist/agent-evals.js +1197 -79
- package/dist/agent-evals.js.map +1 -1
- package/dist/agent-evals.mjs +1197 -81
- package/dist/agent-evals.mjs.map +1 -1
- package/dist/agent-harness.d.mts +60 -1
- package/dist/agent-harness.d.ts +60 -1
- package/dist/agent-harness.js +475 -0
- package/dist/agent-harness.js.map +1 -1
- package/dist/agent-harness.mjs +467 -1
- package/dist/agent-harness.mjs.map +1 -1
- package/dist/cli/index.js +282 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +597 -53
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +589 -54
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/agent-evals.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { writeFile, mkdir } from 'fs/promises';
|
|
1
|
+
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import OpenAI from 'openai';
|
|
4
4
|
import * as Automerge from '@automerge/automerge';
|
|
@@ -162,9 +162,9 @@ var require_node_gyp_build = __commonJS({
|
|
|
162
162
|
}
|
|
163
163
|
function parseTags(file) {
|
|
164
164
|
var arr = file.split(".");
|
|
165
|
-
var
|
|
165
|
+
var extension2 = arr.pop();
|
|
166
166
|
var tags = { file, specificity: 0 };
|
|
167
|
-
if (
|
|
167
|
+
if (extension2 !== "node") return;
|
|
168
168
|
for (var i = 0; i < arr.length; i++) {
|
|
169
169
|
var tag = arr[i];
|
|
170
170
|
if (tag === "node" || tag === "electron" || tag === "node-webkit") {
|
|
@@ -412,7 +412,7 @@ var require_permessage_deflate = __commonJS({
|
|
|
412
412
|
var kBuffers = Symbol("buffers");
|
|
413
413
|
var kError = Symbol("error");
|
|
414
414
|
var zlibLimiter;
|
|
415
|
-
var
|
|
415
|
+
var PerMessageDeflate2 = class {
|
|
416
416
|
/**
|
|
417
417
|
* Creates a PerMessageDeflate instance.
|
|
418
418
|
*
|
|
@@ -423,6 +423,9 @@ var require_permessage_deflate = __commonJS({
|
|
|
423
423
|
* acknowledge disabling of client context takeover
|
|
424
424
|
* @param {Number} [options.concurrencyLimit=10] The number of concurrent
|
|
425
425
|
* calls to zlib
|
|
426
|
+
* @param {Boolean} [options.isServer=false] Create the instance in either
|
|
427
|
+
* server or client mode
|
|
428
|
+
* @param {Number} [options.maxPayload=0] The maximum allowed message length
|
|
426
429
|
* @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
|
|
427
430
|
* use of a custom server window size
|
|
428
431
|
* @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
|
|
@@ -433,15 +436,12 @@ var require_permessage_deflate = __commonJS({
|
|
|
433
436
|
* deflate
|
|
434
437
|
* @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
|
|
435
438
|
* inflate
|
|
436
|
-
* @param {Boolean} [isServer=false] Create the instance in either server or
|
|
437
|
-
* client mode
|
|
438
|
-
* @param {Number} [maxPayload=0] The maximum allowed message length
|
|
439
439
|
*/
|
|
440
|
-
constructor(options
|
|
441
|
-
this._maxPayload = maxPayload | 0;
|
|
440
|
+
constructor(options) {
|
|
442
441
|
this._options = options || {};
|
|
443
442
|
this._threshold = this._options.threshold !== void 0 ? this._options.threshold : 1024;
|
|
444
|
-
this.
|
|
443
|
+
this._maxPayload = this._options.maxPayload | 0;
|
|
444
|
+
this._isServer = !!this._options.isServer;
|
|
445
445
|
this._deflate = null;
|
|
446
446
|
this._inflate = null;
|
|
447
447
|
this.params = null;
|
|
@@ -750,7 +750,7 @@ var require_permessage_deflate = __commonJS({
|
|
|
750
750
|
});
|
|
751
751
|
}
|
|
752
752
|
};
|
|
753
|
-
module.exports =
|
|
753
|
+
module.exports = PerMessageDeflate2;
|
|
754
754
|
function deflateOnData(chunk) {
|
|
755
755
|
this[kBuffers].push(chunk);
|
|
756
756
|
this[kTotalLength] += chunk.length;
|
|
@@ -1030,7 +1030,7 @@ var require_validation = __commonJS({
|
|
|
1030
1030
|
var require_receiver = __commonJS({
|
|
1031
1031
|
"../../node_modules/ws/lib/receiver.js"(exports, module) {
|
|
1032
1032
|
var { Writable } = __require("stream");
|
|
1033
|
-
var
|
|
1033
|
+
var PerMessageDeflate2 = require_permessage_deflate();
|
|
1034
1034
|
var {
|
|
1035
1035
|
BINARY_TYPES,
|
|
1036
1036
|
EMPTY_BUFFER,
|
|
@@ -1060,6 +1060,10 @@ var require_receiver = __commonJS({
|
|
|
1060
1060
|
* extensions
|
|
1061
1061
|
* @param {Boolean} [options.isServer=false] Specifies whether to operate in
|
|
1062
1062
|
* client or server mode
|
|
1063
|
+
* @param {Number} [options.maxBufferedChunks=0] The maximum number of
|
|
1064
|
+
* buffered data chunks
|
|
1065
|
+
* @param {Number} [options.maxFragments=0] The maximum number of message
|
|
1066
|
+
* fragments
|
|
1063
1067
|
* @param {Number} [options.maxPayload=0] The maximum allowed message length
|
|
1064
1068
|
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
|
|
1065
1069
|
* not to skip UTF-8 validation for text and close messages
|
|
@@ -1070,6 +1074,8 @@ var require_receiver = __commonJS({
|
|
|
1070
1074
|
this._binaryType = options.binaryType || BINARY_TYPES[0];
|
|
1071
1075
|
this._extensions = options.extensions || {};
|
|
1072
1076
|
this._isServer = !!options.isServer;
|
|
1077
|
+
this._maxBufferedChunks = options.maxBufferedChunks | 0;
|
|
1078
|
+
this._maxFragments = options.maxFragments | 0;
|
|
1073
1079
|
this._maxPayload = options.maxPayload | 0;
|
|
1074
1080
|
this._skipUTF8Validation = !!options.skipUTF8Validation;
|
|
1075
1081
|
this[kWebSocket] = void 0;
|
|
@@ -1099,6 +1105,18 @@ var require_receiver = __commonJS({
|
|
|
1099
1105
|
*/
|
|
1100
1106
|
_write(chunk, encoding, cb) {
|
|
1101
1107
|
if (this._opcode === 8 && this._state == GET_INFO) return cb();
|
|
1108
|
+
if (this._maxBufferedChunks > 0 && this._buffers.length >= this._maxBufferedChunks) {
|
|
1109
|
+
cb(
|
|
1110
|
+
this.createError(
|
|
1111
|
+
RangeError,
|
|
1112
|
+
"Too many buffered chunks",
|
|
1113
|
+
false,
|
|
1114
|
+
1008,
|
|
1115
|
+
"WS_ERR_TOO_MANY_BUFFERED_PARTS"
|
|
1116
|
+
)
|
|
1117
|
+
);
|
|
1118
|
+
return;
|
|
1119
|
+
}
|
|
1102
1120
|
this._bufferedBytes += chunk.length;
|
|
1103
1121
|
this._buffers.push(chunk);
|
|
1104
1122
|
this.startLoop(cb);
|
|
@@ -1197,7 +1215,7 @@ var require_receiver = __commonJS({
|
|
|
1197
1215
|
return;
|
|
1198
1216
|
}
|
|
1199
1217
|
const compressed = (buf[0] & 64) === 64;
|
|
1200
|
-
if (compressed && !this._extensions[
|
|
1218
|
+
if (compressed && !this._extensions[PerMessageDeflate2.extensionName]) {
|
|
1201
1219
|
const error = this.createError(
|
|
1202
1220
|
RangeError,
|
|
1203
1221
|
"RSV1 must be clear",
|
|
@@ -1428,6 +1446,17 @@ var require_receiver = __commonJS({
|
|
|
1428
1446
|
return;
|
|
1429
1447
|
}
|
|
1430
1448
|
if (data.length) {
|
|
1449
|
+
if (this._maxFragments > 0 && this._fragments.length >= this._maxFragments) {
|
|
1450
|
+
const error = this.createError(
|
|
1451
|
+
RangeError,
|
|
1452
|
+
"Too many message fragments",
|
|
1453
|
+
false,
|
|
1454
|
+
1008,
|
|
1455
|
+
"WS_ERR_TOO_MANY_BUFFERED_PARTS"
|
|
1456
|
+
);
|
|
1457
|
+
cb(error);
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1431
1460
|
this._messageLength = this._totalPayloadLength;
|
|
1432
1461
|
this._fragments.push(data);
|
|
1433
1462
|
}
|
|
@@ -1441,7 +1470,7 @@ var require_receiver = __commonJS({
|
|
|
1441
1470
|
* @private
|
|
1442
1471
|
*/
|
|
1443
1472
|
decompress(data, cb) {
|
|
1444
|
-
const perMessageDeflate = this._extensions[
|
|
1473
|
+
const perMessageDeflate = this._extensions[PerMessageDeflate2.extensionName];
|
|
1445
1474
|
perMessageDeflate.decompress(data, this._fin, (err, buf) => {
|
|
1446
1475
|
if (err) return cb(err);
|
|
1447
1476
|
if (buf.length) {
|
|
@@ -1457,6 +1486,17 @@ var require_receiver = __commonJS({
|
|
|
1457
1486
|
cb(error);
|
|
1458
1487
|
return;
|
|
1459
1488
|
}
|
|
1489
|
+
if (this._maxFragments > 0 && this._fragments.length >= this._maxFragments) {
|
|
1490
|
+
const error = this.createError(
|
|
1491
|
+
RangeError,
|
|
1492
|
+
"Too many message fragments",
|
|
1493
|
+
false,
|
|
1494
|
+
1008,
|
|
1495
|
+
"WS_ERR_TOO_MANY_BUFFERED_PARTS"
|
|
1496
|
+
);
|
|
1497
|
+
cb(error);
|
|
1498
|
+
return;
|
|
1499
|
+
}
|
|
1460
1500
|
this._fragments.push(buf);
|
|
1461
1501
|
}
|
|
1462
1502
|
this.dataMessage(cb);
|
|
@@ -1622,7 +1662,10 @@ var require_sender = __commonJS({
|
|
|
1622
1662
|
"../../node_modules/ws/lib/sender.js"(exports, module) {
|
|
1623
1663
|
var { Duplex } = __require("stream");
|
|
1624
1664
|
var { randomFillSync } = __require("crypto");
|
|
1625
|
-
var
|
|
1665
|
+
var {
|
|
1666
|
+
types: { isUint8Array }
|
|
1667
|
+
} = __require("util");
|
|
1668
|
+
var PerMessageDeflate2 = require_permessage_deflate();
|
|
1626
1669
|
var { EMPTY_BUFFER, kWebSocket, NOOP } = require_constants();
|
|
1627
1670
|
var { isBlob, isValidStatusCode } = require_validation();
|
|
1628
1671
|
var { mask: applyMask, toBuffer } = require_buffer_util();
|
|
@@ -1775,8 +1818,10 @@ var require_sender = __commonJS({
|
|
|
1775
1818
|
buf.writeUInt16BE(code, 0);
|
|
1776
1819
|
if (typeof data === "string") {
|
|
1777
1820
|
buf.write(data, 2);
|
|
1778
|
-
} else {
|
|
1821
|
+
} else if (isUint8Array(data)) {
|
|
1779
1822
|
buf.set(data, 2);
|
|
1823
|
+
} else {
|
|
1824
|
+
throw new TypeError("Second argument must be a string or a Uint8Array");
|
|
1780
1825
|
}
|
|
1781
1826
|
}
|
|
1782
1827
|
const options = {
|
|
@@ -1906,7 +1951,7 @@ var require_sender = __commonJS({
|
|
|
1906
1951
|
* @public
|
|
1907
1952
|
*/
|
|
1908
1953
|
send(data, options, cb) {
|
|
1909
|
-
const perMessageDeflate = this._extensions[
|
|
1954
|
+
const perMessageDeflate = this._extensions[PerMessageDeflate2.extensionName];
|
|
1910
1955
|
let opcode = options.binary ? 2 : 1;
|
|
1911
1956
|
let rsv1 = options.compress;
|
|
1912
1957
|
let byteLength;
|
|
@@ -2030,7 +2075,7 @@ var require_sender = __commonJS({
|
|
|
2030
2075
|
this.sendFrame(_Sender.frame(data, options), cb);
|
|
2031
2076
|
return;
|
|
2032
2077
|
}
|
|
2033
|
-
const perMessageDeflate = this._extensions[
|
|
2078
|
+
const perMessageDeflate = this._extensions[PerMessageDeflate2.extensionName];
|
|
2034
2079
|
this._bufferedBytes += options[kByteLength];
|
|
2035
2080
|
this._state = DEFLATING;
|
|
2036
2081
|
perMessageDeflate.compress(data, options.fin, (_, buf) => {
|
|
@@ -2466,11 +2511,11 @@ var require_extension = __commonJS({
|
|
|
2466
2511
|
return offers;
|
|
2467
2512
|
}
|
|
2468
2513
|
function format(extensions) {
|
|
2469
|
-
return Object.keys(extensions).map((
|
|
2470
|
-
let configurations = extensions[
|
|
2514
|
+
return Object.keys(extensions).map((extension2) => {
|
|
2515
|
+
let configurations = extensions[extension2];
|
|
2471
2516
|
if (!Array.isArray(configurations)) configurations = [configurations];
|
|
2472
2517
|
return configurations.map((params) => {
|
|
2473
|
-
return [
|
|
2518
|
+
return [extension2].concat(
|
|
2474
2519
|
Object.keys(params).map((k) => {
|
|
2475
2520
|
let values = params[k];
|
|
2476
2521
|
if (!Array.isArray(values)) values = [values];
|
|
@@ -2495,7 +2540,7 @@ var require_websocket = __commonJS({
|
|
|
2495
2540
|
var { randomBytes, createHash } = __require("crypto");
|
|
2496
2541
|
var { Duplex, Readable } = __require("stream");
|
|
2497
2542
|
var { URL: URL2 } = __require("url");
|
|
2498
|
-
var
|
|
2543
|
+
var PerMessageDeflate2 = require_permessage_deflate();
|
|
2499
2544
|
var Receiver2 = require_receiver();
|
|
2500
2545
|
var Sender2 = require_sender();
|
|
2501
2546
|
var { isBlob } = require_validation();
|
|
@@ -2654,6 +2699,10 @@ var require_websocket = __commonJS({
|
|
|
2654
2699
|
* multiple times in the same tick
|
|
2655
2700
|
* @param {Function} [options.generateMask] The function used to generate the
|
|
2656
2701
|
* masking key
|
|
2702
|
+
* @param {Number} [options.maxBufferedChunks=0] The maximum number of
|
|
2703
|
+
* buffered data chunks
|
|
2704
|
+
* @param {Number} [options.maxFragments=0] The maximum number of message
|
|
2705
|
+
* fragments
|
|
2657
2706
|
* @param {Number} [options.maxPayload=0] The maximum allowed message size
|
|
2658
2707
|
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
|
|
2659
2708
|
* not to skip UTF-8 validation for text and close messages
|
|
@@ -2665,6 +2714,8 @@ var require_websocket = __commonJS({
|
|
|
2665
2714
|
binaryType: this.binaryType,
|
|
2666
2715
|
extensions: this._extensions,
|
|
2667
2716
|
isServer: this._isServer,
|
|
2717
|
+
maxBufferedChunks: options.maxBufferedChunks,
|
|
2718
|
+
maxFragments: options.maxFragments,
|
|
2668
2719
|
maxPayload: options.maxPayload,
|
|
2669
2720
|
skipUTF8Validation: options.skipUTF8Validation
|
|
2670
2721
|
});
|
|
@@ -2703,8 +2754,8 @@ var require_websocket = __commonJS({
|
|
|
2703
2754
|
this.emit("close", this._closeCode, this._closeMessage);
|
|
2704
2755
|
return;
|
|
2705
2756
|
}
|
|
2706
|
-
if (this._extensions[
|
|
2707
|
-
this._extensions[
|
|
2757
|
+
if (this._extensions[PerMessageDeflate2.extensionName]) {
|
|
2758
|
+
this._extensions[PerMessageDeflate2.extensionName].cleanup();
|
|
2708
2759
|
}
|
|
2709
2760
|
this._receiver.removeAllListeners();
|
|
2710
2761
|
this._readyState = _WebSocket.CLOSED;
|
|
@@ -2866,7 +2917,7 @@ var require_websocket = __commonJS({
|
|
|
2866
2917
|
fin: true,
|
|
2867
2918
|
...options
|
|
2868
2919
|
};
|
|
2869
|
-
if (!this._extensions[
|
|
2920
|
+
if (!this._extensions[PerMessageDeflate2.extensionName]) {
|
|
2870
2921
|
opts.compress = false;
|
|
2871
2922
|
}
|
|
2872
2923
|
this._sender.send(data || EMPTY_BUFFER, opts, cb);
|
|
@@ -2964,6 +3015,8 @@ var require_websocket = __commonJS({
|
|
|
2964
3015
|
autoPong: true,
|
|
2965
3016
|
closeTimeout: CLOSE_TIMEOUT,
|
|
2966
3017
|
protocolVersion: protocolVersions[1],
|
|
3018
|
+
maxBufferedChunks: 1024 * 1024,
|
|
3019
|
+
maxFragments: 128 * 1024,
|
|
2967
3020
|
maxPayload: 100 * 1024 * 1024,
|
|
2968
3021
|
skipUTF8Validation: false,
|
|
2969
3022
|
perMessageDeflate: true,
|
|
@@ -2992,7 +3045,7 @@ var require_websocket = __commonJS({
|
|
|
2992
3045
|
} else {
|
|
2993
3046
|
try {
|
|
2994
3047
|
parsedUrl = new URL2(address);
|
|
2995
|
-
} catch
|
|
3048
|
+
} catch {
|
|
2996
3049
|
throw new SyntaxError(`Invalid URL: ${address}`);
|
|
2997
3050
|
}
|
|
2998
3051
|
}
|
|
@@ -3040,13 +3093,13 @@ var require_websocket = __commonJS({
|
|
|
3040
3093
|
opts.path = parsedUrl.pathname + parsedUrl.search;
|
|
3041
3094
|
opts.timeout = opts.handshakeTimeout;
|
|
3042
3095
|
if (opts.perMessageDeflate) {
|
|
3043
|
-
perMessageDeflate = new
|
|
3044
|
-
opts.perMessageDeflate
|
|
3045
|
-
false,
|
|
3046
|
-
opts.maxPayload
|
|
3047
|
-
);
|
|
3096
|
+
perMessageDeflate = new PerMessageDeflate2({
|
|
3097
|
+
...opts.perMessageDeflate,
|
|
3098
|
+
isServer: false,
|
|
3099
|
+
maxPayload: opts.maxPayload
|
|
3100
|
+
});
|
|
3048
3101
|
opts.headers["Sec-WebSocket-Extensions"] = format({
|
|
3049
|
-
[
|
|
3102
|
+
[PerMessageDeflate2.extensionName]: perMessageDeflate.offer()
|
|
3050
3103
|
});
|
|
3051
3104
|
}
|
|
3052
3105
|
if (protocols.length) {
|
|
@@ -3189,23 +3242,25 @@ var require_websocket = __commonJS({
|
|
|
3189
3242
|
return;
|
|
3190
3243
|
}
|
|
3191
3244
|
const extensionNames = Object.keys(extensions);
|
|
3192
|
-
if (extensionNames.length !== 1 || extensionNames[0] !==
|
|
3245
|
+
if (extensionNames.length !== 1 || extensionNames[0] !== PerMessageDeflate2.extensionName) {
|
|
3193
3246
|
const message = "Server indicated an extension that was not requested";
|
|
3194
3247
|
abortHandshake(websocket, socket, message);
|
|
3195
3248
|
return;
|
|
3196
3249
|
}
|
|
3197
3250
|
try {
|
|
3198
|
-
perMessageDeflate.accept(extensions[
|
|
3251
|
+
perMessageDeflate.accept(extensions[PerMessageDeflate2.extensionName]);
|
|
3199
3252
|
} catch (err) {
|
|
3200
3253
|
const message = "Invalid Sec-WebSocket-Extensions header";
|
|
3201
3254
|
abortHandshake(websocket, socket, message);
|
|
3202
3255
|
return;
|
|
3203
3256
|
}
|
|
3204
|
-
websocket._extensions[
|
|
3257
|
+
websocket._extensions[PerMessageDeflate2.extensionName] = perMessageDeflate;
|
|
3205
3258
|
}
|
|
3206
3259
|
websocket.setSocket(socket, head, {
|
|
3207
3260
|
allowSynchronousEvents: opts.allowSynchronousEvents,
|
|
3208
3261
|
generateMask: opts.generateMask,
|
|
3262
|
+
maxBufferedChunks: opts.maxBufferedChunks,
|
|
3263
|
+
maxFragments: opts.maxFragments,
|
|
3209
3264
|
maxPayload: opts.maxPayload,
|
|
3210
3265
|
skipUTF8Validation: opts.skipUTF8Validation
|
|
3211
3266
|
});
|
|
@@ -3517,9 +3572,9 @@ var require_websocket_server = __commonJS({
|
|
|
3517
3572
|
var http = __require("http");
|
|
3518
3573
|
var { Duplex } = __require("stream");
|
|
3519
3574
|
var { createHash } = __require("crypto");
|
|
3520
|
-
var
|
|
3521
|
-
var
|
|
3522
|
-
var
|
|
3575
|
+
var extension2 = require_extension();
|
|
3576
|
+
var PerMessageDeflate2 = require_permessage_deflate();
|
|
3577
|
+
var subprotocol2 = require_subprotocol();
|
|
3523
3578
|
var WebSocket2 = require_websocket();
|
|
3524
3579
|
var { CLOSE_TIMEOUT, GUID, kWebSocket } = require_constants();
|
|
3525
3580
|
var keyRegex = /^[+/0-9A-Za-z]{22}==$/;
|
|
@@ -3545,6 +3600,10 @@ var require_websocket_server = __commonJS({
|
|
|
3545
3600
|
* called
|
|
3546
3601
|
* @param {Function} [options.handleProtocols] A hook to handle protocols
|
|
3547
3602
|
* @param {String} [options.host] The hostname where to bind the server
|
|
3603
|
+
* @param {Number} [options.maxBufferedChunks=1048576] The maximum number of
|
|
3604
|
+
* buffered data chunks
|
|
3605
|
+
* @param {Number} [options.maxFragments=131072] The maximum number of message
|
|
3606
|
+
* fragments
|
|
3548
3607
|
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
|
|
3549
3608
|
* size
|
|
3550
3609
|
* @param {Boolean} [options.noServer=false] Enable no server mode
|
|
@@ -3566,6 +3625,8 @@ var require_websocket_server = __commonJS({
|
|
|
3566
3625
|
options = {
|
|
3567
3626
|
allowSynchronousEvents: true,
|
|
3568
3627
|
autoPong: true,
|
|
3628
|
+
maxBufferedChunks: 1024 * 1024,
|
|
3629
|
+
maxFragments: 128 * 1024,
|
|
3569
3630
|
maxPayload: 100 * 1024 * 1024,
|
|
3570
3631
|
skipUTF8Validation: false,
|
|
3571
3632
|
perMessageDeflate: false,
|
|
@@ -3742,7 +3803,7 @@ var require_websocket_server = __commonJS({
|
|
|
3742
3803
|
let protocols = /* @__PURE__ */ new Set();
|
|
3743
3804
|
if (secWebSocketProtocol !== void 0) {
|
|
3744
3805
|
try {
|
|
3745
|
-
protocols =
|
|
3806
|
+
protocols = subprotocol2.parse(secWebSocketProtocol);
|
|
3746
3807
|
} catch (err) {
|
|
3747
3808
|
const message = "Invalid Sec-WebSocket-Protocol header";
|
|
3748
3809
|
abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
|
|
@@ -3752,16 +3813,16 @@ var require_websocket_server = __commonJS({
|
|
|
3752
3813
|
const secWebSocketExtensions = req.headers["sec-websocket-extensions"];
|
|
3753
3814
|
const extensions = {};
|
|
3754
3815
|
if (this.options.perMessageDeflate && secWebSocketExtensions !== void 0) {
|
|
3755
|
-
const perMessageDeflate = new
|
|
3756
|
-
this.options.perMessageDeflate,
|
|
3757
|
-
true,
|
|
3758
|
-
this.options.maxPayload
|
|
3759
|
-
);
|
|
3816
|
+
const perMessageDeflate = new PerMessageDeflate2({
|
|
3817
|
+
...this.options.perMessageDeflate,
|
|
3818
|
+
isServer: true,
|
|
3819
|
+
maxPayload: this.options.maxPayload
|
|
3820
|
+
});
|
|
3760
3821
|
try {
|
|
3761
|
-
const offers =
|
|
3762
|
-
if (offers[
|
|
3763
|
-
perMessageDeflate.accept(offers[
|
|
3764
|
-
extensions[
|
|
3822
|
+
const offers = extension2.parse(secWebSocketExtensions);
|
|
3823
|
+
if (offers[PerMessageDeflate2.extensionName]) {
|
|
3824
|
+
perMessageDeflate.accept(offers[PerMessageDeflate2.extensionName]);
|
|
3825
|
+
extensions[PerMessageDeflate2.extensionName] = perMessageDeflate;
|
|
3765
3826
|
}
|
|
3766
3827
|
} catch (err) {
|
|
3767
3828
|
const message = "Invalid or unacceptable Sec-WebSocket-Extensions header";
|
|
@@ -3832,10 +3893,10 @@ var require_websocket_server = __commonJS({
|
|
|
3832
3893
|
ws._protocol = protocol;
|
|
3833
3894
|
}
|
|
3834
3895
|
}
|
|
3835
|
-
if (extensions[
|
|
3836
|
-
const params = extensions[
|
|
3837
|
-
const value =
|
|
3838
|
-
[
|
|
3896
|
+
if (extensions[PerMessageDeflate2.extensionName]) {
|
|
3897
|
+
const params = extensions[PerMessageDeflate2.extensionName].params;
|
|
3898
|
+
const value = extension2.format({
|
|
3899
|
+
[PerMessageDeflate2.extensionName]: [params]
|
|
3839
3900
|
});
|
|
3840
3901
|
headers.push(`Sec-WebSocket-Extensions: ${value}`);
|
|
3841
3902
|
ws._extensions = extensions;
|
|
@@ -3845,6 +3906,8 @@ var require_websocket_server = __commonJS({
|
|
|
3845
3906
|
socket.removeListener("error", socketOnError);
|
|
3846
3907
|
ws.setSocket(socket, head, {
|
|
3847
3908
|
allowSynchronousEvents: this.options.allowSynchronousEvents,
|
|
3909
|
+
maxBufferedChunks: this.options.maxBufferedChunks,
|
|
3910
|
+
maxFragments: this.options.maxFragments,
|
|
3848
3911
|
maxPayload: this.options.maxPayload,
|
|
3849
3912
|
skipUTF8Validation: this.options.skipUTF8Validation
|
|
3850
3913
|
});
|
|
@@ -3905,19 +3968,25 @@ var require_websocket_server = __commonJS({
|
|
|
3905
3968
|
// ../../node_modules/ws/wrapper.mjs
|
|
3906
3969
|
var wrapper_exports = {};
|
|
3907
3970
|
__export(wrapper_exports, {
|
|
3971
|
+
PerMessageDeflate: () => import_permessage_deflate.default,
|
|
3908
3972
|
Receiver: () => import_receiver.default,
|
|
3909
3973
|
Sender: () => import_sender.default,
|
|
3910
3974
|
WebSocket: () => import_websocket.default,
|
|
3911
3975
|
WebSocketServer: () => import_websocket_server.default,
|
|
3912
3976
|
createWebSocketStream: () => import_stream.default,
|
|
3913
|
-
default: () => wrapper_default
|
|
3977
|
+
default: () => wrapper_default,
|
|
3978
|
+
extension: () => import_extension.default,
|
|
3979
|
+
subprotocol: () => import_subprotocol.default
|
|
3914
3980
|
});
|
|
3915
|
-
var import_stream, import_receiver, import_sender, import_websocket, import_websocket_server, wrapper_default;
|
|
3981
|
+
var import_stream, import_extension, import_permessage_deflate, import_receiver, import_sender, import_subprotocol, import_websocket, import_websocket_server, wrapper_default;
|
|
3916
3982
|
var init_wrapper = __esm({
|
|
3917
3983
|
"../../node_modules/ws/wrapper.mjs"() {
|
|
3918
3984
|
import_stream = __toESM(require_stream());
|
|
3985
|
+
import_extension = __toESM(require_extension());
|
|
3986
|
+
import_permessage_deflate = __toESM(require_permessage_deflate());
|
|
3919
3987
|
import_receiver = __toESM(require_receiver());
|
|
3920
3988
|
import_sender = __toESM(require_sender());
|
|
3989
|
+
import_subprotocol = __toESM(require_subprotocol());
|
|
3921
3990
|
import_websocket = __toESM(require_websocket());
|
|
3922
3991
|
import_websocket_server = __toESM(require_websocket_server());
|
|
3923
3992
|
wrapper_default = import_websocket.default;
|
|
@@ -16060,7 +16129,275 @@ var Granular = class _Granular {
|
|
|
16060
16129
|
}
|
|
16061
16130
|
};
|
|
16062
16131
|
|
|
16132
|
+
// src/agent-harness-templates/action-presentation/0.1.0/manifest.json
|
|
16133
|
+
var manifest_default = {
|
|
16134
|
+
id: "action-presentation",
|
|
16135
|
+
version: "0.1.0",
|
|
16136
|
+
status: "candidate",
|
|
16137
|
+
owner: "granular",
|
|
16138
|
+
createdAt: "2026-05-25T00:00:00.000Z",
|
|
16139
|
+
changelog: "Candidate harness template focused on action-request detection and mutation result presentation. It exists to harden cases where the model answers with a terse completion such as Done instead of using tools and reporting the target/action/result.",
|
|
16140
|
+
promptBuilder: "buildGranularAgentSystemPrompt:action-presentation",
|
|
16141
|
+
continuationBuilder: "buildContinuationInstruction:action-presentation",
|
|
16142
|
+
modelOutputInstruction: "agent-evals:modelOutputInstruction",
|
|
16143
|
+
codeReviewPolicy: "reviewGeneratedJobCode",
|
|
16144
|
+
defaultModel: "gpt-5.4",
|
|
16145
|
+
modelMatrix: ["gpt-5.4"],
|
|
16146
|
+
temperature: 0,
|
|
16147
|
+
compatibility: {
|
|
16148
|
+
minSdkVersion: "0.4.40",
|
|
16149
|
+
capabilities: [
|
|
16150
|
+
"executeCode",
|
|
16151
|
+
"readEntities",
|
|
16152
|
+
"workflowHelpers",
|
|
16153
|
+
"savedData",
|
|
16154
|
+
"showRecords"
|
|
16155
|
+
]
|
|
16156
|
+
},
|
|
16157
|
+
evalGates: {
|
|
16158
|
+
requiredSuites: [
|
|
16159
|
+
"agent-harness-hardening",
|
|
16160
|
+
"agent-harness-runtime-e2e",
|
|
16161
|
+
"agent-production-readiness-e2e"
|
|
16162
|
+
],
|
|
16163
|
+
criticalBuckets: [
|
|
16164
|
+
"relationship-traversal",
|
|
16165
|
+
"cross-turn-reference",
|
|
16166
|
+
"ambiguous-target-choice",
|
|
16167
|
+
"confirmation-gated-mutation",
|
|
16168
|
+
"denied-action-refusal",
|
|
16169
|
+
"mutation-presentation"
|
|
16170
|
+
],
|
|
16171
|
+
maxRegressionPct: 0,
|
|
16172
|
+
minPassK: {
|
|
16173
|
+
"critical-mutation": 0.9,
|
|
16174
|
+
"permission-boundary": 1
|
|
16175
|
+
}
|
|
16176
|
+
}
|
|
16177
|
+
};
|
|
16178
|
+
|
|
16179
|
+
// src/agent-harness-templates/experimental-compact/0.1.0/manifest.json
|
|
16180
|
+
var manifest_default2 = {
|
|
16181
|
+
id: "experimental-compact",
|
|
16182
|
+
version: "0.1.0",
|
|
16183
|
+
status: "candidate",
|
|
16184
|
+
owner: "granular",
|
|
16185
|
+
createdAt: "2026-05-24T00:00:00.000Z",
|
|
16186
|
+
changelog: "Candidate harness template used for champion/challenger testing. It adds a compact decision discipline section on top of the stable renderer.",
|
|
16187
|
+
promptBuilder: "buildGranularAgentSystemPrompt:experimental-compact",
|
|
16188
|
+
continuationBuilder: "buildContinuationInstruction:experimental-compact",
|
|
16189
|
+
modelOutputInstruction: "agent-evals:modelOutputInstruction",
|
|
16190
|
+
codeReviewPolicy: "reviewGeneratedJobCode",
|
|
16191
|
+
defaultModel: "gpt-5.4",
|
|
16192
|
+
modelMatrix: ["gpt-5.4"],
|
|
16193
|
+
temperature: 0,
|
|
16194
|
+
compatibility: {
|
|
16195
|
+
minSdkVersion: "0.4.40",
|
|
16196
|
+
capabilities: [
|
|
16197
|
+
"executeCode",
|
|
16198
|
+
"readEntities",
|
|
16199
|
+
"workflowHelpers",
|
|
16200
|
+
"savedData",
|
|
16201
|
+
"showRecords"
|
|
16202
|
+
]
|
|
16203
|
+
},
|
|
16204
|
+
evalGates: {
|
|
16205
|
+
requiredSuites: [
|
|
16206
|
+
"agent-harness-hardening",
|
|
16207
|
+
"agent-harness-runtime-e2e",
|
|
16208
|
+
"agent-production-readiness-e2e"
|
|
16209
|
+
],
|
|
16210
|
+
criticalBuckets: [
|
|
16211
|
+
"relationship-traversal",
|
|
16212
|
+
"cross-turn-reference",
|
|
16213
|
+
"ambiguous-target-choice",
|
|
16214
|
+
"confirmation-gated-mutation",
|
|
16215
|
+
"denied-action-refusal",
|
|
16216
|
+
"mutation-presentation"
|
|
16217
|
+
],
|
|
16218
|
+
maxRegressionPct: 0,
|
|
16219
|
+
minPassK: {
|
|
16220
|
+
"critical-mutation": 0.9,
|
|
16221
|
+
"permission-boundary": 1
|
|
16222
|
+
}
|
|
16223
|
+
}
|
|
16224
|
+
};
|
|
16225
|
+
|
|
16226
|
+
// src/agent-harness-templates/stable/1.0.0/manifest.json
|
|
16227
|
+
var manifest_default3 = {
|
|
16228
|
+
id: "stable",
|
|
16229
|
+
version: "1.0.0",
|
|
16230
|
+
status: "stable",
|
|
16231
|
+
owner: "granular",
|
|
16232
|
+
createdAt: "2026-05-24T00:00:00.000Z",
|
|
16233
|
+
changelog: "Baseline template wrapping the existing Granular agent harness prompt, continuation instruction, output contract, and generated-job review policy.",
|
|
16234
|
+
promptBuilder: "buildGranularAgentSystemPrompt",
|
|
16235
|
+
continuationBuilder: "buildContinuationInstruction",
|
|
16236
|
+
modelOutputInstruction: "agent-evals:modelOutputInstruction",
|
|
16237
|
+
codeReviewPolicy: "reviewGeneratedJobCode",
|
|
16238
|
+
defaultModel: "gpt-5.4",
|
|
16239
|
+
modelMatrix: ["gpt-5.4"],
|
|
16240
|
+
temperature: 0,
|
|
16241
|
+
compatibility: {
|
|
16242
|
+
minSdkVersion: "0.4.40",
|
|
16243
|
+
capabilities: [
|
|
16244
|
+
"executeCode",
|
|
16245
|
+
"readEntities",
|
|
16246
|
+
"workflowHelpers",
|
|
16247
|
+
"savedData",
|
|
16248
|
+
"showRecords"
|
|
16249
|
+
]
|
|
16250
|
+
},
|
|
16251
|
+
evalGates: {
|
|
16252
|
+
requiredSuites: [
|
|
16253
|
+
"agent-harness-hardening",
|
|
16254
|
+
"agent-harness-runtime-e2e",
|
|
16255
|
+
"agent-production-readiness-e2e"
|
|
16256
|
+
],
|
|
16257
|
+
criticalBuckets: [
|
|
16258
|
+
"relationship-traversal",
|
|
16259
|
+
"cross-turn-reference",
|
|
16260
|
+
"ambiguous-target-choice",
|
|
16261
|
+
"confirmation-gated-mutation",
|
|
16262
|
+
"denied-action-refusal",
|
|
16263
|
+
"mutation-presentation"
|
|
16264
|
+
],
|
|
16265
|
+
maxRegressionPct: 0,
|
|
16266
|
+
minPassK: {
|
|
16267
|
+
"critical-mutation": 0.9,
|
|
16268
|
+
"permission-boundary": 1
|
|
16269
|
+
}
|
|
16270
|
+
}
|
|
16271
|
+
};
|
|
16272
|
+
|
|
16063
16273
|
// src/agent-harness.ts
|
|
16274
|
+
var HARNESS_TEMPLATE_STATUSES = [
|
|
16275
|
+
"draft",
|
|
16276
|
+
"candidate",
|
|
16277
|
+
"release-candidate",
|
|
16278
|
+
"stable",
|
|
16279
|
+
"deprecated"
|
|
16280
|
+
];
|
|
16281
|
+
function requireRecord(value, context) {
|
|
16282
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
16283
|
+
throw new Error(`${context} must be an object.`);
|
|
16284
|
+
}
|
|
16285
|
+
return value;
|
|
16286
|
+
}
|
|
16287
|
+
function requiredString(record, key, context) {
|
|
16288
|
+
const value = record[key];
|
|
16289
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
16290
|
+
throw new Error(`${context}.${key} must be a non-empty string.`);
|
|
16291
|
+
}
|
|
16292
|
+
return value;
|
|
16293
|
+
}
|
|
16294
|
+
function requiredNumber(record, key, context) {
|
|
16295
|
+
const value = record[key];
|
|
16296
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
16297
|
+
throw new Error(`${context}.${key} must be a finite number.`);
|
|
16298
|
+
}
|
|
16299
|
+
return value;
|
|
16300
|
+
}
|
|
16301
|
+
function requiredStringArray(record, key, context) {
|
|
16302
|
+
const value = record[key];
|
|
16303
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !item.trim())) {
|
|
16304
|
+
throw new Error(`${context}.${key} must be an array of non-empty strings.`);
|
|
16305
|
+
}
|
|
16306
|
+
return [...value];
|
|
16307
|
+
}
|
|
16308
|
+
function requiredNumberRecord(record, key, context) {
|
|
16309
|
+
const value = requireRecord(record[key], `${context}.${key}`);
|
|
16310
|
+
const output = {};
|
|
16311
|
+
for (const [entryKey, entryValue] of Object.entries(value)) {
|
|
16312
|
+
if (typeof entryValue !== "number" || !Number.isFinite(entryValue) || entryValue < 0 || entryValue > 1) {
|
|
16313
|
+
throw new Error(
|
|
16314
|
+
`${context}.${key}.${entryKey} must be a number between 0 and 1.`
|
|
16315
|
+
);
|
|
16316
|
+
}
|
|
16317
|
+
output[entryKey] = entryValue;
|
|
16318
|
+
}
|
|
16319
|
+
return output;
|
|
16320
|
+
}
|
|
16321
|
+
function validateHarnessTemplateManifest(value, context = "HarnessTemplateManifest") {
|
|
16322
|
+
const record = requireRecord(value, context);
|
|
16323
|
+
const status = requiredString(record, "status", context);
|
|
16324
|
+
if (!HARNESS_TEMPLATE_STATUSES.includes(status)) {
|
|
16325
|
+
throw new Error(
|
|
16326
|
+
`${context}.status must be one of ${HARNESS_TEMPLATE_STATUSES.join(", ")}.`
|
|
16327
|
+
);
|
|
16328
|
+
}
|
|
16329
|
+
const createdAt = requiredString(record, "createdAt", context);
|
|
16330
|
+
if (Number.isNaN(Date.parse(createdAt))) {
|
|
16331
|
+
throw new Error(`${context}.createdAt must be an ISO timestamp.`);
|
|
16332
|
+
}
|
|
16333
|
+
const compatibility = requireRecord(
|
|
16334
|
+
record.compatibility,
|
|
16335
|
+
`${context}.compatibility`
|
|
16336
|
+
);
|
|
16337
|
+
const evalGates = requireRecord(record.evalGates, `${context}.evalGates`);
|
|
16338
|
+
const maxRegressionPct = requiredNumber(
|
|
16339
|
+
evalGates,
|
|
16340
|
+
"maxRegressionPct",
|
|
16341
|
+
`${context}.evalGates`
|
|
16342
|
+
);
|
|
16343
|
+
if (maxRegressionPct < 0 || maxRegressionPct > 1) {
|
|
16344
|
+
throw new Error(
|
|
16345
|
+
`${context}.evalGates.maxRegressionPct must be between 0 and 1.`
|
|
16346
|
+
);
|
|
16347
|
+
}
|
|
16348
|
+
return {
|
|
16349
|
+
id: requiredString(record, "id", context),
|
|
16350
|
+
version: requiredString(record, "version", context),
|
|
16351
|
+
status,
|
|
16352
|
+
owner: requiredString(record, "owner", context),
|
|
16353
|
+
createdAt,
|
|
16354
|
+
changelog: requiredString(record, "changelog", context),
|
|
16355
|
+
promptBuilder: requiredString(record, "promptBuilder", context),
|
|
16356
|
+
continuationBuilder: requiredString(record, "continuationBuilder", context),
|
|
16357
|
+
modelOutputInstruction: requiredString(
|
|
16358
|
+
record,
|
|
16359
|
+
"modelOutputInstruction",
|
|
16360
|
+
context
|
|
16361
|
+
),
|
|
16362
|
+
codeReviewPolicy: requiredString(record, "codeReviewPolicy", context),
|
|
16363
|
+
defaultModel: requiredString(record, "defaultModel", context),
|
|
16364
|
+
modelMatrix: requiredStringArray(record, "modelMatrix", context),
|
|
16365
|
+
temperature: requiredNumber(record, "temperature", context),
|
|
16366
|
+
compatibility: {
|
|
16367
|
+
minSdkVersion: requiredString(
|
|
16368
|
+
compatibility,
|
|
16369
|
+
"minSdkVersion",
|
|
16370
|
+
`${context}.compatibility`
|
|
16371
|
+
),
|
|
16372
|
+
capabilities: requiredStringArray(
|
|
16373
|
+
compatibility,
|
|
16374
|
+
"capabilities",
|
|
16375
|
+
`${context}.compatibility`
|
|
16376
|
+
)
|
|
16377
|
+
},
|
|
16378
|
+
evalGates: {
|
|
16379
|
+
requiredSuites: requiredStringArray(
|
|
16380
|
+
evalGates,
|
|
16381
|
+
"requiredSuites",
|
|
16382
|
+
`${context}.evalGates`
|
|
16383
|
+
),
|
|
16384
|
+
criticalBuckets: requiredStringArray(
|
|
16385
|
+
evalGates,
|
|
16386
|
+
"criticalBuckets",
|
|
16387
|
+
`${context}.evalGates`
|
|
16388
|
+
),
|
|
16389
|
+
maxRegressionPct,
|
|
16390
|
+
minPassK: requiredNumberRecord(
|
|
16391
|
+
evalGates,
|
|
16392
|
+
"minPassK",
|
|
16393
|
+
`${context}.evalGates`
|
|
16394
|
+
)
|
|
16395
|
+
}
|
|
16396
|
+
};
|
|
16397
|
+
}
|
|
16398
|
+
function defineHarnessTemplateManifest(value, context) {
|
|
16399
|
+
return validateHarnessTemplateManifest(value, context);
|
|
16400
|
+
}
|
|
16064
16401
|
function asRecord4(value) {
|
|
16065
16402
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
16066
16403
|
return value;
|
|
@@ -16084,6 +16421,16 @@ function uniqueStrings(values, maxCount) {
|
|
|
16084
16421
|
}
|
|
16085
16422
|
return output;
|
|
16086
16423
|
}
|
|
16424
|
+
function stableStringify(value) {
|
|
16425
|
+
if (value === null || typeof value !== "object") {
|
|
16426
|
+
return JSON.stringify(value);
|
|
16427
|
+
}
|
|
16428
|
+
if (Array.isArray(value)) {
|
|
16429
|
+
return `[${value.map((entry) => stableStringify(entry)).join(",")}]`;
|
|
16430
|
+
}
|
|
16431
|
+
const record = value;
|
|
16432
|
+
return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`).join(",")}}`;
|
|
16433
|
+
}
|
|
16087
16434
|
function renderConstBlock(name, value) {
|
|
16088
16435
|
return `const ${name} = ${JSON.stringify(value, null, 2)} as const;`;
|
|
16089
16436
|
}
|
|
@@ -18023,6 +18370,156 @@ ${knownFactsBlock}
|
|
|
18023
18370
|
[Request]
|
|
18024
18371
|
${input.request?.trim() || "Use the latest user message in the conversation."}`;
|
|
18025
18372
|
}
|
|
18373
|
+
var STABLE_AGENT_HARNESS_TEMPLATE_MANIFEST = defineHarnessTemplateManifest(
|
|
18374
|
+
manifest_default3,
|
|
18375
|
+
"stable@1.0.0 manifest"
|
|
18376
|
+
);
|
|
18377
|
+
function hashHarnessTemplateValue(value) {
|
|
18378
|
+
return hashString(stableStringify(value)) || "00000000";
|
|
18379
|
+
}
|
|
18380
|
+
function renderStableHarnessPrompt(input) {
|
|
18381
|
+
const prompt = buildGranularAgentSystemPrompt(input);
|
|
18382
|
+
const templateHash = hashHarnessTemplateValue(
|
|
18383
|
+
STABLE_AGENT_HARNESS_TEMPLATE_MANIFEST
|
|
18384
|
+
);
|
|
18385
|
+
return {
|
|
18386
|
+
templateId: STABLE_AGENT_HARNESS_TEMPLATE_MANIFEST.id,
|
|
18387
|
+
templateVersion: STABLE_AGENT_HARNESS_TEMPLATE_MANIFEST.version,
|
|
18388
|
+
templateHash,
|
|
18389
|
+
promptInstanceHash: hashHarnessTemplateValue({
|
|
18390
|
+
templateHash,
|
|
18391
|
+
input,
|
|
18392
|
+
prompt
|
|
18393
|
+
}),
|
|
18394
|
+
prompt
|
|
18395
|
+
};
|
|
18396
|
+
}
|
|
18397
|
+
function renderStableHarnessContinuation(resultPreview) {
|
|
18398
|
+
const instruction = buildContinuationInstruction(resultPreview);
|
|
18399
|
+
const templateHash = hashHarnessTemplateValue(
|
|
18400
|
+
STABLE_AGENT_HARNESS_TEMPLATE_MANIFEST
|
|
18401
|
+
);
|
|
18402
|
+
return {
|
|
18403
|
+
templateId: STABLE_AGENT_HARNESS_TEMPLATE_MANIFEST.id,
|
|
18404
|
+
templateVersion: STABLE_AGENT_HARNESS_TEMPLATE_MANIFEST.version,
|
|
18405
|
+
templateHash,
|
|
18406
|
+
instruction
|
|
18407
|
+
};
|
|
18408
|
+
}
|
|
18409
|
+
var STABLE_AGENT_HARNESS_TEMPLATE = {
|
|
18410
|
+
manifest: STABLE_AGENT_HARNESS_TEMPLATE_MANIFEST,
|
|
18411
|
+
renderPrompt: renderStableHarnessPrompt,
|
|
18412
|
+
renderContinuation: renderStableHarnessContinuation
|
|
18413
|
+
};
|
|
18414
|
+
var EXPERIMENTAL_COMPACT_AGENT_HARNESS_TEMPLATE_MANIFEST = defineHarnessTemplateManifest(
|
|
18415
|
+
manifest_default2,
|
|
18416
|
+
"experimental-compact@0.1.0 manifest"
|
|
18417
|
+
);
|
|
18418
|
+
function renderExperimentalCompactHarnessPrompt(input) {
|
|
18419
|
+
const prompt = `${buildGranularAgentSystemPrompt(input)}
|
|
18420
|
+
|
|
18421
|
+
[Candidate Harness Delta: Compact Decision Discipline]
|
|
18422
|
+
- Prefer the smallest action that satisfies the current request.
|
|
18423
|
+
- When several records could match, ask one structured choice question before mutating.
|
|
18424
|
+
- Before any irreversible or outbound mutation, obtain explicit confirmation unless the policy surface already requires it.
|
|
18425
|
+
- Do not compensate for missing tools with raw network calls, synthetic records, or hidden side channels.
|
|
18426
|
+
- Keep the final user-facing reply focused on what was done, what was not done, and any remaining blocker.`;
|
|
18427
|
+
const templateHash = hashHarnessTemplateValue(
|
|
18428
|
+
EXPERIMENTAL_COMPACT_AGENT_HARNESS_TEMPLATE_MANIFEST
|
|
18429
|
+
);
|
|
18430
|
+
return {
|
|
18431
|
+
templateId: EXPERIMENTAL_COMPACT_AGENT_HARNESS_TEMPLATE_MANIFEST.id,
|
|
18432
|
+
templateVersion: EXPERIMENTAL_COMPACT_AGENT_HARNESS_TEMPLATE_MANIFEST.version,
|
|
18433
|
+
templateHash,
|
|
18434
|
+
promptInstanceHash: hashHarnessTemplateValue({
|
|
18435
|
+
templateHash,
|
|
18436
|
+
input,
|
|
18437
|
+
prompt
|
|
18438
|
+
}),
|
|
18439
|
+
prompt
|
|
18440
|
+
};
|
|
18441
|
+
}
|
|
18442
|
+
function renderExperimentalCompactHarnessContinuation(resultPreview) {
|
|
18443
|
+
const instruction = `${buildContinuationInstruction(resultPreview)}
|
|
18444
|
+
|
|
18445
|
+
Keep the continuation compact: either finish, ask the one blocking question, or run the next smallest safe action.`;
|
|
18446
|
+
const templateHash = hashHarnessTemplateValue(
|
|
18447
|
+
EXPERIMENTAL_COMPACT_AGENT_HARNESS_TEMPLATE_MANIFEST
|
|
18448
|
+
);
|
|
18449
|
+
return {
|
|
18450
|
+
templateId: EXPERIMENTAL_COMPACT_AGENT_HARNESS_TEMPLATE_MANIFEST.id,
|
|
18451
|
+
templateVersion: EXPERIMENTAL_COMPACT_AGENT_HARNESS_TEMPLATE_MANIFEST.version,
|
|
18452
|
+
templateHash,
|
|
18453
|
+
instruction
|
|
18454
|
+
};
|
|
18455
|
+
}
|
|
18456
|
+
var EXPERIMENTAL_COMPACT_AGENT_HARNESS_TEMPLATE = {
|
|
18457
|
+
manifest: EXPERIMENTAL_COMPACT_AGENT_HARNESS_TEMPLATE_MANIFEST,
|
|
18458
|
+
renderPrompt: renderExperimentalCompactHarnessPrompt,
|
|
18459
|
+
renderContinuation: renderExperimentalCompactHarnessContinuation
|
|
18460
|
+
};
|
|
18461
|
+
var ACTION_PRESENTATION_AGENT_HARNESS_TEMPLATE_MANIFEST = defineHarnessTemplateManifest(
|
|
18462
|
+
manifest_default,
|
|
18463
|
+
"action-presentation@0.1.0 manifest"
|
|
18464
|
+
);
|
|
18465
|
+
function renderActionPresentationHarnessPrompt(input) {
|
|
18466
|
+
const prompt = `${buildGranularAgentSystemPrompt(input)}
|
|
18467
|
+
|
|
18468
|
+
[Candidate Harness Delta: Action Request And Result Presentation]
|
|
18469
|
+
- Treat requests like "handle it", "take care of it", "send it", "update it", "fix it", "process it", or "do it" as action requests when the message names a business object, target, workflow, or mutation verb.
|
|
18470
|
+
- For action requests involving session data, generated files, records, effects, or workflows, do not use text-only completion. Generate and run code, ask the blocking human question, or clearly refuse if policy/tooling prevents the action.
|
|
18471
|
+
- Never answer only "Done", "OK", "Handled", or similar terse completion text for a mutation request. The final user-facing reply must name the action attempted, the grounded target or blocker, and the actual result.
|
|
18472
|
+
- After a mutation/effect call, base the reply on the returned action result and include a visible target label or identifier when one exists.
|
|
18473
|
+
- If no target can be grounded, say what was searched and what exact identifier or choice is needed; do not pretend the action completed.`;
|
|
18474
|
+
const templateHash = hashHarnessTemplateValue(
|
|
18475
|
+
ACTION_PRESENTATION_AGENT_HARNESS_TEMPLATE_MANIFEST
|
|
18476
|
+
);
|
|
18477
|
+
return {
|
|
18478
|
+
templateId: ACTION_PRESENTATION_AGENT_HARNESS_TEMPLATE_MANIFEST.id,
|
|
18479
|
+
templateVersion: ACTION_PRESENTATION_AGENT_HARNESS_TEMPLATE_MANIFEST.version,
|
|
18480
|
+
templateHash,
|
|
18481
|
+
promptInstanceHash: hashHarnessTemplateValue({
|
|
18482
|
+
templateHash,
|
|
18483
|
+
input,
|
|
18484
|
+
prompt
|
|
18485
|
+
}),
|
|
18486
|
+
prompt
|
|
18487
|
+
};
|
|
18488
|
+
}
|
|
18489
|
+
function renderActionPresentationHarnessContinuation(resultPreview) {
|
|
18490
|
+
const instruction = `${buildContinuationInstruction(resultPreview)}
|
|
18491
|
+
|
|
18492
|
+
Before finishing, check whether the latest user request asked for an action. If it did, do not finish with a bare completion token; either continue with the needed tool/code step, ask the blocking question, refuse with the policy reason, or report the grounded action result with the target label.`;
|
|
18493
|
+
const templateHash = hashHarnessTemplateValue(
|
|
18494
|
+
ACTION_PRESENTATION_AGENT_HARNESS_TEMPLATE_MANIFEST
|
|
18495
|
+
);
|
|
18496
|
+
return {
|
|
18497
|
+
templateId: ACTION_PRESENTATION_AGENT_HARNESS_TEMPLATE_MANIFEST.id,
|
|
18498
|
+
templateVersion: ACTION_PRESENTATION_AGENT_HARNESS_TEMPLATE_MANIFEST.version,
|
|
18499
|
+
templateHash,
|
|
18500
|
+
instruction
|
|
18501
|
+
};
|
|
18502
|
+
}
|
|
18503
|
+
var ACTION_PRESENTATION_AGENT_HARNESS_TEMPLATE = {
|
|
18504
|
+
manifest: ACTION_PRESENTATION_AGENT_HARNESS_TEMPLATE_MANIFEST,
|
|
18505
|
+
renderPrompt: renderActionPresentationHarnessPrompt,
|
|
18506
|
+
renderContinuation: renderActionPresentationHarnessContinuation
|
|
18507
|
+
};
|
|
18508
|
+
var AGENT_HARNESS_TEMPLATES = {
|
|
18509
|
+
[STABLE_AGENT_HARNESS_TEMPLATE.manifest.id]: STABLE_AGENT_HARNESS_TEMPLATE,
|
|
18510
|
+
[EXPERIMENTAL_COMPACT_AGENT_HARNESS_TEMPLATE.manifest.id]: EXPERIMENTAL_COMPACT_AGENT_HARNESS_TEMPLATE,
|
|
18511
|
+
[ACTION_PRESENTATION_AGENT_HARNESS_TEMPLATE.manifest.id]: ACTION_PRESENTATION_AGENT_HARNESS_TEMPLATE
|
|
18512
|
+
};
|
|
18513
|
+
function resolveHarnessTemplate(templateId = "stable", options) {
|
|
18514
|
+
const resolved = AGENT_HARNESS_TEMPLATES[templateId];
|
|
18515
|
+
if (resolved) return resolved;
|
|
18516
|
+
{
|
|
18517
|
+
const known = Object.keys(AGENT_HARNESS_TEMPLATES).join(", ");
|
|
18518
|
+
throw new Error(
|
|
18519
|
+
`Unknown harness template "${templateId}". Known templates: ${known}`
|
|
18520
|
+
);
|
|
18521
|
+
}
|
|
18522
|
+
}
|
|
18026
18523
|
|
|
18027
18524
|
// src/openai-usage.ts
|
|
18028
18525
|
var OPENAI_PRICING_SOURCE_URL = "https://developers.openai.com/api/docs/models/gpt-5.4/";
|
|
@@ -18144,6 +18641,98 @@ function matchesPattern(text, matcher) {
|
|
|
18144
18641
|
if (typeof matcher === "string") return text.includes(matcher);
|
|
18145
18642
|
return matcher.test(text);
|
|
18146
18643
|
}
|
|
18644
|
+
function matcherFromConfig(value) {
|
|
18645
|
+
const match = value.match(/^\/([\s\S]*)\/([dgimsuvy]*)$/);
|
|
18646
|
+
if (!match) return value;
|
|
18647
|
+
return new RegExp(match[1] || "", match[2] || "");
|
|
18648
|
+
}
|
|
18649
|
+
function matchersFromConfig(values) {
|
|
18650
|
+
if (!values?.length) return void 0;
|
|
18651
|
+
return values.map((value) => matcherFromConfig(value));
|
|
18652
|
+
}
|
|
18653
|
+
function expectationsFromConfig(input) {
|
|
18654
|
+
if (!input) return void 0;
|
|
18655
|
+
return {
|
|
18656
|
+
replyIncludes: matchersFromConfig(input.replyIncludes),
|
|
18657
|
+
replyExcludes: matchersFromConfig(input.replyExcludes),
|
|
18658
|
+
actionIncludes: matchersFromConfig(input.actionIncludes),
|
|
18659
|
+
actionExcludes: matchersFromConfig(input.actionExcludes),
|
|
18660
|
+
codeIncludes: matchersFromConfig(input.codeIncludes),
|
|
18661
|
+
codeExcludes: matchersFromConfig(input.codeExcludes),
|
|
18662
|
+
behaviorBuckets: input.behaviorBuckets,
|
|
18663
|
+
actions: input.actions ? {
|
|
18664
|
+
required: matchersFromConfig(input.actions.required),
|
|
18665
|
+
forbidden: matchersFromConfig(input.actions.forbidden)
|
|
18666
|
+
} : void 0,
|
|
18667
|
+
prompts: input.prompts ? {
|
|
18668
|
+
...input.prompts,
|
|
18669
|
+
requiredConfirmationBefore: matchersFromConfig(
|
|
18670
|
+
input.prompts.requiredConfirmationBefore
|
|
18671
|
+
)
|
|
18672
|
+
} : void 0,
|
|
18673
|
+
presentation: input.presentation ? {
|
|
18674
|
+
mustMention: matchersFromConfig(input.presentation.mustMention),
|
|
18675
|
+
mustNotMention: matchersFromConfig(input.presentation.mustNotMention),
|
|
18676
|
+
mustDisplayOrSave: matchersFromConfig(
|
|
18677
|
+
input.presentation.mustDisplayOrSave
|
|
18678
|
+
)
|
|
18679
|
+
} : void 0
|
|
18680
|
+
};
|
|
18681
|
+
}
|
|
18682
|
+
function promptResponderFromConfig(rules) {
|
|
18683
|
+
if (!rules?.length) return void 0;
|
|
18684
|
+
return createHumanResponder(
|
|
18685
|
+
rules.map((rule) => ({
|
|
18686
|
+
type: rule.type,
|
|
18687
|
+
when: Array.isArray(rule.when) ? rule.when.map((matcher) => matcherFromConfig(matcher)) : rule.when ? matcherFromConfig(rule.when) : void 0,
|
|
18688
|
+
answer: rule.answer
|
|
18689
|
+
}))
|
|
18690
|
+
);
|
|
18691
|
+
}
|
|
18692
|
+
function inspectionFromConfig(inspection) {
|
|
18693
|
+
if (!inspection) return void 0;
|
|
18694
|
+
return {
|
|
18695
|
+
code: inspection.code,
|
|
18696
|
+
includes: matchersFromConfig(inspection.includes),
|
|
18697
|
+
excludes: matchersFromConfig(inspection.excludes)
|
|
18698
|
+
};
|
|
18699
|
+
}
|
|
18700
|
+
function inspectionsFromConfig(inspections) {
|
|
18701
|
+
if (!inspections) return void 0;
|
|
18702
|
+
if (Array.isArray(inspections)) {
|
|
18703
|
+
return inspections.map((inspection) => inspectionFromConfig(inspection)).filter(
|
|
18704
|
+
(inspection) => Boolean(inspection)
|
|
18705
|
+
);
|
|
18706
|
+
}
|
|
18707
|
+
return inspectionFromConfig(inspections);
|
|
18708
|
+
}
|
|
18709
|
+
function scenariosFromAgentEvalFile(file) {
|
|
18710
|
+
return file.scenarios.map((scenario) => ({
|
|
18711
|
+
id: scenario.id,
|
|
18712
|
+
description: scenario.description,
|
|
18713
|
+
request: scenario.request,
|
|
18714
|
+
behaviorBuckets: scenario.behaviorBuckets,
|
|
18715
|
+
human: promptResponderFromConfig(scenario.human),
|
|
18716
|
+
prepareRecords: scenario.prepareRecords,
|
|
18717
|
+
expect: expectationsFromConfig(scenario.expect),
|
|
18718
|
+
verify: inspectionFromConfig(scenario.verify),
|
|
18719
|
+
inspect: inspectionsFromConfig(scenario.inspect),
|
|
18720
|
+
steps: scenario.steps?.map((step) => ({
|
|
18721
|
+
id: step.id,
|
|
18722
|
+
request: step.request,
|
|
18723
|
+
behaviorBuckets: step.behaviorBuckets || scenario.behaviorBuckets,
|
|
18724
|
+
human: promptResponderFromConfig(step.human || scenario.human),
|
|
18725
|
+
expect: expectationsFromConfig(step.expect || scenario.expect),
|
|
18726
|
+
inspect: inspectionsFromConfig(step.inspect)
|
|
18727
|
+
}))
|
|
18728
|
+
}));
|
|
18729
|
+
}
|
|
18730
|
+
async function loadAgentEvalScenarioFile(filePath) {
|
|
18731
|
+
const raw = JSON.parse(
|
|
18732
|
+
await readFile(filePath, "utf8")
|
|
18733
|
+
);
|
|
18734
|
+
return scenariosFromAgentEvalFile(raw);
|
|
18735
|
+
}
|
|
18147
18736
|
function assertMatches(label, text, includes = [], excludes = []) {
|
|
18148
18737
|
for (const matcher of includes) {
|
|
18149
18738
|
if (!matchesPattern(text, matcher)) {
|
|
@@ -18176,6 +18765,23 @@ function asArray3(value) {
|
|
|
18176
18765
|
if (!value) return [];
|
|
18177
18766
|
return Array.isArray(value) ? value : [value];
|
|
18178
18767
|
}
|
|
18768
|
+
function progressEvent(input) {
|
|
18769
|
+
return {
|
|
18770
|
+
...input,
|
|
18771
|
+
id: input.id || [
|
|
18772
|
+
input.scenarioId || "suite",
|
|
18773
|
+
input.stepId || input.phase,
|
|
18774
|
+
input.iteration ? `iteration-${input.iteration}` : "",
|
|
18775
|
+
input.jobId || "",
|
|
18776
|
+
input.title,
|
|
18777
|
+
Date.now()
|
|
18778
|
+
].filter(Boolean).join(":"),
|
|
18779
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
18780
|
+
};
|
|
18781
|
+
}
|
|
18782
|
+
async function emitProgress(handler, event) {
|
|
18783
|
+
await handler?.(progressEvent(event));
|
|
18784
|
+
}
|
|
18179
18785
|
var GPT_54_TOKEN_PRICING_USD_PER_MILLION = {
|
|
18180
18786
|
input: 2.5,
|
|
18181
18787
|
cachedInput: 0.25,
|
|
@@ -18418,7 +19024,7 @@ function filterPromptsByBoundary(liveDoc, prompts, boundaryTimestamp) {
|
|
|
18418
19024
|
});
|
|
18419
19025
|
}
|
|
18420
19026
|
function createScriptedPromptResponder(rules, fallback) {
|
|
18421
|
-
|
|
19027
|
+
const responder = async ({ prompt, history }) => {
|
|
18422
19028
|
const promptText = `${prompt.title || ""}
|
|
18423
19029
|
${prompt.message || ""}`;
|
|
18424
19030
|
for (const rule of rules) {
|
|
@@ -18435,6 +19041,11 @@ ${prompt.message || ""}`;
|
|
|
18435
19041
|
`No scripted prompt responder matched prompt ${prompt.id}: ${promptText}`
|
|
18436
19042
|
);
|
|
18437
19043
|
};
|
|
19044
|
+
Object.defineProperty(responder, "__granularScriptedPromptRules", {
|
|
19045
|
+
enumerable: false,
|
|
19046
|
+
value: rules
|
|
19047
|
+
});
|
|
19048
|
+
return responder;
|
|
18438
19049
|
}
|
|
18439
19050
|
function extractJsonObject(text) {
|
|
18440
19051
|
const start = text.indexOf("{");
|
|
@@ -18721,6 +19332,22 @@ ${checkpoint.latestJobResult}` : null
|
|
|
18721
19332
|
];
|
|
18722
19333
|
return lines.filter(Boolean).join("\n\n");
|
|
18723
19334
|
}
|
|
19335
|
+
function readableAgentMessage(message) {
|
|
19336
|
+
const record = asRecord6(message);
|
|
19337
|
+
if (!record) return JSON.stringify(message);
|
|
19338
|
+
if (typeof record.reply === "string" && record.reply.trim()) {
|
|
19339
|
+
return record.reply;
|
|
19340
|
+
}
|
|
19341
|
+
const show = asRecord6(record.show);
|
|
19342
|
+
const variableNames = asArray3(show?.variableNames).map((value) => String(value)).filter(Boolean);
|
|
19343
|
+
if (variableNames.length) {
|
|
19344
|
+
return `Displayed ${variableNames.join(", ")}`;
|
|
19345
|
+
}
|
|
19346
|
+
if (typeof record.kind === "string") {
|
|
19347
|
+
return `Agent ${record.kind} message`;
|
|
19348
|
+
}
|
|
19349
|
+
return JSON.stringify(message);
|
|
19350
|
+
}
|
|
18724
19351
|
async function waitForJobOutcome(input) {
|
|
18725
19352
|
const stdout = [];
|
|
18726
19353
|
const stderr = [];
|
|
@@ -18728,6 +19355,11 @@ async function waitForJobOutcome(input) {
|
|
|
18728
19355
|
let lastPromptCount = 0;
|
|
18729
19356
|
let lastMessageCount = 0;
|
|
18730
19357
|
let lastJobSummary = null;
|
|
19358
|
+
let lastActionSummaryKey = "";
|
|
19359
|
+
let lastActionSummaryLength = 0;
|
|
19360
|
+
let lastAgentMessageKey = "";
|
|
19361
|
+
let lastAgentMessageCount = 0;
|
|
19362
|
+
let lastJobStatus = "";
|
|
18731
19363
|
input.job.on("stdout", (line) => stdout.push(String(line)));
|
|
18732
19364
|
input.job.on("stderr", (line) => stderr.push(String(line)));
|
|
18733
19365
|
const startedAt = Date.now();
|
|
@@ -18743,7 +19375,71 @@ async function waitForJobOutcome(input) {
|
|
|
18743
19375
|
const messages = asArray3(asRecord6(liveDoc.conversation)?.messages);
|
|
18744
19376
|
lastMessageCount = messages.length;
|
|
18745
19377
|
lastJobSummary = asRecord6(asRecord6(liveDoc.jobs)?.byId)?.[input.job.id] || null;
|
|
19378
|
+
const jobRecord = asRecord6(lastJobSummary);
|
|
19379
|
+
const jobStatus = typeof jobRecord?.status === "string" ? jobRecord.status : "";
|
|
19380
|
+
if (jobStatus && jobStatus !== lastJobStatus) {
|
|
19381
|
+
lastJobStatus = jobStatus;
|
|
19382
|
+
input.onProgress?.({
|
|
19383
|
+
id: `${input.job.id}:status:${jobStatus}:${Date.now()}`,
|
|
19384
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19385
|
+
phase: "job",
|
|
19386
|
+
status: "running",
|
|
19387
|
+
jobId: input.job.id,
|
|
19388
|
+
title: `Job ${jobStatus}`,
|
|
19389
|
+
message: `Granular job ${input.job.id}`,
|
|
19390
|
+
data: jobRecord,
|
|
19391
|
+
...input.progressContext
|
|
19392
|
+
});
|
|
19393
|
+
}
|
|
19394
|
+
const actionSummary = getActionSummary(liveDoc, input.job.id);
|
|
19395
|
+
const actionSummaryKey = JSON.stringify(actionSummary);
|
|
19396
|
+
if (actionSummary.length && actionSummaryKey !== lastActionSummaryKey) {
|
|
19397
|
+
const newActions = actionSummary.slice(lastActionSummaryLength);
|
|
19398
|
+
lastActionSummaryLength = actionSummary.length;
|
|
19399
|
+
lastActionSummaryKey = actionSummaryKey;
|
|
19400
|
+
input.onProgress?.({
|
|
19401
|
+
id: `${input.job.id}:actions:${Date.now()}`,
|
|
19402
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19403
|
+
phase: "job",
|
|
19404
|
+
status: "running",
|
|
19405
|
+
jobId: input.job.id,
|
|
19406
|
+
title: newActions.length === 1 ? "Action observed" : "Actions observed",
|
|
19407
|
+
message: (newActions.length ? newActions : actionSummary).join("\n"),
|
|
19408
|
+
data: { actionSummary, newActions },
|
|
19409
|
+
...input.progressContext
|
|
19410
|
+
});
|
|
19411
|
+
}
|
|
19412
|
+
const agentMessages = getJobAgentMessages(liveDoc, input.job.id);
|
|
19413
|
+
const agentMessageKey = JSON.stringify(agentMessages);
|
|
19414
|
+
if (agentMessages.length && agentMessageKey !== lastAgentMessageKey) {
|
|
19415
|
+
const newMessages = agentMessages.slice(lastAgentMessageCount);
|
|
19416
|
+
lastAgentMessageCount = agentMessages.length;
|
|
19417
|
+
lastAgentMessageKey = agentMessageKey;
|
|
19418
|
+
const latestMessage = newMessages.at(-1) || agentMessages.at(-1);
|
|
19419
|
+
input.onProgress?.({
|
|
19420
|
+
id: `${input.job.id}:messages:${Date.now()}`,
|
|
19421
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19422
|
+
phase: "job",
|
|
19423
|
+
status: "running",
|
|
19424
|
+
jobId: input.job.id,
|
|
19425
|
+
title: "Agent message",
|
|
19426
|
+
message: readableAgentMessage(latestMessage),
|
|
19427
|
+
data: { agentMessages, newMessages },
|
|
19428
|
+
...input.progressContext
|
|
19429
|
+
});
|
|
19430
|
+
}
|
|
18746
19431
|
if (prompts.length > 0) {
|
|
19432
|
+
input.onProgress?.({
|
|
19433
|
+
id: `${input.job.id}:prompt:${prompts[0]?.id || Date.now()}`,
|
|
19434
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19435
|
+
phase: "prompt",
|
|
19436
|
+
status: "running",
|
|
19437
|
+
jobId: input.job.id,
|
|
19438
|
+
title: "Waiting for prompt answer",
|
|
19439
|
+
message: prompts[0]?.message || prompts[0]?.title,
|
|
19440
|
+
data: { prompts },
|
|
19441
|
+
...input.progressContext
|
|
19442
|
+
});
|
|
18747
19443
|
return { kind: "prompt", prompts, liveDoc, stdout, stderr };
|
|
18748
19444
|
}
|
|
18749
19445
|
try {
|
|
@@ -18752,6 +19448,17 @@ async function waitForJobOutcome(input) {
|
|
|
18752
19448
|
input.pollIntervalMs,
|
|
18753
19449
|
`job ${input.job.id} tick`
|
|
18754
19450
|
);
|
|
19451
|
+
input.onProgress?.({
|
|
19452
|
+
id: `${input.job.id}:completed:${Date.now()}`,
|
|
19453
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19454
|
+
phase: "job",
|
|
19455
|
+
status: "passed",
|
|
19456
|
+
jobId: input.job.id,
|
|
19457
|
+
title: "Job completed",
|
|
19458
|
+
message: JSON.stringify(result)?.slice(0, 800),
|
|
19459
|
+
data: { result, stdout, stderr },
|
|
19460
|
+
...input.progressContext
|
|
19461
|
+
});
|
|
18755
19462
|
return { kind: "completed", result, liveDoc, stdout, stderr };
|
|
18756
19463
|
} catch (error) {
|
|
18757
19464
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -18983,6 +19690,10 @@ function buildSessionLogReport(input) {
|
|
|
18983
19690
|
`- Environment id: \`${conversation.environment.environmentId}\``,
|
|
18984
19691
|
`- Sandbox id: \`${conversation.environment.sandboxId}\``,
|
|
18985
19692
|
`- Status: ${result?.status || (error ? "failed" : "unknown")}`,
|
|
19693
|
+
...systemPrompts[0]?.iteration.templateId ? [
|
|
19694
|
+
`- Harness template: \`${systemPrompts[0].iteration.templateId}@${systemPrompts[0].iteration.templateVersion || "unknown"}\``,
|
|
19695
|
+
`- Template hash: \`${systemPrompts[0].iteration.templateHash || "unknown"}\``
|
|
19696
|
+
] : [],
|
|
18986
19697
|
...result?.error || error ? [`- Error: ${result?.error || error}`] : [],
|
|
18987
19698
|
"",
|
|
18988
19699
|
"## Conversation"
|
|
@@ -19090,6 +19801,12 @@ function buildSessionLogReport(input) {
|
|
|
19090
19801
|
lines.push(
|
|
19091
19802
|
`### Turn ${turn.turnNumber}, Generation ${iteration.iteration}`,
|
|
19092
19803
|
"",
|
|
19804
|
+
...iteration.templateId ? [
|
|
19805
|
+
`- Template: \`${iteration.templateId}@${iteration.templateVersion || "unknown"}\``,
|
|
19806
|
+
`- Template hash: \`${iteration.templateHash || "unknown"}\``,
|
|
19807
|
+
`- Prompt hash: \`${iteration.promptInstanceHash || "unknown"}\``,
|
|
19808
|
+
""
|
|
19809
|
+
] : [],
|
|
19093
19810
|
fenced(iteration.systemPrompt, "text"),
|
|
19094
19811
|
""
|
|
19095
19812
|
);
|
|
@@ -19131,9 +19848,167 @@ function isTransientEvalError(error) {
|
|
|
19131
19848
|
const message = error instanceof Error ? error.message : String(error);
|
|
19132
19849
|
return /socket connection was closed unexpectedly/i.test(message) || /timed out after/i.test(message) || /ECONNRESET/i.test(message) || /network/i.test(message) || /429/.test(message);
|
|
19133
19850
|
}
|
|
19851
|
+
function assertionPassed(id, run) {
|
|
19852
|
+
try {
|
|
19853
|
+
run(id);
|
|
19854
|
+
return { id, label: id, status: "passed" };
|
|
19855
|
+
} catch (error) {
|
|
19856
|
+
return {
|
|
19857
|
+
id,
|
|
19858
|
+
label: id,
|
|
19859
|
+
status: "failed",
|
|
19860
|
+
message: error instanceof Error ? error.message : String(error)
|
|
19861
|
+
};
|
|
19862
|
+
}
|
|
19863
|
+
}
|
|
19864
|
+
function hasMatchers(matchers) {
|
|
19865
|
+
return Boolean(matchers?.length);
|
|
19866
|
+
}
|
|
19867
|
+
function evaluateExpectationAssertions(input) {
|
|
19868
|
+
const expect = input.expect;
|
|
19869
|
+
if (!expect) return [];
|
|
19870
|
+
const prefix = `${input.scenarioId} step ${input.stepIndex + 1}`;
|
|
19871
|
+
const assertions = [];
|
|
19872
|
+
const actionText = input.completed.actionSummary.join("\n");
|
|
19873
|
+
const codeText = input.completed.finalCode || "";
|
|
19874
|
+
const displaySurface = [
|
|
19875
|
+
input.completed.responseText,
|
|
19876
|
+
actionText,
|
|
19877
|
+
codeText,
|
|
19878
|
+
JSON.stringify(input.completed.result)
|
|
19879
|
+
].join("\n");
|
|
19880
|
+
const promptSurface = input.completed.promptInteractions.map(
|
|
19881
|
+
(interaction) => [interaction.type, interaction.title, interaction.message].join(" ")
|
|
19882
|
+
).join("\n");
|
|
19883
|
+
if (hasMatchers(expect.replyIncludes) || hasMatchers(expect.replyExcludes)) {
|
|
19884
|
+
assertions.push(
|
|
19885
|
+
assertionPassed(
|
|
19886
|
+
"reply",
|
|
19887
|
+
() => assertMatches(
|
|
19888
|
+
`Reply for ${prefix}`,
|
|
19889
|
+
input.completed.responseText,
|
|
19890
|
+
expect.replyIncludes,
|
|
19891
|
+
expect.replyExcludes
|
|
19892
|
+
)
|
|
19893
|
+
)
|
|
19894
|
+
);
|
|
19895
|
+
}
|
|
19896
|
+
if (hasMatchers(expect.actionIncludes) || hasMatchers(expect.actionExcludes)) {
|
|
19897
|
+
assertions.push(
|
|
19898
|
+
assertionPassed(
|
|
19899
|
+
"actions",
|
|
19900
|
+
() => assertMatches(
|
|
19901
|
+
`Action summary for ${prefix}`,
|
|
19902
|
+
actionText,
|
|
19903
|
+
expect.actionIncludes,
|
|
19904
|
+
expect.actionExcludes
|
|
19905
|
+
)
|
|
19906
|
+
)
|
|
19907
|
+
);
|
|
19908
|
+
}
|
|
19909
|
+
if (hasMatchers(expect.codeIncludes) || hasMatchers(expect.codeExcludes)) {
|
|
19910
|
+
assertions.push(
|
|
19911
|
+
assertionPassed(
|
|
19912
|
+
"code",
|
|
19913
|
+
() => assertMatches(
|
|
19914
|
+
`Generated code for ${prefix}`,
|
|
19915
|
+
codeText,
|
|
19916
|
+
expect.codeIncludes,
|
|
19917
|
+
expect.codeExcludes
|
|
19918
|
+
)
|
|
19919
|
+
)
|
|
19920
|
+
);
|
|
19921
|
+
}
|
|
19922
|
+
if (hasMatchers(expect.actions?.required) || hasMatchers(expect.actions?.forbidden)) {
|
|
19923
|
+
assertions.push(
|
|
19924
|
+
assertionPassed(
|
|
19925
|
+
"required-actions",
|
|
19926
|
+
() => assertMatches(
|
|
19927
|
+
`Required actions for ${prefix}`,
|
|
19928
|
+
actionText,
|
|
19929
|
+
expect.actions?.required,
|
|
19930
|
+
expect.actions?.forbidden
|
|
19931
|
+
)
|
|
19932
|
+
)
|
|
19933
|
+
);
|
|
19934
|
+
}
|
|
19935
|
+
if (hasMatchers(expect.presentation?.mustMention) || hasMatchers(expect.presentation?.mustNotMention)) {
|
|
19936
|
+
assertions.push(
|
|
19937
|
+
assertionPassed(
|
|
19938
|
+
"presentation",
|
|
19939
|
+
() => assertMatches(
|
|
19940
|
+
`Presentation for ${prefix}`,
|
|
19941
|
+
input.completed.responseText,
|
|
19942
|
+
expect.presentation?.mustMention,
|
|
19943
|
+
expect.presentation?.mustNotMention
|
|
19944
|
+
)
|
|
19945
|
+
)
|
|
19946
|
+
);
|
|
19947
|
+
}
|
|
19948
|
+
if (hasMatchers(expect.presentation?.mustDisplayOrSave)) {
|
|
19949
|
+
assertions.push(
|
|
19950
|
+
assertionPassed(
|
|
19951
|
+
"display",
|
|
19952
|
+
() => assertMatches(
|
|
19953
|
+
`Displayed or saved records for ${prefix}`,
|
|
19954
|
+
displaySurface,
|
|
19955
|
+
expect.presentation?.mustDisplayOrSave
|
|
19956
|
+
)
|
|
19957
|
+
)
|
|
19958
|
+
);
|
|
19959
|
+
}
|
|
19960
|
+
if (expect.prompts?.requiredChoiceWhenAmbiguous) {
|
|
19961
|
+
assertions.push(
|
|
19962
|
+
assertionPassed("choice", () => {
|
|
19963
|
+
if (!input.completed.promptInteractions.some(
|
|
19964
|
+
(interaction) => interaction.type === "choice"
|
|
19965
|
+
)) {
|
|
19966
|
+
throw new Error(`Expected ${prefix} to use a choice prompt.`);
|
|
19967
|
+
}
|
|
19968
|
+
})
|
|
19969
|
+
);
|
|
19970
|
+
}
|
|
19971
|
+
for (const forbiddenType of expect.prompts?.forbiddenPromptTypes || []) {
|
|
19972
|
+
assertions.push(
|
|
19973
|
+
assertionPassed(`forbidden-prompt:${forbiddenType}`, () => {
|
|
19974
|
+
if (input.completed.promptInteractions.some(
|
|
19975
|
+
(interaction) => interaction.type === forbiddenType
|
|
19976
|
+
)) {
|
|
19977
|
+
throw new Error(
|
|
19978
|
+
`Prompt interactions for ${prefix} used forbidden prompt type ${forbiddenType}.`
|
|
19979
|
+
);
|
|
19980
|
+
}
|
|
19981
|
+
})
|
|
19982
|
+
);
|
|
19983
|
+
}
|
|
19984
|
+
if (expect.prompts?.requiredConfirmationBefore?.length) {
|
|
19985
|
+
assertions.push(
|
|
19986
|
+
assertionPassed(
|
|
19987
|
+
"confirmation",
|
|
19988
|
+
() => assertMatches(
|
|
19989
|
+
`Confirmation prompts for ${prefix}`,
|
|
19990
|
+
[actionText, promptSurface].join("\n"),
|
|
19991
|
+
expect.prompts?.requiredConfirmationBefore
|
|
19992
|
+
)
|
|
19993
|
+
)
|
|
19994
|
+
);
|
|
19995
|
+
}
|
|
19996
|
+
return assertions;
|
|
19997
|
+
}
|
|
19134
19998
|
async function runAgentEvalSuite(options) {
|
|
19135
19999
|
const results = [];
|
|
19136
20000
|
for (const scenario of options.scenarios) {
|
|
20001
|
+
await options.harness.emitProgress?.({
|
|
20002
|
+
phase: "scenario",
|
|
20003
|
+
status: "running",
|
|
20004
|
+
scenarioId: scenario.id,
|
|
20005
|
+
title: "Scenario started",
|
|
20006
|
+
message: scenario.description || scenario.request || scenario.id,
|
|
20007
|
+
data: {
|
|
20008
|
+
scenarioId: scenario.id,
|
|
20009
|
+
behaviorBuckets: scenario.behaviorBuckets
|
|
20010
|
+
}
|
|
20011
|
+
});
|
|
19137
20012
|
let attempt = 0;
|
|
19138
20013
|
let finalResult = null;
|
|
19139
20014
|
while (attempt < 2 && !finalResult) {
|
|
@@ -19204,27 +20079,38 @@ async function runAgentEvalSuite(options) {
|
|
|
19204
20079
|
},
|
|
19205
20080
|
assertMatches
|
|
19206
20081
|
};
|
|
19207
|
-
|
|
19208
|
-
|
|
19209
|
-
|
|
19210
|
-
|
|
19211
|
-
|
|
19212
|
-
|
|
19213
|
-
|
|
19214
|
-
|
|
19215
|
-
|
|
19216
|
-
|
|
19217
|
-
|
|
19218
|
-
step.
|
|
19219
|
-
|
|
19220
|
-
|
|
19221
|
-
|
|
19222
|
-
|
|
19223
|
-
|
|
19224
|
-
|
|
19225
|
-
)
|
|
20082
|
+
const assertions = evaluateExpectationAssertions({
|
|
20083
|
+
scenarioId: scenario.id,
|
|
20084
|
+
stepIndex: index,
|
|
20085
|
+
expect: step.expect,
|
|
20086
|
+
completed
|
|
20087
|
+
});
|
|
20088
|
+
for (const assertion of assertions) {
|
|
20089
|
+
await options.harness.emitProgress?.({
|
|
20090
|
+
phase: "assertion",
|
|
20091
|
+
status: assertion.status,
|
|
20092
|
+
scenarioId: scenario.id,
|
|
20093
|
+
stepId: step.id || `step-${index + 1}`,
|
|
20094
|
+
title: assertion.label,
|
|
20095
|
+
message: assertion.message,
|
|
20096
|
+
data: assertion
|
|
20097
|
+
});
|
|
20098
|
+
}
|
|
20099
|
+
const failedAssertion = assertions.find(
|
|
20100
|
+
(assertion) => assertion.status === "failed"
|
|
20101
|
+
);
|
|
20102
|
+
if (failedAssertion) {
|
|
20103
|
+
throw new Error(failedAssertion.message || failedAssertion.label);
|
|
19226
20104
|
}
|
|
19227
20105
|
for (const inspection of stepInspections) {
|
|
20106
|
+
await options.harness.emitProgress?.({
|
|
20107
|
+
phase: "inspection",
|
|
20108
|
+
status: "running",
|
|
20109
|
+
scenarioId: scenario.id,
|
|
20110
|
+
stepId: step.id || `step-${index + 1}`,
|
|
20111
|
+
title: "Running step inspection",
|
|
20112
|
+
message: inspection.code.slice(0, 500)
|
|
20113
|
+
});
|
|
19228
20114
|
const inspectionResult = await context.inspect(inspection.code);
|
|
19229
20115
|
const inspectionText = JSON.stringify(inspectionResult, null, 2);
|
|
19230
20116
|
assertMatches(
|
|
@@ -19240,9 +20126,32 @@ async function runAgentEvalSuite(options) {
|
|
|
19240
20126
|
});
|
|
19241
20127
|
}
|
|
19242
20128
|
inspectionResults.push(inspectionResult);
|
|
20129
|
+
await options.harness.emitProgress?.({
|
|
20130
|
+
phase: "inspection",
|
|
20131
|
+
status: "passed",
|
|
20132
|
+
scenarioId: scenario.id,
|
|
20133
|
+
stepId: step.id || `step-${index + 1}`,
|
|
20134
|
+
title: "Step inspection passed",
|
|
20135
|
+
message: inspectionText.slice(0, 800),
|
|
20136
|
+
data: inspectionResult
|
|
20137
|
+
});
|
|
19243
20138
|
}
|
|
19244
20139
|
for (const check of stepChecks) {
|
|
20140
|
+
await options.harness.emitProgress?.({
|
|
20141
|
+
phase: "check",
|
|
20142
|
+
status: "running",
|
|
20143
|
+
scenarioId: scenario.id,
|
|
20144
|
+
stepId: step.id || `step-${index + 1}`,
|
|
20145
|
+
title: "Running custom check"
|
|
20146
|
+
});
|
|
19245
20147
|
await check(context);
|
|
20148
|
+
await options.harness.emitProgress?.({
|
|
20149
|
+
phase: "check",
|
|
20150
|
+
status: "passed",
|
|
20151
|
+
scenarioId: scenario.id,
|
|
20152
|
+
stepId: step.id || `step-${index + 1}`,
|
|
20153
|
+
title: "Custom check passed"
|
|
20154
|
+
});
|
|
19246
20155
|
}
|
|
19247
20156
|
stepResults.push({
|
|
19248
20157
|
id: step.id || `step-${index + 1}`,
|
|
@@ -19253,6 +20162,7 @@ async function runAgentEvalSuite(options) {
|
|
|
19253
20162
|
actionSummary: completed.actionSummary,
|
|
19254
20163
|
promptInteractions: completed.promptInteractions,
|
|
19255
20164
|
inspectionResults,
|
|
20165
|
+
assertions,
|
|
19256
20166
|
turnDir: completed.turnDir
|
|
19257
20167
|
});
|
|
19258
20168
|
}
|
|
@@ -19271,6 +20181,7 @@ async function runAgentEvalSuite(options) {
|
|
|
19271
20181
|
actionSummary: lastStep.actionSummary,
|
|
19272
20182
|
promptInteractions: lastStep.promptInteractions,
|
|
19273
20183
|
verification: lastStep.inspectionResults.length <= 1 ? lastStep.inspectionResults[0] ?? null : lastStep.inspectionResults,
|
|
20184
|
+
assertions: stepResults.flatMap((step) => step.assertions || []),
|
|
19274
20185
|
tokenUsage: aggregateConversationTokenUsage(conversation),
|
|
19275
20186
|
steps: stepResults,
|
|
19276
20187
|
turnDir: conversation.artifactDir
|
|
@@ -19292,6 +20203,14 @@ async function runAgentEvalSuite(options) {
|
|
|
19292
20203
|
conversation,
|
|
19293
20204
|
result
|
|
19294
20205
|
});
|
|
20206
|
+
await options.harness.emitProgress?.({
|
|
20207
|
+
phase: "scenario",
|
|
20208
|
+
status: "passed",
|
|
20209
|
+
scenarioId: scenario.id,
|
|
20210
|
+
title: "Scenario passed",
|
|
20211
|
+
message: `${result.assertions?.filter((assertion) => assertion.status === "passed").length || 0}/${result.assertions?.length || 0} assertions`,
|
|
20212
|
+
data: result
|
|
20213
|
+
});
|
|
19295
20214
|
finalResult = result;
|
|
19296
20215
|
} catch (error) {
|
|
19297
20216
|
const failureMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -19332,6 +20251,14 @@ async function runAgentEvalSuite(options) {
|
|
|
19332
20251
|
result: failed,
|
|
19333
20252
|
error: failureMessage
|
|
19334
20253
|
});
|
|
20254
|
+
await options.harness.emitProgress?.({
|
|
20255
|
+
phase: "scenario",
|
|
20256
|
+
status: "failed",
|
|
20257
|
+
scenarioId: scenario.id,
|
|
20258
|
+
title: "Scenario failed",
|
|
20259
|
+
message: failureMessage,
|
|
20260
|
+
data: failed
|
|
20261
|
+
});
|
|
19335
20262
|
finalResult = failed;
|
|
19336
20263
|
} finally {
|
|
19337
20264
|
await options.harness.closeConversation(conversation);
|
|
@@ -19380,6 +20307,11 @@ function createAgentEvalHarness(options) {
|
|
|
19380
20307
|
const chatTimeoutMs = options.chatTimeoutMs ?? 12e4;
|
|
19381
20308
|
const jobTimeoutMs = options.jobTimeoutMs ?? 9e4;
|
|
19382
20309
|
const pollIntervalMs = options.pollIntervalMs ?? 250;
|
|
20310
|
+
const resolvedTemplate = resolveHarnessTemplate(
|
|
20311
|
+
options.harnessTemplateId || process.env.GRANULAR_AGENT_HARNESS_TEMPLATE || "stable");
|
|
20312
|
+
const promptRenderer = options.promptRenderer || resolvedTemplate.renderPrompt;
|
|
20313
|
+
const continuationRenderer = options.continuationRenderer || resolvedTemplate.renderContinuation;
|
|
20314
|
+
const onProgress = options.onProgress;
|
|
19383
20315
|
async function openConversation(label) {
|
|
19384
20316
|
await ensureDir(artifactDir);
|
|
19385
20317
|
const clientId = `${slugify(label)}-${Date.now()}`;
|
|
@@ -19448,6 +20380,13 @@ function createAgentEvalHarness(options) {
|
|
|
19448
20380
|
};
|
|
19449
20381
|
}
|
|
19450
20382
|
async function runInspection(conversation, inspection, completed, turnDir) {
|
|
20383
|
+
await emitProgress(onProgress, {
|
|
20384
|
+
phase: "inspection",
|
|
20385
|
+
status: "running",
|
|
20386
|
+
scenarioId: conversation.label,
|
|
20387
|
+
title: "Running inspection",
|
|
20388
|
+
message: inspection.code.slice(0, 500)
|
|
20389
|
+
});
|
|
19451
20390
|
let result = null;
|
|
19452
20391
|
let lastError = null;
|
|
19453
20392
|
for (let attempt = 0; attempt < 10; attempt += 1) {
|
|
@@ -19475,6 +20414,14 @@ function createAgentEvalHarness(options) {
|
|
|
19475
20414
|
});
|
|
19476
20415
|
}
|
|
19477
20416
|
await writeJson(path.join(turnDir, "verification.json"), result);
|
|
20417
|
+
await emitProgress(onProgress, {
|
|
20418
|
+
phase: "inspection",
|
|
20419
|
+
status: "passed",
|
|
20420
|
+
scenarioId: conversation.label,
|
|
20421
|
+
title: "Inspection passed",
|
|
20422
|
+
message: JSON.stringify(result)?.slice(0, 800),
|
|
20423
|
+
data: result
|
|
20424
|
+
});
|
|
19478
20425
|
return result;
|
|
19479
20426
|
}
|
|
19480
20427
|
async function resumePendingTurn(pending, responder) {
|
|
@@ -19484,6 +20431,16 @@ function createAgentEvalHarness(options) {
|
|
|
19484
20431
|
prompt,
|
|
19485
20432
|
history: pending.promptInteractions
|
|
19486
20433
|
});
|
|
20434
|
+
await emitProgress(onProgress, {
|
|
20435
|
+
phase: "interaction",
|
|
20436
|
+
status: "running",
|
|
20437
|
+
scenarioId: pending.conversation.label,
|
|
20438
|
+
stepId: path.basename(pending.turnDir),
|
|
20439
|
+
jobId: pending.job.id,
|
|
20440
|
+
title: "Prompt answered",
|
|
20441
|
+
message: `${prompt.type}: ${prompt.message || prompt.title} -> ${JSON.stringify(answer)}`,
|
|
20442
|
+
data: { prompt, answer }
|
|
20443
|
+
});
|
|
19487
20444
|
const session = pending.conversation.environment;
|
|
19488
20445
|
await session.answerPrompt(prompt.id, answer);
|
|
19489
20446
|
pending.promptInteractions.push({
|
|
@@ -19503,7 +20460,12 @@ function createAgentEvalHarness(options) {
|
|
|
19503
20460
|
job: pending.job,
|
|
19504
20461
|
boundaryTimestamp: pending.boundaryTimestamp,
|
|
19505
20462
|
timeoutMs: jobTimeoutMs,
|
|
19506
|
-
pollIntervalMs
|
|
20463
|
+
pollIntervalMs,
|
|
20464
|
+
onProgress: (event) => void onProgress?.(event),
|
|
20465
|
+
progressContext: {
|
|
20466
|
+
scenarioId: pending.conversation.label,
|
|
20467
|
+
stepId: path.basename(pending.turnDir)
|
|
20468
|
+
}
|
|
19507
20469
|
});
|
|
19508
20470
|
if (resumed.kind === "prompt") {
|
|
19509
20471
|
return {
|
|
@@ -19584,12 +20546,44 @@ function createAgentEvalHarness(options) {
|
|
|
19584
20546
|
};
|
|
19585
20547
|
conversation.logTurns.push(turnLog);
|
|
19586
20548
|
if (input.prepareRecords?.length) {
|
|
20549
|
+
await emitProgress(onProgress, {
|
|
20550
|
+
phase: "setup",
|
|
20551
|
+
status: "running",
|
|
20552
|
+
scenarioId: conversation.label,
|
|
20553
|
+
stepId: turnId,
|
|
20554
|
+
title: "Recording setup records",
|
|
20555
|
+
message: `${input.prepareRecords.length} records`,
|
|
20556
|
+
data: input.prepareRecords
|
|
20557
|
+
});
|
|
19587
20558
|
await conversation.environment.recordObjects(input.prepareRecords);
|
|
20559
|
+
await emitProgress(onProgress, {
|
|
20560
|
+
phase: "setup",
|
|
20561
|
+
status: "passed",
|
|
20562
|
+
scenarioId: conversation.label,
|
|
20563
|
+
stepId: turnId,
|
|
20564
|
+
title: "Setup records recorded",
|
|
20565
|
+
message: `${input.prepareRecords.length} records`
|
|
20566
|
+
});
|
|
19588
20567
|
}
|
|
19589
20568
|
if (input.prepareTools?.length) {
|
|
20569
|
+
await emitProgress(onProgress, {
|
|
20570
|
+
phase: "setup",
|
|
20571
|
+
status: "running",
|
|
20572
|
+
scenarioId: conversation.label,
|
|
20573
|
+
stepId: turnId,
|
|
20574
|
+
title: "Registering effect handlers",
|
|
20575
|
+
message: `${input.prepareTools.length} handlers`
|
|
20576
|
+
});
|
|
19590
20577
|
await options.granular.ontology(conversation.environment.sandboxId).effects.registerMany(input.prepareTools);
|
|
19591
20578
|
}
|
|
19592
20579
|
if (input.prepare) {
|
|
20580
|
+
await emitProgress(onProgress, {
|
|
20581
|
+
phase: "setup",
|
|
20582
|
+
status: "running",
|
|
20583
|
+
scenarioId: conversation.label,
|
|
20584
|
+
stepId: turnId,
|
|
20585
|
+
title: "Running custom setup"
|
|
20586
|
+
});
|
|
19593
20587
|
await input.prepare({
|
|
19594
20588
|
conversation,
|
|
19595
20589
|
environment: conversation.environment,
|
|
@@ -19598,6 +20592,14 @@ function createAgentEvalHarness(options) {
|
|
|
19598
20592
|
}
|
|
19599
20593
|
const boundaryTimestamp = Date.now();
|
|
19600
20594
|
conversation.history.push({ role: "user", content: input.request });
|
|
20595
|
+
await emitProgress(onProgress, {
|
|
20596
|
+
phase: "step",
|
|
20597
|
+
status: "running",
|
|
20598
|
+
scenarioId: conversation.label,
|
|
20599
|
+
stepId: turnId,
|
|
20600
|
+
title: "User request",
|
|
20601
|
+
message: input.request
|
|
20602
|
+
});
|
|
19601
20603
|
await writeJson(path.join(turnDir, "request.json"), {
|
|
19602
20604
|
request: input.request,
|
|
19603
20605
|
boundaryTimestamp
|
|
@@ -19639,7 +20641,7 @@ function createAgentEvalHarness(options) {
|
|
|
19639
20641
|
inputSchema: tool.inputSchema,
|
|
19640
20642
|
outputSchema: tool.outputSchema
|
|
19641
20643
|
}));
|
|
19642
|
-
const
|
|
20644
|
+
const renderedPrompt = promptRenderer({
|
|
19643
20645
|
domainDocumentation: await conversation.environment.getDomainDocumentation(),
|
|
19644
20646
|
sessionContext: {
|
|
19645
20647
|
sandboxId: conversation.environment.sandboxId,
|
|
@@ -19660,9 +20662,39 @@ function createAgentEvalHarness(options) {
|
|
|
19660
20662
|
tools,
|
|
19661
20663
|
checkpoint: latestCheckpoint
|
|
19662
20664
|
});
|
|
19663
|
-
const
|
|
20665
|
+
const systemPrompt = renderedPrompt.prompt;
|
|
20666
|
+
await emitProgress(onProgress, {
|
|
20667
|
+
phase: "prompt",
|
|
20668
|
+
status: "passed",
|
|
20669
|
+
scenarioId: conversation.label,
|
|
20670
|
+
stepId: turnId,
|
|
20671
|
+
iteration: iteration + 1,
|
|
20672
|
+
templateId: renderedPrompt.templateId,
|
|
20673
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
20674
|
+
title: "Rendered harness prompt",
|
|
20675
|
+
message: `${systemPrompt.split("\n").length} lines`,
|
|
20676
|
+
data: {
|
|
20677
|
+
templateId: renderedPrompt.templateId,
|
|
20678
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
20679
|
+
templateHash: renderedPrompt.templateHash,
|
|
20680
|
+
promptInstanceHash: renderedPrompt.promptInstanceHash,
|
|
20681
|
+
prompt: systemPrompt
|
|
20682
|
+
}
|
|
20683
|
+
});
|
|
20684
|
+
const request = iteration === 0 ? input.request : continuationRenderer(
|
|
19664
20685
|
buildContinuationPreview(latestCheckpoint, noProgressCount)
|
|
19665
|
-
);
|
|
20686
|
+
).instruction;
|
|
20687
|
+
await emitProgress(onProgress, {
|
|
20688
|
+
phase: "generation",
|
|
20689
|
+
status: "running",
|
|
20690
|
+
scenarioId: conversation.label,
|
|
20691
|
+
stepId: turnId,
|
|
20692
|
+
iteration: iteration + 1,
|
|
20693
|
+
templateId: renderedPrompt.templateId,
|
|
20694
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
20695
|
+
title: iteration === 0 ? "Generating agent response" : "Generating continuation",
|
|
20696
|
+
message: request
|
|
20697
|
+
});
|
|
19666
20698
|
const generation = await withTimeout2(
|
|
19667
20699
|
generateTurnWithRepair(options.generator, {
|
|
19668
20700
|
systemPrompt,
|
|
@@ -19681,10 +20713,31 @@ function createAgentEvalHarness(options) {
|
|
|
19681
20713
|
chatTimeoutMs,
|
|
19682
20714
|
`chat generation for ${conversation.label} iteration ${iteration + 1}`
|
|
19683
20715
|
);
|
|
20716
|
+
await emitProgress(onProgress, {
|
|
20717
|
+
phase: "generation",
|
|
20718
|
+
status: "passed",
|
|
20719
|
+
scenarioId: conversation.label,
|
|
20720
|
+
stepId: turnId,
|
|
20721
|
+
iteration: iteration + 1,
|
|
20722
|
+
templateId: renderedPrompt.templateId,
|
|
20723
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
20724
|
+
title: generation.code ? "Generated job code" : "Generated text reply",
|
|
20725
|
+
message: generation.code || generation.reply || "",
|
|
20726
|
+
data: {
|
|
20727
|
+
reply: generation.reply,
|
|
20728
|
+
code: generation.code,
|
|
20729
|
+
attempts: generation.generationAttempts,
|
|
20730
|
+
usage: tokenUsageForGenerationOutput(generation)
|
|
20731
|
+
}
|
|
20732
|
+
});
|
|
19684
20733
|
const iterationLog = {
|
|
19685
20734
|
iteration: iteration + 1,
|
|
19686
20735
|
request,
|
|
19687
20736
|
systemPrompt,
|
|
20737
|
+
templateId: renderedPrompt.templateId,
|
|
20738
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
20739
|
+
templateHash: renderedPrompt.templateHash,
|
|
20740
|
+
promptInstanceHash: renderedPrompt.promptInstanceHash,
|
|
19688
20741
|
generationReply: generation.reply,
|
|
19689
20742
|
generatedCode: generation.code,
|
|
19690
20743
|
rawGeneration: generation.raw,
|
|
@@ -19731,6 +20784,15 @@ function createAgentEvalHarness(options) {
|
|
|
19731
20784
|
result: completed.result
|
|
19732
20785
|
};
|
|
19733
20786
|
await writeJson(path.join(turnDir, "result.json"), completed);
|
|
20787
|
+
await emitProgress(onProgress, {
|
|
20788
|
+
phase: "step",
|
|
20789
|
+
status: "passed",
|
|
20790
|
+
scenarioId: conversation.label,
|
|
20791
|
+
stepId: turnId,
|
|
20792
|
+
title: "Step completed with text reply",
|
|
20793
|
+
message: responseText2,
|
|
20794
|
+
data: completed
|
|
20795
|
+
});
|
|
19734
20796
|
return completed;
|
|
19735
20797
|
}
|
|
19736
20798
|
const session = conversation.environment;
|
|
@@ -19751,12 +20813,33 @@ function createAgentEvalHarness(options) {
|
|
|
19751
20813
|
)
|
|
19752
20814
|
}
|
|
19753
20815
|
});
|
|
20816
|
+
await emitProgress(onProgress, {
|
|
20817
|
+
phase: "job",
|
|
20818
|
+
status: "running",
|
|
20819
|
+
scenarioId: conversation.label,
|
|
20820
|
+
stepId: turnId,
|
|
20821
|
+
iteration: iteration + 1,
|
|
20822
|
+
jobId: job.id,
|
|
20823
|
+
templateId: renderedPrompt.templateId,
|
|
20824
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
20825
|
+
title: "Submitted Granular job",
|
|
20826
|
+
message: job.id,
|
|
20827
|
+
data: { code: generation.code }
|
|
20828
|
+
});
|
|
19754
20829
|
const outcome = await waitForJobOutcome({
|
|
19755
20830
|
environment: conversation.environment,
|
|
19756
20831
|
job,
|
|
19757
20832
|
boundaryTimestamp,
|
|
19758
20833
|
timeoutMs: jobTimeoutMs,
|
|
19759
|
-
pollIntervalMs
|
|
20834
|
+
pollIntervalMs,
|
|
20835
|
+
onProgress: (event) => void onProgress?.(event),
|
|
20836
|
+
progressContext: {
|
|
20837
|
+
scenarioId: conversation.label,
|
|
20838
|
+
stepId: turnId,
|
|
20839
|
+
iteration: iteration + 1,
|
|
20840
|
+
templateId: renderedPrompt.templateId,
|
|
20841
|
+
templateVersion: renderedPrompt.templateVersion
|
|
20842
|
+
}
|
|
19760
20843
|
});
|
|
19761
20844
|
if (outcome.kind === "prompt") {
|
|
19762
20845
|
if (!autoAnswerPrompts) {
|
|
@@ -19866,6 +20949,23 @@ function createAgentEvalHarness(options) {
|
|
|
19866
20949
|
controllerReason: continuation.reason,
|
|
19867
20950
|
noProgressCount: continuation.nextNoProgressCount
|
|
19868
20951
|
};
|
|
20952
|
+
await emitProgress(onProgress, {
|
|
20953
|
+
phase: "continuation",
|
|
20954
|
+
status: continuation.shouldContinue ? "running" : "passed",
|
|
20955
|
+
scenarioId: conversation.label,
|
|
20956
|
+
stepId: turnId,
|
|
20957
|
+
iteration: iteration + 1,
|
|
20958
|
+
jobId: job.id,
|
|
20959
|
+
templateId: renderedPrompt.templateId,
|
|
20960
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
20961
|
+
title: continuation.shouldContinue ? "Harness requested another loop" : "Harness accepted completion",
|
|
20962
|
+
message: `${continuation.reason}; ${continuation.outcome}`,
|
|
20963
|
+
data: {
|
|
20964
|
+
continuation,
|
|
20965
|
+
checkpoint: latestCheckpoint,
|
|
20966
|
+
verifierSnapshot
|
|
20967
|
+
}
|
|
20968
|
+
});
|
|
19869
20969
|
previousSnapshot = verifierSnapshot;
|
|
19870
20970
|
noProgressCount = continuation.nextNoProgressCount;
|
|
19871
20971
|
conversation.history.push({
|
|
@@ -19919,6 +21019,17 @@ function createAgentEvalHarness(options) {
|
|
|
19919
21019
|
result: outcome.result
|
|
19920
21020
|
};
|
|
19921
21021
|
await writeJson(path.join(turnDir, "result.json"), completed);
|
|
21022
|
+
await emitProgress(onProgress, {
|
|
21023
|
+
phase: "step",
|
|
21024
|
+
status: "passed",
|
|
21025
|
+
scenarioId: conversation.label,
|
|
21026
|
+
stepId: turnId,
|
|
21027
|
+
iteration: iteration + 1,
|
|
21028
|
+
jobId: job.id,
|
|
21029
|
+
title: "Step completed",
|
|
21030
|
+
message: responseText,
|
|
21031
|
+
data: completed
|
|
21032
|
+
});
|
|
19922
21033
|
return completed;
|
|
19923
21034
|
}
|
|
19924
21035
|
iteration += 1;
|
|
@@ -19930,6 +21041,7 @@ function createAgentEvalHarness(options) {
|
|
|
19930
21041
|
return {
|
|
19931
21042
|
artifactDir,
|
|
19932
21043
|
granular: options.granular,
|
|
21044
|
+
emitProgress: (event) => emitProgress(onProgress, event),
|
|
19933
21045
|
openConversation,
|
|
19934
21046
|
closeConversation,
|
|
19935
21047
|
runTurn,
|
|
@@ -19995,7 +21107,11 @@ function createAgentTester(options) {
|
|
|
19995
21107
|
controllerBudgets: options.controllerBudgets,
|
|
19996
21108
|
chatTimeoutMs: options.chatTimeoutMs,
|
|
19997
21109
|
jobTimeoutMs: options.jobTimeoutMs,
|
|
19998
|
-
pollIntervalMs: options.pollIntervalMs
|
|
21110
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
21111
|
+
harnessTemplateId: options.harnessTemplateId,
|
|
21112
|
+
promptRenderer: options.promptRenderer,
|
|
21113
|
+
continuationRenderer: options.continuationRenderer,
|
|
21114
|
+
onProgress: options.onProgress
|
|
19999
21115
|
});
|
|
20000
21116
|
return {
|
|
20001
21117
|
...harness,
|
|
@@ -20021,6 +21137,6 @@ var createHumanResponder = createScriptedPromptResponder;
|
|
|
20021
21137
|
var createOpenAIGenerator = createOpenAIChatTurnGenerator;
|
|
20022
21138
|
var createTestArtifactsDirectory = createTimestampedArtifactDirectory;
|
|
20023
21139
|
|
|
20024
|
-
export { createAgentEvalHarness, createAgentTester, createHumanResponder, createOpenAIChatTurnGenerator, createOpenAIGenerator, createScriptedPromptResponder, createTestArtifactsDirectory, createTimestampedArtifactDirectory, generateTurnWithRepair, runAgentEvalSuite, runAgentTests };
|
|
21140
|
+
export { createAgentEvalHarness, createAgentTester, createHumanResponder, createOpenAIChatTurnGenerator, createOpenAIGenerator, createScriptedPromptResponder, createTestArtifactsDirectory, createTimestampedArtifactDirectory, generateTurnWithRepair, loadAgentEvalScenarioFile, runAgentEvalSuite, runAgentTests, scenariosFromAgentEvalFile };
|
|
20025
21141
|
//# sourceMappingURL=agent-evals.mjs.map
|
|
20026
21142
|
//# sourceMappingURL=agent-evals.mjs.map
|