@apo-ai/sdk 0.3.0 → 0.5.0
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/README.md +11 -0
- package/dist/agent-task/integrations/ai-sdk.d.ts +1 -1
- package/dist/agent-task/integrations/anthropic.d.ts +1 -1
- package/dist/agent-task/integrations/openai.d.ts +1 -1
- package/dist/agent-task/public.d.ts +258 -196
- package/dist/agent-task/public.js +142 -61
- package/dist/agent-task/public.js.map +1 -1
- package/dist/{tracing-BE53Q8Ru.d.ts → tracing-D5Yhzq8e.d.ts} +1 -1
- package/package.json +1 -1
|
@@ -235,7 +235,8 @@ function levenshtein(a, b) {
|
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
// src/agent-task/checks/judge.ts
|
|
238
|
-
var
|
|
238
|
+
var JUDGE_RESPONSE_CONTRACT = 'Respond with ONLY a JSON object: {"pass": true/false, "reasoning": "your reasoning"}';
|
|
239
|
+
var JUDGE_SYSTEM_PROMPT = `You are an evaluation judge. Evaluate the given value(s) against the instruction. ${JUDGE_RESPONSE_CONTRACT}`;
|
|
239
240
|
function formatValue(value, depth = 0) {
|
|
240
241
|
const indent = " ".repeat(depth);
|
|
241
242
|
if (value === null || value === void 0) return String(value);
|
|
@@ -314,12 +315,11 @@ async function callJudge(args) {
|
|
|
314
315
|
const apiKey = args.apiKey ?? process.env.OPENROUTER_API_KEY ?? process.env.OPENAI_API_KEY;
|
|
315
316
|
const deliverableText = `Values to evaluate:
|
|
316
317
|
${formatJudgeValues(args.values)}`;
|
|
317
|
-
const instructionText =
|
|
318
|
-
|
|
319
|
-
const systemPromptText = `${JUDGE_SYSTEM_PROMPT}
|
|
318
|
+
const { briefingText, instructionText } = assembleBriefing(args);
|
|
319
|
+
const systemPromptText = `${briefingText}
|
|
320
320
|
|
|
321
321
|
${deliverableText}`;
|
|
322
|
-
const cacheKey = `${args.model}\0${deliverableText}`;
|
|
322
|
+
const cacheKey = `${args.model}\0${briefingText}\0${deliverableText}`;
|
|
323
323
|
return runWithSharedPrefix(cacheKey, async () => {
|
|
324
324
|
const startedAt = Date.now();
|
|
325
325
|
const response = await fetch(`${baseURL}/chat/completions`, {
|
|
@@ -334,7 +334,7 @@ ${deliverableText}`;
|
|
|
334
334
|
{
|
|
335
335
|
role: "system",
|
|
336
336
|
content: [
|
|
337
|
-
{ type: "text", text:
|
|
337
|
+
{ type: "text", text: briefingText },
|
|
338
338
|
{
|
|
339
339
|
type: "text",
|
|
340
340
|
text: deliverableText,
|
|
@@ -384,6 +384,33 @@ ${deliverableText}`;
|
|
|
384
384
|
};
|
|
385
385
|
});
|
|
386
386
|
}
|
|
387
|
+
function assembleBriefing(args) {
|
|
388
|
+
if (!args.prompt) {
|
|
389
|
+
return {
|
|
390
|
+
briefingText: JUDGE_SYSTEM_PROMPT,
|
|
391
|
+
instructionText: `Instruction:
|
|
392
|
+
${args.instruction}`
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
const ctx = {
|
|
396
|
+
taskId: args.context?.taskId ?? "",
|
|
397
|
+
checkName: args.context?.checkName ?? "",
|
|
398
|
+
...args.context?.taskDescription !== void 0 ? { taskDescription: args.context.taskDescription } : {},
|
|
399
|
+
...args.context?.deliverableNames !== void 0 && args.context.deliverableNames.length > 0 ? { deliverableNames: args.context.deliverableNames } : {},
|
|
400
|
+
instruction: args.instruction
|
|
401
|
+
};
|
|
402
|
+
const built = args.prompt(ctx);
|
|
403
|
+
const system = built.system?.trim();
|
|
404
|
+
const user = built.user?.trim();
|
|
405
|
+
return {
|
|
406
|
+
// The SDK appends its own response contract to any custom briefing.
|
|
407
|
+
briefingText: system ? `${system}
|
|
408
|
+
|
|
409
|
+
${JUDGE_RESPONSE_CONTRACT}` : JUDGE_SYSTEM_PROMPT,
|
|
410
|
+
instructionText: user ?? `Instruction:
|
|
411
|
+
${args.instruction}`
|
|
412
|
+
};
|
|
413
|
+
}
|
|
387
414
|
|
|
388
415
|
// src/agent-task/checks/t.ts
|
|
389
416
|
function resolveJudgeConfig(judgeConfig, override) {
|
|
@@ -392,7 +419,8 @@ function resolveJudgeConfig(judgeConfig, override) {
|
|
|
392
419
|
return {
|
|
393
420
|
model,
|
|
394
421
|
baseURL: override?.baseURL ?? judgeConfig?.baseURL,
|
|
395
|
-
apiKey: override?.apiKey ?? judgeConfig?.apiKey
|
|
422
|
+
apiKey: override?.apiKey ?? judgeConfig?.apiKey,
|
|
423
|
+
prompt: override?.prompt ?? judgeConfig?.prompt
|
|
396
424
|
};
|
|
397
425
|
}
|
|
398
426
|
var TEST_METHOD_NAMES = [
|
|
@@ -421,6 +449,67 @@ function matchName(name, m) {
|
|
|
421
449
|
if (m instanceof RegExp) return m.test(name);
|
|
422
450
|
return m(name);
|
|
423
451
|
}
|
|
452
|
+
function createJudgeMethod(rec, judgeConfig, judgeScope) {
|
|
453
|
+
return async (values, instruction, opts) => {
|
|
454
|
+
const label = opts?.label ?? "judge";
|
|
455
|
+
const location = rec.captureLocation();
|
|
456
|
+
const valueArray = Array.isArray(values) ? values : [values];
|
|
457
|
+
const effective = resolveJudgeConfig(judgeConfig, opts?.judge);
|
|
458
|
+
if (!effective) {
|
|
459
|
+
rec.record(
|
|
460
|
+
label,
|
|
461
|
+
false,
|
|
462
|
+
"No judge model configured. Set one of:\n\u2022 OPENROUTER_MODEL + OPENROUTER_API_KEY (OpenRouter \u2014 works with 200+ models, one account)\n\u2022 OPENAI_MODEL + OPENAI_API_KEY (OpenAI direct)\nOr pass { judge } to runTask() programmatically.",
|
|
463
|
+
{ evaluator_type: "llm", location }
|
|
464
|
+
);
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
const context2 = judgeScopeToContext(judgeScope);
|
|
468
|
+
try {
|
|
469
|
+
const { pass, reasoning, judge } = await callJudge({
|
|
470
|
+
values: valueArray,
|
|
471
|
+
instruction,
|
|
472
|
+
model: effective.model,
|
|
473
|
+
baseURL: effective.baseURL,
|
|
474
|
+
apiKey: effective.apiKey,
|
|
475
|
+
prompt: effective.prompt,
|
|
476
|
+
...context2 ? { context: context2 } : {}
|
|
477
|
+
});
|
|
478
|
+
rec.record(label, pass, reasoning, {
|
|
479
|
+
evaluator_type: "llm",
|
|
480
|
+
judge,
|
|
481
|
+
expected: instruction,
|
|
482
|
+
// Store the raw evaluated value (not a truncated string) so the
|
|
483
|
+
// dashboard can render it with the right viewer — Markdown for
|
|
484
|
+
// prose, a JSON tree for structured objects.
|
|
485
|
+
received: valueArray.length === 1 ? valueArray[0] : valueArray,
|
|
486
|
+
location
|
|
487
|
+
});
|
|
488
|
+
} catch (error) {
|
|
489
|
+
rec.record(
|
|
490
|
+
label,
|
|
491
|
+
false,
|
|
492
|
+
`judge failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
493
|
+
{
|
|
494
|
+
evaluator_type: "llm",
|
|
495
|
+
expected: instruction,
|
|
496
|
+
received: valueArray.length === 1 ? valueArray[0] : valueArray,
|
|
497
|
+
location
|
|
498
|
+
}
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
function judgeScopeToContext(scope) {
|
|
504
|
+
if (!scope) return void 0;
|
|
505
|
+
const deliverableNames = scope.readDeliverableNames?.();
|
|
506
|
+
return {
|
|
507
|
+
taskId: scope.taskId,
|
|
508
|
+
checkName: scope.checkName,
|
|
509
|
+
...scope.taskDescription !== void 0 ? { taskDescription: scope.taskDescription } : {},
|
|
510
|
+
...deliverableNames && deliverableNames.length > 0 ? { deliverableNames } : {}
|
|
511
|
+
};
|
|
512
|
+
}
|
|
424
513
|
var CAPABILITY_LABELS = {
|
|
425
514
|
messages: "message",
|
|
426
515
|
tools: "tool",
|
|
@@ -429,7 +518,7 @@ var CAPABILITY_LABELS = {
|
|
|
429
518
|
skills: "skill",
|
|
430
519
|
subagents: "subagent"
|
|
431
520
|
};
|
|
432
|
-
function createTraceTestContext(view, rec, judgeConfig) {
|
|
521
|
+
function createTraceTestContext(view, rec, judgeConfig, judgeScope) {
|
|
433
522
|
const unsupported = (id, capability) => {
|
|
434
523
|
const label = CAPABILITY_LABELS[capability];
|
|
435
524
|
rec.record(id, false, `${label} evidence is unavailable in this trace projection`, {
|
|
@@ -613,49 +702,9 @@ function createTraceTestContext(view, rec, judgeConfig) {
|
|
|
613
702
|
{ expected: matcher.label, received: describeValue(value) }
|
|
614
703
|
);
|
|
615
704
|
},
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
const valueArray = Array.isArray(values) ? values : [values];
|
|
620
|
-
const effective = resolveJudgeConfig(judgeConfig, opts?.judge);
|
|
621
|
-
if (!effective) {
|
|
622
|
-
rec.record(
|
|
623
|
-
label,
|
|
624
|
-
false,
|
|
625
|
-
"No judge model configured. Set one of:\n\u2022 OPENROUTER_MODEL + OPENROUTER_API_KEY (OpenRouter \u2014 works with 200+ models, one account)\n\u2022 OPENAI_MODEL + OPENAI_API_KEY (OpenAI direct)\nOr pass { judge } to runTask() programmatically.",
|
|
626
|
-
{ evaluator_type: "llm", location }
|
|
627
|
-
);
|
|
628
|
-
return;
|
|
629
|
-
}
|
|
630
|
-
try {
|
|
631
|
-
const { pass, reasoning, judge } = await callJudge({
|
|
632
|
-
values: valueArray,
|
|
633
|
-
instruction,
|
|
634
|
-
model: effective.model,
|
|
635
|
-
baseURL: effective.baseURL,
|
|
636
|
-
apiKey: effective.apiKey
|
|
637
|
-
});
|
|
638
|
-
rec.record(label, pass, reasoning, {
|
|
639
|
-
evaluator_type: "llm",
|
|
640
|
-
judge,
|
|
641
|
-
expected: instruction,
|
|
642
|
-
received: valueArray.length === 1 ? valueArray[0] : valueArray,
|
|
643
|
-
location
|
|
644
|
-
});
|
|
645
|
-
} catch (error) {
|
|
646
|
-
rec.record(
|
|
647
|
-
label,
|
|
648
|
-
false,
|
|
649
|
-
`judge failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
650
|
-
{
|
|
651
|
-
evaluator_type: "llm",
|
|
652
|
-
expected: instruction,
|
|
653
|
-
received: valueArray.length === 1 ? valueArray[0] : valueArray,
|
|
654
|
-
location
|
|
655
|
-
}
|
|
656
|
-
);
|
|
657
|
-
}
|
|
658
|
-
}
|
|
705
|
+
// judge does not consult trace capabilities; the scope carries the
|
|
706
|
+
// task/check frame for prompt builders (#161).
|
|
707
|
+
judge: createJudgeMethod(rec, judgeConfig, judgeScope)
|
|
659
708
|
};
|
|
660
709
|
}
|
|
661
710
|
function matchesTraceToolCall(call, name, opts) {
|
|
@@ -787,14 +836,21 @@ function describe(id, nameOrFn, fn) {
|
|
|
787
836
|
async function runTraceChecks(args) {
|
|
788
837
|
const view = new TraceView(args.snapshot);
|
|
789
838
|
const locate = args.moduleUrl && args.displayFile ? (stack) => parseCheckLocation(stack, args.moduleUrl, args.displayFile) : void 0;
|
|
839
|
+
const taskMeta = readTaskMeta(args.task);
|
|
790
840
|
const results = await Promise.all(
|
|
791
841
|
registry.map(async (check) => {
|
|
792
842
|
const rec = new Recorder(locate);
|
|
793
|
-
const
|
|
843
|
+
const reads = trackDeliverableReads(args.deliverables);
|
|
844
|
+
const t = createTraceTestContext(view, rec, args.judgeConfig, {
|
|
845
|
+
taskId: taskMeta.id ?? "",
|
|
846
|
+
...taskMeta.description !== void 0 ? { taskDescription: taskMeta.description } : {},
|
|
847
|
+
checkName: check.id,
|
|
848
|
+
readDeliverableNames: reads.names
|
|
849
|
+
});
|
|
794
850
|
let thrownLocation;
|
|
795
851
|
try {
|
|
796
852
|
await check.fn(t, {
|
|
797
|
-
deliverables:
|
|
853
|
+
deliverables: reads.proxied,
|
|
798
854
|
files: args.files,
|
|
799
855
|
task: args.task
|
|
800
856
|
});
|
|
@@ -866,6 +922,26 @@ function proxyBrokenDeliverables(deliverables, brokenDeliverables) {
|
|
|
866
922
|
}
|
|
867
923
|
});
|
|
868
924
|
}
|
|
925
|
+
function readTaskMeta(task2) {
|
|
926
|
+
if (!task2 || typeof task2 !== "object") return {};
|
|
927
|
+
const record = task2;
|
|
928
|
+
return {
|
|
929
|
+
...typeof record.id === "string" ? { id: record.id } : {},
|
|
930
|
+
...typeof record.description === "string" ? { description: record.description } : {}
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
function trackDeliverableReads(deliverables) {
|
|
934
|
+
const read = /* @__PURE__ */ new Set();
|
|
935
|
+
const proxied = new Proxy(deliverables, {
|
|
936
|
+
get(target, property, receiver) {
|
|
937
|
+
if (typeof property === "string" && Object.prototype.hasOwnProperty.call(target, property)) {
|
|
938
|
+
read.add(property);
|
|
939
|
+
}
|
|
940
|
+
return Reflect.get(target, property, receiver);
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
return { proxied, names: () => [...read] };
|
|
944
|
+
}
|
|
869
945
|
|
|
870
946
|
// src/agent-task/task/defineTask.ts
|
|
871
947
|
var TASK_ADAPTER_SYMBOL = /* @__PURE__ */ Symbol.for("agent-task.adapter-definition");
|
|
@@ -1553,6 +1629,8 @@ function observationTypeFor(t) {
|
|
|
1553
1629
|
return "EMBEDDING";
|
|
1554
1630
|
case "GUARDRAIL":
|
|
1555
1631
|
return "GUARDRAIL";
|
|
1632
|
+
case "SKILL":
|
|
1633
|
+
return "SKILL";
|
|
1556
1634
|
default:
|
|
1557
1635
|
return "SPAN";
|
|
1558
1636
|
}
|
|
@@ -2076,6 +2154,7 @@ async function executeLoadedTask(loaded, options, rawTrace, traceRunId) {
|
|
|
2076
2154
|
summarize: (result2) => summarizeEvaluationResults(result2)
|
|
2077
2155
|
},
|
|
2078
2156
|
async () => {
|
|
2157
|
+
const judgeConfig = resolveJudgeConfig(options?.judge, task2.judge);
|
|
2079
2158
|
if (!inlineChecks) {
|
|
2080
2159
|
return loadAndRunFlowChecks(
|
|
2081
2160
|
checksPath,
|
|
@@ -2084,7 +2163,7 @@ async function executeLoadedTask(loaded, options, rawTrace, traceRunId) {
|
|
|
2084
2163
|
deliverables: collected,
|
|
2085
2164
|
files,
|
|
2086
2165
|
task: task2,
|
|
2087
|
-
judgeConfig:
|
|
2166
|
+
...judgeConfig ? { judgeConfig } : {}
|
|
2088
2167
|
},
|
|
2089
2168
|
validationResults.brokenDeliverables
|
|
2090
2169
|
);
|
|
@@ -2097,7 +2176,7 @@ async function executeLoadedTask(loaded, options, rawTrace, traceRunId) {
|
|
|
2097
2176
|
),
|
|
2098
2177
|
files,
|
|
2099
2178
|
task: task2,
|
|
2100
|
-
judgeConfig:
|
|
2179
|
+
...judgeConfig ? { judgeConfig } : {},
|
|
2101
2180
|
moduleUrl,
|
|
2102
2181
|
displayFile: evalFileName
|
|
2103
2182
|
});
|
|
@@ -2277,12 +2356,13 @@ async function evaluate(loaded, options, phase1) {
|
|
|
2277
2356
|
phase1.collected,
|
|
2278
2357
|
validationResults.brokenDeliverables
|
|
2279
2358
|
);
|
|
2359
|
+
const judgeConfig = resolveJudgeConfig(options?.judge, task2.judge);
|
|
2280
2360
|
const checksResults = await (inlineChecks ? runTraceChecks({
|
|
2281
2361
|
snapshot: phase1.snapshot,
|
|
2282
2362
|
deliverables,
|
|
2283
2363
|
files,
|
|
2284
2364
|
task: task2,
|
|
2285
|
-
judgeConfig:
|
|
2365
|
+
...judgeConfig ? { judgeConfig } : {},
|
|
2286
2366
|
moduleUrl,
|
|
2287
2367
|
displayFile: evalFileName
|
|
2288
2368
|
}) : loadAndRunFlowChecks(
|
|
@@ -2292,7 +2372,7 @@ async function evaluate(loaded, options, phase1) {
|
|
|
2292
2372
|
deliverables,
|
|
2293
2373
|
files,
|
|
2294
2374
|
task: task2,
|
|
2295
|
-
judgeConfig:
|
|
2375
|
+
...judgeConfig ? { judgeConfig } : {}
|
|
2296
2376
|
},
|
|
2297
2377
|
validationResults.brokenDeliverables
|
|
2298
2378
|
));
|
|
@@ -2449,9 +2529,10 @@ async function rejudgeTaskRun(runId, endpoints, options = {}) {
|
|
|
2449
2529
|
const proxied = proxyBrokenDeliverables(deliverables, validation.brokenDeliverables);
|
|
2450
2530
|
const passCounts = /* @__PURE__ */ new Map();
|
|
2451
2531
|
let primary = [];
|
|
2532
|
+
const judgeConfig = resolveJudgeConfig(options.judge, loaded.task.judge);
|
|
2452
2533
|
for (let sample = 0; sample < samples; sample++) {
|
|
2453
2534
|
if (samples > 1) progress(`judging sample ${sample + 1}/${samples}`);
|
|
2454
|
-
const results = await runChecksOnce(loaded, proxied, snapshot,
|
|
2535
|
+
const results = await runChecksOnce(loaded, proxied, snapshot, judgeConfig);
|
|
2455
2536
|
if (sample === 0) primary = results;
|
|
2456
2537
|
for (const result of results) {
|
|
2457
2538
|
passCounts.set(result.id, (passCounts.get(result.id) ?? 0) + (result.pass ? 1 : 0));
|
|
@@ -2468,9 +2549,9 @@ async function rejudgeTaskRun(runId, endpoints, options = {}) {
|
|
|
2468
2549
|
taskId: detail.task_id,
|
|
2469
2550
|
definitionRevisionId: revisionId,
|
|
2470
2551
|
definitionRevisionIsPinned: revisionIsPinned,
|
|
2471
|
-
judge:
|
|
2472
|
-
model:
|
|
2473
|
-
baseURL:
|
|
2552
|
+
judge: judgeConfig ? {
|
|
2553
|
+
model: judgeConfig.model,
|
|
2554
|
+
baseURL: judgeConfig.baseURL ?? process.env.OPENROUTER_BASE_URL
|
|
2474
2555
|
} : null,
|
|
2475
2556
|
samples,
|
|
2476
2557
|
checks: aggregate.checks,
|