@hsuite/smart-engines-sdk 3.11.0 → 3.12.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/CHANGELOG.md CHANGED
@@ -252,7 +252,7 @@ class MyService {
252
252
  ValidatorRules` section, two new rows in the "Available clients" table,
253
253
  and a pointer to the full developer guide.
254
254
  - Complete developer guide added at
255
- `docs/developers/libs/rules-engine.md#smart-app-sdk-guide` — covers
255
+ `docs/internal/developers/libs/rules-engine.md#smart-app-sdk-guide` — covers
256
256
  authoring paths, composer reference tables, publish + entity-create
257
257
  end-to-end flow, `baas.rules.*` + `baas.entities.*` reference, and 7
258
258
  common pitfalls.
package/README.md CHANGED
@@ -235,7 +235,7 @@ const sim = await baas.rules.simulate({ ruleRef, action: 'mint', context: { amou
235
235
  // sim.isValid === true | false (+ reason)
236
236
  ```
237
237
 
238
- Full reference: [Smart-App SDK Guide](../../docs/developers/libs/rules-engine.md#smart-app-sdk-guide)
238
+ Full reference: [Smart-App SDK Guide](../../docs/internal/developers/libs/rules-engine.md#smart-app-sdk-guide)
239
239
 
240
240
  ---
241
241
 
package/dist/index.d.ts CHANGED
@@ -5396,6 +5396,58 @@ declare function xlmToStroops(xlm: string | number): string;
5396
5396
  declare function validateBitcoinAddress(address: string): boolean;
5397
5397
  declare function satoshisToBtc(satoshis: string | number): string;
5398
5398
  declare function btcToSatoshis(btc: string | number): string;
5399
+ export type ModelProvider = "anthropic" | "openai" | "gemini";
5400
+ export type ChatMessage = {
5401
+ role: "system" | "user" | "assistant";
5402
+ content: string;
5403
+ };
5404
+ export type InferArgs = {
5405
+ system?: string;
5406
+ messages: ChatMessage[];
5407
+ maxTokens?: number;
5408
+ };
5409
+ export type InferResult = {
5410
+ ok: boolean;
5411
+ text?: string;
5412
+ error?: string;
5413
+ raw?: unknown;
5414
+ };
5415
+ export type IModelProvider = {
5416
+ readonly provider: ModelProvider;
5417
+ infer(args: InferArgs): Promise<InferResult>;
5418
+ };
5419
+ export declare function createAnthropicProvider(opts: {
5420
+ apiKey: string;
5421
+ model: string;
5422
+ }): IModelProvider;
5423
+ export declare function createOpenAiProvider(opts: {
5424
+ apiKey: string;
5425
+ model: string;
5426
+ }): IModelProvider;
5427
+ export declare function createGeminiProvider(opts: {
5428
+ apiKey: string;
5429
+ model: string;
5430
+ }): IModelProvider;
5431
+ export declare function createModelProvider(opts: {
5432
+ provider: ModelProvider;
5433
+ apiKey: string;
5434
+ model: string;
5435
+ }): IModelProvider;
5436
+ export type InferJsonResult<T> = {
5437
+ ok: boolean;
5438
+ value?: T;
5439
+ error?: string;
5440
+ raw?: string;
5441
+ };
5442
+ export declare function inferJson<T = unknown>(opts: {
5443
+ provider: ModelProvider;
5444
+ apiKey: string;
5445
+ model: string;
5446
+ system?: string;
5447
+ input: unknown;
5448
+ maxTokens?: number;
5449
+ parse?: (raw: unknown) => T;
5450
+ }): Promise<InferJsonResult<T>>;
5399
5451
  export type StateRootResponse = {
5400
5452
  appId: string;
5401
5453
  stateRoot: string;
@@ -25558,6 +25610,9 @@ declare namespace subscription {
25558
25610
  declare namespace faucet {
25559
25611
  export { FaucetChallenge, FaucetClient, FaucetDispenseRequest, FaucetDispenseResult, FaucetDispensed, FaucetRateLimited, FaucetStatusResponse, FaucetTrustlineRequired };
25560
25612
  }
25613
+ declare namespace ai {
25614
+ export { ChatMessage, IModelProvider, InferArgs, InferJsonResult, InferResult, ModelProvider, createAnthropicProvider, createGeminiProvider, createModelProvider, createOpenAiProvider, inferJson };
25615
+ }
25561
25616
  declare namespace bridge {
25562
25617
  export { BridgeChain, BridgeClaimRecord, BridgeClaimStatus, BridgeClient, BridgeConfig, BridgeDestinationConfig, BridgeDirection, BridgeGenesisBinding, BridgeMode, BridgeOperationConfig, BridgeRulesConfig, BridgeSourceConfig, BridgeStatus, BridgeSupply, BridgeTrustLevel, CreateBridgeRequest, CreateBridgeResponse, ListBridgesOptions, ListBridgesResponse, ListClaimsOptions, ListClaimsResponse, PortRequest, PortResult, ReturnRequest };
25563
25618
  }
@@ -25595,6 +25650,7 @@ declare namespace pqcVerify {
25595
25650
  export {
25596
25651
  RetryConfig as ResilienceRetryConfig,
25597
25652
  RetryConfig$1 as RetryConfig,
25653
+ ai,
25598
25654
  auth,
25599
25655
  baas,
25600
25656
  bridge,
package/dist/index.js CHANGED
@@ -10375,6 +10375,214 @@ function btcToSatoshis(btc) {
10375
10375
  return (amount * 1e8).toFixed(0);
10376
10376
  }
10377
10377
 
10378
+ // src/ai/index.ts
10379
+ var ai_exports = {};
10380
+ __export(ai_exports, {
10381
+ createAnthropicProvider: () => createAnthropicProvider,
10382
+ createGeminiProvider: () => createGeminiProvider,
10383
+ createModelProvider: () => createModelProvider,
10384
+ createOpenAiProvider: () => createOpenAiProvider,
10385
+ inferJson: () => inferJson
10386
+ });
10387
+
10388
+ // src/ai/anthropic.ts
10389
+ var ANTHROPIC_URL = "https://api.anthropic.com/v1/messages";
10390
+ var ANTHROPIC_VERSION = "2023-06-01";
10391
+ var DEFAULT_MAX_TOKENS = 1024;
10392
+ function createAnthropicProvider(opts) {
10393
+ const { apiKey, model } = opts;
10394
+ return {
10395
+ provider: "anthropic",
10396
+ async infer(args) {
10397
+ const messages = args.messages.filter((m) => m.role === "user" || m.role === "assistant").map((m) => ({ role: m.role, content: m.content }));
10398
+ const body = {
10399
+ model,
10400
+ max_tokens: args.maxTokens ?? DEFAULT_MAX_TOKENS,
10401
+ messages
10402
+ };
10403
+ if (args.system) {
10404
+ body.system = args.system;
10405
+ }
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
+ });
10415
+ if (!res.ok) {
10416
+ throw new Error(`Anthropic request failed with status ${res.status}`);
10417
+ }
10418
+ const data = await res.json();
10419
+ const text = Array.isArray(data.content) ? data.content.find((b) => typeof b.text === "string")?.text : void 0;
10420
+ if (typeof text !== "string") {
10421
+ return { ok: false, error: "Anthropic response contained no text block", raw: data };
10422
+ }
10423
+ return { ok: true, text, raw: data };
10424
+ }
10425
+ };
10426
+ }
10427
+
10428
+ // src/ai/openai.ts
10429
+ var OPENAI_URL = "https://api.openai.com/v1/chat/completions";
10430
+ var DEFAULT_MAX_TOKENS2 = 1024;
10431
+ function createOpenAiProvider(opts) {
10432
+ const { apiKey, model } = opts;
10433
+ return {
10434
+ provider: "openai",
10435
+ async infer(args) {
10436
+ const messages = [];
10437
+ if (args.system) {
10438
+ messages.push({ role: "system", content: args.system });
10439
+ }
10440
+ for (const m of args.messages) {
10441
+ messages.push({ role: m.role, content: m.content });
10442
+ }
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
+ });
10455
+ if (!res.ok) {
10456
+ throw new Error(`OpenAI request failed with status ${res.status}`);
10457
+ }
10458
+ const data = await res.json();
10459
+ const text = data.choices?.[0]?.message?.content;
10460
+ if (typeof text !== "string") {
10461
+ return { ok: false, error: "OpenAI response contained no message content", raw: data };
10462
+ }
10463
+ return { ok: true, text, raw: data };
10464
+ }
10465
+ };
10466
+ }
10467
+
10468
+ // src/ai/gemini.ts
10469
+ var GEMINI_BASE = "https://generativelanguage.googleapis.com/v1beta/models";
10470
+ var DEFAULT_MAX_TOKENS3 = 1024;
10471
+ function createGeminiProvider(opts) {
10472
+ const { apiKey, model } = opts;
10473
+ return {
10474
+ provider: "gemini",
10475
+ async infer(args) {
10476
+ const contents = args.messages.filter((m) => m.role === "user" || m.role === "assistant").map((m) => ({
10477
+ role: m.role === "assistant" ? "model" : "user",
10478
+ parts: [{ text: m.content }]
10479
+ }));
10480
+ const body = {
10481
+ contents,
10482
+ generationConfig: { maxOutputTokens: args.maxTokens ?? DEFAULT_MAX_TOKENS3 }
10483
+ };
10484
+ if (args.system) {
10485
+ body.systemInstruction = { parts: [{ text: args.system }] };
10486
+ }
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
+ });
10493
+ if (!res.ok) {
10494
+ throw new Error(`Gemini request failed with status ${res.status}`);
10495
+ }
10496
+ const data = await res.json();
10497
+ const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
10498
+ if (typeof text !== "string") {
10499
+ return { ok: false, error: "Gemini response contained no text part", raw: data };
10500
+ }
10501
+ return { ok: true, text, raw: data };
10502
+ }
10503
+ };
10504
+ }
10505
+
10506
+ // src/ai/factory.ts
10507
+ function createModelProvider(opts) {
10508
+ const { provider, apiKey, model } = opts;
10509
+ switch (provider) {
10510
+ case "anthropic":
10511
+ return createAnthropicProvider({ apiKey, model });
10512
+ case "openai":
10513
+ return createOpenAiProvider({ apiKey, model });
10514
+ case "gemini":
10515
+ return createGeminiProvider({ apiKey, model });
10516
+ default: {
10517
+ const never = provider;
10518
+ throw new Error(`Unsupported model provider: ${String(never)}`);
10519
+ }
10520
+ }
10521
+ }
10522
+
10523
+ // src/ai/infer-json.ts
10524
+ var JSON_ONLY_INSTRUCTION = "Respond with ONLY a single JSON object, no prose.";
10525
+ var RETRY_INSTRUCTION = "Return valid JSON only.";
10526
+ 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");
10531
+ }
10532
+ return JSON.parse(raw.slice(start, end + 1));
10533
+ }
10534
+ async function inferJson(opts) {
10535
+ const { provider, apiKey, model, system, input, maxTokens, parse } = opts;
10536
+ let client;
10537
+ try {
10538
+ client = createModelProvider({ provider, apiKey, model });
10539
+ } catch (err) {
10540
+ return { ok: false, error: errMsg(err) };
10541
+ }
10542
+ const systemPrompt = system ? `${system}
10543
+
10544
+ ${JSON_ONLY_INSTRUCTION}` : JSON_ONLY_INSTRUCTION;
10545
+ const userContent = typeof input === "string" ? input : JSON.stringify(input);
10546
+ const messages = [{ role: "user", content: userContent }];
10547
+ const first = await runOnce(client, { system: systemPrompt, messages, maxTokens }, parse);
10548
+ if (first.ok) {
10549
+ return first;
10550
+ }
10551
+ const retryMessages = [...messages];
10552
+ if (typeof first.raw === "string") {
10553
+ retryMessages.push({ role: "assistant", content: first.raw });
10554
+ }
10555
+ retryMessages.push({ role: "user", content: RETRY_INSTRUCTION });
10556
+ const second = await runOnce(
10557
+ client,
10558
+ { system: systemPrompt, messages: retryMessages, maxTokens },
10559
+ parse
10560
+ );
10561
+ return second;
10562
+ }
10563
+ async function runOnce(client, args, parse) {
10564
+ let inferred;
10565
+ try {
10566
+ inferred = await client.infer(args);
10567
+ } catch (err) {
10568
+ return { ok: false, error: errMsg(err) };
10569
+ }
10570
+ if (!inferred.ok || typeof inferred.text !== "string") {
10571
+ return { ok: false, error: inferred.error ?? "provider returned no text", raw: inferred.text };
10572
+ }
10573
+ const raw = inferred.text;
10574
+ try {
10575
+ const parsed = extractJson(raw);
10576
+ const value = parse ? parse(parsed) : parsed;
10577
+ return { ok: true, value, raw };
10578
+ } catch (err) {
10579
+ return { ok: false, error: errMsg(err), raw };
10580
+ }
10581
+ }
10582
+ function errMsg(err) {
10583
+ return err instanceof Error ? err.message : String(err);
10584
+ }
10585
+
10378
10586
  // src/baas/index.ts
10379
10587
  var baas_exports = {};
10380
10588
  __export(baas_exports, {
@@ -13501,6 +13709,7 @@ exports.ValidatorDiscoveryClient = ValidatorDiscoveryClient;
13501
13709
  exports.ValidatorMetadataSchema = ValidatorMetadataSchema;
13502
13710
  exports.ValidatorRulesSchema = ValidatorRulesSchema;
13503
13711
  exports.XrplTransactionsClient = XrplTransactionsClient;
13712
+ exports.ai = ai_exports;
13504
13713
  exports.appTopic = appTopic;
13505
13714
  exports.atom = atom;
13506
13715
  exports.auth = auth_exports;
@@ -13509,7 +13718,11 @@ exports.bridge = bridge_exports;
13509
13718
  exports.canonicalizeAttestation = canonicalizeAttestation;
13510
13719
  exports.chains = chains_exports;
13511
13720
  exports.computeAttestationHash = computeAttestationHash;
13721
+ exports.createAnthropicProvider = createAnthropicProvider;
13722
+ exports.createGeminiProvider = createGeminiProvider;
13512
13723
  exports.createHttpClient = createHttpClient;
13724
+ exports.createModelProvider = createModelProvider;
13725
+ exports.createOpenAiProvider = createOpenAiProvider;
13513
13726
  exports.createResilientFetchWithBreaker = createResilientFetchWithBreaker;
13514
13727
  exports.createXrplWeb3Signer = createXrplWeb3Signer;
13515
13728
  exports.dao = dao_exports;
@@ -13525,6 +13738,7 @@ exports.forAgent = forAgent;
13525
13738
  exports.forToken = forToken;
13526
13739
  exports.forTopic = forTopic;
13527
13740
  exports.governance = governance_exports;
13741
+ exports.inferJson = inferJson;
13528
13742
  exports.isKnownNetwork = isKnownNetwork;
13529
13743
  exports.isPersonhoodVerifierNotConfigured = isPersonhoodVerifierNotConfigured;
13530
13744
  exports.isRuleRejected = isRuleRejected;