@neetru/sdk 3.1.9 → 3.1.11

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.
Files changed (51) hide show
  1. package/dist/ai.cjs +304 -0
  2. package/dist/ai.cjs.map +1 -0
  3. package/dist/ai.d.cts +3 -0
  4. package/dist/ai.d.ts +3 -0
  5. package/dist/ai.mjs +302 -0
  6. package/dist/ai.mjs.map +1 -0
  7. package/dist/auth.cjs +283 -1
  8. package/dist/auth.cjs.map +1 -1
  9. package/dist/auth.d.cts +1 -1
  10. package/dist/auth.d.ts +1 -1
  11. package/dist/auth.mjs +283 -1
  12. package/dist/auth.mjs.map +1 -1
  13. package/dist/catalog.d.cts +1 -1
  14. package/dist/catalog.d.ts +1 -1
  15. package/dist/checkout.d.cts +1 -1
  16. package/dist/checkout.d.ts +1 -1
  17. package/dist/db-react.d.cts +1 -1
  18. package/dist/db-react.d.ts +1 -1
  19. package/dist/db.d.cts +1 -1
  20. package/dist/db.d.ts +1 -1
  21. package/dist/entitlements.d.cts +1 -1
  22. package/dist/entitlements.d.ts +1 -1
  23. package/dist/firestore-compat.d.cts +1 -1
  24. package/dist/firestore-compat.d.ts +1 -1
  25. package/dist/index.cjs +286 -2
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +3 -3
  28. package/dist/index.d.ts +3 -3
  29. package/dist/index.mjs +285 -3
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/mocks.cjs +52 -0
  32. package/dist/mocks.cjs.map +1 -1
  33. package/dist/mocks.d.cts +20 -2
  34. package/dist/mocks.d.ts +20 -2
  35. package/dist/mocks.mjs +52 -1
  36. package/dist/mocks.mjs.map +1 -1
  37. package/dist/notifications.d.cts +1 -1
  38. package/dist/notifications.d.ts +1 -1
  39. package/dist/react.d.cts +1 -1
  40. package/dist/react.d.ts +1 -1
  41. package/dist/support.d.cts +1 -1
  42. package/dist/support.d.ts +1 -1
  43. package/dist/telemetry.d.cts +1 -1
  44. package/dist/telemetry.d.ts +1 -1
  45. package/dist/{types-DDiVzgCT.d.cts → types-Cog9S-tC.d.cts} +84 -1
  46. package/dist/{types-HWDOUmlC.d.ts → types-dagUxKYz.d.ts} +84 -1
  47. package/dist/usage.d.cts +1 -1
  48. package/dist/usage.d.ts +1 -1
  49. package/dist/webhooks.d.cts +1 -1
  50. package/dist/webhooks.d.ts +1 -1
  51. package/package.json +6 -1
@@ -1,4 +1,4 @@
1
- import { a3 as ResolvedConfig, C as CatalogListOptions, b as CatalogListResponse, X as Product } from './types-DDiVzgCT.cjs';
1
+ import { ab as ResolvedConfig, C as CatalogListOptions, j as CatalogListResponse, a3 as Product } from './types-Cog9S-tC.cjs';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.cjs';
4
4
 
package/dist/catalog.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a3 as ResolvedConfig, C as CatalogListOptions, b as CatalogListResponse, X as Product } from './types-HWDOUmlC.js';
1
+ import { ab as ResolvedConfig, C as CatalogListOptions, j as CatalogListResponse, a3 as Product } from './types-dagUxKYz.js';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.js';
4
4
 
@@ -1,3 +1,3 @@
1
- export { c as CheckoutAuthOpts, d as CheckoutIntentInfo, e as CheckoutIntentStatus, f as CheckoutNamespace, g as CheckoutStartInput, h as CheckoutStartResult, i as CheckoutTenantType, M as MockCheckout, au as createCheckoutNamespace } from './types-DDiVzgCT.cjs';
1
+ export { k as CheckoutAuthOpts, l as CheckoutIntentInfo, m as CheckoutIntentStatus, n as CheckoutNamespace, o as CheckoutStartInput, p as CheckoutStartResult, q as CheckoutTenantType, N as MockCheckout, aD as createCheckoutNamespace } from './types-Cog9S-tC.cjs';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.cjs';
@@ -1,3 +1,3 @@
1
- export { c as CheckoutAuthOpts, d as CheckoutIntentInfo, e as CheckoutIntentStatus, f as CheckoutNamespace, g as CheckoutStartInput, h as CheckoutStartResult, i as CheckoutTenantType, M as MockCheckout, au as createCheckoutNamespace } from './types-HWDOUmlC.js';
1
+ export { k as CheckoutAuthOpts, l as CheckoutIntentInfo, m as CheckoutIntentStatus, n as CheckoutNamespace, o as CheckoutStartInput, p as CheckoutStartResult, q as CheckoutTenantType, N as MockCheckout, aD as createCheckoutNamespace } from './types-dagUxKYz.js';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.js';
@@ -1,4 +1,4 @@
1
- import { ac as SyncState, ah as Unsubscribe, p as DbDoc, B as NeetruClient, o as DbCollectionRef, u as DbQuery } from './types-DDiVzgCT.cjs';
1
+ import { ak as SyncState, ap as Unsubscribe, x as DbDoc, R as NeetruClient, w as DbCollectionRef, F as DbQuery } from './types-Cog9S-tC.cjs';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.cjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { ac as SyncState, ah as Unsubscribe, p as DbDoc, B as NeetruClient, o as DbCollectionRef, u as DbQuery } from './types-HWDOUmlC.js';
1
+ import { ak as SyncState, ap as Unsubscribe, x as DbDoc, R as NeetruClient, w as DbCollectionRef, F as DbQuery } from './types-dagUxKYz.js';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.js';
4
4
 
package/dist/db.d.cts CHANGED
@@ -1,3 +1,3 @@
1
- export { j as ConflictRecord, k as CreateOfflineDocumentsOptions, m as DbBatchOp, n as DbChangeType, o as DbCollectionRef, p as DbDoc, q as DbDocRef, r as DbGetResult, s as DbListResult, u as DbQuery, v as DbSqlLease, x as DbWhereFilter, F as FieldSentinel, I as IncrementSentinel, N as NEETRU_SENTINEL_KEY, H as NeetruDb, J as NeetruDbDocuments, K as NeetruDbEngine, O as NeetruDbError, P as NeetruDbErrorCode, Q as NeetruDbOptions, R as NeetruDbTransport, T as NeetruSqlClient, a0 as RealtimeTransport, a5 as ServerTimestampSentinel, a7 as SqlOptions, ac as SyncState, at as WithFieldSentinels, av as createNeetruDb, ax as createRestSyncTransport, az as getWebSocketRealtimeClient, aA as increment, aB as isFieldSentinel, aC as isIncrementSentinel, aD as isServerTimestampSentinel, aE as serverTimestamp } from './types-DDiVzgCT.cjs';
1
+ export { r as ConflictRecord, s as CreateOfflineDocumentsOptions, u as DbBatchOp, v as DbChangeType, w as DbCollectionRef, x as DbDoc, y as DbDocRef, z as DbGetResult, B as DbListResult, F as DbQuery, G as DbSqlLease, I as DbWhereFilter, K as FieldSentinel, L as IncrementSentinel, Q as NEETRU_SENTINEL_KEY, T as NeetruDb, U as NeetruDbDocuments, V as NeetruDbEngine, W as NeetruDbError, X as NeetruDbErrorCode, Y as NeetruDbOptions, Z as NeetruDbTransport, $ as NeetruSqlClient, a8 as RealtimeTransport, ad as ServerTimestampSentinel, af as SqlOptions, ak as SyncState, aB as WithFieldSentinels, aE as createNeetruDb, aG as createRestSyncTransport, aI as getWebSocketRealtimeClient, aJ as increment, aK as isFieldSentinel, aL as isIncrementSentinel, aM as isServerTimestampSentinel, aN as serverTimestamp } from './types-Cog9S-tC.cjs';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.cjs';
package/dist/db.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { j as ConflictRecord, k as CreateOfflineDocumentsOptions, m as DbBatchOp, n as DbChangeType, o as DbCollectionRef, p as DbDoc, q as DbDocRef, r as DbGetResult, s as DbListResult, u as DbQuery, v as DbSqlLease, x as DbWhereFilter, F as FieldSentinel, I as IncrementSentinel, N as NEETRU_SENTINEL_KEY, H as NeetruDb, J as NeetruDbDocuments, K as NeetruDbEngine, O as NeetruDbError, P as NeetruDbErrorCode, Q as NeetruDbOptions, R as NeetruDbTransport, T as NeetruSqlClient, a0 as RealtimeTransport, a5 as ServerTimestampSentinel, a7 as SqlOptions, ac as SyncState, at as WithFieldSentinels, av as createNeetruDb, ax as createRestSyncTransport, az as getWebSocketRealtimeClient, aA as increment, aB as isFieldSentinel, aC as isIncrementSentinel, aD as isServerTimestampSentinel, aE as serverTimestamp } from './types-HWDOUmlC.js';
1
+ export { r as ConflictRecord, s as CreateOfflineDocumentsOptions, u as DbBatchOp, v as DbChangeType, w as DbCollectionRef, x as DbDoc, y as DbDocRef, z as DbGetResult, B as DbListResult, F as DbQuery, G as DbSqlLease, I as DbWhereFilter, K as FieldSentinel, L as IncrementSentinel, Q as NEETRU_SENTINEL_KEY, T as NeetruDb, U as NeetruDbDocuments, V as NeetruDbEngine, W as NeetruDbError, X as NeetruDbErrorCode, Y as NeetruDbOptions, Z as NeetruDbTransport, $ as NeetruSqlClient, a8 as RealtimeTransport, ad as ServerTimestampSentinel, af as SqlOptions, ak as SyncState, aB as WithFieldSentinels, aE as createNeetruDb, aG as createRestSyncTransport, aI as getWebSocketRealtimeClient, aJ as increment, aK as isFieldSentinel, aL as isIncrementSentinel, aM as isServerTimestampSentinel, aN as serverTimestamp } from './types-dagUxKYz.js';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.js';
@@ -1,4 +1,4 @@
1
- import { a3 as ResolvedConfig, E as EntitlementCheck } from './types-DDiVzgCT.cjs';
1
+ import { ab as ResolvedConfig, J as EntitlementCheck } from './types-Cog9S-tC.cjs';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.cjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { a3 as ResolvedConfig, E as EntitlementCheck } from './types-HWDOUmlC.js';
1
+ import { ab as ResolvedConfig, J as EntitlementCheck } from './types-dagUxKYz.js';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.js';
4
4
 
@@ -1,4 +1,4 @@
1
- import { H as NeetruDb, o as DbCollectionRef, F as FieldSentinel, u as DbQuery } from './types-DDiVzgCT.cjs';
1
+ import { T as NeetruDb, w as DbCollectionRef, K as FieldSentinel, F as DbQuery } from './types-Cog9S-tC.cjs';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.cjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { H as NeetruDb, o as DbCollectionRef, F as FieldSentinel, u as DbQuery } from './types-HWDOUmlC.js';
1
+ import { T as NeetruDb, w as DbCollectionRef, K as FieldSentinel, F as DbQuery } from './types-dagUxKYz.js';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.js';
4
4
 
package/dist/index.cjs CHANGED
@@ -5596,6 +5596,235 @@ var MockNotifications = class {
5596
5596
  }
5597
5597
  };
5598
5598
 
5599
+ // src/ai.ts
5600
+ init_errors();
5601
+ init_http();
5602
+ var AI_CHAT_PATH = "/api/sdk/v1/ai/chat";
5603
+ var AI_NONSTREAM_TIMEOUT_MS = 12e4;
5604
+ function resolveAiBody(config, opts, stream) {
5605
+ if (!opts || typeof opts !== "object") {
5606
+ throw new exports.NeetruError("validation_failed", "ai: options object is required");
5607
+ }
5608
+ if (typeof opts.model !== "string" || opts.model.length === 0) {
5609
+ throw new exports.NeetruError("validation_failed", "ai: model is required");
5610
+ }
5611
+ if (!Array.isArray(opts.messages) || opts.messages.length === 0) {
5612
+ throw new exports.NeetruError("validation_failed", "ai: messages must be a non-empty array");
5613
+ }
5614
+ for (const m of opts.messages) {
5615
+ if (!m || typeof m !== "object" || typeof m.role !== "string" || m.role.length === 0 || typeof m.content !== "string") {
5616
+ throw new exports.NeetruError(
5617
+ "validation_failed",
5618
+ "ai: each message must be { role: string, content: string }"
5619
+ );
5620
+ }
5621
+ }
5622
+ const productId = opts.productId ?? config.productId;
5623
+ const tenantId = opts.tenantId ?? config.tenantId;
5624
+ if (!productId) {
5625
+ throw new exports.NeetruError(
5626
+ "validation_failed",
5627
+ "ai: productId required (pass to options or set on createNeetruClient)"
5628
+ );
5629
+ }
5630
+ if (!tenantId) {
5631
+ throw new exports.NeetruError(
5632
+ "validation_failed",
5633
+ "ai: tenantId required (pass to options or set on createNeetruClient)"
5634
+ );
5635
+ }
5636
+ assertValidSdkId("productId", productId);
5637
+ assertValidSdkId("tenantId", tenantId);
5638
+ const body = {
5639
+ productId,
5640
+ tenantId,
5641
+ model: opts.model,
5642
+ messages: opts.messages,
5643
+ stream
5644
+ };
5645
+ if (opts.maxTokens !== void 0) {
5646
+ if (!Number.isInteger(opts.maxTokens) || opts.maxTokens <= 0) {
5647
+ throw new exports.NeetruError("validation_failed", "ai: maxTokens must be a positive integer");
5648
+ }
5649
+ body.maxTokens = opts.maxTokens;
5650
+ }
5651
+ if (opts.temperature !== void 0) {
5652
+ if (typeof opts.temperature !== "number" || !Number.isFinite(opts.temperature)) {
5653
+ throw new exports.NeetruError("validation_failed", "ai: temperature must be a finite number");
5654
+ }
5655
+ body.temperature = opts.temperature;
5656
+ }
5657
+ return body;
5658
+ }
5659
+ async function safeJson2(res) {
5660
+ try {
5661
+ const text = await res.text();
5662
+ if (!text) return void 0;
5663
+ return JSON.parse(text);
5664
+ } catch {
5665
+ return void 0;
5666
+ }
5667
+ }
5668
+ function statusToCode2(status) {
5669
+ if (status === 401) return "unauthorized";
5670
+ if (status === 403) return "forbidden";
5671
+ if (status === 404) return "not_found";
5672
+ if (status === 409) return "conflict";
5673
+ if (status === 422 || status === 400) return "validation_failed";
5674
+ if (status === 429) return "rate_limited";
5675
+ if (status >= 500) return "server_error";
5676
+ return "unknown";
5677
+ }
5678
+ function joinUrl(baseUrl, path) {
5679
+ const base = baseUrl.replace(/\/+$/, "");
5680
+ const p = path.startsWith("/") ? path : `/${path}`;
5681
+ return `${base}${p}`;
5682
+ }
5683
+ async function aiFetch(config, body, signal, stream) {
5684
+ if (!config.apiKey) {
5685
+ throw new exports.NeetruError(
5686
+ "missing_api_key",
5687
+ "ai requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var."
5688
+ );
5689
+ }
5690
+ const url = joinUrl(config.baseUrl, AI_CHAT_PATH);
5691
+ const headers = {
5692
+ "content-type": "application/json",
5693
+ accept: stream ? "text/event-stream" : "application/json",
5694
+ authorization: `Bearer ${config.apiKey}`
5695
+ };
5696
+ const init = { method: "POST", headers, body: JSON.stringify(body) };
5697
+ if (stream) {
5698
+ if (signal) init.signal = signal;
5699
+ } else {
5700
+ init.signal = signal ?? AbortSignal.timeout(AI_NONSTREAM_TIMEOUT_MS);
5701
+ }
5702
+ let res;
5703
+ try {
5704
+ res = await config.fetch(url, init);
5705
+ } catch (err) {
5706
+ const message = err instanceof DOMException && err.name === "TimeoutError" ? `Network error: timeout after ${AI_NONSTREAM_TIMEOUT_MS / 1e3}s` : err instanceof DOMException && err.name === "AbortError" ? "Network error: request aborted" : `Network error: ${err instanceof Error ? err.message : "fetch failed"}`;
5707
+ throw new exports.NeetruError("network_error", message);
5708
+ }
5709
+ const requestId = res.headers.get("x-request-id") ?? res.headers.get("x-correlation-id") ?? void 0;
5710
+ if (!res.ok) {
5711
+ const parsed = await safeJson2(res);
5712
+ let code = statusToCode2(res.status);
5713
+ let message = `HTTP ${res.status}`;
5714
+ if (parsed && typeof parsed === "object" && "error" in parsed) {
5715
+ const errField = parsed.error;
5716
+ if (typeof errField === "string") {
5717
+ message = errField;
5718
+ } else if (errField && typeof errField === "object") {
5719
+ if (typeof errField.code === "string") code = errField.code;
5720
+ if (typeof errField.message === "string") message = errField.message;
5721
+ }
5722
+ }
5723
+ throw new exports.NeetruError(code, message, res.status, requestId);
5724
+ }
5725
+ const coreVersion = res.headers.get("x-neetru-version");
5726
+ if (coreVersion) checkCoreVersionCompat(coreVersion);
5727
+ return res;
5728
+ }
5729
+ function readMeta(res) {
5730
+ return {
5731
+ provider: res.headers.get("x-neetru-provider") ?? "",
5732
+ usageWarning: res.headers.get("x-neetru-ai-usage-warning") === "1"
5733
+ };
5734
+ }
5735
+ function parseSseData(rawEvent) {
5736
+ const dataLines = [];
5737
+ for (const line of rawEvent.split("\n")) {
5738
+ const trimmed = line.replace(/\r$/, "");
5739
+ if (trimmed.startsWith("data:")) {
5740
+ let v = trimmed.slice(5);
5741
+ if (v.startsWith(" ")) v = v.slice(1);
5742
+ dataLines.push(v);
5743
+ }
5744
+ }
5745
+ if (dataLines.length === 0) return null;
5746
+ const payload = dataLines.join("\n");
5747
+ if (payload === "[DONE]") return { done: true };
5748
+ try {
5749
+ const obj = JSON.parse(payload);
5750
+ const content = obj?.choices?.[0]?.delta?.content;
5751
+ if (typeof content === "string" && content.length > 0) return { content };
5752
+ return null;
5753
+ } catch {
5754
+ return null;
5755
+ }
5756
+ }
5757
+ function createAiNamespace(config) {
5758
+ return {
5759
+ async chat(opts) {
5760
+ const body = resolveAiBody(config, opts, false);
5761
+ const res = await aiFetch(config, body, opts.signal, false);
5762
+ const { provider: providerHeader, usageWarning } = readMeta(res);
5763
+ const raw = await safeJson2(res);
5764
+ if (!raw || raw.ok !== true || !Array.isArray(raw.choices)) {
5765
+ throw new exports.NeetruError("invalid_response", "ai.chat response missing ok/choices");
5766
+ }
5767
+ return {
5768
+ choices: raw.choices,
5769
+ usage: raw.usage ?? { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },
5770
+ model: raw.model ?? opts.model,
5771
+ provider: raw.provider ?? providerHeader ?? "",
5772
+ usageWarning
5773
+ };
5774
+ },
5775
+ stream(opts) {
5776
+ const body = resolveAiBody(config, opts, true);
5777
+ const responsePromise = aiFetch(config, body, opts.signal, true);
5778
+ const meta = responsePromise.then(readMeta);
5779
+ meta.catch(() => {
5780
+ });
5781
+ async function* iterate() {
5782
+ const res = await responsePromise;
5783
+ const stream = res.body;
5784
+ if (!stream) {
5785
+ throw new exports.NeetruError("invalid_response", "ai.stream: response has no body");
5786
+ }
5787
+ const reader = stream.getReader();
5788
+ const decoder = new TextDecoder();
5789
+ let buffer = "";
5790
+ try {
5791
+ while (true) {
5792
+ const { done, value } = await reader.read();
5793
+ if (done) break;
5794
+ buffer += decoder.decode(value, { stream: true });
5795
+ let sep;
5796
+ while ((sep = buffer.indexOf("\n\n")) !== -1) {
5797
+ const rawEvent = buffer.slice(0, sep);
5798
+ buffer = buffer.slice(sep + 2);
5799
+ const parsed = parseSseData(rawEvent);
5800
+ if (parsed && "done" in parsed) return;
5801
+ if (parsed && "content" in parsed) yield parsed.content;
5802
+ }
5803
+ }
5804
+ const tail = buffer.trim();
5805
+ if (tail) {
5806
+ const parsed = parseSseData(tail);
5807
+ if (parsed && "content" in parsed) yield parsed.content;
5808
+ }
5809
+ } finally {
5810
+ try {
5811
+ reader.releaseLock();
5812
+ } catch {
5813
+ }
5814
+ try {
5815
+ await stream.cancel();
5816
+ } catch {
5817
+ }
5818
+ }
5819
+ }
5820
+ return {
5821
+ meta,
5822
+ [Symbol.asyncIterator]: iterate
5823
+ };
5824
+ }
5825
+ };
5826
+ }
5827
+
5599
5828
  // src/mocks.ts
5600
5829
  init_db_errors();
5601
5830
  init_errors();
@@ -6196,6 +6425,57 @@ var MockDb = class {
6196
6425
  this._store.clear();
6197
6426
  }
6198
6427
  };
6428
+ var MockAi = class {
6429
+ _calls = [];
6430
+ _reply(opts) {
6431
+ const last = [...opts.messages].reverse().find((m) => m.role === "user") ?? opts.messages[opts.messages.length - 1];
6432
+ const content = last?.content ?? "";
6433
+ return content ? `mock-reply: ${content}` : "mock-reply";
6434
+ }
6435
+ async chat(opts) {
6436
+ if (!opts || typeof opts.model !== "string" || opts.model.length === 0) {
6437
+ throw new exports.NeetruError("validation_failed", "ai: model is required");
6438
+ }
6439
+ if (!Array.isArray(opts.messages) || opts.messages.length === 0) {
6440
+ throw new exports.NeetruError("validation_failed", "ai: messages must be a non-empty array");
6441
+ }
6442
+ this._calls.push({ model: opts.model, messages: opts.messages, stream: false });
6443
+ const text = this._reply(opts);
6444
+ const promptTokens = opts.messages.reduce((n, m) => n + (m.content?.length ?? 0), 0);
6445
+ const completionTokens = text.length;
6446
+ return {
6447
+ choices: [{ message: { role: "assistant", content: text }, finish_reason: "stop" }],
6448
+ usage: {
6449
+ prompt_tokens: promptTokens,
6450
+ completion_tokens: completionTokens,
6451
+ total_tokens: promptTokens + completionTokens
6452
+ },
6453
+ model: opts.model,
6454
+ provider: "mock",
6455
+ usageWarning: false
6456
+ };
6457
+ }
6458
+ stream(opts) {
6459
+ if (!opts || typeof opts.model !== "string" || opts.model.length === 0) {
6460
+ throw new exports.NeetruError("validation_failed", "ai: model is required");
6461
+ }
6462
+ if (!Array.isArray(opts.messages) || opts.messages.length === 0) {
6463
+ throw new exports.NeetruError("validation_failed", "ai: messages must be a non-empty array");
6464
+ }
6465
+ this._calls.push({ model: opts.model, messages: opts.messages, stream: true });
6466
+ const text = this._reply(opts);
6467
+ const parts = text.match(/\S+\s*/g) ?? [text];
6468
+ const meta = Promise.resolve({ provider: "mock", usageWarning: false });
6469
+ async function* iterate() {
6470
+ for (const p of parts) yield p;
6471
+ }
6472
+ return { meta, [Symbol.asyncIterator]: iterate };
6473
+ }
6474
+ /** Test helper — histórico de chamadas. */
6475
+ __getCalls() {
6476
+ return this._calls;
6477
+ }
6478
+ };
6199
6479
 
6200
6480
  // src/auth.ts
6201
6481
  function readEnvApiKey() {
@@ -6634,6 +6914,7 @@ function createNeetruClient(config = {}) {
6634
6914
  const db = config.mocks?.db ?? createNeetruDb(resolved, config.db);
6635
6915
  const webhooks = config.mocks?.webhooks ?? (isDev ? new MockWebhooks() : createWebhooksNamespace(resolved));
6636
6916
  const notifications = config.mocks?.notifications ?? (isDev ? new MockNotifications() : createNotificationsNamespace(resolved));
6917
+ const ai = config.mocks?.ai ?? (isDev ? new MockAi() : createAiNamespace(resolved));
6637
6918
  const client = Object.freeze({
6638
6919
  config: resolved,
6639
6920
  auth,
@@ -6645,7 +6926,8 @@ function createNeetruClient(config = {}) {
6645
6926
  db,
6646
6927
  checkout: createCheckoutNamespace(resolved),
6647
6928
  webhooks,
6648
- notifications
6929
+ notifications,
6930
+ ai
6649
6931
  });
6650
6932
  return client;
6651
6933
  }
@@ -6654,10 +6936,11 @@ function createNeetruClient(config = {}) {
6654
6936
  init_errors();
6655
6937
  init_db_errors();
6656
6938
  init_http();
6657
- var VERSION = "3.1.9";
6939
+ var VERSION = "3.1.11";
6658
6940
 
6659
6941
  exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
6660
6942
  exports.DEV_FIXTURE_USER = DEV_FIXTURE_USER;
6943
+ exports.MockAi = MockAi;
6661
6944
  exports.MockAuth = MockAuth;
6662
6945
  exports.MockCheckout = MockCheckout;
6663
6946
  exports.MockDb = MockDb;
@@ -6669,6 +6952,7 @@ exports.MockWebhooks = MockWebhooks;
6669
6952
  exports.NEETRU_SENTINEL_KEY = NEETRU_SENTINEL_KEY;
6670
6953
  exports.VERSION = VERSION;
6671
6954
  exports.checkCoreVersionCompat = checkCoreVersionCompat;
6955
+ exports.createAiNamespace = createAiNamespace;
6672
6956
  exports.createCheckoutNamespace = createCheckoutNamespace;
6673
6957
  exports.createNeetruClient = createNeetruClient;
6674
6958
  exports.createNeetruDb = createNeetruDb;