@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/cron.cjs CHANGED
@@ -5163,12 +5163,23 @@ var init_objective_coerce = __esm({
5163
5163
  // src/internal/persistence/pagination.ts
5164
5164
  function paginate(items, opts) {
5165
5165
  if (opts === void 0 || opts.offset === void 0 && opts.limit === void 0) return items;
5166
- const start = Math.max(0, opts.offset ?? 0);
5167
- const end = opts.limit === void 0 ? items.length : start + Math.max(0, opts.limit);
5166
+ const start = opts.offset === void 0 ? 0 : requireNonNegativeInt(opts.offset, "offset");
5167
+ const limit = opts.limit === void 0 ? void 0 : requireNonNegativeInt(opts.limit, "limit");
5168
+ const end = limit === void 0 ? items.length : start + limit;
5168
5169
  return items.slice(start, end);
5169
5170
  }
5171
+ function requireNonNegativeInt(value, field) {
5172
+ if (!Number.isInteger(value) || value < 0) {
5173
+ throw new ConfigurationError(
5174
+ `Invalid pagination ${field}: expected a non-negative integer, got ${value}`,
5175
+ { code: "pagination_invalid" }
5176
+ );
5177
+ }
5178
+ return value;
5179
+ }
5170
5180
  var init_pagination = __esm({
5171
5181
  "src/internal/persistence/pagination.ts"() {
5182
+ init_errors();
5172
5183
  }
5173
5184
  });
5174
5185
 
@@ -10326,6 +10337,8 @@ function parseRetryAfter(headers) {
10326
10337
  if (raw === null) return void 0;
10327
10338
  const n = Number(raw);
10328
10339
  if (Number.isFinite(n) && n >= 0) return Math.ceil(n);
10340
+ const dateMs = Date.parse(raw);
10341
+ if (Number.isFinite(dateMs)) return Math.max(0, Math.ceil((dateMs - Date.now()) / 1e3));
10329
10342
  return void 0;
10330
10343
  }
10331
10344
  function truncateRaw(body) {
@@ -10646,6 +10659,7 @@ function buildAnthropicBody(request) {
10646
10659
  var AnthropicClient, AnthropicStreamAccumulator;
10647
10660
  var init_anthropic3 = __esm({
10648
10661
  "src/internal/llm/anthropic.ts"() {
10662
+ init_errors();
10649
10663
  init_anthropic2();
10650
10664
  init_anthropic_shared();
10651
10665
  init_finish();
@@ -10699,12 +10713,23 @@ var init_anthropic3 = __esm({
10699
10713
  const events = accumulator.consume(parsed);
10700
10714
  for (const event of events) yield event;
10701
10715
  }
10716
+ if (!accumulator.finishReasonSeen) {
10717
+ throw new NetworkError("Anthropic SSE stream truncated (no stop_reason)", {
10718
+ code: "stream_truncated"
10719
+ });
10720
+ }
10702
10721
  return accumulator.finish();
10703
10722
  }
10704
10723
  };
10705
10724
  AnthropicStreamAccumulator = class {
10706
10725
  text = "";
10707
10726
  stopReason = "end_turn";
10727
+ /**
10728
+ * M2 #61 — whether a `message_delta` carrying a real `stop_reason` was seen.
10729
+ * A stream that closes before it is a truncation (server FIN / proxy hiccup),
10730
+ * not a clean `end_turn` — the caller throws `stream_truncated` on `false`.
10731
+ */
10732
+ sawStopReason = false;
10708
10733
  inputTokens;
10709
10734
  outputTokens;
10710
10735
  cacheReadTokens;
@@ -10751,6 +10776,9 @@ var init_anthropic3 = __esm({
10751
10776
  * spinning the SSE parser.
10752
10777
  */
10753
10778
  handleMessageDelta(md) {
10779
+ if (md.delta.stop_reason !== void 0 && md.delta.stop_reason !== null) {
10780
+ this.sawStopReason = true;
10781
+ }
10754
10782
  this.stopReason = mapAnthropicStopReason(md.delta.stop_reason);
10755
10783
  if (md.usage?.input_tokens !== void 0) this.inputTokens = md.usage.input_tokens;
10756
10784
  if (md.usage?.output_tokens !== void 0) this.outputTokens = md.usage.output_tokens;
@@ -10761,6 +10789,10 @@ var init_anthropic3 = __esm({
10761
10789
  this.cacheReadTokens = md.usage.cache_read_input_tokens;
10762
10790
  }
10763
10791
  }
10792
+ /** M2 #61 — whether the terminal `message_delta` (stop_reason) was seen. */
10793
+ get finishReasonSeen() {
10794
+ return this.sawStopReason;
10795
+ }
10764
10796
  finish() {
10765
10797
  const toolCalls = [];
10766
10798
  for (const [index, tool] of this.toolCalls.entries()) {
@@ -12994,7 +13026,6 @@ var init_client = __esm({
12994
13026
  // concurrent request so parallel tool dispatch after a drop awaits one handshake
12995
13027
  // instead of racing (or spuriously failing with mcp_not_init).
12996
13028
  dropped = false;
12997
- reconnectAttempts = 0;
12998
13029
  reconnectPromise;
12999
13030
  get timeoutMs() {
13000
13031
  return this.config.requestTimeoutMs ?? DEFAULT_MCP_TIMEOUT_MS;
@@ -13047,15 +13078,22 @@ var init_client = __esm({
13047
13078
  return this.reconnectPromise;
13048
13079
  }
13049
13080
  async reconnect() {
13050
- if (this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
13051
- throw new NetworkError(`MCP ${this.name} reconnect exhausted`, { code: "mcp_disconnected" });
13081
+ let lastErr;
13082
+ for (let attempt = 0; attempt < MAX_RECONNECT_ATTEMPTS; attempt += 1) {
13083
+ await reconnectDelay(attempt);
13084
+ this.spawnChild();
13085
+ try {
13086
+ await super.initialize();
13087
+ this.dropped = false;
13088
+ return;
13089
+ } catch (err) {
13090
+ lastErr = err;
13091
+ }
13052
13092
  }
13053
- await reconnectDelay(this.reconnectAttempts);
13054
- this.reconnectAttempts += 1;
13055
- this.spawnChild();
13056
- await super.initialize();
13057
- this.dropped = false;
13058
- this.reconnectAttempts = 0;
13093
+ throw new NetworkError(`MCP ${this.name} reconnect exhausted`, {
13094
+ code: "mcp_disconnected",
13095
+ ...lastErr instanceof Error ? { cause: lastErr } : {}
13096
+ });
13059
13097
  }
13060
13098
  async close() {
13061
13099
  this.rejectAllPending(new NetworkError(`MCP ${this.name} closed`, { code: "mcp_closed" }));