@kuznai/inception-engine 0.19.0 → 0.21.0
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/README.md +50 -22
- package/dist/{config → src/config}/agents.js +113 -14
- package/dist/{core → src/core}/adapters/agent-definitions.d.ts +0 -12
- package/dist/src/core/adapters/agent-definitions.js +162 -0
- package/dist/{core → src/core}/adapters/frontmatter.d.ts +10 -0
- package/dist/{core → src/core}/adapters/frontmatter.js +23 -6
- package/dist/src/core/adapters/index.js +25 -0
- package/dist/{core → src/core}/adapters/mcp.js +17 -20
- package/dist/{core → src/core}/adapters/permissions.js +16 -20
- package/dist/{core → src/core}/adapters/rules.js +26 -50
- package/dist/src/core/capabilities.d.ts +47 -0
- package/dist/src/core/capabilities.js +280 -0
- package/dist/{core → src/core}/deploy.js +82 -54
- package/dist/{core → src/core}/detect.js +2 -7
- package/dist/{core → src/core}/init.js +20 -25
- package/dist/src/core/merge-patch.d.ts +4 -0
- package/dist/src/core/merge-patch.js +46 -0
- package/dist/{core → src/core}/ownership.js +13 -0
- package/dist/src/core/preflight.js +296 -0
- package/dist/{core → src/core}/revert.js +86 -26
- package/dist/{core → src/core}/validation.js +31 -0
- package/dist/{errors.d.ts → src/errors.d.ts} +3 -1
- package/dist/{errors.js → src/errors.js} +2 -2
- package/dist/{schemas → src/schemas}/manifest.d.ts +20 -0
- package/dist/{schemas → src/schemas}/manifest.js +11 -0
- package/dist/{schemas → src/schemas}/registry.d.ts +36 -0
- package/dist/{schemas → src/schemas}/registry.js +12 -4
- package/dist/{types.d.ts → src/types.d.ts} +15 -0
- package/dist/test/helpers/fs.d.ts +2 -0
- package/dist/test/helpers/fs.js +17 -0
- package/dist/test/helpers/path.d.ts +10 -0
- package/dist/test/helpers/path.js +15 -0
- package/dist/test/helpers/skill-dir-scenarios.d.ts +7 -0
- package/dist/test/helpers/skill-dir-scenarios.js +206 -0
- package/dist/test/helpers/skill-dir.d.ts +7 -0
- package/dist/test/helpers/skill-dir.js +46 -0
- package/dist/test/os/cross-platform/cross-platform.test.d.ts +1 -0
- package/dist/test/os/cross-platform/cross-platform.test.js +328 -0
- package/dist/test/os/posix/skill-dir.test.d.ts +1 -0
- package/dist/test/os/posix/skill-dir.test.js +19 -0
- package/dist/test/os/windows/agentRules-integration.test.d.ts +1 -0
- package/dist/test/os/windows/agentRules-integration.test.js +245 -0
- package/dist/test/os/windows/revert-integration.test.d.ts +1 -0
- package/dist/test/os/windows/revert-integration.test.js +72 -0
- package/dist/test/os/windows/skill-dir.test.d.ts +1 -0
- package/dist/test/os/windows/skill-dir.test.js +19 -0
- package/dist/test/unit/adapters.test.d.ts +1 -0
- package/dist/test/unit/adapters.test.js +1017 -0
- package/dist/test/unit/capabilities.test.d.ts +1 -0
- package/dist/test/unit/capabilities.test.js +71 -0
- package/dist/test/unit/cli.test.d.ts +1 -0
- package/dist/test/unit/cli.test.js +834 -0
- package/dist/test/unit/deploy.test.d.ts +1 -0
- package/dist/test/unit/deploy.test.js +2481 -0
- package/dist/test/unit/detect.test.d.ts +1 -0
- package/dist/test/unit/detect.test.js +192 -0
- package/dist/test/unit/enterprise.test.d.ts +1 -0
- package/dist/test/unit/enterprise.test.js +106 -0
- package/dist/test/unit/frontmatter.test.d.ts +1 -0
- package/dist/test/unit/frontmatter.test.js +102 -0
- package/dist/test/unit/gemini-north-star.test.d.ts +1 -0
- package/dist/test/unit/gemini-north-star.test.js +243 -0
- package/dist/test/unit/init-fixture.test.d.ts +1 -0
- package/dist/test/unit/init-fixture.test.js +153 -0
- package/dist/test/unit/manifest.test.d.ts +1 -0
- package/dist/test/unit/manifest.test.js +737 -0
- package/dist/test/unit/migration-golden.test.d.ts +1 -0
- package/dist/test/unit/migration-golden.test.js +197 -0
- package/dist/test/unit/ownership.test.d.ts +1 -0
- package/dist/test/unit/ownership.test.js +587 -0
- package/dist/test/unit/preflight.test.d.ts +1 -0
- package/dist/test/unit/preflight.test.js +521 -0
- package/dist/test/unit/resolve.test.d.ts +1 -0
- package/dist/test/unit/resolve.test.js +119 -0
- package/dist/test/unit/revert.test.d.ts +1 -0
- package/dist/test/unit/revert.test.js +1004 -0
- package/dist/test/unit/toml.test.d.ts +1 -0
- package/dist/test/unit/toml.test.js +55 -0
- package/package.json +1 -1
- package/dist/core/adapters/agent-definitions.js +0 -91
- package/dist/core/adapters/index.js +0 -30
- package/dist/core/preflight.js +0 -168
- /package/dist/{config → src/config}/agents.d.ts +0 -0
- /package/dist/{config → src/config}/manifest.d.ts +0 -0
- /package/dist/{config → src/config}/manifest.js +0 -0
- /package/dist/{core → src/core}/adapters/index.d.ts +0 -0
- /package/dist/{core → src/core}/adapters/mcp.d.ts +0 -0
- /package/dist/{core → src/core}/adapters/permissions.d.ts +0 -0
- /package/dist/{core → src/core}/adapters/rules.d.ts +0 -0
- /package/dist/{core → src/core}/adapters/toml.d.ts +0 -0
- /package/dist/{core → src/core}/adapters/toml.js +0 -0
- /package/dist/{core → src/core}/deploy.d.ts +0 -0
- /package/dist/{core → src/core}/detect.d.ts +0 -0
- /package/dist/{core → src/core}/init.d.ts +0 -0
- /package/dist/{core → src/core}/ownership.d.ts +0 -0
- /package/dist/{core → src/core}/preflight.d.ts +0 -0
- /package/dist/{core → src/core}/resolve.d.ts +0 -0
- /package/dist/{core → src/core}/resolve.js +0 -0
- /package/dist/{core → src/core}/revert.d.ts +0 -0
- /package/dist/{core → src/core}/runtime-paths.d.ts +0 -0
- /package/dist/{core → src/core}/runtime-paths.js +0 -0
- /package/dist/{core → src/core}/validation.d.ts +0 -0
- /package/dist/{formatters.d.ts → src/formatters.d.ts} +0 -0
- /package/dist/{formatters.js → src/formatters.js} +0 -0
- /package/dist/{index.d.ts → src/index.d.ts} +0 -0
- /package/dist/{index.js → src/index.js} +0 -0
- /package/dist/{logger.d.ts → src/logger.d.ts} +0 -0
- /package/dist/{logger.js → src/logger.js} +0 -0
- /package/dist/{schemas → src/schemas}/errors.d.ts +0 -0
- /package/dist/{schemas → src/schemas}/errors.js +0 -0
- /package/dist/{types.js → src/types.js} +0 -0
|
@@ -26,10 +26,10 @@ export function splitFrontmatter(raw) {
|
|
|
26
26
|
export function parseFrontmatterDocument(raw) {
|
|
27
27
|
const { frontmatter, body } = splitFrontmatter(raw);
|
|
28
28
|
if (!(frontmatter || raw.startsWith("---"))) {
|
|
29
|
-
return { attributes: {}, body };
|
|
29
|
+
return { attributes: {}, body, hasFrontmatter: false };
|
|
30
30
|
}
|
|
31
31
|
const attributes = YAML.parse(frontmatter);
|
|
32
|
-
return { attributes: (attributes || {}), body };
|
|
32
|
+
return { attributes: (attributes || {}), body, hasFrontmatter: true };
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
35
|
* Serializes an object to a YAML block.
|
|
@@ -42,9 +42,15 @@ export function serializeFrontmatter(data) {
|
|
|
42
42
|
* Builds the full content of a frontmatter-bearing Markdown file.
|
|
43
43
|
*/
|
|
44
44
|
export function buildFrontmatterDocument(frontmatter, body = "") {
|
|
45
|
+
return buildMarkdownDocument(frontmatter, body, { hasFrontmatter: true });
|
|
46
|
+
}
|
|
47
|
+
export function buildMarkdownDocument(frontmatter, body = "", options = {}) {
|
|
48
|
+
const cleanBody = body.trimStart();
|
|
49
|
+
if (Object.keys(frontmatter).length === 0 && !options.hasFrontmatter) {
|
|
50
|
+
return cleanBody;
|
|
51
|
+
}
|
|
45
52
|
const serialized = serializeFrontmatter(frontmatter);
|
|
46
53
|
// Ensure exactly one newline after the closing delimiter before the body
|
|
47
|
-
const cleanBody = body.trimStart();
|
|
48
54
|
const separator = cleanBody ? "\n\n" : "\n";
|
|
49
55
|
return `---\n${serialized}\n---\n${separator}${cleanBody}`;
|
|
50
56
|
}
|
|
@@ -58,17 +64,28 @@ function createAtomicTempPath(targetPath) {
|
|
|
58
64
|
* Returns `{ attributes: {}, body: "" }` if the file does not exist.
|
|
59
65
|
*/
|
|
60
66
|
export async function readFrontmatterFile(filePath) {
|
|
67
|
+
const document = await readFrontmatterDocumentFile(filePath);
|
|
68
|
+
return { attributes: document.attributes, body: document.body };
|
|
69
|
+
}
|
|
70
|
+
export async function readFrontmatterDocumentFile(filePath) {
|
|
61
71
|
let raw;
|
|
62
72
|
try {
|
|
63
73
|
raw = await readFile(filePath, "utf-8");
|
|
64
74
|
}
|
|
65
75
|
catch (err) {
|
|
66
76
|
const code = err.code;
|
|
67
|
-
if (code === "ENOENT")
|
|
68
|
-
return {
|
|
77
|
+
if (code === "ENOENT") {
|
|
78
|
+
return {
|
|
79
|
+
exists: false,
|
|
80
|
+
hasFrontmatter: false,
|
|
81
|
+
attributes: {},
|
|
82
|
+
body: "",
|
|
83
|
+
};
|
|
84
|
+
}
|
|
69
85
|
throw err;
|
|
70
86
|
}
|
|
71
|
-
|
|
87
|
+
const parsed = parseFrontmatterDocument(raw);
|
|
88
|
+
return { exists: true, ...parsed };
|
|
72
89
|
}
|
|
73
90
|
/**
|
|
74
91
|
* Atomically writes a Markdown file with the given frontmatter and optional
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { compileAgentDefinitionActions, compileAgentDefinitionReverts, } from "./agent-definitions.js";
|
|
2
|
+
import { compileMcpServerActions, compileMcpServerReverts } from "./mcp.js";
|
|
3
|
+
import { compilePermissionsActions, compilePermissionsReverts, } from "./permissions.js";
|
|
4
|
+
import { compileAgentRuleActions, compileAgentRuleReverts } from "./rules.js";
|
|
5
|
+
export { compileAgentDefinitionReverts, compileAgentRuleReverts, compileMcpServerReverts, compilePermissionsReverts, };
|
|
6
|
+
async function compileAll(entries, fn) {
|
|
7
|
+
const results = await Promise.all(entries.map(fn));
|
|
8
|
+
return {
|
|
9
|
+
actions: results.flatMap((r) => r.actions),
|
|
10
|
+
warnings: results.flatMap((r) => r.warnings),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export async function compileAdapterActions(mcpServers, agentRules, permissions, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, agentDefinitions, workspace) {
|
|
14
|
+
const actions = [];
|
|
15
|
+
const warnings = [];
|
|
16
|
+
const [mcp, rules, perms, defs] = await Promise.all([
|
|
17
|
+
compileAll(mcpServers, (entry) => compileMcpServerActions(entry, detectedAgents, home, repo, workspace)),
|
|
18
|
+
compileAll(agentRules, (entry) => compileAgentRuleActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, workspace)),
|
|
19
|
+
compileAll(permissions, (entry) => compilePermissionsActions(entry, detectedAgents, home)),
|
|
20
|
+
compileAll(agentDefinitions ?? [], (entry) => compileAgentDefinitionActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, workspace)),
|
|
21
|
+
]);
|
|
22
|
+
actions.push(...mcp.actions, ...rules.actions, ...perms.actions, ...defs.actions);
|
|
23
|
+
warnings.push(...mcp.warnings, ...rules.warnings, ...perms.warnings, ...defs.warnings);
|
|
24
|
+
return { actions, warnings };
|
|
25
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import {
|
|
2
|
+
import { planCapabilityForDeploy, resolveCapabilitySurface, } from "../capabilities.js";
|
|
3
3
|
import { getPlatformKey, resolvePlaceholders } from "../resolve.js";
|
|
4
4
|
import { validateMcpServerConfigShape } from "../validation.js";
|
|
5
5
|
/**
|
|
@@ -53,26 +53,26 @@ export function compileMcpServerActions(entry, detectedAgents, home, repo, works
|
|
|
53
53
|
for (const agentId of entry.agents) {
|
|
54
54
|
if (!detectedAgents.includes(agentId))
|
|
55
55
|
continue;
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
const plan = planCapabilityForDeploy({
|
|
57
|
+
agentId,
|
|
58
|
+
capability: "mcpServers",
|
|
59
|
+
entryName: entry.name,
|
|
60
|
+
targetAgentIds: entry.agents,
|
|
61
|
+
scope: entry.scope,
|
|
62
|
+
});
|
|
63
|
+
if (plan.outcome === "warn") {
|
|
64
|
+
warnings.push(plan.warning);
|
|
63
65
|
continue;
|
|
64
66
|
}
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
});
|
|
67
|
+
if (plan.outcome === "native" || plan.outcome === "redundant")
|
|
68
|
+
continue;
|
|
69
|
+
const support = resolveCapabilitySurface(agentId, "mcpServers", entry.scope).support;
|
|
70
|
+
if (!support)
|
|
70
71
|
continue;
|
|
71
|
-
}
|
|
72
72
|
validateMcpServerConfigShape(entry.config, entry.name, agentId);
|
|
73
73
|
const rawTarget = resolvePlaceholders(support.path[platform], entry.name, home, repo, workspace);
|
|
74
74
|
const resolvedTarget = path.resolve(rawTarget);
|
|
75
|
-
const confidence =
|
|
75
|
+
const confidence = plan.confidence ?? "provisional";
|
|
76
76
|
const mcpPatchKey = support.mcpPatchKey ?? "mcpServers";
|
|
77
77
|
actions.push(buildMcpDeployAction(entry, agentId, resolvedTarget, confidence, mcpPatchKey));
|
|
78
78
|
}
|
|
@@ -84,11 +84,8 @@ export function compileMcpServerReverts(entry, agentFilter, home, repo, workspac
|
|
|
84
84
|
for (const agentId of entry.agents) {
|
|
85
85
|
if (agentFilter && !agentFilter.includes(agentId))
|
|
86
86
|
continue;
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
if (!support ||
|
|
90
|
-
support.status === "unsupported" ||
|
|
91
|
-
support.status === "planned")
|
|
87
|
+
const support = resolveCapabilitySurface(agentId, "mcpServers", entry.scope).support;
|
|
88
|
+
if (!support)
|
|
92
89
|
continue;
|
|
93
90
|
const rawTarget = resolvePlaceholders(support.path[platform], entry.name, home, repo, workspace);
|
|
94
91
|
const target = path.resolve(rawTarget);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import {
|
|
2
|
+
import { planCapabilityForDeploy, resolveCapabilitySurface, } from "../capabilities.js";
|
|
3
3
|
import { getPlatformKey, resolvePlaceholders } from "../resolve.js";
|
|
4
4
|
import { validatePermissionsConfigShape } from "../validation.js";
|
|
5
5
|
function isTomlTarget(targetPath) {
|
|
@@ -12,26 +12,25 @@ export function compilePermissionsActions(entry, detectedAgents, home) {
|
|
|
12
12
|
for (const agentId of entry.agents) {
|
|
13
13
|
if (!detectedAgents.includes(agentId))
|
|
14
14
|
continue;
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
const plan = planCapabilityForDeploy({
|
|
16
|
+
agentId,
|
|
17
|
+
capability: "permissions",
|
|
18
|
+
entryName: entry.name,
|
|
19
|
+
targetAgentIds: entry.agents,
|
|
20
|
+
});
|
|
21
|
+
if (plan.outcome === "warn") {
|
|
22
|
+
warnings.push(plan.warning);
|
|
22
23
|
continue;
|
|
23
24
|
}
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
});
|
|
25
|
+
if (plan.outcome === "native" || plan.outcome === "redundant")
|
|
26
|
+
continue;
|
|
27
|
+
const support = resolveCapabilitySurface(agentId, "permissions").support;
|
|
28
|
+
if (!support)
|
|
29
29
|
continue;
|
|
30
|
-
}
|
|
31
30
|
validatePermissionsConfigShape(entry.config, entry.name, agentId);
|
|
32
31
|
const rawTarget = resolvePlaceholders(support.path[platform], entry.name, home);
|
|
33
32
|
const resolvedTarget = path.resolve(rawTarget);
|
|
34
|
-
const confidence =
|
|
33
|
+
const confidence = plan.confidence ?? "provisional";
|
|
35
34
|
if (isTomlTarget(resolvedTarget)) {
|
|
36
35
|
actions.push({
|
|
37
36
|
kind: "toml-patch",
|
|
@@ -61,11 +60,8 @@ export function compilePermissionsReverts(entry, agentFilter, home) {
|
|
|
61
60
|
for (const agentId of entry.agents) {
|
|
62
61
|
if (agentFilter && !agentFilter.includes(agentId))
|
|
63
62
|
continue;
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
if (!support ||
|
|
67
|
-
support.status === "unsupported" ||
|
|
68
|
-
support.status === "planned")
|
|
63
|
+
const support = resolveCapabilitySurface(agentId, "permissions").support;
|
|
64
|
+
if (!support)
|
|
69
65
|
continue;
|
|
70
66
|
const rawTarget = resolvePlaceholders(support.path[platform], entry.name, home);
|
|
71
67
|
const target = path.resolve(rawTarget);
|
|
@@ -1,44 +1,21 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import {
|
|
2
|
+
import { planCapabilityForDeploy, resolveCapabilitySurface, } from "../capabilities.js";
|
|
3
3
|
import { getPlatformKey, resolvePlaceholders } from "../resolve.js";
|
|
4
4
|
import { validateAgentRuleMarkdownPath, validateInstructionFileRequirements, validateSourceFile, validateSourcePath, } from "../validation.js";
|
|
5
|
-
function resolveRulesSupport(agentId, scope) {
|
|
6
|
-
const agent = AGENT_REGISTRY_BY_ID[agentId];
|
|
7
|
-
if (scope === "repo") {
|
|
8
|
-
return agent?.agentRulesRepoSupport ?? agent?.agentRulesSupport;
|
|
9
|
-
}
|
|
10
|
-
if (scope === "workspace") {
|
|
11
|
-
return (agent?.agentRulesWorkspaceSupport ??
|
|
12
|
-
agent?.agentRulesRepoSupport ??
|
|
13
|
-
agent?.agentRulesSupport);
|
|
14
|
-
}
|
|
15
|
-
return agent?.agentRulesSupport;
|
|
16
|
-
}
|
|
17
5
|
function resolveAgentTarget(agentId, entry, home, repo, platform, workspace, allTargetAgentIds) {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
if (
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// shared-via: when requiresPrimary is set and the primary agent is absent
|
|
32
|
-
// from the target list, emit a guidance warning instead of deploying.
|
|
33
|
-
if (support.surfaceKind?.kind === "shared-via" &&
|
|
34
|
-
support.surfaceKind.requiresPrimary &&
|
|
35
|
-
allTargetAgentIds &&
|
|
36
|
-
!allTargetAgentIds.includes(support.surfaceKind.via)) {
|
|
37
|
-
return {
|
|
38
|
-
kind: "confidence",
|
|
39
|
-
message: `agentRules: agent "${agentId}" reads this surface via "${support.surfaceKind.via}" — add "${support.surfaceKind.via}" to the entry's agents list to deploy to this surface, or deploy via the "${support.surfaceKind.via}" agentRules target instead`,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
6
|
+
const plan = planCapabilityForDeploy({
|
|
7
|
+
agentId,
|
|
8
|
+
capability: "agentRules",
|
|
9
|
+
entryName: entry.name,
|
|
10
|
+
targetAgentIds: allTargetAgentIds ?? [agentId],
|
|
11
|
+
scope: entry.scope,
|
|
12
|
+
});
|
|
13
|
+
if (plan.outcome === "warn")
|
|
14
|
+
return plan.warning;
|
|
15
|
+
if (plan.outcome === "native" || plan.outcome === "redundant")
|
|
16
|
+
return null;
|
|
17
|
+
const surface = resolveCapabilitySurface(agentId, "agentRules", entry.scope);
|
|
18
|
+
const support = surface.support;
|
|
42
19
|
if (entry.scope === "repo" && !repo) {
|
|
43
20
|
return {
|
|
44
21
|
kind: "confidence",
|
|
@@ -51,11 +28,10 @@ function resolveAgentTarget(agentId, entry, home, repo, platform, workspace, all
|
|
|
51
28
|
message: `agentRules: scope "workspace" requires a workspace or repository path but none was resolved — skipping "${entry.name}" for agent "${agentId}"`,
|
|
52
29
|
};
|
|
53
30
|
}
|
|
54
|
-
const agent = AGENT_REGISTRY_BY_ID[agentId];
|
|
55
31
|
return {
|
|
56
32
|
agentId,
|
|
57
|
-
confidence:
|
|
58
|
-
target: resolvePlaceholders(support
|
|
33
|
+
confidence: plan.confidence,
|
|
34
|
+
target: resolvePlaceholders(support?.path[platform] ?? [], entry.name, home, repo, workspace),
|
|
59
35
|
};
|
|
60
36
|
}
|
|
61
37
|
export async function compileAgentRuleActions(entry, sourceDir, resolvedSourceDir, realRoot, detectedAgents, home, repo, workspace) {
|
|
@@ -69,6 +45,9 @@ export async function compileAgentRuleActions(entry, sourceDir, resolvedSourceDi
|
|
|
69
45
|
}
|
|
70
46
|
for (const agentId of targetAgents) {
|
|
71
47
|
const result = resolveAgentTarget(agentId, entry, home, repo, platform, workspace, targetAgents);
|
|
48
|
+
if (result === null) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
72
51
|
if ("kind" in result) {
|
|
73
52
|
warnings.push(result);
|
|
74
53
|
}
|
|
@@ -85,12 +64,10 @@ export async function compileAgentRuleActions(entry, sourceDir, resolvedSourceDi
|
|
|
85
64
|
const seenTargetPaths = new Set();
|
|
86
65
|
const dedupedTargets = [];
|
|
87
66
|
for (const t of supportedTargets) {
|
|
88
|
-
const
|
|
89
|
-
if (
|
|
90
|
-
|
|
91
|
-
supportedTargets.some((o) => o.agentId ===
|
|
92
|
-
sup.surfaceKind.via &&
|
|
93
|
-
o.target === t.target)) {
|
|
67
|
+
const surface = resolveCapabilitySurface(t.agentId, "agentRules", entry.scope);
|
|
68
|
+
if (surface.surfaceKind === "shared-via" &&
|
|
69
|
+
surface.sharedVia &&
|
|
70
|
+
supportedTargets.some((o) => o.agentId === surface.sharedVia && o.target === t.target)) {
|
|
94
71
|
// Primary agent is present and writes the same target — skip rider.
|
|
95
72
|
continue;
|
|
96
73
|
}
|
|
@@ -125,10 +102,9 @@ export function compileAgentRuleReverts(entry, agentFilter, home, repo, workspac
|
|
|
125
102
|
for (const agentId of entry.agents) {
|
|
126
103
|
if (agentFilter && !agentFilter.includes(agentId))
|
|
127
104
|
continue;
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
support.status === "planned") {
|
|
105
|
+
const surface = resolveCapabilitySurface(agentId, "agentRules", entry.scope);
|
|
106
|
+
const support = surface.support;
|
|
107
|
+
if (surface.supportStatus !== "supported" || !support) {
|
|
132
108
|
continue;
|
|
133
109
|
}
|
|
134
110
|
if (entry.scope === "repo" && !repo)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { AgentId, AgentSurfaceSupport, CapabilityKind, Confidence, PlanWarning, SupportedAgentSurface } from "../types.ts";
|
|
2
|
+
type CapabilityScope = "global" | "repo" | "workspace";
|
|
3
|
+
export interface ResolvedCapabilitySurface {
|
|
4
|
+
agentId: AgentId;
|
|
5
|
+
capability: CapabilityKind;
|
|
6
|
+
supportStatus: "supported" | "unsupported" | "planned";
|
|
7
|
+
support?: SupportedAgentSurface;
|
|
8
|
+
supportRecord?: AgentSurfaceSupport;
|
|
9
|
+
confidence?: Confidence;
|
|
10
|
+
schemaLabel: string;
|
|
11
|
+
surfaceKind: "agent-specific" | "native" | "shared-via";
|
|
12
|
+
sharedVia?: AgentId;
|
|
13
|
+
requiresPrimary: boolean;
|
|
14
|
+
canDeployDirectlyWhenPrimaryAbsent: boolean;
|
|
15
|
+
includeInInitByDefault: boolean;
|
|
16
|
+
reason?: string;
|
|
17
|
+
plannedSurface?: string;
|
|
18
|
+
}
|
|
19
|
+
export type DeployCapabilityPlan = {
|
|
20
|
+
outcome: "action";
|
|
21
|
+
confidence?: Confidence;
|
|
22
|
+
support?: SupportedAgentSurface;
|
|
23
|
+
} | {
|
|
24
|
+
outcome: "redundant";
|
|
25
|
+
confidence?: Confidence;
|
|
26
|
+
support?: SupportedAgentSurface;
|
|
27
|
+
sharedVia: AgentId;
|
|
28
|
+
} | {
|
|
29
|
+
outcome: "warn";
|
|
30
|
+
warning: PlanWarning;
|
|
31
|
+
} | {
|
|
32
|
+
outcome: "native";
|
|
33
|
+
};
|
|
34
|
+
export declare function resolveCapabilitySurface(agentId: AgentId, capability: CapabilityKind, scope?: CapabilityScope): ResolvedCapabilitySurface;
|
|
35
|
+
export declare function planCapabilityForDeploy(opts: {
|
|
36
|
+
agentId: AgentId;
|
|
37
|
+
capability: CapabilityKind;
|
|
38
|
+
entryName: string;
|
|
39
|
+
targetAgentIds: AgentId[];
|
|
40
|
+
scope?: CapabilityScope;
|
|
41
|
+
}): DeployCapabilityPlan;
|
|
42
|
+
export declare function shouldInitIncludeAgent(agentId: AgentId, capability: CapabilityKind, scope?: CapabilityScope): boolean;
|
|
43
|
+
export declare function describeCapabilityConfidence(agentId: AgentId, capability: CapabilityKind, scope?: CapabilityScope): {
|
|
44
|
+
confidence?: Confidence;
|
|
45
|
+
message: string | null;
|
|
46
|
+
};
|
|
47
|
+
export {};
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { AGENT_REGISTRY_BY_ID } from "../config/agents.js";
|
|
2
|
+
function resolveAgentRulesSupport(agentId, scope) {
|
|
3
|
+
const agent = AGENT_REGISTRY_BY_ID[agentId];
|
|
4
|
+
if (scope === "repo") {
|
|
5
|
+
return agent?.agentRulesRepoSupport ?? agent?.agentRulesSupport;
|
|
6
|
+
}
|
|
7
|
+
if (scope === "workspace") {
|
|
8
|
+
return (agent?.agentRulesWorkspaceSupport ??
|
|
9
|
+
agent?.agentRulesRepoSupport ??
|
|
10
|
+
agent?.agentRulesSupport);
|
|
11
|
+
}
|
|
12
|
+
return agent?.agentRulesSupport;
|
|
13
|
+
}
|
|
14
|
+
function resolveMcpSupport(agentId, scope) {
|
|
15
|
+
const agent = AGENT_REGISTRY_BY_ID[agentId];
|
|
16
|
+
if (scope === "repo") {
|
|
17
|
+
return agent?.mcpRepoSupport ?? agent?.mcpSupport;
|
|
18
|
+
}
|
|
19
|
+
if (scope === "workspace") {
|
|
20
|
+
return (agent?.mcpWorkspaceSupport ?? agent?.mcpRepoSupport ?? agent?.mcpSupport);
|
|
21
|
+
}
|
|
22
|
+
return agent?.mcpSupport;
|
|
23
|
+
}
|
|
24
|
+
function resolveAgentDefinitionsSupport(agentId, scope) {
|
|
25
|
+
const agent = AGENT_REGISTRY_BY_ID[agentId];
|
|
26
|
+
if (scope === "repo") {
|
|
27
|
+
return agent?.agentDefinitionsRepoSupport ?? agent?.agentDefinitionsSupport;
|
|
28
|
+
}
|
|
29
|
+
if (scope === "workspace") {
|
|
30
|
+
return (agent?.agentDefinitionsWorkspaceSupport ??
|
|
31
|
+
agent?.agentDefinitionsRepoSupport ??
|
|
32
|
+
agent?.agentDefinitionsSupport);
|
|
33
|
+
}
|
|
34
|
+
return agent?.agentDefinitionsSupport;
|
|
35
|
+
}
|
|
36
|
+
function capabilityLabel(capability) {
|
|
37
|
+
switch (capability) {
|
|
38
|
+
case "skills":
|
|
39
|
+
return "skills";
|
|
40
|
+
case "mcpServers":
|
|
41
|
+
return "mcpServers";
|
|
42
|
+
case "agentRules":
|
|
43
|
+
return "agentRules";
|
|
44
|
+
case "permissions":
|
|
45
|
+
return "permissions";
|
|
46
|
+
case "agentDefinitions":
|
|
47
|
+
return "agentDefinitions";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function capabilitySurfaceLabel(capability) {
|
|
51
|
+
switch (capability) {
|
|
52
|
+
case "skills":
|
|
53
|
+
return "skill";
|
|
54
|
+
case "mcpServers":
|
|
55
|
+
return "MCP";
|
|
56
|
+
case "agentRules":
|
|
57
|
+
return "rules";
|
|
58
|
+
case "permissions":
|
|
59
|
+
return "permissions";
|
|
60
|
+
case "agentDefinitions":
|
|
61
|
+
return "agent-definitions";
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function resolveSkillsCapability(agentId) {
|
|
65
|
+
const agent = AGENT_REGISTRY_BY_ID[agentId];
|
|
66
|
+
if (agent.skills) {
|
|
67
|
+
return {
|
|
68
|
+
agentId,
|
|
69
|
+
capability: "skills",
|
|
70
|
+
supportStatus: "supported",
|
|
71
|
+
confidence: agent.provenance.skills ?? "provisional",
|
|
72
|
+
schemaLabel: "dedicated skill directory",
|
|
73
|
+
surfaceKind: "agent-specific",
|
|
74
|
+
requiresPrimary: false,
|
|
75
|
+
canDeployDirectlyWhenPrimaryAbsent: true,
|
|
76
|
+
includeInInitByDefault: true,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const via = agent.skillsSurfaceKind?.via;
|
|
80
|
+
return {
|
|
81
|
+
agentId,
|
|
82
|
+
capability: "skills",
|
|
83
|
+
supportStatus: "supported",
|
|
84
|
+
confidence: agent.provenance.skills,
|
|
85
|
+
schemaLabel: "shared native skill directory",
|
|
86
|
+
surfaceKind: agent.skillsSurfaceKind?.kind === "shared-via" ? "shared-via" : "native",
|
|
87
|
+
sharedVia: via,
|
|
88
|
+
requiresPrimary: true,
|
|
89
|
+
canDeployDirectlyWhenPrimaryAbsent: false,
|
|
90
|
+
includeInInitByDefault: false,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function getSurfaceRecordAndConfidence(agentId, capability, scope) {
|
|
94
|
+
const agent = AGENT_REGISTRY_BY_ID[agentId];
|
|
95
|
+
if (capability === "mcpServers") {
|
|
96
|
+
return {
|
|
97
|
+
supportRecord: resolveMcpSupport(agentId, scope),
|
|
98
|
+
confidence: agent.provenance.mcpConfig,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (capability === "agentRules") {
|
|
102
|
+
return {
|
|
103
|
+
supportRecord: resolveAgentRulesSupport(agentId, scope),
|
|
104
|
+
confidence: agent.provenance.agentRules,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (capability === "permissions") {
|
|
108
|
+
return {
|
|
109
|
+
supportRecord: agent.permissionsSupport,
|
|
110
|
+
confidence: agent.provenance.permissions,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
supportRecord: resolveAgentDefinitionsSupport(agentId, scope),
|
|
115
|
+
confidence: agent.provenance.agentDefinitions,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function resolveUnsupportedSurface(agentId, capability, supportRecord, confidence) {
|
|
119
|
+
return {
|
|
120
|
+
agentId,
|
|
121
|
+
capability,
|
|
122
|
+
supportStatus: "unsupported",
|
|
123
|
+
supportRecord,
|
|
124
|
+
confidence,
|
|
125
|
+
schemaLabel: supportRecord?.schemaLabel ?? "an unsupported surface",
|
|
126
|
+
surfaceKind: "agent-specific",
|
|
127
|
+
requiresPrimary: false,
|
|
128
|
+
canDeployDirectlyWhenPrimaryAbsent: false,
|
|
129
|
+
includeInInitByDefault: false,
|
|
130
|
+
reason: supportRecord?.status === "unsupported"
|
|
131
|
+
? supportRecord.reason
|
|
132
|
+
: undefined,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function resolvePlannedSurface(agentId, capability, supportRecord, confidence) {
|
|
136
|
+
return {
|
|
137
|
+
agentId,
|
|
138
|
+
capability,
|
|
139
|
+
supportStatus: "planned",
|
|
140
|
+
supportRecord,
|
|
141
|
+
confidence,
|
|
142
|
+
schemaLabel: supportRecord.schemaLabel,
|
|
143
|
+
surfaceKind: "agent-specific",
|
|
144
|
+
requiresPrimary: false,
|
|
145
|
+
canDeployDirectlyWhenPrimaryAbsent: false,
|
|
146
|
+
includeInInitByDefault: false,
|
|
147
|
+
reason: supportRecord.reason,
|
|
148
|
+
plannedSurface: supportRecord.plannedSurface,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function resolveSupportedSurface(agentId, capability, supportRecord, confidence) {
|
|
152
|
+
const surfaceKind = supportRecord.surfaceKind?.kind ?? "agent-specific";
|
|
153
|
+
const sharedVia = supportRecord.surfaceKind?.kind === "shared-via"
|
|
154
|
+
? supportRecord.surfaceKind.via
|
|
155
|
+
: undefined;
|
|
156
|
+
const requiresPrimary = supportRecord.surfaceKind?.kind === "shared-via" &&
|
|
157
|
+
supportRecord.surfaceKind.requiresPrimary === true;
|
|
158
|
+
return {
|
|
159
|
+
agentId,
|
|
160
|
+
capability,
|
|
161
|
+
supportStatus: "supported",
|
|
162
|
+
support: supportRecord,
|
|
163
|
+
supportRecord,
|
|
164
|
+
confidence: confidence ?? "provisional",
|
|
165
|
+
schemaLabel: supportRecord.schemaLabel,
|
|
166
|
+
surfaceKind,
|
|
167
|
+
sharedVia,
|
|
168
|
+
requiresPrimary,
|
|
169
|
+
canDeployDirectlyWhenPrimaryAbsent: surfaceKind !== "shared-via" || !requiresPrimary,
|
|
170
|
+
includeInInitByDefault: surfaceKind === "agent-specific",
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
export function resolveCapabilitySurface(agentId, capability, scope = "global") {
|
|
174
|
+
if (capability === "skills")
|
|
175
|
+
return resolveSkillsCapability(agentId);
|
|
176
|
+
const { supportRecord, confidence } = getSurfaceRecordAndConfidence(agentId, capability, scope);
|
|
177
|
+
if (!supportRecord || supportRecord.status === "unsupported") {
|
|
178
|
+
return resolveUnsupportedSurface(agentId, capability, supportRecord, confidence);
|
|
179
|
+
}
|
|
180
|
+
if (supportRecord.status === "planned") {
|
|
181
|
+
return resolvePlannedSurface(agentId, capability, supportRecord, confidence);
|
|
182
|
+
}
|
|
183
|
+
return resolveSupportedSurface(agentId, capability, supportRecord, confidence);
|
|
184
|
+
}
|
|
185
|
+
function createSurfaceWarning(surface, entryName) {
|
|
186
|
+
const label = capabilityLabel(surface.capability);
|
|
187
|
+
if (surface.supportStatus === "unsupported") {
|
|
188
|
+
return {
|
|
189
|
+
kind: "confidence",
|
|
190
|
+
message: `${label}: agent "${surface.agentId}" uses ${surface.schemaLabel} (unsupported) and ${surface.reason ?? "does not expose a supported adapter"} — skipping "${entryName}"`,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
if (surface.supportStatus === "planned") {
|
|
194
|
+
return {
|
|
195
|
+
kind: "confidence",
|
|
196
|
+
message: `${label}: agent "${surface.agentId}" ${capabilitySurfaceLabel(surface.capability)} support is planned via ${surface.plannedSurface} — skipping "${entryName}" until that surface is implemented`,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
if (surface.surfaceKind === "shared-via" && surface.sharedVia) {
|
|
200
|
+
return {
|
|
201
|
+
kind: "confidence",
|
|
202
|
+
message: `${label}: agent "${surface.agentId}" reads this surface via "${surface.sharedVia}" — add "${surface.sharedVia}" to the entry's agents list to deploy to this surface, or deploy via the "${surface.sharedVia}" ${label} target instead`,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
kind: "confidence",
|
|
207
|
+
message: `${label}: agent "${surface.agentId}" does not expose a directly deployable surface — skipping "${entryName}"`,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
export function planCapabilityForDeploy(opts) {
|
|
211
|
+
const surface = resolveCapabilitySurface(opts.agentId, opts.capability, opts.scope);
|
|
212
|
+
if (surface.supportStatus !== "supported") {
|
|
213
|
+
return {
|
|
214
|
+
outcome: "warn",
|
|
215
|
+
warning: createSurfaceWarning(surface, opts.entryName),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
if (surface.surfaceKind === "native") {
|
|
219
|
+
return { outcome: "native" };
|
|
220
|
+
}
|
|
221
|
+
if (surface.surfaceKind === "shared-via" && surface.sharedVia) {
|
|
222
|
+
if (opts.targetAgentIds.includes(surface.sharedVia)) {
|
|
223
|
+
return {
|
|
224
|
+
outcome: "redundant",
|
|
225
|
+
confidence: surface.confidence,
|
|
226
|
+
support: surface.support,
|
|
227
|
+
sharedVia: surface.sharedVia,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
if (!surface.canDeployDirectlyWhenPrimaryAbsent) {
|
|
231
|
+
return {
|
|
232
|
+
outcome: "warn",
|
|
233
|
+
warning: createSurfaceWarning(surface, opts.entryName),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
outcome: "action",
|
|
239
|
+
confidence: surface.confidence,
|
|
240
|
+
support: surface.support,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
export function shouldInitIncludeAgent(agentId, capability, scope = "global") {
|
|
244
|
+
return resolveCapabilitySurface(agentId, capability, scope)
|
|
245
|
+
.includeInInitByDefault;
|
|
246
|
+
}
|
|
247
|
+
export function describeCapabilityConfidence(agentId, capability, scope = "global") {
|
|
248
|
+
const surface = resolveCapabilitySurface(agentId, capability, scope);
|
|
249
|
+
if (surface.supportStatus === "planned") {
|
|
250
|
+
return {
|
|
251
|
+
confidence: surface.confidence,
|
|
252
|
+
message: `Agent "${agentId}" ${capabilitySurfaceLabel(capability)} support remains planned via ${surface.plannedSurface}.`,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
if (surface.supportStatus === "unsupported") {
|
|
256
|
+
return {
|
|
257
|
+
confidence: surface.confidence,
|
|
258
|
+
message: `Agent "${agentId}" ${capabilitySurfaceLabel(capability)} surface is unsupported: ${surface.reason ?? surface.schemaLabel}.`,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
if (surface.surfaceKind === "shared-via" && surface.sharedVia) {
|
|
262
|
+
return {
|
|
263
|
+
confidence: surface.confidence,
|
|
264
|
+
message: `Agent "${agentId}" ${capabilitySurfaceLabel(capability)} surface is shared through "${surface.sharedVia}"${surface.requiresPrimary ? " and requires the primary target to deploy" : ""}.`,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if (surface.confidence === "implementation-only") {
|
|
268
|
+
return {
|
|
269
|
+
confidence: surface.confidence,
|
|
270
|
+
message: `Agent "${agentId}" ${capabilitySurfaceLabel(capability)} support is implementation-only: behavior is based on registry inspection and local validation, not published documentation.`,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
if (surface.confidence === "provisional") {
|
|
274
|
+
return {
|
|
275
|
+
confidence: surface.confidence,
|
|
276
|
+
message: `Agent "${agentId}" ${capabilitySurfaceLabel(capability)} support is provisional: behavior has not been independently verified.`,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
return { confidence: surface.confidence, message: null };
|
|
280
|
+
}
|