@hsuite/smart-engines-sdk 3.12.0 → 3.13.0

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/index.d.ts CHANGED
@@ -3885,7 +3885,7 @@ export type AgentExecuteRequest = {
3885
3885
  params: Record<string, unknown>;
3886
3886
  };
3887
3887
  export type AgentExecuteStepResult = {
3888
- kind: "onchain" | "offchain";
3888
+ kind: "onchain" | "offchain" | "function";
3889
3889
  status: string;
3890
3890
  transactionBytes?: string;
3891
3891
  ref?: string;
@@ -5405,6 +5405,8 @@ export type InferArgs = {
5405
5405
  system?: string;
5406
5406
  messages: ChatMessage[];
5407
5407
  maxTokens?: number;
5408
+ timeoutMs?: number;
5409
+ signal?: AbortSignal;
5408
5410
  };
5409
5411
  export type InferResult = {
5410
5412
  ok: boolean;
@@ -5446,6 +5448,8 @@ export declare function inferJson<T = unknown>(opts: {
5446
5448
  system?: string;
5447
5449
  input: unknown;
5448
5450
  maxTokens?: number;
5451
+ timeoutMs?: number;
5452
+ signal?: AbortSignal;
5449
5453
  parse?: (raw: unknown) => T;
5450
5454
  }): Promise<InferJsonResult<T>>;
5451
5455
  export type StateRootResponse = {
package/dist/index.js CHANGED
@@ -10385,6 +10385,65 @@ __export(ai_exports, {
10385
10385
  inferJson: () => inferJson
10386
10386
  });
10387
10387
 
10388
+ // src/ai/types.ts
10389
+ var DEFAULT_INFER_TIMEOUT_MS = 3e4;
10390
+
10391
+ // src/ai/http.ts
10392
+ var InferTimeoutError = class extends Error {
10393
+ constructor(timeoutMs) {
10394
+ super(`request timed out after ${timeoutMs}ms`);
10395
+ this.name = "InferTimeoutError";
10396
+ }
10397
+ };
10398
+ function isAbortError(err) {
10399
+ if (err instanceof InferTimeoutError) {
10400
+ return true;
10401
+ }
10402
+ return typeof err === "object" && err !== null && err.name === "AbortError";
10403
+ }
10404
+ function errMsg(err) {
10405
+ return err instanceof Error ? err.message : String(err);
10406
+ }
10407
+ async function fetchWithTimeout(url, init, opts = {}) {
10408
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_INFER_TIMEOUT_MS;
10409
+ const callerSignal = opts.signal;
10410
+ const controller = new AbortController();
10411
+ let timedOut = false;
10412
+ let timer;
10413
+ if (timeoutMs > 0) {
10414
+ timer = setTimeout(() => {
10415
+ timedOut = true;
10416
+ controller.abort();
10417
+ }, timeoutMs);
10418
+ if (typeof timer === "object" && typeof timer.unref === "function") {
10419
+ timer.unref();
10420
+ }
10421
+ }
10422
+ const onCallerAbort = () => controller.abort();
10423
+ if (callerSignal) {
10424
+ if (callerSignal.aborted) {
10425
+ controller.abort();
10426
+ } else {
10427
+ callerSignal.addEventListener("abort", onCallerAbort, { once: true });
10428
+ }
10429
+ }
10430
+ try {
10431
+ return await fetch(url, { ...init, signal: controller.signal });
10432
+ } catch (err) {
10433
+ if (timedOut) {
10434
+ throw new InferTimeoutError(timeoutMs);
10435
+ }
10436
+ throw err;
10437
+ } finally {
10438
+ if (timer !== void 0) {
10439
+ clearTimeout(timer);
10440
+ }
10441
+ if (callerSignal) {
10442
+ callerSignal.removeEventListener("abort", onCallerAbort);
10443
+ }
10444
+ }
10445
+ }
10446
+
10388
10447
  // src/ai/anthropic.ts
10389
10448
  var ANTHROPIC_URL = "https://api.anthropic.com/v1/messages";
10390
10449
  var ANTHROPIC_VERSION = "2023-06-01";
@@ -10403,15 +10462,27 @@ function createAnthropicProvider(opts) {
10403
10462
  if (args.system) {
10404
10463
  body.system = args.system;
10405
10464
  }
10406
- const res = await fetch(ANTHROPIC_URL, {
10407
- method: "POST",
10408
- headers: {
10409
- "x-api-key": apiKey,
10410
- "anthropic-version": ANTHROPIC_VERSION,
10411
- "content-type": "application/json"
10412
- },
10413
- body: JSON.stringify(body)
10414
- });
10465
+ let res;
10466
+ try {
10467
+ res = await fetchWithTimeout(
10468
+ ANTHROPIC_URL,
10469
+ {
10470
+ method: "POST",
10471
+ headers: {
10472
+ "x-api-key": apiKey,
10473
+ "anthropic-version": ANTHROPIC_VERSION,
10474
+ "content-type": "application/json"
10475
+ },
10476
+ body: JSON.stringify(body)
10477
+ },
10478
+ { timeoutMs: args.timeoutMs, signal: args.signal }
10479
+ );
10480
+ } catch (err) {
10481
+ if (isAbortError(err)) {
10482
+ return { ok: false, error: errMsg(err) };
10483
+ }
10484
+ throw err;
10485
+ }
10415
10486
  if (!res.ok) {
10416
10487
  throw new Error(`Anthropic request failed with status ${res.status}`);
10417
10488
  }
@@ -10440,18 +10511,30 @@ function createOpenAiProvider(opts) {
10440
10511
  for (const m of args.messages) {
10441
10512
  messages.push({ role: m.role, content: m.content });
10442
10513
  }
10443
- const res = await fetch(OPENAI_URL, {
10444
- method: "POST",
10445
- headers: {
10446
- Authorization: `Bearer ${apiKey}`,
10447
- "content-type": "application/json"
10448
- },
10449
- body: JSON.stringify({
10450
- model,
10451
- max_tokens: args.maxTokens ?? DEFAULT_MAX_TOKENS2,
10452
- messages
10453
- })
10454
- });
10514
+ let res;
10515
+ try {
10516
+ res = await fetchWithTimeout(
10517
+ OPENAI_URL,
10518
+ {
10519
+ method: "POST",
10520
+ headers: {
10521
+ Authorization: `Bearer ${apiKey}`,
10522
+ "content-type": "application/json"
10523
+ },
10524
+ body: JSON.stringify({
10525
+ model,
10526
+ max_tokens: args.maxTokens ?? DEFAULT_MAX_TOKENS2,
10527
+ messages
10528
+ })
10529
+ },
10530
+ { timeoutMs: args.timeoutMs, signal: args.signal }
10531
+ );
10532
+ } catch (err) {
10533
+ if (isAbortError(err)) {
10534
+ return { ok: false, error: errMsg(err) };
10535
+ }
10536
+ throw err;
10537
+ }
10455
10538
  if (!res.ok) {
10456
10539
  throw new Error(`OpenAI request failed with status ${res.status}`);
10457
10540
  }
@@ -10484,12 +10567,27 @@ function createGeminiProvider(opts) {
10484
10567
  if (args.system) {
10485
10568
  body.systemInstruction = { parts: [{ text: args.system }] };
10486
10569
  }
10487
- const url = `${GEMINI_BASE}/${model}:generateContent?key=${encodeURIComponent(apiKey)}`;
10488
- const res = await fetch(url, {
10489
- method: "POST",
10490
- headers: { "content-type": "application/json" },
10491
- body: JSON.stringify(body)
10492
- });
10570
+ const url = `${GEMINI_BASE}/${model}:generateContent`;
10571
+ let res;
10572
+ try {
10573
+ res = await fetchWithTimeout(
10574
+ url,
10575
+ {
10576
+ method: "POST",
10577
+ headers: {
10578
+ "content-type": "application/json",
10579
+ "x-goog-api-key": apiKey
10580
+ },
10581
+ body: JSON.stringify(body)
10582
+ },
10583
+ { timeoutMs: args.timeoutMs, signal: args.signal }
10584
+ );
10585
+ } catch (err) {
10586
+ if (isAbortError(err)) {
10587
+ return { ok: false, error: errMsg(err) };
10588
+ }
10589
+ throw err;
10590
+ }
10493
10591
  if (!res.ok) {
10494
10592
  throw new Error(`Gemini request failed with status ${res.status}`);
10495
10593
  }
@@ -10523,16 +10621,61 @@ function createModelProvider(opts) {
10523
10621
  // src/ai/infer-json.ts
10524
10622
  var JSON_ONLY_INSTRUCTION = "Respond with ONLY a single JSON object, no prose.";
10525
10623
  var RETRY_INSTRUCTION = "Return valid JSON only.";
10624
+ function nextBalancedObject(raw, from) {
10625
+ const start = raw.indexOf("{", from);
10626
+ if (start === -1) {
10627
+ return null;
10628
+ }
10629
+ let depth = 0;
10630
+ let inString = false;
10631
+ let escaped = false;
10632
+ for (let i = start; i < raw.length; i++) {
10633
+ const ch = raw[i];
10634
+ if (inString) {
10635
+ if (escaped) {
10636
+ escaped = false;
10637
+ } else if (ch === "\\") {
10638
+ escaped = true;
10639
+ } else if (ch === '"') {
10640
+ inString = false;
10641
+ }
10642
+ continue;
10643
+ }
10644
+ if (ch === '"') {
10645
+ inString = true;
10646
+ } else if (ch === "{") {
10647
+ depth++;
10648
+ } else if (ch === "}") {
10649
+ depth--;
10650
+ if (depth === 0) {
10651
+ return [start, i];
10652
+ }
10653
+ }
10654
+ }
10655
+ return null;
10656
+ }
10526
10657
  function extractJson(raw) {
10527
- const start = raw.indexOf("{");
10528
- const end = raw.lastIndexOf("}");
10529
- if (start === -1 || end === -1 || end < start) {
10530
- throw new Error("no JSON object found in reply");
10658
+ let from = 0;
10659
+ let sawCandidate = false;
10660
+ for (; ; ) {
10661
+ const span = nextBalancedObject(raw, from);
10662
+ if (!span) {
10663
+ break;
10664
+ }
10665
+ sawCandidate = true;
10666
+ const slice = raw.slice(span[0], span[1] + 1);
10667
+ try {
10668
+ return JSON.parse(slice);
10669
+ } catch {
10670
+ from = span[0] + 1;
10671
+ }
10531
10672
  }
10532
- return JSON.parse(raw.slice(start, end + 1));
10673
+ throw new Error(
10674
+ sawCandidate ? "no valid JSON object found in reply" : "no JSON object found in reply"
10675
+ );
10533
10676
  }
10534
10677
  async function inferJson(opts) {
10535
- const { provider, apiKey, model, system, input, maxTokens, parse } = opts;
10678
+ const { provider, apiKey, model, system, input, maxTokens, timeoutMs, signal, parse } = opts;
10536
10679
  let client;
10537
10680
  try {
10538
10681
  client = createModelProvider({ provider, apiKey, model });
@@ -10544,7 +10687,11 @@ async function inferJson(opts) {
10544
10687
  ${JSON_ONLY_INSTRUCTION}` : JSON_ONLY_INSTRUCTION;
10545
10688
  const userContent = typeof input === "string" ? input : JSON.stringify(input);
10546
10689
  const messages = [{ role: "user", content: userContent }];
10547
- const first = await runOnce(client, { system: systemPrompt, messages, maxTokens }, parse);
10690
+ const first = await runOnce(
10691
+ client,
10692
+ { system: systemPrompt, messages, maxTokens, timeoutMs, signal },
10693
+ parse
10694
+ );
10548
10695
  if (first.ok) {
10549
10696
  return first;
10550
10697
  }
@@ -10555,7 +10702,7 @@ ${JSON_ONLY_INSTRUCTION}` : JSON_ONLY_INSTRUCTION;
10555
10702
  retryMessages.push({ role: "user", content: RETRY_INSTRUCTION });
10556
10703
  const second = await runOnce(
10557
10704
  client,
10558
- { system: systemPrompt, messages: retryMessages, maxTokens },
10705
+ { system: systemPrompt, messages: retryMessages, maxTokens, timeoutMs, signal },
10559
10706
  parse
10560
10707
  );
10561
10708
  return second;
@@ -10579,9 +10726,6 @@ async function runOnce(client, args, parse) {
10579
10726
  return { ok: false, error: errMsg(err), raw };
10580
10727
  }
10581
10728
  }
10582
- function errMsg(err) {
10583
- return err instanceof Error ? err.message : String(err);
10584
- }
10585
10729
 
10586
10730
  // src/baas/index.ts
10587
10731
  var baas_exports = {};