@invergent/website-widget 2.7.8 → 2.8.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/ui.cjs CHANGED
@@ -16,6 +16,8 @@ var PATH_BOOTSTRAP = "/v1/website/sessions";
16
16
  var PATH_MESSAGES = (sessionId) => `/v1/website/sessions/${sessionId}/messages`;
17
17
  var PATH_EVENTS = (sessionId, after) => `/v1/website/sessions/${sessionId}/events?after=${after}`;
18
18
  var PATH_END = (sessionId) => `/v1/website/sessions/${sessionId}/end`;
19
+ var PATH_PAIRING = (key) => `/api/widget/p/${encodeURIComponent(key)}`;
20
+ var DEFAULT_PAIRING_BASE = "https://api.surogate.ai";
19
21
  var SURG_EVENT = {
20
22
  USER_MESSAGE: "user.message",
21
23
  LLM_REQUEST: "llm.request",
@@ -81,6 +83,34 @@ var SurogatesNetworkError = class extends SurogatesError {
81
83
  };
82
84
 
83
85
  // src/protocol.ts
86
+ async function resolvePairing(pairingBase, publishableKey, doFetchImpl = fetch) {
87
+ const url = pairingBase.replace(/\/+$/, "") + PATH_PAIRING(publishableKey);
88
+ let response;
89
+ try {
90
+ response = await doFetchImpl(url, { method: "GET" });
91
+ } catch (cause) {
92
+ throw new SurogatesNetworkError("Widget pairing request failed", { cause });
93
+ }
94
+ if (!response.ok) {
95
+ throw new SurogatesAuthError("Unknown or inactive widget key", {
96
+ status: response.status
97
+ });
98
+ }
99
+ let body;
100
+ try {
101
+ body = await response.json();
102
+ } catch (cause) {
103
+ throw new SurogatesProtocolError("Pairing returned a non-JSON body", {
104
+ cause
105
+ });
106
+ }
107
+ if (typeof body?.agent_id !== "string" || typeof body?.api_web_url !== "string") {
108
+ throw new SurogatesProtocolError(
109
+ "Pairing response missing agent_id / api_web_url"
110
+ );
111
+ }
112
+ return { agentId: body.agent_id, apiWebUrl: body.api_web_url };
113
+ }
84
114
  function withAgentId(path, agentId) {
85
115
  if (!agentId) return path;
86
116
  const sep = path.includes("?") ? "&" : "?";
@@ -795,6 +825,7 @@ var WIDGET_STYLES = `
795
825
  border-radius: 6px;
796
826
  }
797
827
  .surg-close:hover { opacity: 1; background: rgba(255, 255, 255, 0.18); }
828
+ .surg-close svg { width: 18px; height: 18px; }
798
829
 
799
830
  .surg-messages {
800
831
  flex: 1;
@@ -912,6 +943,8 @@ var WIDGET_STYLES = `
912
943
  padding: 0 0 8px;
913
944
  background: #ffffff;
914
945
  }
946
+ .surg-powered a { color: inherit; font-weight: 500; text-decoration: none; }
947
+ .surg-powered a:hover { text-decoration: underline; }
915
948
  `;
916
949
 
917
950
  // src/ui/markdown.ts
@@ -1149,7 +1182,11 @@ function Widget({ agent, config, registerOpenControl, onOpenChange }) {
1149
1182
  ),
1150
1183
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", class: "surg-send", "aria-label": "Send", disabled: running || !input.trim(), onClick: send, children: ICON_SEND })
1151
1184
  ] }),
1152
- /* @__PURE__ */ jsxRuntime.jsx("div", { class: "surg-powered", children: "Powered by Surogate" })
1185
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { class: "surg-powered", children: [
1186
+ "Powered by",
1187
+ " ",
1188
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: "https://surogate.ai/", target: "_blank", rel: "noopener noreferrer", children: "Surogate" })
1189
+ ] })
1153
1190
  ] });
1154
1191
  }
1155
1192
  var DEFAULT_ACCENT = "#4f46e5";
@@ -1163,6 +1200,21 @@ function accentForeground(hex) {
1163
1200
  const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
1164
1201
  return luminance > 0.62 ? "#0f172a" : "#ffffff";
1165
1202
  }
1203
+ async function mountWithPairing(config) {
1204
+ if (config?.apiUrl) {
1205
+ return mount(config);
1206
+ }
1207
+ if (!config?.publishableKey) {
1208
+ throw new Error(
1209
+ 'SurogatesWidget.mountWithPairing: "publishableKey" is required.'
1210
+ );
1211
+ }
1212
+ const { agentId, apiWebUrl } = await resolvePairing(
1213
+ config.pairingUrl ?? DEFAULT_PAIRING_BASE,
1214
+ config.publishableKey
1215
+ );
1216
+ return mount({ ...config, apiUrl: apiWebUrl, agentId });
1217
+ }
1166
1218
  function mount(config) {
1167
1219
  if (!config || !config.apiUrl || !config.publishableKey) {
1168
1220
  throw new Error(
@@ -1250,5 +1302,6 @@ function mount(config) {
1250
1302
  }
1251
1303
 
1252
1304
  exports.mount = mount;
1305
+ exports.mountWithPairing = mountWithPairing;
1253
1306
  //# sourceMappingURL=ui.cjs.map
1254
1307
  //# sourceMappingURL=ui.cjs.map