@rtrvr-ai/rover 4.1.0 → 4.2.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 +9 -2
- package/dist/agentDiscovery.d.ts +1 -0
- package/dist/agentDiscovery.js +9 -7
- package/dist/embed.js +303 -86
- package/dist/index.d.ts +1 -0
- package/dist/ownerInstall.js +11 -8
- package/dist/previewBootstrap.d.ts +20 -0
- package/dist/previewBootstrap.js +132 -9
- package/dist/rover.js +303 -86
- package/dist/worker/rover-worker.js +15 -15
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -45,6 +45,7 @@ export type RoverInit = {
|
|
|
45
45
|
pageConfig?: RoverPageCaptureConfig;
|
|
46
46
|
allowedDomains?: string[];
|
|
47
47
|
domainScopeMode?: 'host_only' | 'registrable_domain';
|
|
48
|
+
cloudSandboxEnabled?: boolean;
|
|
48
49
|
tabPolicy?: {
|
|
49
50
|
observerByDefault?: boolean;
|
|
50
51
|
actionLeaseMs?: number;
|
package/dist/ownerInstall.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_AGENT_CARD_PATH, DEFAULT_ROVER_SITE_PATH, createRoverAgentCard, createRoverAgentCardJson, createRoverSiteProfile, createRoverSiteProfileJson, createRoverServiceDescLinkHeader, } from './agentDiscovery.js';
|
|
1
|
+
import { DEFAULT_AGENT_CARD_PATH, DEFAULT_LLMS_PATH, DEFAULT_ROVER_SITE_PATH, createRoverAgentCard, createRoverAgentCardJson, createRoverSiteProfile, createRoverSiteProfileJson, createRoverServiceDescLinkHeader, } from './agentDiscovery.js';
|
|
2
2
|
const DEFAULT_EMBED_SCRIPT_URL = 'https://rover.rtrvr.ai/embed.js';
|
|
3
3
|
const DEFAULT_ROVERBOOK_SCRIPT_URL = 'https://rover.rtrvr.ai/roverbook.js';
|
|
4
4
|
function text(value) {
|
|
@@ -260,20 +260,23 @@ function buildRoverBookAttachScript(config, options) {
|
|
|
260
260
|
export function createRoverOwnerInstallBundle(input) {
|
|
261
261
|
const bootConfig = materializeCloudSandboxBootConfig(input.bootConfig);
|
|
262
262
|
const discoveryConfig = discoveryEnabled(input.discovery) ? input.discovery : null;
|
|
263
|
+
const publishLlmsTxt = llmsEnabled(input, discoveryConfig);
|
|
263
264
|
const publishedAgentCardUrl = discoveryConfig ? text(discoveryConfig.agentCardUrl) || DEFAULT_AGENT_CARD_PATH : '';
|
|
264
265
|
const publishedRoverSiteUrl = discoveryConfig ? text(discoveryConfig.roverSiteUrl) || DEFAULT_ROVER_SITE_PATH : '';
|
|
265
|
-
const
|
|
266
|
-
const
|
|
266
|
+
const publishedLlmsUrl = discoveryConfig ? text(discoveryConfig.llmsUrl) || (publishLlmsTxt ? DEFAULT_LLMS_PATH : '') : '';
|
|
267
|
+
const effectiveDiscoveryConfig = discoveryConfig && publishedLlmsUrl && !text(discoveryConfig.llmsUrl)
|
|
268
|
+
? { ...discoveryConfig, llmsUrl: publishedLlmsUrl }
|
|
269
|
+
: discoveryConfig;
|
|
267
270
|
const embedScriptUrl = text(input.embedScriptUrl) || DEFAULT_EMBED_SCRIPT_URL;
|
|
268
271
|
const roverBookEnabled = input.roverBook?.enabled !== false && hasObjectEntries(input.roverBook?.config);
|
|
269
272
|
const roverBookScriptUrl = roverBookEnabled
|
|
270
273
|
? (text(input.roverBook?.scriptUrl) || DEFAULT_ROVERBOOK_SCRIPT_URL)
|
|
271
274
|
: '';
|
|
272
|
-
const agentCard =
|
|
273
|
-
const agentCardJson =
|
|
274
|
-
const roverSite =
|
|
275
|
-
const roverSiteJson =
|
|
276
|
-
const pageManifestJson =
|
|
275
|
+
const agentCard = effectiveDiscoveryConfig ? createRoverAgentCard(effectiveDiscoveryConfig) : undefined;
|
|
276
|
+
const agentCardJson = effectiveDiscoveryConfig ? createRoverAgentCardJson(effectiveDiscoveryConfig) : undefined;
|
|
277
|
+
const roverSite = effectiveDiscoveryConfig ? createRoverSiteProfile(effectiveDiscoveryConfig) : undefined;
|
|
278
|
+
const roverSiteJson = effectiveDiscoveryConfig ? createRoverSiteProfileJson(effectiveDiscoveryConfig) : undefined;
|
|
279
|
+
const pageManifestJson = effectiveDiscoveryConfig
|
|
277
280
|
? JSON.stringify(agentCard?.extensions?.rover.currentPage || null, null, 2)
|
|
278
281
|
: undefined;
|
|
279
282
|
const marker = agentCard && publishedAgentCardUrl
|
|
@@ -7,8 +7,24 @@ export type RoverPreviewBootstrapVoiceConfig = {
|
|
|
7
7
|
language?: string;
|
|
8
8
|
autoStopMs?: number;
|
|
9
9
|
};
|
|
10
|
+
export type RoverPreviewBootstrapExperienceConfig = {
|
|
11
|
+
audio?: {
|
|
12
|
+
narration?: {
|
|
13
|
+
enabled?: boolean;
|
|
14
|
+
defaultMode?: 'guided' | 'always' | 'off';
|
|
15
|
+
rate?: number;
|
|
16
|
+
language?: string;
|
|
17
|
+
voicePreference?: 'auto' | 'system' | 'natural';
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
motion?: {
|
|
21
|
+
actionSpotlight?: boolean;
|
|
22
|
+
actionSpotlightColor?: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
10
25
|
export type RoverPreviewBootstrapUiConfig = {
|
|
11
26
|
voice?: RoverPreviewBootstrapVoiceConfig;
|
|
27
|
+
experience?: RoverPreviewBootstrapExperienceConfig;
|
|
12
28
|
};
|
|
13
29
|
export type RoverPreviewBootstrapConfig = {
|
|
14
30
|
scriptUrl?: string;
|
|
@@ -21,10 +37,14 @@ export type RoverPreviewBootstrapConfig = {
|
|
|
21
37
|
workerUrl?: string;
|
|
22
38
|
allowedDomains?: string[];
|
|
23
39
|
domainScopeMode?: 'host_only' | 'registrable_domain';
|
|
40
|
+
cloudSandboxEnabled?: boolean;
|
|
24
41
|
sessionScope?: 'shared_site' | 'tab';
|
|
25
42
|
openOnInit?: boolean;
|
|
26
43
|
mode?: 'safe' | 'full';
|
|
27
44
|
allowActions?: boolean;
|
|
45
|
+
pageConfig?: {
|
|
46
|
+
disableAutoScroll?: boolean;
|
|
47
|
+
};
|
|
28
48
|
ui?: RoverPreviewBootstrapUiConfig;
|
|
29
49
|
attachLaunch?: RoverPreviewAttachLaunch;
|
|
30
50
|
};
|
package/dist/previewBootstrap.js
CHANGED
|
@@ -2,6 +2,8 @@ const DEFAULT_EMBED_SCRIPT_URL = 'https://rover.rtrvr.ai/embed.js';
|
|
|
2
2
|
const DEFAULT_AGENT_BASE = 'https://agent.rtrvr.ai';
|
|
3
3
|
const VOICE_AUTO_STOP_MIN_MS = 800;
|
|
4
4
|
const VOICE_AUTO_STOP_MAX_MS = 5000;
|
|
5
|
+
const NARRATION_RATE_MIN = 0.85;
|
|
6
|
+
const NARRATION_RATE_MAX = 1.15;
|
|
5
7
|
function toStringValue(value) {
|
|
6
8
|
return String(value || '').trim();
|
|
7
9
|
}
|
|
@@ -41,6 +43,13 @@ function parseIntegerAttr(value) {
|
|
|
41
43
|
const parsed = Number(toStringValue(value));
|
|
42
44
|
return Number.isFinite(parsed) ? Math.trunc(parsed) : undefined;
|
|
43
45
|
}
|
|
46
|
+
function normalizeHexColor(value) {
|
|
47
|
+
const raw = toStringValue(value);
|
|
48
|
+
if (!raw)
|
|
49
|
+
return undefined;
|
|
50
|
+
const match = raw.match(/^#?([0-9a-fA-F]{6})$/);
|
|
51
|
+
return match ? `#${match[1].toUpperCase()}` : undefined;
|
|
52
|
+
}
|
|
44
53
|
function normalizeVoiceConfig(value) {
|
|
45
54
|
if (!value || typeof value !== 'object')
|
|
46
55
|
return undefined;
|
|
@@ -56,6 +65,53 @@ function normalizeVoiceConfig(value) {
|
|
|
56
65
|
}
|
|
57
66
|
return Object.keys(voice).length ? voice : undefined;
|
|
58
67
|
}
|
|
68
|
+
function normalizeExperienceConfig(value) {
|
|
69
|
+
if (!value || typeof value !== 'object')
|
|
70
|
+
return undefined;
|
|
71
|
+
const experience = {};
|
|
72
|
+
if (value.audio && typeof value.audio === 'object') {
|
|
73
|
+
const narrationInput = value.audio.narration && typeof value.audio.narration === 'object'
|
|
74
|
+
? value.audio.narration
|
|
75
|
+
: undefined;
|
|
76
|
+
if (narrationInput) {
|
|
77
|
+
const narration = {};
|
|
78
|
+
if (typeof narrationInput.enabled === 'boolean')
|
|
79
|
+
narration.enabled = narrationInput.enabled;
|
|
80
|
+
if (narrationInput.defaultMode === 'guided' ||
|
|
81
|
+
narrationInput.defaultMode === 'always' ||
|
|
82
|
+
narrationInput.defaultMode === 'off') {
|
|
83
|
+
narration.defaultMode = narrationInput.defaultMode;
|
|
84
|
+
}
|
|
85
|
+
const rate = Number(narrationInput.rate);
|
|
86
|
+
if (Number.isFinite(rate)) {
|
|
87
|
+
narration.rate = Math.max(NARRATION_RATE_MIN, Math.min(NARRATION_RATE_MAX, rate));
|
|
88
|
+
}
|
|
89
|
+
const language = toStringValue(narrationInput.language).replace(/[^a-zA-Z0-9-]/g, '').slice(0, 24);
|
|
90
|
+
if (language)
|
|
91
|
+
narration.language = language;
|
|
92
|
+
if (narrationInput.voicePreference === 'auto' ||
|
|
93
|
+
narrationInput.voicePreference === 'system' ||
|
|
94
|
+
narrationInput.voicePreference === 'natural') {
|
|
95
|
+
narration.voicePreference = narrationInput.voicePreference;
|
|
96
|
+
}
|
|
97
|
+
if (Object.keys(narration).length)
|
|
98
|
+
experience.audio = { narration };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (value.motion && typeof value.motion === 'object') {
|
|
102
|
+
const motion = {};
|
|
103
|
+
if (typeof value.motion.actionSpotlight === 'boolean') {
|
|
104
|
+
motion.actionSpotlight = value.motion.actionSpotlight;
|
|
105
|
+
}
|
|
106
|
+
const actionSpotlightColor = normalizeHexColor(value.motion.actionSpotlightColor);
|
|
107
|
+
if (actionSpotlightColor) {
|
|
108
|
+
motion.actionSpotlightColor = actionSpotlightColor;
|
|
109
|
+
}
|
|
110
|
+
if (Object.keys(motion).length)
|
|
111
|
+
experience.motion = motion;
|
|
112
|
+
}
|
|
113
|
+
return Object.keys(experience).length ? experience : undefined;
|
|
114
|
+
}
|
|
59
115
|
function normalizeUiConfig(value) {
|
|
60
116
|
if (!value || typeof value !== 'object')
|
|
61
117
|
return undefined;
|
|
@@ -63,6 +119,9 @@ function normalizeUiConfig(value) {
|
|
|
63
119
|
const voice = normalizeVoiceConfig(value.voice);
|
|
64
120
|
if (voice)
|
|
65
121
|
ui.voice = voice;
|
|
122
|
+
const experience = normalizeExperienceConfig(value.experience);
|
|
123
|
+
if (experience)
|
|
124
|
+
ui.experience = experience;
|
|
66
125
|
return Object.keys(ui).length ? ui : undefined;
|
|
67
126
|
}
|
|
68
127
|
function normalizeBootstrapConfig(config) {
|
|
@@ -98,6 +157,8 @@ function buildBootstrapPayload(config) {
|
|
|
98
157
|
payload.allowedDomains = normalized.allowedDomains;
|
|
99
158
|
if (normalized.domainScopeMode)
|
|
100
159
|
payload.domainScopeMode = normalized.domainScopeMode;
|
|
160
|
+
if (typeof normalized.cloudSandboxEnabled === 'boolean')
|
|
161
|
+
payload.cloudSandboxEnabled = normalized.cloudSandboxEnabled;
|
|
101
162
|
if (normalized.sessionScope)
|
|
102
163
|
payload.sessionScope = normalized.sessionScope;
|
|
103
164
|
if (typeof normalized.openOnInit === 'boolean')
|
|
@@ -106,8 +167,11 @@ function buildBootstrapPayload(config) {
|
|
|
106
167
|
payload.mode = normalized.mode;
|
|
107
168
|
if (typeof normalized.allowActions === 'boolean')
|
|
108
169
|
payload.allowActions = normalized.allowActions;
|
|
109
|
-
if (normalized.
|
|
110
|
-
payload.
|
|
170
|
+
if (typeof normalized.pageConfig?.disableAutoScroll === 'boolean') {
|
|
171
|
+
payload.pageConfig = { disableAutoScroll: normalized.pageConfig.disableAutoScroll };
|
|
172
|
+
}
|
|
173
|
+
if (normalized.ui)
|
|
174
|
+
payload.ui = normalized.ui;
|
|
111
175
|
return payload;
|
|
112
176
|
}
|
|
113
177
|
function buildQueueStub() {
|
|
@@ -180,6 +244,8 @@ export function createRoverScriptTagSnippet(config) {
|
|
|
180
244
|
attrs.push(`data-allowed-domains="${escapeHtmlAttr(normalized.allowedDomains.join(','))}"`);
|
|
181
245
|
if (normalized.domainScopeMode)
|
|
182
246
|
attrs.push(`data-domain-scope-mode="${escapeHtmlAttr(normalized.domainScopeMode)}"`);
|
|
247
|
+
if (typeof normalized.cloudSandboxEnabled === 'boolean')
|
|
248
|
+
attrs.push(`data-cloud-sandbox-enabled="${escapeHtmlAttr(String(normalized.cloudSandboxEnabled))}"`);
|
|
183
249
|
if (normalized.sessionScope)
|
|
184
250
|
attrs.push(`data-session-scope="${escapeHtmlAttr(normalized.sessionScope)}"`);
|
|
185
251
|
if (typeof normalized.openOnInit === 'boolean')
|
|
@@ -188,14 +254,34 @@ export function createRoverScriptTagSnippet(config) {
|
|
|
188
254
|
attrs.push(`data-mode="${escapeHtmlAttr(normalized.mode)}"`);
|
|
189
255
|
if (typeof normalized.allowActions === 'boolean')
|
|
190
256
|
attrs.push(`data-allow-actions="${escapeHtmlAttr(String(normalized.allowActions))}"`);
|
|
257
|
+
if (typeof normalized.pageConfig?.disableAutoScroll === 'boolean') {
|
|
258
|
+
attrs.push(`data-disable-auto-scroll="${escapeHtmlAttr(String(normalized.pageConfig.disableAutoScroll))}"`);
|
|
259
|
+
}
|
|
191
260
|
if (typeof normalized.ui?.voice?.enabled === 'boolean')
|
|
192
261
|
attrs.push(`data-voice-enabled="${escapeHtmlAttr(String(normalized.ui.voice.enabled))}"`);
|
|
193
262
|
if (normalized.ui?.voice?.language)
|
|
194
263
|
attrs.push(`data-voice-language="${escapeHtmlAttr(normalized.ui.voice.language)}"`);
|
|
195
264
|
if (typeof normalized.ui?.voice?.autoStopMs === 'number')
|
|
196
265
|
attrs.push(`data-voice-auto-stop-ms="${escapeHtmlAttr(String(normalized.ui.voice.autoStopMs))}"`);
|
|
266
|
+
const narration = normalized.ui?.experience?.audio?.narration;
|
|
267
|
+
if (typeof narration?.enabled === 'boolean')
|
|
268
|
+
attrs.push(`data-narration-enabled="${escapeHtmlAttr(String(narration.enabled))}"`);
|
|
269
|
+
if (narration?.defaultMode)
|
|
270
|
+
attrs.push(`data-narration-default-mode="${escapeHtmlAttr(narration.defaultMode)}"`);
|
|
271
|
+
if (typeof narration?.rate === 'number')
|
|
272
|
+
attrs.push(`data-narration-rate="${escapeHtmlAttr(String(narration.rate))}"`);
|
|
273
|
+
if (narration?.language)
|
|
274
|
+
attrs.push(`data-narration-language="${escapeHtmlAttr(narration.language)}"`);
|
|
275
|
+
if (narration?.voicePreference)
|
|
276
|
+
attrs.push(`data-narration-voice-preference="${escapeHtmlAttr(narration.voicePreference)}"`);
|
|
277
|
+
if (typeof normalized.ui?.experience?.motion?.actionSpotlight === 'boolean') {
|
|
278
|
+
attrs.push(`data-action-spotlight="${escapeHtmlAttr(String(normalized.ui.experience.motion.actionSpotlight))}"`);
|
|
279
|
+
}
|
|
280
|
+
if (normalized.ui?.experience?.motion?.actionSpotlightColor) {
|
|
281
|
+
attrs.push(`data-action-spotlight-color="${escapeHtmlAttr(normalized.ui.experience.motion.actionSpotlightColor)}"`);
|
|
282
|
+
}
|
|
197
283
|
const runEndpoint = `${toStringValue(normalized.apiBase) || DEFAULT_AGENT_BASE}/v1/a2w/runs`;
|
|
198
|
-
const markerJson = escapeScriptJson(JSON.stringify({ a2w: runEndpoint, run: runEndpoint
|
|
284
|
+
const markerJson = escapeScriptJson(JSON.stringify({ a2w: runEndpoint, run: runEndpoint }));
|
|
199
285
|
return [
|
|
200
286
|
`<script type="application/agent+json" data-rover-agent-discovery="marker">${markerJson}</script>`,
|
|
201
287
|
'<link rel="service-desc" href="/.well-known/agent-card.json" type="application/json" data-rover-agent-discovery="service-desc" />',
|
|
@@ -235,6 +321,9 @@ export function readRoverScriptDataAttributes(scriptEl) {
|
|
|
235
321
|
if (domainScopeMode === 'host_only' || domainScopeMode === 'registrable_domain') {
|
|
236
322
|
config.domainScopeMode = domainScopeMode;
|
|
237
323
|
}
|
|
324
|
+
const cloudSandboxEnabled = parseBooleanAttr(scriptEl.getAttribute('data-cloud-sandbox-enabled'));
|
|
325
|
+
if (typeof cloudSandboxEnabled === 'boolean')
|
|
326
|
+
config.cloudSandboxEnabled = cloudSandboxEnabled;
|
|
238
327
|
const sessionScope = toStringValue(scriptEl.getAttribute('data-session-scope'));
|
|
239
328
|
if (sessionScope === 'shared_site' || sessionScope === 'tab') {
|
|
240
329
|
config.sessionScope = sessionScope;
|
|
@@ -249,16 +338,50 @@ export function readRoverScriptDataAttributes(scriptEl) {
|
|
|
249
338
|
const allowActions = parseBooleanAttr(scriptEl.getAttribute('data-allow-actions'));
|
|
250
339
|
if (typeof allowActions === 'boolean')
|
|
251
340
|
config.allowActions = allowActions;
|
|
341
|
+
const disableAutoScroll = parseBooleanAttr(scriptEl.getAttribute('data-disable-auto-scroll'));
|
|
342
|
+
if (typeof disableAutoScroll === 'boolean')
|
|
343
|
+
config.pageConfig = { disableAutoScroll };
|
|
252
344
|
const voiceEnabled = parseBooleanAttr(scriptEl.getAttribute('data-voice-enabled'));
|
|
253
345
|
const voiceLanguage = toStringValue(scriptEl.getAttribute('data-voice-language'));
|
|
254
346
|
const voiceAutoStopMs = parseIntegerAttr(scriptEl.getAttribute('data-voice-auto-stop-ms'));
|
|
255
|
-
|
|
347
|
+
const narrationEnabled = parseBooleanAttr(scriptEl.getAttribute('data-narration-enabled'));
|
|
348
|
+
const narrationDefaultMode = toStringValue(scriptEl.getAttribute('data-narration-default-mode'));
|
|
349
|
+
const narrationRate = Number(toStringValue(scriptEl.getAttribute('data-narration-rate')));
|
|
350
|
+
const narrationLanguage = toStringValue(scriptEl.getAttribute('data-narration-language'));
|
|
351
|
+
const narrationVoicePreference = toStringValue(scriptEl.getAttribute('data-narration-voice-preference'));
|
|
352
|
+
const actionSpotlight = parseBooleanAttr(scriptEl.getAttribute('data-action-spotlight'));
|
|
353
|
+
const actionSpotlightColor = normalizeHexColor(scriptEl.getAttribute('data-action-spotlight-color'));
|
|
354
|
+
const voice = normalizeVoiceConfig({
|
|
355
|
+
...(typeof voiceEnabled === 'boolean' ? { enabled: voiceEnabled } : {}),
|
|
356
|
+
...(voiceLanguage ? { language: voiceLanguage } : {}),
|
|
357
|
+
...(typeof voiceAutoStopMs === 'number' ? { autoStopMs: voiceAutoStopMs } : {}),
|
|
358
|
+
});
|
|
359
|
+
const experience = normalizeExperienceConfig({
|
|
360
|
+
...(typeof narrationEnabled === 'boolean' || narrationDefaultMode || Number.isFinite(narrationRate) || narrationLanguage || narrationVoicePreference
|
|
361
|
+
? {
|
|
362
|
+
audio: {
|
|
363
|
+
narration: {
|
|
364
|
+
...(typeof narrationEnabled === 'boolean' ? { enabled: narrationEnabled } : {}),
|
|
365
|
+
...(narrationDefaultMode === 'guided' || narrationDefaultMode === 'always' || narrationDefaultMode === 'off'
|
|
366
|
+
? { defaultMode: narrationDefaultMode }
|
|
367
|
+
: {}),
|
|
368
|
+
...(Number.isFinite(narrationRate) ? { rate: narrationRate } : {}),
|
|
369
|
+
...(narrationLanguage ? { language: narrationLanguage } : {}),
|
|
370
|
+
...(narrationVoicePreference === 'auto' || narrationVoicePreference === 'system' || narrationVoicePreference === 'natural'
|
|
371
|
+
? { voicePreference: narrationVoicePreference }
|
|
372
|
+
: {}),
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
}
|
|
376
|
+
: {}),
|
|
377
|
+
...(typeof actionSpotlight === 'boolean' || actionSpotlightColor
|
|
378
|
+
? { motion: { ...(typeof actionSpotlight === 'boolean' ? { actionSpotlight } : {}), ...(actionSpotlightColor ? { actionSpotlightColor } : {}) } }
|
|
379
|
+
: {}),
|
|
380
|
+
});
|
|
381
|
+
if (voice || experience) {
|
|
256
382
|
config.ui = {
|
|
257
|
-
voice: {
|
|
258
|
-
|
|
259
|
-
...(voiceLanguage ? { language: voiceLanguage } : {}),
|
|
260
|
-
...(typeof voiceAutoStopMs === 'number' ? { autoStopMs: voiceAutoStopMs } : {}),
|
|
261
|
-
},
|
|
383
|
+
...(voice ? { voice } : {}),
|
|
384
|
+
...(experience ? { experience } : {}),
|
|
262
385
|
};
|
|
263
386
|
}
|
|
264
387
|
return config;
|