@h-rig/runtime 0.0.6-alpha.27 → 0.0.6-alpha.29

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.
Files changed (39) hide show
  1. package/dist/bin/rig-agent-dispatch.js +552 -483
  2. package/dist/bin/rig-agent.js +418 -364
  3. package/dist/src/control-plane/agent-wrapper.js +557 -488
  4. package/dist/src/control-plane/harness-main.js +559 -1418
  5. package/dist/src/control-plane/hooks/completion-verification.js +451 -808
  6. package/dist/src/control-plane/hooks/inject-context.js +191 -137
  7. package/dist/src/control-plane/hooks/submodule-branch.js +596 -542
  8. package/dist/src/control-plane/hooks/task-runtime-start.js +596 -542
  9. package/dist/src/control-plane/materialize-task-config.js +64 -8
  10. package/dist/src/control-plane/native/git-ops.js +3 -0
  11. package/dist/src/control-plane/native/harness-cli.js +544 -496
  12. package/dist/src/control-plane/native/repo-ops.js +3 -0
  13. package/dist/src/control-plane/native/run-ops.js +3 -0
  14. package/dist/src/control-plane/native/task-ops.js +418 -370
  15. package/dist/src/control-plane/native/validator.js +161 -107
  16. package/dist/src/control-plane/native/verifier.js +217 -169
  17. package/dist/src/control-plane/pi-sessiond/launcher.js +12 -2
  18. package/dist/src/control-plane/plugin-host-context.js +54 -0
  19. package/dist/src/control-plane/runtime/image/fingerprint-sidecar.js +3 -0
  20. package/dist/src/control-plane/runtime/image/index.js +3 -0
  21. package/dist/src/control-plane/runtime/image-fingerprint-sidecar.js +3 -0
  22. package/dist/src/control-plane/runtime/image.js +3 -0
  23. package/dist/src/control-plane/runtime/index.js +487 -718
  24. package/dist/src/control-plane/runtime/isolation/index.js +511 -457
  25. package/dist/src/control-plane/runtime/isolation.js +511 -457
  26. package/dist/src/control-plane/runtime/plugin-mode.js +3 -27
  27. package/dist/src/control-plane/runtime/queue.js +428 -381
  28. package/dist/src/control-plane/runtime/snapshot/task-run.js +3 -0
  29. package/dist/src/control-plane/runtime/task-run-snapshot.js +3 -0
  30. package/dist/src/control-plane/skill-materializer.js +46 -0
  31. package/dist/src/control-plane/tasks/source-lifecycle.js +84 -30
  32. package/dist/src/index.js +0 -278
  33. package/native/darwin-arm64/rig-shell +0 -0
  34. package/native/darwin-arm64/rig-shell.build-manifest.json +1 -1
  35. package/native/darwin-arm64/rig-tools +0 -0
  36. package/native/darwin-arm64/rig-tools.build-manifest.json +1 -1
  37. package/package.json +8 -7
  38. package/dist/src/control-plane/runtime/plugins.js +0 -1131
  39. package/dist/src/plugins.js +0 -329
@@ -1,329 +0,0 @@
1
- // @bun
2
- // packages/runtime/src/plugins.ts
3
- import { existsSync, readdirSync } from "fs";
4
- import { basename, resolve } from "path";
5
-
6
- // packages/runtime/src/binary-run.ts
7
- import { spawn as nodeSpawn } from "child_process";
8
- var runtimeBinaryBuildQueue = Promise.resolve();
9
- async function launchRuntimeBinary(request) {
10
- const options = {
11
- cwd: request.cwd,
12
- env: request.env ? { ...process.env, ...request.env } : process.env
13
- };
14
- if (request.timeoutMs !== undefined) {
15
- options.timeoutMs = request.timeoutMs;
16
- }
17
- return spawnProcess(request.binaryPath, request.args, options);
18
- }
19
- async function spawnProcess(command, args, options) {
20
- const child = nodeSpawn(command, args, {
21
- cwd: options.cwd,
22
- env: options.env,
23
- stdio: ["ignore", "pipe", "pipe"]
24
- });
25
- let stdout = "";
26
- let stderr = "";
27
- child.stdout?.setEncoding("utf8");
28
- child.stderr?.setEncoding("utf8");
29
- child.stdout?.on("data", (chunk) => {
30
- stdout += chunk;
31
- });
32
- child.stderr?.on("data", (chunk) => {
33
- stderr += chunk;
34
- });
35
- let timedOut = false;
36
- let timer;
37
- const exitCode = await new Promise((resolveExit, rejectExit) => {
38
- if (options.timeoutMs && options.timeoutMs > 0) {
39
- timer = setTimeout(() => {
40
- timedOut = true;
41
- child.kill();
42
- }, options.timeoutMs);
43
- }
44
- child.once("error", rejectExit);
45
- child.once("close", (code) => resolveExit(code ?? (timedOut ? 1 : 0)));
46
- }).finally(() => {
47
- if (timer) {
48
- clearTimeout(timer);
49
- }
50
- });
51
- return { exitCode, stdout, stderr, timedOut };
52
- }
53
-
54
- // packages/runtime/src/control-plane/runtime/plugin-mode.ts
55
- var LEGACY_PLUGIN_SCAN_ENV = "RIG_LEGACY_PLUGIN_SCAN";
56
- function isLegacyPluginScanEnabled(env = process.env) {
57
- const value = env[LEGACY_PLUGIN_SCAN_ENV]?.trim().toLowerCase();
58
- return value === "1" || value === "true" || value === "yes" || value === "on";
59
- }
60
-
61
- // packages/runtime/src/plugins.ts
62
- var runtimeHookPhases = ["beforeCommand", "afterCommand", "onEvent"];
63
- var PLUGIN_SOURCE_PATTERN = /\.plugin\.(ts|js|mjs|cjs)$/;
64
- function inferRuntimePluginName(fileName) {
65
- return fileName.replace(PLUGIN_SOURCE_PATTERN, "");
66
- }
67
- function describeRuntimePluginFiles(filePaths) {
68
- return filePaths.filter((filePath) => PLUGIN_SOURCE_PATTERN.test(filePath)).map((filePath) => {
69
- const fileName = filePath.split(/[\\/]/).at(-1) ?? filePath;
70
- const name = inferRuntimePluginName(fileName);
71
- return { name, sourcePath: filePath, binaryName: name };
72
- });
73
- }
74
-
75
- class PluginManager {
76
- eventBus;
77
- context;
78
- pluginDir;
79
- pluginFiles;
80
- pluginNames;
81
- localBinDir;
82
- imageBinDir;
83
- pluginsRequireBinaries;
84
- ensureImageBinDir;
85
- plugins = null;
86
- loadPromise = null;
87
- constructor(options) {
88
- this.eventBus = options.eventBus;
89
- this.context = options.context;
90
- this.pluginDir = options.pluginDir;
91
- this.pluginFiles = options.pluginFiles;
92
- this.pluginNames = options.pluginNames;
93
- this.localBinDir = options.localBinDir;
94
- this.imageBinDir = options.imageBinDir;
95
- this.pluginsRequireBinaries = options.pluginsRequireBinaries;
96
- this.ensureImageBinDir = options.ensureImageBinDir;
97
- }
98
- static async load(options) {
99
- const pluginDir = options.pluginDir ?? resolve(options.projectRoot, "rig", "plugins");
100
- const localBinDir = options.localBinDir ?? resolve(options.projectRoot, "rig", "plugins");
101
- const imageBinDir = options.imageBinDir ?? (options.runtimeContext ? resolve(options.runtimeContext.binDir, "plugins") : "");
102
- const legacyPluginScan = options.legacyPluginScan ?? isLegacyPluginScanEnabled(options.env);
103
- const pluginFiles = legacyPluginScan ? safeReadDir(pluginDir).filter((entry) => PLUGIN_SOURCE_PATTERN.test(entry)) : [];
104
- const pluginNames = pluginFiles.map((file) => inferRuntimePluginName(basename(file)));
105
- const context = {
106
- projectRoot: options.projectRoot,
107
- runId: options.runId,
108
- eventBus: options.eventBus
109
- };
110
- return new PluginManager({
111
- eventBus: options.eventBus,
112
- context,
113
- pluginDir,
114
- pluginFiles,
115
- pluginNames,
116
- localBinDir,
117
- imageBinDir,
118
- pluginsRequireBinaries: options.pluginsRequireBinaries ?? true,
119
- ensureImageBinDir: options.ensureImageBinDir
120
- });
121
- }
122
- list() {
123
- if (this.plugins) {
124
- return this.plugins.map((plugin) => ({
125
- name: plugin.name,
126
- validators: plugin.validators?.map((validator) => validator.id) ?? []
127
- }));
128
- }
129
- return this.pluginNames.map((name) => ({ name, validators: [] }));
130
- }
131
- async beforeCommand(ctx) {
132
- const plugins = await this.ensureLoaded();
133
- for (const plugin of plugins) {
134
- if (!plugin.beforeCommand)
135
- continue;
136
- await this.safeInvoke(plugin.name, "beforeCommand", () => plugin.beforeCommand?.(ctx, this.context));
137
- }
138
- }
139
- async afterCommand(result) {
140
- const plugins = await this.ensureLoaded();
141
- for (const plugin of plugins) {
142
- if (!plugin.afterCommand)
143
- continue;
144
- await this.safeInvoke(plugin.name, "afterCommand", () => plugin.afterCommand?.(result, this.context));
145
- }
146
- }
147
- async onEvent(event) {
148
- const plugins = this.plugins;
149
- if (!plugins)
150
- return;
151
- for (const plugin of plugins) {
152
- if (!plugin.onEvent)
153
- continue;
154
- await this.safeInvoke(plugin.name, "onEvent", () => plugin.onEvent?.(event, this.context));
155
- }
156
- }
157
- async runValidators(taskId) {
158
- const plugins = await this.ensureLoaded();
159
- const results = [];
160
- for (const plugin of plugins) {
161
- for (const validator of plugin.validators ?? []) {
162
- await this.eventBus.emit("validator.started", {
163
- plugin: plugin.name,
164
- validator: validator.id,
165
- taskId
166
- });
167
- try {
168
- const result = await validator.run({ taskId, projectRoot: this.context.projectRoot }, this.context);
169
- results.push(result);
170
- await this.eventBus.emit("validator.finished", {
171
- plugin: plugin.name,
172
- validator: validator.id,
173
- taskId,
174
- passed: result.passed,
175
- summary: result.summary
176
- });
177
- } catch (error) {
178
- const failed = {
179
- id: validator.id,
180
- passed: false,
181
- summary: `${plugin.name}/${validator.id} failed unexpectedly`,
182
- details: `${error}`
183
- };
184
- results.push(failed);
185
- await this.eventBus.emit("validator.finished", {
186
- plugin: plugin.name,
187
- validator: validator.id,
188
- taskId,
189
- passed: false,
190
- summary: failed.summary,
191
- details: failed.details
192
- });
193
- }
194
- }
195
- }
196
- return results;
197
- }
198
- async ensureLoaded() {
199
- if (this.plugins)
200
- return this.plugins;
201
- if (this.loadPromise)
202
- return this.loadPromise;
203
- this.loadPromise = this.loadCompiledPlugins();
204
- try {
205
- this.plugins = await this.loadPromise;
206
- return this.plugins;
207
- } finally {
208
- this.loadPromise = null;
209
- }
210
- }
211
- resolveBinPath(binName) {
212
- const candidates = [this.imageBinDir, this.localBinDir].filter(Boolean).map((dir) => resolve(dir, binName));
213
- return candidates.find((candidate) => existsSync(candidate));
214
- }
215
- async loadCompiledPlugins() {
216
- const plugins = [];
217
- for (const file of this.pluginFiles) {
218
- const binName = inferRuntimePluginName(basename(file));
219
- let binPath = this.resolveBinPath(binName);
220
- if (!binPath && !this.imageBinDir && this.pluginsRequireBinaries && this.ensureImageBinDir) {
221
- try {
222
- this.imageBinDir = await this.ensureImageBinDir(this.context.projectRoot);
223
- binPath = this.resolveBinPath(binName);
224
- } catch {}
225
- }
226
- if (!binPath) {
227
- const triedPaths = [this.imageBinDir, this.localBinDir].filter(Boolean).map((dir) => resolve(dir, binName));
228
- const missingError = `Compiled plugin binary not found for '${binName}'. Tried: ${triedPaths.join(", ")}`;
229
- await this.eventBus.emit("plugin.error", {
230
- file: resolve(this.pluginDir, file),
231
- phase: "load",
232
- error: missingError
233
- });
234
- if (this.pluginsRequireBinaries) {
235
- throw new Error(missingError);
236
- }
237
- plugins.push({ name: binName, validators: [] });
238
- await this.eventBus.emit("plugin.loaded", {
239
- plugin: binName,
240
- file: resolve(this.pluginDir, file),
241
- source: "metadata-only"
242
- });
243
- continue;
244
- }
245
- const wrapper = createBinaryPluginWrapper(binName, binPath, this.context.projectRoot);
246
- plugins.push(wrapper);
247
- await this.eventBus.emit("plugin.loaded", {
248
- plugin: wrapper.name,
249
- file: binPath,
250
- source: "compiled-binary"
251
- });
252
- }
253
- return plugins;
254
- }
255
- async safeInvoke(pluginName, hook, call) {
256
- try {
257
- await call();
258
- } catch (error) {
259
- await this.eventBus.emit("plugin.error", {
260
- plugin: pluginName,
261
- phase: hook,
262
- error: `${error}`
263
- });
264
- }
265
- }
266
- }
267
- function createBinaryPluginWrapper(name, binPath, projectRoot) {
268
- return {
269
- name,
270
- validators: [
271
- {
272
- id: `${name}:compiled`,
273
- async run(ctx) {
274
- const { exitCode, stdout, stderr } = await launchRuntimeBinary({
275
- binaryPath: binPath,
276
- args: ["--validate", ctx.taskId, ctx.projectRoot],
277
- cwd: projectRoot
278
- });
279
- if (exitCode !== 0) {
280
- return {
281
- id: `${name}:compiled`,
282
- passed: false,
283
- summary: `Plugin binary ${name} exited with code ${exitCode}`,
284
- details: stderr || stdout
285
- };
286
- }
287
- try {
288
- const results = JSON.parse(stdout.trim());
289
- const failed = results.filter((result) => !result.passed);
290
- if (failed.length > 0) {
291
- return {
292
- id: `${name}:compiled`,
293
- passed: false,
294
- summary: `${failed.length} of ${results.length} validator(s) failed`,
295
- details: failed.map((result) => `${result.id}: ${result.summary}`).join(`
296
- `)
297
- };
298
- }
299
- return {
300
- id: `${name}:compiled`,
301
- passed: true,
302
- summary: `All ${results.length} validator(s) passed`
303
- };
304
- } catch {
305
- return {
306
- id: `${name}:compiled`,
307
- passed: false,
308
- summary: `Failed to parse output from compiled plugin ${name}`,
309
- details: stdout.slice(0, 500)
310
- };
311
- }
312
- }
313
- }
314
- ]
315
- };
316
- }
317
- function safeReadDir(path) {
318
- try {
319
- return readdirSync(path, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
320
- } catch {
321
- return [];
322
- }
323
- }
324
- export {
325
- runtimeHookPhases,
326
- inferRuntimePluginName,
327
- describeRuntimePluginFiles,
328
- PluginManager
329
- };