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