@h-rig/core 0.0.6-alpha.157 → 0.0.6-alpha.158

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 (89) hide show
  1. package/dist/src/agent-role-registry.d.ts +4 -0
  2. package/dist/src/agent-role-registry.js +27 -0
  3. package/dist/src/authority-paths.d.ts +15 -0
  4. package/dist/src/authority-paths.js +80 -0
  5. package/dist/src/baked-secrets.d.ts +6 -0
  6. package/dist/src/baked-secrets.js +121 -0
  7. package/dist/src/build-time-config.d.ts +12 -0
  8. package/dist/src/build-time-config.js +25 -0
  9. package/dist/src/build-time-config.macro.d.ts +1 -0
  10. package/dist/src/capability-loaders.d.ts +51 -0
  11. package/dist/src/{task-io.js → capability-loaders.js} +237 -195
  12. package/dist/src/capability.d.ts +79 -0
  13. package/dist/src/capability.js +63 -0
  14. package/dist/src/checkout-root.d.ts +1 -0
  15. package/dist/src/checkout-root.js +30 -0
  16. package/dist/src/config-env.d.ts +4 -0
  17. package/dist/src/config-env.js +23 -0
  18. package/dist/src/config.d.ts +1 -1
  19. package/dist/src/config.js +7 -4
  20. package/dist/src/declarative-config.d.ts +14 -0
  21. package/dist/src/declarative-config.js +82 -0
  22. package/dist/src/define-config.d.ts +2 -1
  23. package/dist/src/define-config.js +7 -4
  24. package/dist/src/embedded-plugins.d.ts +59 -0
  25. package/dist/src/embedded-plugins.js +22 -0
  26. package/dist/src/exec.d.ts +13 -0
  27. package/dist/src/exec.js +101 -0
  28. package/dist/src/harness-paths.d.ts +18 -0
  29. package/dist/src/harness-paths.js +141 -0
  30. package/dist/src/hook-materializer.d.ts +72 -0
  31. package/dist/src/hook-materializer.js +274 -0
  32. package/dist/src/hook-runner.d.ts +48 -0
  33. package/dist/src/hook-runner.js +752 -0
  34. package/dist/src/hook-runtime.d.ts +11 -0
  35. package/dist/src/hook-runtime.js +307 -0
  36. package/dist/src/index.d.ts +3 -1
  37. package/dist/src/index.js +119 -5
  38. package/dist/src/json-files.d.ts +9 -0
  39. package/dist/src/json-files.js +125 -0
  40. package/dist/src/kernel-entrypoint.d.ts +22 -0
  41. package/dist/src/kernel-entrypoint.js +537 -0
  42. package/dist/src/layout.d.ts +10 -0
  43. package/dist/src/layout.js +144 -0
  44. package/dist/src/load-config.js +149 -50
  45. package/dist/src/placement.d.ts +50 -0
  46. package/dist/src/placement.js +990 -0
  47. package/dist/src/plugin-host-context.d.ts +66 -0
  48. package/dist/src/plugin-host-context.js +1270 -0
  49. package/dist/src/plugin-host-registries.d.ts +31 -0
  50. package/dist/src/plugin-host-registries.js +79 -0
  51. package/dist/src/plugin-host.d.ts +6 -1
  52. package/dist/src/plugin-host.js +51 -0
  53. package/dist/src/plugin-runtime.d.ts +45 -6
  54. package/dist/src/profile-ops.d.ts +9 -0
  55. package/dist/src/profile-ops.js +252 -0
  56. package/dist/src/project-plugins.d.ts +9 -12
  57. package/dist/src/project-plugins.js +248 -61
  58. package/dist/src/remote-config.d.ts +183 -0
  59. package/dist/src/remote-config.js +568 -0
  60. package/dist/src/root-resolver.d.ts +5 -0
  61. package/dist/src/root-resolver.js +69 -0
  62. package/dist/src/run-provisioning.d.ts +58 -0
  63. package/dist/src/run-provisioning.js +128 -0
  64. package/dist/src/runtime-context.d.ts +20 -0
  65. package/dist/src/runtime-context.js +257 -0
  66. package/dist/src/runtime-events.d.ts +44 -0
  67. package/dist/src/runtime-events.js +212 -0
  68. package/dist/src/runtime-overlay.d.ts +11 -0
  69. package/dist/src/runtime-overlay.js +71 -0
  70. package/dist/src/runtime-paths.d.ts +21 -0
  71. package/dist/src/runtime-paths.js +181 -0
  72. package/dist/src/runtime-provisioning-env.d.ts +5 -0
  73. package/dist/src/runtime-provisioning-env.js +217 -0
  74. package/dist/src/runtime-runner-context.d.ts +12 -0
  75. package/dist/src/runtime-runner-context.js +1 -0
  76. package/dist/src/safe-identifiers.d.ts +44 -0
  77. package/dist/src/safe-identifiers.js +96 -0
  78. package/dist/src/scope-rules.d.ts +4 -0
  79. package/dist/src/scope-rules.js +21 -0
  80. package/dist/src/server-paths.d.ts +26 -0
  81. package/dist/src/server-paths.js +308 -0
  82. package/dist/src/setup-version.d.ts +3 -0
  83. package/dist/src/setup-version.js +14 -0
  84. package/dist/src/task-record-reader.d.ts +3 -0
  85. package/dist/src/task-record-reader.js +9 -0
  86. package/dist/src/validator-registry.d.ts +27 -0
  87. package/dist/src/validator-registry.js +64 -0
  88. package/package.json +136 -6
  89. package/dist/src/task-io.d.ts +0 -54
@@ -1,6 +1,6 @@
1
1
  // @bun
2
2
  // packages/core/src/project-plugins.ts
3
- import { existsSync as existsSync2, statSync as statSync2 } from "fs";
3
+ import { existsSync as existsSync3, statSync as statSync2 } from "fs";
4
4
  import { resolve as resolve2 } from "path";
5
5
 
6
6
  // packages/core/src/plugin-host.ts
@@ -39,6 +39,7 @@ function createPluginHost(plugins) {
39
39
  const panels = [];
40
40
  const blockerClassifiers = [];
41
41
  const sessionExtensions = [];
42
+ const seedEntrypoints = [];
42
43
  const stages = [];
43
44
  const stageMutations = [];
44
45
  const stageExecutors = {};
@@ -71,6 +72,8 @@ function createPluginHost(plugins) {
71
72
  blockerClassifiers.push(...c.blockerClassifiers.map((item) => ({ item, pluginName })));
72
73
  if (c.sessionExtensions)
73
74
  sessionExtensions.push(...c.sessionExtensions.map((item) => ({ item, pluginName })));
75
+ if (c.seedEntrypoints)
76
+ seedEntrypoints.push(...c.seedEntrypoints.map((item) => ({ item, pluginName })));
74
77
  if (c.stageMutations)
75
78
  stageMutations.push(...c.stageMutations.map((item) => ({ item, pluginName })));
76
79
  if (c.stages) {
@@ -93,6 +96,7 @@ function createPluginHost(plugins) {
93
96
  const panelMap = indexById(panels, "panel");
94
97
  const blockerClassifierMap = indexById(blockerClassifiers, "blockerClassifier");
95
98
  indexById(sessionExtensions, "sessionExtension");
99
+ indexById(seedEntrypoints, "seedEntrypoint");
96
100
  const taskSourceFactoryByKind = new Map;
97
101
  const taskSourceKindRegistrant = new Map;
98
102
  for (const { item, pluginName } of taskSources) {
@@ -102,6 +106,38 @@ function createPluginHost(plugins) {
102
106
  taskSourceFactoryByKind.set(item.kind, item);
103
107
  taskSourceKindRegistrant.set(item.kind, pluginName);
104
108
  }
109
+ const seedEntrypointByBasename = new Map;
110
+ const seedEntrypointByWorkerArg = new Map;
111
+ let insidePtySeedEntrypoint;
112
+ const registerSeedEntrypointSelector = (map, selectorKind, selector, contribution) => {
113
+ const existing = map.get(selector);
114
+ if (existing) {
115
+ throw new Error(`duplicate seed entrypoint ${selectorKind} "${selector}": registered by entrypoint "${existing.item.id}" from plugin "${existing.pluginName}" and entrypoint "${contribution.item.id}" from plugin "${contribution.pluginName}"`);
116
+ }
117
+ map.set(selector, contribution);
118
+ };
119
+ for (const contribution of seedEntrypoints) {
120
+ const entrypoint = contribution.item;
121
+ let selectorCount = 0;
122
+ if (entrypoint.basename) {
123
+ selectorCount += 1;
124
+ registerSeedEntrypointSelector(seedEntrypointByBasename, "basename", entrypoint.basename, contribution);
125
+ }
126
+ if (entrypoint.workerArg) {
127
+ selectorCount += 1;
128
+ registerSeedEntrypointSelector(seedEntrypointByWorkerArg, "workerArg", entrypoint.workerArg, contribution);
129
+ }
130
+ if (entrypoint.insidePty) {
131
+ selectorCount += 1;
132
+ if (insidePtySeedEntrypoint) {
133
+ throw new Error(`duplicate seed entrypoint inside-pty selector: registered by entrypoint "${insidePtySeedEntrypoint.item.id}" from plugin "${insidePtySeedEntrypoint.pluginName}" and entrypoint "${entrypoint.id}" from plugin "${contribution.pluginName}"`);
134
+ }
135
+ insidePtySeedEntrypoint = contribution;
136
+ }
137
+ if (selectorCount === 0) {
138
+ throw new Error(`seed entrypoint "${entrypoint.id}" from plugin "${contribution.pluginName}" must declare at least one selector (basename, workerArg, or insidePty)`);
139
+ }
140
+ }
105
141
  const allValidators = validators.map((c) => c.item);
106
142
  const allHooks = hooks.map((c) => c.item);
107
143
  const allSkills = skills.map((c) => c.item);
@@ -116,6 +152,7 @@ function createPluginHost(plugins) {
116
152
  const allPanels = panels.map((c) => c.item);
117
153
  const allBlockerClassifiers = blockerClassifiers.map((c) => c.item);
118
154
  const allSessionExtensions = sessionExtensions.map((c) => c.item);
155
+ const allSeedEntrypoints = seedEntrypoints.map((c) => c.item);
119
156
  const executableCliCommandByName = new Map;
120
157
  const registerExecutableCliCommandSelector = (selector, contribution) => {
121
158
  const existing = executableCliCommandByName.get(selector);
@@ -133,6 +170,15 @@ function createPluginHost(plugins) {
133
170
  registerExecutableCliCommandSelector(alias, contribution);
134
171
  }
135
172
  }
173
+ let defaultRootCliCommand;
174
+ for (const contribution of cliCommands) {
175
+ if (!contribution.item.rootDefault)
176
+ continue;
177
+ if (defaultRootCliCommand) {
178
+ throw new Error(`duplicate default root CLI command registered by command "${defaultRootCliCommand.item.id}" from plugin "${defaultRootCliCommand.pluginName}" and command "${contribution.item.id}" from plugin "${contribution.pluginName}"`);
179
+ }
180
+ defaultRootCliCommand = contribution;
181
+ }
136
182
  return {
137
183
  getValidator: (id) => validatorMap.get(id),
138
184
  getHook: (id) => hookMap.get(id),
@@ -166,27 +212,35 @@ function createPluginHost(plugins) {
166
212
  listExecutableBlockerClassifiers: () => allBlockerClassifiers,
167
213
  listExecutableCliCommands: () => allCliCommands,
168
214
  listSessionExtensions: () => allSessionExtensions,
215
+ listSeedEntrypoints: () => allSeedEntrypoints,
216
+ resolveSeedEntrypointByBasename: (value) => seedEntrypointByBasename.get(value)?.item,
217
+ resolveSeedEntrypointByWorkerArg: (value) => seedEntrypointByWorkerArg.get(value)?.item,
218
+ resolveInsidePtySeedEntrypoint: () => insidePtySeedEntrypoint?.item,
169
219
  resolveExecutableCliCommand: (requested) => executableCliCommandByName.get(requested)?.item,
220
+ resolveDefaultRootCliCommand: () => defaultRootCliCommand?.item,
170
221
  resolveTaskSourceFactoryByKind: (kind) => taskSourceFactoryByKind.get(kind)
171
222
  };
172
223
  }
173
224
 
174
225
  // packages/core/src/load-config.ts
175
- import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync } from "fs";
226
+ import { existsSync as existsSync2, mkdirSync, mkdtempSync, readFileSync as readFileSync2, readdirSync, rmSync, statSync } from "fs";
176
227
  import { isBuiltin } from "module";
177
- import { dirname, isAbsolute, join, relative, resolve } from "path";
228
+ import { dirname, isAbsolute, join as join2, relative, resolve } from "path";
178
229
  import { pathToFileURL } from "url";
179
- import { Schema as Schema2 } from "effect";
180
- import { RigConfig as RigConfig2 } from "@rig/contracts";
230
+ import { Schema as Schema3 } from "effect";
231
+ import { RigConfig as RigConfig3 } from "@rig/contracts";
181
232
 
182
233
  // packages/core/src/define-config.ts
183
234
  import { Schema } from "effect";
184
235
  import { RigConfig } from "@rig/contracts";
185
236
  function normalizeWorkspaceConfig(raw) {
186
- const workspace = raw && typeof raw === "object" && !Array.isArray(raw) ? { ...raw } : { mainRepo: "." };
187
- workspace.checkout = workspace.checkout ?? workspace.isolation ?? "worktree";
188
- workspace.isolation = workspace.isolation ?? workspace.checkout;
189
- workspace.sandbox = workspace.sandbox ?? "enforce";
237
+ const workspace = raw && typeof raw === "object" && !Array.isArray(raw) ? { ...raw } : {};
238
+ if (workspace.mainRepo === undefined)
239
+ workspace.mainRepo = ".";
240
+ if (workspace.checkout === undefined && workspace.isolation !== undefined)
241
+ workspace.checkout = workspace.isolation;
242
+ if (workspace.isolation === undefined && workspace.checkout !== undefined)
243
+ workspace.isolation = workspace.checkout;
190
244
  return workspace;
191
245
  }
192
246
  function applyConfigDefaults(raw) {
@@ -200,6 +254,64 @@ function applyConfigDefaults(raw) {
200
254
  };
201
255
  }
202
256
 
257
+ // packages/core/src/declarative-config.ts
258
+ import { existsSync, readFileSync } from "fs";
259
+ import { join } from "path";
260
+ import { parse as parseToml } from "smol-toml";
261
+ import { Schema as Schema2 } from "effect";
262
+ import { RigConfig as RigConfig2 } from "@rig/contracts";
263
+
264
+ // packages/core/src/embedded-plugins.ts
265
+ var registered = null;
266
+ function getStandardPluginsResolver() {
267
+ return registered;
268
+ }
269
+ var bakedProjectConfig = null;
270
+ function getEmbeddedProjectConfig() {
271
+ return bakedProjectConfig;
272
+ }
273
+
274
+ // packages/core/src/declarative-config.ts
275
+ var DECLARATIVE_CONFIG_NAMES = ["rigfig.toml", "rigfig.json"];
276
+ function findDeclarativeConfigPath(cwd) {
277
+ const dir = join(cwd, ".rig");
278
+ for (const name of DECLARATIVE_CONFIG_NAMES) {
279
+ const candidate = join(dir, name);
280
+ if (existsSync(candidate))
281
+ return candidate;
282
+ }
283
+ return null;
284
+ }
285
+ function parseDeclarativeFile(path) {
286
+ const raw = readFileSync(path, "utf8");
287
+ const parsed = path.endsWith(".json") ? JSON.parse(raw) : parseToml(raw);
288
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
289
+ throw new Error(`Declarative config ${path} must parse to an object.`);
290
+ }
291
+ return parsed;
292
+ }
293
+ function loadDeclarativeConfig(path) {
294
+ const data = parseDeclarativeFile(path);
295
+ const standardSection = data.standard && typeof data.standard === "object" && !Array.isArray(data.standard) ? data.standard : {};
296
+ const useStandard = standardSection.enabled !== false;
297
+ let plugins = [];
298
+ if (useStandard) {
299
+ const resolver = getStandardPluginsResolver();
300
+ if (!resolver) {
301
+ throw new Error(`Declarative config ${path} needs the embedded standard plugins, but none were registered. ` + `This is a seed/boot wiring error (the binary entrypoint must import the standard-plugin registration).`);
302
+ }
303
+ plugins = resolver(data);
304
+ }
305
+ const { standard: _standardDirective, ...configFields } = data;
306
+ const withDefaults = applyConfigDefaults({ ...configFields, plugins });
307
+ const explicitPlugins = Array.isArray(withDefaults.plugins) ? [...withDefaults.plugins] : [];
308
+ const decoded = Schema2.decodeUnknownSync(RigConfig2)({
309
+ ...withDefaults,
310
+ plugins: explicitPlugins
311
+ });
312
+ return { ...decoded, plugins: explicitPlugins };
313
+ }
314
+
203
315
  // packages/core/src/load-config.ts
204
316
  var TS_NAMES = ["rig.config.ts", "rig.config.mts"];
205
317
  var JSON_NAMES = ["rig.config.json"];
@@ -261,18 +373,18 @@ function exportTargetFromPackageJson(pkg, subpath) {
261
373
  return subpath === "." && typeof pkg.module === "string" ? pkg.module : subpath === "." && typeof pkg.main === "string" ? pkg.main : null;
262
374
  }
263
375
  function resolvePackageDirFromBunStore(packageName, nodeModulesDir) {
264
- const storeDir = join(nodeModulesDir, ".bun");
265
- if (!existsSync(storeDir))
376
+ const storeDir = join2(nodeModulesDir, ".bun");
377
+ if (!existsSync2(storeDir))
266
378
  return null;
267
379
  const encoded = packageName.replace("/", "+");
268
380
  try {
269
381
  const candidates = readdirSync(storeDir).filter((entry) => entry.startsWith(`${encoded}@`)).map((entry) => {
270
- const candidateDir = join(storeDir, entry, "node_modules", packageName);
271
- const packageJsonPath = join(candidateDir, "package.json");
272
- if (!existsSync(packageJsonPath))
382
+ const candidateDir = join2(storeDir, entry, "node_modules", packageName);
383
+ const packageJsonPath = join2(candidateDir, "package.json");
384
+ if (!existsSync2(packageJsonPath))
273
385
  return null;
274
386
  try {
275
- const pkg = JSON.parse(readFileSync(packageJsonPath, "utf8"));
387
+ const pkg = JSON.parse(readFileSync2(packageJsonPath, "utf8"));
276
388
  return {
277
389
  dir: candidateDir,
278
390
  sortKey: pkg.version?.trim() || entry
@@ -290,30 +402,30 @@ function resolvePackageDirFromBunStore(packageName, nodeModulesDir) {
290
402
  }
291
403
  }
292
404
  function resolveDirectoryModulePath(directoryPath) {
293
- const packageJsonPath = join(directoryPath, "package.json");
294
- if (existsSync(packageJsonPath)) {
405
+ const packageJsonPath = join2(directoryPath, "package.json");
406
+ if (existsSync2(packageJsonPath)) {
295
407
  try {
296
- const pkg = JSON.parse(readFileSync(packageJsonPath, "utf8"));
408
+ const pkg = JSON.parse(readFileSync2(packageJsonPath, "utf8"));
297
409
  const target = exportTargetFromPackageJson(pkg, ".");
298
410
  if (target) {
299
- const resolved = resolveModulePath(join(directoryPath, target));
411
+ const resolved = resolveModulePath(join2(directoryPath, target));
300
412
  if (resolved)
301
413
  return resolved;
302
414
  }
303
415
  } catch {}
304
416
  }
305
417
  for (const candidate of ["index.js", "index.mjs", "index.cjs", "index.ts", "index.json"]) {
306
- const resolved = resolveModulePath(join(directoryPath, candidate));
418
+ const resolved = resolveModulePath(join2(directoryPath, candidate));
307
419
  if (resolved)
308
420
  return resolved;
309
421
  }
310
422
  return null;
311
423
  }
312
424
  function resolveModulePath(candidatePath) {
313
- if (!existsSync(candidatePath)) {
425
+ if (!existsSync2(candidatePath)) {
314
426
  for (const extension of [".ts", ".mts", ".tsx", ".js", ".mjs", ".cjs", ".json"]) {
315
427
  const withExtension = `${candidatePath}${extension}`;
316
- if (existsSync(withExtension))
428
+ if (existsSync2(withExtension))
317
429
  return resolveModulePath(withExtension);
318
430
  }
319
431
  return null;
@@ -330,13 +442,13 @@ function resolveModulePath(candidatePath) {
330
442
  return null;
331
443
  }
332
444
  function resolvePackageExportFromDir(packageDir, subpath) {
333
- const packageJsonPath = join(packageDir, "package.json");
334
- if (existsSync(packageJsonPath)) {
445
+ const packageJsonPath = join2(packageDir, "package.json");
446
+ if (existsSync2(packageJsonPath)) {
335
447
  try {
336
- const pkg = JSON.parse(readFileSync(packageJsonPath, "utf8"));
448
+ const pkg = JSON.parse(readFileSync2(packageJsonPath, "utf8"));
337
449
  const target = exportTargetFromPackageJson(pkg, subpath);
338
450
  if (target) {
339
- const resolved = resolveModulePath(join(packageDir, target));
451
+ const resolved = resolveModulePath(join2(packageDir, target));
340
452
  if (resolved)
341
453
  return resolved;
342
454
  }
@@ -347,12 +459,12 @@ function resolvePackageExportFromDir(packageDir, subpath) {
347
459
  if (subpath !== ".") {
348
460
  const legacySubpath = subpath.replace(/^\.\//, "");
349
461
  for (const candidate of [
350
- join(packageDir, legacySubpath),
351
- join(packageDir, `${legacySubpath}.js`),
352
- join(packageDir, `${legacySubpath}.mjs`),
353
- join(packageDir, `${legacySubpath}.cjs`),
354
- join(packageDir, `${legacySubpath}.ts`),
355
- join(packageDir, `${legacySubpath}.json`)
462
+ join2(packageDir, legacySubpath),
463
+ join2(packageDir, `${legacySubpath}.js`),
464
+ join2(packageDir, `${legacySubpath}.mjs`),
465
+ join2(packageDir, `${legacySubpath}.cjs`),
466
+ join2(packageDir, `${legacySubpath}.ts`),
467
+ join2(packageDir, `${legacySubpath}.json`)
356
468
  ]) {
357
469
  const resolved = resolveModulePath(candidate);
358
470
  if (resolved)
@@ -387,32 +499,62 @@ function resolveProjectPackageImport(specifier, configDir) {
387
499
  const parsed = packageNameAndSubpath(specifier);
388
500
  if (!parsed)
389
501
  return null;
390
- const nodeModulesDir = join(configDir, "node_modules");
391
- const directPackageDir = join(nodeModulesDir, parsed.packageName);
392
- const packageDir = existsSync(join(directPackageDir, "package.json")) ? directPackageDir : resolvePackageDirFromBunStore(parsed.packageName, nodeModulesDir);
502
+ const nodeModulesDir = join2(configDir, "node_modules");
503
+ const directPackageDir = join2(nodeModulesDir, parsed.packageName);
504
+ const packageDir = existsSync2(join2(directPackageDir, "package.json")) ? directPackageDir : resolvePackageDirFromBunStore(parsed.packageName, nodeModulesDir);
393
505
  return packageDir ? resolvePackageExportFromDir(packageDir, parsed.subpath) : null;
394
506
  }
507
+ function canImportRigWorkspacePackagesDirectly(source, configDir) {
508
+ const packageNames = new Set;
509
+ for (const match of source.matchAll(/(?:from\s*|import\s*\(\s*|import\s*)["'](@rig\/[^"']+)["']/g)) {
510
+ const parsed = packageNameAndSubpath(match[1] ?? "");
511
+ if (parsed?.packageName)
512
+ packageNames.add(parsed.packageName);
513
+ }
514
+ if (packageNames.size === 0)
515
+ return false;
516
+ for (const packageName of packageNames) {
517
+ const shortName = packageName.replace(/^@rig\//, "");
518
+ const manifestPath = join2(configDir, "packages", shortName, "package.json");
519
+ if (!existsSync2(manifestPath))
520
+ return false;
521
+ try {
522
+ const parsed = JSON.parse(readFileSync2(manifestPath, "utf8"));
523
+ if (parsed.name !== packageName)
524
+ return false;
525
+ } catch {
526
+ return false;
527
+ }
528
+ }
529
+ return true;
530
+ }
395
531
  async function importConfigViaRuntimeBundleUnserialized(configPath) {
396
532
  const bun = globalThis.Bun;
397
533
  if (!bun?.build) {
398
534
  throw new Error(`Failed to import ${configPath}: bare imports could not be resolved and no Bun.build runtime bundler is available.`);
399
535
  }
400
- const RUNTIME_ONLY_EXTERNAL_PACKAGES = new Set(["mupdf", "fastembed", "onnxruntime-node", "markit-ai"]);
536
+ const RUNTIME_ONLY_EXTERNAL_PACKAGES = new Set(["effect", "mupdf", "fastembed", "onnxruntime-node", "markit-ai"]);
401
537
  const configDir = dirname(configPath);
402
538
  const UNRESOLVED_NAMESPACE = "rig-config-unresolved";
403
539
  const unresolvedLocalPlugin = {
404
540
  name: "rig-config-unresolved-local",
405
541
  setup(build) {
542
+ build.onLoad({ filter: /\.(?:html|txt)$/ }, (args) => ({
543
+ loader: "js",
544
+ contents: `export default ${JSON.stringify(readFileSync2(args.path, "utf8"))};
545
+ `
546
+ }));
406
547
  build.onResolve({ filter: /.*/ }, (args) => {
407
548
  const directFilePath = resolvedFilePath(args.path, configDir);
408
549
  if (directFilePath)
409
550
  return { path: directFilePath };
410
551
  const packageImport = packageNameAndSubpath(args.path);
411
- if (packageImport && RUNTIME_ONLY_EXTERNAL_PACKAGES.has(packageImport.packageName))
552
+ if (packageImport && (packageImport.packageName.startsWith("@rig/") || RUNTIME_ONLY_EXTERNAL_PACKAGES.has(packageImport.packageName))) {
412
553
  return { path: args.path, external: true };
554
+ }
413
555
  const projectPackagePath = resolveProjectPackageImport(args.path, configDir);
414
556
  if (projectPackagePath)
415
- return packageImport?.packageName.startsWith("@oh-my-pi/") ? { path: projectPackagePath, external: true } : { path: projectPackagePath };
557
+ return { path: projectPackagePath };
416
558
  if (/^(?:node|bun):/.test(args.path) || isBuiltin(args.path))
417
559
  return;
418
560
  if (packageImport)
@@ -443,7 +585,7 @@ throw new Error(${JSON.stringify(`Failed to bundle ${configPath}: Could not reso
443
585
  const result = await bun.build({
444
586
  entrypoints: [configPath],
445
587
  target: "bun",
446
- external: ["mupdf", "fastembed", "onnxruntime-node", "markit-ai"],
588
+ external: ["effect", "mupdf", "fastembed", "onnxruntime-node", "markit-ai"],
447
589
  format: "esm",
448
590
  throw: false,
449
591
  packages: "bundle",
@@ -454,11 +596,11 @@ throw new Error(${JSON.stringify(`Failed to bundle ${configPath}: Could not reso
454
596
  `);
455
597
  throw new Error(`Failed to bundle ${configPath}: ${detail || "unknown bundler error"}`);
456
598
  }
457
- const bundleParentDir = join(configDir, ".rig", "tmp");
599
+ const bundleParentDir = join2(configDir, ".rig", "tmp");
458
600
  mkdirSync(bundleParentDir, { recursive: true });
459
- const dir = mkdtempSync(join(bundleParentDir, "rig-config-bundle-"));
601
+ const dir = mkdtempSync(join2(bundleParentDir, "rig-config-bundle-"));
460
602
  try {
461
- const bundledPath = join(dir, "rig.config.bundled.js");
603
+ const bundledPath = join2(dir, "rig.config.bundled.js");
462
604
  await bun.write(bundledPath, await result.outputs[0].text());
463
605
  return await import(pathToFileURL(bundledPath).href);
464
606
  } finally {
@@ -468,16 +610,20 @@ throw new Error(${JSON.stringify(`Failed to bundle ${configPath}: Could not reso
468
610
  }
469
611
  }
470
612
  async function loadConfig(cwd) {
613
+ const baked = getEmbeddedProjectConfig();
614
+ if (baked && resolve(baked.projectRoot) === resolve(cwd)) {
615
+ return decodeExplicitPluginConfig(baked.raw);
616
+ }
471
617
  for (const name of TS_NAMES) {
472
- const p = join(cwd, name);
473
- if (existsSync(p)) {
618
+ const p = join2(cwd, name);
619
+ if (existsSync2(p)) {
474
620
  const mod = await enqueueRuntimeBundle(async () => {
475
621
  if (runningFromCompiledBinary()) {
476
622
  return importConfigViaRuntimeBundleUnserialized(p);
477
623
  }
478
- const source = readFileSync(p, "utf8");
624
+ const source = readFileSync2(p, "utf8");
479
625
  const importsRigHostPackages = /(?:import\s+[^;]*?from\s*|import\s*\()\s*["']@rig\//.test(source);
480
- if (importsRigHostPackages) {
626
+ if (importsRigHostPackages && !canImportRigWorkspacePackagesDirectly(source, cwd)) {
481
627
  return importConfigViaRuntimeBundleUnserialized(p);
482
628
  }
483
629
  try {
@@ -492,19 +638,23 @@ async function loadConfig(cwd) {
492
638
  return decodeExplicitPluginConfig(raw);
493
639
  }
494
640
  }
641
+ const declarativePath = findDeclarativeConfigPath(cwd);
642
+ if (declarativePath) {
643
+ return loadDeclarativeConfig(declarativePath);
644
+ }
495
645
  for (const name of JSON_NAMES) {
496
- const p = join(cwd, name);
497
- if (existsSync(p)) {
498
- const raw = JSON.parse(readFileSync(p, "utf-8"));
646
+ const p = join2(cwd, name);
647
+ if (existsSync2(p)) {
648
+ const raw = JSON.parse(readFileSync2(p, "utf-8"));
499
649
  return decodeExplicitPluginConfig(raw);
500
650
  }
501
651
  }
502
- throw new Error(`no rig.config.{ts,mts,json} found in ${cwd}`);
652
+ throw new Error(`no rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
503
653
  }
504
654
  function decodeExplicitPluginConfig(raw) {
505
655
  const withDefaults = applyConfigDefaults(raw);
506
656
  const explicitPlugins = Array.isArray(withDefaults.plugins) ? [...withDefaults.plugins] : [];
507
- const decoded = Schema2.decodeUnknownSync(RigConfig2)({
657
+ const decoded = Schema3.decodeUnknownSync(RigConfig3)({
508
658
  ...withDefaults,
509
659
  plugins: explicitPlugins
510
660
  });
@@ -516,7 +666,7 @@ var RIG_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts", "rig.config.json"
516
666
  function findProjectConfigPath(projectRoot) {
517
667
  for (const name of RIG_CONFIG_FILENAMES) {
518
668
  const path = resolve2(projectRoot, name);
519
- if (existsSync2(path))
669
+ if (existsSync3(path))
520
670
  return path;
521
671
  }
522
672
  return null;
@@ -554,154 +704,46 @@ function resolvePluginHost(projectRoot, options = {}) {
554
704
  return promise;
555
705
  }
556
706
 
557
- // packages/core/src/task-io.ts
558
- function isRecord(value) {
559
- return typeof value === "object" && value !== null && !Array.isArray(value);
560
- }
561
- function taskText(value) {
562
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
563
- }
564
- function taskUrl(record) {
565
- const metadata = record;
566
- return taskText(metadata.url) ?? taskText(metadata.html_url) ?? taskText(metadata.webUrl);
567
- }
568
- function taskBody(record) {
569
- const metadata = record;
570
- return taskText(metadata.body) ?? taskText(metadata.description);
571
- }
572
- function taskTitle(record) {
573
- const metadata = record;
574
- return taskText(metadata.title) ?? taskText(metadata.name) ?? record.id;
575
- }
576
- function taskStringList(value) {
577
- return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
578
- }
579
- function taskDependencies(record) {
580
- const raw = record;
581
- const dependencies = taskStringList(raw.dependencies);
582
- if (dependencies.length > 0)
583
- return dependencies;
584
- const deps = taskStringList(raw.deps);
585
- return deps.length > 0 ? deps : null;
586
- }
587
- function taskParentChildDeps(record) {
588
- const raw = record;
589
- const parentChildDeps = taskStringList(raw.parentChildDeps);
590
- if (parentChildDeps.length > 0)
591
- return parentChildDeps;
592
- const parents = taskStringList(raw.parents);
593
- return parents.length > 0 ? parents : null;
594
- }
595
- function taskCreateInput(task) {
596
- const deps = Array.isArray(task.dependencies) ? task.dependencies.filter((entry) => typeof entry === "string") : Array.isArray(task.deps) ? task.deps.filter((entry) => typeof entry === "string") : [];
597
- const parents = Array.isArray(task.parents) ? task.parents.filter((entry) => typeof entry === "string") : [];
598
- return {
599
- title: taskText(task.title) ?? taskText(task.name) ?? "Untitled task",
600
- body: taskText(task.body) ?? taskText(task.description) ?? "",
601
- ...deps.length > 0 ? { deps } : {},
602
- ...parents.length > 0 ? { parents } : {},
603
- metadata: { ...task }
604
- };
707
+ // packages/core/src/capability-loaders.ts
708
+ async function buildProjectPluginHost(projectRoot) {
709
+ try {
710
+ return (await resolvePluginHost(projectRoot)).host;
711
+ } catch {
712
+ return null;
713
+ }
605
714
  }
606
- function toRigTask(record, sourceKind) {
607
- const dependencies = taskDependencies(record);
608
- const parentChildDeps = taskParentChildDeps(record);
609
- return {
610
- ...record,
611
- id: record.id,
612
- title: taskTitle(record),
613
- status: typeof record.status === "string" ? record.status : null,
614
- source: sourceKind,
615
- url: taskUrl(record),
616
- body: taskBody(record),
617
- ...dependencies ? { dependencies } : {},
618
- ...parentChildDeps ? { parentChildDeps } : {}
619
- };
715
+ async function loadCapabilityForRoot(projectRoot, capability) {
716
+ const host = await buildProjectPluginHost(projectRoot);
717
+ return host ? capability.resolve(host) : null;
620
718
  }
621
- function normalizeTaskId(value) {
622
- const trimmed = value?.trim();
623
- if (!trimmed)
624
- return;
625
- return trimmed.startsWith("#") && /^#\d+$/.test(trimmed) ? trimmed.slice(1) : trimmed;
719
+ async function requireCapabilityForRoot(projectRoot, capability, message) {
720
+ const resolved = await loadCapabilityForRoot(projectRoot, capability);
721
+ if (!resolved)
722
+ throw new Error(message);
723
+ return resolved;
626
724
  }
627
- function readTaskTitle(task) {
628
- if (!task)
629
- return null;
630
- for (const key of ["title", "summary", "name"]) {
631
- const value = task[key];
632
- if (typeof value === "string" && value.trim())
633
- return value.trim();
634
- }
635
- return null;
725
+ var INSTALLED = new Map;
726
+ function installCapability(capability, impl) {
727
+ INSTALLED.set(String(capability.id), impl);
636
728
  }
637
- async function loadTaskSource(projectRoot) {
638
- const { config, host: pluginHost } = await resolvePluginHost(projectRoot);
639
- const factory = pluginHost.resolveTaskSourceFactoryByKind(config.taskSource.kind);
640
- if (!factory) {
641
- const kinds = pluginHost.listExecutableTaskSources().map((entry) => entry.kind).join(", ") || "none";
642
- throw new Error(`No task source factory registered for kind ${config.taskSource.kind}. Registered task sources: ${kinds}.`);
643
- }
644
- return { kind: config.taskSource.kind, source: factory.factory(config.taskSource, { projectRoot }) };
645
- }
646
- var defaultLoadTaskSource = loadTaskSource;
647
- async function listTasks(projectRoot, deps = {}) {
648
- const { kind, source } = await (deps.loadTaskSource ?? loadTaskSource)(projectRoot);
649
- return (await source.list()).map((task) => toRigTask(task, kind));
650
- }
651
- var listTasksFromSource = listTasks;
652
- async function getTask(projectRoot, taskId, deps = {}) {
653
- const { kind, source } = await (deps.loadTaskSource ?? loadTaskSource)(projectRoot);
654
- const task = source.get ? await source.get(taskId) ?? null : (await source.list()).find((entry) => entry.id === taskId) ?? null;
655
- return task ? toRigTask(task, kind) : null;
656
- }
657
- var getTaskFromSource = getTask;
658
- async function listTasksForCommand(projectRoot, deps = {}) {
659
- if (deps.listTasks)
660
- return deps.listTasks(projectRoot);
661
- if (deps.loadTaskSource) {
662
- const { kind, source } = await deps.loadTaskSource(projectRoot);
663
- return (await source.list()).map((task) => ({ ...toRigTask(task, kind), source: kind }));
664
- }
665
- return listTasks(projectRoot);
666
- }
667
- async function getTaskForCommand(projectRoot, taskId, deps = {}) {
668
- if (deps.getTask)
669
- return deps.getTask(projectRoot, taskId);
670
- if (deps.loadTaskSource) {
671
- const { kind, source } = await deps.loadTaskSource(projectRoot);
672
- const task = source.get ? await source.get(taskId) : (await source.list()).find((entry) => entry.id === taskId);
673
- return task ? toRigTask(task, kind) : null;
674
- }
675
- return getTask(projectRoot, taskId);
676
- }
677
- function getTaskCreator(source) {
678
- const record = source;
679
- if (typeof record.createTask === "function")
680
- return record.createTask.bind(source);
681
- if (typeof record.create === "function")
682
- return (task) => record.create?.(taskCreateInput(task));
683
- return null;
729
+ function clearInstalledCapability(capability) {
730
+ INSTALLED.delete(String(capability.id));
731
+ }
732
+ function getInstalledCapability(capability) {
733
+ return INSTALLED.get(String(capability.id)) ?? null;
684
734
  }
685
- async function createTask(projectRoot, task, deps = {}) {
686
- const { kind, source } = await (deps.loadTaskSource ?? loadTaskSource)(projectRoot);
687
- const creator = getTaskCreator(source);
688
- if (!creator)
689
- throw new Error(`The configured ${kind} task source does not expose a task creation API.`);
690
- const result = await creator(task);
691
- const taskId = typeof result === "string" ? result : isRecord(result) && typeof result.id === "string" ? result.id : null;
692
- return { taskId, source: kind, result };
735
+ function requireInstalledCapability(capability, message) {
736
+ const impl = getInstalledCapability(capability);
737
+ if (!impl)
738
+ throw new Error(message);
739
+ return impl;
693
740
  }
694
741
  export {
695
- readTaskTitle,
696
- normalizeTaskId,
697
- loadTaskSource,
698
- listTasksFromSource,
699
- listTasksForCommand,
700
- listTasks,
701
- getTaskFromSource,
702
- getTaskForCommand,
703
- getTaskCreator,
704
- getTask,
705
- defaultLoadTaskSource,
706
- createTask
742
+ requireInstalledCapability,
743
+ requireCapabilityForRoot,
744
+ loadCapabilityForRoot,
745
+ installCapability,
746
+ getInstalledCapability,
747
+ clearInstalledCapability,
748
+ buildProjectPluginHost
707
749
  };