@apo-ai/sdk 0.12.0 → 0.14.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.
@@ -1307,6 +1307,13 @@ type JudgeConfig = {
1307
1307
  * dual behavior (second judge as parallel, evidence-only shadow).
1308
1308
  */
1309
1309
  mode?: "cascade";
1310
+ /**
1311
+ * Sampling temperature for `t.judge` requests (not `t.agent`, whose session
1312
+ * stays at 0). Unset falls back to `APO_JUDGE_TEMPERATURE`, then `0`. Some
1313
+ * reasoning models recommend a non-zero value (DeepSeek: 0.6) to avoid
1314
+ * repetition at greedy decoding. Recorded on the check's judge metadata.
1315
+ */
1316
+ temperature?: number;
1310
1317
  };
1311
1318
  /**
1312
1319
  * What a check knows about its scope when it invokes the judge — the
@@ -1193,7 +1193,13 @@ async function readCompletion(response, onData, guards) {
1193
1193
  dispatch();
1194
1194
  return { text, usage, finishReason };
1195
1195
  }
1196
- var prefixQueues = /* @__PURE__ */ new Map();
1196
+ var prefixLanes = /* @__PURE__ */ new Map();
1197
+ function judgeConcurrency() {
1198
+ const raw = process.env.APO_JUDGE_CONCURRENCY?.trim();
1199
+ if (!raw) return 1;
1200
+ const n = Number(raw);
1201
+ return Number.isInteger(n) && n >= 1 ? n : 1;
1202
+ }
1197
1203
  function promptCacheKey(prefix) {
1198
1204
  return `apo-${createHash("sha256").update(prefix).digest("hex").slice(0, 32)}`;
1199
1205
  }
@@ -1225,16 +1231,46 @@ async function fetchWithPromptCacheKey(input, init) {
1225
1231
  return retry;
1226
1232
  }
1227
1233
  function runWithSharedPrefix(key, task2) {
1228
- const prev = prefixQueues.get(key) ?? Promise.resolve();
1229
- const next = prev.then(task2, task2);
1230
- prefixQueues.set(
1231
- key,
1232
- next.then(
1233
- () => void 0,
1234
- () => void 0
1235
- )
1236
- );
1237
- return next;
1234
+ const existing = prefixLanes.get(key);
1235
+ if (!existing) {
1236
+ const warmer = task2();
1237
+ prefixLanes.set(key, {
1238
+ warmed: warmer.then(
1239
+ () => void 0,
1240
+ () => void 0
1241
+ ),
1242
+ active: 0,
1243
+ waiting: []
1244
+ });
1245
+ return warmer;
1246
+ }
1247
+ const lane = existing;
1248
+ const acquire = () => new Promise((resolve5) => {
1249
+ if (lane.active < judgeConcurrency()) {
1250
+ lane.active += 1;
1251
+ resolve5();
1252
+ } else {
1253
+ lane.waiting.push(() => {
1254
+ lane.active += 1;
1255
+ resolve5();
1256
+ });
1257
+ }
1258
+ });
1259
+ const release = () => {
1260
+ lane.active -= 1;
1261
+ lane.waiting.shift()?.();
1262
+ };
1263
+ return lane.warmed.then(acquire).then(() => task2().finally(release));
1264
+ }
1265
+ function judgeTemperature(configured) {
1266
+ const raw = process.env.APO_JUDGE_TEMPERATURE?.trim();
1267
+ const fromEnv = raw ? Number(raw) : void 0;
1268
+ const value = configured ?? fromEnv ?? 0;
1269
+ if (!Number.isFinite(value) || value < 0 || value > 2) {
1270
+ const source = configured !== void 0 ? "judge.temperature" : "APO_JUDGE_TEMPERATURE";
1271
+ throw new Error(`${source} must be a number between 0 and 2, got ${configured ?? raw}`);
1272
+ }
1273
+ return value;
1238
1274
  }
1239
1275
  function defaultJudgeBaseURL(baseURL) {
1240
1276
  return baseURL ?? process.env.OPENROUTER_BASE_URL ?? "https://openrouter.ai/api/v1";
@@ -1245,6 +1281,7 @@ function defaultJudgeAPIKey(apiKey) {
1245
1281
  async function callJudge(args) {
1246
1282
  const baseURL = defaultJudgeBaseURL(args.baseURL);
1247
1283
  const apiKey = defaultJudgeAPIKey(args.apiKey);
1284
+ const temperature = judgeTemperature(args.temperature);
1248
1285
  const { briefingText, instructionText, systemPromptText, deliverableText, secondJudgeState, secondJudgeProjected } = buildJudgePromptParts({
1249
1286
  values: args.values,
1250
1287
  instruction: args.instruction,
@@ -1278,7 +1315,7 @@ async function callJudge(args) {
1278
1315
  },
1279
1316
  { role: "user", content: instructionText }
1280
1317
  ],
1281
- temperature: 0,
1318
+ temperature,
1282
1319
  response_format: schema ? judgeResponseFormat() : JSON_OBJECT_FORMAT,
1283
1320
  ...stream ? { stream: true, stream_options: { include_usage: true } } : {}
1284
1321
  });
@@ -1401,6 +1438,7 @@ async function callJudge(args) {
1401
1438
  }
1402
1439
  const judgeMetadata = async (completion) => ({
1403
1440
  model: args.model,
1441
+ temperature,
1404
1442
  contract: judgeContractInUse(),
1405
1443
  prompt: { system: systemPromptText, user: instructionText },
1406
1444
  ...completion ? { response: completion.text, tokens: parseJudgeUsage(completion.usage) } : {},
@@ -2515,7 +2553,8 @@ function resolveJudgeConfig(judgeConfig, override) {
2515
2553
  baseURL: override?.baseURL ?? judgeConfig?.baseURL,
2516
2554
  apiKey: override?.apiKey ?? judgeConfig?.apiKey,
2517
2555
  prompt: override?.prompt ?? judgeConfig?.prompt,
2518
- mode: override?.mode ?? judgeConfig?.mode
2556
+ mode: override?.mode ?? judgeConfig?.mode,
2557
+ temperature: override?.temperature ?? judgeConfig?.temperature
2519
2558
  };
2520
2559
  }
2521
2560
  var TEST_METHOD_NAMES = [
@@ -2624,6 +2663,18 @@ function createJudgeMethod(rec, judgeConfig, judgeScope, judgeTracer) {
2624
2663
  );
2625
2664
  return;
2626
2665
  }
2666
+ try {
2667
+ judgeTemperature(effective.temperature);
2668
+ } catch (error) {
2669
+ rec.record(label, false, `judge failed: ${error instanceof Error ? error.message : String(error)}`, {
2670
+ evaluator_type: "llm",
2671
+ expected: instruction,
2672
+ received: valueArray.length === 1 ? valueArray[0] : valueArray,
2673
+ location,
2674
+ outcome: "error"
2675
+ });
2676
+ return;
2677
+ }
2627
2678
  const context2 = judgeScopeToContext(judgeScope);
2628
2679
  const judgeServing = servingHostFromBaseURL(effective.baseURL);
2629
2680
  const secondJudgeValue = opts?.secondJudgeValue;
@@ -2680,6 +2731,7 @@ function createJudgeMethod(rec, judgeConfig, judgeScope, judgeTracer) {
2680
2731
  baseURL: effective.baseURL,
2681
2732
  apiKey: effective.apiKey,
2682
2733
  prompt: effective.prompt,
2734
+ ...effective.temperature !== void 0 ? { temperature: effective.temperature } : {},
2683
2735
  ...context2 ? { context: context2 } : {},
2684
2736
  ...prefetchedSecondJudge ? { prefetchedSecondJudge } : {},
2685
2737
  ...secondJudgeValue !== void 0 ? {