@theokit/sdk 3.2.2 → 3.2.3

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/eval.js CHANGED
@@ -5156,12 +5156,23 @@ var init_objective_coerce = __esm({
5156
5156
  // src/internal/persistence/pagination.ts
5157
5157
  function paginate(items, opts) {
5158
5158
  if (opts === void 0 || opts.offset === void 0 && opts.limit === void 0) return items;
5159
- const start = Math.max(0, opts.offset ?? 0);
5160
- const end = opts.limit === void 0 ? items.length : start + Math.max(0, opts.limit);
5159
+ const start = opts.offset === void 0 ? 0 : requireNonNegativeInt(opts.offset, "offset");
5160
+ const limit = opts.limit === void 0 ? void 0 : requireNonNegativeInt(opts.limit, "limit");
5161
+ const end = limit === void 0 ? items.length : start + limit;
5161
5162
  return items.slice(start, end);
5162
5163
  }
5164
+ function requireNonNegativeInt(value, field) {
5165
+ if (!Number.isInteger(value) || value < 0) {
5166
+ throw new ConfigurationError(
5167
+ `Invalid pagination ${field}: expected a non-negative integer, got ${value}`,
5168
+ { code: "pagination_invalid" }
5169
+ );
5170
+ }
5171
+ return value;
5172
+ }
5163
5173
  var init_pagination = __esm({
5164
5174
  "src/internal/persistence/pagination.ts"() {
5175
+ init_errors();
5165
5176
  }
5166
5177
  });
5167
5178
 
@@ -10319,6 +10330,8 @@ function parseRetryAfter(headers) {
10319
10330
  if (raw === null) return void 0;
10320
10331
  const n = Number(raw);
10321
10332
  if (Number.isFinite(n) && n >= 0) return Math.ceil(n);
10333
+ const dateMs = Date.parse(raw);
10334
+ if (Number.isFinite(dateMs)) return Math.max(0, Math.ceil((dateMs - Date.now()) / 1e3));
10322
10335
  return void 0;
10323
10336
  }
10324
10337
  function truncateRaw(body) {
@@ -10639,6 +10652,7 @@ function buildAnthropicBody(request) {
10639
10652
  var AnthropicClient, AnthropicStreamAccumulator;
10640
10653
  var init_anthropic3 = __esm({
10641
10654
  "src/internal/llm/anthropic.ts"() {
10655
+ init_errors();
10642
10656
  init_anthropic2();
10643
10657
  init_anthropic_shared();
10644
10658
  init_finish();
@@ -10692,12 +10706,23 @@ var init_anthropic3 = __esm({
10692
10706
  const events = accumulator.consume(parsed);
10693
10707
  for (const event of events) yield event;
10694
10708
  }
10709
+ if (!accumulator.finishReasonSeen) {
10710
+ throw new NetworkError("Anthropic SSE stream truncated (no stop_reason)", {
10711
+ code: "stream_truncated"
10712
+ });
10713
+ }
10695
10714
  return accumulator.finish();
10696
10715
  }
10697
10716
  };
10698
10717
  AnthropicStreamAccumulator = class {
10699
10718
  text = "";
10700
10719
  stopReason = "end_turn";
10720
+ /**
10721
+ * M2 #61 — whether a `message_delta` carrying a real `stop_reason` was seen.
10722
+ * A stream that closes before it is a truncation (server FIN / proxy hiccup),
10723
+ * not a clean `end_turn` — the caller throws `stream_truncated` on `false`.
10724
+ */
10725
+ sawStopReason = false;
10701
10726
  inputTokens;
10702
10727
  outputTokens;
10703
10728
  cacheReadTokens;
@@ -10744,6 +10769,9 @@ var init_anthropic3 = __esm({
10744
10769
  * spinning the SSE parser.
10745
10770
  */
10746
10771
  handleMessageDelta(md) {
10772
+ if (md.delta.stop_reason !== void 0 && md.delta.stop_reason !== null) {
10773
+ this.sawStopReason = true;
10774
+ }
10747
10775
  this.stopReason = mapAnthropicStopReason(md.delta.stop_reason);
10748
10776
  if (md.usage?.input_tokens !== void 0) this.inputTokens = md.usage.input_tokens;
10749
10777
  if (md.usage?.output_tokens !== void 0) this.outputTokens = md.usage.output_tokens;
@@ -10754,6 +10782,10 @@ var init_anthropic3 = __esm({
10754
10782
  this.cacheReadTokens = md.usage.cache_read_input_tokens;
10755
10783
  }
10756
10784
  }
10785
+ /** M2 #61 — whether the terminal `message_delta` (stop_reason) was seen. */
10786
+ get finishReasonSeen() {
10787
+ return this.sawStopReason;
10788
+ }
10757
10789
  finish() {
10758
10790
  const toolCalls = [];
10759
10791
  for (const [index, tool] of this.toolCalls.entries()) {
@@ -12987,7 +13019,6 @@ var init_client = __esm({
12987
13019
  // concurrent request so parallel tool dispatch after a drop awaits one handshake
12988
13020
  // instead of racing (or spuriously failing with mcp_not_init).
12989
13021
  dropped = false;
12990
- reconnectAttempts = 0;
12991
13022
  reconnectPromise;
12992
13023
  get timeoutMs() {
12993
13024
  return this.config.requestTimeoutMs ?? DEFAULT_MCP_TIMEOUT_MS;
@@ -13040,15 +13071,22 @@ var init_client = __esm({
13040
13071
  return this.reconnectPromise;
13041
13072
  }
13042
13073
  async reconnect() {
13043
- if (this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
13044
- throw new NetworkError(`MCP ${this.name} reconnect exhausted`, { code: "mcp_disconnected" });
13074
+ let lastErr;
13075
+ for (let attempt = 0; attempt < MAX_RECONNECT_ATTEMPTS; attempt += 1) {
13076
+ await reconnectDelay(attempt);
13077
+ this.spawnChild();
13078
+ try {
13079
+ await super.initialize();
13080
+ this.dropped = false;
13081
+ return;
13082
+ } catch (err) {
13083
+ lastErr = err;
13084
+ }
13045
13085
  }
13046
- await reconnectDelay(this.reconnectAttempts);
13047
- this.reconnectAttempts += 1;
13048
- this.spawnChild();
13049
- await super.initialize();
13050
- this.dropped = false;
13051
- this.reconnectAttempts = 0;
13086
+ throw new NetworkError(`MCP ${this.name} reconnect exhausted`, {
13087
+ code: "mcp_disconnected",
13088
+ ...lastErr instanceof Error ? { cause: lastErr } : {}
13089
+ });
13052
13090
  }
13053
13091
  async close() {
13054
13092
  this.rejectAllPending(new NetworkError(`MCP ${this.name} closed`, { code: "mcp_closed" }));