@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.cjs CHANGED
@@ -5159,12 +5159,23 @@ var init_objective_coerce = __esm({
5159
5159
  // src/internal/persistence/pagination.ts
5160
5160
  function paginate(items, opts) {
5161
5161
  if (opts === void 0 || opts.offset === void 0 && opts.limit === void 0) return items;
5162
- const start = Math.max(0, opts.offset ?? 0);
5163
- const end = opts.limit === void 0 ? items.length : start + Math.max(0, opts.limit);
5162
+ const start = opts.offset === void 0 ? 0 : requireNonNegativeInt(opts.offset, "offset");
5163
+ const limit = opts.limit === void 0 ? void 0 : requireNonNegativeInt(opts.limit, "limit");
5164
+ const end = limit === void 0 ? items.length : start + limit;
5164
5165
  return items.slice(start, end);
5165
5166
  }
5167
+ function requireNonNegativeInt(value, field) {
5168
+ if (!Number.isInteger(value) || value < 0) {
5169
+ throw new ConfigurationError(
5170
+ `Invalid pagination ${field}: expected a non-negative integer, got ${value}`,
5171
+ { code: "pagination_invalid" }
5172
+ );
5173
+ }
5174
+ return value;
5175
+ }
5166
5176
  var init_pagination = __esm({
5167
5177
  "src/internal/persistence/pagination.ts"() {
5178
+ init_errors();
5168
5179
  }
5169
5180
  });
5170
5181
 
@@ -10322,6 +10333,8 @@ function parseRetryAfter(headers) {
10322
10333
  if (raw === null) return void 0;
10323
10334
  const n = Number(raw);
10324
10335
  if (Number.isFinite(n) && n >= 0) return Math.ceil(n);
10336
+ const dateMs = Date.parse(raw);
10337
+ if (Number.isFinite(dateMs)) return Math.max(0, Math.ceil((dateMs - Date.now()) / 1e3));
10325
10338
  return void 0;
10326
10339
  }
10327
10340
  function truncateRaw(body) {
@@ -10642,6 +10655,7 @@ function buildAnthropicBody(request) {
10642
10655
  var AnthropicClient, AnthropicStreamAccumulator;
10643
10656
  var init_anthropic3 = __esm({
10644
10657
  "src/internal/llm/anthropic.ts"() {
10658
+ init_errors();
10645
10659
  init_anthropic2();
10646
10660
  init_anthropic_shared();
10647
10661
  init_finish();
@@ -10695,12 +10709,23 @@ var init_anthropic3 = __esm({
10695
10709
  const events = accumulator.consume(parsed);
10696
10710
  for (const event of events) yield event;
10697
10711
  }
10712
+ if (!accumulator.finishReasonSeen) {
10713
+ throw new NetworkError("Anthropic SSE stream truncated (no stop_reason)", {
10714
+ code: "stream_truncated"
10715
+ });
10716
+ }
10698
10717
  return accumulator.finish();
10699
10718
  }
10700
10719
  };
10701
10720
  AnthropicStreamAccumulator = class {
10702
10721
  text = "";
10703
10722
  stopReason = "end_turn";
10723
+ /**
10724
+ * M2 #61 — whether a `message_delta` carrying a real `stop_reason` was seen.
10725
+ * A stream that closes before it is a truncation (server FIN / proxy hiccup),
10726
+ * not a clean `end_turn` — the caller throws `stream_truncated` on `false`.
10727
+ */
10728
+ sawStopReason = false;
10704
10729
  inputTokens;
10705
10730
  outputTokens;
10706
10731
  cacheReadTokens;
@@ -10747,6 +10772,9 @@ var init_anthropic3 = __esm({
10747
10772
  * spinning the SSE parser.
10748
10773
  */
10749
10774
  handleMessageDelta(md) {
10775
+ if (md.delta.stop_reason !== void 0 && md.delta.stop_reason !== null) {
10776
+ this.sawStopReason = true;
10777
+ }
10750
10778
  this.stopReason = mapAnthropicStopReason(md.delta.stop_reason);
10751
10779
  if (md.usage?.input_tokens !== void 0) this.inputTokens = md.usage.input_tokens;
10752
10780
  if (md.usage?.output_tokens !== void 0) this.outputTokens = md.usage.output_tokens;
@@ -10757,6 +10785,10 @@ var init_anthropic3 = __esm({
10757
10785
  this.cacheReadTokens = md.usage.cache_read_input_tokens;
10758
10786
  }
10759
10787
  }
10788
+ /** M2 #61 — whether the terminal `message_delta` (stop_reason) was seen. */
10789
+ get finishReasonSeen() {
10790
+ return this.sawStopReason;
10791
+ }
10760
10792
  finish() {
10761
10793
  const toolCalls = [];
10762
10794
  for (const [index, tool] of this.toolCalls.entries()) {
@@ -12990,7 +13022,6 @@ var init_client = __esm({
12990
13022
  // concurrent request so parallel tool dispatch after a drop awaits one handshake
12991
13023
  // instead of racing (or spuriously failing with mcp_not_init).
12992
13024
  dropped = false;
12993
- reconnectAttempts = 0;
12994
13025
  reconnectPromise;
12995
13026
  get timeoutMs() {
12996
13027
  return this.config.requestTimeoutMs ?? DEFAULT_MCP_TIMEOUT_MS;
@@ -13043,15 +13074,22 @@ var init_client = __esm({
13043
13074
  return this.reconnectPromise;
13044
13075
  }
13045
13076
  async reconnect() {
13046
- if (this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
13047
- throw new NetworkError(`MCP ${this.name} reconnect exhausted`, { code: "mcp_disconnected" });
13077
+ let lastErr;
13078
+ for (let attempt = 0; attempt < MAX_RECONNECT_ATTEMPTS; attempt += 1) {
13079
+ await reconnectDelay(attempt);
13080
+ this.spawnChild();
13081
+ try {
13082
+ await super.initialize();
13083
+ this.dropped = false;
13084
+ return;
13085
+ } catch (err) {
13086
+ lastErr = err;
13087
+ }
13048
13088
  }
13049
- await reconnectDelay(this.reconnectAttempts);
13050
- this.reconnectAttempts += 1;
13051
- this.spawnChild();
13052
- await super.initialize();
13053
- this.dropped = false;
13054
- this.reconnectAttempts = 0;
13089
+ throw new NetworkError(`MCP ${this.name} reconnect exhausted`, {
13090
+ code: "mcp_disconnected",
13091
+ ...lastErr instanceof Error ? { cause: lastErr } : {}
13092
+ });
13055
13093
  }
13056
13094
  async close() {
13057
13095
  this.rejectAllPending(new NetworkError(`MCP ${this.name} closed`, { code: "mcp_closed" }));