@h-rig/browser-plugin 0.0.6-alpha.156
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 +1 -0
- package/dist/src/browser-contract.d.ts +16 -0
- package/dist/src/browser-contract.js +101 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +167 -0
- package/dist/src/plugin.d.ts +4 -0
- package/dist/src/plugin.js +153 -0
- package/dist/src/service.d.ts +14 -0
- package/dist/src/service.js +104 -0
- package/package.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @h-rig/browser-plugin
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { RuntimeBrowserContext, TaskBrowserConfig } from "@rig/contracts";
|
|
2
|
+
export declare const DEFAULT_BROWSER_ATTACH_URL = "http://127.0.0.1:9333";
|
|
3
|
+
export declare const DEFAULT_BROWSER_MODE = "persistent";
|
|
4
|
+
export declare const RUNTIME_BROWSER_HELPERS: {
|
|
5
|
+
readonly launch: "rig-browser-launch";
|
|
6
|
+
readonly check: "rig-browser-check";
|
|
7
|
+
readonly attachInfo: "rig-browser-attach-info";
|
|
8
|
+
readonly e2e: "rig-browser-e2e";
|
|
9
|
+
readonly resetProfile: "rig-browser-reset-profile";
|
|
10
|
+
};
|
|
11
|
+
export declare function resolveBrowserStateDir(projectRoot: string | undefined, configuredStateDir: string | undefined): string;
|
|
12
|
+
export declare function resolveTaskBrowserContext(browser: TaskBrowserConfig | undefined, options?: {
|
|
13
|
+
hostProjectRoot?: string;
|
|
14
|
+
runtimeId?: string;
|
|
15
|
+
}): RuntimeBrowserContext | undefined;
|
|
16
|
+
export declare function buildBrowserGuidanceLines(browser: RuntimeBrowserContext): string[];
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/browser-plugin/src/browser-contract.ts
|
|
3
|
+
import { resolve } from "path";
|
|
4
|
+
var DEFAULT_BROWSER_ATTACH_URL = "http://127.0.0.1:9333";
|
|
5
|
+
var DEFAULT_BROWSER_MODE = "persistent";
|
|
6
|
+
var RUNTIME_BROWSER_HELPERS = {
|
|
7
|
+
launch: "rig-browser-launch",
|
|
8
|
+
check: "rig-browser-check",
|
|
9
|
+
attachInfo: "rig-browser-attach-info",
|
|
10
|
+
e2e: "rig-browser-e2e",
|
|
11
|
+
resetProfile: "rig-browser-reset-profile"
|
|
12
|
+
};
|
|
13
|
+
var BASE_REMOTE_DEBUGGING_PORT = 9222;
|
|
14
|
+
var REMOTE_DEBUGGING_PORT_SPREAD = 4000;
|
|
15
|
+
function hashString(input) {
|
|
16
|
+
let hash = 0;
|
|
17
|
+
for (let index = 0;index < input.length; index += 1) {
|
|
18
|
+
hash = (hash << 5) - hash + input.charCodeAt(index) | 0;
|
|
19
|
+
}
|
|
20
|
+
return Math.abs(hash);
|
|
21
|
+
}
|
|
22
|
+
function derivePortFromProfile(profileName) {
|
|
23
|
+
return BASE_REMOTE_DEBUGGING_PORT + hashString(profileName) % REMOTE_DEBUGGING_PORT_SPREAD;
|
|
24
|
+
}
|
|
25
|
+
function parseAttachUrl(attachUrl) {
|
|
26
|
+
try {
|
|
27
|
+
return new URL((attachUrl || DEFAULT_BROWSER_ATTACH_URL).trim() || DEFAULT_BROWSER_ATTACH_URL);
|
|
28
|
+
} catch {
|
|
29
|
+
return new URL(DEFAULT_BROWSER_ATTACH_URL);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function sanitizeRuntimeSuffix(runtimeId) {
|
|
33
|
+
return runtimeId.replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 16) || "runtime";
|
|
34
|
+
}
|
|
35
|
+
function resolveBrowserStateDir(projectRoot, configuredStateDir) {
|
|
36
|
+
const trimmed = configuredStateDir?.trim() || ".tmp/rig-browser";
|
|
37
|
+
if (trimmed.startsWith("/")) {
|
|
38
|
+
return resolve(trimmed);
|
|
39
|
+
}
|
|
40
|
+
return resolve(projectRoot || process.cwd(), trimmed);
|
|
41
|
+
}
|
|
42
|
+
function resolveTaskBrowserContext(browser, options = {}) {
|
|
43
|
+
if (!browser?.required) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const defaultProfile = browser.profile?.trim() || "default";
|
|
47
|
+
const mode = browser.mode?.trim() || DEFAULT_BROWSER_MODE;
|
|
48
|
+
const defaultAttach = parseAttachUrl(browser.attach_url);
|
|
49
|
+
const shouldDeriveRuntimeProfile = Boolean(options.runtimeId?.trim()) && mode !== "shared";
|
|
50
|
+
const effectiveProfile = shouldDeriveRuntimeProfile ? `${defaultProfile}-${sanitizeRuntimeSuffix(options.runtimeId.trim())}` : defaultProfile;
|
|
51
|
+
const effectivePort = shouldDeriveRuntimeProfile ? derivePortFromProfile(effectiveProfile) : Number(defaultAttach.port || "80");
|
|
52
|
+
const effectiveAttach = new URL(defaultAttach.toString());
|
|
53
|
+
effectiveAttach.port = String(effectivePort);
|
|
54
|
+
return {
|
|
55
|
+
required: true,
|
|
56
|
+
preset: browser.preset?.trim() || "default",
|
|
57
|
+
mode,
|
|
58
|
+
stateDir: resolveBrowserStateDir(options.hostProjectRoot, browser.state_dir),
|
|
59
|
+
defaultProfile,
|
|
60
|
+
effectiveProfile,
|
|
61
|
+
defaultAttachUrl: defaultAttach.toString(),
|
|
62
|
+
effectiveAttachUrl: effectiveAttach.toString(),
|
|
63
|
+
...browser.dev_command?.trim() ? { devCommand: browser.dev_command.trim() } : {},
|
|
64
|
+
...browser.launch_command?.trim() ? { launchCommand: browser.launch_command.trim() } : {},
|
|
65
|
+
...browser.check_command?.trim() ? { checkCommand: browser.check_command.trim() } : {},
|
|
66
|
+
...browser.e2e_command?.trim() ? { e2eCommand: browser.e2e_command.trim() } : {},
|
|
67
|
+
launchHelper: RUNTIME_BROWSER_HELPERS.launch,
|
|
68
|
+
checkHelper: RUNTIME_BROWSER_HELPERS.check,
|
|
69
|
+
attachInfoHelper: RUNTIME_BROWSER_HELPERS.attachInfo,
|
|
70
|
+
e2eHelper: RUNTIME_BROWSER_HELPERS.e2e,
|
|
71
|
+
resetProfileHelper: RUNTIME_BROWSER_HELPERS.resetProfile
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function buildBrowserGuidanceLines(browser) {
|
|
75
|
+
const lines = [
|
|
76
|
+
"This task requires Rig Browser.",
|
|
77
|
+
`Launch the browser: \`${browser.launchHelper}\`${browser.devCommand ? " or `rig-browser-launch --dev`" : ""}.`,
|
|
78
|
+
`Check the browser contract: \`${browser.checkHelper}\`.`,
|
|
79
|
+
`Show attach details: \`${browser.attachInfoHelper}\`.`,
|
|
80
|
+
`Attach Chrome DevTools MCP to ${browser.effectiveAttachUrl}.`,
|
|
81
|
+
`Preset: ${browser.preset}.`,
|
|
82
|
+
`Profile: ${browser.effectiveProfile}.`,
|
|
83
|
+
`State dir: ${browser.stateDir}.`,
|
|
84
|
+
`Reset the active profile with \`${browser.resetProfileHelper}\`.`
|
|
85
|
+
];
|
|
86
|
+
if (browser.e2eCommand) {
|
|
87
|
+
lines.push(`Run app-owned browser e2e with \`${browser.e2eHelper}\`.`);
|
|
88
|
+
}
|
|
89
|
+
if (browser.defaultProfile !== browser.effectiveProfile) {
|
|
90
|
+
lines.push(`Base profile: ${browser.defaultProfile}. Runtime launches derive an isolated effective profile.`);
|
|
91
|
+
}
|
|
92
|
+
return lines;
|
|
93
|
+
}
|
|
94
|
+
export {
|
|
95
|
+
resolveTaskBrowserContext,
|
|
96
|
+
resolveBrowserStateDir,
|
|
97
|
+
buildBrowserGuidanceLines,
|
|
98
|
+
RUNTIME_BROWSER_HELPERS,
|
|
99
|
+
DEFAULT_BROWSER_MODE,
|
|
100
|
+
DEFAULT_BROWSER_ATTACH_URL
|
|
101
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
|
+
|
|
18
|
+
// packages/browser-plugin/src/browser-contract.ts
|
|
19
|
+
import { resolve } from "path";
|
|
20
|
+
function hashString(input) {
|
|
21
|
+
let hash = 0;
|
|
22
|
+
for (let index = 0;index < input.length; index += 1) {
|
|
23
|
+
hash = (hash << 5) - hash + input.charCodeAt(index) | 0;
|
|
24
|
+
}
|
|
25
|
+
return Math.abs(hash);
|
|
26
|
+
}
|
|
27
|
+
function derivePortFromProfile(profileName) {
|
|
28
|
+
return BASE_REMOTE_DEBUGGING_PORT + hashString(profileName) % REMOTE_DEBUGGING_PORT_SPREAD;
|
|
29
|
+
}
|
|
30
|
+
function parseAttachUrl(attachUrl) {
|
|
31
|
+
try {
|
|
32
|
+
return new URL((attachUrl || DEFAULT_BROWSER_ATTACH_URL).trim() || DEFAULT_BROWSER_ATTACH_URL);
|
|
33
|
+
} catch {
|
|
34
|
+
return new URL(DEFAULT_BROWSER_ATTACH_URL);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function sanitizeRuntimeSuffix(runtimeId) {
|
|
38
|
+
return runtimeId.replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 16) || "runtime";
|
|
39
|
+
}
|
|
40
|
+
function resolveBrowserStateDir(projectRoot, configuredStateDir) {
|
|
41
|
+
const trimmed = configuredStateDir?.trim() || ".tmp/rig-browser";
|
|
42
|
+
if (trimmed.startsWith("/")) {
|
|
43
|
+
return resolve(trimmed);
|
|
44
|
+
}
|
|
45
|
+
return resolve(projectRoot || process.cwd(), trimmed);
|
|
46
|
+
}
|
|
47
|
+
function resolveTaskBrowserContext(browser, options = {}) {
|
|
48
|
+
if (!browser?.required) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const defaultProfile = browser.profile?.trim() || "default";
|
|
52
|
+
const mode = browser.mode?.trim() || DEFAULT_BROWSER_MODE;
|
|
53
|
+
const defaultAttach = parseAttachUrl(browser.attach_url);
|
|
54
|
+
const shouldDeriveRuntimeProfile = Boolean(options.runtimeId?.trim()) && mode !== "shared";
|
|
55
|
+
const effectiveProfile = shouldDeriveRuntimeProfile ? `${defaultProfile}-${sanitizeRuntimeSuffix(options.runtimeId.trim())}` : defaultProfile;
|
|
56
|
+
const effectivePort = shouldDeriveRuntimeProfile ? derivePortFromProfile(effectiveProfile) : Number(defaultAttach.port || "80");
|
|
57
|
+
const effectiveAttach = new URL(defaultAttach.toString());
|
|
58
|
+
effectiveAttach.port = String(effectivePort);
|
|
59
|
+
return {
|
|
60
|
+
required: true,
|
|
61
|
+
preset: browser.preset?.trim() || "default",
|
|
62
|
+
mode,
|
|
63
|
+
stateDir: resolveBrowserStateDir(options.hostProjectRoot, browser.state_dir),
|
|
64
|
+
defaultProfile,
|
|
65
|
+
effectiveProfile,
|
|
66
|
+
defaultAttachUrl: defaultAttach.toString(),
|
|
67
|
+
effectiveAttachUrl: effectiveAttach.toString(),
|
|
68
|
+
...browser.dev_command?.trim() ? { devCommand: browser.dev_command.trim() } : {},
|
|
69
|
+
...browser.launch_command?.trim() ? { launchCommand: browser.launch_command.trim() } : {},
|
|
70
|
+
...browser.check_command?.trim() ? { checkCommand: browser.check_command.trim() } : {},
|
|
71
|
+
...browser.e2e_command?.trim() ? { e2eCommand: browser.e2e_command.trim() } : {},
|
|
72
|
+
launchHelper: RUNTIME_BROWSER_HELPERS.launch,
|
|
73
|
+
checkHelper: RUNTIME_BROWSER_HELPERS.check,
|
|
74
|
+
attachInfoHelper: RUNTIME_BROWSER_HELPERS.attachInfo,
|
|
75
|
+
e2eHelper: RUNTIME_BROWSER_HELPERS.e2e,
|
|
76
|
+
resetProfileHelper: RUNTIME_BROWSER_HELPERS.resetProfile
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function buildBrowserGuidanceLines(browser) {
|
|
80
|
+
const lines = [
|
|
81
|
+
"This task requires Rig Browser.",
|
|
82
|
+
`Launch the browser: \`${browser.launchHelper}\`${browser.devCommand ? " or `rig-browser-launch --dev`" : ""}.`,
|
|
83
|
+
`Check the browser contract: \`${browser.checkHelper}\`.`,
|
|
84
|
+
`Show attach details: \`${browser.attachInfoHelper}\`.`,
|
|
85
|
+
`Attach Chrome DevTools MCP to ${browser.effectiveAttachUrl}.`,
|
|
86
|
+
`Preset: ${browser.preset}.`,
|
|
87
|
+
`Profile: ${browser.effectiveProfile}.`,
|
|
88
|
+
`State dir: ${browser.stateDir}.`,
|
|
89
|
+
`Reset the active profile with \`${browser.resetProfileHelper}\`.`
|
|
90
|
+
];
|
|
91
|
+
if (browser.e2eCommand) {
|
|
92
|
+
lines.push(`Run app-owned browser e2e with \`${browser.e2eHelper}\`.`);
|
|
93
|
+
}
|
|
94
|
+
if (browser.defaultProfile !== browser.effectiveProfile) {
|
|
95
|
+
lines.push(`Base profile: ${browser.defaultProfile}. Runtime launches derive an isolated effective profile.`);
|
|
96
|
+
}
|
|
97
|
+
return lines;
|
|
98
|
+
}
|
|
99
|
+
var DEFAULT_BROWSER_ATTACH_URL = "http://127.0.0.1:9333", DEFAULT_BROWSER_MODE = "persistent", RUNTIME_BROWSER_HELPERS, BASE_REMOTE_DEBUGGING_PORT = 9222, REMOTE_DEBUGGING_PORT_SPREAD = 4000;
|
|
100
|
+
var init_browser_contract = __esm(() => {
|
|
101
|
+
RUNTIME_BROWSER_HELPERS = {
|
|
102
|
+
launch: "rig-browser-launch",
|
|
103
|
+
check: "rig-browser-check",
|
|
104
|
+
attachInfo: "rig-browser-attach-info",
|
|
105
|
+
e2e: "rig-browser-e2e",
|
|
106
|
+
resetProfile: "rig-browser-reset-profile"
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// packages/browser-plugin/src/service.ts
|
|
111
|
+
var exports_service = {};
|
|
112
|
+
__export(exports_service, {
|
|
113
|
+
svc: () => svc,
|
|
114
|
+
browserContractService: () => browserContractService
|
|
115
|
+
});
|
|
116
|
+
var svc, browserContractService;
|
|
117
|
+
var init_service = __esm(() => {
|
|
118
|
+
init_browser_contract();
|
|
119
|
+
svc = {
|
|
120
|
+
resolveTaskBrowserContext,
|
|
121
|
+
buildBrowserGuidanceLines
|
|
122
|
+
};
|
|
123
|
+
browserContractService = svc;
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// packages/browser-plugin/src/index.ts
|
|
127
|
+
init_browser_contract();
|
|
128
|
+
|
|
129
|
+
// packages/browser-plugin/src/plugin.ts
|
|
130
|
+
import { definePlugin } from "@rig/core/config";
|
|
131
|
+
import { BROWSER_CONTRACT_SERVICE_CAPABILITY_ID } from "@rig/contracts";
|
|
132
|
+
var BROWSER_PLUGIN_NAME = "@rig/browser-plugin";
|
|
133
|
+
var browserPlugin = definePlugin({
|
|
134
|
+
name: BROWSER_PLUGIN_NAME,
|
|
135
|
+
version: "0.0.0-alpha.1",
|
|
136
|
+
contributes: {
|
|
137
|
+
capabilities: [
|
|
138
|
+
{
|
|
139
|
+
id: BROWSER_CONTRACT_SERVICE_CAPABILITY_ID,
|
|
140
|
+
title: "Browser-required task contract",
|
|
141
|
+
description: "Resolve a task's browser config into the runtime-effective browser context and render task-info browser guidance.",
|
|
142
|
+
run: async () => (await Promise.resolve().then(() => (init_service(), exports_service))).svc
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
function createBrowserPlugin() {
|
|
148
|
+
return browserPlugin;
|
|
149
|
+
}
|
|
150
|
+
var plugin_default = browserPlugin;
|
|
151
|
+
|
|
152
|
+
// packages/browser-plugin/src/index.ts
|
|
153
|
+
init_service();
|
|
154
|
+
export {
|
|
155
|
+
svc,
|
|
156
|
+
resolveTaskBrowserContext,
|
|
157
|
+
resolveBrowserStateDir,
|
|
158
|
+
plugin_default as default,
|
|
159
|
+
createBrowserPlugin,
|
|
160
|
+
buildBrowserGuidanceLines,
|
|
161
|
+
browserPlugin,
|
|
162
|
+
browserContractService,
|
|
163
|
+
RUNTIME_BROWSER_HELPERS,
|
|
164
|
+
DEFAULT_BROWSER_MODE,
|
|
165
|
+
DEFAULT_BROWSER_ATTACH_URL,
|
|
166
|
+
BROWSER_PLUGIN_NAME
|
|
167
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
|
+
|
|
18
|
+
// packages/browser-plugin/src/browser-contract.ts
|
|
19
|
+
import { resolve } from "path";
|
|
20
|
+
function hashString(input) {
|
|
21
|
+
let hash = 0;
|
|
22
|
+
for (let index = 0;index < input.length; index += 1) {
|
|
23
|
+
hash = (hash << 5) - hash + input.charCodeAt(index) | 0;
|
|
24
|
+
}
|
|
25
|
+
return Math.abs(hash);
|
|
26
|
+
}
|
|
27
|
+
function derivePortFromProfile(profileName) {
|
|
28
|
+
return BASE_REMOTE_DEBUGGING_PORT + hashString(profileName) % REMOTE_DEBUGGING_PORT_SPREAD;
|
|
29
|
+
}
|
|
30
|
+
function parseAttachUrl(attachUrl) {
|
|
31
|
+
try {
|
|
32
|
+
return new URL((attachUrl || DEFAULT_BROWSER_ATTACH_URL).trim() || DEFAULT_BROWSER_ATTACH_URL);
|
|
33
|
+
} catch {
|
|
34
|
+
return new URL(DEFAULT_BROWSER_ATTACH_URL);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function sanitizeRuntimeSuffix(runtimeId) {
|
|
38
|
+
return runtimeId.replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 16) || "runtime";
|
|
39
|
+
}
|
|
40
|
+
function resolveBrowserStateDir(projectRoot, configuredStateDir) {
|
|
41
|
+
const trimmed = configuredStateDir?.trim() || ".tmp/rig-browser";
|
|
42
|
+
if (trimmed.startsWith("/")) {
|
|
43
|
+
return resolve(trimmed);
|
|
44
|
+
}
|
|
45
|
+
return resolve(projectRoot || process.cwd(), trimmed);
|
|
46
|
+
}
|
|
47
|
+
function resolveTaskBrowserContext(browser, options = {}) {
|
|
48
|
+
if (!browser?.required) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const defaultProfile = browser.profile?.trim() || "default";
|
|
52
|
+
const mode = browser.mode?.trim() || DEFAULT_BROWSER_MODE;
|
|
53
|
+
const defaultAttach = parseAttachUrl(browser.attach_url);
|
|
54
|
+
const shouldDeriveRuntimeProfile = Boolean(options.runtimeId?.trim()) && mode !== "shared";
|
|
55
|
+
const effectiveProfile = shouldDeriveRuntimeProfile ? `${defaultProfile}-${sanitizeRuntimeSuffix(options.runtimeId.trim())}` : defaultProfile;
|
|
56
|
+
const effectivePort = shouldDeriveRuntimeProfile ? derivePortFromProfile(effectiveProfile) : Number(defaultAttach.port || "80");
|
|
57
|
+
const effectiveAttach = new URL(defaultAttach.toString());
|
|
58
|
+
effectiveAttach.port = String(effectivePort);
|
|
59
|
+
return {
|
|
60
|
+
required: true,
|
|
61
|
+
preset: browser.preset?.trim() || "default",
|
|
62
|
+
mode,
|
|
63
|
+
stateDir: resolveBrowserStateDir(options.hostProjectRoot, browser.state_dir),
|
|
64
|
+
defaultProfile,
|
|
65
|
+
effectiveProfile,
|
|
66
|
+
defaultAttachUrl: defaultAttach.toString(),
|
|
67
|
+
effectiveAttachUrl: effectiveAttach.toString(),
|
|
68
|
+
...browser.dev_command?.trim() ? { devCommand: browser.dev_command.trim() } : {},
|
|
69
|
+
...browser.launch_command?.trim() ? { launchCommand: browser.launch_command.trim() } : {},
|
|
70
|
+
...browser.check_command?.trim() ? { checkCommand: browser.check_command.trim() } : {},
|
|
71
|
+
...browser.e2e_command?.trim() ? { e2eCommand: browser.e2e_command.trim() } : {},
|
|
72
|
+
launchHelper: RUNTIME_BROWSER_HELPERS.launch,
|
|
73
|
+
checkHelper: RUNTIME_BROWSER_HELPERS.check,
|
|
74
|
+
attachInfoHelper: RUNTIME_BROWSER_HELPERS.attachInfo,
|
|
75
|
+
e2eHelper: RUNTIME_BROWSER_HELPERS.e2e,
|
|
76
|
+
resetProfileHelper: RUNTIME_BROWSER_HELPERS.resetProfile
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function buildBrowserGuidanceLines(browser) {
|
|
80
|
+
const lines = [
|
|
81
|
+
"This task requires Rig Browser.",
|
|
82
|
+
`Launch the browser: \`${browser.launchHelper}\`${browser.devCommand ? " or `rig-browser-launch --dev`" : ""}.`,
|
|
83
|
+
`Check the browser contract: \`${browser.checkHelper}\`.`,
|
|
84
|
+
`Show attach details: \`${browser.attachInfoHelper}\`.`,
|
|
85
|
+
`Attach Chrome DevTools MCP to ${browser.effectiveAttachUrl}.`,
|
|
86
|
+
`Preset: ${browser.preset}.`,
|
|
87
|
+
`Profile: ${browser.effectiveProfile}.`,
|
|
88
|
+
`State dir: ${browser.stateDir}.`,
|
|
89
|
+
`Reset the active profile with \`${browser.resetProfileHelper}\`.`
|
|
90
|
+
];
|
|
91
|
+
if (browser.e2eCommand) {
|
|
92
|
+
lines.push(`Run app-owned browser e2e with \`${browser.e2eHelper}\`.`);
|
|
93
|
+
}
|
|
94
|
+
if (browser.defaultProfile !== browser.effectiveProfile) {
|
|
95
|
+
lines.push(`Base profile: ${browser.defaultProfile}. Runtime launches derive an isolated effective profile.`);
|
|
96
|
+
}
|
|
97
|
+
return lines;
|
|
98
|
+
}
|
|
99
|
+
var DEFAULT_BROWSER_ATTACH_URL = "http://127.0.0.1:9333", DEFAULT_BROWSER_MODE = "persistent", RUNTIME_BROWSER_HELPERS, BASE_REMOTE_DEBUGGING_PORT = 9222, REMOTE_DEBUGGING_PORT_SPREAD = 4000;
|
|
100
|
+
var init_browser_contract = __esm(() => {
|
|
101
|
+
RUNTIME_BROWSER_HELPERS = {
|
|
102
|
+
launch: "rig-browser-launch",
|
|
103
|
+
check: "rig-browser-check",
|
|
104
|
+
attachInfo: "rig-browser-attach-info",
|
|
105
|
+
e2e: "rig-browser-e2e",
|
|
106
|
+
resetProfile: "rig-browser-reset-profile"
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// packages/browser-plugin/src/service.ts
|
|
111
|
+
var exports_service = {};
|
|
112
|
+
__export(exports_service, {
|
|
113
|
+
svc: () => svc,
|
|
114
|
+
browserContractService: () => browserContractService
|
|
115
|
+
});
|
|
116
|
+
var svc, browserContractService;
|
|
117
|
+
var init_service = __esm(() => {
|
|
118
|
+
init_browser_contract();
|
|
119
|
+
svc = {
|
|
120
|
+
resolveTaskBrowserContext,
|
|
121
|
+
buildBrowserGuidanceLines
|
|
122
|
+
};
|
|
123
|
+
browserContractService = svc;
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// packages/browser-plugin/src/plugin.ts
|
|
127
|
+
import { definePlugin } from "@rig/core/config";
|
|
128
|
+
import { BROWSER_CONTRACT_SERVICE_CAPABILITY_ID } from "@rig/contracts";
|
|
129
|
+
var BROWSER_PLUGIN_NAME = "@rig/browser-plugin";
|
|
130
|
+
var browserPlugin = definePlugin({
|
|
131
|
+
name: BROWSER_PLUGIN_NAME,
|
|
132
|
+
version: "0.0.0-alpha.1",
|
|
133
|
+
contributes: {
|
|
134
|
+
capabilities: [
|
|
135
|
+
{
|
|
136
|
+
id: BROWSER_CONTRACT_SERVICE_CAPABILITY_ID,
|
|
137
|
+
title: "Browser-required task contract",
|
|
138
|
+
description: "Resolve a task's browser config into the runtime-effective browser context and render task-info browser guidance.",
|
|
139
|
+
run: async () => (await Promise.resolve().then(() => (init_service(), exports_service))).svc
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
function createBrowserPlugin() {
|
|
145
|
+
return browserPlugin;
|
|
146
|
+
}
|
|
147
|
+
var plugin_default = browserPlugin;
|
|
148
|
+
export {
|
|
149
|
+
plugin_default as default,
|
|
150
|
+
createBrowserPlugin,
|
|
151
|
+
browserPlugin,
|
|
152
|
+
BROWSER_PLUGIN_NAME
|
|
153
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* service.ts — the concrete browser-contract service the runtime port resolves
|
|
3
|
+
* and consumes.
|
|
4
|
+
*
|
|
5
|
+
* CONFIG-LIGHT: this module top-level-imports the browser-contract impl. It is
|
|
6
|
+
* loaded LAZILY by the capability `run()` in plugin.ts
|
|
7
|
+
* (`(await import("./service")).svc`), so merely evaluating rig.config.ts never
|
|
8
|
+
* drags the browser-contract impl into scope.
|
|
9
|
+
*/
|
|
10
|
+
import type { BrowserContractService } from "@rig/runtime/control-plane/browser-contract-port";
|
|
11
|
+
/** The concrete browser-contract service the runtime port resolves and consumes. */
|
|
12
|
+
export declare const svc: BrowserContractService;
|
|
13
|
+
/** Back-compat alias. */
|
|
14
|
+
export declare const browserContractService: BrowserContractService;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/browser-plugin/src/browser-contract.ts
|
|
3
|
+
import { resolve } from "path";
|
|
4
|
+
var DEFAULT_BROWSER_ATTACH_URL = "http://127.0.0.1:9333";
|
|
5
|
+
var DEFAULT_BROWSER_MODE = "persistent";
|
|
6
|
+
var RUNTIME_BROWSER_HELPERS = {
|
|
7
|
+
launch: "rig-browser-launch",
|
|
8
|
+
check: "rig-browser-check",
|
|
9
|
+
attachInfo: "rig-browser-attach-info",
|
|
10
|
+
e2e: "rig-browser-e2e",
|
|
11
|
+
resetProfile: "rig-browser-reset-profile"
|
|
12
|
+
};
|
|
13
|
+
var BASE_REMOTE_DEBUGGING_PORT = 9222;
|
|
14
|
+
var REMOTE_DEBUGGING_PORT_SPREAD = 4000;
|
|
15
|
+
function hashString(input) {
|
|
16
|
+
let hash = 0;
|
|
17
|
+
for (let index = 0;index < input.length; index += 1) {
|
|
18
|
+
hash = (hash << 5) - hash + input.charCodeAt(index) | 0;
|
|
19
|
+
}
|
|
20
|
+
return Math.abs(hash);
|
|
21
|
+
}
|
|
22
|
+
function derivePortFromProfile(profileName) {
|
|
23
|
+
return BASE_REMOTE_DEBUGGING_PORT + hashString(profileName) % REMOTE_DEBUGGING_PORT_SPREAD;
|
|
24
|
+
}
|
|
25
|
+
function parseAttachUrl(attachUrl) {
|
|
26
|
+
try {
|
|
27
|
+
return new URL((attachUrl || DEFAULT_BROWSER_ATTACH_URL).trim() || DEFAULT_BROWSER_ATTACH_URL);
|
|
28
|
+
} catch {
|
|
29
|
+
return new URL(DEFAULT_BROWSER_ATTACH_URL);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function sanitizeRuntimeSuffix(runtimeId) {
|
|
33
|
+
return runtimeId.replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 16) || "runtime";
|
|
34
|
+
}
|
|
35
|
+
function resolveBrowserStateDir(projectRoot, configuredStateDir) {
|
|
36
|
+
const trimmed = configuredStateDir?.trim() || ".tmp/rig-browser";
|
|
37
|
+
if (trimmed.startsWith("/")) {
|
|
38
|
+
return resolve(trimmed);
|
|
39
|
+
}
|
|
40
|
+
return resolve(projectRoot || process.cwd(), trimmed);
|
|
41
|
+
}
|
|
42
|
+
function resolveTaskBrowserContext(browser, options = {}) {
|
|
43
|
+
if (!browser?.required) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const defaultProfile = browser.profile?.trim() || "default";
|
|
47
|
+
const mode = browser.mode?.trim() || DEFAULT_BROWSER_MODE;
|
|
48
|
+
const defaultAttach = parseAttachUrl(browser.attach_url);
|
|
49
|
+
const shouldDeriveRuntimeProfile = Boolean(options.runtimeId?.trim()) && mode !== "shared";
|
|
50
|
+
const effectiveProfile = shouldDeriveRuntimeProfile ? `${defaultProfile}-${sanitizeRuntimeSuffix(options.runtimeId.trim())}` : defaultProfile;
|
|
51
|
+
const effectivePort = shouldDeriveRuntimeProfile ? derivePortFromProfile(effectiveProfile) : Number(defaultAttach.port || "80");
|
|
52
|
+
const effectiveAttach = new URL(defaultAttach.toString());
|
|
53
|
+
effectiveAttach.port = String(effectivePort);
|
|
54
|
+
return {
|
|
55
|
+
required: true,
|
|
56
|
+
preset: browser.preset?.trim() || "default",
|
|
57
|
+
mode,
|
|
58
|
+
stateDir: resolveBrowserStateDir(options.hostProjectRoot, browser.state_dir),
|
|
59
|
+
defaultProfile,
|
|
60
|
+
effectiveProfile,
|
|
61
|
+
defaultAttachUrl: defaultAttach.toString(),
|
|
62
|
+
effectiveAttachUrl: effectiveAttach.toString(),
|
|
63
|
+
...browser.dev_command?.trim() ? { devCommand: browser.dev_command.trim() } : {},
|
|
64
|
+
...browser.launch_command?.trim() ? { launchCommand: browser.launch_command.trim() } : {},
|
|
65
|
+
...browser.check_command?.trim() ? { checkCommand: browser.check_command.trim() } : {},
|
|
66
|
+
...browser.e2e_command?.trim() ? { e2eCommand: browser.e2e_command.trim() } : {},
|
|
67
|
+
launchHelper: RUNTIME_BROWSER_HELPERS.launch,
|
|
68
|
+
checkHelper: RUNTIME_BROWSER_HELPERS.check,
|
|
69
|
+
attachInfoHelper: RUNTIME_BROWSER_HELPERS.attachInfo,
|
|
70
|
+
e2eHelper: RUNTIME_BROWSER_HELPERS.e2e,
|
|
71
|
+
resetProfileHelper: RUNTIME_BROWSER_HELPERS.resetProfile
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function buildBrowserGuidanceLines(browser) {
|
|
75
|
+
const lines = [
|
|
76
|
+
"This task requires Rig Browser.",
|
|
77
|
+
`Launch the browser: \`${browser.launchHelper}\`${browser.devCommand ? " or `rig-browser-launch --dev`" : ""}.`,
|
|
78
|
+
`Check the browser contract: \`${browser.checkHelper}\`.`,
|
|
79
|
+
`Show attach details: \`${browser.attachInfoHelper}\`.`,
|
|
80
|
+
`Attach Chrome DevTools MCP to ${browser.effectiveAttachUrl}.`,
|
|
81
|
+
`Preset: ${browser.preset}.`,
|
|
82
|
+
`Profile: ${browser.effectiveProfile}.`,
|
|
83
|
+
`State dir: ${browser.stateDir}.`,
|
|
84
|
+
`Reset the active profile with \`${browser.resetProfileHelper}\`.`
|
|
85
|
+
];
|
|
86
|
+
if (browser.e2eCommand) {
|
|
87
|
+
lines.push(`Run app-owned browser e2e with \`${browser.e2eHelper}\`.`);
|
|
88
|
+
}
|
|
89
|
+
if (browser.defaultProfile !== browser.effectiveProfile) {
|
|
90
|
+
lines.push(`Base profile: ${browser.defaultProfile}. Runtime launches derive an isolated effective profile.`);
|
|
91
|
+
}
|
|
92
|
+
return lines;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// packages/browser-plugin/src/service.ts
|
|
96
|
+
var svc = {
|
|
97
|
+
resolveTaskBrowserContext,
|
|
98
|
+
buildBrowserGuidanceLines
|
|
99
|
+
};
|
|
100
|
+
var browserContractService = svc;
|
|
101
|
+
export {
|
|
102
|
+
svc,
|
|
103
|
+
browserContractService
|
|
104
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@h-rig/browser-plugin",
|
|
3
|
+
"version": "0.0.6-alpha.156",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "First-party browser-required task contract capability plugin for Rig.",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/src/plugin.d.ts",
|
|
14
|
+
"import": "./dist/src/plugin.js"
|
|
15
|
+
},
|
|
16
|
+
"./plugin": {
|
|
17
|
+
"types": "./dist/src/plugin.d.ts",
|
|
18
|
+
"import": "./dist/src/plugin.js"
|
|
19
|
+
},
|
|
20
|
+
"./index": {
|
|
21
|
+
"types": "./dist/src/index.d.ts",
|
|
22
|
+
"import": "./dist/src/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"bun": ">=1.3.11"
|
|
27
|
+
},
|
|
28
|
+
"main": "./dist/src/index.js",
|
|
29
|
+
"module": "./dist/src/index.js",
|
|
30
|
+
"types": "./dist/src/index.d.ts",
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.156",
|
|
33
|
+
"@rig/core": "npm:@h-rig/core@0.0.6-alpha.156",
|
|
34
|
+
"@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.156"
|
|
35
|
+
}
|
|
36
|
+
}
|