@ergoblockchain/sage-widget 0.2.0 → 0.3.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/react.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { CSSProperties } from 'react';
2
- import { u as SageWidgetOptions, c as SageActivityResponse, l as SagePaymentWidgetOptions } from './types-yv1THHVz.cjs';
3
- export { D as DEFAULT_API_BASE, a as DEFAULT_LIMIT, b as DEFAULT_REFRESH_MS, S as SageActivityEvent, d as SageActivityType, e as SageChatMessage, f as SageChatRole, g as SageChatStreamEvent, h as SageChatStreamResult, i as SageChatTier, j as SagePaymentInstructions, k as SagePaymentPhase, m as SagePaymentWidgetStatus, n as SagePremiumPaymentRequired, o as SagePremiumReason, p as SageQuote, q as SageQuoteResponse, r as SageReceiptBundle, s as SageTenantConfig, t as SageVerifyPaymentResponse } from './types-yv1THHVz.cjs';
2
+ import { y as SageWidgetOptions, c as SageActivityResponse, n as SagePaymentWidgetOptions } from './types-B5V2rsYn.cjs';
3
+ export { D as DEFAULT_API_BASE, a as DEFAULT_LIMIT, b as DEFAULT_REFRESH_MS, S as SageActivityEvent, d as SageActivityType, e as SageChatMessage, f as SageChatRole, g as SageChatStreamEvent, h as SageChatStreamResult, i as SageChatTier, j as SagePaymentInstructions, k as SagePaymentIntent, l as SagePaymentNetwork, m as SagePaymentPhase, o as SagePaymentWidgetStatus, p as SagePremiumPaymentRequired, q as SagePremiumReason, r as SageQuote, s as SageQuoteResponse, t as SageReceiptBundle, u as SageTenantConfig, v as SageVerifyPaymentResponse, w as SageWalletLaunchResult, x as SageWalletLauncher } from './types-B5V2rsYn.cjs';
4
4
 
5
5
  /**
6
6
  * <SageActivityFeed /> — drop-in React component rendering Sage's live
package/dist/react.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { CSSProperties } from 'react';
2
- import { u as SageWidgetOptions, c as SageActivityResponse, l as SagePaymentWidgetOptions } from './types-yv1THHVz.js';
3
- export { D as DEFAULT_API_BASE, a as DEFAULT_LIMIT, b as DEFAULT_REFRESH_MS, S as SageActivityEvent, d as SageActivityType, e as SageChatMessage, f as SageChatRole, g as SageChatStreamEvent, h as SageChatStreamResult, i as SageChatTier, j as SagePaymentInstructions, k as SagePaymentPhase, m as SagePaymentWidgetStatus, n as SagePremiumPaymentRequired, o as SagePremiumReason, p as SageQuote, q as SageQuoteResponse, r as SageReceiptBundle, s as SageTenantConfig, t as SageVerifyPaymentResponse } from './types-yv1THHVz.js';
2
+ import { y as SageWidgetOptions, c as SageActivityResponse, n as SagePaymentWidgetOptions } from './types-B5V2rsYn.js';
3
+ export { D as DEFAULT_API_BASE, a as DEFAULT_LIMIT, b as DEFAULT_REFRESH_MS, S as SageActivityEvent, d as SageActivityType, e as SageChatMessage, f as SageChatRole, g as SageChatStreamEvent, h as SageChatStreamResult, i as SageChatTier, j as SagePaymentInstructions, k as SagePaymentIntent, l as SagePaymentNetwork, m as SagePaymentPhase, o as SagePaymentWidgetStatus, p as SagePremiumPaymentRequired, q as SagePremiumReason, r as SageQuote, s as SageQuoteResponse, t as SageReceiptBundle, u as SageTenantConfig, v as SageVerifyPaymentResponse, w as SageWalletLaunchResult, x as SageWalletLauncher } from './types-B5V2rsYn.js';
4
4
 
5
5
  /**
6
6
  * <SageActivityFeed /> — drop-in React component rendering Sage's live
package/dist/react.js CHANGED
@@ -57,6 +57,28 @@ async function fetchSageReceipt(id, opts = {}) {
57
57
  if (!res.ok) throw new Error(readError(body, `sage receipt ${res.status}`));
58
58
  return body;
59
59
  }
60
+ function createSagePaymentIntent(opts) {
61
+ const base = trimSlash(opts.apiBase ?? DEFAULT_API_BASE);
62
+ return {
63
+ type: "sage.payment_intent.v1",
64
+ network: opts.network ?? "ergo-testnet",
65
+ createdAt: opts.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
66
+ question: opts.question,
67
+ ...opts.tenant?.id || opts.tenant?.label ? { tenant: { id: opts.tenant.id, label: opts.tenant.label } } : {},
68
+ quote: opts.quote,
69
+ amountErg: opts.quote.price,
70
+ receiverAddress: opts.quote.receiverAddress,
71
+ reserveBoxId: opts.quote.reserveBoxId,
72
+ taskHash: opts.quote.taskHash,
73
+ expiresAt: opts.quote.expiresAt,
74
+ deadline: opts.quote.deadline,
75
+ verifyEndpoint: `${base}/api/sage/verify-payment`,
76
+ receiptEndpointTemplate: `${base}/api/sage/receipt/{receiptId}`
77
+ };
78
+ }
79
+ function serializeSagePaymentIntent(intent) {
80
+ return JSON.stringify(intent, null, 2);
81
+ }
60
82
  async function streamSageChat(opts) {
61
83
  const res = await fetch(`${apiBase(opts)}/api/sage/chat`, {
62
84
  method: "POST",
@@ -490,6 +512,8 @@ function SagePaymentWidget(props) {
490
512
  initialMessages = [],
491
513
  placeholder = "Ask Sage about Ergo or agent payments...",
492
514
  paymentInstructions,
515
+ showPaymentIntent = true,
516
+ testnetWarning = "Testnet proof flow. The widget never signs funds; connect your own reviewed wallet layer before handling real value.",
493
517
  className,
494
518
  style,
495
519
  title = "Ask Sage"
@@ -498,6 +522,7 @@ function SagePaymentWidget(props) {
498
522
  const [input, setInput] = useState("");
499
523
  const [phase, setPhase] = useState("idle");
500
524
  const [quoteResponse, setQuoteResponse] = useState(null);
525
+ const [paymentIntent, setPaymentIntent] = useState(null);
501
526
  const [activeQuestion, setActiveQuestion] = useState("");
502
527
  const [noteBoxId, setNoteBoxId] = useState("");
503
528
  const [receipt, setReceipt] = useState(null);
@@ -526,6 +551,7 @@ function SagePaymentWidget(props) {
526
551
  setReceipt(null);
527
552
  setReceiptBundle(null);
528
553
  setQuoteResponse(null);
554
+ setPaymentIntent(null);
529
555
  setActiveQuestion(question);
530
556
  setNoteBoxId("");
531
557
  setTier(null);
@@ -539,8 +565,15 @@ function SagePaymentWidget(props) {
539
565
  props.onQuote?.(quote2);
540
566
  if (quote2.premium) {
541
567
  if (!quote2.quote) throw new Error("Sage marked this question premium but did not return a quote.");
568
+ const intent = createSagePaymentIntent({
569
+ ...apiOpts,
570
+ question,
571
+ quote: quote2.quote
572
+ });
573
+ setPaymentIntent(intent);
542
574
  setQuoteResponse(quote2);
543
- transition("payment_required", { quote: quote2.quote });
575
+ props.onPaymentIntent?.(intent);
576
+ transition("payment_required", { quote: quote2.quote, paymentIntent: intent });
544
577
  return;
545
578
  }
546
579
  await streamAnswer(nextMessages, void 0, question);
@@ -571,14 +604,15 @@ function SagePaymentWidget(props) {
571
604
  setReceipt(verified);
572
605
  props.onReceipt?.(verified);
573
606
  setQuoteResponse(null);
607
+ setPaymentIntent(null);
574
608
  setNoteBoxId("");
575
- transition("streaming", { quote: null, receipt: verified });
609
+ transition("streaming", { quote: null, paymentIntent: null, receipt: verified });
576
610
  try {
577
611
  const bundle = await fetchSageReceipt(verified.receiptId, apiOpts);
578
612
  if (!mountedRef.current) return;
579
613
  setReceiptBundle(bundle);
580
614
  props.onReceiptBundle?.(bundle);
581
- emitStatus("streaming", { quote: null, receipt: verified, receiptBundle: bundle });
615
+ emitStatus("streaming", { quote: null, paymentIntent: null, receipt: verified, receiptBundle: bundle });
582
616
  } catch (bundleErr) {
583
617
  props.onError?.(bundleErr);
584
618
  }
@@ -622,7 +656,10 @@ function SagePaymentWidget(props) {
622
656
  props.onQuote?.(quote2);
623
657
  setQuoteResponse(quote2);
624
658
  setActiveQuestion(question);
625
- transition("payment_required", { quote: quote2.quote ?? null });
659
+ const intent = quote2.quote ? createSagePaymentIntent({ ...apiOpts, question, quote: quote2.quote }) : null;
660
+ setPaymentIntent(intent);
661
+ if (intent) props.onPaymentIntent?.(intent);
662
+ transition("payment_required", { quote: quote2.quote ?? null, paymentIntent: intent });
626
663
  return;
627
664
  }
628
665
  throw new Error(result.error ?? "Sage chat failed.");
@@ -651,6 +688,7 @@ function SagePaymentWidget(props) {
651
688
  phase: nextPhase,
652
689
  tier: has("tier") ? overrides.tier ?? null : tier,
653
690
  quote: has("quote") ? overrides.quote ?? null : quoteResponse?.quote ?? null,
691
+ paymentIntent: has("paymentIntent") ? overrides.paymentIntent ?? null : paymentIntent,
654
692
  receipt: has("receipt") ? overrides.receipt ?? null : receipt,
655
693
  receiptBundle: has("receiptBundle") ? overrides.receiptBundle ?? null : receiptBundle,
656
694
  error: has("error") ? overrides.error ?? null : error,
@@ -660,6 +698,23 @@ function SagePaymentWidget(props) {
660
698
  }
661
699
  const quote = quoteResponse?.quote;
662
700
  const showPaymentPanel = quote && !receipt;
701
+ async function copyPaymentIntent() {
702
+ if (!paymentIntent) return;
703
+ await copyText(serializeSagePaymentIntent(paymentIntent));
704
+ }
705
+ async function launchWallet() {
706
+ if (!paymentIntent || !props.walletLauncher || busy) return;
707
+ setError(null);
708
+ try {
709
+ const result = await props.walletLauncher(paymentIntent);
710
+ if (result?.ok === false) {
711
+ throw new Error(result.error ?? "Wallet flow did not produce a Note.");
712
+ }
713
+ if (result?.noteBoxId) setNoteBoxId(result.noteBoxId);
714
+ } catch (err) {
715
+ fail(err, false);
716
+ }
717
+ }
663
718
  return /* @__PURE__ */ jsxs("section", { className, style: { ...rootStyle2, ...style }, children: [
664
719
  /* @__PURE__ */ jsxs("header", { style: headerStyle2, children: [
665
720
  /* @__PURE__ */ jsxs("div", { children: [
@@ -695,6 +750,24 @@ function SagePaymentWidget(props) {
695
750
  /* @__PURE__ */ jsx(Field, { label: "Receiver", value: quote.receiverAddress, copy: true }),
696
751
  /* @__PURE__ */ jsx(Field, { label: "Reserve box", value: quote.reserveBoxId, copy: true }),
697
752
  /* @__PURE__ */ jsx(Field, { label: "Task hash", value: quote.taskHash, copy: true }),
753
+ testnetWarning ? /* @__PURE__ */ jsx("div", { style: warningStyle, children: testnetWarning }) : null,
754
+ showPaymentIntent && paymentIntent ? /* @__PURE__ */ jsxs("div", { style: intentStyle, children: [
755
+ /* @__PURE__ */ jsxs("div", { style: intentHeaderStyle, children: [
756
+ /* @__PURE__ */ jsx("strong", { children: "Payment intent" }),
757
+ /* @__PURE__ */ jsx("button", { type: "button", style: copyButtonStyle, onClick: copyPaymentIntent, children: "Copy JSON" })
758
+ ] }),
759
+ /* @__PURE__ */ jsx("code", { style: intentCodeStyle, children: serializeSagePaymentIntent(paymentIntent) })
760
+ ] }) : null,
761
+ props.walletLauncher && paymentIntent ? /* @__PURE__ */ jsx(
762
+ "button",
763
+ {
764
+ type: "button",
765
+ onClick: launchWallet,
766
+ disabled: busy,
767
+ style: secondaryButtonStyle,
768
+ children: paymentInstructions?.walletLauncherLabel ?? "Open wallet flow"
769
+ }
770
+ ) : null,
698
771
  /* @__PURE__ */ jsxs("label", { style: labelStyle2, children: [
699
772
  paymentInstructions?.noteBoxLabel ?? "Note box id",
700
773
  /* @__PURE__ */ jsx(
@@ -750,9 +823,9 @@ function Field({ label, value, copy = false }) {
750
823
  copy ? /* @__PURE__ */ jsx("button", { type: "button", style: copyButtonStyle, onClick: () => copyText(value), children: "Copy" }) : null
751
824
  ] });
752
825
  }
753
- function copyText(value) {
826
+ async function copyText(value) {
754
827
  if (typeof navigator !== "undefined" && navigator.clipboard) {
755
- void navigator.clipboard.writeText(value);
828
+ await navigator.clipboard.writeText(value);
756
829
  }
757
830
  }
758
831
  function shortId(value) {
@@ -925,6 +998,50 @@ var primaryButtonStyle = {
925
998
  ...sendButtonStyle,
926
999
  padding: "10px 12px"
927
1000
  };
1001
+ var secondaryButtonStyle = {
1002
+ border: "1px solid rgba(103,232,249,.28)",
1003
+ background: "rgba(103,232,249,.08)",
1004
+ color: "#cffafe",
1005
+ borderRadius: 6,
1006
+ padding: "10px 12px",
1007
+ fontWeight: 800,
1008
+ cursor: "pointer"
1009
+ };
1010
+ var warningStyle = {
1011
+ color: "#fde68a",
1012
+ background: "rgba(245,158,11,.1)",
1013
+ border: "1px solid rgba(245,158,11,.24)",
1014
+ borderRadius: 6,
1015
+ padding: "8px 9px",
1016
+ fontSize: 12,
1017
+ lineHeight: 1.45
1018
+ };
1019
+ var intentStyle = {
1020
+ border: "1px solid rgba(255,255,255,.12)",
1021
+ background: "rgba(255,255,255,.04)",
1022
+ borderRadius: 6,
1023
+ padding: 10,
1024
+ display: "grid",
1025
+ gap: 8
1026
+ };
1027
+ var intentHeaderStyle = {
1028
+ display: "flex",
1029
+ justifyContent: "space-between",
1030
+ alignItems: "center",
1031
+ gap: 8,
1032
+ color: "#e2e8f0",
1033
+ fontSize: 12
1034
+ };
1035
+ var intentCodeStyle = {
1036
+ display: "block",
1037
+ maxHeight: 130,
1038
+ overflow: "auto",
1039
+ whiteSpace: "pre-wrap",
1040
+ wordBreak: "break-word",
1041
+ color: "#cbd5e1",
1042
+ fontSize: 10,
1043
+ lineHeight: 1.45
1044
+ };
928
1045
  var receiptStyle = {
929
1046
  display: "inline-flex",
930
1047
  color: "#67e8f9",