@h-rig/core 0.0.6-alpha.17 → 0.0.6-alpha.171
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/src/agent-role-registry.d.ts +4 -0
- package/dist/src/agent-role-registry.js +27 -0
- package/dist/src/authority-paths.d.ts +15 -0
- package/dist/src/authority-paths.js +80 -0
- package/dist/src/baked-secrets.d.ts +6 -0
- package/dist/src/baked-secrets.js +121 -0
- package/dist/src/build-time-config.d.ts +12 -0
- package/dist/src/build-time-config.js +25 -0
- package/dist/src/build-time-config.macro.d.ts +1 -0
- package/dist/src/capability-loaders.d.ts +51 -0
- package/dist/src/capability-loaders.js +758 -0
- package/dist/src/capability.d.ts +79 -0
- package/dist/src/capability.js +63 -0
- package/dist/src/checkout-root.d.ts +1 -0
- package/dist/src/checkout-root.js +30 -0
- package/dist/src/config-env.d.ts +4 -0
- package/dist/src/config-env.js +23 -0
- package/dist/src/config.d.ts +3 -0
- package/dist/src/config.js +44 -0
- package/dist/src/declarative-config.d.ts +14 -0
- package/dist/src/declarative-config.js +82 -0
- package/dist/src/default-kernel.d.ts +1 -0
- package/dist/src/default-kernel.js +12 -0
- package/dist/src/define-config.d.ts +20 -0
- package/dist/src/define-config.js +28 -15
- package/dist/src/define-plugin.d.ts +13 -0
- package/dist/src/define-plugin.js +4 -43
- package/dist/src/embedded-plugins.d.ts +59 -0
- package/dist/src/embedded-plugins.js +22 -0
- package/dist/src/exec.d.ts +13 -0
- package/dist/src/exec.js +101 -0
- package/dist/src/harness-paths.d.ts +18 -0
- package/dist/src/harness-paths.js +141 -0
- package/dist/src/hook-materializer.d.ts +72 -0
- package/dist/src/hook-materializer.js +281 -0
- package/dist/src/hook-protocol.d.ts +2 -0
- package/dist/src/hook-protocol.js +462 -0
- package/dist/src/hook-runner.d.ts +48 -0
- package/dist/src/hook-runner.js +756 -0
- package/dist/src/hook-runtime.d.ts +52 -0
- package/dist/src/hook-runtime.js +462 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.js +210 -2499
- package/dist/src/json-files.d.ts +9 -0
- package/dist/src/json-files.js +125 -0
- package/dist/src/kernel-boot.d.ts +2 -0
- package/dist/src/kernel-boot.js +10 -0
- package/dist/src/kernel-entrypoint.d.ts +22 -0
- package/dist/src/kernel-entrypoint.js +548 -0
- package/dist/src/kernel-plugin-abi.d.ts +1 -0
- package/dist/src/kernel-plugin-abi.js +1 -0
- package/dist/src/kernel-resolver.d.ts +2 -0
- package/dist/src/kernel-resolver.js +6 -0
- package/dist/src/layout.d.ts +10 -0
- package/dist/src/layout.js +144 -0
- package/dist/src/load-config.d.ts +2 -0
- package/dist/src/load-config.js +423 -30
- package/dist/src/placement.d.ts +50 -0
- package/dist/src/placement.js +996 -0
- package/dist/src/plugin-host-context.d.ts +66 -0
- package/dist/src/plugin-host-context.js +1292 -0
- package/dist/src/plugin-host-registries.d.ts +31 -0
- package/dist/src/plugin-host-registries.js +79 -0
- package/dist/src/plugin-host.d.ts +77 -0
- package/dist/src/plugin-host.js +127 -63
- package/dist/src/plugin-runtime.d.ts +173 -0
- package/dist/src/profile-ops.d.ts +9 -0
- package/dist/src/profile-ops.js +252 -0
- package/dist/src/project-plugins.d.ts +63 -0
- package/dist/src/project-plugins.js +793 -0
- package/dist/src/remote-config.d.ts +183 -0
- package/dist/src/remote-config.js +574 -0
- package/dist/src/root-resolver.d.ts +5 -0
- package/dist/src/root-resolver.js +69 -0
- package/dist/src/run-provisioning.d.ts +58 -0
- package/dist/src/run-provisioning.js +128 -0
- package/dist/src/runtime-context.d.ts +20 -0
- package/dist/src/runtime-context.js +257 -0
- package/dist/src/runtime-events.d.ts +44 -0
- package/dist/src/runtime-events.js +212 -0
- package/dist/src/runtime-overlay.d.ts +11 -0
- package/dist/src/runtime-overlay.js +71 -0
- package/dist/src/runtime-paths.d.ts +21 -0
- package/dist/src/runtime-paths.js +181 -0
- package/dist/src/runtime-provisioning-env.d.ts +5 -0
- package/dist/src/runtime-provisioning-env.js +217 -0
- package/dist/src/runtime-runner-context.d.ts +12 -0
- package/dist/src/runtime-runner-context.js +1 -0
- package/dist/src/safe-identifiers.d.ts +44 -0
- package/dist/src/safe-identifiers.js +96 -0
- package/dist/src/scope-rules.d.ts +4 -0
- package/dist/src/scope-rules.js +21 -0
- package/dist/src/server-paths.d.ts +26 -0
- package/dist/src/server-paths.js +308 -0
- package/dist/src/setup-version.d.ts +3 -0
- package/dist/src/setup-version.js +14 -0
- package/dist/src/task-record-reader.d.ts +3 -0
- package/dist/src/task-record-reader.js +9 -0
- package/dist/src/validator-registry.d.ts +27 -0
- package/dist/src/validator-registry.js +64 -0
- package/package.json +166 -10
- package/dist/src/engineReadModelReducer.js +0 -1780
- package/dist/src/rig-init-builder.js +0 -57
- package/dist/src/rigSelectors.js +0 -293
- package/dist/src/taskGraph.js +0 -64
- package/dist/src/taskGraphCodes.js +0 -26
- package/dist/src/taskGraphLayout.js +0 -374
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { RegisteredTaskSource, RigConfig, TaskFieldExtension } from "@rig/contracts";
|
|
2
|
+
import type { PluginHost } from "./plugin-host";
|
|
3
|
+
import type { TaskSourceFactoryContext } from "./plugin-runtime";
|
|
4
|
+
export interface TaskSourceRegistry {
|
|
5
|
+
register(s: RegisteredTaskSource): void;
|
|
6
|
+
resolveById(id: string): RegisteredTaskSource;
|
|
7
|
+
resolveByKind(kind: string): RegisteredTaskSource;
|
|
8
|
+
list(): readonly RegisteredTaskSource[];
|
|
9
|
+
}
|
|
10
|
+
export declare function createTaskSourceRegistry(): TaskSourceRegistry;
|
|
11
|
+
/**
|
|
12
|
+
* Instantiate the task-source adapter selected by `config.taskSource.kind`
|
|
13
|
+
* from executable task-source factories contributed by loaded plugins.
|
|
14
|
+
*
|
|
15
|
+
* First-party adapters are not special-cased here: projects that use the
|
|
16
|
+
* standard GitHub Issues or files sources get those factories by loading
|
|
17
|
+
* `standard()` in `rig.config.ts`, exactly like any third-party adapter.
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildTaskSourceRegistry(config: RigConfig, pluginHost?: PluginHost, context?: TaskSourceFactoryContext): TaskSourceRegistry;
|
|
20
|
+
export interface TaskFieldRegistry {
|
|
21
|
+
get(id: string): TaskFieldExtension | undefined;
|
|
22
|
+
list(): readonly TaskFieldExtension[];
|
|
23
|
+
fieldNames(): readonly string[];
|
|
24
|
+
validateTaskFields(task: Record<string, unknown>): {
|
|
25
|
+
ok: true;
|
|
26
|
+
} | {
|
|
27
|
+
ok: false;
|
|
28
|
+
errors: string[];
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export declare function createTaskFieldRegistry(extensions: readonly TaskFieldExtension[]): TaskFieldRegistry;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/core/src/plugin-host-registries.ts
|
|
3
|
+
function createTaskSourceRegistry() {
|
|
4
|
+
const byId = new Map;
|
|
5
|
+
const order = [];
|
|
6
|
+
return {
|
|
7
|
+
register(s) {
|
|
8
|
+
if (byId.has(s.id))
|
|
9
|
+
throw new Error(`task source already registered: ${s.id}`);
|
|
10
|
+
byId.set(s.id, s);
|
|
11
|
+
order.push(s);
|
|
12
|
+
},
|
|
13
|
+
resolveById(id) {
|
|
14
|
+
const s = byId.get(id);
|
|
15
|
+
if (!s)
|
|
16
|
+
throw new Error(`task source not registered: ${id}`);
|
|
17
|
+
return s;
|
|
18
|
+
},
|
|
19
|
+
resolveByKind(kind) {
|
|
20
|
+
for (const s of order)
|
|
21
|
+
if (s.kind === kind)
|
|
22
|
+
return s;
|
|
23
|
+
throw new Error(`no task source registered for kind: ${kind}`);
|
|
24
|
+
},
|
|
25
|
+
list: () => order
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function formatRegisteredKinds(pluginHost) {
|
|
29
|
+
const kinds = pluginHost ? pluginHost.listExecutableTaskSources().map((source) => source.kind) : [];
|
|
30
|
+
return kinds.length > 0 ? kinds.join(", ") : "none";
|
|
31
|
+
}
|
|
32
|
+
function buildTaskSourceRegistry(config, pluginHost, context) {
|
|
33
|
+
const registry = createTaskSourceRegistry();
|
|
34
|
+
const taskSourceConfig = config.taskSource;
|
|
35
|
+
const factory = pluginHost?.resolveTaskSourceFactoryByKind(taskSourceConfig.kind);
|
|
36
|
+
if (!factory) {
|
|
37
|
+
throw new Error(`No task source factory registered for kind "${taskSourceConfig.kind}". ` + `Registered kinds: ${formatRegisteredKinds(pluginHost)}. ` + "Load a plugin that contributes an executable task source factory for this kind.");
|
|
38
|
+
}
|
|
39
|
+
registry.register(factory.factory(taskSourceConfig, context ? { ...context, rigConfig: config } : undefined));
|
|
40
|
+
return registry;
|
|
41
|
+
}
|
|
42
|
+
function createTaskFieldRegistry(extensions) {
|
|
43
|
+
const byId = new Map;
|
|
44
|
+
for (const e of extensions) {
|
|
45
|
+
if (byId.has(e.id))
|
|
46
|
+
throw new Error(`task field extension already registered: ${e.id}`);
|
|
47
|
+
byId.set(e.id, e);
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
get: (id) => byId.get(id),
|
|
51
|
+
list: () => Array.from(byId.values()),
|
|
52
|
+
fieldNames: () => Array.from(byId.values()).map((e) => e.fieldName),
|
|
53
|
+
validateTaskFields(task) {
|
|
54
|
+
const errors = [];
|
|
55
|
+
for (const ext of byId.values()) {
|
|
56
|
+
let schema;
|
|
57
|
+
try {
|
|
58
|
+
schema = JSON.parse(ext.schemaJson);
|
|
59
|
+
} catch {
|
|
60
|
+
errors.push(`task field "${ext.id}": schemaJson is not valid JSON`);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const isRequired = typeof schema === "object" && schema !== null && schema.required === true;
|
|
64
|
+
if (!isRequired)
|
|
65
|
+
continue;
|
|
66
|
+
const value = task[ext.fieldName];
|
|
67
|
+
if (value === undefined || value === null || value === "") {
|
|
68
|
+
errors.push(`task field "${ext.fieldName}" (from extension "${ext.id}") is required but missing`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return errors.length === 0 ? { ok: true } : { ok: false, errors };
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
createTaskSourceRegistry,
|
|
77
|
+
createTaskFieldRegistry,
|
|
78
|
+
buildTaskSourceRegistry
|
|
79
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { AgentRoleRegistration, BlockerClassifierRegistration, CliCommandRegistration, HookRegistration, PanelRegistration, ProductCapabilityRegistration, RepoSourceRegistration, SkillRegistration, Stage, StageMutation, StageRun, TaskFieldExtension, TaskSourceRegistration, ValidatorRegistration } from "@rig/contracts";
|
|
2
|
+
import type { BlockerClassifierEntry, CliCommand, FeatureCapability, Panel, RigPlugin, SessionExtensionEntry, SeedEntrypoint, TaskSource, Validator } from "./plugin-runtime";
|
|
3
|
+
export interface PluginHost {
|
|
4
|
+
getValidator(id: string): ValidatorRegistration | undefined;
|
|
5
|
+
getHook(id: string): HookRegistration | undefined;
|
|
6
|
+
getSkill(id: string): SkillRegistration | undefined;
|
|
7
|
+
getRepoSource(id: string): RepoSourceRegistration | undefined;
|
|
8
|
+
getAgentRole(id: string): AgentRoleRegistration | undefined;
|
|
9
|
+
getTaskFieldExtension(id: string): TaskFieldExtension | undefined;
|
|
10
|
+
getTaskSource(id: string): TaskSourceRegistration | undefined;
|
|
11
|
+
getCliCommand(id: string): CliCommandRegistration | undefined;
|
|
12
|
+
getCapability(id: string): ProductCapabilityRegistration | undefined;
|
|
13
|
+
getPanel(id: string): PanelRegistration | undefined;
|
|
14
|
+
getBlockerClassifier(id: string): BlockerClassifierRegistration | undefined;
|
|
15
|
+
listValidators(): readonly ValidatorRegistration[];
|
|
16
|
+
listHooks(): readonly HookRegistration[];
|
|
17
|
+
listSkills(): readonly SkillRegistration[];
|
|
18
|
+
listRepoSources(): readonly RepoSourceRegistration[];
|
|
19
|
+
listAgentRoles(): readonly AgentRoleRegistration[];
|
|
20
|
+
listTaskFieldExtensions(): readonly TaskFieldExtension[];
|
|
21
|
+
listTaskSources(): readonly TaskSourceRegistration[];
|
|
22
|
+
listCliCommands(): readonly CliCommandRegistration[];
|
|
23
|
+
listCapabilities(): readonly ProductCapabilityRegistration[];
|
|
24
|
+
listPanels(): readonly PanelRegistration[];
|
|
25
|
+
listBlockerClassifiers(): readonly BlockerClassifierRegistration[];
|
|
26
|
+
listStages(): readonly Stage[];
|
|
27
|
+
/**
|
|
28
|
+
* Stage mutations contributed by all loaded plugins, flattened in load order.
|
|
29
|
+
* The kernel resolves these (+ the default-lifecycle stages) into the run
|
|
30
|
+
* pipeline — this is the wire that makes "every plugin mutates the lifecycle"
|
|
31
|
+
* real (drift pre-merge gate, closure observer, reclassify observer).
|
|
32
|
+
*/
|
|
33
|
+
listStageMutations(): readonly StageMutation[];
|
|
34
|
+
/**
|
|
35
|
+
* Executable stage implementations contributed by plugins, derived from
|
|
36
|
+
* `contributes.stages` entries that carry a `run`, keyed by stage id. The
|
|
37
|
+
* kernel's stage runner uses these to execute plugin-contributed stages
|
|
38
|
+
* inserted via stageMutations.
|
|
39
|
+
*/
|
|
40
|
+
listStageExecutors(): Readonly<Record<string, StageRun>>;
|
|
41
|
+
/**
|
|
42
|
+
* Executable validators contributed by plugins (single-channel: the same
|
|
43
|
+
* `contributes.validators` entries, which carry their `run`).
|
|
44
|
+
*/
|
|
45
|
+
listExecutableValidators(): readonly Validator[];
|
|
46
|
+
/**
|
|
47
|
+
* Executable task source factories contributed by plugins. Used by the
|
|
48
|
+
* runtime's `buildTaskSourceRegistry` to instantiate non-standard task
|
|
49
|
+
* source kinds (Linear, Jira, custom) declared by plugins.
|
|
50
|
+
*/
|
|
51
|
+
listExecutableTaskSources(): readonly TaskSource[];
|
|
52
|
+
listExecutableCapabilities(): readonly FeatureCapability[];
|
|
53
|
+
listExecutablePanels(): readonly Panel[];
|
|
54
|
+
listExecutableBlockerClassifiers(): readonly BlockerClassifierEntry[];
|
|
55
|
+
listExecutableCliCommands(): readonly CliCommand[];
|
|
56
|
+
/**
|
|
57
|
+
* Executable session-extension installers contributed by plugins. The
|
|
58
|
+
* agent-session host (rig-host) resolves these and invokes each `install(api)`
|
|
59
|
+
* at `createAgentSession` time, so the run lifecycle (and any other
|
|
60
|
+
* session-time extension) is resolved from the explicit plugin collection
|
|
61
|
+
* rather than injected directly by a leaf.
|
|
62
|
+
*/
|
|
63
|
+
listSessionExtensions(): readonly SessionExtensionEntry[];
|
|
64
|
+
listSeedEntrypoints(): readonly SeedEntrypoint[];
|
|
65
|
+
resolveSeedEntrypointByBasename(basename: string): SeedEntrypoint | undefined;
|
|
66
|
+
resolveSeedEntrypointByWorkerArg(workerArg: string): SeedEntrypoint | undefined;
|
|
67
|
+
resolveInsidePtySeedEntrypoint(): SeedEntrypoint | undefined;
|
|
68
|
+
resolveExecutableCliCommand(requested: string): CliCommand | undefined;
|
|
69
|
+
resolveDefaultRootCliCommand(): CliCommand | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* Look up an executable task source factory by its `kind` (the value in
|
|
72
|
+
* `config.taskSource.kind`). Returns undefined when no plugin provides
|
|
73
|
+
* a factory for that kind.
|
|
74
|
+
*/
|
|
75
|
+
resolveTaskSourceFactoryByKind(kind: string): TaskSource | undefined;
|
|
76
|
+
}
|
|
77
|
+
export declare function createPluginHost(plugins: readonly RigPlugin[]): PluginHost;
|
package/dist/src/plugin-host.js
CHANGED
|
@@ -21,49 +21,8 @@ function assertUniquePluginNames(plugins) {
|
|
|
21
21
|
seen.add(plugin.name);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
function assertRuntimeMatchesMetadata(plugin) {
|
|
25
|
-
const declaredValidators = new Map((plugin.contributes?.validators ?? []).map((validator) => [validator.id, validator]));
|
|
26
|
-
const runtimeValidators = new Map((plugin.__runtime?.validators ?? []).map((validator) => [validator.id, validator]));
|
|
27
|
-
for (const validator of runtimeValidators.values()) {
|
|
28
|
-
const metadata = declaredValidators.get(validator.id);
|
|
29
|
-
if (!metadata) {
|
|
30
|
-
throw new Error(`plugin "${plugin.name}" executable validator "${validator.id}" has no matching metadata entry in contributes.validators`);
|
|
31
|
-
}
|
|
32
|
-
if (metadata.category !== validator.category) {
|
|
33
|
-
throw new Error(`plugin "${plugin.name}" executable validator "${validator.id}" category "${validator.category}" does not match metadata category "${metadata.category}"`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
if (plugin.__runtime?.validators) {
|
|
37
|
-
for (const validator of declaredValidators.values()) {
|
|
38
|
-
if (!runtimeValidators.has(validator.id)) {
|
|
39
|
-
throw new Error(`plugin "${plugin.name}" validator metadata "${validator.id}" has no runtime implementation`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
const declaredTaskSources = new Map((plugin.contributes?.taskSources ?? []).map((source) => [source.id, source]));
|
|
44
|
-
const runtimeTaskSources = new Map((plugin.__runtime?.taskSources ?? []).map((source) => [source.id, source]));
|
|
45
|
-
for (const source of runtimeTaskSources.values()) {
|
|
46
|
-
const metadata = declaredTaskSources.get(source.id);
|
|
47
|
-
if (!metadata) {
|
|
48
|
-
throw new Error(`plugin "${plugin.name}" executable task source "${source.id}" has no matching metadata entry in contributes.taskSources`);
|
|
49
|
-
}
|
|
50
|
-
if (metadata.kind !== source.kind) {
|
|
51
|
-
throw new Error(`plugin "${plugin.name}" executable task source "${source.id}" kind "${source.kind}" does not match metadata kind "${metadata.kind}"`);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (plugin.__runtime?.taskSources) {
|
|
55
|
-
for (const source of declaredTaskSources.values()) {
|
|
56
|
-
if (!runtimeTaskSources.has(source.id)) {
|
|
57
|
-
throw new Error(`plugin "${plugin.name}" task source metadata "${source.id}" has no runtime implementation`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
24
|
function createPluginHost(plugins) {
|
|
63
25
|
assertUniquePluginNames(plugins);
|
|
64
|
-
for (const plugin of plugins) {
|
|
65
|
-
assertRuntimeMatchesMetadata(plugin);
|
|
66
|
-
}
|
|
67
26
|
const validators = [];
|
|
68
27
|
const hooks = [];
|
|
69
28
|
const skills = [];
|
|
@@ -72,19 +31,19 @@ function createPluginHost(plugins) {
|
|
|
72
31
|
const taskFieldExtensions = [];
|
|
73
32
|
const taskSources = [];
|
|
74
33
|
const cliCommands = [];
|
|
75
|
-
const
|
|
76
|
-
const
|
|
34
|
+
const capabilities = [];
|
|
35
|
+
const panels = [];
|
|
36
|
+
const blockerClassifiers = [];
|
|
37
|
+
const sessionExtensions = [];
|
|
38
|
+
const seedEntrypoints = [];
|
|
39
|
+
const stages = [];
|
|
40
|
+
const stageMutations = [];
|
|
41
|
+
const stageExecutors = {};
|
|
77
42
|
for (const plugin of plugins) {
|
|
78
43
|
const c = plugin.contributes;
|
|
79
44
|
if (!c)
|
|
80
45
|
continue;
|
|
81
46
|
const pluginName = plugin.name;
|
|
82
|
-
if (plugin.__runtime?.validators) {
|
|
83
|
-
executableValidators.push(...plugin.__runtime.validators.map((item) => ({ item, pluginName })));
|
|
84
|
-
}
|
|
85
|
-
if (plugin.__runtime?.taskSources) {
|
|
86
|
-
executableTaskSources.push(...plugin.__runtime.taskSources.map((item) => ({ item, pluginName })));
|
|
87
|
-
}
|
|
88
47
|
if (c.validators)
|
|
89
48
|
validators.push(...c.validators.map((item) => ({ item, pluginName })));
|
|
90
49
|
if (c.hooks)
|
|
@@ -101,17 +60,25 @@ function createPluginHost(plugins) {
|
|
|
101
60
|
taskSources.push(...c.taskSources.map((item) => ({ item, pluginName })));
|
|
102
61
|
if (c.cliCommands)
|
|
103
62
|
cliCommands.push(...c.cliCommands.map((item) => ({ item, pluginName })));
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (
|
|
111
|
-
|
|
63
|
+
if (c.capabilities)
|
|
64
|
+
capabilities.push(...c.capabilities.map((item) => ({ item, pluginName })));
|
|
65
|
+
if (c.panels)
|
|
66
|
+
panels.push(...c.panels.map((item) => ({ item, pluginName })));
|
|
67
|
+
if (c.blockerClassifiers)
|
|
68
|
+
blockerClassifiers.push(...c.blockerClassifiers.map((item) => ({ item, pluginName })));
|
|
69
|
+
if (c.sessionExtensions)
|
|
70
|
+
sessionExtensions.push(...c.sessionExtensions.map((item) => ({ item, pluginName })));
|
|
71
|
+
if (c.seedEntrypoints)
|
|
72
|
+
seedEntrypoints.push(...c.seedEntrypoints.map((item) => ({ item, pluginName })));
|
|
73
|
+
if (c.stageMutations)
|
|
74
|
+
stageMutations.push(...c.stageMutations.map((item) => ({ item, pluginName })));
|
|
75
|
+
if (c.stages) {
|
|
76
|
+
for (const stage of c.stages) {
|
|
77
|
+
stages.push({ item: stage, pluginName });
|
|
78
|
+
if (stage.run)
|
|
79
|
+
stageExecutors[stage.id] = stage.run;
|
|
80
|
+
}
|
|
112
81
|
}
|
|
113
|
-
taskSourceFactoryByKind.set(item.kind, item);
|
|
114
|
-
taskSourceKindRegistrant.set(item.kind, pluginName);
|
|
115
82
|
}
|
|
116
83
|
const validatorMap = indexById(validators, "validator");
|
|
117
84
|
const hookMap = indexById(hooks, "hook");
|
|
@@ -121,6 +88,52 @@ function createPluginHost(plugins) {
|
|
|
121
88
|
const taskFieldExtMap = indexById(taskFieldExtensions, "taskFieldExtension");
|
|
122
89
|
const taskSourceMap = indexById(taskSources, "taskSource");
|
|
123
90
|
const cliCommandMap = indexById(cliCommands, "cliCommand");
|
|
91
|
+
const capabilityMap = indexById(capabilities, "capability");
|
|
92
|
+
const panelMap = indexById(panels, "panel");
|
|
93
|
+
const blockerClassifierMap = indexById(blockerClassifiers, "blockerClassifier");
|
|
94
|
+
indexById(sessionExtensions, "sessionExtension");
|
|
95
|
+
indexById(seedEntrypoints, "seedEntrypoint");
|
|
96
|
+
const taskSourceFactoryByKind = new Map;
|
|
97
|
+
const taskSourceKindRegistrant = new Map;
|
|
98
|
+
for (const { item, pluginName } of taskSources) {
|
|
99
|
+
if (taskSourceFactoryByKind.has(item.kind)) {
|
|
100
|
+
throw new Error(`duplicate task source kind "${item.kind}": registered by plugins "${taskSourceKindRegistrant.get(item.kind)}" and "${pluginName}"`);
|
|
101
|
+
}
|
|
102
|
+
taskSourceFactoryByKind.set(item.kind, item);
|
|
103
|
+
taskSourceKindRegistrant.set(item.kind, pluginName);
|
|
104
|
+
}
|
|
105
|
+
const seedEntrypointByBasename = new Map;
|
|
106
|
+
const seedEntrypointByWorkerArg = new Map;
|
|
107
|
+
let insidePtySeedEntrypoint;
|
|
108
|
+
const registerSeedEntrypointSelector = (map, selectorKind, selector, contribution) => {
|
|
109
|
+
const existing = map.get(selector);
|
|
110
|
+
if (existing) {
|
|
111
|
+
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}"`);
|
|
112
|
+
}
|
|
113
|
+
map.set(selector, contribution);
|
|
114
|
+
};
|
|
115
|
+
for (const contribution of seedEntrypoints) {
|
|
116
|
+
const entrypoint = contribution.item;
|
|
117
|
+
let selectorCount = 0;
|
|
118
|
+
if (entrypoint.basename) {
|
|
119
|
+
selectorCount += 1;
|
|
120
|
+
registerSeedEntrypointSelector(seedEntrypointByBasename, "basename", entrypoint.basename, contribution);
|
|
121
|
+
}
|
|
122
|
+
if (entrypoint.workerArg) {
|
|
123
|
+
selectorCount += 1;
|
|
124
|
+
registerSeedEntrypointSelector(seedEntrypointByWorkerArg, "workerArg", entrypoint.workerArg, contribution);
|
|
125
|
+
}
|
|
126
|
+
if (entrypoint.insidePty) {
|
|
127
|
+
selectorCount += 1;
|
|
128
|
+
if (insidePtySeedEntrypoint) {
|
|
129
|
+
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}"`);
|
|
130
|
+
}
|
|
131
|
+
insidePtySeedEntrypoint = contribution;
|
|
132
|
+
}
|
|
133
|
+
if (selectorCount === 0) {
|
|
134
|
+
throw new Error(`seed entrypoint "${entrypoint.id}" from plugin "${contribution.pluginName}" must declare at least one selector (basename, workerArg, or insidePty)`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
124
137
|
const allValidators = validators.map((c) => c.item);
|
|
125
138
|
const allHooks = hooks.map((c) => c.item);
|
|
126
139
|
const allSkills = skills.map((c) => c.item);
|
|
@@ -129,8 +142,39 @@ function createPluginHost(plugins) {
|
|
|
129
142
|
const allTaskFieldExtensions = taskFieldExtensions.map((c) => c.item);
|
|
130
143
|
const allTaskSources = taskSources.map((c) => c.item);
|
|
131
144
|
const allCliCommands = cliCommands.map((c) => c.item);
|
|
132
|
-
const
|
|
133
|
-
const
|
|
145
|
+
const allStageMutations = stageMutations.map((c) => c.item);
|
|
146
|
+
const allStages = stages.map((c) => c.item);
|
|
147
|
+
const allCapabilities = capabilities.map((c) => c.item);
|
|
148
|
+
const allPanels = panels.map((c) => c.item);
|
|
149
|
+
const allBlockerClassifiers = blockerClassifiers.map((c) => c.item);
|
|
150
|
+
const allSessionExtensions = sessionExtensions.map((c) => c.item);
|
|
151
|
+
const allSeedEntrypoints = seedEntrypoints.map((c) => c.item);
|
|
152
|
+
const executableCliCommandByName = new Map;
|
|
153
|
+
const registerExecutableCliCommandSelector = (selector, contribution) => {
|
|
154
|
+
const existing = executableCliCommandByName.get(selector);
|
|
155
|
+
if (existing && existing.item.id !== contribution.item.id) {
|
|
156
|
+
throw new Error(`duplicate executable CLI selector "${selector}" registered by command "${existing.item.id}" from plugin "${existing.pluginName}" and command "${contribution.item.id}" from plugin "${contribution.pluginName}"`);
|
|
157
|
+
}
|
|
158
|
+
executableCliCommandByName.set(selector, contribution);
|
|
159
|
+
};
|
|
160
|
+
for (const contribution of cliCommands) {
|
|
161
|
+
const command = contribution.item;
|
|
162
|
+
const family = command.family ?? command.id;
|
|
163
|
+
registerExecutableCliCommandSelector(command.id, contribution);
|
|
164
|
+
registerExecutableCliCommandSelector(family, contribution);
|
|
165
|
+
for (const alias of command.aliases ?? []) {
|
|
166
|
+
registerExecutableCliCommandSelector(alias, contribution);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
let defaultRootCliCommand;
|
|
170
|
+
for (const contribution of cliCommands) {
|
|
171
|
+
if (!contribution.item.rootDefault)
|
|
172
|
+
continue;
|
|
173
|
+
if (defaultRootCliCommand) {
|
|
174
|
+
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}"`);
|
|
175
|
+
}
|
|
176
|
+
defaultRootCliCommand = contribution;
|
|
177
|
+
}
|
|
134
178
|
return {
|
|
135
179
|
getValidator: (id) => validatorMap.get(id),
|
|
136
180
|
getHook: (id) => hookMap.get(id),
|
|
@@ -140,6 +184,9 @@ function createPluginHost(plugins) {
|
|
|
140
184
|
getTaskFieldExtension: (id) => taskFieldExtMap.get(id),
|
|
141
185
|
getTaskSource: (id) => taskSourceMap.get(id),
|
|
142
186
|
getCliCommand: (id) => cliCommandMap.get(id),
|
|
187
|
+
getCapability: (id) => capabilityMap.get(id),
|
|
188
|
+
getPanel: (id) => panelMap.get(id),
|
|
189
|
+
getBlockerClassifier: (id) => blockerClassifierMap.get(id),
|
|
143
190
|
listValidators: () => allValidators,
|
|
144
191
|
listHooks: () => allHooks,
|
|
145
192
|
listSkills: () => allSkills,
|
|
@@ -148,8 +195,25 @@ function createPluginHost(plugins) {
|
|
|
148
195
|
listTaskFieldExtensions: () => allTaskFieldExtensions,
|
|
149
196
|
listTaskSources: () => allTaskSources,
|
|
150
197
|
listCliCommands: () => allCliCommands,
|
|
151
|
-
|
|
152
|
-
|
|
198
|
+
listCapabilities: () => allCapabilities,
|
|
199
|
+
listPanels: () => allPanels,
|
|
200
|
+
listBlockerClassifiers: () => allBlockerClassifiers,
|
|
201
|
+
listStages: () => allStages,
|
|
202
|
+
listStageMutations: () => allStageMutations,
|
|
203
|
+
listStageExecutors: () => stageExecutors,
|
|
204
|
+
listExecutableValidators: () => allValidators.filter((v) => typeof v.run === "function"),
|
|
205
|
+
listExecutableTaskSources: () => allTaskSources,
|
|
206
|
+
listExecutableCapabilities: () => allCapabilities.filter((c) => typeof c.run === "function"),
|
|
207
|
+
listExecutablePanels: () => allPanels.filter((p) => typeof p.produce === "function"),
|
|
208
|
+
listExecutableBlockerClassifiers: () => allBlockerClassifiers,
|
|
209
|
+
listExecutableCliCommands: () => allCliCommands,
|
|
210
|
+
listSessionExtensions: () => allSessionExtensions,
|
|
211
|
+
listSeedEntrypoints: () => allSeedEntrypoints,
|
|
212
|
+
resolveSeedEntrypointByBasename: (value) => seedEntrypointByBasename.get(value)?.item,
|
|
213
|
+
resolveSeedEntrypointByWorkerArg: (value) => seedEntrypointByWorkerArg.get(value)?.item,
|
|
214
|
+
resolveInsidePtySeedEntrypoint: () => insidePtySeedEntrypoint?.item,
|
|
215
|
+
resolveExecutableCliCommand: (requested) => executableCliCommandByName.get(requested)?.item,
|
|
216
|
+
resolveDefaultRootCliCommand: () => defaultRootCliCommand?.item,
|
|
153
217
|
resolveTaskSourceFactoryByKind: (kind) => taskSourceFactoryByKind.get(kind)
|
|
154
218
|
};
|
|
155
219
|
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import type { AgentRoleRegistration, BlockerClassifierRegistration, CapabilityReplacementSpec, CapabilityTag, CliCommandRegistration, HookImplementation, HookRegistration, PanelRegistration, ProductCapabilityRegistration, RegisteredTaskSource, RepoSourceRegistration, RigConfig, SeedEntrypointRegistration, SessionExtensionRegistration, SkillRegistration, Stage, StageMutation, StageRun, TaskFieldExtension, TaskSourceConfig, TaskSourceRegistration, ValidatorRegistration } from "@rig/contracts";
|
|
2
|
+
export interface ValidatorResult {
|
|
3
|
+
id: string;
|
|
4
|
+
passed: boolean;
|
|
5
|
+
summary: string;
|
|
6
|
+
details?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ValidatorContext {
|
|
9
|
+
taskId: string;
|
|
10
|
+
workspaceRoot: string;
|
|
11
|
+
scope: readonly string[];
|
|
12
|
+
monorepoRoot?: string;
|
|
13
|
+
artifactsDir?: string;
|
|
14
|
+
taskConfig?: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface Validator extends ValidatorRegistration {
|
|
17
|
+
run(ctx: ValidatorContext): Promise<ValidatorResult>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Project context handed to task-source factories at instantiation. The
|
|
21
|
+
* server process's cwd is NOT necessarily the project root (workspace-spawned
|
|
22
|
+
* servers run from the engine checkout), so factories that touch the
|
|
23
|
+
* filesystem must resolve relative config paths against `projectRoot`,
|
|
24
|
+
* never cwd.
|
|
25
|
+
*/
|
|
26
|
+
export interface TaskSourceFactoryContext {
|
|
27
|
+
projectRoot: string;
|
|
28
|
+
/**
|
|
29
|
+
* Full project config for adapters that need source-adjacent top-level
|
|
30
|
+
* settings (for example github.projects). Factories should still treat
|
|
31
|
+
* TaskSourceConfig as the primary adapter config.
|
|
32
|
+
*/
|
|
33
|
+
rigConfig?: RigConfig;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Task-source contribution: metadata (`id`, `kind`) plus the `factory` that
|
|
37
|
+
* turns a TaskSourceConfig into a RegisteredTaskSource. `kind` is matched
|
|
38
|
+
* against `config.taskSource.kind` at boot; duplicate kinds throw in
|
|
39
|
+
* `createPluginHost`.
|
|
40
|
+
*/
|
|
41
|
+
export interface TaskSource extends TaskSourceRegistration {
|
|
42
|
+
factory(config: TaskSourceConfig, context?: TaskSourceFactoryContext): RegisteredTaskSource;
|
|
43
|
+
}
|
|
44
|
+
export type FeatureCapability = ProductCapabilityRegistration;
|
|
45
|
+
/** @deprecated single-channel rename — use {@link FeatureCapability}. */
|
|
46
|
+
export interface Panel extends PanelRegistration {
|
|
47
|
+
produce?: (context?: unknown) => Promise<unknown> | unknown;
|
|
48
|
+
}
|
|
49
|
+
export interface BlockerClassifierEntry extends BlockerClassifierRegistration {
|
|
50
|
+
classify(input: unknown): Promise<unknown> | unknown;
|
|
51
|
+
}
|
|
52
|
+
/** @deprecated single-channel rename — use {@link BlockerClassifierEntry}. */
|
|
53
|
+
export interface RuntimeCliContext {
|
|
54
|
+
projectRoot: string;
|
|
55
|
+
outputMode?: string;
|
|
56
|
+
dryRun?: boolean;
|
|
57
|
+
}
|
|
58
|
+
export interface CliCommand extends CliCommandRegistration {
|
|
59
|
+
run(context: RuntimeCliContext, args: readonly string[]): Promise<unknown> | unknown;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Hook contribution: metadata plus an optional typed `handler`. A hook is
|
|
63
|
+
* implemented either by a typed `handler` or by a raw `command` string in its
|
|
64
|
+
* metadata — never both. The runtime's hook-materializer generates the shim
|
|
65
|
+
* command that routes Claude Code's hook invocation to the typed function.
|
|
66
|
+
*/
|
|
67
|
+
export interface Hook extends HookRegistration {
|
|
68
|
+
handler?: HookImplementation;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Stage contribution: the stage descriptor plus its executor. When a plugin
|
|
72
|
+
* inserts/replaces a stage (via a matching `stageMutations` entry), its
|
|
73
|
+
* `run(ctx)` lives here so the kernel's stage runner can execute it.
|
|
74
|
+
*/
|
|
75
|
+
export interface StageEntry extends Stage {
|
|
76
|
+
run?: StageRun;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Executable installer for a contributed session extension. The `api` argument
|
|
80
|
+
* is the agent-session extension API (the OMP/Pi `ExtensionAPI`), kept as `any`
|
|
81
|
+
* here on purpose: typing it against the OMP runtime would couple the
|
|
82
|
+
* substrate-agnostic plugin model to the OMP substrate (architecture reference
|
|
83
|
+
* §12). The plugin author (run-worker) and the consumer (rig-host) hold the
|
|
84
|
+
* concrete `ExtensionAPI` type; the plugin host only sees an opaque installer.
|
|
85
|
+
*/
|
|
86
|
+
export type SessionExtensionInstall = (api: any) => void | Promise<void>;
|
|
87
|
+
export interface SessionExtensionEntry extends SessionExtensionRegistration {
|
|
88
|
+
install: SessionExtensionInstall;
|
|
89
|
+
}
|
|
90
|
+
export type SeedEntrypointRunResult = boolean | void | number;
|
|
91
|
+
export interface SeedEntrypointContext {
|
|
92
|
+
argv: readonly string[];
|
|
93
|
+
execPath?: string;
|
|
94
|
+
basename?: string;
|
|
95
|
+
workerArg?: string;
|
|
96
|
+
parentPort?: unknown;
|
|
97
|
+
}
|
|
98
|
+
export interface SeedEntrypoint extends SeedEntrypointRegistration {
|
|
99
|
+
run(context: SeedEntrypointContext): Promise<SeedEntrypointRunResult> | SeedEntrypointRunResult;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Single-channel contributions. Fn-bearing kinds carry their executable fn on
|
|
103
|
+
* the same entry as their metadata; metadata-only kinds (skills, repoSources,
|
|
104
|
+
* agentRoles, taskFieldSchemas, stageMutations) are pure registrations.
|
|
105
|
+
*/
|
|
106
|
+
/** Context handed to a plugin when it default-fills its config fragment. */
|
|
107
|
+
export interface ConfigDefaultsContext {
|
|
108
|
+
/** Absolute path to the project root being configured. */
|
|
109
|
+
readonly projectRoot: string;
|
|
110
|
+
/**
|
|
111
|
+
* Explicit `owner/repo` slug when a caller already knows it (the init wizard,
|
|
112
|
+
* a setup flow). When absent, a plugin that needs the repo identity derives it
|
|
113
|
+
* from its own domain (e.g. the github plugin reads the git remote). This is
|
|
114
|
+
* the single override seam so autocreate and the wizard share one composer.
|
|
115
|
+
*/
|
|
116
|
+
readonly repoSlug?: string;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* A plugin's contribution to the declarative `.rig/rigfig.toml`.
|
|
120
|
+
*
|
|
121
|
+
* Plugins are the things that ENRICH the config: each one owns the config
|
|
122
|
+
* properties IT needs and default-fills them with its OWN domain logic — the
|
|
123
|
+
* github plugin detects owner/repo from the git remote and fills the github
|
|
124
|
+
* task source + workspace id; the pr plugin fills `[pr]`; planning fills
|
|
125
|
+
* `[planning]`; and so on. The autocreate/init composer deep-merges every
|
|
126
|
+
* active plugin's fragment (in plugin order) into the written config. Returning
|
|
127
|
+
* null (or a plugin omitting `config`) contributes nothing.
|
|
128
|
+
*
|
|
129
|
+
* `defaults` is a fn — it rides on the authored RigPlugin and is ignored by the
|
|
130
|
+
* serializable manifest Schema, like every other executable contribution entry.
|
|
131
|
+
*/
|
|
132
|
+
export interface PluginConfigContribution {
|
|
133
|
+
defaults(context: ConfigDefaultsContext): Record<string, unknown> | null;
|
|
134
|
+
}
|
|
135
|
+
export interface PluginContributes {
|
|
136
|
+
validators?: readonly Validator[];
|
|
137
|
+
hooks?: readonly Hook[];
|
|
138
|
+
skills?: readonly SkillRegistration[];
|
|
139
|
+
repoSources?: readonly RepoSourceRegistration[];
|
|
140
|
+
agentRoles?: readonly AgentRoleRegistration[];
|
|
141
|
+
taskFieldSchemas?: readonly TaskFieldExtension[];
|
|
142
|
+
taskSources?: readonly TaskSource[];
|
|
143
|
+
cliCommands?: readonly CliCommand[];
|
|
144
|
+
stages?: readonly StageEntry[];
|
|
145
|
+
stageMutations?: readonly StageMutation[];
|
|
146
|
+
capabilities?: readonly FeatureCapability[];
|
|
147
|
+
panels?: readonly Panel[];
|
|
148
|
+
blockerClassifiers?: readonly BlockerClassifierEntry[];
|
|
149
|
+
sessionExtensions?: readonly SessionExtensionEntry[];
|
|
150
|
+
seedEntrypoints?: readonly SeedEntrypoint[];
|
|
151
|
+
/** Declarative config defaults this plugin contributes to `.rig/rigfig.toml`. */
|
|
152
|
+
config?: PluginConfigContribution;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* The authored plugin object. Validated against the `RigPlugin` metadata schema
|
|
156
|
+
* in @rig/contracts; the executable fns on `contributes` entries and the kernel
|
|
157
|
+
* `capabilityProviders` ride alongside and are ignored by Schema decode.
|
|
158
|
+
*/
|
|
159
|
+
export interface RigPlugin {
|
|
160
|
+
name: string;
|
|
161
|
+
version: string;
|
|
162
|
+
provides?: readonly CapabilityTag[];
|
|
163
|
+
requires?: readonly CapabilityTag[];
|
|
164
|
+
replaces?: readonly CapabilityReplacementSpec[];
|
|
165
|
+
contributes?: PluginContributes;
|
|
166
|
+
/**
|
|
167
|
+
* Kernel capability implementations keyed by the tag named in `provides`
|
|
168
|
+
* (`transport`, `journal`, `stage-runner`, `loader-policy`, `kernel`). This
|
|
169
|
+
* is the single home for what the old kernel `LoadedPlugin.runtime.capabilities`
|
|
170
|
+
* / `runtime.kernel` carried — kernel-seed resolves capabilities from here.
|
|
171
|
+
*/
|
|
172
|
+
capabilityProviders?: Partial<Record<CapabilityTag, unknown>>;
|
|
173
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function showProfile(projectRoot: string, compact?: boolean): Promise<void>;
|
|
2
|
+
export declare function setProfile(projectRoot: string, options: {
|
|
3
|
+
model?: string;
|
|
4
|
+
runtime?: string;
|
|
5
|
+
plugin?: string;
|
|
6
|
+
preset?: string;
|
|
7
|
+
}): Promise<void>;
|
|
8
|
+
export declare function showReviewProfile(projectRoot: string): Promise<void>;
|
|
9
|
+
export declare function setReviewProfile(projectRoot: string, mode: string, provider?: string): Promise<void>;
|