@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.d.mts +40 -2
- package/dist/index.d.ts +40 -2
- package/dist/index.js +139 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +139 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/dropshipper.test.ts +92 -0
- package/src/dropshipper.ts +209 -0
- package/src/index.ts +1 -1
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
|