@thorprovider/medusa-extended 1.11.2 → 1.11.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/index.mjs CHANGED
@@ -449,6 +449,70 @@ var DropshipperClient = class {
449
449
  body
450
450
  );
451
451
  }
452
+ /**
453
+ * Stream the AI assistant's reply.
454
+ *
455
+ * Unlike `chatAssistant`, this surfaces the model's progress: the backend
456
+ * resolves the intent first and then streams the answer token by token
457
+ * (catalog searches) or returns the full answer in one shot (greetings/other).
458
+ * The response is normalized into a single `ReadableStream<ChatStreamEvent>`
459
+ * so callers can show a live "thinking" label and render text incrementally.
460
+ *
461
+ * `POST /admin/thor/dropshipper/ai/chat`
462
+ */
463
+ async chatAssistantStream(body) {
464
+ const url = `${this.baseUrl}/admin/thor/dropshipper/ai/chat`;
465
+ this.logger.debug("[dropshipper] POST /admin/thor/dropshipper/ai/chat (stream)");
466
+ const init = {
467
+ method: "POST",
468
+ headers: {
469
+ Authorization: `Bearer ${this.token}`,
470
+ "Content-Type": "application/json",
471
+ Accept: "text/event-stream"
472
+ },
473
+ body: JSON.stringify(body)
474
+ };
475
+ let response;
476
+ try {
477
+ response = await fetchBackendWithResilience(url, init);
478
+ } catch (networkError) {
479
+ throw new ProviderAPIError3(
480
+ `[dropshipper] Network error on POST /admin/thor/dropshipper/ai/chat: ${networkError.message}`,
481
+ "NETWORK_ERROR",
482
+ networkError
483
+ );
484
+ }
485
+ if (!response.ok) {
486
+ let message = `HTTP ${response.status}`;
487
+ try {
488
+ const json = await response.json();
489
+ message = json?.message ?? message;
490
+ } catch {
491
+ }
492
+ throw new ProviderAPIError3(
493
+ `[dropshipper] POST /admin/thor/dropshipper/ai/chat failed: ${message}`,
494
+ `DROPSHIPPER_API_${response.status}`,
495
+ response.status
496
+ );
497
+ }
498
+ const contentType = response.headers.get("content-type") ?? "";
499
+ if (contentType.includes("text/event-stream") && response.body) {
500
+ return mapUiMessageStreamToEvents(response.body);
501
+ }
502
+ const data = await response.json();
503
+ return new ReadableStream({
504
+ start(controller) {
505
+ controller.enqueue({ type: "start", intent: data.intent });
506
+ controller.enqueue({ type: "text-delta", delta: data.answer });
507
+ controller.enqueue({
508
+ type: "finish",
509
+ intent: data.intent,
510
+ sources: data.sources ?? []
511
+ });
512
+ controller.close();
513
+ }
514
+ });
515
+ }
452
516
  // -------------------------------------------------------------------------
453
517
  // Notifications
454
518
  // -------------------------------------------------------------------------
@@ -1607,6 +1671,81 @@ var DropshipperClient = class {
1607
1671
  );
1608
1672
  }
1609
1673
  };
1674
+ async function* parseSse(stream) {
1675
+ const reader = stream.getReader();
1676
+ const decoder = new TextDecoder();
1677
+ let buffer = "";
1678
+ try {
1679
+ while (true) {
1680
+ const { done, value } = await reader.read();
1681
+ if (done) break;
1682
+ buffer += decoder.decode(value, { stream: true });
1683
+ const lines = buffer.split(/\r?\n/);
1684
+ buffer = lines.pop() ?? "";
1685
+ for (const line of lines) {
1686
+ const trimmed = line.trim();
1687
+ if (!trimmed.startsWith("data:")) continue;
1688
+ const payload = trimmed.slice(5).trim();
1689
+ if (!payload || payload === "[DONE]") continue;
1690
+ try {
1691
+ yield JSON.parse(payload);
1692
+ } catch {
1693
+ }
1694
+ }
1695
+ }
1696
+ const tail = buffer.trim();
1697
+ if (tail.startsWith("data:")) {
1698
+ const payload = tail.slice(5).trim();
1699
+ if (payload && payload !== "[DONE]") {
1700
+ try {
1701
+ yield JSON.parse(payload);
1702
+ } catch {
1703
+ }
1704
+ }
1705
+ }
1706
+ } finally {
1707
+ reader.releaseLock();
1708
+ }
1709
+ }
1710
+ function mapUiMessageStreamToEvents(stream) {
1711
+ return new ReadableStream({
1712
+ async start(controller) {
1713
+ for await (const raw of parseSse(stream)) {
1714
+ const chunk = raw;
1715
+ switch (chunk.type) {
1716
+ case "start":
1717
+ controller.enqueue({
1718
+ type: "start",
1719
+ intent: chunk.messageMetadata?.intent
1720
+ });
1721
+ break;
1722
+ case "text-delta":
1723
+ if (chunk.delta !== void 0) {
1724
+ controller.enqueue({ type: "text-delta", delta: chunk.delta });
1725
+ }
1726
+ break;
1727
+ case "finish":
1728
+ controller.enqueue({
1729
+ type: "finish",
1730
+ intent: chunk.messageMetadata?.intent ?? "other",
1731
+ sources: chunk.messageMetadata?.sources ?? []
1732
+ });
1733
+ break;
1734
+ case "error":
1735
+ controller.enqueue({
1736
+ type: "error",
1737
+ errorText: chunk.errorText ?? "Error inesperado del asistente."
1738
+ });
1739
+ break;
1740
+ }
1741
+ }
1742
+ controller.close();
1743
+ },
1744
+ cancel() {
1745
+ stream.cancel?.();
1746
+ }
1747
+ });
1748
+ }
1610
1749
  export {
1611
1750
  DropshipperClient,
1612
1751
  MedusaAdminClient