@helpai/elements 0.27.0 → 0.28.1
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/configurator.mjs +6 -6
- package/elements-web-component.esm.js +6 -6
- package/elements-web-component.esm.js.map +3 -3
- package/elements.cjs.js +27 -27
- package/elements.cjs.js.map +3 -3
- package/elements.esm.js +27 -27
- package/elements.esm.js.map +3 -3
- package/elements.js +6 -6
- package/elements.js.map +3 -3
- package/index.d.ts +12 -12
- package/index.mjs +48 -26
- package/package.json +1 -1
- package/schema.d.ts +1 -1
- package/schema.json +7 -7
- package/schema.mjs +6 -6
- package/web-component.mjs +48 -26
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, H as HandshakeResponse, L as Link, S as ServerConfig, b as SiteConfig, W as WidgetConfig, c as WidgetConfigPartial, d as WidgetSettings, e as WidgetSettingsPartial } from './deployment-
|
|
1
|
+
export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, H as HandshakeResponse, L as Link, S as ServerConfig, b as SiteConfig, W as WidgetConfig, c as WidgetConfigPartial, d as WidgetSettings, e as WidgetSettingsPartial } from './deployment-E-Jyc0nF.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -896,7 +896,7 @@ interface PageContext {
|
|
|
896
896
|
/**
|
|
897
897
|
* Override the HTTP endpoints the widget calls. `upload` / `transcribe`
|
|
898
898
|
* paths are appended to the agent base (`${baseUrl}/api/agent`);
|
|
899
|
-
* `submitForm` is appended to the data base (`
|
|
899
|
+
* `submitForm` is appended to the data base (`dataApiBaseUrl`). Absolute URLs
|
|
900
900
|
* also work (useful when the upload endpoint lives on a different origin
|
|
901
901
|
* like a CDN presign service).
|
|
902
902
|
*/
|
|
@@ -939,7 +939,7 @@ interface TrackingOptions {
|
|
|
939
939
|
*/
|
|
940
940
|
enabled?: boolean;
|
|
941
941
|
/**
|
|
942
|
-
* Pixel collector URL. Default: `${
|
|
942
|
+
* Pixel collector URL. Default: `${dataApiBaseUrl}/pai/elements-px.gif`
|
|
943
943
|
* (e.g. `https://help.ai/api/data/pai/elements-px.gif`).
|
|
944
944
|
*/
|
|
945
945
|
endpoint?: string;
|
|
@@ -1016,22 +1016,22 @@ interface ChatWidgetOptions {
|
|
|
1016
1016
|
* Agent-API base (no trailing slash) — set it when the
|
|
1017
1017
|
* `module-help-ai-agent-api` service is reached DIRECTLY (a standalone
|
|
1018
1018
|
* local module, e.g. `http://localhost:3087`) instead of through the
|
|
1019
|
-
* edge. Routes attach as-is (`${
|
|
1019
|
+
* edge. Routes attach as-is (`${agentApiBaseUrl}/pai/handshake`).
|
|
1020
1020
|
* Precedence: this option > derived from the main origin
|
|
1021
1021
|
* (`${baseUrl}/api/agent`). Not server-pushable — the handshake already
|
|
1022
1022
|
* travelled over it.
|
|
1023
1023
|
*/
|
|
1024
|
-
|
|
1024
|
+
agentApiBaseUrl?: string;
|
|
1025
1025
|
/**
|
|
1026
1026
|
* Data-API base (no trailing slash) — the `module-help-ai-data-api`
|
|
1027
1027
|
* service serving content, form definitions, and form submissions at
|
|
1028
1028
|
* root-level paths (`/content`, `/forms`, `/activity`, `/submit-form`).
|
|
1029
1029
|
* Set it for a standalone local module (e.g. `http://localhost:3106`).
|
|
1030
|
-
* Precedence: this option > server-pushed `config.
|
|
1030
|
+
* Precedence: this option > server-pushed `config.dataApiBaseUrl` > derived
|
|
1031
1031
|
* from the main origin (`${baseUrl}/api/data`, e.g.
|
|
1032
1032
|
* `https://help.ai/api/data`).
|
|
1033
1033
|
*/
|
|
1034
|
-
|
|
1034
|
+
dataApiBaseUrl?: string;
|
|
1035
1035
|
/** Host-asserted, informational end-user context (untrusted; not auth). */
|
|
1036
1036
|
userContext?: UserContext;
|
|
1037
1037
|
/** Host-asserted, informational page/visit context (untrusted; `area`, url, …). */
|
|
@@ -1086,10 +1086,10 @@ interface ResolvedOptions {
|
|
|
1086
1086
|
publicKey?: string;
|
|
1087
1087
|
aiAgentDeploymentId?: string;
|
|
1088
1088
|
baseUrl: string;
|
|
1089
|
-
/** Resolved agent-API base — see {@link ChatWidgetOptions.
|
|
1090
|
-
|
|
1091
|
-
/** Resolved data-API base — see {@link ChatWidgetOptions.
|
|
1092
|
-
|
|
1089
|
+
/** Resolved agent-API base — see {@link ChatWidgetOptions.agentApiBaseUrl}. */
|
|
1090
|
+
agentApiBaseUrl: string;
|
|
1091
|
+
/** Resolved data-API base — see {@link ChatWidgetOptions.dataApiBaseUrl}. */
|
|
1092
|
+
dataApiBaseUrl: string;
|
|
1093
1093
|
userContext?: UserContext;
|
|
1094
1094
|
pageContext?: PageContext;
|
|
1095
1095
|
position: Position;
|
|
@@ -1188,7 +1188,7 @@ interface ResolvedOptions {
|
|
|
1188
1188
|
*/
|
|
1189
1189
|
interface ServerConfig {
|
|
1190
1190
|
/** Data-API base override — adopted only when the host didn't set one. */
|
|
1191
|
-
|
|
1191
|
+
dataApiBaseUrl?: string;
|
|
1192
1192
|
presentation?: PresentationOptions;
|
|
1193
1193
|
behavior?: BehaviorOptions;
|
|
1194
1194
|
theme?: ThemePreference | ThemeOverrides;
|
package/index.mjs
CHANGED
|
@@ -525,15 +525,15 @@ function resolveOptions(rawOpts) {
|
|
|
525
525
|
const locale = i18n.locale ?? resolveDefaultLocale(i18n.defaultLocale);
|
|
526
526
|
const availableLocales = i18n.availableLocales ?? [locale];
|
|
527
527
|
const baseUrl = (opts.baseUrl ?? BRAND.defaultBaseUrl).replace(/\/$/, "");
|
|
528
|
-
const
|
|
529
|
-
const
|
|
528
|
+
const agentApiBaseUrl = (opts.agentApiBaseUrl ?? `${baseUrl}/api/agent`).replace(/\/$/, "");
|
|
529
|
+
const dataApiBaseUrl = (opts.dataApiBaseUrl ?? `${baseUrl}/api/data`).replace(/\/$/, "");
|
|
530
530
|
return {
|
|
531
531
|
widgetId: opts.widgetId ?? "default",
|
|
532
532
|
publicKey: opts.publicKey,
|
|
533
533
|
aiAgentDeploymentId: opts.aiAgentDeploymentId,
|
|
534
534
|
baseUrl,
|
|
535
|
-
|
|
536
|
-
|
|
535
|
+
agentApiBaseUrl,
|
|
536
|
+
dataApiBaseUrl,
|
|
537
537
|
userContext: sanitizeUserContext(opts.userContext),
|
|
538
538
|
pageContext: sanitizePageContext(opts.pageContext),
|
|
539
539
|
position: presentation.position ?? "bottom-right",
|
|
@@ -578,7 +578,7 @@ function resolveOptions(rawOpts) {
|
|
|
578
578
|
poweredBy: resolvePoweredBy(footer.poweredBy),
|
|
579
579
|
composer: resolveComposer(opts.composer),
|
|
580
580
|
modules: resolveModules(opts.modules),
|
|
581
|
-
tracking: resolveTracking(opts.tracking,
|
|
581
|
+
tracking: resolveTracking(opts.tracking, dataApiBaseUrl),
|
|
582
582
|
storage: opts.storage ?? defaultStorage,
|
|
583
583
|
onMessage: opts.onMessage,
|
|
584
584
|
onOpen: opts.onOpen,
|
|
@@ -611,13 +611,13 @@ function resolveHaptics(overrides) {
|
|
|
611
611
|
events: overrides?.events
|
|
612
612
|
};
|
|
613
613
|
}
|
|
614
|
-
function resolveTracking(overrides,
|
|
614
|
+
function resolveTracking(overrides, dataApiBaseUrl) {
|
|
615
615
|
const sampleRate = overrides?.sampleRate ?? DEFAULT_TRACKING.sampleRate;
|
|
616
616
|
return {
|
|
617
617
|
enabled: overrides?.enabled ?? DEFAULT_TRACKING.enabled,
|
|
618
|
-
// The collector rides the data module — `${
|
|
618
|
+
// The collector rides the data module — `${dataApiBaseUrl}/pai/elements-px.gif`
|
|
619
619
|
// (e.g. `https://help.ai/api/data/pai/elements-px.gif`).
|
|
620
|
-
endpoint: overrides?.endpoint ?? `${
|
|
620
|
+
endpoint: overrides?.endpoint ?? `${dataApiBaseUrl}/pai/elements-px.gif`,
|
|
621
621
|
// Clamp instead of reject — a malformed rate must never turn a
|
|
622
622
|
// disabled tracker on or crash resolve (no Zod on the IIFE path).
|
|
623
623
|
sampleRate: Math.min(1, Math.max(0, Number.isFinite(sampleRate) ? sampleRate : 1)),
|
|
@@ -786,7 +786,8 @@ function mergeServerConfig(user, server) {
|
|
|
786
786
|
out[key] = mergeLeaves(sv, uv);
|
|
787
787
|
}
|
|
788
788
|
if (server.modules !== void 0 && user.modules === void 0) out.modules = server.modules;
|
|
789
|
-
if (server.
|
|
789
|
+
if (server.dataApiBaseUrl !== void 0 && user.dataApiBaseUrl === void 0)
|
|
790
|
+
out.dataApiBaseUrl = server.dataApiBaseUrl;
|
|
790
791
|
const userI18n = user.i18n;
|
|
791
792
|
const serverI18n = server.i18n;
|
|
792
793
|
if (userI18n || serverI18n) {
|
|
@@ -846,8 +847,8 @@ var EMBED_SCALAR_ATTRS = [
|
|
|
846
847
|
["public-key", "publicKey"],
|
|
847
848
|
["ai-agent-deployment-id", "aiAgentDeploymentId"],
|
|
848
849
|
["base-url", "baseUrl"],
|
|
849
|
-
["agent-base-url", "
|
|
850
|
-
["data-base-url", "
|
|
850
|
+
["agent-api-base-url", "agentApiBaseUrl"],
|
|
851
|
+
["data-api-base-url", "dataApiBaseUrl"],
|
|
851
852
|
["theme", "theme", (v) => v]
|
|
852
853
|
];
|
|
853
854
|
var PRESENTATION_ATTRS = [
|
|
@@ -1283,7 +1284,7 @@ var DEFAULT_PATHS = {
|
|
|
1283
1284
|
* on the client; a failure just leaves the badge until the next sync.
|
|
1284
1285
|
*/
|
|
1285
1286
|
markRead: "/pai/mark-read",
|
|
1286
|
-
// ── Data API (module-help-ai-data-api, via `
|
|
1287
|
+
// ── Data API (module-help-ai-data-api, via `dataApiBaseUrl`) ─────────
|
|
1287
1288
|
/**
|
|
1288
1289
|
* The data module's one ACTIVATION read. `GET
|
|
1289
1290
|
* /pai/bootstrap?visitorId=…&conversationId=…` →
|
|
@@ -1380,6 +1381,7 @@ function messageToWireParts(m) {
|
|
|
1380
1381
|
var log4 = logger.scope("transport");
|
|
1381
1382
|
var MAX_RESUME_ATTEMPTS = 3;
|
|
1382
1383
|
var RESUME_BACKOFF_MS = 400;
|
|
1384
|
+
var CONTENT_CACHE_TTL_MS = 6e4;
|
|
1383
1385
|
var MAX_REQUEST_RETRIES = 3;
|
|
1384
1386
|
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
|
|
1385
1387
|
function backoffMs(attempt) {
|
|
@@ -1418,6 +1420,20 @@ var AgentTransport = class {
|
|
|
1418
1420
|
// always sees the visitor's latest context as they navigate.
|
|
1419
1421
|
__publicField(this, "userContext");
|
|
1420
1422
|
__publicField(this, "pageContext");
|
|
1423
|
+
// ---- Data API (content / forms — module-help-ai-data-api) --------------
|
|
1424
|
+
//
|
|
1425
|
+
// The DATA surfaces live on `dataApiBaseUrl` (default `${baseUrl}/api/data`)
|
|
1426
|
+
// under the module's `/pai/*` group — same auth headers + envelope, same
|
|
1427
|
+
// retry behavior. One endpoint for every content surface (Home / Help /
|
|
1428
|
+
// News / docs); callers pass filters; a thrown StreamError (e.g. 404 on an
|
|
1429
|
+
// older backend) is treated as "no content" by the module and the tab
|
|
1430
|
+
// degrades gracefully.
|
|
1431
|
+
// Per-query content cache: published content barely changes mid-visit, but
|
|
1432
|
+
// every tab switch remounts its module and re-asks. Entries hold the
|
|
1433
|
+
// REQUEST PROMISE (concurrent identical queries share one network call)
|
|
1434
|
+
// and serve repeats for CONTENT_CACHE_TTL_MS; failures are evicted so the
|
|
1435
|
+
// next ask retries.
|
|
1436
|
+
__publicField(this, "contentCache", /* @__PURE__ */ new Map());
|
|
1421
1437
|
}
|
|
1422
1438
|
// ---- Public API -------------------------------------------------------
|
|
1423
1439
|
/**
|
|
@@ -1574,16 +1590,22 @@ var AgentTransport = class {
|
|
|
1574
1590
|
log4.debug("markRead failed (non-fatal)", { err });
|
|
1575
1591
|
}
|
|
1576
1592
|
}
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1593
|
+
/** Fetch content rows by filter. `GET /pai/content` (data-API), TTL-cached. */
|
|
1594
|
+
listContent(query = {}) {
|
|
1595
|
+
const key = JSON.stringify(query, Object.keys(query).toSorted());
|
|
1596
|
+
const cached = this.contentCache.get(key);
|
|
1597
|
+
if (cached && Date.now() - cached.at < CONTENT_CACHE_TTL_MS) {
|
|
1598
|
+
log4.debug("listContent \u2192 cache", query);
|
|
1599
|
+
return cached.result;
|
|
1600
|
+
}
|
|
1601
|
+
const result = this.fetchContent(query).catch((err) => {
|
|
1602
|
+
this.contentCache.delete(key);
|
|
1603
|
+
throw err;
|
|
1604
|
+
});
|
|
1605
|
+
this.contentCache.set(key, { at: Date.now(), result });
|
|
1606
|
+
return result;
|
|
1607
|
+
}
|
|
1608
|
+
async fetchContent(query) {
|
|
1587
1609
|
const url = new URL(this.dataUrl(DEFAULT_PATHS.content));
|
|
1588
1610
|
for (const [key, value] of Object.entries(query)) {
|
|
1589
1611
|
if (value === void 0) continue;
|
|
@@ -1889,7 +1911,7 @@ var AgentTransport = class {
|
|
|
1889
1911
|
*/
|
|
1890
1912
|
url(pathOrUrl) {
|
|
1891
1913
|
if (/^https?:\/\//i.test(pathOrUrl)) return pathOrUrl;
|
|
1892
|
-
return `${this.opts.
|
|
1914
|
+
return `${this.opts.agentApiBaseUrl}${pathOrUrl}`;
|
|
1893
1915
|
}
|
|
1894
1916
|
/**
|
|
1895
1917
|
* Data-API variant of {@link url} — resolves a root-level path (content /
|
|
@@ -1899,7 +1921,7 @@ var AgentTransport = class {
|
|
|
1899
1921
|
*/
|
|
1900
1922
|
dataUrl(pathOrUrl) {
|
|
1901
1923
|
if (/^https?:\/\//i.test(pathOrUrl)) return pathOrUrl;
|
|
1902
|
-
return `${this.opts.
|
|
1924
|
+
return `${this.opts.dataApiBaseUrl}${pathOrUrl}`;
|
|
1903
1925
|
}
|
|
1904
1926
|
get fetchImpl() {
|
|
1905
1927
|
return this.opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
@@ -6465,8 +6487,8 @@ function App({ options, hostElement, bus }) {
|
|
|
6465
6487
|
const [formContext, setFormContext] = useState13({});
|
|
6466
6488
|
const [transport] = useState13(
|
|
6467
6489
|
() => new AgentTransport({
|
|
6468
|
-
|
|
6469
|
-
|
|
6490
|
+
agentApiBaseUrl: options.agentApiBaseUrl,
|
|
6491
|
+
dataApiBaseUrl: options.dataApiBaseUrl,
|
|
6470
6492
|
auth: createAuth({
|
|
6471
6493
|
publicKey: options.publicKey,
|
|
6472
6494
|
aiAgentDeploymentId: options.aiAgentDeploymentId,
|
package/package.json
CHANGED
package/schema.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, E as Endpoints, H as HandshakeResponse, L as Link, P as PAGE_AREA_SUGGESTIONS, f as PageContext, S as ServerConfig, b as SiteConfig, U as UserContext, W as WidgetConfig, c as WidgetConfigPartial, d as WidgetSettings, e as WidgetSettingsPartial, g as assetSchema, h as blocksConfigSchema, i as connectionConfigPartialSchema, j as connectionConfigSchema, k as cssColorSchema, l as cssLengthSchema, m as endpointsSchema, n as handshakeResponseSchema, o as linkSchema, p as localeSchema, q as pageContextSchema, s as serverConfigSchema, r as siteConfigSchema, u as userContextSchema, t as uuid7Schema, w as widgetConfigPartialSchema, v as widgetConfigSchema, x as widgetSettingsPartialSchema, y as widgetSettingsSchema } from './deployment-
|
|
1
|
+
export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, E as Endpoints, H as HandshakeResponse, L as Link, P as PAGE_AREA_SUGGESTIONS, f as PageContext, S as ServerConfig, b as SiteConfig, U as UserContext, W as WidgetConfig, c as WidgetConfigPartial, d as WidgetSettings, e as WidgetSettingsPartial, g as assetSchema, h as blocksConfigSchema, i as connectionConfigPartialSchema, j as connectionConfigSchema, k as cssColorSchema, l as cssLengthSchema, m as endpointsSchema, n as handshakeResponseSchema, o as linkSchema, p as localeSchema, q as pageContextSchema, s as serverConfigSchema, r as siteConfigSchema, u as userContextSchema, t as uuid7Schema, w as widgetConfigPartialSchema, v as widgetConfigSchema, x as widgetSettingsPartialSchema, y as widgetSettingsSchema } from './deployment-E-Jyc0nF.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
/**
|
package/schema.json
CHANGED
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
"minLength": 1,
|
|
33
33
|
"maxLength": 2048
|
|
34
34
|
},
|
|
35
|
-
"
|
|
35
|
+
"agentApiBaseUrl": {
|
|
36
36
|
"description": "Full agent-API base — set it to reach a STANDALONE `module-help-ai-agent-api` directly (local module on its own port, e.g. `http://localhost:3087`; routes attach as-is: `/pai/handshake`). Precedence: this option > derived from the main origin (`${baseUrl}/api/agent`). Not server-pushable.",
|
|
37
37
|
"type": "string",
|
|
38
38
|
"minLength": 1,
|
|
39
39
|
"maxLength": 2048
|
|
40
40
|
},
|
|
41
|
-
"
|
|
42
|
-
"description": "Full data-API base (e.g. `https://help.ai/api/data`, or a standalone local module like `http://localhost:3106`) — the service serving content, form definitions (`GET /forms`), and form submissions at root-level paths. Precedence: this option > server-pushed `config.
|
|
41
|
+
"dataApiBaseUrl": {
|
|
42
|
+
"description": "Full data-API base (e.g. `https://help.ai/api/data`, or a standalone local module like `http://localhost:3106`) — the service serving content, form definitions (`GET /forms`), and form submissions at root-level paths. Precedence: this option > server-pushed `config.dataApiBaseUrl` > derived from the main origin (`${baseUrl}/api/data`).",
|
|
43
43
|
"type": "string",
|
|
44
44
|
"minLength": 1,
|
|
45
45
|
"maxLength": 2048
|
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
"submitForm"
|
|
192
192
|
],
|
|
193
193
|
"additionalProperties": {},
|
|
194
|
-
"description": "HTTP endpoint overrides. `upload` / `transcribe` paths are appended to the agent base (`${baseUrl}/api/agent`), `submitForm` to the data base (`
|
|
194
|
+
"description": "HTTP endpoint overrides. `upload` / `transcribe` paths are appended to the agent base (`${baseUrl}/api/agent`), `submitForm` to the data base (`dataApiBaseUrl`); absolute URLs are accepted too.",
|
|
195
195
|
"examples": [
|
|
196
196
|
{
|
|
197
197
|
"upload": "/pai/upload-file",
|
|
@@ -1871,7 +1871,7 @@
|
|
|
1871
1871
|
"type": "boolean"
|
|
1872
1872
|
},
|
|
1873
1873
|
"endpoint": {
|
|
1874
|
-
"description": "Pixel collector URL. Default: `${
|
|
1874
|
+
"description": "Pixel collector URL. Default: `${dataApiBaseUrl}/pai/elements-px.gif` (e.g. `https://help.ai/api/data/pai/elements-px.gif`). Must be a full URL.",
|
|
1875
1875
|
"type": "string",
|
|
1876
1876
|
"maxLength": 2048,
|
|
1877
1877
|
"format": "uri"
|
|
@@ -3276,7 +3276,7 @@
|
|
|
3276
3276
|
"type": "boolean"
|
|
3277
3277
|
},
|
|
3278
3278
|
"endpoint": {
|
|
3279
|
-
"description": "Pixel collector URL. Default: `${
|
|
3279
|
+
"description": "Pixel collector URL. Default: `${dataApiBaseUrl}/pai/elements-px.gif` (e.g. `https://help.ai/api/data/pai/elements-px.gif`). Must be a full URL.",
|
|
3280
3280
|
"type": "string",
|
|
3281
3281
|
"maxLength": 2048,
|
|
3282
3282
|
"format": "uri"
|
|
@@ -3305,7 +3305,7 @@
|
|
|
3305
3305
|
}
|
|
3306
3306
|
]
|
|
3307
3307
|
},
|
|
3308
|
-
"
|
|
3308
|
+
"dataApiBaseUrl": {
|
|
3309
3309
|
"type": "string",
|
|
3310
3310
|
"minLength": 1,
|
|
3311
3311
|
"maxLength": 2048
|
package/schema.mjs
CHANGED
|
@@ -573,7 +573,7 @@ var trackingSchema = z15.object({
|
|
|
573
573
|
"Master switch. Default `true` \u2014 the widget always fires; the data module gates ingestion per deployment server-side. Set `false` to silence the client entirely."
|
|
574
574
|
),
|
|
575
575
|
endpoint: z15.url().max(2048).optional().describe(
|
|
576
|
-
"Pixel collector URL. Default: `${
|
|
576
|
+
"Pixel collector URL. Default: `${dataApiBaseUrl}/pai/elements-px.gif` (e.g. `https://help.ai/api/data/pai/elements-px.gif`). Must be a full URL."
|
|
577
577
|
),
|
|
578
578
|
sampleRate: z15.number().min(0).max(1).optional().describe("Per-visitor sampling 0..1 (decided once per page load, keeping funnels intact). Default `1`."),
|
|
579
579
|
token: z15.string().max(512).optional().describe(
|
|
@@ -593,7 +593,7 @@ var endpointsSchema = z16.object({
|
|
|
593
593
|
"Form submission endpoint. The widget POSTs each completed form's values here (fire-and-forget), keyed by the same visitorId + conversationId as the conversation; the payload carries `formId` + `trigger` so the backend can route. Optional \u2014 a 404 is ignored."
|
|
594
594
|
)
|
|
595
595
|
}).loose().describe(
|
|
596
|
-
"HTTP endpoint overrides. `upload` / `transcribe` paths are appended to the agent base (`${baseUrl}/api/agent`), `submitForm` to the data base (`
|
|
596
|
+
"HTTP endpoint overrides. `upload` / `transcribe` paths are appended to the agent base (`${baseUrl}/api/agent`), `submitForm` to the data base (`dataApiBaseUrl`); absolute URLs are accepted too."
|
|
597
597
|
).meta({
|
|
598
598
|
examples: [
|
|
599
599
|
{ upload: "/pai/upload-file", transcribe: "/pai/transcribe-audio" },
|
|
@@ -645,11 +645,11 @@ var connectionConfigSchema = z16.object({
|
|
|
645
645
|
baseUrl: z16.string().min(1).max(2048).optional().describe(
|
|
646
646
|
"MAIN site origin (e.g. `https://help.ai`) \u2014 the API modules derive from it: agent API at `${baseUrl}/api/agent`, data API at `${baseUrl}/api/data`. Set this to point at your staging / self-hosted / custom backend. Default: the brand's `defaultBaseUrl` baked at build time."
|
|
647
647
|
),
|
|
648
|
-
|
|
648
|
+
agentApiBaseUrl: z16.string().min(1).max(2048).optional().describe(
|
|
649
649
|
"Full agent-API base \u2014 set it to reach a STANDALONE `module-help-ai-agent-api` directly (local module on its own port, e.g. `http://localhost:3087`; routes attach as-is: `/pai/handshake`). Precedence: this option > derived from the main origin (`${baseUrl}/api/agent`). Not server-pushable."
|
|
650
650
|
),
|
|
651
|
-
|
|
652
|
-
"Full data-API base (e.g. `https://help.ai/api/data`, or a standalone local module like `http://localhost:3106`) \u2014 the service serving content, form definitions (`GET /forms`), and form submissions at root-level paths. Precedence: this option > server-pushed `config.
|
|
651
|
+
dataApiBaseUrl: z16.string().min(1).max(2048).optional().describe(
|
|
652
|
+
"Full data-API base (e.g. `https://help.ai/api/data`, or a standalone local module like `http://localhost:3106`) \u2014 the service serving content, form definitions (`GET /forms`), and form submissions at root-level paths. Precedence: this option > server-pushed `config.dataApiBaseUrl` > derived from the main origin (`${baseUrl}/api/data`)."
|
|
653
653
|
),
|
|
654
654
|
userContext: userContextSchema.optional(),
|
|
655
655
|
pageContext: pageContextSchema.optional(),
|
|
@@ -733,7 +733,7 @@ var connectionConfigPartialSchema = connectionConfigSchema.partial();
|
|
|
733
733
|
// src/schema/deployment.ts
|
|
734
734
|
import { z as z17 } from "zod";
|
|
735
735
|
var serverConfigSchema = widgetSettingsSchema.partial().omit({ forms: true }).extend({
|
|
736
|
-
|
|
736
|
+
dataApiBaseUrl: z17.string().min(1).max(2048).optional()
|
|
737
737
|
});
|
|
738
738
|
var siteConfigSchema = z17.object({
|
|
739
739
|
title: z17.string().min(1).max(120).optional().describe("Brand / site name. Used as the logo's alt-text fallback."),
|
package/web-component.mjs
CHANGED
|
@@ -510,15 +510,15 @@ function resolveOptions(rawOpts) {
|
|
|
510
510
|
const locale = i18n.locale ?? resolveDefaultLocale(i18n.defaultLocale);
|
|
511
511
|
const availableLocales = i18n.availableLocales ?? [locale];
|
|
512
512
|
const baseUrl = (opts.baseUrl ?? BRAND.defaultBaseUrl).replace(/\/$/, "");
|
|
513
|
-
const
|
|
514
|
-
const
|
|
513
|
+
const agentApiBaseUrl = (opts.agentApiBaseUrl ?? `${baseUrl}/api/agent`).replace(/\/$/, "");
|
|
514
|
+
const dataApiBaseUrl = (opts.dataApiBaseUrl ?? `${baseUrl}/api/data`).replace(/\/$/, "");
|
|
515
515
|
return {
|
|
516
516
|
widgetId: opts.widgetId ?? "default",
|
|
517
517
|
publicKey: opts.publicKey,
|
|
518
518
|
aiAgentDeploymentId: opts.aiAgentDeploymentId,
|
|
519
519
|
baseUrl,
|
|
520
|
-
|
|
521
|
-
|
|
520
|
+
agentApiBaseUrl,
|
|
521
|
+
dataApiBaseUrl,
|
|
522
522
|
userContext: sanitizeUserContext(opts.userContext),
|
|
523
523
|
pageContext: sanitizePageContext(opts.pageContext),
|
|
524
524
|
position: presentation.position ?? "bottom-right",
|
|
@@ -563,7 +563,7 @@ function resolveOptions(rawOpts) {
|
|
|
563
563
|
poweredBy: resolvePoweredBy(footer.poweredBy),
|
|
564
564
|
composer: resolveComposer(opts.composer),
|
|
565
565
|
modules: resolveModules(opts.modules),
|
|
566
|
-
tracking: resolveTracking(opts.tracking,
|
|
566
|
+
tracking: resolveTracking(opts.tracking, dataApiBaseUrl),
|
|
567
567
|
storage: opts.storage ?? defaultStorage,
|
|
568
568
|
onMessage: opts.onMessage,
|
|
569
569
|
onOpen: opts.onOpen,
|
|
@@ -596,13 +596,13 @@ function resolveHaptics(overrides) {
|
|
|
596
596
|
events: overrides?.events
|
|
597
597
|
};
|
|
598
598
|
}
|
|
599
|
-
function resolveTracking(overrides,
|
|
599
|
+
function resolveTracking(overrides, dataApiBaseUrl) {
|
|
600
600
|
const sampleRate = overrides?.sampleRate ?? DEFAULT_TRACKING.sampleRate;
|
|
601
601
|
return {
|
|
602
602
|
enabled: overrides?.enabled ?? DEFAULT_TRACKING.enabled,
|
|
603
|
-
// The collector rides the data module — `${
|
|
603
|
+
// The collector rides the data module — `${dataApiBaseUrl}/pai/elements-px.gif`
|
|
604
604
|
// (e.g. `https://help.ai/api/data/pai/elements-px.gif`).
|
|
605
|
-
endpoint: overrides?.endpoint ?? `${
|
|
605
|
+
endpoint: overrides?.endpoint ?? `${dataApiBaseUrl}/pai/elements-px.gif`,
|
|
606
606
|
// Clamp instead of reject — a malformed rate must never turn a
|
|
607
607
|
// disabled tracker on or crash resolve (no Zod on the IIFE path).
|
|
608
608
|
sampleRate: Math.min(1, Math.max(0, Number.isFinite(sampleRate) ? sampleRate : 1)),
|
|
@@ -771,7 +771,8 @@ function mergeServerConfig(user, server) {
|
|
|
771
771
|
out[key] = mergeLeaves(sv, uv);
|
|
772
772
|
}
|
|
773
773
|
if (server.modules !== void 0 && user.modules === void 0) out.modules = server.modules;
|
|
774
|
-
if (server.
|
|
774
|
+
if (server.dataApiBaseUrl !== void 0 && user.dataApiBaseUrl === void 0)
|
|
775
|
+
out.dataApiBaseUrl = server.dataApiBaseUrl;
|
|
775
776
|
const userI18n = user.i18n;
|
|
776
777
|
const serverI18n = server.i18n;
|
|
777
778
|
if (userI18n || serverI18n) {
|
|
@@ -831,8 +832,8 @@ var EMBED_SCALAR_ATTRS = [
|
|
|
831
832
|
["public-key", "publicKey"],
|
|
832
833
|
["ai-agent-deployment-id", "aiAgentDeploymentId"],
|
|
833
834
|
["base-url", "baseUrl"],
|
|
834
|
-
["agent-base-url", "
|
|
835
|
-
["data-base-url", "
|
|
835
|
+
["agent-api-base-url", "agentApiBaseUrl"],
|
|
836
|
+
["data-api-base-url", "dataApiBaseUrl"],
|
|
836
837
|
["theme", "theme", (v) => v]
|
|
837
838
|
];
|
|
838
839
|
var PRESENTATION_ATTRS = [
|
|
@@ -1338,7 +1339,7 @@ var DEFAULT_PATHS = {
|
|
|
1338
1339
|
* on the client; a failure just leaves the badge until the next sync.
|
|
1339
1340
|
*/
|
|
1340
1341
|
markRead: "/pai/mark-read",
|
|
1341
|
-
// ── Data API (module-help-ai-data-api, via `
|
|
1342
|
+
// ── Data API (module-help-ai-data-api, via `dataApiBaseUrl`) ─────────
|
|
1342
1343
|
/**
|
|
1343
1344
|
* The data module's one ACTIVATION read. `GET
|
|
1344
1345
|
* /pai/bootstrap?visitorId=…&conversationId=…` →
|
|
@@ -1435,6 +1436,7 @@ function messageToWireParts(m) {
|
|
|
1435
1436
|
var log4 = logger.scope("transport");
|
|
1436
1437
|
var MAX_RESUME_ATTEMPTS = 3;
|
|
1437
1438
|
var RESUME_BACKOFF_MS = 400;
|
|
1439
|
+
var CONTENT_CACHE_TTL_MS = 6e4;
|
|
1438
1440
|
var MAX_REQUEST_RETRIES = 3;
|
|
1439
1441
|
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
|
|
1440
1442
|
function backoffMs(attempt) {
|
|
@@ -1473,6 +1475,20 @@ var AgentTransport = class {
|
|
|
1473
1475
|
// always sees the visitor's latest context as they navigate.
|
|
1474
1476
|
__publicField(this, "userContext");
|
|
1475
1477
|
__publicField(this, "pageContext");
|
|
1478
|
+
// ---- Data API (content / forms — module-help-ai-data-api) --------------
|
|
1479
|
+
//
|
|
1480
|
+
// The DATA surfaces live on `dataApiBaseUrl` (default `${baseUrl}/api/data`)
|
|
1481
|
+
// under the module's `/pai/*` group — same auth headers + envelope, same
|
|
1482
|
+
// retry behavior. One endpoint for every content surface (Home / Help /
|
|
1483
|
+
// News / docs); callers pass filters; a thrown StreamError (e.g. 404 on an
|
|
1484
|
+
// older backend) is treated as "no content" by the module and the tab
|
|
1485
|
+
// degrades gracefully.
|
|
1486
|
+
// Per-query content cache: published content barely changes mid-visit, but
|
|
1487
|
+
// every tab switch remounts its module and re-asks. Entries hold the
|
|
1488
|
+
// REQUEST PROMISE (concurrent identical queries share one network call)
|
|
1489
|
+
// and serve repeats for CONTENT_CACHE_TTL_MS; failures are evicted so the
|
|
1490
|
+
// next ask retries.
|
|
1491
|
+
__publicField(this, "contentCache", /* @__PURE__ */ new Map());
|
|
1476
1492
|
}
|
|
1477
1493
|
// ---- Public API -------------------------------------------------------
|
|
1478
1494
|
/**
|
|
@@ -1629,16 +1645,22 @@ var AgentTransport = class {
|
|
|
1629
1645
|
log4.debug("markRead failed (non-fatal)", { err });
|
|
1630
1646
|
}
|
|
1631
1647
|
}
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1648
|
+
/** Fetch content rows by filter. `GET /pai/content` (data-API), TTL-cached. */
|
|
1649
|
+
listContent(query = {}) {
|
|
1650
|
+
const key = JSON.stringify(query, Object.keys(query).toSorted());
|
|
1651
|
+
const cached = this.contentCache.get(key);
|
|
1652
|
+
if (cached && Date.now() - cached.at < CONTENT_CACHE_TTL_MS) {
|
|
1653
|
+
log4.debug("listContent \u2192 cache", query);
|
|
1654
|
+
return cached.result;
|
|
1655
|
+
}
|
|
1656
|
+
const result = this.fetchContent(query).catch((err) => {
|
|
1657
|
+
this.contentCache.delete(key);
|
|
1658
|
+
throw err;
|
|
1659
|
+
});
|
|
1660
|
+
this.contentCache.set(key, { at: Date.now(), result });
|
|
1661
|
+
return result;
|
|
1662
|
+
}
|
|
1663
|
+
async fetchContent(query) {
|
|
1642
1664
|
const url = new URL(this.dataUrl(DEFAULT_PATHS.content));
|
|
1643
1665
|
for (const [key, value] of Object.entries(query)) {
|
|
1644
1666
|
if (value === void 0) continue;
|
|
@@ -1944,7 +1966,7 @@ var AgentTransport = class {
|
|
|
1944
1966
|
*/
|
|
1945
1967
|
url(pathOrUrl) {
|
|
1946
1968
|
if (/^https?:\/\//i.test(pathOrUrl)) return pathOrUrl;
|
|
1947
|
-
return `${this.opts.
|
|
1969
|
+
return `${this.opts.agentApiBaseUrl}${pathOrUrl}`;
|
|
1948
1970
|
}
|
|
1949
1971
|
/**
|
|
1950
1972
|
* Data-API variant of {@link url} — resolves a root-level path (content /
|
|
@@ -1954,7 +1976,7 @@ var AgentTransport = class {
|
|
|
1954
1976
|
*/
|
|
1955
1977
|
dataUrl(pathOrUrl) {
|
|
1956
1978
|
if (/^https?:\/\//i.test(pathOrUrl)) return pathOrUrl;
|
|
1957
|
-
return `${this.opts.
|
|
1979
|
+
return `${this.opts.dataApiBaseUrl}${pathOrUrl}`;
|
|
1958
1980
|
}
|
|
1959
1981
|
get fetchImpl() {
|
|
1960
1982
|
return this.opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
@@ -6520,8 +6542,8 @@ function App({ options, hostElement, bus }) {
|
|
|
6520
6542
|
const [formContext, setFormContext] = useState13({});
|
|
6521
6543
|
const [transport] = useState13(
|
|
6522
6544
|
() => new AgentTransport({
|
|
6523
|
-
|
|
6524
|
-
|
|
6545
|
+
agentApiBaseUrl: options.agentApiBaseUrl,
|
|
6546
|
+
dataApiBaseUrl: options.dataApiBaseUrl,
|
|
6525
6547
|
auth: createAuth({
|
|
6526
6548
|
publicKey: options.publicKey,
|
|
6527
6549
|
aiAgentDeploymentId: options.aiAgentDeploymentId,
|