@h-rig/runtime 0.0.6-alpha.28 → 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.
- package/dist/bin/rig-agent-dispatch.js +552 -483
- package/dist/bin/rig-agent.js +418 -364
- package/dist/src/control-plane/agent-wrapper.js +557 -488
- package/dist/src/control-plane/harness-main.js +559 -1418
- package/dist/src/control-plane/hooks/completion-verification.js +451 -808
- package/dist/src/control-plane/hooks/inject-context.js +191 -137
- package/dist/src/control-plane/hooks/submodule-branch.js +596 -542
- package/dist/src/control-plane/hooks/task-runtime-start.js +596 -542
- package/dist/src/control-plane/materialize-task-config.js +64 -8
- package/dist/src/control-plane/native/git-ops.js +3 -0
- package/dist/src/control-plane/native/harness-cli.js +544 -496
- package/dist/src/control-plane/native/repo-ops.js +3 -0
- package/dist/src/control-plane/native/run-ops.js +3 -0
- package/dist/src/control-plane/native/task-ops.js +418 -370
- package/dist/src/control-plane/native/validator.js +161 -107
- package/dist/src/control-plane/native/verifier.js +217 -169
- package/dist/src/control-plane/pi-sessiond/launcher.js +12 -2
- package/dist/src/control-plane/plugin-host-context.js +54 -0
- package/dist/src/control-plane/runtime/image/fingerprint-sidecar.js +3 -0
- package/dist/src/control-plane/runtime/image/index.js +3 -0
- package/dist/src/control-plane/runtime/image-fingerprint-sidecar.js +3 -0
- package/dist/src/control-plane/runtime/image.js +3 -0
- package/dist/src/control-plane/runtime/index.js +487 -718
- package/dist/src/control-plane/runtime/isolation/index.js +511 -457
- package/dist/src/control-plane/runtime/isolation.js +511 -457
- package/dist/src/control-plane/runtime/plugin-mode.js +3 -27
- package/dist/src/control-plane/runtime/queue.js +428 -381
- package/dist/src/control-plane/runtime/snapshot/task-run.js +3 -0
- package/dist/src/control-plane/runtime/task-run-snapshot.js +3 -0
- package/dist/src/control-plane/skill-materializer.js +46 -0
- package/dist/src/control-plane/tasks/source-lifecycle.js +84 -30
- package/dist/src/index.js +0 -278
- package/native/darwin-arm64/rig-shell +0 -0
- package/native/darwin-arm64/rig-shell.build-manifest.json +1 -1
- package/native/darwin-arm64/rig-tools +0 -0
- package/native/darwin-arm64/rig-tools.build-manifest.json +1 -1
- package/package.json +8 -7
- package/dist/src/control-plane/runtime/plugins.js +0 -1131
- package/dist/src/plugins.js +0 -329
|
@@ -598,6 +598,9 @@ import { loadConfig } from "@rig/core/load-config";
|
|
|
598
598
|
// packages/runtime/src/control-plane/repos/registry.ts
|
|
599
599
|
var MANAGED_REPOS = new Map;
|
|
600
600
|
|
|
601
|
+
// packages/runtime/src/control-plane/skill-materializer.ts
|
|
602
|
+
import { loadSkill } from "@rig/skill-loader";
|
|
603
|
+
|
|
601
604
|
// packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
|
|
602
605
|
var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
|
|
603
606
|
|
|
@@ -598,6 +598,9 @@ import { loadConfig } from "@rig/core/load-config";
|
|
|
598
598
|
// packages/runtime/src/control-plane/repos/registry.ts
|
|
599
599
|
var MANAGED_REPOS = new Map;
|
|
600
600
|
|
|
601
|
+
// packages/runtime/src/control-plane/skill-materializer.ts
|
|
602
|
+
import { loadSkill } from "@rig/skill-loader";
|
|
603
|
+
|
|
601
604
|
// packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
|
|
602
605
|
var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
|
|
603
606
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/runtime/src/control-plane/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
|
+
};
|
|
@@ -283,6 +283,49 @@ function safeReadJson(path) {
|
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
+
// packages/runtime/src/control-plane/skill-materializer.ts
|
|
287
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, readdirSync, rmSync, writeFileSync as writeFileSync2 } from "fs";
|
|
288
|
+
import { resolve as resolve2 } from "path";
|
|
289
|
+
import { loadSkill } from "@rig/skill-loader";
|
|
290
|
+
var MARKER_FILENAME = ".rig-plugin";
|
|
291
|
+
function skillDirName(id) {
|
|
292
|
+
return id.replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
293
|
+
}
|
|
294
|
+
async function materializeSkills(projectRoot, entries) {
|
|
295
|
+
const skillsRoot = resolve2(projectRoot, ".pi", "skills");
|
|
296
|
+
if (existsSync3(skillsRoot)) {
|
|
297
|
+
for (const name of readdirSync(skillsRoot)) {
|
|
298
|
+
const dir = resolve2(skillsRoot, name);
|
|
299
|
+
if (existsSync3(resolve2(dir, MARKER_FILENAME))) {
|
|
300
|
+
rmSync(dir, { recursive: true, force: true });
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const written = [];
|
|
305
|
+
for (const { pluginName, skill } of entries) {
|
|
306
|
+
const sourcePath = resolve2(projectRoot, skill.path);
|
|
307
|
+
if (!existsSync3(sourcePath)) {
|
|
308
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${sourcePath} does not exist`);
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
let body;
|
|
312
|
+
try {
|
|
313
|
+
await loadSkill(sourcePath);
|
|
314
|
+
body = readFileSync2(sourcePath, "utf-8");
|
|
315
|
+
} catch (err) {
|
|
316
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${err instanceof Error ? err.message : err}`);
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
const dir = resolve2(skillsRoot, skillDirName(skill.id));
|
|
320
|
+
mkdirSync2(dir, { recursive: true });
|
|
321
|
+
writeFileSync2(resolve2(dir, "SKILL.md"), body, "utf-8");
|
|
322
|
+
writeFileSync2(resolve2(dir, MARKER_FILENAME), `${JSON.stringify({ plugin: pluginName, skillId: skill.id }, null, 2)}
|
|
323
|
+
`, "utf-8");
|
|
324
|
+
written.push({ id: skill.id, pluginName, directory: dir });
|
|
325
|
+
}
|
|
326
|
+
return written;
|
|
327
|
+
}
|
|
328
|
+
|
|
286
329
|
// packages/runtime/src/control-plane/plugin-host-context.ts
|
|
287
330
|
async function buildPluginHostContext(projectRoot) {
|
|
288
331
|
let config;
|
|
@@ -319,6 +362,17 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
319
362
|
} catch (err) {
|
|
320
363
|
console.warn(`[plugin-host] hook materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
321
364
|
}
|
|
365
|
+
try {
|
|
366
|
+
const skillEntries = config.plugins.flatMap((plugin) => (plugin.contributes?.skills ?? []).map((skill) => ({
|
|
367
|
+
pluginName: plugin.name,
|
|
368
|
+
skill
|
|
369
|
+
})));
|
|
370
|
+
if (skillEntries.length > 0) {
|
|
371
|
+
await materializeSkills(projectRoot, skillEntries);
|
|
372
|
+
}
|
|
373
|
+
} catch (err) {
|
|
374
|
+
console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
375
|
+
}
|
|
322
376
|
return {
|
|
323
377
|
config,
|
|
324
378
|
pluginHost,
|
|
@@ -332,12 +386,12 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
332
386
|
|
|
333
387
|
// packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
|
|
334
388
|
import { spawnSync } from "child_process";
|
|
335
|
-
import { existsSync as
|
|
336
|
-
import { basename, join as join2, resolve as
|
|
389
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync as readdirSync2, statSync, writeFileSync as writeFileSync3 } from "fs";
|
|
390
|
+
import { basename, join as join2, resolve as resolve4 } from "path";
|
|
337
391
|
|
|
338
392
|
// packages/runtime/src/control-plane/tasks/legacy-task-config-source.ts
|
|
339
|
-
import { existsSync as
|
|
340
|
-
import { resolve as
|
|
393
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
394
|
+
import { resolve as resolve3 } from "path";
|
|
341
395
|
|
|
342
396
|
// packages/runtime/src/control-plane/tasks/task-record-reader.ts
|
|
343
397
|
async function findTaskById(reader, id) {
|
|
@@ -360,7 +414,7 @@ class LegacyTaskConfigReadError extends Error {
|
|
|
360
414
|
}
|
|
361
415
|
}
|
|
362
416
|
function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
363
|
-
const configPath = options.configPath ??
|
|
417
|
+
const configPath = options.configPath ?? resolve3(projectRoot, ".rig", "task-config.json");
|
|
364
418
|
const reader = {
|
|
365
419
|
async listTasks() {
|
|
366
420
|
return readLegacyTaskRecords(projectRoot, configPath);
|
|
@@ -371,8 +425,8 @@ function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
|
371
425
|
};
|
|
372
426
|
return reader;
|
|
373
427
|
}
|
|
374
|
-
function readLegacyTaskRecords(projectRoot, configPath =
|
|
375
|
-
if (!
|
|
428
|
+
function readLegacyTaskRecords(projectRoot, configPath = resolve3(projectRoot, ".rig", "task-config.json")) {
|
|
429
|
+
if (!existsSync4(configPath)) {
|
|
376
430
|
return [];
|
|
377
431
|
}
|
|
378
432
|
const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
|
|
@@ -380,7 +434,7 @@ function readLegacyTaskRecords(projectRoot, configPath = resolve2(projectRoot, "
|
|
|
380
434
|
}
|
|
381
435
|
function readLegacyTaskConfigJson(projectRoot, configPath) {
|
|
382
436
|
try {
|
|
383
|
-
const parsed = JSON.parse(
|
|
437
|
+
const parsed = JSON.parse(readFileSync3(configPath, "utf8"));
|
|
384
438
|
if (isPlainRecord(parsed)) {
|
|
385
439
|
return parsed;
|
|
386
440
|
}
|
|
@@ -464,7 +518,7 @@ function isPlainRecord(candidate) {
|
|
|
464
518
|
var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
|
|
465
519
|
var FILE_TASK_PATTERN = /\.(task\.)?json$/;
|
|
466
520
|
function createSourceAwareTaskConfigRecordReader(projectRoot, options = {}) {
|
|
467
|
-
const configPath = options.configPath ??
|
|
521
|
+
const configPath = options.configPath ?? resolve4(projectRoot, ".rig", "task-config.json");
|
|
468
522
|
const legacy = createLegacyTaskConfigRecordReader(projectRoot, { configPath });
|
|
469
523
|
const spawnFn = options.spawn ?? spawnSync;
|
|
470
524
|
const ghBinary = options.ghBinary ?? "gh";
|
|
@@ -530,7 +584,7 @@ async function readSourceAwareTaskStatus(projectRoot, taskId, options = {}) {
|
|
|
530
584
|
}
|
|
531
585
|
}
|
|
532
586
|
function updateSourceAwareTaskConfigTask(projectRoot, taskId, update, options = {}) {
|
|
533
|
-
const configPath = options.configPath ??
|
|
587
|
+
const configPath = options.configPath ?? resolve4(projectRoot, ".rig", "task-config.json");
|
|
534
588
|
const rawEntry = readRawTaskEntry(configPath, taskId);
|
|
535
589
|
if (!rawEntry) {
|
|
536
590
|
const configuredFilesPath = readConfiguredFilesTaskSourcePath(projectRoot);
|
|
@@ -583,10 +637,10 @@ function readMaterializedTaskMetadata(entry) {
|
|
|
583
637
|
return metadata;
|
|
584
638
|
}
|
|
585
639
|
function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
586
|
-
const jsonPath =
|
|
587
|
-
if (
|
|
640
|
+
const jsonPath = resolve4(projectRoot, "rig.config.json");
|
|
641
|
+
if (existsSync5(jsonPath)) {
|
|
588
642
|
try {
|
|
589
|
-
const parsed = JSON.parse(
|
|
643
|
+
const parsed = JSON.parse(readFileSync4(jsonPath, "utf8"));
|
|
590
644
|
if (isPlainRecord2(parsed) && isPlainRecord2(parsed.taskSource)) {
|
|
591
645
|
const source = parsed.taskSource;
|
|
592
646
|
return source.kind === "files" && typeof source.path === "string" ? source.path : null;
|
|
@@ -595,12 +649,12 @@ function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
|
595
649
|
return null;
|
|
596
650
|
}
|
|
597
651
|
}
|
|
598
|
-
const tsPath =
|
|
599
|
-
if (!
|
|
652
|
+
const tsPath = resolve4(projectRoot, "rig.config.ts");
|
|
653
|
+
if (!existsSync5(tsPath)) {
|
|
600
654
|
return null;
|
|
601
655
|
}
|
|
602
656
|
try {
|
|
603
|
-
const source =
|
|
657
|
+
const source = readFileSync4(tsPath, "utf8");
|
|
604
658
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
605
659
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
606
660
|
if (kind !== "files") {
|
|
@@ -620,10 +674,10 @@ function readRawTaskEntry(configPath, taskId) {
|
|
|
620
674
|
return isPlainRecord2(entry) ? entry : null;
|
|
621
675
|
}
|
|
622
676
|
function readRawTaskConfig(configPath) {
|
|
623
|
-
if (!
|
|
677
|
+
if (!existsSync5(configPath)) {
|
|
624
678
|
return null;
|
|
625
679
|
}
|
|
626
|
-
const parsed = JSON.parse(
|
|
680
|
+
const parsed = JSON.parse(readFileSync4(configPath, "utf8"));
|
|
627
681
|
return isPlainRecord2(parsed) ? parsed : null;
|
|
628
682
|
}
|
|
629
683
|
function stripLegacyTaskConfigMetadata2(raw) {
|
|
@@ -640,16 +694,16 @@ function writeLegacyTaskStatus(configPath, taskId, status) {
|
|
|
640
694
|
return;
|
|
641
695
|
}
|
|
642
696
|
entry.status = status;
|
|
643
|
-
|
|
697
|
+
writeFileSync3(configPath, `${JSON.stringify(rawConfig, null, 2)}
|
|
644
698
|
`, "utf8");
|
|
645
699
|
}
|
|
646
700
|
function updateFileBackedTask(projectRoot, sourcePath, taskId, update) {
|
|
647
|
-
const directory =
|
|
701
|
+
const directory = resolve4(projectRoot, sourcePath);
|
|
648
702
|
const file = findFileBackedTaskFile(directory, taskId);
|
|
649
703
|
if (!file) {
|
|
650
704
|
return false;
|
|
651
705
|
}
|
|
652
|
-
const raw = JSON.parse(
|
|
706
|
+
const raw = JSON.parse(readFileSync4(file, "utf8"));
|
|
653
707
|
if (!isPlainRecord2(raw)) {
|
|
654
708
|
return false;
|
|
655
709
|
}
|
|
@@ -666,17 +720,17 @@ function updateFileBackedTask(projectRoot, sourcePath, taskId, update) {
|
|
|
666
720
|
{ body: update.comment, createdAt: new Date().toISOString(), source: "rig" }
|
|
667
721
|
];
|
|
668
722
|
}
|
|
669
|
-
|
|
723
|
+
writeFileSync3(file, `${JSON.stringify(raw, null, 2)}
|
|
670
724
|
`, "utf8");
|
|
671
725
|
return true;
|
|
672
726
|
}
|
|
673
727
|
function listFileBackedTasks(projectRoot, sourcePath) {
|
|
674
|
-
const directory =
|
|
675
|
-
if (!
|
|
728
|
+
const directory = resolve4(projectRoot, sourcePath);
|
|
729
|
+
if (!existsSync5(directory)) {
|
|
676
730
|
return [];
|
|
677
731
|
}
|
|
678
732
|
const tasks = [];
|
|
679
|
-
for (const name of
|
|
733
|
+
for (const name of readdirSync2(directory)) {
|
|
680
734
|
if (!FILE_TASK_PATTERN.test(name))
|
|
681
735
|
continue;
|
|
682
736
|
const inferredId = basename(name).replace(FILE_TASK_PATTERN, "");
|
|
@@ -687,11 +741,11 @@ function listFileBackedTasks(projectRoot, sourcePath) {
|
|
|
687
741
|
return tasks;
|
|
688
742
|
}
|
|
689
743
|
function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
690
|
-
const file = findFileBackedTaskFile(
|
|
744
|
+
const file = findFileBackedTaskFile(resolve4(projectRoot, sourcePath), taskId);
|
|
691
745
|
if (!file) {
|
|
692
746
|
return null;
|
|
693
747
|
}
|
|
694
|
-
const raw = JSON.parse(
|
|
748
|
+
const raw = JSON.parse(readFileSync4(file, "utf8"));
|
|
695
749
|
if (!isPlainRecord2(raw)) {
|
|
696
750
|
return null;
|
|
697
751
|
}
|
|
@@ -704,17 +758,17 @@ function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
|
704
758
|
};
|
|
705
759
|
}
|
|
706
760
|
function findFileBackedTaskFile(directory, taskId) {
|
|
707
|
-
if (!
|
|
761
|
+
if (!existsSync5(directory)) {
|
|
708
762
|
return null;
|
|
709
763
|
}
|
|
710
|
-
for (const name of
|
|
764
|
+
for (const name of readdirSync2(directory)) {
|
|
711
765
|
if (!FILE_TASK_PATTERN.test(name))
|
|
712
766
|
continue;
|
|
713
767
|
const file = join2(directory, name);
|
|
714
768
|
try {
|
|
715
769
|
if (!statSync(file).isFile())
|
|
716
770
|
continue;
|
|
717
|
-
const raw = JSON.parse(
|
|
771
|
+
const raw = JSON.parse(readFileSync4(file, "utf8"));
|
|
718
772
|
const inferredId = basename(file).replace(FILE_TASK_PATTERN, "");
|
|
719
773
|
const id = isPlainRecord2(raw) && typeof raw.id === "string" ? raw.id : inferredId;
|
|
720
774
|
if (id === taskId) {
|
package/dist/src/index.js
CHANGED
|
@@ -1069,280 +1069,6 @@ async function spawnProcess(command, args, options) {
|
|
|
1069
1069
|
});
|
|
1070
1070
|
return { exitCode, stdout, stderr, timedOut };
|
|
1071
1071
|
}
|
|
1072
|
-
// packages/runtime/src/plugins.ts
|
|
1073
|
-
import { existsSync as existsSync6, readdirSync } from "fs";
|
|
1074
|
-
import { basename as basename3, resolve as resolve7 } from "path";
|
|
1075
|
-
|
|
1076
|
-
// packages/runtime/src/control-plane/runtime/plugin-mode.ts
|
|
1077
|
-
var LEGACY_PLUGIN_SCAN_ENV = "RIG_LEGACY_PLUGIN_SCAN";
|
|
1078
|
-
function isLegacyPluginScanEnabled(env = process.env) {
|
|
1079
|
-
const value = env[LEGACY_PLUGIN_SCAN_ENV]?.trim().toLowerCase();
|
|
1080
|
-
return value === "1" || value === "true" || value === "yes" || value === "on";
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
// packages/runtime/src/plugins.ts
|
|
1084
|
-
var runtimeHookPhases = ["beforeCommand", "afterCommand", "onEvent"];
|
|
1085
|
-
var PLUGIN_SOURCE_PATTERN = /\.plugin\.(ts|js|mjs|cjs)$/;
|
|
1086
|
-
function inferRuntimePluginName(fileName) {
|
|
1087
|
-
return fileName.replace(PLUGIN_SOURCE_PATTERN, "");
|
|
1088
|
-
}
|
|
1089
|
-
function describeRuntimePluginFiles(filePaths) {
|
|
1090
|
-
return filePaths.filter((filePath) => PLUGIN_SOURCE_PATTERN.test(filePath)).map((filePath) => {
|
|
1091
|
-
const fileName = filePath.split(/[\\/]/).at(-1) ?? filePath;
|
|
1092
|
-
const name = inferRuntimePluginName(fileName);
|
|
1093
|
-
return { name, sourcePath: filePath, binaryName: name };
|
|
1094
|
-
});
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
class PluginManager {
|
|
1098
|
-
eventBus;
|
|
1099
|
-
context;
|
|
1100
|
-
pluginDir;
|
|
1101
|
-
pluginFiles;
|
|
1102
|
-
pluginNames;
|
|
1103
|
-
localBinDir;
|
|
1104
|
-
imageBinDir;
|
|
1105
|
-
pluginsRequireBinaries;
|
|
1106
|
-
ensureImageBinDir;
|
|
1107
|
-
plugins = null;
|
|
1108
|
-
loadPromise = null;
|
|
1109
|
-
constructor(options) {
|
|
1110
|
-
this.eventBus = options.eventBus;
|
|
1111
|
-
this.context = options.context;
|
|
1112
|
-
this.pluginDir = options.pluginDir;
|
|
1113
|
-
this.pluginFiles = options.pluginFiles;
|
|
1114
|
-
this.pluginNames = options.pluginNames;
|
|
1115
|
-
this.localBinDir = options.localBinDir;
|
|
1116
|
-
this.imageBinDir = options.imageBinDir;
|
|
1117
|
-
this.pluginsRequireBinaries = options.pluginsRequireBinaries;
|
|
1118
|
-
this.ensureImageBinDir = options.ensureImageBinDir;
|
|
1119
|
-
}
|
|
1120
|
-
static async load(options) {
|
|
1121
|
-
const pluginDir = options.pluginDir ?? resolve7(options.projectRoot, "rig", "plugins");
|
|
1122
|
-
const localBinDir = options.localBinDir ?? resolve7(options.projectRoot, "rig", "plugins");
|
|
1123
|
-
const imageBinDir = options.imageBinDir ?? (options.runtimeContext ? resolve7(options.runtimeContext.binDir, "plugins") : "");
|
|
1124
|
-
const legacyPluginScan = options.legacyPluginScan ?? isLegacyPluginScanEnabled(options.env);
|
|
1125
|
-
const pluginFiles = legacyPluginScan ? safeReadDir(pluginDir).filter((entry) => PLUGIN_SOURCE_PATTERN.test(entry)) : [];
|
|
1126
|
-
const pluginNames = pluginFiles.map((file) => inferRuntimePluginName(basename3(file)));
|
|
1127
|
-
const context = {
|
|
1128
|
-
projectRoot: options.projectRoot,
|
|
1129
|
-
runId: options.runId,
|
|
1130
|
-
eventBus: options.eventBus
|
|
1131
|
-
};
|
|
1132
|
-
return new PluginManager({
|
|
1133
|
-
eventBus: options.eventBus,
|
|
1134
|
-
context,
|
|
1135
|
-
pluginDir,
|
|
1136
|
-
pluginFiles,
|
|
1137
|
-
pluginNames,
|
|
1138
|
-
localBinDir,
|
|
1139
|
-
imageBinDir,
|
|
1140
|
-
pluginsRequireBinaries: options.pluginsRequireBinaries ?? true,
|
|
1141
|
-
ensureImageBinDir: options.ensureImageBinDir
|
|
1142
|
-
});
|
|
1143
|
-
}
|
|
1144
|
-
list() {
|
|
1145
|
-
if (this.plugins) {
|
|
1146
|
-
return this.plugins.map((plugin) => ({
|
|
1147
|
-
name: plugin.name,
|
|
1148
|
-
validators: plugin.validators?.map((validator) => validator.id) ?? []
|
|
1149
|
-
}));
|
|
1150
|
-
}
|
|
1151
|
-
return this.pluginNames.map((name) => ({ name, validators: [] }));
|
|
1152
|
-
}
|
|
1153
|
-
async beforeCommand(ctx) {
|
|
1154
|
-
const plugins = await this.ensureLoaded();
|
|
1155
|
-
for (const plugin of plugins) {
|
|
1156
|
-
if (!plugin.beforeCommand)
|
|
1157
|
-
continue;
|
|
1158
|
-
await this.safeInvoke(plugin.name, "beforeCommand", () => plugin.beforeCommand?.(ctx, this.context));
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
async afterCommand(result) {
|
|
1162
|
-
const plugins = await this.ensureLoaded();
|
|
1163
|
-
for (const plugin of plugins) {
|
|
1164
|
-
if (!plugin.afterCommand)
|
|
1165
|
-
continue;
|
|
1166
|
-
await this.safeInvoke(plugin.name, "afterCommand", () => plugin.afterCommand?.(result, this.context));
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
async onEvent(event) {
|
|
1170
|
-
const plugins = this.plugins;
|
|
1171
|
-
if (!plugins)
|
|
1172
|
-
return;
|
|
1173
|
-
for (const plugin of plugins) {
|
|
1174
|
-
if (!plugin.onEvent)
|
|
1175
|
-
continue;
|
|
1176
|
-
await this.safeInvoke(plugin.name, "onEvent", () => plugin.onEvent?.(event, this.context));
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
async runValidators(taskId) {
|
|
1180
|
-
const plugins = await this.ensureLoaded();
|
|
1181
|
-
const results = [];
|
|
1182
|
-
for (const plugin of plugins) {
|
|
1183
|
-
for (const validator of plugin.validators ?? []) {
|
|
1184
|
-
await this.eventBus.emit("validator.started", {
|
|
1185
|
-
plugin: plugin.name,
|
|
1186
|
-
validator: validator.id,
|
|
1187
|
-
taskId
|
|
1188
|
-
});
|
|
1189
|
-
try {
|
|
1190
|
-
const result = await validator.run({ taskId, projectRoot: this.context.projectRoot }, this.context);
|
|
1191
|
-
results.push(result);
|
|
1192
|
-
await this.eventBus.emit("validator.finished", {
|
|
1193
|
-
plugin: plugin.name,
|
|
1194
|
-
validator: validator.id,
|
|
1195
|
-
taskId,
|
|
1196
|
-
passed: result.passed,
|
|
1197
|
-
summary: result.summary
|
|
1198
|
-
});
|
|
1199
|
-
} catch (error) {
|
|
1200
|
-
const failed = {
|
|
1201
|
-
id: validator.id,
|
|
1202
|
-
passed: false,
|
|
1203
|
-
summary: `${plugin.name}/${validator.id} failed unexpectedly`,
|
|
1204
|
-
details: `${error}`
|
|
1205
|
-
};
|
|
1206
|
-
results.push(failed);
|
|
1207
|
-
await this.eventBus.emit("validator.finished", {
|
|
1208
|
-
plugin: plugin.name,
|
|
1209
|
-
validator: validator.id,
|
|
1210
|
-
taskId,
|
|
1211
|
-
passed: false,
|
|
1212
|
-
summary: failed.summary,
|
|
1213
|
-
details: failed.details
|
|
1214
|
-
});
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
return results;
|
|
1219
|
-
}
|
|
1220
|
-
async ensureLoaded() {
|
|
1221
|
-
if (this.plugins)
|
|
1222
|
-
return this.plugins;
|
|
1223
|
-
if (this.loadPromise)
|
|
1224
|
-
return this.loadPromise;
|
|
1225
|
-
this.loadPromise = this.loadCompiledPlugins();
|
|
1226
|
-
try {
|
|
1227
|
-
this.plugins = await this.loadPromise;
|
|
1228
|
-
return this.plugins;
|
|
1229
|
-
} finally {
|
|
1230
|
-
this.loadPromise = null;
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
resolveBinPath(binName) {
|
|
1234
|
-
const candidates = [this.imageBinDir, this.localBinDir].filter(Boolean).map((dir) => resolve7(dir, binName));
|
|
1235
|
-
return candidates.find((candidate) => existsSync6(candidate));
|
|
1236
|
-
}
|
|
1237
|
-
async loadCompiledPlugins() {
|
|
1238
|
-
const plugins = [];
|
|
1239
|
-
for (const file of this.pluginFiles) {
|
|
1240
|
-
const binName = inferRuntimePluginName(basename3(file));
|
|
1241
|
-
let binPath = this.resolveBinPath(binName);
|
|
1242
|
-
if (!binPath && !this.imageBinDir && this.pluginsRequireBinaries && this.ensureImageBinDir) {
|
|
1243
|
-
try {
|
|
1244
|
-
this.imageBinDir = await this.ensureImageBinDir(this.context.projectRoot);
|
|
1245
|
-
binPath = this.resolveBinPath(binName);
|
|
1246
|
-
} catch {}
|
|
1247
|
-
}
|
|
1248
|
-
if (!binPath) {
|
|
1249
|
-
const triedPaths = [this.imageBinDir, this.localBinDir].filter(Boolean).map((dir) => resolve7(dir, binName));
|
|
1250
|
-
const missingError = `Compiled plugin binary not found for '${binName}'. Tried: ${triedPaths.join(", ")}`;
|
|
1251
|
-
await this.eventBus.emit("plugin.error", {
|
|
1252
|
-
file: resolve7(this.pluginDir, file),
|
|
1253
|
-
phase: "load",
|
|
1254
|
-
error: missingError
|
|
1255
|
-
});
|
|
1256
|
-
if (this.pluginsRequireBinaries) {
|
|
1257
|
-
throw new Error(missingError);
|
|
1258
|
-
}
|
|
1259
|
-
plugins.push({ name: binName, validators: [] });
|
|
1260
|
-
await this.eventBus.emit("plugin.loaded", {
|
|
1261
|
-
plugin: binName,
|
|
1262
|
-
file: resolve7(this.pluginDir, file),
|
|
1263
|
-
source: "metadata-only"
|
|
1264
|
-
});
|
|
1265
|
-
continue;
|
|
1266
|
-
}
|
|
1267
|
-
const wrapper = createBinaryPluginWrapper(binName, binPath, this.context.projectRoot);
|
|
1268
|
-
plugins.push(wrapper);
|
|
1269
|
-
await this.eventBus.emit("plugin.loaded", {
|
|
1270
|
-
plugin: wrapper.name,
|
|
1271
|
-
file: binPath,
|
|
1272
|
-
source: "compiled-binary"
|
|
1273
|
-
});
|
|
1274
|
-
}
|
|
1275
|
-
return plugins;
|
|
1276
|
-
}
|
|
1277
|
-
async safeInvoke(pluginName, hook, call) {
|
|
1278
|
-
try {
|
|
1279
|
-
await call();
|
|
1280
|
-
} catch (error) {
|
|
1281
|
-
await this.eventBus.emit("plugin.error", {
|
|
1282
|
-
plugin: pluginName,
|
|
1283
|
-
phase: hook,
|
|
1284
|
-
error: `${error}`
|
|
1285
|
-
});
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1288
|
-
}
|
|
1289
|
-
function createBinaryPluginWrapper(name, binPath, projectRoot) {
|
|
1290
|
-
return {
|
|
1291
|
-
name,
|
|
1292
|
-
validators: [
|
|
1293
|
-
{
|
|
1294
|
-
id: `${name}:compiled`,
|
|
1295
|
-
async run(ctx) {
|
|
1296
|
-
const { exitCode, stdout, stderr } = await launchRuntimeBinary({
|
|
1297
|
-
binaryPath: binPath,
|
|
1298
|
-
args: ["--validate", ctx.taskId, ctx.projectRoot],
|
|
1299
|
-
cwd: projectRoot
|
|
1300
|
-
});
|
|
1301
|
-
if (exitCode !== 0) {
|
|
1302
|
-
return {
|
|
1303
|
-
id: `${name}:compiled`,
|
|
1304
|
-
passed: false,
|
|
1305
|
-
summary: `Plugin binary ${name} exited with code ${exitCode}`,
|
|
1306
|
-
details: stderr || stdout
|
|
1307
|
-
};
|
|
1308
|
-
}
|
|
1309
|
-
try {
|
|
1310
|
-
const results = JSON.parse(stdout.trim());
|
|
1311
|
-
const failed = results.filter((result) => !result.passed);
|
|
1312
|
-
if (failed.length > 0) {
|
|
1313
|
-
return {
|
|
1314
|
-
id: `${name}:compiled`,
|
|
1315
|
-
passed: false,
|
|
1316
|
-
summary: `${failed.length} of ${results.length} validator(s) failed`,
|
|
1317
|
-
details: failed.map((result) => `${result.id}: ${result.summary}`).join(`
|
|
1318
|
-
`)
|
|
1319
|
-
};
|
|
1320
|
-
}
|
|
1321
|
-
return {
|
|
1322
|
-
id: `${name}:compiled`,
|
|
1323
|
-
passed: true,
|
|
1324
|
-
summary: `All ${results.length} validator(s) passed`
|
|
1325
|
-
};
|
|
1326
|
-
} catch {
|
|
1327
|
-
return {
|
|
1328
|
-
id: `${name}:compiled`,
|
|
1329
|
-
passed: false,
|
|
1330
|
-
summary: `Failed to parse output from compiled plugin ${name}`,
|
|
1331
|
-
details: stdout.slice(0, 500)
|
|
1332
|
-
};
|
|
1333
|
-
}
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1336
|
-
]
|
|
1337
|
-
};
|
|
1338
|
-
}
|
|
1339
|
-
function safeReadDir(path) {
|
|
1340
|
-
try {
|
|
1341
|
-
return readdirSync(path, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
|
|
1342
|
-
} catch {
|
|
1343
|
-
return [];
|
|
1344
|
-
}
|
|
1345
|
-
}
|
|
1346
1072
|
// packages/runtime/src/agent-mode.ts
|
|
1347
1073
|
function looksLikeShellInvocation(args, mode = process.env.RIG_AGENT_MODE) {
|
|
1348
1074
|
if (mode === "shell") {
|
|
@@ -1599,7 +1325,6 @@ var RIG_RUNTIME_PACKAGE = "@rig/runtime";
|
|
|
1599
1325
|
export {
|
|
1600
1326
|
writeRuntimeContext,
|
|
1601
1327
|
secretDefinesFromEnv,
|
|
1602
|
-
runtimeHookPhases,
|
|
1603
1328
|
runtimeContextStringFields,
|
|
1604
1329
|
runtimeContextArrayFields,
|
|
1605
1330
|
runtimeBinaryAssetEntries,
|
|
@@ -1615,10 +1340,8 @@ export {
|
|
|
1615
1340
|
loadDotEnvSecrets,
|
|
1616
1341
|
launchRuntimeBinary,
|
|
1617
1342
|
isRuntimeBinaryAssetEntry,
|
|
1618
|
-
inferRuntimePluginName,
|
|
1619
1343
|
findTaskById,
|
|
1620
1344
|
ensureLocalRigServerConnection,
|
|
1621
|
-
describeRuntimePluginFiles,
|
|
1622
1345
|
createRuntimeExecutionSession,
|
|
1623
1346
|
createRuntimeBinaryBuildManifest,
|
|
1624
1347
|
createPluginTaskRecordReader,
|
|
@@ -1631,7 +1354,6 @@ export {
|
|
|
1631
1354
|
RIG_RUNTIME_PACKAGE,
|
|
1632
1355
|
RIG_DEFINITION_DIRNAME,
|
|
1633
1356
|
RIG_ARTIFACTS_DIRNAME,
|
|
1634
|
-
PluginManager,
|
|
1635
1357
|
HttpRuntimeRunReporter,
|
|
1636
1358
|
HttpRuntimeHostSession,
|
|
1637
1359
|
GeneralCliEventBus,
|
|
Binary file
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"buildKey": "{\"version\":1,\"sourcePath\":\"/var/folders/zr/6js4xbjs3bgf46v76j145mlw0000gn/T/rig-native/rig-shell-darwin-arm64\",\"sourceDigest\":\"
|
|
3
|
+
"buildKey": "{\"version\":1,\"sourcePath\":\"/var/folders/zr/6js4xbjs3bgf46v76j145mlw0000gn/T/rig-native/rig-shell-darwin-arm64\",\"sourceDigest\":\"b7ec0fc575a3b2bea9bf2538207d59a5400c2cb3561080c24b87e0194954bd7a\"}"
|
|
4
4
|
}
|
|
Binary file
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"buildKey": "{\"version\":1,\"sourcePath\":\"/var/folders/zr/6js4xbjs3bgf46v76j145mlw0000gn/T/rig-native/rig-tools-darwin-arm64\",\"sourceDigest\":\"
|
|
3
|
+
"buildKey": "{\"version\":1,\"sourcePath\":\"/var/folders/zr/6js4xbjs3bgf46v76j145mlw0000gn/T/rig-native/rig-tools-darwin-arm64\",\"sourceDigest\":\"abfbb45225c08b4cc154e2cc5a70d0b8ba83d162a027c23a9c71ca22b350854d\"}"
|
|
4
4
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@h-rig/runtime",
|
|
3
|
-
"version": "0.0.6-alpha.
|
|
3
|
+
"version": "0.0.6-alpha.29",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Rig package",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -63,13 +63,14 @@
|
|
|
63
63
|
"main": "./dist/src/index.js",
|
|
64
64
|
"module": "./dist/src/index.js",
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@earendil-works/pi-coding-agent": "npm:@h-rig/pi-coding-agent@0.0.6-alpha.
|
|
66
|
+
"@earendil-works/pi-coding-agent": "npm:@h-rig/pi-coding-agent@0.0.6-alpha.29",
|
|
67
67
|
"@libsql/client": "^0.17.2",
|
|
68
|
-
"@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.
|
|
69
|
-
"@rig/core": "npm:@h-rig/core@0.0.6-alpha.
|
|
70
|
-
"@rig/hook-kit": "npm:@h-rig/hook-kit@0.0.6-alpha.
|
|
71
|
-
"@rig/shared": "npm:@h-rig/shared@0.0.6-alpha.
|
|
72
|
-
"@rig/
|
|
68
|
+
"@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.29",
|
|
69
|
+
"@rig/core": "npm:@h-rig/core@0.0.6-alpha.29",
|
|
70
|
+
"@rig/hook-kit": "npm:@h-rig/hook-kit@0.0.6-alpha.29",
|
|
71
|
+
"@rig/shared": "npm:@h-rig/shared@0.0.6-alpha.29",
|
|
72
|
+
"@rig/skill-loader": "npm:@h-rig/skill-loader@0.0.6-alpha.29",
|
|
73
|
+
"@rig/validator-kit": "npm:@h-rig/validator-kit@0.0.6-alpha.29",
|
|
73
74
|
"effect": "4.0.0-beta.78",
|
|
74
75
|
"smol-toml": "^1.6.0"
|
|
75
76
|
}
|