@helpai/elements 0.26.0 → 0.28.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/configurator.mjs +15 -13
- package/elements-web-component.esm.js +18 -18
- package/elements-web-component.esm.js.map +3 -3
- package/elements.cjs.js +18 -18
- package/elements.cjs.js.map +3 -3
- package/elements.esm.js +18 -18
- package/elements.esm.js.map +3 -3
- package/elements.js +18 -18
- package/elements.js.map +3 -3
- package/index.d.ts +19 -18
- package/index.mjs +91 -88
- package/package.json +1 -1
- package/schema.d.ts +1 -1
- package/schema.json +15 -15
- package/schema.mjs +15 -13
- package/web-component.mjs +91 -88
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
|
/**
|
|
@@ -146,7 +146,7 @@ interface ConversationWelcome {
|
|
|
146
146
|
suggestions?: ConversationSuggestion[];
|
|
147
147
|
}
|
|
148
148
|
/**
|
|
149
|
-
* Response from `POST /
|
|
149
|
+
* Response from `POST /pai/handshake` — the widget's one mount-time
|
|
150
150
|
* round-trip. Deliberately LIGHT: identity + deployment surface only
|
|
151
151
|
* (config, agent persona, welcome, page-mode site/blocks, userPrefs).
|
|
152
152
|
* The conversation THREAD is a separate, lazily-fetched read
|
|
@@ -896,14 +896,14 @@ 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
|
*/
|
|
903
903
|
interface Endpoints {
|
|
904
|
-
/** File upload endpoint. Default: `'/
|
|
904
|
+
/** File upload endpoint. Default: `'/pai/upload-file'`. */
|
|
905
905
|
upload?: string;
|
|
906
|
-
/** Voice transcription endpoint. Default: `'/
|
|
906
|
+
/** Voice transcription endpoint. Default: `'/pai/transcribe-audio'`. */
|
|
907
907
|
transcribe?: string;
|
|
908
908
|
/**
|
|
909
909
|
* Form submission endpoint. Default: `'/submit-form'`. When any form
|
|
@@ -933,13 +933,14 @@ interface Endpoints {
|
|
|
933
933
|
/** Section: anonymous owner-facing usage tracking. */
|
|
934
934
|
interface TrackingOptions {
|
|
935
935
|
/**
|
|
936
|
-
* Master switch. Default `
|
|
937
|
-
*
|
|
936
|
+
* Master switch. Default `true` — the widget always fires; the data
|
|
937
|
+
* module gates ingestion per deployment server-side. Set `false`
|
|
938
|
+
* (deployment config or init) to silence the client entirely.
|
|
938
939
|
*/
|
|
939
940
|
enabled?: boolean;
|
|
940
941
|
/**
|
|
941
|
-
* Pixel collector URL. Default: `${
|
|
942
|
-
* (e.g. `https://help.ai/api/data/elements
|
|
942
|
+
* Pixel collector URL. Default: `${dataApiBaseUrl}/pai/elements-px.gif`
|
|
943
|
+
* (e.g. `https://help.ai/api/data/pai/elements-px.gif`).
|
|
943
944
|
*/
|
|
944
945
|
endpoint?: string;
|
|
945
946
|
/**
|
|
@@ -1015,22 +1016,22 @@ interface ChatWidgetOptions {
|
|
|
1015
1016
|
* Agent-API base (no trailing slash) — set it when the
|
|
1016
1017
|
* `module-help-ai-agent-api` service is reached DIRECTLY (a standalone
|
|
1017
1018
|
* local module, e.g. `http://localhost:3087`) instead of through the
|
|
1018
|
-
* edge. Routes attach as-is (`${
|
|
1019
|
+
* edge. Routes attach as-is (`${agentApiBaseUrl}/pai/handshake`).
|
|
1019
1020
|
* Precedence: this option > derived from the main origin
|
|
1020
1021
|
* (`${baseUrl}/api/agent`). Not server-pushable — the handshake already
|
|
1021
1022
|
* travelled over it.
|
|
1022
1023
|
*/
|
|
1023
|
-
|
|
1024
|
+
agentApiBaseUrl?: string;
|
|
1024
1025
|
/**
|
|
1025
1026
|
* Data-API base (no trailing slash) — the `module-help-ai-data-api`
|
|
1026
1027
|
* service serving content, form definitions, and form submissions at
|
|
1027
1028
|
* root-level paths (`/content`, `/forms`, `/activity`, `/submit-form`).
|
|
1028
1029
|
* Set it for a standalone local module (e.g. `http://localhost:3106`).
|
|
1029
|
-
* Precedence: this option > server-pushed `config.
|
|
1030
|
+
* Precedence: this option > server-pushed `config.dataApiBaseUrl` > derived
|
|
1030
1031
|
* from the main origin (`${baseUrl}/api/data`, e.g.
|
|
1031
1032
|
* `https://help.ai/api/data`).
|
|
1032
1033
|
*/
|
|
1033
|
-
|
|
1034
|
+
dataApiBaseUrl?: string;
|
|
1034
1035
|
/** Host-asserted, informational end-user context (untrusted; not auth). */
|
|
1035
1036
|
userContext?: UserContext;
|
|
1036
1037
|
/** Host-asserted, informational page/visit context (untrusted; `area`, url, …). */
|
|
@@ -1085,10 +1086,10 @@ interface ResolvedOptions {
|
|
|
1085
1086
|
publicKey?: string;
|
|
1086
1087
|
aiAgentDeploymentId?: string;
|
|
1087
1088
|
baseUrl: string;
|
|
1088
|
-
/** Resolved agent-API base — see {@link ChatWidgetOptions.
|
|
1089
|
-
|
|
1090
|
-
/** Resolved data-API base — see {@link ChatWidgetOptions.
|
|
1091
|
-
|
|
1089
|
+
/** Resolved agent-API base — see {@link ChatWidgetOptions.agentApiBaseUrl}. */
|
|
1090
|
+
agentApiBaseUrl: string;
|
|
1091
|
+
/** Resolved data-API base — see {@link ChatWidgetOptions.dataApiBaseUrl}. */
|
|
1092
|
+
dataApiBaseUrl: string;
|
|
1092
1093
|
userContext?: UserContext;
|
|
1093
1094
|
pageContext?: PageContext;
|
|
1094
1095
|
position: Position;
|
|
@@ -1187,7 +1188,7 @@ interface ResolvedOptions {
|
|
|
1187
1188
|
*/
|
|
1188
1189
|
interface ServerConfig {
|
|
1189
1190
|
/** Data-API base override — adopted only when the host didn't set one. */
|
|
1190
|
-
|
|
1191
|
+
dataApiBaseUrl?: string;
|
|
1191
1192
|
presentation?: PresentationOptions;
|
|
1192
1193
|
behavior?: BehaviorOptions;
|
|
1193
1194
|
theme?: ThemePreference | ThemeOverrides;
|
package/index.mjs
CHANGED
|
@@ -476,13 +476,13 @@ var DEFAULT_FEATURES = {
|
|
|
476
476
|
};
|
|
477
477
|
var DEFAULT_FORMS = { list: [], byTrigger: {} };
|
|
478
478
|
var DEFAULT_TRACKING = {
|
|
479
|
-
enabled:
|
|
479
|
+
enabled: true,
|
|
480
480
|
sampleRate: 1
|
|
481
481
|
};
|
|
482
482
|
var DEFAULT_ENDPOINTS = {
|
|
483
|
-
upload: "/
|
|
484
|
-
transcribe: "/
|
|
485
|
-
submitForm: "/submit-form"
|
|
483
|
+
upload: "/pai/upload-file",
|
|
484
|
+
transcribe: "/pai/transcribe-audio",
|
|
485
|
+
submitForm: "/pai/submit-form"
|
|
486
486
|
};
|
|
487
487
|
var DEFAULT_LAUNCHER = {
|
|
488
488
|
variant: "circle",
|
|
@@ -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 — `${
|
|
619
|
-
// (e.g. `https://help.ai/api/data/elements
|
|
620
|
-
endpoint: overrides?.endpoint ?? `${
|
|
618
|
+
// The collector rides the data module — `${dataApiBaseUrl}/pai/elements-px.gif`
|
|
619
|
+
// (e.g. `https://help.ai/api/data/pai/elements-px.gif`).
|
|
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 = [
|
|
@@ -1253,63 +1254,61 @@ function parseWireDate(value) {
|
|
|
1253
1254
|
}
|
|
1254
1255
|
var DEFAULT_PATHS = {
|
|
1255
1256
|
/** Conversation bootstrap. `POST` → deployment config + per-visitor state. */
|
|
1256
|
-
handshake: "/
|
|
1257
|
+
handshake: "/pai/handshake",
|
|
1257
1258
|
/** Send a message + stream the reply (SSE). `POST`. */
|
|
1258
|
-
streamMessage: "/
|
|
1259
|
+
streamMessage: "/pai/stream-message",
|
|
1259
1260
|
/**
|
|
1260
1261
|
* Resume an interrupted reply. `GET` (envelope rides as query params).
|
|
1261
1262
|
* Stateless: the server re-streams the whole reply SSE again from the start —
|
|
1262
1263
|
* there is NO `Last-Event-ID`. The client reconciles by id (`seenIds`), so
|
|
1263
1264
|
* replayed events are skipped and only the continuation surfaces.
|
|
1264
1265
|
*/
|
|
1265
|
-
streamResume: "/
|
|
1266
|
+
streamResume: "/pai/stream-resume",
|
|
1266
1267
|
/** Abort the in-flight reply stream. `POST`. */
|
|
1267
|
-
cancelStream: "/
|
|
1268
|
+
cancelStream: "/pai/cancel-stream",
|
|
1268
1269
|
/** List the visitor's conversations. `GET`. */
|
|
1269
|
-
listConversations: "/
|
|
1270
|
+
listConversations: "/pai/list-conversations",
|
|
1270
1271
|
/** Load one conversation's thread (messages + canContinue + suggestions). `GET ?conversationId=…`. */
|
|
1271
|
-
listMessages: "/
|
|
1272
|
+
listMessages: "/pai/list-messages",
|
|
1272
1273
|
/**
|
|
1273
1274
|
* Persist a user-driven settings change. POST `{ visitorId, userPrefs }` →
|
|
1274
1275
|
* server persists, returns the merged authoritative copy. Fire-and-forget on
|
|
1275
1276
|
* the client — a failure leaves the local cache valid; the next
|
|
1276
1277
|
* `handshake()` reconciles.
|
|
1277
1278
|
*/
|
|
1278
|
-
updateSettings: "/
|
|
1279
|
+
updateSettings: "/pai/update-settings",
|
|
1279
1280
|
/**
|
|
1280
1281
|
* Mark a conversation read. POST `{ visitorId, conversationId }` → the server
|
|
1281
1282
|
* records `lastReadAt = now` for that (visitor, conversation) and recomputes
|
|
1282
1283
|
* `unreadCount` (returned on `/list-conversations`) accordingly. Fire-and-forget
|
|
1283
1284
|
* on the client; a failure just leaves the badge until the next sync.
|
|
1284
1285
|
*/
|
|
1285
|
-
markRead: "/
|
|
1286
|
-
// ── Data API (module-help-ai-data-api, via `
|
|
1287
|
-
/**
|
|
1288
|
-
|
|
1286
|
+
markRead: "/pai/mark-read",
|
|
1287
|
+
// ── Data API (module-help-ai-data-api, via `dataApiBaseUrl`) ─────────
|
|
1288
|
+
/**
|
|
1289
|
+
* The data module's one ACTIVATION read. `GET
|
|
1290
|
+
* /pai/bootstrap?visitorId=…&conversationId=…` →
|
|
1291
|
+
* `{ forms, formSubmissions }`: the deployment's resolved form
|
|
1292
|
+
* definitions plus the visitor's recorded submissions for the envelope's
|
|
1293
|
+
* conversation (chronological — they rebuild the timeline markers).
|
|
1294
|
+
* Also re-read with an explicit `conversationId` selector on a
|
|
1295
|
+
* history-pane thread switch. A failure is treated as "no forms, no
|
|
1296
|
+
* records" (non-fatal) — the chat works regardless.
|
|
1297
|
+
*/
|
|
1298
|
+
bootstrap: "/pai/bootstrap",
|
|
1289
1299
|
/**
|
|
1290
|
-
*
|
|
1291
|
-
*
|
|
1292
|
-
*
|
|
1293
|
-
* "no forms" (non-fatal).
|
|
1300
|
+
* All widget content via one filtered endpoint — content stays OUT of the
|
|
1301
|
+
* bootstrap because its reads are query-driven (`tags` / `categories` /
|
|
1302
|
+
* `ids` / `search` + pagination). `GET /pai/content?tags=…`.
|
|
1294
1303
|
*/
|
|
1295
|
-
|
|
1304
|
+
content: "/pai/content",
|
|
1296
1305
|
/**
|
|
1297
1306
|
* Form submission (the event-driven forms engine). POST `{ visitorId,
|
|
1298
1307
|
* conversationId, formId, trigger, values, skipped? }` → record the form's answers
|
|
1299
1308
|
* immediately, keyed by the same `visitorId` + `conversationId` the chat uses.
|
|
1300
1309
|
* Overridable via `endpoints.submitForm`. Fire-and-forget; 404 is ignored.
|
|
1301
1310
|
*/
|
|
1302
|
-
submitForm: "/submit-form"
|
|
1303
|
-
/**
|
|
1304
|
-
* Visitor interaction records for a conversation. `GET
|
|
1305
|
-
* /activity?visitorId=…&conversationId=…` →
|
|
1306
|
-
* `{ formSubmissions: FormSubmissionRecord[] }` (chronological). Replaces
|
|
1307
|
-
* the former `formSubmissions` echo on the handshake / list-messages;
|
|
1308
|
-
* deliberately generic — future visitor interaction records ride the same
|
|
1309
|
-
* endpoint. A failure (e.g. 404 `AI_AGENT_PUBLIC_ACCESS_NOT_FOUND` when the
|
|
1310
|
-
* deployment doesn't resolve) is treated as "no records" (non-fatal).
|
|
1311
|
-
*/
|
|
1312
|
-
activity: "/activity"
|
|
1311
|
+
submitForm: "/pai/submit-form"
|
|
1313
1312
|
};
|
|
1314
1313
|
var CONTEXT_PARAM = "context";
|
|
1315
1314
|
function buildSendMessageRequest(params) {
|
|
@@ -1578,7 +1577,7 @@ var AgentTransport = class {
|
|
|
1578
1577
|
}
|
|
1579
1578
|
// ---- Data API (content / forms — module-help-ai-data-api) --------------
|
|
1580
1579
|
//
|
|
1581
|
-
// The DATA surfaces live on `
|
|
1580
|
+
// The DATA surfaces live on `dataApiBaseUrl` (default `${baseUrl}/api/data`)
|
|
1582
1581
|
// with ROOT-level paths — same auth headers + envelope, same retry
|
|
1583
1582
|
// behavior. One endpoint for every content surface (Home / Help / News /
|
|
1584
1583
|
// docs); callers pass filters; a thrown StreamError (e.g. 404 on an older
|
|
@@ -1598,38 +1597,26 @@ var AgentTransport = class {
|
|
|
1598
1597
|
return { ...res, items };
|
|
1599
1598
|
}
|
|
1600
1599
|
/**
|
|
1601
|
-
*
|
|
1602
|
-
*
|
|
1603
|
-
*
|
|
1604
|
-
* (
|
|
1605
|
-
*
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
log4.debug("listForms \u2190", { count: forms.length });
|
|
1612
|
-
return { forms };
|
|
1613
|
-
}
|
|
1614
|
-
/**
|
|
1615
|
-
* Fetch the visitor's recorded activity for a conversation — currently the
|
|
1616
|
-
* form submissions that rebuild the collapsed "form submitted / skipped"
|
|
1617
|
-
* timeline markers on resume. `GET /activity` (data-API); the
|
|
1618
|
-
* envelope carries `visitorId` / `conversationId` as query params.
|
|
1619
|
-
* `conversationId` here is an optional resource selector (a thread that may
|
|
1620
|
-
* differ from the active conversation — the history-pane switch); when
|
|
1621
|
-
* omitted, the envelope's active conversation applies. Callers treat a
|
|
1622
|
-
* thrown StreamError (e.g. 404 on a deployment that doesn't resolve) as
|
|
1623
|
-
* "no activity" (non-fatal).
|
|
1600
|
+
* The data module's ONE activation read. `GET /pai/bootstrap` (data-API)
|
|
1601
|
+
* → the deployment's resolved form definitions + the visitor's recorded
|
|
1602
|
+
* form submissions for the envelope's conversation. The handshake
|
|
1603
|
+
* (agent-API) is completely independent of these surfaces.
|
|
1604
|
+
*
|
|
1605
|
+
* `conversationId` is an optional resource selector (a thread that may
|
|
1606
|
+
* differ from the active conversation — the history-pane switch re-reads
|
|
1607
|
+
* that thread's submissions); when omitted, the envelope's active
|
|
1608
|
+
* conversation applies. Callers treat a thrown StreamError (e.g. 404 on a
|
|
1609
|
+
* deployment that doesn't resolve) as "no forms, no records" (non-fatal).
|
|
1624
1610
|
*/
|
|
1625
|
-
async
|
|
1626
|
-
const url = new URL(this.dataUrl(DEFAULT_PATHS.
|
|
1611
|
+
async bootstrap(conversationId) {
|
|
1612
|
+
const url = new URL(this.dataUrl(DEFAULT_PATHS.bootstrap));
|
|
1627
1613
|
if (conversationId) url.searchParams.set("conversationId", conversationId);
|
|
1628
|
-
log4.debug("
|
|
1629
|
-
const res = await this.getJson(url.toString(), "
|
|
1614
|
+
log4.debug("bootstrap \u2192", { conversationId: conversationId ?? this.conversationId });
|
|
1615
|
+
const res = await this.getJson(url.toString(), "bootstrap");
|
|
1616
|
+
const forms = res.forms ?? [];
|
|
1630
1617
|
const formSubmissions = res.formSubmissions ?? [];
|
|
1631
|
-
log4.debug("
|
|
1632
|
-
return { formSubmissions };
|
|
1618
|
+
log4.debug("bootstrap \u2190", { forms: forms.length, formSubmissions: formSubmissions.length });
|
|
1619
|
+
return { forms, formSubmissions };
|
|
1633
1620
|
}
|
|
1634
1621
|
async saveUserPrefs(userPrefs) {
|
|
1635
1622
|
log4.debug("saveUserPrefs \u2192", {
|
|
@@ -1642,10 +1629,10 @@ var AgentTransport = class {
|
|
|
1642
1629
|
return res;
|
|
1643
1630
|
}
|
|
1644
1631
|
get uploadPath() {
|
|
1645
|
-
return this.opts.endpoints?.upload ?? "/
|
|
1632
|
+
return this.opts.endpoints?.upload ?? "/pai/upload-file";
|
|
1646
1633
|
}
|
|
1647
1634
|
get transcribePath() {
|
|
1648
|
-
return this.opts.endpoints?.transcribe ?? "/
|
|
1635
|
+
return this.opts.endpoints?.transcribe ?? "/pai/transcribe-audio";
|
|
1649
1636
|
}
|
|
1650
1637
|
get submitFormPath() {
|
|
1651
1638
|
return this.opts.endpoints?.submitForm ?? DEFAULT_PATHS.submitForm;
|
|
@@ -1788,7 +1775,7 @@ var AgentTransport = class {
|
|
|
1788
1775
|
}
|
|
1789
1776
|
return false;
|
|
1790
1777
|
}
|
|
1791
|
-
/** Abort + fire-and-forget POST to `/
|
|
1778
|
+
/** Abort + fire-and-forget POST to `/pai/cancel-stream`. Idempotent. */
|
|
1792
1779
|
cancelStream(ctrl, conversationId) {
|
|
1793
1780
|
if (ctrl.signal.aborted) return;
|
|
1794
1781
|
log4.debug("cancel stream", { conversationId, visitorId: this.visitorId });
|
|
@@ -1898,12 +1885,12 @@ var AgentTransport = class {
|
|
|
1898
1885
|
return await res.json();
|
|
1899
1886
|
}
|
|
1900
1887
|
/**
|
|
1901
|
-
* Agent-API URL — resolves a `/
|
|
1888
|
+
* Agent-API URL — resolves a `/pai/*` path against the resolved
|
|
1902
1889
|
* agent module base. Absolute URLs pass through unchanged.
|
|
1903
1890
|
*/
|
|
1904
1891
|
url(pathOrUrl) {
|
|
1905
1892
|
if (/^https?:\/\//i.test(pathOrUrl)) return pathOrUrl;
|
|
1906
|
-
return `${this.opts.
|
|
1893
|
+
return `${this.opts.agentApiBaseUrl}${pathOrUrl}`;
|
|
1907
1894
|
}
|
|
1908
1895
|
/**
|
|
1909
1896
|
* Data-API variant of {@link url} — resolves a root-level path (content /
|
|
@@ -1913,7 +1900,7 @@ var AgentTransport = class {
|
|
|
1913
1900
|
*/
|
|
1914
1901
|
dataUrl(pathOrUrl) {
|
|
1915
1902
|
if (/^https?:\/\//i.test(pathOrUrl)) return pathOrUrl;
|
|
1916
|
-
return `${this.opts.
|
|
1903
|
+
return `${this.opts.dataApiBaseUrl}${pathOrUrl}`;
|
|
1917
1904
|
}
|
|
1918
1905
|
get fetchImpl() {
|
|
1919
1906
|
return this.opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
@@ -6479,8 +6466,8 @@ function App({ options, hostElement, bus }) {
|
|
|
6479
6466
|
const [formContext, setFormContext] = useState13({});
|
|
6480
6467
|
const [transport] = useState13(
|
|
6481
6468
|
() => new AgentTransport({
|
|
6482
|
-
|
|
6483
|
-
|
|
6469
|
+
agentApiBaseUrl: options.agentApiBaseUrl,
|
|
6470
|
+
dataApiBaseUrl: options.dataApiBaseUrl,
|
|
6484
6471
|
auth: createAuth({
|
|
6485
6472
|
publicKey: options.publicKey,
|
|
6486
6473
|
aiAgentDeploymentId: options.aiAgentDeploymentId,
|
|
@@ -6561,10 +6548,11 @@ function App({ options, hostElement, bus }) {
|
|
|
6561
6548
|
},
|
|
6562
6549
|
[messagesSig]
|
|
6563
6550
|
);
|
|
6551
|
+
const dataBootRef = useRef9(null);
|
|
6564
6552
|
const fetchFormMarkers = useCallback6(
|
|
6565
6553
|
async (conversationId) => {
|
|
6566
6554
|
try {
|
|
6567
|
-
const { formSubmissions: subs } = await transport.
|
|
6555
|
+
const { formSubmissions: subs } = await (conversationId ? transport.bootstrap(conversationId) : dataBootRef.current ?? transport.bootstrap());
|
|
6568
6556
|
const lastIndexByForm = /* @__PURE__ */ new Map();
|
|
6569
6557
|
subs.forEach((rec, i) => lastIndexByForm.set(rec.formId, i));
|
|
6570
6558
|
return subs.filter((rec, i) => !rec.skipped || lastIndexByForm.get(rec.formId) === i).map((rec, i) => ({
|
|
@@ -6575,7 +6563,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6575
6563
|
values: rec.values
|
|
6576
6564
|
}));
|
|
6577
6565
|
} catch (err) {
|
|
6578
|
-
log16.debug("
|
|
6566
|
+
log16.debug("bootstrap failed \u2014 no form markers (non-fatal)", { err });
|
|
6579
6567
|
return [];
|
|
6580
6568
|
}
|
|
6581
6569
|
},
|
|
@@ -6764,12 +6752,13 @@ function App({ options, hostElement, bus }) {
|
|
|
6764
6752
|
}, []);
|
|
6765
6753
|
useEffect17(() => {
|
|
6766
6754
|
if (!activated) return;
|
|
6755
|
+
dataBootRef.current = transport.bootstrap();
|
|
6767
6756
|
void (async () => {
|
|
6768
6757
|
try {
|
|
6769
|
-
const res = await
|
|
6770
|
-
setRemoteForms(resolveForms(res.forms));
|
|
6758
|
+
const res = await dataBootRef.current;
|
|
6759
|
+
setRemoteForms(resolveForms((res ?? { forms: [] }).forms));
|
|
6771
6760
|
} catch (err) {
|
|
6772
|
-
log16.debug("
|
|
6761
|
+
log16.debug("bootstrap failed \u2014 treating as no forms", { err });
|
|
6773
6762
|
} finally {
|
|
6774
6763
|
setFormsReady(true);
|
|
6775
6764
|
}
|
|
@@ -7154,6 +7143,20 @@ function App({ options, hostElement, bus }) {
|
|
|
7154
7143
|
},
|
|
7155
7144
|
[transport, messagesSig, conversationIdSig, bus, options, persistence, refreshUnread, fetchFormMarkers]
|
|
7156
7145
|
);
|
|
7146
|
+
const pendingOpenFormRef = useRef9(null);
|
|
7147
|
+
const openForm = useCallback6(
|
|
7148
|
+
(id) => {
|
|
7149
|
+
if (typeof id !== "string") return;
|
|
7150
|
+
if (formsReady) forms.fire("manual", id);
|
|
7151
|
+
else pendingOpenFormRef.current = id;
|
|
7152
|
+
},
|
|
7153
|
+
[formsReady, forms]
|
|
7154
|
+
);
|
|
7155
|
+
useEffect17(() => {
|
|
7156
|
+
if (!formsReady || !pendingOpenFormRef.current) return;
|
|
7157
|
+
forms.fire("manual", pendingOpenFormRef.current);
|
|
7158
|
+
pendingOpenFormRef.current = null;
|
|
7159
|
+
}, [formsReady, forms]);
|
|
7157
7160
|
useEffect17(() => {
|
|
7158
7161
|
const unsub = bindHostCommands(hostElement, {
|
|
7159
7162
|
open: handleOpen,
|
|
@@ -7161,10 +7164,10 @@ function App({ options, hostElement, bus }) {
|
|
|
7161
7164
|
expand: handleExpand,
|
|
7162
7165
|
fullscreen: handleFullscreen,
|
|
7163
7166
|
popout: handlePopOut,
|
|
7164
|
-
openForm
|
|
7167
|
+
openForm
|
|
7165
7168
|
});
|
|
7166
7169
|
return unsub;
|
|
7167
|
-
}, [hostElement, handleOpen, handleClose, handleExpand, handleFullscreen, handlePopOut,
|
|
7170
|
+
}, [hostElement, handleOpen, handleClose, handleExpand, handleFullscreen, handlePopOut, openForm]);
|
|
7168
7171
|
const effectiveOptions = useMemo3(
|
|
7169
7172
|
() => applyOptionOverrides(options, activeLocale, activeThemeMode, activeTextSize),
|
|
7170
7173
|
[options, activeLocale, activeThemeMode, activeTextSize]
|
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
|
-
"
|
|
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: `/
|
|
35
|
+
"agentApiBaseUrl": {
|
|
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
|
|
@@ -166,19 +166,19 @@
|
|
|
166
166
|
"type": "object",
|
|
167
167
|
"properties": {
|
|
168
168
|
"upload": {
|
|
169
|
-
"default": "/
|
|
169
|
+
"default": "/pai/upload-file",
|
|
170
170
|
"type": "string",
|
|
171
171
|
"minLength": 1,
|
|
172
172
|
"maxLength": 2048
|
|
173
173
|
},
|
|
174
174
|
"transcribe": {
|
|
175
|
-
"default": "/
|
|
175
|
+
"default": "/pai/transcribe-audio",
|
|
176
176
|
"type": "string",
|
|
177
177
|
"minLength": 1,
|
|
178
178
|
"maxLength": 2048
|
|
179
179
|
},
|
|
180
180
|
"submitForm": {
|
|
181
|
-
"default": "/submit-form",
|
|
181
|
+
"default": "/pai/submit-form",
|
|
182
182
|
"description": "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 — a 404 is ignored.",
|
|
183
183
|
"type": "string",
|
|
184
184
|
"minLength": 1,
|
|
@@ -191,11 +191,11 @@
|
|
|
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
|
-
"upload": "/
|
|
198
|
-
"transcribe": "/
|
|
197
|
+
"upload": "/pai/upload-file",
|
|
198
|
+
"transcribe": "/pai/transcribe-audio"
|
|
199
199
|
},
|
|
200
200
|
{
|
|
201
201
|
"upload": "https://help.ai/uploads/presign"
|
|
@@ -1867,11 +1867,11 @@
|
|
|
1867
1867
|
"type": "object",
|
|
1868
1868
|
"properties": {
|
|
1869
1869
|
"enabled": {
|
|
1870
|
-
"description": "Master switch. Default `
|
|
1870
|
+
"description": "Master switch. Default `true` — the widget always fires; the data module gates ingestion per deployment server-side. Set `false` to silence the client entirely.",
|
|
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"
|
|
@@ -3272,11 +3272,11 @@
|
|
|
3272
3272
|
"type": "object",
|
|
3273
3273
|
"properties": {
|
|
3274
3274
|
"enabled": {
|
|
3275
|
-
"description": "Master switch. Default `
|
|
3275
|
+
"description": "Master switch. Default `true` — the widget always fires; the data module gates ingestion per deployment server-side. Set `false` to silence the client entirely.",
|
|
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
|