@apo-ai/sdk 0.9.3 → 0.9.4

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.
@@ -560,8 +560,19 @@ function parseJudgeJson(raw) {
560
560
  reasoning: "Judge response could not be parsed as JSON \u2014 the verdict is unknown, so this check is treated as a failure. The model's raw response is available in the judge metadata."
561
561
  };
562
562
  }
563
- var JUDGE_TIMEOUT_MS = 3e5;
564
563
  var JUDGE_IDLE_TIMEOUT_MS = 9e4;
564
+ function envMs(name, fallback) {
565
+ const raw = process.env[name]?.trim();
566
+ if (!raw) return fallback;
567
+ const ms = Number(raw);
568
+ return Number.isFinite(ms) && ms > 0 ? ms : fallback;
569
+ }
570
+ function judgeFirstDataTimeoutMs() {
571
+ return envMs("APO_JUDGE_TIMEOUT_MS", 3e5);
572
+ }
573
+ function judgeMaxDurationMs() {
574
+ return envMs("APO_JUDGE_MAX_DURATION_MS", 12e5);
575
+ }
565
576
  var JUDGE_RETRY_DELAY_MS = 1e3;
566
577
  var JUDGE_RETRY_AFTER_CAP_MS = 2e4;
567
578
  var JUDGE_MIN_RETRY_BUDGET_MS = 6e4;
@@ -736,16 +747,29 @@ ${instructionText}`,
736
747
  response_format: { type: "json_object" },
737
748
  ...stream ? { stream: true, stream_options: { include_usage: true } } : {}
738
749
  });
739
- const attempt = async (stream, deadline) => {
750
+ const attempt = async (stream, maxDeadline) => {
740
751
  const controller = new AbortController();
741
752
  const expire = (reason, name) => () => controller.abort(new DOMException(reason, name));
742
- const total = setTimeout(
743
- expire(`no complete response within ${JUDGE_TIMEOUT_MS / 1e3}s`, "TimeoutError"),
744
- Math.max(deadline - Date.now(), 0)
753
+ const firstDataMs = judgeFirstDataTimeoutMs();
754
+ const runaway = setTimeout(
755
+ expire(
756
+ `still streaming after ${Math.round(judgeMaxDurationMs() / 1e3)}s (APO_JUDGE_MAX_DURATION_MS)`,
757
+ "TimeoutError"
758
+ ),
759
+ Math.max(maxDeadline - Date.now(), 0)
760
+ );
761
+ let waiting = setTimeout(
762
+ expire(
763
+ `no data within ${Math.round(firstDataMs / 1e3)}s (APO_JUDGE_TIMEOUT_MS)`,
764
+ "FirstDataTimeoutError"
765
+ ),
766
+ firstDataMs
745
767
  );
746
768
  const stalled = expire(`no data for ${JUDGE_IDLE_TIMEOUT_MS / 1e3}s`, "IdleTimeoutError");
747
769
  let idle;
748
770
  const onData = () => {
771
+ clearTimeout(waiting);
772
+ waiting = void 0;
749
773
  clearTimeout(idle);
750
774
  idle = setTimeout(stalled, JUDGE_IDLE_TIMEOUT_MS);
751
775
  };
@@ -782,7 +806,8 @@ ${instructionText}`,
782
806
  return transportFailure("Judge response failed", controller.signal.reason ?? error);
783
807
  }
784
808
  } finally {
785
- clearTimeout(total);
809
+ clearTimeout(runaway);
810
+ clearTimeout(waiting);
786
811
  clearTimeout(idle);
787
812
  controller.abort();
788
813
  }
@@ -802,7 +827,7 @@ ${instructionText}`,
802
827
  };
803
828
  return runWithSharedPrefix(cacheKey, async () => {
804
829
  const startedAt = Date.now();
805
- const deadline = startedAt + JUDGE_TIMEOUT_MS;
830
+ const deadline = startedAt + judgeMaxDurationMs();
806
831
  let stream = true;
807
832
  let result = await attempt(stream, deadline);
808
833
  const truncated = result.kind === "completion" && isTruncated(result.completion);