@h-rig/provider-plugin 0.0.6-alpha.157 → 0.0.6-alpha.159
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/bin/rig-agent-dispatch.d.ts +2 -0
- package/dist/bin/rig-agent-dispatch.js +863 -0
- package/dist/src/agent-harness/agent-mode.d.ts +1 -0
- package/dist/src/agent-harness/agent-mode.js +48 -0
- package/dist/src/agent-harness/agent-wrapper.d.ts +53 -0
- package/dist/src/agent-harness/agent-wrapper.js +916 -0
- package/dist/src/agent-harness/controlled-bash.d.ts +3 -0
- package/dist/src/agent-harness/controlled-bash.js +45 -0
- package/dist/src/agent-harness/git-ops.d.ts +2 -0
- package/dist/src/agent-harness/git-ops.js +27 -0
- package/dist/src/agent-harness/repo-ops.d.ts +8 -0
- package/dist/src/agent-harness/repo-ops.js +471 -0
- package/dist/src/agent-harness/rig-agent-entrypoint.d.ts +1 -0
- package/dist/src/agent-harness/rig-agent-entrypoint.js +1277 -0
- package/dist/src/agent-harness/rig-agent.d.ts +2 -0
- package/dist/src/agent-harness/rig-agent.js +1244 -0
- package/dist/src/agent-harness/runtime-snapshot-config.d.ts +2 -0
- package/dist/src/agent-harness/runtime-snapshot-config.js +25 -0
- package/dist/src/agent-harness/task-data.d.ts +2 -0
- package/dist/src/agent-harness/task-data.js +12 -0
- package/dist/src/agent-harness/task-ops.d.ts +10 -0
- package/dist/src/agent-harness/task-ops.js +53 -0
- package/dist/src/index.js +3366 -16
- package/dist/src/pi-settings-materializer.d.ts +10 -0
- package/dist/src/pi-settings-materializer.js +52 -0
- package/dist/src/plugin.d.ts +9 -2
- package/dist/src/plugin.js +3360 -8
- package/dist/src/service.d.ts +1 -1
- package/dist/src/session-asset-materializer-service.d.ts +13 -0
- package/dist/src/session-asset-materializer-service.js +124 -0
- package/dist/src/skill-materializer.d.ts +25 -0
- package/dist/src/skill-materializer.js +46 -0
- package/dist/src/tooling/binary-build-worker.d.ts +1 -0
- package/dist/src/tooling/binary-build-worker.js +323 -0
- package/dist/src/tooling/browser-tool-entrypoint.d.ts +2 -0
- package/dist/src/tooling/browser-tool-entrypoint.js +125 -0
- package/dist/src/tooling/browser-tools.d.ts +3 -0
- package/dist/src/tooling/browser-tools.js +27 -0
- package/dist/src/tooling/claude-router-binary.d.ts +3 -0
- package/dist/src/tooling/claude-router-binary.js +381 -0
- package/dist/src/tooling/claude-router.d.ts +22 -0
- package/dist/src/tooling/claude-router.js +524 -0
- package/dist/src/tooling/embedded-native-assets.d.ts +7 -0
- package/dist/src/tooling/embedded-native-assets.js +6 -0
- package/dist/src/tooling/file-tools.d.ts +5 -0
- package/dist/src/tooling/file-tools.js +224 -0
- package/dist/src/tooling/gateway.d.ts +4 -0
- package/dist/src/tooling/gateway.js +430 -0
- package/dist/src/tooling/native-extract.d.ts +2 -0
- package/dist/src/tooling/native-extract.js +44 -0
- package/dist/src/tooling/runtime-binary-build.d.ts +88 -0
- package/dist/src/tooling/runtime-binary-build.js +480 -0
- package/dist/src/tooling/shell-tools.d.ts +5 -0
- package/dist/src/tooling/shell-tools.js +217 -0
- package/native/darwin-arm64/rig-shell +0 -0
- package/native/darwin-arm64/rig-shell.build-manifest.json +4 -0
- package/native/darwin-arm64/rig-tools +0 -0
- package/native/darwin-arm64/rig-tools.build-manifest.json +4 -0
- package/native/darwin-x64/rig-shell +0 -0
- package/native/darwin-x64/rig-tools +0 -0
- package/native/linux-arm64/rig-shell +0 -0
- package/native/linux-arm64/rig-tools +0 -0
- package/native/linux-x64/rig-shell +0 -0
- package/native/linux-x64/rig-tools +0 -0
- package/native/win32-x64/rig-shell.exe +0 -0
- package/native/win32-x64/rig-tools.exe +0 -0
- package/package.json +54 -5
- package/dist/src/claude-stream-records.d.ts +0 -24
- package/dist/src/claude-stream-records.js +0 -158
- package/dist/src/codex-app-server.d.ts +0 -16
- package/dist/src/codex-app-server.js +0 -548
- package/dist/src/codex-exec-records.d.ts +0 -27
- package/dist/src/codex-exec-records.js +0 -203
package/dist/src/service.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* (`(await import("./service")).svc`), so merely evaluating rig.config.ts never
|
|
8
8
|
* drags the provider impl into scope.
|
|
9
9
|
*/
|
|
10
|
-
import type { RuntimeInstructionService } from "@rig/
|
|
10
|
+
import type { RuntimeInstructionService } from "@rig/contracts";
|
|
11
11
|
/** The concrete agent-harness instruction service the runtime port resolves. */
|
|
12
12
|
export declare const svc: RuntimeInstructionService;
|
|
13
13
|
/** Back-compat alias. */
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SessionAssetMaterializerService } from "@rig/contracts";
|
|
2
|
+
/**
|
|
3
|
+
* Provider-owned implementation of the SESSION_ASSET_MATERIALIZER capability.
|
|
4
|
+
*
|
|
5
|
+
* This is the logic that previously lived inline in the runtime's
|
|
6
|
+
* `plugin-host-context`: extract plugin-contributed skills + config-declared Pi
|
|
7
|
+
* packages from the loaded rig.config and materialize them into the workspace's
|
|
8
|
+
* `.pi/` directory. It moved here (provider domain) so the plugin-host assembler
|
|
9
|
+
* in @rig/core can trigger materialization through the capability seam without a
|
|
10
|
+
* floor->plugin import. Every step is non-fatal — a write failure logs and
|
|
11
|
+
* continues so it can never deadlock harness boot.
|
|
12
|
+
*/
|
|
13
|
+
export declare const sessionAssetMaterializer: SessionAssetMaterializerService;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/provider-plugin/src/session-asset-materializer-service.ts
|
|
3
|
+
import { existsSync as existsSync3 } from "fs";
|
|
4
|
+
import { resolve as resolvePath } from "path";
|
|
5
|
+
|
|
6
|
+
// packages/provider-plugin/src/skill-materializer.ts
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "fs";
|
|
8
|
+
import { resolve } from "path";
|
|
9
|
+
import { loadSkill } from "@rig/skill-loader";
|
|
10
|
+
var MARKER_FILENAME = ".rig-plugin";
|
|
11
|
+
function skillDirName(id) {
|
|
12
|
+
return id.replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
13
|
+
}
|
|
14
|
+
async function materializeSkills(projectRoot, entries) {
|
|
15
|
+
const skillsRoot = resolve(projectRoot, ".pi", "skills");
|
|
16
|
+
if (existsSync(skillsRoot)) {
|
|
17
|
+
for (const name of readdirSync(skillsRoot)) {
|
|
18
|
+
const dir = resolve(skillsRoot, name);
|
|
19
|
+
if (existsSync(resolve(dir, MARKER_FILENAME))) {
|
|
20
|
+
rmSync(dir, { recursive: true, force: true });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const written = [];
|
|
25
|
+
for (const { pluginName, skill } of entries) {
|
|
26
|
+
const sourcePath = resolve(projectRoot, skill.path);
|
|
27
|
+
if (!existsSync(sourcePath)) {
|
|
28
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${sourcePath} does not exist`);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
let body;
|
|
32
|
+
try {
|
|
33
|
+
await loadSkill(sourcePath);
|
|
34
|
+
body = readFileSync(sourcePath, "utf-8");
|
|
35
|
+
} catch (err) {
|
|
36
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${err instanceof Error ? err.message : err}`);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const dir = resolve(skillsRoot, skillDirName(skill.id));
|
|
40
|
+
mkdirSync(dir, { recursive: true });
|
|
41
|
+
writeFileSync(resolve(dir, "SKILL.md"), body, "utf-8");
|
|
42
|
+
writeFileSync(resolve(dir, MARKER_FILENAME), `${JSON.stringify({ plugin: pluginName, skillId: skill.id }, null, 2)}
|
|
43
|
+
`, "utf-8");
|
|
44
|
+
written.push({ id: skill.id, pluginName, directory: dir });
|
|
45
|
+
}
|
|
46
|
+
return written;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// packages/provider-plugin/src/pi-settings-materializer.ts
|
|
50
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
51
|
+
import { dirname, resolve as resolve2 } from "path";
|
|
52
|
+
var SETTINGS_RELATIVE_PATH = ".pi/settings.json";
|
|
53
|
+
var MANAGED_RECORD_RELATIVE_PATH = ".rig/state/pi-managed-packages.json";
|
|
54
|
+
function readJson(path, fallback) {
|
|
55
|
+
if (!existsSync2(path))
|
|
56
|
+
return fallback;
|
|
57
|
+
try {
|
|
58
|
+
return JSON.parse(readFileSync2(path, "utf-8"));
|
|
59
|
+
} catch {
|
|
60
|
+
return fallback;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function packageKey(entry) {
|
|
64
|
+
if (typeof entry === "string")
|
|
65
|
+
return entry;
|
|
66
|
+
if (entry && typeof entry === "object" && typeof entry.source === "string") {
|
|
67
|
+
return entry.source;
|
|
68
|
+
}
|
|
69
|
+
return JSON.stringify(entry);
|
|
70
|
+
}
|
|
71
|
+
function materializePiPackages(projectRoot, declaredPackages) {
|
|
72
|
+
const settingsPath = resolve2(projectRoot, SETTINGS_RELATIVE_PATH);
|
|
73
|
+
const managedRecordPath = resolve2(projectRoot, MANAGED_RECORD_RELATIVE_PATH);
|
|
74
|
+
const settings = readJson(settingsPath, {});
|
|
75
|
+
const previouslyManaged = new Set(readJson(managedRecordPath, []));
|
|
76
|
+
const existing = Array.isArray(settings.packages) ? settings.packages : [];
|
|
77
|
+
const operatorEntries = existing.filter((entry) => !previouslyManaged.has(packageKey(entry)));
|
|
78
|
+
const operatorKeys = new Set(operatorEntries.map(packageKey));
|
|
79
|
+
const managedToAdd = declaredPackages.filter((pkg) => !operatorKeys.has(pkg));
|
|
80
|
+
const nextPackages = [...operatorEntries, ...managedToAdd];
|
|
81
|
+
if (nextPackages.length > 0 || existsSync2(settingsPath)) {
|
|
82
|
+
const nextSettings = { ...settings };
|
|
83
|
+
if (nextPackages.length > 0) {
|
|
84
|
+
nextSettings.packages = nextPackages;
|
|
85
|
+
} else {
|
|
86
|
+
delete nextSettings.packages;
|
|
87
|
+
}
|
|
88
|
+
mkdirSync2(dirname(settingsPath), { recursive: true });
|
|
89
|
+
writeFileSync2(settingsPath, `${JSON.stringify(nextSettings, null, 2)}
|
|
90
|
+
`, "utf-8");
|
|
91
|
+
}
|
|
92
|
+
mkdirSync2(dirname(managedRecordPath), { recursive: true });
|
|
93
|
+
writeFileSync2(managedRecordPath, `${JSON.stringify(managedToAdd, null, 2)}
|
|
94
|
+
`, "utf-8");
|
|
95
|
+
return { settingsPath, packages: managedToAdd };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// packages/provider-plugin/src/session-asset-materializer-service.ts
|
|
99
|
+
var sessionAssetMaterializer = {
|
|
100
|
+
async materializeSessionAssets(projectRoot, config) {
|
|
101
|
+
try {
|
|
102
|
+
const skillEntries = config.plugins.flatMap((plugin) => (plugin.contributes?.skills ?? []).map((skill) => ({
|
|
103
|
+
pluginName: plugin.name,
|
|
104
|
+
skill
|
|
105
|
+
})));
|
|
106
|
+
if (skillEntries.length > 0) {
|
|
107
|
+
await materializeSkills(projectRoot, skillEntries);
|
|
108
|
+
}
|
|
109
|
+
} catch (err) {
|
|
110
|
+
console.warn(`[session-assets] skill materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
const piPackages = config.runtime?.pi?.packages ?? [];
|
|
114
|
+
if (piPackages.length > 0 || existsSync3(resolvePath(projectRoot, ".rig/state/pi-managed-packages.json"))) {
|
|
115
|
+
materializePiPackages(projectRoot, piPackages);
|
|
116
|
+
}
|
|
117
|
+
} catch (err) {
|
|
118
|
+
console.warn(`[session-assets] Pi package materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
export {
|
|
123
|
+
sessionAssetMaterializer
|
|
124
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { SkillRegistration } from "@rig/contracts";
|
|
2
|
+
export interface PluginSkillEntry {
|
|
3
|
+
/** The plugin that owns this skill. Recorded in the marker file. */
|
|
4
|
+
pluginName: string;
|
|
5
|
+
/** The plugin's skill registration. `path` is resolved against projectRoot
|
|
6
|
+
* unless absolute. */
|
|
7
|
+
skill: SkillRegistration;
|
|
8
|
+
}
|
|
9
|
+
export interface MaterializedSkill {
|
|
10
|
+
id: string;
|
|
11
|
+
pluginName: string;
|
|
12
|
+
directory: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Materialize plugin-contributed skills into `.pi/skills/<id>/SKILL.md`.
|
|
16
|
+
*
|
|
17
|
+
* Removes any previously-materialized plugin skill directories (identified by
|
|
18
|
+
* the `.rig-plugin` marker file) before re-inserting the current set, so the
|
|
19
|
+
* function is idempotent and never touches operator-authored skill
|
|
20
|
+
* directories. Skills whose source file is missing or fails frontmatter
|
|
21
|
+
* parsing are skipped with a warning rather than failing the boot.
|
|
22
|
+
*
|
|
23
|
+
* @returns the skills that were written.
|
|
24
|
+
*/
|
|
25
|
+
export declare function materializeSkills(projectRoot: string, entries: readonly PluginSkillEntry[]): Promise<MaterializedSkill[]>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/provider-plugin/src/skill-materializer.ts
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "fs";
|
|
4
|
+
import { resolve } from "path";
|
|
5
|
+
import { loadSkill } from "@rig/skill-loader";
|
|
6
|
+
var MARKER_FILENAME = ".rig-plugin";
|
|
7
|
+
function skillDirName(id) {
|
|
8
|
+
return id.replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
9
|
+
}
|
|
10
|
+
async function materializeSkills(projectRoot, entries) {
|
|
11
|
+
const skillsRoot = resolve(projectRoot, ".pi", "skills");
|
|
12
|
+
if (existsSync(skillsRoot)) {
|
|
13
|
+
for (const name of readdirSync(skillsRoot)) {
|
|
14
|
+
const dir = resolve(skillsRoot, name);
|
|
15
|
+
if (existsSync(resolve(dir, MARKER_FILENAME))) {
|
|
16
|
+
rmSync(dir, { recursive: true, force: true });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const written = [];
|
|
21
|
+
for (const { pluginName, skill } of entries) {
|
|
22
|
+
const sourcePath = resolve(projectRoot, skill.path);
|
|
23
|
+
if (!existsSync(sourcePath)) {
|
|
24
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${sourcePath} does not exist`);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
let body;
|
|
28
|
+
try {
|
|
29
|
+
await loadSkill(sourcePath);
|
|
30
|
+
body = readFileSync(sourcePath, "utf-8");
|
|
31
|
+
} catch (err) {
|
|
32
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${err instanceof Error ? err.message : err}`);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const dir = resolve(skillsRoot, skillDirName(skill.id));
|
|
36
|
+
mkdirSync(dir, { recursive: true });
|
|
37
|
+
writeFileSync(resolve(dir, "SKILL.md"), body, "utf-8");
|
|
38
|
+
writeFileSync(resolve(dir, MARKER_FILENAME), `${JSON.stringify({ plugin: pluginName, skillId: skill.id }, null, 2)}
|
|
39
|
+
`, "utf-8");
|
|
40
|
+
written.push({ id: skill.id, pluginName, directory: dir });
|
|
41
|
+
}
|
|
42
|
+
return written;
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
materializeSkills
|
|
46
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/provider-plugin/src/tooling/runtime-binary-build.ts
|
|
3
|
+
import { chmodSync, copyFileSync, cpSync, existsSync, linkSync, mkdirSync, renameSync, rmSync, writeFileSync } from "fs";
|
|
4
|
+
import { basename, dirname, resolve as resolve2 } from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { drainMicrotasks, gcAndSweep } from "bun:jsc";
|
|
7
|
+
import { resolveRigLayout } from "@rig/core/layout";
|
|
8
|
+
import { runtimeProvisioningEnv } from "@rig/core/runtime-provisioning-env";
|
|
9
|
+
|
|
10
|
+
// packages/provider-plugin/src/tooling/native-extract.ts
|
|
11
|
+
import { tmpdir } from "os";
|
|
12
|
+
import { resolve } from "path";
|
|
13
|
+
var sharedNativeOutputDir = resolve(tmpdir(), "rig-native");
|
|
14
|
+
|
|
15
|
+
// packages/provider-plugin/src/tooling/runtime-binary-build.ts
|
|
16
|
+
var runtimeBinaryBuildQueue = Promise.resolve();
|
|
17
|
+
async function buildRuntimeBinary(options) {
|
|
18
|
+
return runSerializedRuntimeBinaryBuild(async () => {
|
|
19
|
+
const resolved = resolveRuntimeBinaryBuildOptions(options);
|
|
20
|
+
runBestEffortBuildGc();
|
|
21
|
+
const manifestPath = runtimeBinaryCacheManifestPath(resolved.outputPath);
|
|
22
|
+
const buildKey = createRuntimeBinaryBuildKey({
|
|
23
|
+
entrypoint: resolved.entrypoint,
|
|
24
|
+
define: resolved.define,
|
|
25
|
+
env: resolved.env,
|
|
26
|
+
external: resolved.external
|
|
27
|
+
});
|
|
28
|
+
if (await isRuntimeBinaryBuildFresh({ outputPath: resolved.outputPath, manifestPath, buildKey })) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (shouldUseRuntimeBinaryBuildWorker()) {
|
|
32
|
+
await buildRuntimeBinaryViaWorker(resolved);
|
|
33
|
+
} else {
|
|
34
|
+
await buildRuntimeBinaryInProcess(resolved, { manifestPath, buildKey });
|
|
35
|
+
}
|
|
36
|
+
runBestEffortBuildGc();
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
40
|
+
const tempBuildDir = resolve2(dirname(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
41
|
+
const tempOutputPath = resolve2(tempBuildDir, basename(options.outputPath));
|
|
42
|
+
mkdirSync(tempBuildDir, { recursive: true });
|
|
43
|
+
await withTemporaryEnv({
|
|
44
|
+
...options.env,
|
|
45
|
+
...options.define ? { RIG_BUILD_CONFIG_JSON: JSON.stringify(options.define) } : {}
|
|
46
|
+
}, async () => withTemporaryCwd(tempBuildDir, async () => {
|
|
47
|
+
const buildResult = await Bun.build({
|
|
48
|
+
entrypoints: [options.entrypoint],
|
|
49
|
+
compile: {
|
|
50
|
+
target: currentCompileTarget(),
|
|
51
|
+
outfile: tempOutputPath
|
|
52
|
+
},
|
|
53
|
+
target: "bun",
|
|
54
|
+
format: "esm",
|
|
55
|
+
minify: true,
|
|
56
|
+
bytecode: true,
|
|
57
|
+
metafile: true,
|
|
58
|
+
...options.external ? { external: options.external } : {},
|
|
59
|
+
...options.define ? { define: { __RIG_BUILD_CONFIG__: JSON.stringify(options.define) } } : {}
|
|
60
|
+
});
|
|
61
|
+
if (!buildResult.success) {
|
|
62
|
+
const details = buildResult.logs.map((log) => [log.message, log.position?.file ? `${log.position.file}:${log.position.line}:${log.position.column}` : ""].filter(Boolean).join(" ")).filter(Boolean).join(`
|
|
63
|
+
`);
|
|
64
|
+
throw new Error(`Failed to build ${options.entrypoint}: ${details || "Bun.build() returned errors"}`);
|
|
65
|
+
}
|
|
66
|
+
if (!existsSync(tempOutputPath)) {
|
|
67
|
+
const emitted = buildResult.outputs.map((output) => output.path).join(", ") || "(none)";
|
|
68
|
+
throw new Error(`Failed to build ${options.entrypoint}: Bun.build() did not emit ${tempOutputPath}. Emitted: ${emitted}`);
|
|
69
|
+
}
|
|
70
|
+
renameSync(tempOutputPath, options.outputPath);
|
|
71
|
+
chmodSync(options.outputPath, 493);
|
|
72
|
+
if (manifest) {
|
|
73
|
+
await writeRuntimeBinaryCacheManifest({
|
|
74
|
+
manifestPath: manifest.manifestPath,
|
|
75
|
+
buildKey: manifest.buildKey,
|
|
76
|
+
cwd: tempBuildDir,
|
|
77
|
+
metafile: buildResult.metafile
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
})).finally(() => {
|
|
81
|
+
rmSync(tempBuildDir, { recursive: true, force: true });
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function runBestEffortBuildGc() {
|
|
85
|
+
try {
|
|
86
|
+
drainMicrotasks();
|
|
87
|
+
} catch {}
|
|
88
|
+
try {
|
|
89
|
+
gcAndSweep();
|
|
90
|
+
} catch {}
|
|
91
|
+
}
|
|
92
|
+
function runtimeBinaryCacheManifestPath(outputPath) {
|
|
93
|
+
return `${outputPath}.build-manifest.json`;
|
|
94
|
+
}
|
|
95
|
+
function resolveRuntimeBinaryBuildOptions(options) {
|
|
96
|
+
return {
|
|
97
|
+
...options,
|
|
98
|
+
entrypoint: resolve2(options.cwd, options.sourcePath),
|
|
99
|
+
outputPath: resolve2(options.outputPath)
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function shouldUseRuntimeBinaryBuildWorker() {
|
|
103
|
+
if (process.env.RIG_RUNTIME_BUILD_WORKER === "1") {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
if (process.env.RIG_RUNTIME_BUILD_IN_PROCESS === "1") {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
async function buildRuntimeBinaryViaWorker(options) {
|
|
112
|
+
const workerSourcePath = resolveRuntimeBinaryBuildWorkerSourcePath(options);
|
|
113
|
+
if (!workerSourcePath || !existsSync(workerSourcePath)) {
|
|
114
|
+
await buildRuntimeBinaryInProcess(options, {
|
|
115
|
+
manifestPath: runtimeBinaryCacheManifestPath(options.outputPath),
|
|
116
|
+
buildKey: createRuntimeBinaryBuildKey({
|
|
117
|
+
entrypoint: options.entrypoint,
|
|
118
|
+
define: options.define,
|
|
119
|
+
env: options.env,
|
|
120
|
+
external: options.external
|
|
121
|
+
})
|
|
122
|
+
});
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const payloadPath = createRuntimeBinaryBuildWorkerPayloadPath(options.outputPath);
|
|
126
|
+
const bunCli = resolveRuntimeBinaryBuildWorkerInvocation();
|
|
127
|
+
await Bun.write(payloadPath, `${JSON.stringify(options)}
|
|
128
|
+
`);
|
|
129
|
+
const build = Bun.spawn([bunCli.command, workerSourcePath, payloadPath], {
|
|
130
|
+
cwd: options.cwd,
|
|
131
|
+
stdout: "pipe",
|
|
132
|
+
stderr: "pipe",
|
|
133
|
+
env: {
|
|
134
|
+
...process.env,
|
|
135
|
+
...options.env,
|
|
136
|
+
...bunCli.env,
|
|
137
|
+
RIG_RUNTIME_BUILD_WORKER: "1"
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
const [exitCode, stdout, stderr] = await Promise.all([
|
|
141
|
+
build.exited,
|
|
142
|
+
new Response(build.stdout).text(),
|
|
143
|
+
new Response(build.stderr).text()
|
|
144
|
+
]);
|
|
145
|
+
rmSync(payloadPath, { force: true });
|
|
146
|
+
if (exitCode !== 0) {
|
|
147
|
+
throw new Error(`Failed to build ${options.entrypoint}: ${(stderr || stdout || `worker exited ${exitCode}`).trim()}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function createRuntimeBinaryBuildWorkerPayloadPath(outputPath) {
|
|
151
|
+
return resolve2(dirname(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
|
|
152
|
+
}
|
|
153
|
+
function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
154
|
+
const envRoots = [
|
|
155
|
+
options.cwd?.trim(),
|
|
156
|
+
process.env.RIG_HOST_PROJECT_ROOT?.trim(),
|
|
157
|
+
process.env.PROJECT_RIG_ROOT?.trim()
|
|
158
|
+
].filter(Boolean);
|
|
159
|
+
for (const root of envRoots) {
|
|
160
|
+
const candidate = resolve2(root, "packages/provider-plugin/src/tooling/binary-build-worker.ts");
|
|
161
|
+
if (existsSync(candidate)) {
|
|
162
|
+
return candidate;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const localCandidate = resolve2(import.meta.dir, "binary-build-worker.ts");
|
|
166
|
+
return existsSync(localCandidate) ? localCandidate : null;
|
|
167
|
+
}
|
|
168
|
+
function resolveRuntimeBinaryBuildWorkerInvocation() {
|
|
169
|
+
const bunPath = Bun.which("bun");
|
|
170
|
+
if (bunPath) {
|
|
171
|
+
return { command: bunPath, env: {} };
|
|
172
|
+
}
|
|
173
|
+
if (process.execPath?.trim()) {
|
|
174
|
+
return {
|
|
175
|
+
command: process.execPath,
|
|
176
|
+
env: { BUN_BE_BUN: "1" }
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
throw new Error("bun is required to run the runtime binary build worker.");
|
|
180
|
+
}
|
|
181
|
+
function currentCompileTarget() {
|
|
182
|
+
if (process.platform === "darwin") {
|
|
183
|
+
return process.arch === "arm64" ? "bun-darwin-arm64" : "bun-darwin-x64";
|
|
184
|
+
}
|
|
185
|
+
if (process.platform === "linux") {
|
|
186
|
+
return process.arch === "arm64" ? "bun-linux-arm64" : "bun-linux-x64";
|
|
187
|
+
}
|
|
188
|
+
return "bun-windows-x64";
|
|
189
|
+
}
|
|
190
|
+
function createRuntimeBinaryBuildKey(input) {
|
|
191
|
+
return JSON.stringify({
|
|
192
|
+
version: 1,
|
|
193
|
+
bunVersion: Bun.version,
|
|
194
|
+
platform: process.platform,
|
|
195
|
+
arch: process.arch,
|
|
196
|
+
entrypoint: input.entrypoint,
|
|
197
|
+
define: sortRecord(input.define),
|
|
198
|
+
external: input.external ? [...input.external].sort() : undefined,
|
|
199
|
+
env: sortRecord(input.env)
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
async function isRuntimeBinaryBuildFresh(input) {
|
|
203
|
+
if (!existsSync(input.outputPath) || !existsSync(input.manifestPath)) {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
let manifest = null;
|
|
207
|
+
try {
|
|
208
|
+
manifest = await Bun.file(input.manifestPath).json();
|
|
209
|
+
} catch {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
if (!manifest || manifest.version !== 1 || manifest.buildKey !== input.buildKey) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
for (const [filePath, expectedDigest] of Object.entries(manifest.inputs || {})) {
|
|
216
|
+
if (!existsSync(filePath)) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
if (await sha256File(filePath) !== expectedDigest) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
async function writeRuntimeBinaryCacheManifest(input) {
|
|
226
|
+
const inputs = {};
|
|
227
|
+
for (const inputPath of Object.keys(input.metafile?.inputs || {}).sort()) {
|
|
228
|
+
const normalized = normalizeBuildInputPath(input.cwd, inputPath);
|
|
229
|
+
if (!normalized || !existsSync(normalized)) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
inputs[normalized] = await sha256File(normalized);
|
|
233
|
+
}
|
|
234
|
+
const manifest = {
|
|
235
|
+
version: 1,
|
|
236
|
+
buildKey: input.buildKey,
|
|
237
|
+
inputs
|
|
238
|
+
};
|
|
239
|
+
await Bun.write(input.manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
240
|
+
`);
|
|
241
|
+
}
|
|
242
|
+
function normalizeBuildInputPath(cwd, inputPath) {
|
|
243
|
+
if (!inputPath) {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
if (inputPath.startsWith("file://")) {
|
|
247
|
+
return fileURLToPath(inputPath);
|
|
248
|
+
}
|
|
249
|
+
if (inputPath.startsWith("<")) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
return resolve2(cwd, inputPath);
|
|
253
|
+
}
|
|
254
|
+
async function sha256File(path) {
|
|
255
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
256
|
+
hasher.update(await Bun.file(path).arrayBuffer());
|
|
257
|
+
return hasher.digest("hex");
|
|
258
|
+
}
|
|
259
|
+
function sortRecord(value) {
|
|
260
|
+
if (!value) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)));
|
|
264
|
+
}
|
|
265
|
+
async function runSerializedRuntimeBinaryBuild(action) {
|
|
266
|
+
const previous = runtimeBinaryBuildQueue;
|
|
267
|
+
let release;
|
|
268
|
+
runtimeBinaryBuildQueue = new Promise((resolve3) => {
|
|
269
|
+
release = resolve3;
|
|
270
|
+
});
|
|
271
|
+
await previous;
|
|
272
|
+
try {
|
|
273
|
+
return await action();
|
|
274
|
+
} finally {
|
|
275
|
+
release();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
async function withTemporaryEnv(env, action) {
|
|
279
|
+
if (!env) {
|
|
280
|
+
return action();
|
|
281
|
+
}
|
|
282
|
+
const previousValues = new Map;
|
|
283
|
+
for (const [key, value] of Object.entries(env)) {
|
|
284
|
+
previousValues.set(key, process.env[key]);
|
|
285
|
+
if (value === undefined) {
|
|
286
|
+
delete process.env[key];
|
|
287
|
+
} else {
|
|
288
|
+
process.env[key] = value;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
try {
|
|
292
|
+
return await action();
|
|
293
|
+
} finally {
|
|
294
|
+
for (const [key, value] of previousValues.entries()) {
|
|
295
|
+
if (value === undefined) {
|
|
296
|
+
delete process.env[key];
|
|
297
|
+
} else {
|
|
298
|
+
process.env[key] = value;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
async function withTemporaryCwd(cwd, action) {
|
|
304
|
+
const previousCwd = process.cwd();
|
|
305
|
+
process.chdir(cwd);
|
|
306
|
+
try {
|
|
307
|
+
return await action();
|
|
308
|
+
} finally {
|
|
309
|
+
process.chdir(previousCwd);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// packages/provider-plugin/src/tooling/binary-build-worker.ts
|
|
314
|
+
var payloadPath = process.argv[2];
|
|
315
|
+
if (!payloadPath) {
|
|
316
|
+
console.error("usage: binary-build-worker <payload.json>");
|
|
317
|
+
process.exit(2);
|
|
318
|
+
}
|
|
319
|
+
var payload = await Bun.file(payloadPath).json();
|
|
320
|
+
await buildRuntimeBinary({
|
|
321
|
+
...payload,
|
|
322
|
+
outputPath: payload.outputPath
|
|
323
|
+
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// @bun
|
|
3
|
+
|
|
4
|
+
// packages/provider-plugin/src/tooling/browser-tool-entrypoint.ts
|
|
5
|
+
import { existsSync, rmSync } from "fs";
|
|
6
|
+
import { basename, dirname, resolve } from "path";
|
|
7
|
+
import { loadRuntimeContext } from "@rig/core/runtime-context";
|
|
8
|
+
function currentCommand() {
|
|
9
|
+
return basename(process.argv[1] || "");
|
|
10
|
+
}
|
|
11
|
+
function runtimeContextPath() {
|
|
12
|
+
const explicit = process.env.RIG_RUNTIME_CONTEXT_FILE?.trim();
|
|
13
|
+
if (explicit) {
|
|
14
|
+
return explicit;
|
|
15
|
+
}
|
|
16
|
+
return resolve(dirname(resolve(process.argv[1] || "")), "..", "runtime-context.json");
|
|
17
|
+
}
|
|
18
|
+
function loadBrowserContext() {
|
|
19
|
+
const contextPath = runtimeContextPath();
|
|
20
|
+
if (!existsSync(contextPath)) {
|
|
21
|
+
throw new Error(`Runtime context file not found for ${currentCommand()}: ${contextPath}`);
|
|
22
|
+
}
|
|
23
|
+
const runtimeContext = loadRuntimeContext(contextPath);
|
|
24
|
+
if (!runtimeContext.browser?.required) {
|
|
25
|
+
throw new Error(`No browser contract is configured for ${runtimeContext.taskId}.`);
|
|
26
|
+
}
|
|
27
|
+
if (!runtimeContext.hostProjectRoot) {
|
|
28
|
+
throw new Error(`Runtime browser command ${currentCommand()} requires hostProjectRoot in runtime context.`);
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
browser: runtimeContext.browser,
|
|
32
|
+
hostProjectRoot: runtimeContext.hostProjectRoot
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async function runConfiguredCommand(command, browser, hostProjectRoot) {
|
|
36
|
+
if (!command) {
|
|
37
|
+
throw new Error(`No backing command is configured for ${currentCommand()}.`);
|
|
38
|
+
}
|
|
39
|
+
const attachUrl = new URL(browser.effectiveAttachUrl);
|
|
40
|
+
const child = Bun.spawn({
|
|
41
|
+
cmd: ["/bin/bash", "-lc", command],
|
|
42
|
+
cwd: hostProjectRoot,
|
|
43
|
+
stdin: "inherit",
|
|
44
|
+
stdout: "inherit",
|
|
45
|
+
stderr: "inherit",
|
|
46
|
+
env: {
|
|
47
|
+
...process.env,
|
|
48
|
+
RIG_STATE_DIR: browser.stateDir,
|
|
49
|
+
T3CODE_STATE_DIR: browser.stateDir,
|
|
50
|
+
RIG_BROWSER_PROFILE: browser.effectiveProfile,
|
|
51
|
+
RIG_BROWSER_REMOTE_DEBUGGING_PORT: attachUrl.port,
|
|
52
|
+
RIG_BROWSER_ATTACH_URL: browser.effectiveAttachUrl
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return await child.exited;
|
|
56
|
+
}
|
|
57
|
+
function printAttachInfo(browser, hostProjectRoot) {
|
|
58
|
+
const payload = {
|
|
59
|
+
preset: browser.preset,
|
|
60
|
+
mode: browser.mode,
|
|
61
|
+
stateDir: browser.stateDir,
|
|
62
|
+
hostProjectRoot,
|
|
63
|
+
defaultProfile: browser.defaultProfile,
|
|
64
|
+
effectiveProfile: browser.effectiveProfile,
|
|
65
|
+
defaultAttachUrl: browser.defaultAttachUrl,
|
|
66
|
+
effectiveAttachUrl: browser.effectiveAttachUrl,
|
|
67
|
+
launchHelper: browser.launchHelper,
|
|
68
|
+
checkHelper: browser.checkHelper,
|
|
69
|
+
attachInfoHelper: browser.attachInfoHelper,
|
|
70
|
+
e2eHelper: browser.e2eHelper,
|
|
71
|
+
resetProfileHelper: browser.resetProfileHelper,
|
|
72
|
+
devCommand: browser.devCommand,
|
|
73
|
+
launchCommand: browser.launchCommand,
|
|
74
|
+
checkCommand: browser.checkCommand,
|
|
75
|
+
e2eCommand: browser.e2eCommand
|
|
76
|
+
};
|
|
77
|
+
if (process.argv.includes("--json")) {
|
|
78
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
console.log("Rig Browser");
|
|
82
|
+
console.log(` Preset: ${browser.preset}`);
|
|
83
|
+
console.log(` Mode: ${browser.mode}`);
|
|
84
|
+
console.log(` State dir: ${browser.stateDir}`);
|
|
85
|
+
console.log(` Default profile: ${browser.defaultProfile}`);
|
|
86
|
+
console.log(` Effective profile: ${browser.effectiveProfile}`);
|
|
87
|
+
console.log(` Default attach URL: ${browser.defaultAttachUrl}`);
|
|
88
|
+
console.log(` Effective attach URL: ${browser.effectiveAttachUrl}`);
|
|
89
|
+
console.log(` Launch helper: ${browser.launchHelper}${browser.devCommand ? " [--dev]" : ""}`);
|
|
90
|
+
console.log(` Check helper: ${browser.checkHelper}`);
|
|
91
|
+
console.log(` E2E helper: ${browser.e2eHelper}`);
|
|
92
|
+
console.log(` Reset helper: ${browser.resetProfileHelper}`);
|
|
93
|
+
}
|
|
94
|
+
function resetProfile(browser) {
|
|
95
|
+
const profileRoot = resolve(browser.stateDir, "browser", "profiles", browser.effectiveProfile);
|
|
96
|
+
rmSync(profileRoot, { recursive: true, force: true });
|
|
97
|
+
console.log(`Removed Rig Browser profile: ${profileRoot}`);
|
|
98
|
+
}
|
|
99
|
+
async function main() {
|
|
100
|
+
const { browser, hostProjectRoot } = loadBrowserContext();
|
|
101
|
+
const command = currentCommand();
|
|
102
|
+
if (command === browser.attachInfoHelper) {
|
|
103
|
+
printAttachInfo(browser, hostProjectRoot);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (command === browser.resetProfileHelper) {
|
|
107
|
+
resetProfile(browser);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (command === browser.launchHelper) {
|
|
111
|
+
const launchCommand = process.argv.includes("--dev") ? browser.devCommand : browser.launchCommand;
|
|
112
|
+
process.exit(await runConfiguredCommand(launchCommand, browser, hostProjectRoot));
|
|
113
|
+
}
|
|
114
|
+
if (command === browser.checkHelper) {
|
|
115
|
+
process.exit(await runConfiguredCommand(browser.checkCommand, browser, hostProjectRoot));
|
|
116
|
+
}
|
|
117
|
+
if (command === browser.e2eHelper) {
|
|
118
|
+
process.exit(await runConfiguredCommand(browser.e2eCommand ?? browser.checkCommand, browser, hostProjectRoot));
|
|
119
|
+
}
|
|
120
|
+
throw new Error(`Unknown Rig Browser helper: ${command}`);
|
|
121
|
+
}
|
|
122
|
+
main().catch((error) => {
|
|
123
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
124
|
+
process.exit(1);
|
|
125
|
+
});
|