@webless/agent 0.7.5 → 0.9.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/README.md +49 -2
- package/dist/chunk-5BCSXCLT.js +297 -0
- package/dist/chunk-5BCSXCLT.js.map +1 -0
- package/dist/{chunk-CD6TKXGT.js → chunk-QMTI5646.js} +69 -40
- package/dist/chunk-QMTI5646.js.map +1 -0
- package/dist/embed.cjs +62 -39
- package/dist/embed.cjs.map +1 -1
- package/dist/embed.css +98 -0
- package/dist/embed.css.map +1 -1
- package/dist/embed.js +1 -1
- package/dist/index.d.cts +3 -180
- package/dist/index.d.ts +3 -180
- package/dist/index.js +9 -288
- package/dist/index.js.map +1 -1
- package/dist/presentation.cjs +850 -0
- package/dist/presentation.cjs.map +1 -0
- package/dist/presentation.d.cts +160 -0
- package/dist/presentation.d.ts +160 -0
- package/dist/presentation.js +549 -0
- package/dist/presentation.js.map +1 -0
- package/dist/react.cjs +218 -39
- package/dist/react.cjs.map +1 -1
- package/dist/react.css +98 -0
- package/dist/react.css.map +1 -1
- package/dist/react.d.cts +26 -3
- package/dist/react.d.ts +26 -3
- package/dist/react.js +163 -2
- package/dist/react.js.map +1 -1
- package/dist/types-ohWeTG9i.d.cts +181 -0
- package/dist/types-ohWeTG9i.d.ts +181 -0
- package/package.json +7 -2
- package/dist/chunk-CD6TKXGT.js.map +0 -1
|
@@ -0,0 +1,850 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/presentation.ts
|
|
21
|
+
var presentation_exports = {};
|
|
22
|
+
__export(presentation_exports, {
|
|
23
|
+
presentTranscriptToolResult: () => presentTranscriptToolResult,
|
|
24
|
+
presentVisitorToolResult: () => presentVisitorToolResult
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(presentation_exports);
|
|
27
|
+
|
|
28
|
+
// src/runtime/search-discovery.ts
|
|
29
|
+
function record(value) {
|
|
30
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
31
|
+
}
|
|
32
|
+
function text(value, max = 500) {
|
|
33
|
+
return typeof value === "string" && value.trim().length > 0 && value.trim().length <= max;
|
|
34
|
+
}
|
|
35
|
+
function safeSearchUrl(value) {
|
|
36
|
+
if (typeof value !== "string") return void 0;
|
|
37
|
+
try {
|
|
38
|
+
const url = new URL(value);
|
|
39
|
+
return (url.protocol === "https:" || url.protocol === "http:") && !url.username && !url.password ? url.href : void 0;
|
|
40
|
+
} catch {
|
|
41
|
+
return void 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function parseAgentSearchReferences(value) {
|
|
45
|
+
const data = record(value);
|
|
46
|
+
if (!data || !Array.isArray(data.sources) || data.sources.length > 20)
|
|
47
|
+
return null;
|
|
48
|
+
const sources = [];
|
|
49
|
+
for (const value2 of data.sources) {
|
|
50
|
+
const source = record(value2);
|
|
51
|
+
if (!source || Object.keys(source).some(
|
|
52
|
+
(key) => !["id", "title", "url"].includes(key)
|
|
53
|
+
) || !text(source.id, Infinity) || !text(source.title) || source.url !== void 0 && typeof source.url !== "string")
|
|
54
|
+
return null;
|
|
55
|
+
const url = safeSearchUrl(source.url);
|
|
56
|
+
sources.push({
|
|
57
|
+
id: source.id.trim(),
|
|
58
|
+
title: source.title.trim(),
|
|
59
|
+
...url ? { url } : {}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
let cta;
|
|
63
|
+
if (data.cta !== void 0) {
|
|
64
|
+
const action = record(data.cta);
|
|
65
|
+
if (!action || Object.keys(action).some((key) => !["label", "url"].includes(key)) || !text(action.label) || action.url !== void 0 && typeof action.url !== "string")
|
|
66
|
+
return null;
|
|
67
|
+
const url = safeSearchUrl(action.url);
|
|
68
|
+
cta = { label: action.label.trim(), ...url ? { url } : {} };
|
|
69
|
+
}
|
|
70
|
+
return { sources, ...cta ? { cta } : {} };
|
|
71
|
+
}
|
|
72
|
+
function parseAgentSearchDiscoveryOutput(value) {
|
|
73
|
+
let decoded = value;
|
|
74
|
+
if (typeof value === "string") {
|
|
75
|
+
try {
|
|
76
|
+
decoded = JSON.parse(value);
|
|
77
|
+
} catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const data = record(decoded);
|
|
82
|
+
if (!data || Object.keys(data).some(
|
|
83
|
+
(key) => !["answer", "sources", "cta", "suggestions"].includes(key)
|
|
84
|
+
) || !text(data.answer, 5e4) || !Array.isArray(data.suggestions) || data.suggestions.length > 8 || !data.suggestions.every((item) => text(item)))
|
|
85
|
+
return null;
|
|
86
|
+
const references = parseAgentSearchReferences(data);
|
|
87
|
+
return references ? {
|
|
88
|
+
...references,
|
|
89
|
+
answer: data.answer.trim(),
|
|
90
|
+
suggestions: data.suggestions.map((item) => item.trim())
|
|
91
|
+
} : null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/runtime/tool-ui.ts
|
|
95
|
+
var AGENT_TOOL_UI_SCHEMA_VERSION = "webless.tool-ui.v1";
|
|
96
|
+
function isRecord(value) {
|
|
97
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
98
|
+
}
|
|
99
|
+
function isJsonValue(value, seen = /* @__PURE__ */ new Set()) {
|
|
100
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
104
|
+
if (typeof value !== "object") return false;
|
|
105
|
+
if (seen.has(value)) return false;
|
|
106
|
+
seen.add(value);
|
|
107
|
+
const valid = Array.isArray(value) ? value.every((item) => isJsonValue(item, seen)) : Object.entries(value).every(
|
|
108
|
+
([key, item]) => typeof key === "string" && isJsonValue(item, seen)
|
|
109
|
+
);
|
|
110
|
+
seen.delete(value);
|
|
111
|
+
return valid;
|
|
112
|
+
}
|
|
113
|
+
function boundedString(value, max) {
|
|
114
|
+
if (typeof value !== "string" || value.trim().length === 0 || value.length > max) {
|
|
115
|
+
return void 0;
|
|
116
|
+
}
|
|
117
|
+
return value.trim();
|
|
118
|
+
}
|
|
119
|
+
function numberValue(value) {
|
|
120
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
121
|
+
}
|
|
122
|
+
function integerValue(value) {
|
|
123
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 8e3 ? value : void 0;
|
|
124
|
+
}
|
|
125
|
+
function isFieldKind(value) {
|
|
126
|
+
return typeof value === "string" && [
|
|
127
|
+
"text",
|
|
128
|
+
"textarea",
|
|
129
|
+
"email",
|
|
130
|
+
"number",
|
|
131
|
+
"select",
|
|
132
|
+
"multi-select",
|
|
133
|
+
"checkbox",
|
|
134
|
+
"confirmation",
|
|
135
|
+
"radio",
|
|
136
|
+
"date",
|
|
137
|
+
"time",
|
|
138
|
+
"date-time",
|
|
139
|
+
"calendar",
|
|
140
|
+
"range",
|
|
141
|
+
"json"
|
|
142
|
+
].includes(value);
|
|
143
|
+
}
|
|
144
|
+
function parseField(value) {
|
|
145
|
+
if (!isRecord(value)) return null;
|
|
146
|
+
if (!hasOnlyKeys(value, [
|
|
147
|
+
"description",
|
|
148
|
+
"kind",
|
|
149
|
+
"label",
|
|
150
|
+
"max",
|
|
151
|
+
"maxItems",
|
|
152
|
+
"maxLength",
|
|
153
|
+
"min",
|
|
154
|
+
"minLength",
|
|
155
|
+
"options",
|
|
156
|
+
"path",
|
|
157
|
+
"placeholder",
|
|
158
|
+
"required",
|
|
159
|
+
"step",
|
|
160
|
+
"defaultValue"
|
|
161
|
+
])) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
if (!isFieldKind(value.kind)) return null;
|
|
165
|
+
const path = boundedString(value.path, 160);
|
|
166
|
+
const label = boundedString(value.label, 160);
|
|
167
|
+
const description = value.description === void 0 ? void 0 : boundedString(value.description, 500);
|
|
168
|
+
const placeholder = value.placeholder === void 0 || typeof value.placeholder !== "string" ? void 0 : value.placeholder;
|
|
169
|
+
const required = value.required === void 0 || typeof value.required !== "boolean" ? void 0 : value.required;
|
|
170
|
+
const min = value.min === void 0 ? void 0 : numberValue(value.min);
|
|
171
|
+
const max = value.max === void 0 ? void 0 : numberValue(value.max);
|
|
172
|
+
const maxItems = value.maxItems === void 0 ? void 0 : integerValue(value.maxItems);
|
|
173
|
+
const step = value.step === void 0 ? void 0 : numberValue(value.step);
|
|
174
|
+
const minLength = value.minLength === void 0 ? void 0 : integerValue(value.minLength);
|
|
175
|
+
const maxLength = value.maxLength === void 0 ? void 0 : integerValue(value.maxLength);
|
|
176
|
+
const defaultValue = value.defaultValue === void 0 || !isJsonValue(value.defaultValue) ? void 0 : value.defaultValue;
|
|
177
|
+
if (!path || !/^[A-Za-z0-9_.[\]-]+$/u.test(path) || !label) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
if (value.description !== void 0 && !description) return null;
|
|
181
|
+
if (value.placeholder !== void 0 && placeholder === void 0) return null;
|
|
182
|
+
if (value.required !== void 0 && required === void 0) return null;
|
|
183
|
+
if (value.min !== void 0 && min === void 0) return null;
|
|
184
|
+
if (value.max !== void 0 && max === void 0) return null;
|
|
185
|
+
if (value.maxItems !== void 0 && (maxItems === void 0 || maxItems < 1 || maxItems > 100))
|
|
186
|
+
return null;
|
|
187
|
+
if (value.step !== void 0 && step === void 0) return null;
|
|
188
|
+
if (value.minLength !== void 0 && minLength === void 0) return null;
|
|
189
|
+
if (value.maxLength !== void 0 && maxLength === void 0) return null;
|
|
190
|
+
if (value.defaultValue !== void 0 && defaultValue === void 0)
|
|
191
|
+
return null;
|
|
192
|
+
if (value.options !== void 0) {
|
|
193
|
+
if (!Array.isArray(value.options) || value.options.length > 100)
|
|
194
|
+
return null;
|
|
195
|
+
for (const option of value.options) {
|
|
196
|
+
if (!isRecord(option) || !boundedString(option.label, 160) || !isJsonValue(option.value)) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
kind: value.kind,
|
|
203
|
+
path,
|
|
204
|
+
label,
|
|
205
|
+
...description ? { description } : {},
|
|
206
|
+
...placeholder !== void 0 ? { placeholder } : {},
|
|
207
|
+
...required !== void 0 ? { required } : {},
|
|
208
|
+
...defaultValue !== void 0 ? { defaultValue } : {},
|
|
209
|
+
...value.options !== void 0 ? { options: value.options } : {},
|
|
210
|
+
...min !== void 0 ? { min } : {},
|
|
211
|
+
...max !== void 0 ? { max } : {},
|
|
212
|
+
...maxItems !== void 0 ? { maxItems } : {},
|
|
213
|
+
...step !== void 0 ? { step } : {},
|
|
214
|
+
...minLength !== void 0 ? { minLength } : {},
|
|
215
|
+
...maxLength !== void 0 ? { maxLength } : {}
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function parseStep(value) {
|
|
219
|
+
if (!isRecord(value)) return null;
|
|
220
|
+
if (!hasOnlyKeys(value, ["description", "fieldPaths", "id", "label"])) {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
const id = boundedString(value.id, 80);
|
|
224
|
+
const label = boundedString(value.label, 160);
|
|
225
|
+
const description = value.description === void 0 ? void 0 : boundedString(value.description, 500);
|
|
226
|
+
if (!id || !/^[A-Za-z0-9][A-Za-z0-9_-]*$/u.test(id) || !label || value.description !== void 0 && !description || !Array.isArray(value.fieldPaths) || value.fieldPaths.length < 1 || value.fieldPaths.length > 32 || value.fieldPaths.some(
|
|
227
|
+
(path) => typeof path !== "string" || !/^[A-Za-z0-9_.[\]-]+$/u.test(path) || path.length > 160
|
|
228
|
+
)) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
id,
|
|
233
|
+
label,
|
|
234
|
+
fieldPaths: value.fieldPaths,
|
|
235
|
+
...description ? { description } : {}
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function parseAction(value) {
|
|
239
|
+
if (!isRecord(value)) return null;
|
|
240
|
+
if (!hasOnlyKeys(value, ["id", "label"])) return null;
|
|
241
|
+
const label = boundedString(value.label, 80);
|
|
242
|
+
if (value.id !== "submit" && value.id !== "back" && value.id !== "next" && value.id !== "reset" || !label) {
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
id: value.id,
|
|
247
|
+
label
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function parseAgentToolUiSurface(value) {
|
|
251
|
+
if (!isRecord(value) || value.schemaVersion !== AGENT_TOOL_UI_SCHEMA_VERSION)
|
|
252
|
+
return null;
|
|
253
|
+
if (!hasOnlyKeys(value, [
|
|
254
|
+
"actions",
|
|
255
|
+
"description",
|
|
256
|
+
"fields",
|
|
257
|
+
"id",
|
|
258
|
+
"operationId",
|
|
259
|
+
"requestId",
|
|
260
|
+
"schemaVersion",
|
|
261
|
+
"steps",
|
|
262
|
+
"submitLabel",
|
|
263
|
+
"title",
|
|
264
|
+
"toolSlug",
|
|
265
|
+
"values"
|
|
266
|
+
])) {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
const id = boundedString(value.id, 200);
|
|
270
|
+
const title = boundedString(value.title, 200);
|
|
271
|
+
const toolSlug = boundedString(value.toolSlug, 200);
|
|
272
|
+
const description = value.description === void 0 ? void 0 : boundedString(value.description, 800);
|
|
273
|
+
const operationId = value.operationId === void 0 ? void 0 : boundedString(value.operationId, 200);
|
|
274
|
+
const requestId = value.requestId === void 0 ? void 0 : boundedString(value.requestId, 200);
|
|
275
|
+
const submitLabel = value.submitLabel === void 0 ? void 0 : boundedString(value.submitLabel, 80);
|
|
276
|
+
if (!id || !title || !toolSlug || !Array.isArray(value.fields) || value.fields.length < 1 || value.fields.length > 32) {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
const fields = value.fields.map(parseField);
|
|
280
|
+
if (fields.some((field) => field === null)) return null;
|
|
281
|
+
const steps = value.steps === void 0 ? void 0 : Array.isArray(value.steps) && value.steps.length <= 8 ? value.steps.map(parseStep) : null;
|
|
282
|
+
if (steps?.some((step) => step === null)) return null;
|
|
283
|
+
const actions = value.actions === void 0 ? void 0 : Array.isArray(value.actions) && value.actions.length <= 8 ? value.actions.map(parseAction) : null;
|
|
284
|
+
if (actions?.some((action) => action === null)) return null;
|
|
285
|
+
if (value.description !== void 0 && !description) return null;
|
|
286
|
+
if (value.operationId !== void 0 && !operationId) return null;
|
|
287
|
+
if (value.requestId !== void 0 && !requestId) return null;
|
|
288
|
+
if (value.submitLabel !== void 0 && !submitLabel) return null;
|
|
289
|
+
const values = value.values !== void 0 && isRecord(value.values) ? value.values : void 0;
|
|
290
|
+
if (value.values !== void 0) {
|
|
291
|
+
if (!values || !Object.values(values).every((item) => isJsonValue(item)))
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
schemaVersion: AGENT_TOOL_UI_SCHEMA_VERSION,
|
|
296
|
+
id,
|
|
297
|
+
title,
|
|
298
|
+
toolSlug,
|
|
299
|
+
fields,
|
|
300
|
+
...actions ? { actions } : {},
|
|
301
|
+
...description ? { description } : {},
|
|
302
|
+
...operationId ? { operationId } : {},
|
|
303
|
+
...requestId ? { requestId } : {},
|
|
304
|
+
...submitLabel ? { submitLabel } : {},
|
|
305
|
+
...steps ? { steps } : {},
|
|
306
|
+
...values ? { values } : {}
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
function hasOnlyKeys(value, allowed) {
|
|
310
|
+
const allowedKeys = new Set(allowed);
|
|
311
|
+
return Object.keys(value).every((key) => allowedKeys.has(key));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// src/runtime/tool-result-envelope.ts
|
|
315
|
+
var ENVELOPE_KEYS = /* @__PURE__ */ new Set([
|
|
316
|
+
"schemaVersion",
|
|
317
|
+
"output",
|
|
318
|
+
"presentationKinds",
|
|
319
|
+
"ui"
|
|
320
|
+
]);
|
|
321
|
+
function isRecord2(value) {
|
|
322
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
323
|
+
}
|
|
324
|
+
function isJsonValue2(value, seen = /* @__PURE__ */ new Set()) {
|
|
325
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
329
|
+
if (typeof value !== "object") return false;
|
|
330
|
+
if (seen.has(value)) return false;
|
|
331
|
+
seen.add(value);
|
|
332
|
+
const valid = Array.isArray(value) ? value.every((item) => isJsonValue2(item, seen)) : Object.entries(value).every(
|
|
333
|
+
([key, item]) => typeof key === "string" && isJsonValue2(item, seen)
|
|
334
|
+
);
|
|
335
|
+
seen.delete(value);
|
|
336
|
+
return valid;
|
|
337
|
+
}
|
|
338
|
+
function decodeEnvelope(value) {
|
|
339
|
+
if (typeof value !== "string") return value;
|
|
340
|
+
try {
|
|
341
|
+
return JSON.parse(value);
|
|
342
|
+
} catch {
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function parseAgentToolResultEnvelope(value) {
|
|
347
|
+
const decoded = decodeEnvelope(value);
|
|
348
|
+
if (!isRecord2(decoded)) return null;
|
|
349
|
+
const keys = Object.keys(decoded);
|
|
350
|
+
if (keys.some((key) => !ENVELOPE_KEYS.has(key)) || decoded.schemaVersion !== "webless.tool-result.v1" || !isJsonValue2(decoded.output) || !Array.isArray(decoded.presentationKinds) || decoded.presentationKinds.length < 1 || decoded.presentationKinds.length > 16) {
|
|
351
|
+
return null;
|
|
352
|
+
}
|
|
353
|
+
const presentationKinds = decoded.presentationKinds.flatMap((kind) => {
|
|
354
|
+
if (typeof kind !== "string") return [];
|
|
355
|
+
const normalized = kind.trim();
|
|
356
|
+
return normalized && normalized.length <= 128 ? [normalized] : [];
|
|
357
|
+
});
|
|
358
|
+
if (presentationKinds.length !== decoded.presentationKinds.length) {
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
const ui = decoded.ui === void 0 ? void 0 : parseAgentToolUiSurface(decoded.ui);
|
|
362
|
+
if (decoded.ui !== void 0 && !ui) return null;
|
|
363
|
+
return {
|
|
364
|
+
schemaVersion: "webless.tool-result.v1",
|
|
365
|
+
output: decoded.output,
|
|
366
|
+
presentationKinds,
|
|
367
|
+
...ui ? { ui } : {}
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// src/react/lib/composer-form.ts
|
|
372
|
+
var MAX_FORM_FIELDS = 5;
|
|
373
|
+
function asRecord(value) {
|
|
374
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
375
|
+
}
|
|
376
|
+
function asString(value) {
|
|
377
|
+
return typeof value === "string" ? value.trim() : "";
|
|
378
|
+
}
|
|
379
|
+
function isFieldKind2(value) {
|
|
380
|
+
return value === "text" || value === "email" || value === "tel" || value === "textarea";
|
|
381
|
+
}
|
|
382
|
+
function parseVisitorFormFields(value) {
|
|
383
|
+
if (!Array.isArray(value)) return [];
|
|
384
|
+
const fields = [];
|
|
385
|
+
const seen = /* @__PURE__ */ new Set();
|
|
386
|
+
for (const item of value) {
|
|
387
|
+
const record2 = asRecord(item);
|
|
388
|
+
const id = asString(record2?.id).toLowerCase().replace(/[^a-z0-9_-]/g, "");
|
|
389
|
+
const kind = asString(record2?.kind);
|
|
390
|
+
if (!record2 || !id || seen.has(id) || !isFieldKind2(kind)) continue;
|
|
391
|
+
seen.add(id);
|
|
392
|
+
const label = asString(record2.label) || id;
|
|
393
|
+
fields.push({
|
|
394
|
+
id,
|
|
395
|
+
kind,
|
|
396
|
+
label,
|
|
397
|
+
placeholder: asString(record2.placeholder) || label,
|
|
398
|
+
required: record2.required !== false,
|
|
399
|
+
...asString(record2.autocomplete) ? { autocomplete: asString(record2.autocomplete) } : {}
|
|
400
|
+
});
|
|
401
|
+
if (fields.length >= MAX_FORM_FIELDS) break;
|
|
402
|
+
}
|
|
403
|
+
return fields;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// src/react/lib/tool-card.ts
|
|
407
|
+
function asRecord2(value) {
|
|
408
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
409
|
+
}
|
|
410
|
+
function asString2(value) {
|
|
411
|
+
return typeof value === "string" ? value.trim() : "";
|
|
412
|
+
}
|
|
413
|
+
function isEventUri(value) {
|
|
414
|
+
return /^https:\/\/api\.calendly\.com\/scheduled_events\/[^/]+$/i.test(value);
|
|
415
|
+
}
|
|
416
|
+
function isEventTypeUri(value) {
|
|
417
|
+
return /^https:\/\/api\.calendly\.com\/event_types\/[^/]+$/i.test(value);
|
|
418
|
+
}
|
|
419
|
+
function parseToolCard(value) {
|
|
420
|
+
const record2 = asRecord2(value);
|
|
421
|
+
if (!record2) return null;
|
|
422
|
+
if (record2.booking_offer && asString2(record2.type) !== "booking_offer") {
|
|
423
|
+
const nested = parseToolCard(record2.booking_offer);
|
|
424
|
+
if (nested) return nested;
|
|
425
|
+
}
|
|
426
|
+
if (record2.visitor_booking && asString2(record2.type) !== "booking_confirmed") {
|
|
427
|
+
const nested = parseToolCard(record2.visitor_booking);
|
|
428
|
+
if (nested) return nested;
|
|
429
|
+
}
|
|
430
|
+
const type = asString2(record2.type);
|
|
431
|
+
if (type === "booking_offer") {
|
|
432
|
+
const eventTypes = Array.isArray(record2.eventTypes) ? record2.eventTypes.flatMap((item) => {
|
|
433
|
+
const entry = asRecord2(item);
|
|
434
|
+
const uri = asString2(entry?.uri);
|
|
435
|
+
if (!entry || !uri) return [];
|
|
436
|
+
const duration = entry.duration;
|
|
437
|
+
const locationKind = asString2(entry.locationKind);
|
|
438
|
+
const location = asString2(entry.location);
|
|
439
|
+
return [
|
|
440
|
+
{
|
|
441
|
+
name: asString2(entry.name) || "Meeting",
|
|
442
|
+
uri,
|
|
443
|
+
...typeof duration === "number" ? { duration } : {},
|
|
444
|
+
...locationKind ? { locationKind } : {},
|
|
445
|
+
...location ? { location } : {}
|
|
446
|
+
}
|
|
447
|
+
];
|
|
448
|
+
}) : [];
|
|
449
|
+
const slots = Array.isArray(record2.slots) ? record2.slots.flatMap((item) => {
|
|
450
|
+
const entry = asRecord2(item);
|
|
451
|
+
const startTime = asString2(entry?.startTime);
|
|
452
|
+
if (!entry || !startTime) return [];
|
|
453
|
+
const eventTypeUri = asString2(entry.eventTypeUri);
|
|
454
|
+
return [
|
|
455
|
+
{
|
|
456
|
+
startTime,
|
|
457
|
+
...isEventTypeUri(eventTypeUri) ? { eventTypeUri } : {}
|
|
458
|
+
}
|
|
459
|
+
];
|
|
460
|
+
}) : [];
|
|
461
|
+
if (eventTypes.length === 0 && slots.length === 0) return null;
|
|
462
|
+
return { type: "booking_offer", eventTypes, slots };
|
|
463
|
+
}
|
|
464
|
+
if (type === "booking_confirmed") {
|
|
465
|
+
const eventUri = asString2(record2.eventUri);
|
|
466
|
+
if (!isEventUri(eventUri)) return null;
|
|
467
|
+
const inviteeUri = asString2(record2.inviteeUri);
|
|
468
|
+
const inviteeEmail = asString2(record2.inviteeEmail);
|
|
469
|
+
const startTime = asString2(record2.startTime);
|
|
470
|
+
return {
|
|
471
|
+
type: "booking_confirmed",
|
|
472
|
+
eventUri,
|
|
473
|
+
...inviteeUri ? { inviteeUri } : {},
|
|
474
|
+
...inviteeEmail ? { inviteeEmail } : {},
|
|
475
|
+
...startTime ? { startTime } : {}
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
if (type === "booking_canceled") {
|
|
479
|
+
const eventUri = asString2(record2.eventUri);
|
|
480
|
+
if (!isEventUri(eventUri)) return null;
|
|
481
|
+
return { type: "booking_canceled", eventUri };
|
|
482
|
+
}
|
|
483
|
+
if (type === "visitor_form") {
|
|
484
|
+
const fields = parseVisitorFormFields(record2.fields);
|
|
485
|
+
if (fields.length < 2) return null;
|
|
486
|
+
return { type: "visitor_form", fields };
|
|
487
|
+
}
|
|
488
|
+
return null;
|
|
489
|
+
}
|
|
490
|
+
function bookingCardFromActionOutput(output) {
|
|
491
|
+
const record2 = asRecord2(output);
|
|
492
|
+
const data = asRecord2(record2?.output) ?? asRecord2(record2?.data) ?? record2;
|
|
493
|
+
return parseToolCard(data);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// src/react/lib/tool-result.ts
|
|
497
|
+
var MAX_TEXT_LENGTH = 240;
|
|
498
|
+
var MAX_DETAILS = 6;
|
|
499
|
+
var MAX_LINKS = 4;
|
|
500
|
+
var MAX_COLLECTION_ITEMS = 8;
|
|
501
|
+
var INTERNAL_FACT_LABEL = /^(hs\b|createdate|created at|updatedate|updated at|firstname|first name|lastname|last name|vid|objectid|object id|all contact)/iu;
|
|
502
|
+
function safeText(value) {
|
|
503
|
+
if (typeof value !== "string") return "";
|
|
504
|
+
return value.trim().slice(0, MAX_TEXT_LENGTH);
|
|
505
|
+
}
|
|
506
|
+
function safeHref(value) {
|
|
507
|
+
const text2 = safeText(value);
|
|
508
|
+
if (!text2) return "";
|
|
509
|
+
try {
|
|
510
|
+
const url = new URL(text2);
|
|
511
|
+
return url.protocol === "https:" ? url.toString() : "";
|
|
512
|
+
} catch {
|
|
513
|
+
return "";
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
function fallbackTitle(result) {
|
|
517
|
+
if (result.status === "failed") return "Couldn\u2019t complete this action";
|
|
518
|
+
if (result.status === "rejected") return "Action not approved";
|
|
519
|
+
return "Action completed";
|
|
520
|
+
}
|
|
521
|
+
function bookingPresenter(kind) {
|
|
522
|
+
return {
|
|
523
|
+
kind,
|
|
524
|
+
present: ({ envelope }) => {
|
|
525
|
+
const card = bookingCardFromActionOutput(envelope.output);
|
|
526
|
+
return card && card.type === kind ? { kind: "booking", card } : null;
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
function providerErrorPresenter() {
|
|
531
|
+
return {
|
|
532
|
+
kind: "provider_error",
|
|
533
|
+
present: ({ envelope }) => {
|
|
534
|
+
const output = asRecord3(envelope.output);
|
|
535
|
+
const providerError = asRecord3(output?.providerError);
|
|
536
|
+
const message = safeText(providerError?.message);
|
|
537
|
+
const action = safeText(providerError?.action);
|
|
538
|
+
if (!message || !action) return null;
|
|
539
|
+
const resourceLabels = Array.isArray(providerError?.resourceLabels) ? providerError.resourceLabels.map(safeText).filter(Boolean).slice(0, MAX_DETAILS) : [];
|
|
540
|
+
return {
|
|
541
|
+
kind: "summary",
|
|
542
|
+
status: "failed",
|
|
543
|
+
title: message,
|
|
544
|
+
description: action,
|
|
545
|
+
...resourceLabels.length ? {
|
|
546
|
+
details: [
|
|
547
|
+
{ label: "Affected", value: resourceLabels.join(", ") }
|
|
548
|
+
]
|
|
549
|
+
} : {}
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
function asRecord3(value) {
|
|
555
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
556
|
+
}
|
|
557
|
+
function parseFacts(value) {
|
|
558
|
+
if (!Array.isArray(value)) return [];
|
|
559
|
+
return value.flatMap((item) => {
|
|
560
|
+
const fact = asRecord3(item);
|
|
561
|
+
const label = safeText(fact?.label);
|
|
562
|
+
const factValue = safeText(fact?.value);
|
|
563
|
+
if (!label || !factValue) return [];
|
|
564
|
+
if (INTERNAL_FACT_LABEL.test(label)) return [];
|
|
565
|
+
return [{ label, value: factValue }];
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
function parseLinks(output, defaultLabel) {
|
|
569
|
+
const href = safeHref(output.href);
|
|
570
|
+
const linkLabel = safeText(output.linkLabel) || defaultLabel;
|
|
571
|
+
return href ? [{ label: linkLabel, href }] : [];
|
|
572
|
+
}
|
|
573
|
+
function entityResultPresenter() {
|
|
574
|
+
return {
|
|
575
|
+
kind: "entity_result",
|
|
576
|
+
present: ({ envelope, result }) => {
|
|
577
|
+
const output = asRecord3(envelope.output);
|
|
578
|
+
if (!output) return null;
|
|
579
|
+
const title = safeText(output.title) || fallbackTitle(result);
|
|
580
|
+
const description = safeText(output.description);
|
|
581
|
+
const facts = parseFacts(output.facts).filter((fact) => fact.value !== description && fact.value !== title).slice(0, MAX_DETAILS);
|
|
582
|
+
return {
|
|
583
|
+
kind: "entity",
|
|
584
|
+
title,
|
|
585
|
+
...description && description !== title ? { description } : {},
|
|
586
|
+
...facts.length ? { details: facts } : {},
|
|
587
|
+
...parseLinks(output, "Open record").length ? { links: parseLinks(output, "Open record") } : {}
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
function collectionResultPresenter() {
|
|
593
|
+
return {
|
|
594
|
+
kind: "collection",
|
|
595
|
+
present: ({ envelope, result }) => {
|
|
596
|
+
const output = asRecord3(envelope.output);
|
|
597
|
+
if (!output) return null;
|
|
598
|
+
const title = safeText(output.title) || fallbackTitleFromKind("collection");
|
|
599
|
+
const items = Array.isArray(output.items) ? output.items.slice(0, MAX_COLLECTION_ITEMS).flatMap((item) => {
|
|
600
|
+
const entry = asRecord3(item);
|
|
601
|
+
if (!entry) return [];
|
|
602
|
+
const itemTitle = safeText(entry.title);
|
|
603
|
+
if (!itemTitle) return [];
|
|
604
|
+
const description = safeText(entry.description);
|
|
605
|
+
const details = parseFacts(entry.facts).slice(0, MAX_DETAILS);
|
|
606
|
+
const href = safeHref(entry.href);
|
|
607
|
+
return [
|
|
608
|
+
{
|
|
609
|
+
title: itemTitle,
|
|
610
|
+
...description ? { description } : {},
|
|
611
|
+
...details.length ? { details } : {},
|
|
612
|
+
...href ? { href } : {}
|
|
613
|
+
}
|
|
614
|
+
];
|
|
615
|
+
}) : [];
|
|
616
|
+
return {
|
|
617
|
+
kind: "collection",
|
|
618
|
+
title,
|
|
619
|
+
items
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
function signatureResultPresenter() {
|
|
625
|
+
return {
|
|
626
|
+
kind: "signature",
|
|
627
|
+
present: ({ envelope, result }) => {
|
|
628
|
+
const output = asRecord3(envelope.output);
|
|
629
|
+
if (!output) return null;
|
|
630
|
+
const title = safeText(output.title) || fallbackTitleFromKind("signature");
|
|
631
|
+
const description = safeText(output.description);
|
|
632
|
+
const statusLabel = safeText(output.status);
|
|
633
|
+
return {
|
|
634
|
+
kind: "signature",
|
|
635
|
+
title,
|
|
636
|
+
...description ? { description } : {},
|
|
637
|
+
...statusLabel ? { statusLabel } : {},
|
|
638
|
+
...parseLinks(output, "Sign now").length ? { links: parseLinks(output, "Sign now") } : {}
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
function resultCardPresenter(kind) {
|
|
644
|
+
return {
|
|
645
|
+
kind,
|
|
646
|
+
present: ({ envelope, result }) => {
|
|
647
|
+
const output = asRecord3(envelope.output);
|
|
648
|
+
if (!output) return null;
|
|
649
|
+
const title = safeText(output.title) || fallbackTitleFromKind(kind);
|
|
650
|
+
const description = safeText(output.description);
|
|
651
|
+
const facts = parseFacts(output.facts).slice(0, MAX_DETAILS);
|
|
652
|
+
return {
|
|
653
|
+
kind: "summary",
|
|
654
|
+
title,
|
|
655
|
+
...description && description !== title ? { description } : {},
|
|
656
|
+
...facts.length ? { details: facts } : {},
|
|
657
|
+
...parseLinks(output, "Open").length ? { links: parseLinks(output, "Open") } : {}
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
function fallbackTitleFromKind(kind) {
|
|
663
|
+
if (kind === "document") return "Document ready";
|
|
664
|
+
if (kind === "signature") return "Ready to sign";
|
|
665
|
+
if (kind === "payment") return "Payment link";
|
|
666
|
+
if (kind === "collection") return "Results";
|
|
667
|
+
if (kind === "confirmation_result") return "Confirmed";
|
|
668
|
+
return "Saved";
|
|
669
|
+
}
|
|
670
|
+
var builtInVisitorToolResultRegistry = [
|
|
671
|
+
providerErrorPresenter(),
|
|
672
|
+
bookingPresenter("booking_offer"),
|
|
673
|
+
bookingPresenter("booking_confirmed"),
|
|
674
|
+
bookingPresenter("booking_canceled"),
|
|
675
|
+
entityResultPresenter(),
|
|
676
|
+
collectionResultPresenter(),
|
|
677
|
+
signatureResultPresenter(),
|
|
678
|
+
resultCardPresenter("document"),
|
|
679
|
+
resultCardPresenter("payment"),
|
|
680
|
+
resultCardPresenter("confirmation_result")
|
|
681
|
+
];
|
|
682
|
+
function resolvePresenterOutput(result, envelope, registry) {
|
|
683
|
+
const presenters = [...registry, ...builtInVisitorToolResultRegistry];
|
|
684
|
+
for (const presentationKind of envelope.presentationKinds) {
|
|
685
|
+
const presenter = presenters.find(
|
|
686
|
+
(candidate) => candidate.kind === presentationKind
|
|
687
|
+
);
|
|
688
|
+
if (!presenter) continue;
|
|
689
|
+
try {
|
|
690
|
+
const presented = presenter.present({
|
|
691
|
+
envelope,
|
|
692
|
+
presentationKind,
|
|
693
|
+
result
|
|
694
|
+
});
|
|
695
|
+
if (presented) return presented;
|
|
696
|
+
} catch {
|
|
697
|
+
return null;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
return null;
|
|
701
|
+
}
|
|
702
|
+
function finalizeSummaryPresentation(result, proposed) {
|
|
703
|
+
const title = safeText(proposed.title) || fallbackTitle(result);
|
|
704
|
+
const description = safeText(proposed.description);
|
|
705
|
+
const details = proposed.details?.slice(0, MAX_DETAILS).flatMap((detail) => {
|
|
706
|
+
const label = safeText(detail.label);
|
|
707
|
+
const value = safeText(detail.value);
|
|
708
|
+
if (!label || !value) return [];
|
|
709
|
+
if (INTERNAL_FACT_LABEL.test(label)) return [];
|
|
710
|
+
if (value === title || value === description) return [];
|
|
711
|
+
return [{ label, value }];
|
|
712
|
+
});
|
|
713
|
+
const links = proposed.links?.slice(0, MAX_LINKS).flatMap((link) => {
|
|
714
|
+
const label = safeText(link.label);
|
|
715
|
+
const href = safeHref(link.href);
|
|
716
|
+
return label && href ? [{ label, href }] : [];
|
|
717
|
+
});
|
|
718
|
+
return {
|
|
719
|
+
id: result.callId,
|
|
720
|
+
toolName: result.toolName,
|
|
721
|
+
status: proposed.status ?? result.status,
|
|
722
|
+
kind: "summary",
|
|
723
|
+
title,
|
|
724
|
+
...description && description !== title ? { description } : {},
|
|
725
|
+
...details?.length ? { details } : {},
|
|
726
|
+
...links?.length ? { links } : {}
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
function presentVisitorToolResult(result, registry = []) {
|
|
730
|
+
if (result.toolName === "search_discovery" && result.status === "completed") {
|
|
731
|
+
const envelope2 = parseAgentToolResultEnvelope(result.output);
|
|
732
|
+
const search = parseAgentSearchDiscoveryOutput(
|
|
733
|
+
envelope2?.output ?? result.output
|
|
734
|
+
);
|
|
735
|
+
if (search) {
|
|
736
|
+
return {
|
|
737
|
+
id: result.callId,
|
|
738
|
+
toolName: "search_discovery",
|
|
739
|
+
status: "completed",
|
|
740
|
+
kind: "search",
|
|
741
|
+
sources: search.sources,
|
|
742
|
+
...search.cta ? { cta: search.cta } : {}
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
const envelope = parseAgentToolResultEnvelope(result.output) ?? providerErrorEnvelope(result.output) ?? legacyBookingEnvelope(result.output);
|
|
747
|
+
const proposed = envelope ? resolvePresenterOutput(result, envelope, registry) : null;
|
|
748
|
+
if (proposed?.kind === "booking") {
|
|
749
|
+
return {
|
|
750
|
+
id: result.callId,
|
|
751
|
+
toolName: result.toolName,
|
|
752
|
+
status: result.status,
|
|
753
|
+
kind: "booking",
|
|
754
|
+
card: proposed.card
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
if (envelope?.ui && envelope.presentationKinds.includes("tool_input")) {
|
|
758
|
+
return {
|
|
759
|
+
id: result.callId,
|
|
760
|
+
toolName: result.toolName,
|
|
761
|
+
status: result.status,
|
|
762
|
+
kind: "input",
|
|
763
|
+
surface: envelope.ui
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
if (!proposed) {
|
|
767
|
+
if (result.status === "failed" || result.status === "rejected") {
|
|
768
|
+
return {
|
|
769
|
+
id: result.callId,
|
|
770
|
+
toolName: result.toolName,
|
|
771
|
+
status: result.status,
|
|
772
|
+
kind: "summary",
|
|
773
|
+
title: fallbackTitle(result)
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
return {
|
|
777
|
+
id: result.callId,
|
|
778
|
+
toolName: result.toolName,
|
|
779
|
+
status: result.status,
|
|
780
|
+
kind: "hidden"
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
if (proposed.kind === "entity") {
|
|
784
|
+
return {
|
|
785
|
+
id: result.callId,
|
|
786
|
+
toolName: result.toolName,
|
|
787
|
+
status: result.status,
|
|
788
|
+
...proposed
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
if (proposed.kind === "collection") {
|
|
792
|
+
return {
|
|
793
|
+
id: result.callId,
|
|
794
|
+
toolName: result.toolName,
|
|
795
|
+
status: result.status,
|
|
796
|
+
...proposed
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
if (proposed.kind === "signature") {
|
|
800
|
+
return {
|
|
801
|
+
id: result.callId,
|
|
802
|
+
toolName: result.toolName,
|
|
803
|
+
status: result.status,
|
|
804
|
+
...proposed
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
return finalizeSummaryPresentation(result, proposed);
|
|
808
|
+
}
|
|
809
|
+
function providerErrorEnvelope(output) {
|
|
810
|
+
const record2 = asRecord3(output);
|
|
811
|
+
const providerError = asRecord3(record2?.providerError);
|
|
812
|
+
const message = safeText(providerError?.message);
|
|
813
|
+
const action = safeText(providerError?.action);
|
|
814
|
+
if (!message || !action) return null;
|
|
815
|
+
const resourceLabels = Array.isArray(providerError?.resourceLabels) ? providerError.resourceLabels.map(safeText).filter(Boolean).slice(0, MAX_DETAILS) : [];
|
|
816
|
+
return {
|
|
817
|
+
schemaVersion: "webless.tool-result.v1",
|
|
818
|
+
output: {
|
|
819
|
+
providerError: {
|
|
820
|
+
action,
|
|
821
|
+
message,
|
|
822
|
+
...resourceLabels.length ? { resourceLabels } : {}
|
|
823
|
+
}
|
|
824
|
+
},
|
|
825
|
+
presentationKinds: ["provider_error"]
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
function legacyBookingEnvelope(output) {
|
|
829
|
+
const card = bookingCardFromActionOutput(output);
|
|
830
|
+
return card ? {
|
|
831
|
+
schemaVersion: "webless.tool-result.v1",
|
|
832
|
+
output: card,
|
|
833
|
+
presentationKinds: [card.type]
|
|
834
|
+
} : null;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
// src/presentation.ts
|
|
838
|
+
function presentTranscriptToolResult(result) {
|
|
839
|
+
const output = parseAgentToolResultEnvelope(result.output)?.output ?? result.output;
|
|
840
|
+
const legacyError = output !== null && typeof output === "object" && "error" in output && typeof output.error === "string" && output.error.trim().length > 0;
|
|
841
|
+
return presentVisitorToolResult(
|
|
842
|
+
legacyError ? { ...result, status: "failed" } : result
|
|
843
|
+
);
|
|
844
|
+
}
|
|
845
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
846
|
+
0 && (module.exports = {
|
|
847
|
+
presentTranscriptToolResult,
|
|
848
|
+
presentVisitorToolResult
|
|
849
|
+
});
|
|
850
|
+
//# sourceMappingURL=presentation.cjs.map
|