@rtrvr-ai/rover 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,12 @@
1
1
  import type { RoverPageCaptureConfig } from '@rover/shared/lib/types/index.js';
2
2
  import { type RoverAskUserQuestion, type RoverShortcut, type RoverVoiceConfig } from '@rover/ui';
3
+ import { normalizePendingRunResumeReason } from './resumeReasons.js';
4
+ import { createRoverBookmarklet, createRoverConsoleSnippet, createRoverScriptTagSnippet, readRoverScriptDataAttributes, type RoverPreviewAttachLaunch } from './previewBootstrap.js';
5
+ import { createRoverOwnerInstallBundle, type RoverOwnerInstallBootConfig, type RoverOwnerInstallBundle, type RoverOwnerInstallBundleInput, type RoverOwnerInstallRoverBookConfig } from './ownerInstall.js';
6
+ import { createRoverAgentCard, createRoverAgentCardJson, createRoverAgentDiscoveryTags, createRoverSiteProfile, createRoverSiteProfileJson, createRoverServiceDescLinkHeader, createRoverWellKnownAgentCard, createRoverWellKnownSiteProfile, type RoverAgentCard, type RoverAgentDiscoveryRuntimeConfig } from './agentDiscovery.js';
3
7
  import { type RoverCloudCheckpointState } from './cloudCheckpoint.js';
4
8
  import type { PersistedRuntimeState, PersistedWorkerState } from './runtimeTypes.js';
9
+ import { type RoverLaunchAttachResponse, type RoverServerExperienceConfig } from './serverRuntime.js';
5
10
  import { type FollowupChatEntry } from './followupChatHeuristics.js';
6
11
  export type RoverWebToolsConfig = {
7
12
  enableExternalWebContext?: boolean;
@@ -73,6 +78,7 @@ export type RoverInit = {
73
78
  activation?: 'on_demand';
74
79
  idleCloseMs?: number;
75
80
  };
81
+ agentDiscovery?: RoverAgentDiscoveryRuntimeConfig;
76
82
  stability?: {
77
83
  maxPersistBytes?: number;
78
84
  maxSnapshotBytes?: number;
@@ -161,6 +167,7 @@ export type RoverInit = {
161
167
  disabled?: boolean;
162
168
  mp4Url?: string;
163
169
  webmUrl?: string;
170
+ soundEnabled?: boolean;
164
171
  };
165
172
  shortcuts?: RoverShortcut[];
166
173
  muted?: boolean;
@@ -169,6 +176,7 @@ export type RoverInit = {
169
176
  resizable?: boolean;
170
177
  };
171
178
  showTaskControls?: boolean;
179
+ experience?: RoverServerExperienceConfig;
172
180
  greeting?: {
173
181
  text?: string;
174
182
  delay?: number;
@@ -193,10 +201,13 @@ export type RoverInit = {
193
201
  };
194
202
  export type ClientToolDefinition = {
195
203
  name: string;
204
+ title?: string;
196
205
  description?: string;
197
206
  parameters?: Record<string, any>;
198
207
  required?: string[];
199
208
  schema?: any;
209
+ outputSchema?: any;
210
+ annotations?: Record<string, any>;
200
211
  llmCallable?: boolean;
201
212
  };
202
213
  export type RoverEventName = 'ready' | 'updated' | 'status' | 'run_started' | 'run_state_transition' | 'run_completed' | 'tool_start' | 'tool_result' | 'error' | 'auth_required' | 'navigation_guardrail' | 'mode_change' | 'task_started' | 'task_ended' | 'task_suggested_reset' | 'context_restored' | 'checkpoint_state' | 'checkpoint_error' | 'tab_event_conflict_retry' | 'tab_event_conflict_exhausted' | 'checkpoint_token_missing' | 'open' | 'close';
@@ -238,7 +249,9 @@ export type RoverInstance = {
238
249
  reason?: string;
239
250
  }) => void;
240
251
  getState: () => any;
252
+ getAgentCard: () => RoverAgentCard | null;
241
253
  requestSigned: (input: string | URL, init?: RequestInit) => Promise<Response>;
254
+ attachLaunch: (params: RoverPreviewAttachLaunch) => Promise<RoverLaunchAttachResponse | null>;
242
255
  registerPromptContextProvider: (provider: RoverPromptContextProvider) => () => void;
243
256
  registerTool: (nameOrDef: string | ClientToolDefinition, handler: (args: any) => any | Promise<any>) => void;
244
257
  identify: (visitor: {
@@ -251,6 +264,7 @@ type TelemetryEventName = RoverEventName | RoverVoiceTelemetryEventName;
251
264
  declare function normalizePromptContextEntry(input: string | RoverPromptContextEntry): FollowupChatEntry | null;
252
265
  declare function buildPublicRunStartedPayload(msg: any): Record<string, unknown>;
253
266
  declare function buildPublicRunLifecyclePayload(msg: any, completionState: ReturnType<typeof normalizeRunCompletionState>): Record<string, unknown>;
267
+ export declare function getAgentCard(): RoverAgentCard | null;
254
268
  declare function normalizeRunCompletionState(msg: any): {
255
269
  taskComplete: boolean;
256
270
  needsUserInput: boolean;
@@ -274,6 +288,7 @@ export declare function close(): void;
274
288
  export declare function show(): void;
275
289
  export declare function hide(): void;
276
290
  export declare function send(text: string): void;
291
+ export declare function attachLaunch(params: RoverPreviewAttachLaunch): Promise<RoverLaunchAttachResponse | null>;
277
292
  export declare function requestSigned(input: string | URL, init?: RequestInit): Promise<Response>;
278
293
  export declare function registerPromptContextProvider(provider: RoverPromptContextProvider): () => void;
279
294
  export declare function newTask(options?: {
@@ -286,6 +301,7 @@ export declare function endTask(options?: {
286
301
  export declare function getState(): any;
287
302
  export declare function registerTool(nameOrDef: string | ClientToolDefinition, handler: (args: any) => any | Promise<any>): void;
288
303
  export declare const __roverInternalsForTests: {
304
+ normalizePendingRunResumeReason: typeof normalizePendingRunResumeReason;
289
305
  sanitizeWorkerState: typeof sanitizeWorkerState;
290
306
  cloneRuntimeStateForCheckpoint: typeof cloneRuntimeStateForCheckpoint;
291
307
  getPersistGovernorConfig: () => {
@@ -297,5 +313,6 @@ export declare const __roverInternalsForTests: {
297
313
  buildPublicRunStartedPayload: typeof buildPublicRunStartedPayload;
298
314
  buildPublicRunLifecyclePayload: typeof buildPublicRunLifecyclePayload;
299
315
  };
316
+ export { createRoverAgentCard, createRoverAgentCardJson, createRoverAgentDiscoveryTags, createRoverBookmarklet, createRoverConsoleSnippet, createRoverOwnerInstallBundle, createRoverSiteProfile, createRoverSiteProfileJson, createRoverServiceDescLinkHeader, createRoverScriptTagSnippet, createRoverWellKnownAgentCard, createRoverWellKnownSiteProfile, readRoverScriptDataAttributes, };
317
+ export type { RoverOwnerInstallBootConfig, RoverOwnerInstallBundle, RoverOwnerInstallBundleInput, RoverOwnerInstallRoverBookConfig, };
300
318
  export declare function installGlobal(): void;
301
- export {};
@@ -0,0 +1,150 @@
1
+ import type { RoverPageCaptureConfig } from '@rover/shared/lib/types/index.js';
2
+ import type { RoverShortcut, RoverVoiceConfig } from '@rover/ui';
3
+ import { type RoverAgentCard, type RoverAgentDiscoveryConfig, type RoverAgentDiscoveryRuntimeConfig, type RoverSiteProfile } from './agentDiscovery.js';
4
+ type JsonRecord = Record<string, unknown>;
5
+ export type RoverOwnerInstallBootConfig = {
6
+ siteId: string;
7
+ publicKey?: string;
8
+ sessionToken?: string;
9
+ sessionId?: string;
10
+ siteKeyId?: string;
11
+ apiBase?: string;
12
+ visitorId?: string;
13
+ workerUrl?: string;
14
+ allowedDomains?: string[];
15
+ domainScopeMode?: 'host_only' | 'registrable_domain';
16
+ externalNavigationPolicy?: 'open_new_tab_notice' | 'block' | 'allow';
17
+ sessionScope?: 'shared_site' | 'tab';
18
+ openOnInit?: boolean;
19
+ mode?: 'safe' | 'full';
20
+ allowActions?: boolean;
21
+ deepLink?: {
22
+ enabled?: boolean;
23
+ promptParam?: string;
24
+ shortcutParam?: string;
25
+ consume?: boolean;
26
+ };
27
+ pageConfig?: RoverPageCaptureConfig | null;
28
+ navigation?: {
29
+ crossHostPolicy?: 'open_new_tab' | 'same_tab';
30
+ };
31
+ tabPolicy?: {
32
+ observerByDefault?: boolean;
33
+ actionLeaseMs?: number;
34
+ };
35
+ taskRouting?: {
36
+ mode?: 'auto' | 'act' | 'planner';
37
+ actHeuristicThreshold?: number;
38
+ plannerOnActError?: boolean;
39
+ };
40
+ taskContext?: {
41
+ resetMode?: 'auto' | 'ask' | 'off';
42
+ inactivityMs?: number;
43
+ suggestReset?: boolean;
44
+ semanticSimilarityThreshold?: number;
45
+ };
46
+ checkpointing?: {
47
+ enabled?: boolean;
48
+ autoVisitorId?: boolean;
49
+ flushIntervalMs?: number;
50
+ pullIntervalMs?: number;
51
+ minFlushIntervalMs?: number;
52
+ ttlHours?: number;
53
+ };
54
+ apiMode?: boolean;
55
+ apiToolsConfig?: {
56
+ mode?: 'allowlist' | 'profile' | 'none';
57
+ enableAdditionalTools?: string[];
58
+ userDefined?: string[];
59
+ };
60
+ telemetry?: {
61
+ enabled?: boolean;
62
+ sampleRate?: number;
63
+ flushIntervalMs?: number;
64
+ maxBatchSize?: number;
65
+ includePayloads?: boolean;
66
+ };
67
+ ui?: {
68
+ agent?: {
69
+ name?: string;
70
+ };
71
+ mascot?: {
72
+ disabled?: boolean;
73
+ mp4Url?: string;
74
+ webmUrl?: string;
75
+ soundEnabled?: boolean;
76
+ };
77
+ shortcuts?: RoverShortcut[];
78
+ greeting?: {
79
+ text?: string;
80
+ delay?: number;
81
+ duration?: number;
82
+ disabled?: boolean;
83
+ };
84
+ voice?: RoverVoiceConfig | JsonRecord | null;
85
+ experience?: JsonRecord | null;
86
+ muted?: boolean;
87
+ thoughtStyle?: 'concise_cards' | 'minimal';
88
+ panel?: {
89
+ resizable?: boolean;
90
+ };
91
+ showTaskControls?: boolean;
92
+ };
93
+ tools?: {
94
+ web?: {
95
+ enableExternalWebContext?: boolean;
96
+ allowDomains?: string[];
97
+ denyDomains?: string[];
98
+ scrapeMode?: 'off' | 'on_demand';
99
+ };
100
+ };
101
+ agentDiscovery?: RoverAgentDiscoveryRuntimeConfig;
102
+ siteMode?: 'agent' | 'analytics_only' | string;
103
+ };
104
+ export type RoverOwnerInstallRoverBookConfig = {
105
+ enabled?: boolean;
106
+ scriptUrl?: string;
107
+ config?: JsonRecord | null;
108
+ attachPollIntervalMs?: number;
109
+ attachMaxAttempts?: number;
110
+ };
111
+ export type RoverOwnerInstallBundleInput = {
112
+ bootConfig: RoverOwnerInstallBootConfig;
113
+ discovery?: RoverAgentDiscoveryConfig | null;
114
+ embedScriptUrl?: string;
115
+ roverBook?: RoverOwnerInstallRoverBookConfig | null;
116
+ emitLlmsTxt?: boolean;
117
+ llmsTxt?: string;
118
+ };
119
+ export type RoverOwnerInstallBundleMetadata = {
120
+ discoveryEnabled: boolean;
121
+ llmsPublished: boolean;
122
+ embedScriptUrl: string;
123
+ roverBookEnabled: boolean;
124
+ roverBookScriptUrl?: string;
125
+ publishedAgentCardUrl?: string;
126
+ publishedRoverSiteUrl?: string;
127
+ publishedLlmsUrl?: string;
128
+ serviceDescLinkTag?: string;
129
+ serviceDocLinkTag?: string;
130
+ markerJson?: string;
131
+ markerScript?: string;
132
+ inlineAgentCardScript?: string;
133
+ roverSiteJson?: string;
134
+ inlineRoverSiteScript?: string;
135
+ pageManifestJson?: string;
136
+ pageManifestScript?: string;
137
+ };
138
+ export type RoverOwnerInstallBundle = {
139
+ bodyInstallHtml: string;
140
+ headDiscoveryHtml: string;
141
+ agentCard?: RoverAgentCard;
142
+ agentCardJson?: string;
143
+ roverSite?: RoverSiteProfile;
144
+ roverSiteJson?: string;
145
+ serviceDescLinkHeader?: string;
146
+ llmsTxt?: string;
147
+ metadata: RoverOwnerInstallBundleMetadata;
148
+ };
149
+ export declare function createRoverOwnerInstallBundle(input: RoverOwnerInstallBundleInput): RoverOwnerInstallBundle;
150
+ export {};
@@ -0,0 +1,340 @@
1
+ import { DEFAULT_AGENT_CARD_PATH, DEFAULT_ROVER_SITE_PATH, createRoverAgentCard, createRoverAgentCardJson, createRoverSiteProfile, createRoverSiteProfileJson, createRoverServiceDescLinkHeader, } from './agentDiscovery.js';
2
+ const DEFAULT_EMBED_SCRIPT_URL = 'https://rover.rtrvr.ai/embed.js';
3
+ const DEFAULT_ROVERBOOK_SCRIPT_URL = 'https://rover.rtrvr.ai/roverbook.js';
4
+ function text(value) {
5
+ return String(value || '').trim();
6
+ }
7
+ function escapeHtmlAttr(value) {
8
+ return String(value || '')
9
+ .replace(/&/g, '&amp;')
10
+ .replace(/"/g, '&quot;')
11
+ .replace(/</g, '&lt;')
12
+ .replace(/>/g, '&gt;');
13
+ }
14
+ function escapeScriptJson(value) {
15
+ return String(value || '')
16
+ .replace(/</g, '\\u003c')
17
+ .replace(/>/g, '\\u003e')
18
+ .replace(/&/g, '\\u0026');
19
+ }
20
+ function replaceInlineDiscoveryScript(html, marker, script) {
21
+ if (!script)
22
+ return html;
23
+ const pattern = new RegExp(`<script[^>]+data-rover-agent-discovery="${marker}"[^>]*>[\\s\\S]*?<\\/script>`);
24
+ if (pattern.test(html)) {
25
+ return html.replace(pattern, script);
26
+ }
27
+ return [html, script].filter(Boolean).join('\n');
28
+ }
29
+ function decorateBundleWithExperience(bundle, bootConfig) {
30
+ const experience = isObject(bootConfig.ui?.experience) ? bootConfig.ui?.experience : null;
31
+ if (!experience)
32
+ return bundle;
33
+ const presence = isObject(experience.presence) ? experience.presence : {};
34
+ const inputs = isObject(experience.inputs) ? experience.inputs : {};
35
+ const shell = isObject(experience.shell) ? experience.shell : {};
36
+ const stream = isObject(experience.stream) ? experience.stream : {};
37
+ const ctaText = text(presence.ctaText) || `Do it with ${text(bootConfig.ui?.agent?.name) || 'Rover'}`;
38
+ const assistantName = text(presence.assistantName) || text(bootConfig.ui?.agent?.name) || 'Rover';
39
+ const agentCard = bundle.agentCard ? JSON.parse(JSON.stringify(bundle.agentCard)) : undefined;
40
+ if (agentCard?.extensions?.rover) {
41
+ agentCard.extensions.rover.discoverySurface = {
42
+ ...(agentCard.extensions.rover.discoverySurface || {}),
43
+ mode: 'beacon',
44
+ hostSurface: 'floating-corner',
45
+ actionReveal: 'click',
46
+ beaconLabel: ctaText,
47
+ };
48
+ agentCard.extensions.rover.presence = {
49
+ assistantName,
50
+ ctaText,
51
+ draggable: presence.draggable !== false,
52
+ };
53
+ agentCard.extensions.rover.experience = experience;
54
+ agentCard.extensions.rover.inputs = {
55
+ filesEnabled: inputs.files !== false,
56
+ acceptedMimeGroups: Array.isArray(inputs.acceptedMimeGroups) ? inputs.acceptedMimeGroups : ['images', 'pdfs', 'office', 'text'],
57
+ allowMultipleFiles: inputs.allowMultipleFiles !== false,
58
+ };
59
+ }
60
+ const roverSite = bundle.roverSite ? JSON.parse(JSON.stringify(bundle.roverSite)) : undefined;
61
+ if (roverSite) {
62
+ roverSite.display = {
63
+ ...(roverSite.display || {}),
64
+ mode: 'beacon',
65
+ hostSurface: 'floating-corner',
66
+ actionReveal: 'click',
67
+ beaconLabel: ctaText,
68
+ presence: 'draggable_pill',
69
+ openMode: text(shell.openMode) || 'center_stage',
70
+ mobileMode: text(shell.mobileMode) || 'fullscreen_sheet',
71
+ streamMode: text(stream.layout) || 'single_column',
72
+ focusView: 'focus_stream',
73
+ };
74
+ roverSite.experience = experience;
75
+ roverSite.inputs = {
76
+ ...(roverSite.inputs || {}),
77
+ filesEnabled: inputs.files !== false,
78
+ acceptedMimeGroups: Array.isArray(inputs.acceptedMimeGroups) ? inputs.acceptedMimeGroups : ['images', 'pdfs', 'office', 'text'],
79
+ allowMultipleFiles: inputs.allowMultipleFiles !== false,
80
+ };
81
+ }
82
+ const agentCardJson = agentCard ? JSON.stringify(agentCard, null, 2) : bundle.agentCardJson;
83
+ const roverSiteJson = roverSite ? JSON.stringify(roverSite, null, 2) : bundle.roverSiteJson;
84
+ const inlineAgentCardScript = agentCardJson
85
+ ? `<script type="application/agent-card+json" data-rover-agent-discovery="agent-card">${escapeScriptJson(agentCardJson)}</script>`
86
+ : bundle.metadata.inlineAgentCardScript;
87
+ const inlineRoverSiteScript = roverSiteJson
88
+ ? `<script type="application/rover-site+json" data-rover-agent-discovery="rover-site">${escapeScriptJson(roverSiteJson)}</script>`
89
+ : bundle.metadata.inlineRoverSiteScript;
90
+ return {
91
+ ...bundle,
92
+ agentCard,
93
+ agentCardJson,
94
+ roverSite,
95
+ roverSiteJson,
96
+ bodyInstallHtml: replaceInlineDiscoveryScript(replaceInlineDiscoveryScript(bundle.bodyInstallHtml, 'agent-card', inlineAgentCardScript), 'rover-site', inlineRoverSiteScript),
97
+ metadata: {
98
+ ...bundle.metadata,
99
+ roverSiteJson,
100
+ inlineAgentCardScript,
101
+ inlineRoverSiteScript,
102
+ },
103
+ };
104
+ }
105
+ function indentJson(value) {
106
+ return JSON.stringify(value, null, 2)
107
+ .split('\n')
108
+ .map(line => ` ${line}`)
109
+ .join('\n');
110
+ }
111
+ function isObject(value) {
112
+ return !!value && typeof value === 'object' && !Array.isArray(value);
113
+ }
114
+ function hasObjectEntries(value) {
115
+ return isObject(value) && Object.keys(value).length > 0;
116
+ }
117
+ function normalizeAttachPollIntervalMs(value) {
118
+ const parsed = Number(value);
119
+ if (!Number.isFinite(parsed) || parsed < 10)
120
+ return 50;
121
+ return Math.round(parsed);
122
+ }
123
+ function normalizeAttachMaxAttempts(value) {
124
+ const parsed = Number(value);
125
+ if (!Number.isFinite(parsed) || parsed < 1)
126
+ return 300;
127
+ return Math.round(parsed);
128
+ }
129
+ function discoveryEnabled(config) {
130
+ return !!config && config.enabled !== false && config.aiAccess?.enabled !== false;
131
+ }
132
+ function llmsEnabled(input, config) {
133
+ if (!discoveryEnabled(config))
134
+ return false;
135
+ return input.emitLlmsTxt === true || !!text(config.llmsUrl);
136
+ }
137
+ function buildOwnerMarker(card, publishedAgentCardUrl) {
138
+ return {
139
+ task: card.extensions?.rover.taskEndpoint,
140
+ card: publishedAgentCardUrl,
141
+ roverSite: card.extensions?.rover.roverSiteUrl,
142
+ site: card.extensions?.rover.siteUrl,
143
+ workflow: card.extensions?.rover.workflowEndpoint,
144
+ page: card.extensions?.rover.currentPage?.pageId,
145
+ preferExecution: card.extensions?.rover.preferredExecution,
146
+ display: card.extensions?.rover.discoverySurface
147
+ ? {
148
+ mode: card.extensions.rover.discoverySurface.mode,
149
+ hostSurface: card.extensions.rover.discoverySurface.hostSurface,
150
+ actionReveal: card.extensions.rover.discoverySurface.actionReveal,
151
+ beaconLabel: card.extensions.rover.discoverySurface.beaconLabel,
152
+ }
153
+ : undefined,
154
+ skills: card.skills.slice(0, 24).map(skill => ({
155
+ id: skill.id,
156
+ name: skill.name,
157
+ })),
158
+ capabilities: (card.extensions?.rover.capabilitiesGraph || []).slice(0, 24).map(capability => ({
159
+ capabilityId: capability.capabilityId,
160
+ label: capability.label,
161
+ })),
162
+ };
163
+ }
164
+ function buildDefaultLlmsTxt(card, options) {
165
+ const lines = [
166
+ `# ${card.name}`,
167
+ '',
168
+ card.description,
169
+ '',
170
+ 'Prefer Rover shortcuts, explicit site tools, and public task flows over raw DOM automation when they match the requested outcome.',
171
+ `Primary task endpoint: ${text(card.extensions?.rover.taskEndpoint || card.url)}`,
172
+ `Workflow endpoint: ${text(card.extensions?.rover.workflowEndpoint)}`,
173
+ `Capability card: ${options.agentCardUrl}`,
174
+ ];
175
+ const skills = card.skills
176
+ .map(skill => ({
177
+ id: text(skill.id),
178
+ name: text(skill.name),
179
+ description: text(skill.description),
180
+ interface: text(skill.preferredInterface || skill.rover?.source || 'task'),
181
+ }))
182
+ .filter(skill => skill.id && skill.name);
183
+ if (skills.length > 0) {
184
+ lines.push('', 'Published skills:');
185
+ for (const skill of skills) {
186
+ const description = skill.description ? ` - ${skill.description}` : '';
187
+ lines.push(`- ${skill.id}: ${skill.name} [${skill.interface}]${description}`);
188
+ }
189
+ }
190
+ const shortcuts = (card.extensions?.rover.shortcuts || [])
191
+ .map(shortcut => `${text(shortcut.id)}: ${text(shortcut.label)}`)
192
+ .filter(Boolean);
193
+ if (shortcuts.length > 0) {
194
+ lines.push('', 'Shortcut IDs:');
195
+ for (const shortcut of shortcuts) {
196
+ lines.push(`- ${shortcut}`);
197
+ }
198
+ }
199
+ return lines.join('\n');
200
+ }
201
+ function buildQueueStubLines() {
202
+ return [
203
+ '(function(){ var r = window.rover = window.rover || function(){ (r.q = r.q || []).push(arguments); }; r.l = +new Date(); })();',
204
+ ];
205
+ }
206
+ function buildBootScript(bootConfig) {
207
+ const lines = [
208
+ '<script>',
209
+ ...buildQueueStubLines().map(line => ` ${line}`),
210
+ ` rover('boot', ${indentJson(bootConfig)});`,
211
+ '</script>',
212
+ ];
213
+ return lines.join('\n');
214
+ }
215
+ function buildRoverBookAttachScript(config, options) {
216
+ const pollIntervalMs = normalizeAttachPollIntervalMs(options?.pollIntervalMs);
217
+ const maxAttempts = normalizeAttachMaxAttempts(options?.maxAttempts);
218
+ return [
219
+ '<script>',
220
+ ' (function(){',
221
+ ` var roverBookConfig = ${indentJson(config)};`,
222
+ ' function attachRoverBook(){',
223
+ ' if (window.__ROVERBOOK_INSTANCE__) return true;',
224
+ ' var roverApi = window.rover;',
225
+ ' var roverBook = window.RoverBook;',
226
+ " if (!roverApi || typeof roverApi.on !== 'function' || typeof roverApi.requestSigned !== 'function') return false;",
227
+ " if (!roverBook || typeof roverBook.enableRoverBook !== 'function') return false;",
228
+ ' window.__ROVERBOOK_INSTANCE__ = roverBook.enableRoverBook(roverApi, roverBookConfig);',
229
+ ' return true;',
230
+ ' }',
231
+ ' if (attachRoverBook()) return;',
232
+ ' var attempts = 0;',
233
+ ' var timer = setInterval(function(){',
234
+ ' attempts += 1;',
235
+ ` if (attachRoverBook() || attempts >= ${maxAttempts}) clearInterval(timer);`,
236
+ ` }, ${pollIntervalMs});`,
237
+ ' })();',
238
+ '</script>',
239
+ ].join('\n');
240
+ }
241
+ export function createRoverOwnerInstallBundle(input) {
242
+ const bootConfig = input.bootConfig;
243
+ const discoveryConfig = discoveryEnabled(input.discovery) ? input.discovery : null;
244
+ const publishedAgentCardUrl = discoveryConfig ? text(discoveryConfig.agentCardUrl) || DEFAULT_AGENT_CARD_PATH : '';
245
+ const publishedRoverSiteUrl = discoveryConfig ? text(discoveryConfig.roverSiteUrl) || DEFAULT_ROVER_SITE_PATH : '';
246
+ const publishLlmsTxt = llmsEnabled(input, discoveryConfig);
247
+ const publishedLlmsUrl = discoveryConfig ? text(discoveryConfig.llmsUrl) : '';
248
+ const embedScriptUrl = text(input.embedScriptUrl) || DEFAULT_EMBED_SCRIPT_URL;
249
+ const roverBookEnabled = input.roverBook?.enabled !== false && hasObjectEntries(input.roverBook?.config);
250
+ const roverBookScriptUrl = roverBookEnabled
251
+ ? (text(input.roverBook?.scriptUrl) || DEFAULT_ROVERBOOK_SCRIPT_URL)
252
+ : '';
253
+ const agentCard = discoveryConfig ? createRoverAgentCard(discoveryConfig) : undefined;
254
+ const agentCardJson = discoveryConfig ? createRoverAgentCardJson(discoveryConfig) : undefined;
255
+ const roverSite = discoveryConfig ? createRoverSiteProfile(discoveryConfig) : undefined;
256
+ const roverSiteJson = discoveryConfig ? createRoverSiteProfileJson(discoveryConfig) : undefined;
257
+ const pageManifestJson = discoveryConfig
258
+ ? JSON.stringify(agentCard?.extensions?.rover.currentPage || null, null, 2)
259
+ : undefined;
260
+ const marker = agentCard && publishedAgentCardUrl
261
+ ? buildOwnerMarker(agentCard, publishedAgentCardUrl)
262
+ : undefined;
263
+ const markerJson = marker ? escapeScriptJson(JSON.stringify(marker)) : undefined;
264
+ const escapedAgentCardJson = agentCardJson ? escapeScriptJson(agentCardJson) : undefined;
265
+ const escapedRoverSiteJson = roverSiteJson ? escapeScriptJson(roverSiteJson) : undefined;
266
+ const escapedPageManifestJson = pageManifestJson ? escapeScriptJson(pageManifestJson) : undefined;
267
+ const serviceDescLinkTag = discoveryConfig && publishedAgentCardUrl
268
+ ? `<link rel="service-desc" href="${escapeHtmlAttr(publishedAgentCardUrl)}" type="application/json" />`
269
+ : undefined;
270
+ const serviceDocLinkTag = discoveryConfig && publishedLlmsUrl
271
+ ? `<link rel="service-doc" href="${escapeHtmlAttr(publishedLlmsUrl)}" type="text/markdown" />`
272
+ : undefined;
273
+ const bodyLines = [];
274
+ if (markerJson) {
275
+ bodyLines.push(`<script type="application/agent+json" data-rover-agent-discovery="marker">${markerJson}</script>`);
276
+ }
277
+ if (escapedRoverSiteJson) {
278
+ bodyLines.push(`<script type="application/rover-site+json" data-rover-agent-discovery="rover-site">${escapedRoverSiteJson}</script>`);
279
+ }
280
+ if (escapedPageManifestJson) {
281
+ bodyLines.push(`<script type="application/rover-page+json" data-rover-agent-discovery="page">${escapedPageManifestJson}</script>`);
282
+ }
283
+ if (escapedAgentCardJson) {
284
+ bodyLines.push(`<script type="application/agent-card+json" data-rover-agent-discovery="agent-card">${escapedAgentCardJson}</script>`);
285
+ }
286
+ bodyLines.push(buildBootScript(bootConfig));
287
+ bodyLines.push(`<script src="${escapeHtmlAttr(embedScriptUrl)}" async></script>`);
288
+ if (roverBookEnabled && roverBookScriptUrl) {
289
+ bodyLines.push(`<script src="${escapeHtmlAttr(roverBookScriptUrl)}" async></script>`);
290
+ bodyLines.push(buildRoverBookAttachScript(input.roverBook?.config || {}, {
291
+ pollIntervalMs: input.roverBook?.attachPollIntervalMs,
292
+ maxAttempts: input.roverBook?.attachMaxAttempts,
293
+ }));
294
+ }
295
+ const llmsTxt = publishLlmsTxt && agentCard
296
+ ? (text(input.llmsTxt) ? input.llmsTxt : buildDefaultLlmsTxt(agentCard, { agentCardUrl: publishedAgentCardUrl || DEFAULT_AGENT_CARD_PATH }))
297
+ : undefined;
298
+ return decorateBundleWithExperience({
299
+ bodyInstallHtml: bodyLines.join('\n'),
300
+ headDiscoveryHtml: [serviceDescLinkTag, serviceDocLinkTag].filter(Boolean).join('\n'),
301
+ agentCard,
302
+ agentCardJson,
303
+ roverSite,
304
+ roverSiteJson,
305
+ serviceDescLinkHeader: discoveryConfig
306
+ ? createRoverServiceDescLinkHeader({
307
+ agentCardUrl: publishedAgentCardUrl || DEFAULT_AGENT_CARD_PATH,
308
+ ...(publishedLlmsUrl ? { llmsUrl: publishedLlmsUrl } : {}),
309
+ })
310
+ : undefined,
311
+ llmsTxt,
312
+ metadata: {
313
+ discoveryEnabled: !!discoveryConfig,
314
+ llmsPublished: !!serviceDocLinkTag,
315
+ embedScriptUrl,
316
+ roverBookEnabled,
317
+ roverBookScriptUrl: roverBookScriptUrl || undefined,
318
+ publishedAgentCardUrl: publishedAgentCardUrl || undefined,
319
+ publishedRoverSiteUrl: publishedRoverSiteUrl || undefined,
320
+ publishedLlmsUrl: publishedLlmsUrl || undefined,
321
+ serviceDescLinkTag,
322
+ serviceDocLinkTag,
323
+ markerJson,
324
+ markerScript: markerJson
325
+ ? `<script type="application/agent+json" data-rover-agent-discovery="marker">${markerJson}</script>`
326
+ : undefined,
327
+ inlineAgentCardScript: escapedAgentCardJson
328
+ ? `<script type="application/agent-card+json" data-rover-agent-discovery="agent-card">${escapedAgentCardJson}</script>`
329
+ : undefined,
330
+ roverSiteJson,
331
+ inlineRoverSiteScript: escapedRoverSiteJson
332
+ ? `<script type="application/rover-site+json" data-rover-agent-discovery="rover-site">${escapedRoverSiteJson}</script>`
333
+ : undefined,
334
+ pageManifestJson,
335
+ pageManifestScript: escapedPageManifestJson
336
+ ? `<script type="application/rover-page+json" data-rover-agent-discovery="page">${escapedPageManifestJson}</script>`
337
+ : undefined,
338
+ },
339
+ }, input.bootConfig);
340
+ }
@@ -0,0 +1,36 @@
1
+ export type RoverPreviewAttachLaunch = {
2
+ requestId: string;
3
+ attachToken: string;
4
+ };
5
+ export type RoverPreviewBootstrapVoiceConfig = {
6
+ enabled?: boolean;
7
+ language?: string;
8
+ autoStopMs?: number;
9
+ };
10
+ export type RoverPreviewBootstrapUiConfig = {
11
+ voice?: RoverPreviewBootstrapVoiceConfig;
12
+ };
13
+ export type RoverPreviewBootstrapConfig = {
14
+ scriptUrl?: string;
15
+ siteId: string;
16
+ publicKey?: string;
17
+ sessionToken?: string;
18
+ sessionId?: string;
19
+ siteKeyId?: string;
20
+ apiBase?: string;
21
+ workerUrl?: string;
22
+ allowedDomains?: string[];
23
+ domainScopeMode?: 'host_only' | 'registrable_domain';
24
+ externalNavigationPolicy?: 'open_new_tab_notice' | 'block' | 'allow';
25
+ sessionScope?: 'shared_site' | 'tab';
26
+ openOnInit?: boolean;
27
+ mode?: 'safe' | 'full';
28
+ allowActions?: boolean;
29
+ ui?: RoverPreviewBootstrapUiConfig;
30
+ attachLaunch?: RoverPreviewAttachLaunch;
31
+ };
32
+ export type RoverScriptAttributeSource = Pick<HTMLScriptElement, 'getAttribute'>;
33
+ export declare function createRoverConsoleSnippet(config: RoverPreviewBootstrapConfig): string;
34
+ export declare function createRoverBookmarklet(config: RoverPreviewBootstrapConfig): string;
35
+ export declare function createRoverScriptTagSnippet(config: RoverPreviewBootstrapConfig): string;
36
+ export declare function readRoverScriptDataAttributes(scriptEl: RoverScriptAttributeSource): RoverPreviewBootstrapConfig | null;