@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
@@ -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 existsSync4, readFileSync as readFileSync3, readdirSync, statSync, writeFileSync as writeFileSync2 } from "fs";
336
- import { basename, join as join2, resolve as resolve3 } from "path";
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 existsSync3, readFileSync as readFileSync2 } from "fs";
340
- import { resolve as resolve2 } from "path";
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 ?? resolve2(projectRoot, ".rig", "task-config.json");
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 = resolve2(projectRoot, ".rig", "task-config.json")) {
375
- if (!existsSync3(configPath)) {
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(readFileSync2(configPath, "utf8"));
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 ?? resolve3(projectRoot, ".rig", "task-config.json");
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 ?? resolve3(projectRoot, ".rig", "task-config.json");
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 = resolve3(projectRoot, "rig.config.json");
587
- if (existsSync4(jsonPath)) {
640
+ const jsonPath = resolve4(projectRoot, "rig.config.json");
641
+ if (existsSync5(jsonPath)) {
588
642
  try {
589
- const parsed = JSON.parse(readFileSync3(jsonPath, "utf8"));
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 = resolve3(projectRoot, "rig.config.ts");
599
- if (!existsSync4(tsPath)) {
652
+ const tsPath = resolve4(projectRoot, "rig.config.ts");
653
+ if (!existsSync5(tsPath)) {
600
654
  return null;
601
655
  }
602
656
  try {
603
- const source = readFileSync3(tsPath, "utf8");
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 (!existsSync4(configPath)) {
677
+ if (!existsSync5(configPath)) {
624
678
  return null;
625
679
  }
626
- const parsed = JSON.parse(readFileSync3(configPath, "utf8"));
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
- writeFileSync2(configPath, `${JSON.stringify(rawConfig, null, 2)}
697
+ writeFileSync3(configPath, `${JSON.stringify(rawConfig, null, 2)}
644
698
  `, "utf8");
645
699
  }
646
700
  function updateFileBackedTask(projectRoot, sourcePath, taskId, update) {
647
- const directory = resolve3(projectRoot, sourcePath);
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(readFileSync3(file, "utf8"));
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
- writeFileSync2(file, `${JSON.stringify(raw, null, 2)}
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 = resolve3(projectRoot, sourcePath);
675
- if (!existsSync4(directory)) {
728
+ const directory = resolve4(projectRoot, sourcePath);
729
+ if (!existsSync5(directory)) {
676
730
  return [];
677
731
  }
678
732
  const tasks = [];
679
- for (const name of readdirSync(directory)) {
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(resolve3(projectRoot, sourcePath), taskId);
744
+ const file = findFileBackedTaskFile(resolve4(projectRoot, sourcePath), taskId);
691
745
  if (!file) {
692
746
  return null;
693
747
  }
694
- const raw = JSON.parse(readFileSync3(file, "utf8"));
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 (!existsSync4(directory)) {
761
+ if (!existsSync5(directory)) {
708
762
  return null;
709
763
  }
710
- for (const name of readdirSync(directory)) {
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(readFileSync3(file, "utf8"));
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\":\"3b73710b3e4cdfb76d959e92d37049234cf54b2d8deee683aba9f342be4f3597\"}"
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\":\"9bf9381cca81f26d1b3ddcad28a0a6211a090ec2905471d6c25a9d89fb20c496\"}"
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.27",
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.27",
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.27",
69
- "@rig/core": "npm:@h-rig/core@0.0.6-alpha.27",
70
- "@rig/hook-kit": "npm:@h-rig/hook-kit@0.0.6-alpha.27",
71
- "@rig/shared": "npm:@h-rig/shared@0.0.6-alpha.27",
72
- "@rig/validator-kit": "npm:@h-rig/validator-kit@0.0.6-alpha.27",
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
  }