agentopology 0.9.2 → 0.10.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 +17 -19
- package/dist/__tests__/e2e/action-guard.test.d.ts +13 -0
- package/dist/__tests__/e2e/action-guard.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/action-guard.test.js +299 -0
- package/dist/__tests__/e2e/action-guard.test.js.map +1 -0
- package/dist/__tests__/e2e/conformance.test.d.ts +13 -0
- package/dist/__tests__/e2e/conformance.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/conformance.test.js +109 -0
- package/dist/__tests__/e2e/conformance.test.js.map +1 -0
- package/dist/__tests__/e2e/contract-drift.test.d.ts +11 -0
- package/dist/__tests__/e2e/contract-drift.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/contract-drift.test.js +142 -0
- package/dist/__tests__/e2e/contract-drift.test.js.map +1 -0
- package/dist/__tests__/e2e/guard-check.test.d.ts +9 -0
- package/dist/__tests__/e2e/guard-check.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/guard-check.test.js +316 -0
- package/dist/__tests__/e2e/guard-check.test.js.map +1 -0
- package/dist/__tests__/e2e/guard-target.test.d.ts +11 -0
- package/dist/__tests__/e2e/guard-target.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/guard-target.test.js +198 -0
- package/dist/__tests__/e2e/guard-target.test.js.map +1 -0
- package/dist/__tests__/e2e/inventory.test.d.ts +18 -0
- package/dist/__tests__/e2e/inventory.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/inventory.test.js +187 -0
- package/dist/__tests__/e2e/inventory.test.js.map +1 -0
- package/dist/__tests__/e2e/matcher.test.d.ts +14 -0
- package/dist/__tests__/e2e/matcher.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/matcher.test.js +145 -0
- package/dist/__tests__/e2e/matcher.test.js.map +1 -0
- package/dist/__tests__/e2e/step-check.test.d.ts +9 -0
- package/dist/__tests__/e2e/step-check.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/step-check.test.js +158 -0
- package/dist/__tests__/e2e/step-check.test.js.map +1 -0
- package/dist/__tests__/e2e/strength.test.d.ts +17 -0
- package/dist/__tests__/e2e/strength.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/strength.test.js +130 -0
- package/dist/__tests__/e2e/strength.test.js.map +1 -0
- package/dist/__tests__/e2e/verified-on.test.d.ts +2 -0
- package/dist/__tests__/e2e/verified-on.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/verified-on.test.js +57 -0
- package/dist/__tests__/e2e/verified-on.test.js.map +1 -0
- package/dist/__tests__/open-findings.test.js +1 -0
- package/dist/__tests__/open-findings.test.js.map +1 -1
- package/dist/bindings/__tests__/bindings.test.js +6 -686
- package/dist/bindings/__tests__/bindings.test.js.map +1 -1
- package/dist/bindings/__tests__/defaults-agreement.test.js +0 -12
- package/dist/bindings/__tests__/defaults-agreement.test.js.map +1 -1
- package/dist/bindings/__tests__/hook-command.test.js +2 -2
- package/dist/bindings/__tests__/hook-command.test.js.map +1 -1
- package/dist/bindings/__tests__/mod-plugin.test.js +2 -2
- package/dist/bindings/__tests__/mod-plugin.test.js.map +1 -1
- package/dist/bindings/claude-code.d.ts +45 -1
- package/dist/bindings/claude-code.d.ts.map +1 -1
- package/dist/bindings/claude-code.js +181 -15
- package/dist/bindings/claude-code.js.map +1 -1
- package/dist/bindings/index.d.ts +5 -5
- package/dist/bindings/index.d.ts.map +1 -1
- package/dist/bindings/index.js +9 -16
- package/dist/bindings/index.js.map +1 -1
- package/dist/bindings/types.d.ts +6 -1
- package/dist/bindings/types.d.ts.map +1 -1
- package/dist/cli/__tests__/cli.test.js +25 -0
- package/dist/cli/__tests__/cli.test.js.map +1 -1
- package/dist/cli/index.js +222 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/conformance/claude-code.d.ts +99 -0
- package/dist/conformance/claude-code.d.ts.map +1 -0
- package/dist/conformance/claude-code.js +242 -0
- package/dist/conformance/claude-code.js.map +1 -0
- package/dist/conformance/extract.d.ts +70 -0
- package/dist/conformance/extract.d.ts.map +1 -0
- package/dist/conformance/extract.js +185 -0
- package/dist/conformance/extract.js.map +1 -0
- package/dist/docs/content.d.ts.map +1 -1
- package/dist/docs/content.js +57 -32
- package/dist/docs/content.js.map +1 -1
- package/dist/guard/check.d.ts +53 -0
- package/dist/guard/check.d.ts.map +1 -0
- package/dist/guard/check.js +366 -0
- package/dist/guard/check.js.map +1 -0
- package/dist/guard/target.d.ts +45 -0
- package/dist/guard/target.d.ts.map +1 -0
- package/dist/guard/target.js +168 -0
- package/dist/guard/target.js.map +1 -0
- package/dist/import/__tests__/import.test.js +0 -554
- package/dist/import/__tests__/import.test.js.map +1 -1
- package/dist/import/index.d.ts +0 -1
- package/dist/import/index.d.ts.map +1 -1
- package/dist/import/index.js +1 -7
- package/dist/import/index.js.map +1 -1
- package/dist/import/serializer.d.ts.map +1 -1
- package/dist/import/serializer.js +41 -0
- package/dist/import/serializer.js.map +1 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/dist/inventory/index.d.ts +65 -0
- package/dist/inventory/index.d.ts.map +1 -0
- package/dist/inventory/index.js +272 -0
- package/dist/inventory/index.js.map +1 -0
- package/dist/parser/ast.d.ts +46 -0
- package/dist/parser/ast.d.ts.map +1 -1
- package/dist/parser/ast.js.map +1 -1
- package/dist/parser/index.d.ts +6 -1
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/index.js +66 -4
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/known-fields.d.ts +3 -0
- package/dist/parser/known-fields.d.ts.map +1 -1
- package/dist/parser/known-fields.js +5 -3
- package/dist/parser/known-fields.js.map +1 -1
- package/dist/parser/ledger.d.ts +36 -0
- package/dist/parser/ledger.d.ts.map +1 -0
- package/dist/parser/ledger.js +72 -0
- package/dist/parser/ledger.js.map +1 -0
- package/dist/parser/run.d.ts +6 -0
- package/dist/parser/run.d.ts.map +1 -1
- package/dist/parser/run.js +10 -0
- package/dist/parser/run.js.map +1 -1
- package/dist/parser/validator.d.ts.map +1 -1
- package/dist/parser/validator.js +255 -1
- package/dist/parser/validator.js.map +1 -1
- package/dist/scaffold/manifest.d.ts.map +1 -1
- package/dist/scaffold/manifest.js +0 -8
- package/dist/scaffold/manifest.js.map +1 -1
- package/dist/scaffold/merge.d.ts.map +1 -1
- package/dist/scaffold/merge.js +1 -3
- package/dist/scaffold/merge.js.map +1 -1
- package/dist/step/check.d.ts +56 -0
- package/dist/step/check.d.ts.map +1 -0
- package/dist/step/check.js +125 -0
- package/dist/step/check.js.map +1 -0
- package/dist/sync/index.d.ts +0 -2
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +0 -109
- package/dist/sync/index.js.map +1 -1
- package/package.json +3 -1
- package/spec/claude-code/README.md +19 -0
- package/spec/claude-code/hooks-contract.2.1.295.json +143 -0
- package/spec/claude-code/hooks-contract.json +142 -0
- package/spec/grammar.md +45 -7
- package/spec/testing.md +15 -0
- package/spec/validation.md +11 -2
- package/dist/__tests__/live/zz-debug.test.d.ts +0 -2
- package/dist/__tests__/live/zz-debug.test.d.ts.map +0 -1
- package/dist/__tests__/live/zz-debug.test.js +0 -4
- package/dist/__tests__/live/zz-debug.test.js.map +0 -1
- package/dist/bindings/copilot-cli.d.ts +0 -20
- package/dist/bindings/copilot-cli.d.ts.map +0 -1
- package/dist/bindings/copilot-cli.js +0 -1516
- package/dist/bindings/copilot-cli.js.map +0 -1
- package/dist/bindings/gemini-cli.d.ts +0 -18
- package/dist/bindings/gemini-cli.d.ts.map +0 -1
- package/dist/bindings/gemini-cli.js +0 -1318
- package/dist/bindings/gemini-cli.js.map +0 -1
- package/dist/bindings/kiro.d.ts +0 -17
- package/dist/bindings/kiro.d.ts.map +0 -1
- package/dist/bindings/kiro.js +0 -1615
- package/dist/bindings/kiro.js.map +0 -1
- package/dist/bindings/openclaw.d.ts +0 -18
- package/dist/bindings/openclaw.d.ts.map +0 -1
- package/dist/bindings/openclaw.js +0 -1947
- package/dist/bindings/openclaw.js.map +0 -1
- package/dist/import/openclaw.d.ts +0 -70
- package/dist/import/openclaw.d.ts.map +0 -1
- package/dist/import/openclaw.js +0 -1060
- package/dist/import/openclaw.js.map +0 -1
package/dist/bindings/kiro.js
DELETED
|
@@ -1,1615 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Kiro CLI binding.
|
|
3
|
-
*
|
|
4
|
-
* Generates the `.kiro/` directory structure, `AGENTS.md`, and supporting
|
|
5
|
-
* files from a parsed {@link TopologyAST}.
|
|
6
|
-
*
|
|
7
|
-
* Kiro uses JSON-based agent definitions (`.kiro/agents/<id>.json`),
|
|
8
|
-
* markdown steering documents (`.kiro/steering/`), and MCP configuration
|
|
9
|
-
* (`.kiro/settings/mcp.json`). Unlike Claude Code where agents are markdown
|
|
10
|
-
* files with frontmatter, Kiro agents are plain JSON.
|
|
11
|
-
*
|
|
12
|
-
* @module
|
|
13
|
-
*/
|
|
14
|
-
import { deduplicateFiles } from "./types.js";
|
|
15
|
-
import { shellStub } from "./lib/stub.js";
|
|
16
|
-
import { byPhase } from "../resolve/phase.js";
|
|
17
|
-
import { gateAnchors } from "../parser/ast.js";
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
|
-
// Helpers
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
/** Convert a kebab-case id to Title Case. */
|
|
22
|
-
function toTitle(id) {
|
|
23
|
-
return id
|
|
24
|
-
.split(/[-_]/)
|
|
25
|
-
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
26
|
-
.join(" ");
|
|
27
|
-
}
|
|
28
|
-
/** Generate an empty directory marker (a .gitkeep file). */
|
|
29
|
-
function gitkeep(dirPath) {
|
|
30
|
-
return { path: `${dirPath}/.gitkeep`, content: "", category: "machine" };
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Map topology hook event names to Kiro event names.
|
|
34
|
-
*
|
|
35
|
-
* Kiro uses camelCase event names (preToolUse, postToolUse) instead of
|
|
36
|
-
* PascalCase (PreToolUse, PostToolUse).
|
|
37
|
-
*/
|
|
38
|
-
function mapHookEvent(event) {
|
|
39
|
-
const eventMap = {
|
|
40
|
-
PreToolUse: "preToolUse",
|
|
41
|
-
PostToolUse: "postToolUse",
|
|
42
|
-
};
|
|
43
|
-
return eventMap[event] ?? event;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Map topology tool names to Kiro tool names.
|
|
47
|
-
*
|
|
48
|
-
* Kiro uses lowercase tool names with fs_ prefixes for file operations.
|
|
49
|
-
*/
|
|
50
|
-
function mapToolName(tool) {
|
|
51
|
-
const toolMap = {
|
|
52
|
-
Read: "read",
|
|
53
|
-
Write: "write",
|
|
54
|
-
Bash: "shell",
|
|
55
|
-
Edit: "write",
|
|
56
|
-
};
|
|
57
|
-
return toolMap[tool] ?? tool.toLowerCase();
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Map topology tool names to Kiro hook matcher names.
|
|
61
|
-
*
|
|
62
|
-
* For hook matchers, Kiro uses the fs_read/fs_write/execute_bash convention.
|
|
63
|
-
*/
|
|
64
|
-
function mapMatcherName(matcher) {
|
|
65
|
-
const matcherMap = {
|
|
66
|
-
Read: "fs_read",
|
|
67
|
-
Write: "fs_write",
|
|
68
|
-
Bash: "execute_bash",
|
|
69
|
-
Edit: "fs_write",
|
|
70
|
-
};
|
|
71
|
-
return matcherMap[matcher] ?? matcher;
|
|
72
|
-
}
|
|
73
|
-
/** Format a SchemaType to a human-readable string. */
|
|
74
|
-
function formatSchemaType(t) {
|
|
75
|
-
switch (t.kind) {
|
|
76
|
-
case "primitive":
|
|
77
|
-
return t.value;
|
|
78
|
-
case "array":
|
|
79
|
-
return `${formatSchemaType(t.itemType)}[]`;
|
|
80
|
-
case "enum":
|
|
81
|
-
return t.values.join(" | ");
|
|
82
|
-
case "ref":
|
|
83
|
-
return t.name;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
/** Format schema fields as a markdown list. */
|
|
87
|
-
function formatSchemaFields(fields) {
|
|
88
|
-
return fields
|
|
89
|
-
.map((f) => `- \`${f.name}${f.optional ? "?" : ""}\`: ${formatSchemaType(f.type)}`)
|
|
90
|
-
.join("\n");
|
|
91
|
-
}
|
|
92
|
-
// ---------------------------------------------------------------------------
|
|
93
|
-
// Agent JSON generation
|
|
94
|
-
// ---------------------------------------------------------------------------
|
|
95
|
-
/**
|
|
96
|
-
* Generate `.kiro/agents/<id>.json` for each agent node.
|
|
97
|
-
*
|
|
98
|
-
* Each agent produces a single JSON file with name, description, prompt,
|
|
99
|
-
* model, tools, hooks, resources, and MCP configuration.
|
|
100
|
-
*
|
|
101
|
-
* NOTE: The `.kiro/agents/` JSON format is not publicly documented by Kiro.
|
|
102
|
-
* This generates a reasonable agent config structure that may need validation
|
|
103
|
-
* against actual Kiro when the format is finalized.
|
|
104
|
-
*/
|
|
105
|
-
function generateAgents(ast) {
|
|
106
|
-
const files = [];
|
|
107
|
-
for (const node of ast.nodes) {
|
|
108
|
-
if (node.type !== "agent")
|
|
109
|
-
continue;
|
|
110
|
-
const agent = node;
|
|
111
|
-
const agentJson = {};
|
|
112
|
-
agentJson.name = agent.id;
|
|
113
|
-
// Description: prefer agent.description, then role description
|
|
114
|
-
const desc = agent.description ??
|
|
115
|
-
ast.roles[agent.role ?? ""] ??
|
|
116
|
-
ast.roles[agent.id] ??
|
|
117
|
-
agent.role;
|
|
118
|
-
if (desc) {
|
|
119
|
-
agentJson.description = desc;
|
|
120
|
-
}
|
|
121
|
-
// Prompt: build from role + inline prompt
|
|
122
|
-
const promptParts = [];
|
|
123
|
-
const roleText = ast.roles[agent.role ?? ""] ?? ast.roles[agent.id] ?? agent.role;
|
|
124
|
-
if (roleText) {
|
|
125
|
-
promptParts.push(`You are the ${toTitle(agent.id)} agent.\n\n## Role\n${roleText}`);
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
promptParts.push(`You are the ${toTitle(agent.id)} agent.`);
|
|
129
|
-
}
|
|
130
|
-
if (agent.prompt) {
|
|
131
|
-
promptParts.push(`\n## Instructions\n\n${agent.prompt}`);
|
|
132
|
-
}
|
|
133
|
-
if (agent.reads && agent.reads.length > 0) {
|
|
134
|
-
promptParts.push(`\n## Reads\n${agent.reads.map((r) => `- ${r}`).join("\n")}`);
|
|
135
|
-
}
|
|
136
|
-
if (agent.writes && agent.writes.length > 0) {
|
|
137
|
-
promptParts.push(`\n## Writes\n${agent.writes.map((w) => `- ${w}`).join("\n")}`);
|
|
138
|
-
}
|
|
139
|
-
if (agent.outputs) {
|
|
140
|
-
const outputLines = Object.entries(agent.outputs)
|
|
141
|
-
.map(([field, values]) => `- ${field}: ${values.join(" | ")}`)
|
|
142
|
-
.join("\n");
|
|
143
|
-
promptParts.push(`\n## Outputs\n${outputLines}`);
|
|
144
|
-
}
|
|
145
|
-
if (agent.skills && agent.skills.length > 0) {
|
|
146
|
-
promptParts.push(`\nSkills: ${agent.skills.join(", ")}`);
|
|
147
|
-
}
|
|
148
|
-
if (agent.behavior) {
|
|
149
|
-
promptParts.push(`\nBehavior: ${agent.behavior}`);
|
|
150
|
-
}
|
|
151
|
-
if (agent.skip) {
|
|
152
|
-
promptParts.push(`\nSkip when: ${agent.skip}`);
|
|
153
|
-
}
|
|
154
|
-
agentJson.prompt = promptParts.join("\n");
|
|
155
|
-
// Model
|
|
156
|
-
if (agent.model) {
|
|
157
|
-
agentJson.model = agent.model;
|
|
158
|
-
}
|
|
159
|
-
// Fields not in Kiro's agent JSON schema — embed in prompt instead
|
|
160
|
-
// (Kiro only supports: name, description, prompt, model, mcpServers,
|
|
161
|
-
// tools, toolAliases, allowedTools, resources, hooks, toolsSettings,
|
|
162
|
-
// includeMcpJson, keyboardShortcut, welcomeMessage)
|
|
163
|
-
const constraints = [];
|
|
164
|
-
if (agent.timeout)
|
|
165
|
-
constraints.push(`Maximum execution time: ${agent.timeout}`);
|
|
166
|
-
if (agent.temperature != null)
|
|
167
|
-
constraints.push(`Temperature: ${agent.temperature}`);
|
|
168
|
-
if (agent.maxTokens != null)
|
|
169
|
-
constraints.push(`Max tokens: ${agent.maxTokens}`);
|
|
170
|
-
if (agent.thinking)
|
|
171
|
-
constraints.push(`Reasoning level: ${agent.thinking}`);
|
|
172
|
-
if (agent.maxTurns != null)
|
|
173
|
-
constraints.push(`Max turns: ${agent.maxTurns}`);
|
|
174
|
-
if (constraints.length > 0) {
|
|
175
|
-
agentJson.prompt += "\n\n## Constraints\n" + constraints.map((c) => `- ${c}`).join("\n");
|
|
176
|
-
}
|
|
177
|
-
// Tools — map topology tool names to Kiro names
|
|
178
|
-
if (agent.tools && agent.tools.length > 0) {
|
|
179
|
-
agentJson.tools = agent.tools.map(mapToolName);
|
|
180
|
-
}
|
|
181
|
-
// Allowed tools (subset that don't require confirmation)
|
|
182
|
-
if (agent.extensions?.kiro?.allowedTools) {
|
|
183
|
-
agentJson.allowedTools = agent.extensions.kiro.allowedTools;
|
|
184
|
-
}
|
|
185
|
-
// MCP servers — inline the full MCP server config from ast.mcpServers
|
|
186
|
-
if (agent.mcpServers && agent.mcpServers.length > 0) {
|
|
187
|
-
const mcpServers = {};
|
|
188
|
-
for (const serverName of agent.mcpServers) {
|
|
189
|
-
const serverConfig = ast.mcpServers[serverName];
|
|
190
|
-
if (serverConfig) {
|
|
191
|
-
const entry = { ...serverConfig };
|
|
192
|
-
// Strip type field for stdio servers (Kiro auto-detects)
|
|
193
|
-
if (entry.command) {
|
|
194
|
-
delete entry.type;
|
|
195
|
-
}
|
|
196
|
-
mcpServers[serverName] = entry;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
if (Object.keys(mcpServers).length > 0) {
|
|
200
|
-
agentJson.mcpServers = mcpServers;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
// Per-agent hooks — object keyed by event name
|
|
204
|
-
if (agent.hooks && agent.hooks.length > 0) {
|
|
205
|
-
const hooksObj = {};
|
|
206
|
-
for (const hook of agent.hooks) {
|
|
207
|
-
const eventName = mapHookEvent(hook.on);
|
|
208
|
-
if (!hooksObj[eventName]) {
|
|
209
|
-
hooksObj[eventName] = [];
|
|
210
|
-
}
|
|
211
|
-
const entry = {
|
|
212
|
-
command: hook.run,
|
|
213
|
-
};
|
|
214
|
-
if (hook.matcher) {
|
|
215
|
-
entry.matcher = mapMatcherName(hook.matcher);
|
|
216
|
-
}
|
|
217
|
-
hooksObj[eventName].push(entry);
|
|
218
|
-
}
|
|
219
|
-
agentJson.hooks = hooksObj;
|
|
220
|
-
}
|
|
221
|
-
// Merge kiro extension fields
|
|
222
|
-
if (agent.extensions?.kiro) {
|
|
223
|
-
const handled = new Set(["allowedTools"]);
|
|
224
|
-
for (const [k, v] of Object.entries(agent.extensions.kiro)) {
|
|
225
|
-
if (handled.has(k))
|
|
226
|
-
continue;
|
|
227
|
-
agentJson[k] = v;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
files.push({
|
|
231
|
-
path: `.kiro/agents/${agent.id}.json`,
|
|
232
|
-
content: JSON.stringify(agentJson, null, 2) + "\n",
|
|
233
|
-
category: "machine",
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
return files;
|
|
237
|
-
}
|
|
238
|
-
// ---------------------------------------------------------------------------
|
|
239
|
-
// Per-agent steering docs for Wave 1-7 features
|
|
240
|
-
// ---------------------------------------------------------------------------
|
|
241
|
-
/**
|
|
242
|
-
* Generate `.kiro/steering/agent-<id>.md` for agents with behavioral config
|
|
243
|
-
* that cannot be expressed in JSON (on-fail, retry, circuitBreaker, schemas,
|
|
244
|
-
* rate limits, artifacts, join semantics, output format, log level, variants).
|
|
245
|
-
*/
|
|
246
|
-
function generateAgentSteering(ast) {
|
|
247
|
-
const files = [];
|
|
248
|
-
for (const node of ast.nodes) {
|
|
249
|
-
if (node.type !== "agent")
|
|
250
|
-
continue;
|
|
251
|
-
const agent = node;
|
|
252
|
-
const sections = [];
|
|
253
|
-
let hasContent = false;
|
|
254
|
-
// on-fail / retry (Wave 1)
|
|
255
|
-
if (agent.onFail) {
|
|
256
|
-
sections.push(`## Failure Handling`);
|
|
257
|
-
sections.push("");
|
|
258
|
-
sections.push(`On failure: **${agent.onFail}**`);
|
|
259
|
-
sections.push("");
|
|
260
|
-
hasContent = true;
|
|
261
|
-
}
|
|
262
|
-
if (agent.retry != null) {
|
|
263
|
-
if (!sections.some((s) => s.includes("Failure Handling"))) {
|
|
264
|
-
sections.push(`## Failure Handling`);
|
|
265
|
-
sections.push("");
|
|
266
|
-
}
|
|
267
|
-
if (typeof agent.retry === "number") {
|
|
268
|
-
sections.push(`Retry up to **${agent.retry}** times on failure.`);
|
|
269
|
-
}
|
|
270
|
-
else {
|
|
271
|
-
const r = agent.retry;
|
|
272
|
-
sections.push(`Retry up to **${r.max}** times.`);
|
|
273
|
-
if (r.backoff)
|
|
274
|
-
sections.push(`- Backoff: ${r.backoff}`);
|
|
275
|
-
if (r.interval)
|
|
276
|
-
sections.push(`- Interval: ${r.interval}`);
|
|
277
|
-
if (r.maxInterval)
|
|
278
|
-
sections.push(`- Max interval: ${r.maxInterval}`);
|
|
279
|
-
if (r.jitter)
|
|
280
|
-
sections.push(`- Jitter: enabled`);
|
|
281
|
-
if (r.nonRetryable && r.nonRetryable.length > 0) {
|
|
282
|
-
sections.push(`- Non-retryable: ${r.nonRetryable.join(", ")}`);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
sections.push("");
|
|
286
|
-
hasContent = true;
|
|
287
|
-
}
|
|
288
|
-
// circuitBreaker (Wave 5)
|
|
289
|
-
if (agent.circuitBreaker) {
|
|
290
|
-
const cb = agent.circuitBreaker;
|
|
291
|
-
sections.push(`## Circuit Breaker`);
|
|
292
|
-
sections.push("");
|
|
293
|
-
sections.push(`- Threshold: ${cb.threshold} failures`);
|
|
294
|
-
sections.push(`- Window: ${cb.window}`);
|
|
295
|
-
sections.push(`- Cooldown: ${cb.cooldown}`);
|
|
296
|
-
sections.push("");
|
|
297
|
-
hasContent = true;
|
|
298
|
-
}
|
|
299
|
-
// compensates (Wave 5 — saga)
|
|
300
|
-
if (agent.compensates) {
|
|
301
|
-
sections.push(`## Compensation`);
|
|
302
|
-
sections.push("");
|
|
303
|
-
sections.push(`This agent compensates (undoes side effects of) **${agent.compensates}**.`);
|
|
304
|
-
sections.push("");
|
|
305
|
-
hasContent = true;
|
|
306
|
-
}
|
|
307
|
-
// inputSchema / outputSchema (Wave 3)
|
|
308
|
-
if (agent.inputSchema && agent.inputSchema.length > 0) {
|
|
309
|
-
sections.push(`## Input Schema`);
|
|
310
|
-
sections.push("");
|
|
311
|
-
sections.push(formatSchemaFields(agent.inputSchema));
|
|
312
|
-
sections.push("");
|
|
313
|
-
hasContent = true;
|
|
314
|
-
}
|
|
315
|
-
if (agent.outputSchema && agent.outputSchema.length > 0) {
|
|
316
|
-
sections.push(`## Output Schema`);
|
|
317
|
-
sections.push("");
|
|
318
|
-
sections.push(formatSchemaFields(agent.outputSchema));
|
|
319
|
-
sections.push("");
|
|
320
|
-
hasContent = true;
|
|
321
|
-
}
|
|
322
|
-
// rateLimit (Wave 6)
|
|
323
|
-
if (agent.rateLimit) {
|
|
324
|
-
sections.push(`## Rate Limit`);
|
|
325
|
-
sections.push("");
|
|
326
|
-
sections.push(`Rate limit: **${agent.rateLimit}**`);
|
|
327
|
-
sections.push("");
|
|
328
|
-
hasContent = true;
|
|
329
|
-
}
|
|
330
|
-
// produces / consumes (Wave 6 — artifacts)
|
|
331
|
-
if (agent.produces && agent.produces.length > 0) {
|
|
332
|
-
sections.push(`## Produces`);
|
|
333
|
-
sections.push("");
|
|
334
|
-
sections.push(agent.produces.map((a) => `- ${a}`).join("\n"));
|
|
335
|
-
sections.push("");
|
|
336
|
-
hasContent = true;
|
|
337
|
-
}
|
|
338
|
-
if (agent.consumes && agent.consumes.length > 0) {
|
|
339
|
-
sections.push(`## Consumes`);
|
|
340
|
-
sections.push("");
|
|
341
|
-
sections.push(agent.consumes.map((a) => `- ${a}`).join("\n"));
|
|
342
|
-
sections.push("");
|
|
343
|
-
hasContent = true;
|
|
344
|
-
}
|
|
345
|
-
// join (Wave 2)
|
|
346
|
-
if (agent.join) {
|
|
347
|
-
sections.push(`## Join Strategy`);
|
|
348
|
-
sections.push("");
|
|
349
|
-
sections.push(`Wait strategy: **${agent.join}**`);
|
|
350
|
-
sections.push("");
|
|
351
|
-
hasContent = true;
|
|
352
|
-
}
|
|
353
|
-
// outputFormat (Wave 1)
|
|
354
|
-
if (agent.outputFormat) {
|
|
355
|
-
sections.push(`## Output Format`);
|
|
356
|
-
sections.push("");
|
|
357
|
-
sections.push(`Expected output format: **${agent.outputFormat}**`);
|
|
358
|
-
sections.push("");
|
|
359
|
-
hasContent = true;
|
|
360
|
-
}
|
|
361
|
-
// logLevel (Wave 3)
|
|
362
|
-
if (agent.logLevel) {
|
|
363
|
-
sections.push(`## Log Level`);
|
|
364
|
-
sections.push("");
|
|
365
|
-
sections.push(`Log level: **${agent.logLevel}**`);
|
|
366
|
-
sections.push("");
|
|
367
|
-
hasContent = true;
|
|
368
|
-
}
|
|
369
|
-
// variants (Wave 7 — A/B testing)
|
|
370
|
-
if (agent.variants && agent.variants.length > 0) {
|
|
371
|
-
sections.push(`## Prompt Variants`);
|
|
372
|
-
sections.push("");
|
|
373
|
-
for (const v of agent.variants) {
|
|
374
|
-
const parts = [`**${v.id}** (weight: ${v.weight})`];
|
|
375
|
-
if (v.model)
|
|
376
|
-
parts.push(`model: ${v.model}`);
|
|
377
|
-
if (v.temperature != null)
|
|
378
|
-
parts.push(`temperature: ${v.temperature}`);
|
|
379
|
-
sections.push(`- ${parts.join(", ")}`);
|
|
380
|
-
if (v.prompt) {
|
|
381
|
-
sections.push(` > ${v.prompt.replace(/\n/g, "\n > ")}`);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
sections.push("");
|
|
385
|
-
hasContent = true;
|
|
386
|
-
}
|
|
387
|
-
if (!hasContent)
|
|
388
|
-
continue;
|
|
389
|
-
// Determine inclusion mode: fileMatch if agent has reads/writes paths,
|
|
390
|
-
// otherwise always.
|
|
391
|
-
const allPaths = [
|
|
392
|
-
...(agent.reads ?? []),
|
|
393
|
-
...(agent.writes ?? []),
|
|
394
|
-
];
|
|
395
|
-
const headerLines = ["---"];
|
|
396
|
-
if (allPaths.length > 0) {
|
|
397
|
-
headerLines.push("inclusion: fileMatch");
|
|
398
|
-
// Combine all read/write paths into a glob pattern
|
|
399
|
-
const pattern = allPaths.length === 1
|
|
400
|
-
? allPaths[0].replace(/\/$/, "/**")
|
|
401
|
-
: `{${allPaths.map((p) => p.replace(/\/$/, "/**")).join(",")}}`;
|
|
402
|
-
headerLines.push(`fileMatchPattern: "${pattern}"`);
|
|
403
|
-
}
|
|
404
|
-
else {
|
|
405
|
-
headerLines.push("inclusion: always");
|
|
406
|
-
}
|
|
407
|
-
headerLines.push("---");
|
|
408
|
-
headerLines.push("");
|
|
409
|
-
headerLines.push(`# ${toTitle(agent.id)} — Behavioral Config`);
|
|
410
|
-
headerLines.push("");
|
|
411
|
-
const header = headerLines;
|
|
412
|
-
files.push({
|
|
413
|
-
path: `.kiro/steering/agent-${agent.id}.md`,
|
|
414
|
-
content: header.join("\n") + sections.join("\n") + "\n",
|
|
415
|
-
category: "machine",
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
return files;
|
|
419
|
-
}
|
|
420
|
-
// ---------------------------------------------------------------------------
|
|
421
|
-
// Human node steering docs
|
|
422
|
-
// ---------------------------------------------------------------------------
|
|
423
|
-
/**
|
|
424
|
-
* Generate `.kiro/steering/human-<id>.md` for human-in-the-loop pause points.
|
|
425
|
-
*/
|
|
426
|
-
function generateHumanSteering(ast) {
|
|
427
|
-
const files = [];
|
|
428
|
-
for (const node of ast.nodes) {
|
|
429
|
-
if (node.type !== "human")
|
|
430
|
-
continue;
|
|
431
|
-
const human = node;
|
|
432
|
-
const sections = [
|
|
433
|
-
"---",
|
|
434
|
-
"inclusion: always",
|
|
435
|
-
"---",
|
|
436
|
-
"",
|
|
437
|
-
`# ${toTitle(human.id)} — Human Pause Point`,
|
|
438
|
-
"",
|
|
439
|
-
];
|
|
440
|
-
if (human.description) {
|
|
441
|
-
sections.push(human.description);
|
|
442
|
-
sections.push("");
|
|
443
|
-
}
|
|
444
|
-
sections.push("## Behavior");
|
|
445
|
-
sections.push("");
|
|
446
|
-
sections.push("This is a human-in-the-loop pause point. Stop and wait for human input before continuing.");
|
|
447
|
-
sections.push("");
|
|
448
|
-
if (human.timeout) {
|
|
449
|
-
sections.push(`- Timeout: ${human.timeout}`);
|
|
450
|
-
}
|
|
451
|
-
if (human.onTimeout) {
|
|
452
|
-
sections.push(`- On timeout: ${human.onTimeout}`);
|
|
453
|
-
}
|
|
454
|
-
if (human.timeout || human.onTimeout) {
|
|
455
|
-
sections.push("");
|
|
456
|
-
}
|
|
457
|
-
files.push({
|
|
458
|
-
path: `.kiro/steering/human-${human.id}.md`,
|
|
459
|
-
content: sections.join("\n") + "\n",
|
|
460
|
-
category: "machine",
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
return files;
|
|
464
|
-
}
|
|
465
|
-
// ---------------------------------------------------------------------------
|
|
466
|
-
// Group node steering docs
|
|
467
|
-
// ---------------------------------------------------------------------------
|
|
468
|
-
/**
|
|
469
|
-
* Generate `.kiro/steering/group-<id>.md` for group chat coordination nodes.
|
|
470
|
-
*/
|
|
471
|
-
function generateGroupSteering(ast) {
|
|
472
|
-
const files = [];
|
|
473
|
-
for (const node of ast.nodes) {
|
|
474
|
-
if (node.type !== "group")
|
|
475
|
-
continue;
|
|
476
|
-
const group = node;
|
|
477
|
-
const sections = [
|
|
478
|
-
"---",
|
|
479
|
-
"inclusion: always",
|
|
480
|
-
"---",
|
|
481
|
-
"",
|
|
482
|
-
`# ${toTitle(group.id)} — Group Chat`,
|
|
483
|
-
"",
|
|
484
|
-
];
|
|
485
|
-
if (group.description) {
|
|
486
|
-
sections.push(group.description);
|
|
487
|
-
sections.push("");
|
|
488
|
-
}
|
|
489
|
-
sections.push("## Coordination");
|
|
490
|
-
sections.push("");
|
|
491
|
-
sections.push(`Members: ${group.members.join(", ")}`);
|
|
492
|
-
if (group.speakerSelection) {
|
|
493
|
-
sections.push(`Speaker selection: ${group.speakerSelection}`);
|
|
494
|
-
}
|
|
495
|
-
if (group.maxRounds != null) {
|
|
496
|
-
sections.push(`Max rounds: ${group.maxRounds}`);
|
|
497
|
-
}
|
|
498
|
-
if (group.termination) {
|
|
499
|
-
sections.push(`Termination: ${group.termination}`);
|
|
500
|
-
}
|
|
501
|
-
if (group.timeout) {
|
|
502
|
-
sections.push(`Timeout: ${group.timeout}`);
|
|
503
|
-
}
|
|
504
|
-
sections.push("");
|
|
505
|
-
files.push({
|
|
506
|
-
path: `.kiro/steering/group-${group.id}.md`,
|
|
507
|
-
content: sections.join("\n") + "\n",
|
|
508
|
-
category: "machine",
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
return files;
|
|
512
|
-
}
|
|
513
|
-
// ---------------------------------------------------------------------------
|
|
514
|
-
// Steering documents
|
|
515
|
-
// ---------------------------------------------------------------------------
|
|
516
|
-
/**
|
|
517
|
-
* Generate `.kiro/steering/product.md` — product context with topology
|
|
518
|
-
* description, version, and patterns.
|
|
519
|
-
*/
|
|
520
|
-
function generateProductSteering(ast) {
|
|
521
|
-
const sections = [];
|
|
522
|
-
sections.push("---");
|
|
523
|
-
sections.push("inclusion: always");
|
|
524
|
-
sections.push("---");
|
|
525
|
-
sections.push("");
|
|
526
|
-
sections.push("# Product Context");
|
|
527
|
-
sections.push("");
|
|
528
|
-
if (ast.topology.description) {
|
|
529
|
-
sections.push(ast.topology.description);
|
|
530
|
-
sections.push("");
|
|
531
|
-
}
|
|
532
|
-
sections.push(`Version: ${ast.topology.version}`);
|
|
533
|
-
if (ast.topology.patterns.length > 0) {
|
|
534
|
-
sections.push(`Patterns: ${ast.topology.patterns.join(", ")}`);
|
|
535
|
-
}
|
|
536
|
-
sections.push("");
|
|
537
|
-
// Schedules
|
|
538
|
-
if (ast.schedules && ast.schedules.length > 0) {
|
|
539
|
-
sections.push("## Schedules");
|
|
540
|
-
sections.push("");
|
|
541
|
-
for (const job of ast.schedules) {
|
|
542
|
-
const expr = job.cron
|
|
543
|
-
? `cron: ${job.cron}`
|
|
544
|
-
: job.every
|
|
545
|
-
? `every: ${job.every}`
|
|
546
|
-
: "";
|
|
547
|
-
const target = job.agent
|
|
548
|
-
? `agent: ${job.agent}`
|
|
549
|
-
: job.action
|
|
550
|
-
? `action: ${job.action}`
|
|
551
|
-
: "";
|
|
552
|
-
sections.push(`- **${job.id}**: ${expr}${target ? ` -> ${target}` : ""}${job.enabled === false ? " (disabled)" : ""}`);
|
|
553
|
-
}
|
|
554
|
-
sections.push("");
|
|
555
|
-
}
|
|
556
|
-
// Interfaces
|
|
557
|
-
if (ast.interfaces && ast.interfaces.length > 0) {
|
|
558
|
-
sections.push("## Interfaces");
|
|
559
|
-
sections.push("");
|
|
560
|
-
for (const iface of ast.interfaces) {
|
|
561
|
-
const typePart = iface.type ? ` (${iface.type})` : "";
|
|
562
|
-
const configKeys = Object.keys(iface.config);
|
|
563
|
-
const configPart = configKeys.length > 0
|
|
564
|
-
? ` — ${configKeys.map((k) => `${k}: ${iface.config[k]}`).join(", ")}`
|
|
565
|
-
: "";
|
|
566
|
-
sections.push(`- **${iface.id}**${typePart}${configPart}`);
|
|
567
|
-
}
|
|
568
|
-
sections.push("");
|
|
569
|
-
}
|
|
570
|
-
// Depth levels
|
|
571
|
-
if (ast.depth && ast.depth.levels && ast.depth.levels.length > 0) {
|
|
572
|
-
sections.push("## Depth Levels");
|
|
573
|
-
sections.push("");
|
|
574
|
-
if (ast.depth.factors.length > 0) {
|
|
575
|
-
sections.push(`Factors: ${ast.depth.factors.join(", ")}`);
|
|
576
|
-
}
|
|
577
|
-
for (const level of ast.depth.levels) {
|
|
578
|
-
let line = `- **Level ${level.level}**: ${level.label}`;
|
|
579
|
-
if (level.omit.length > 0)
|
|
580
|
-
line += ` (omit: ${level.omit.join(", ")})`;
|
|
581
|
-
sections.push(line);
|
|
582
|
-
}
|
|
583
|
-
sections.push("");
|
|
584
|
-
}
|
|
585
|
-
// Composition: params
|
|
586
|
-
if (ast.params && ast.params.length > 0) {
|
|
587
|
-
sections.push("## Parameters");
|
|
588
|
-
sections.push("");
|
|
589
|
-
for (const p of ast.params) {
|
|
590
|
-
const req = p.required ? " (required)" : "";
|
|
591
|
-
const def = p.default != null ? ` = ${p.default}` : "";
|
|
592
|
-
sections.push(`- **${p.name}**: ${p.type}${req}${def}`);
|
|
593
|
-
}
|
|
594
|
-
sections.push("");
|
|
595
|
-
}
|
|
596
|
-
// Composition: interface endpoints
|
|
597
|
-
if (ast.interfaceEndpoints) {
|
|
598
|
-
sections.push("## Interface");
|
|
599
|
-
sections.push("");
|
|
600
|
-
sections.push(`- Entry: ${ast.interfaceEndpoints.entry}`);
|
|
601
|
-
sections.push(`- Exit: ${ast.interfaceEndpoints.exit}`);
|
|
602
|
-
sections.push("");
|
|
603
|
-
}
|
|
604
|
-
// Composition: imports
|
|
605
|
-
if (ast.imports && ast.imports.length > 0) {
|
|
606
|
-
sections.push("## Imports");
|
|
607
|
-
sections.push("");
|
|
608
|
-
for (const imp of ast.imports) {
|
|
609
|
-
let line = `- **${imp.alias}** from \`${imp.source}\``;
|
|
610
|
-
if (imp.sha256)
|
|
611
|
-
line += ` (sha256: ${imp.sha256})`;
|
|
612
|
-
if (imp.registry)
|
|
613
|
-
line += ` [registry: ${imp.registryPackage}@${imp.registryVersion}]`;
|
|
614
|
-
sections.push(line);
|
|
615
|
-
if (Object.keys(imp.params).length > 0) {
|
|
616
|
-
for (const [k, v] of Object.entries(imp.params)) {
|
|
617
|
-
sections.push(` - ${k}: ${v}`);
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
sections.push("");
|
|
622
|
-
}
|
|
623
|
-
// Composition: includes
|
|
624
|
-
if (ast.includes && ast.includes.length > 0) {
|
|
625
|
-
sections.push("## Includes");
|
|
626
|
-
sections.push("");
|
|
627
|
-
for (const inc of ast.includes) {
|
|
628
|
-
sections.push(`- ${inc.source}`);
|
|
629
|
-
}
|
|
630
|
-
sections.push("");
|
|
631
|
-
}
|
|
632
|
-
// Defaults
|
|
633
|
-
if (ast.defaults) {
|
|
634
|
-
const d = ast.defaults;
|
|
635
|
-
const items = [];
|
|
636
|
-
if (d.thinking)
|
|
637
|
-
items.push(`thinking: ${d.thinking}`);
|
|
638
|
-
if (d.thinkingBudget)
|
|
639
|
-
items.push(`thinking-budget: ${d.thinkingBudget}`);
|
|
640
|
-
if (d.temperature != null)
|
|
641
|
-
items.push(`temperature: ${d.temperature}`);
|
|
642
|
-
if (d.maxTokens != null)
|
|
643
|
-
items.push(`max-tokens: ${d.maxTokens}`);
|
|
644
|
-
if (d.topP != null)
|
|
645
|
-
items.push(`top-p: ${d.topP}`);
|
|
646
|
-
if (d.topK != null)
|
|
647
|
-
items.push(`top-k: ${d.topK}`);
|
|
648
|
-
if (d.seed != null)
|
|
649
|
-
items.push(`seed: ${d.seed}`);
|
|
650
|
-
if (d.timeout)
|
|
651
|
-
items.push(`timeout: ${d.timeout}`);
|
|
652
|
-
if (d.outputFormat)
|
|
653
|
-
items.push(`output-format: ${d.outputFormat}`);
|
|
654
|
-
if (d.logLevel)
|
|
655
|
-
items.push(`log-level: ${d.logLevel}`);
|
|
656
|
-
if (d.stop && d.stop.length > 0)
|
|
657
|
-
items.push(`stop: ${d.stop.join(", ")}`);
|
|
658
|
-
if (items.length > 0) {
|
|
659
|
-
sections.push("## Defaults");
|
|
660
|
-
sections.push("");
|
|
661
|
-
for (const item of items)
|
|
662
|
-
sections.push(`- ${item}`);
|
|
663
|
-
sections.push("");
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
// Artifacts
|
|
667
|
-
if (ast.artifacts && ast.artifacts.length > 0) {
|
|
668
|
-
sections.push("## Artifacts");
|
|
669
|
-
sections.push("");
|
|
670
|
-
for (const art of ast.artifacts) {
|
|
671
|
-
let line = `- **${art.id}** (${art.type})`;
|
|
672
|
-
if (art.path)
|
|
673
|
-
line += ` — path: ${art.path}`;
|
|
674
|
-
if (art.retention)
|
|
675
|
-
line += `, retention: ${art.retention}`;
|
|
676
|
-
if (art.dependsOn && art.dependsOn.length > 0)
|
|
677
|
-
line += `, depends on: ${art.dependsOn.join(", ")}`;
|
|
678
|
-
sections.push(line);
|
|
679
|
-
}
|
|
680
|
-
sections.push("");
|
|
681
|
-
}
|
|
682
|
-
// Observability
|
|
683
|
-
if (ast.observability && ast.observability.enabled) {
|
|
684
|
-
sections.push("## Observability");
|
|
685
|
-
sections.push("");
|
|
686
|
-
sections.push(`- Level: ${ast.observability.level}`);
|
|
687
|
-
sections.push(`- Exporter: ${ast.observability.exporter}`);
|
|
688
|
-
if (ast.observability.endpoint)
|
|
689
|
-
sections.push(`- Endpoint: ${ast.observability.endpoint}`);
|
|
690
|
-
if (ast.observability.service)
|
|
691
|
-
sections.push(`- Service: ${ast.observability.service}`);
|
|
692
|
-
sections.push(`- Sample rate: ${ast.observability.sampleRate}`);
|
|
693
|
-
const cap = ast.observability.capture;
|
|
694
|
-
if (cap) {
|
|
695
|
-
sections.push(`- Capture: prompts=${cap.prompts}, completions=${cap.completions}, tool-args=${cap.toolArgs}, tool-results=${cap.toolResults}`);
|
|
696
|
-
}
|
|
697
|
-
const sp = ast.observability.spans;
|
|
698
|
-
if (sp) {
|
|
699
|
-
sections.push(`- Spans: agents=${sp.agents}, tools=${sp.tools}, gates=${sp.gates}, memory=${sp.memory}`);
|
|
700
|
-
}
|
|
701
|
-
sections.push("");
|
|
702
|
-
}
|
|
703
|
-
// Checkpoint
|
|
704
|
-
if (ast.checkpoint) {
|
|
705
|
-
sections.push("## Checkpoint");
|
|
706
|
-
sections.push("");
|
|
707
|
-
sections.push(`- Backend: ${ast.checkpoint.backend}`);
|
|
708
|
-
sections.push(`- Strategy: ${ast.checkpoint.strategy}`);
|
|
709
|
-
if (ast.checkpoint.connection)
|
|
710
|
-
sections.push(`- Connection: ${ast.checkpoint.connection}`);
|
|
711
|
-
if (ast.checkpoint.ttl)
|
|
712
|
-
sections.push(`- TTL: ${ast.checkpoint.ttl}`);
|
|
713
|
-
if (ast.checkpoint.replay) {
|
|
714
|
-
sections.push(`- Replay: enabled=${ast.checkpoint.replay.enabled}${ast.checkpoint.replay.maxHistory ? `, maxHistory=${ast.checkpoint.replay.maxHistory}` : ""}${ast.checkpoint.replay.branch ? ", branching enabled" : ""}`);
|
|
715
|
-
}
|
|
716
|
-
sections.push("");
|
|
717
|
-
}
|
|
718
|
-
return {
|
|
719
|
-
path: ".kiro/steering/product.md",
|
|
720
|
-
content: sections.join("\n") + "\n",
|
|
721
|
-
category: "machine",
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
/**
|
|
725
|
-
* Generate `.kiro/steering/tech.md` — technology context with models,
|
|
726
|
-
* tool configuration, and provider settings.
|
|
727
|
-
*/
|
|
728
|
-
function generateTechSteering(ast) {
|
|
729
|
-
const sections = [];
|
|
730
|
-
sections.push("---");
|
|
731
|
-
sections.push("inclusion: always");
|
|
732
|
-
sections.push("---");
|
|
733
|
-
sections.push("");
|
|
734
|
-
sections.push("# Technology");
|
|
735
|
-
sections.push("");
|
|
736
|
-
// Models used
|
|
737
|
-
const models = new Set();
|
|
738
|
-
for (const node of ast.nodes) {
|
|
739
|
-
if (node.type === "orchestrator") {
|
|
740
|
-
models.add(node.model);
|
|
741
|
-
}
|
|
742
|
-
else if (node.type === "agent" && node.model) {
|
|
743
|
-
models.add(node.model);
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
if (models.size > 0) {
|
|
747
|
-
sections.push("## Models");
|
|
748
|
-
sections.push("");
|
|
749
|
-
for (const model of models) {
|
|
750
|
-
sections.push(`- ${model}`);
|
|
751
|
-
}
|
|
752
|
-
sections.push("");
|
|
753
|
-
}
|
|
754
|
-
// Providers
|
|
755
|
-
if (ast.providers && ast.providers.length > 0) {
|
|
756
|
-
sections.push("## Providers");
|
|
757
|
-
sections.push("");
|
|
758
|
-
for (const p of ast.providers) {
|
|
759
|
-
const parts = [p.name];
|
|
760
|
-
if (p.baseUrl)
|
|
761
|
-
parts.push(`base: ${p.baseUrl}`);
|
|
762
|
-
if (p.default)
|
|
763
|
-
parts.push("(default)");
|
|
764
|
-
sections.push(`- ${parts.join(" — ")}`);
|
|
765
|
-
}
|
|
766
|
-
sections.push("");
|
|
767
|
-
}
|
|
768
|
-
// Tools
|
|
769
|
-
if (ast.toolDefs.length > 0) {
|
|
770
|
-
sections.push("## Tools");
|
|
771
|
-
sections.push("");
|
|
772
|
-
for (const tool of ast.toolDefs) {
|
|
773
|
-
sections.push(`- **${tool.id}**: ${tool.description}`);
|
|
774
|
-
}
|
|
775
|
-
sections.push("");
|
|
776
|
-
}
|
|
777
|
-
// Skills summary
|
|
778
|
-
if (ast.skills.length > 0) {
|
|
779
|
-
sections.push("## Skills");
|
|
780
|
-
sections.push("");
|
|
781
|
-
for (const skill of ast.skills) {
|
|
782
|
-
const desc = skill.description ? ` — ${skill.description}` : "";
|
|
783
|
-
sections.push(`- **${skill.id}**${desc}`);
|
|
784
|
-
}
|
|
785
|
-
sections.push("");
|
|
786
|
-
}
|
|
787
|
-
// Environment variables
|
|
788
|
-
if (Object.keys(ast.env).length > 0) {
|
|
789
|
-
sections.push("## Environment");
|
|
790
|
-
sections.push("");
|
|
791
|
-
for (const [key, val] of Object.entries(ast.env)) {
|
|
792
|
-
const value = typeof val === "string" ? val : val.value;
|
|
793
|
-
sections.push(`- \`${key}\`: ${value}`);
|
|
794
|
-
}
|
|
795
|
-
sections.push("");
|
|
796
|
-
}
|
|
797
|
-
return {
|
|
798
|
-
path: ".kiro/steering/tech.md",
|
|
799
|
-
content: sections.join("\n") + "\n",
|
|
800
|
-
category: "machine",
|
|
801
|
-
};
|
|
802
|
-
}
|
|
803
|
-
/**
|
|
804
|
-
* Generate `.kiro/steering/structure.md` — file organization with
|
|
805
|
-
* memory layout and read/write patterns.
|
|
806
|
-
*/
|
|
807
|
-
function generateStructureSteering(ast) {
|
|
808
|
-
const sections = [];
|
|
809
|
-
sections.push("---");
|
|
810
|
-
sections.push("inclusion: always");
|
|
811
|
-
sections.push("---");
|
|
812
|
-
sections.push("");
|
|
813
|
-
sections.push("# Structure");
|
|
814
|
-
sections.push("");
|
|
815
|
-
// Memory layout
|
|
816
|
-
if (Object.keys(ast.memory).length > 0) {
|
|
817
|
-
sections.push("## Memory Layout");
|
|
818
|
-
sections.push("");
|
|
819
|
-
if (ast.memory.domains) {
|
|
820
|
-
sections.push("- **Domains:** .kiro/domains/");
|
|
821
|
-
}
|
|
822
|
-
if (ast.memory.references) {
|
|
823
|
-
sections.push("- **References:** .kiro/references/");
|
|
824
|
-
}
|
|
825
|
-
if (ast.memory.metrics) {
|
|
826
|
-
sections.push("- **Metrics:** .kiro/metrics.jsonl");
|
|
827
|
-
}
|
|
828
|
-
if (ast.memory.workspace) {
|
|
829
|
-
sections.push("- **Workspace:** .kiro/runs/");
|
|
830
|
-
}
|
|
831
|
-
sections.push("");
|
|
832
|
-
}
|
|
833
|
-
// Read/Write patterns
|
|
834
|
-
const agents = ast.nodes.filter((n) => n.type === "agent");
|
|
835
|
-
const agentsWithAccess = agents.filter((a) => (a.reads && a.reads.length > 0) || (a.writes && a.writes.length > 0));
|
|
836
|
-
if (agentsWithAccess.length > 0) {
|
|
837
|
-
sections.push("## Read/Write Patterns");
|
|
838
|
-
sections.push("");
|
|
839
|
-
for (const agent of agentsWithAccess) {
|
|
840
|
-
sections.push(`### ${toTitle(agent.id)}`);
|
|
841
|
-
if (agent.reads && agent.reads.length > 0) {
|
|
842
|
-
sections.push(`- Reads: ${agent.reads.join(", ")}`);
|
|
843
|
-
}
|
|
844
|
-
if (agent.writes && agent.writes.length > 0) {
|
|
845
|
-
sections.push(`- Writes: ${agent.writes.join(", ")}`);
|
|
846
|
-
}
|
|
847
|
-
sections.push("");
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
// Workspace protocol
|
|
851
|
-
const workspace = ast.memory.workspace;
|
|
852
|
-
if (workspace?.structure && Array.isArray(workspace.structure)) {
|
|
853
|
-
sections.push("## Workspace Structure");
|
|
854
|
-
sections.push("");
|
|
855
|
-
for (const item of workspace.structure) {
|
|
856
|
-
sections.push(`- ${item}`);
|
|
857
|
-
}
|
|
858
|
-
sections.push("");
|
|
859
|
-
}
|
|
860
|
-
return {
|
|
861
|
-
path: ".kiro/steering/structure.md",
|
|
862
|
-
content: sections.join("\n") + "\n",
|
|
863
|
-
category: "machine",
|
|
864
|
-
};
|
|
865
|
-
}
|
|
866
|
-
// ---------------------------------------------------------------------------
|
|
867
|
-
// MCP configuration
|
|
868
|
-
// ---------------------------------------------------------------------------
|
|
869
|
-
/**
|
|
870
|
-
* Generate `.kiro/settings/mcp.json` — MCP server configuration.
|
|
871
|
-
*
|
|
872
|
-
* Nearly identical to Claude Code's .mcp.json format: an object with a
|
|
873
|
-
* `mcpServers` key mapping server names to their configuration.
|
|
874
|
-
*/
|
|
875
|
-
function generateMcpJson(ast) {
|
|
876
|
-
if (Object.keys(ast.mcpServers).length === 0)
|
|
877
|
-
return null;
|
|
878
|
-
// Collect per-server autonomous status from agent declarations
|
|
879
|
-
// If ANY agent using this server has permissions: autonomous, use ["*"]
|
|
880
|
-
const serverHasAutonomousAgent = new Map();
|
|
881
|
-
const serverDisabledTools = new Map();
|
|
882
|
-
for (const node of ast.nodes) {
|
|
883
|
-
if (node.type !== "agent")
|
|
884
|
-
continue;
|
|
885
|
-
const agent = node;
|
|
886
|
-
if (!agent.mcpServers || agent.mcpServers.length === 0)
|
|
887
|
-
continue;
|
|
888
|
-
for (const serverName of agent.mcpServers) {
|
|
889
|
-
if (agent.permissions === "autonomous") {
|
|
890
|
-
serverHasAutonomousAgent.set(serverName, true);
|
|
891
|
-
}
|
|
892
|
-
// Agent disallowedTools -> disabledTools (only plain names, no patterns)
|
|
893
|
-
if (agent.disallowedTools && agent.disallowedTools.length > 0) {
|
|
894
|
-
if (!serverDisabledTools.has(serverName)) {
|
|
895
|
-
serverDisabledTools.set(serverName, new Set());
|
|
896
|
-
}
|
|
897
|
-
for (const tool of agent.disallowedTools) {
|
|
898
|
-
// Only include plain tool names (no parentheses = no patterns)
|
|
899
|
-
if (!tool.includes("(")) {
|
|
900
|
-
serverDisabledTools.get(serverName).add(tool);
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
// Collect topology-level settings deny, filtering out patterns
|
|
907
|
-
const settingsDeny = ast.settings?.deny;
|
|
908
|
-
const mcpConfig = { mcpServers: {} };
|
|
909
|
-
const servers = mcpConfig.mcpServers;
|
|
910
|
-
for (const [name, config] of Object.entries(ast.mcpServers)) {
|
|
911
|
-
const entry = {};
|
|
912
|
-
let hasEnv = false;
|
|
913
|
-
for (const [key, value] of Object.entries(config)) {
|
|
914
|
-
if (key === "args" && Array.isArray(value)) {
|
|
915
|
-
entry.args = value;
|
|
916
|
-
}
|
|
917
|
-
else {
|
|
918
|
-
entry[key] = value;
|
|
919
|
-
}
|
|
920
|
-
if (key === "env")
|
|
921
|
-
hasEnv = true;
|
|
922
|
-
}
|
|
923
|
-
// Strip type field for stdio servers (Kiro auto-detects)
|
|
924
|
-
if (entry.command) {
|
|
925
|
-
delete entry.type;
|
|
926
|
-
}
|
|
927
|
-
// Always include env field
|
|
928
|
-
if (!hasEnv) {
|
|
929
|
-
entry.env = {};
|
|
930
|
-
}
|
|
931
|
-
// disabled: false by default
|
|
932
|
-
entry.disabled = false;
|
|
933
|
-
// autoApprove: ["*"] for autonomous agents, omit for supervised
|
|
934
|
-
if (serverHasAutonomousAgent.get(name)) {
|
|
935
|
-
entry.autoApprove = ["*"];
|
|
936
|
-
}
|
|
937
|
-
// disabledTools: merge agent-level disallowedTools + settings deny (plain names only)
|
|
938
|
-
const disableSet = new Set(serverDisabledTools.get(name) ?? []);
|
|
939
|
-
if (settingsDeny) {
|
|
940
|
-
for (const tool of settingsDeny) {
|
|
941
|
-
// Only include plain tool names (no parentheses = no patterns)
|
|
942
|
-
if (!tool.includes("(")) {
|
|
943
|
-
disableSet.add(tool);
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
if (disableSet.size > 0) {
|
|
948
|
-
entry.disabledTools = [...disableSet];
|
|
949
|
-
}
|
|
950
|
-
servers[name] = entry;
|
|
951
|
-
}
|
|
952
|
-
return {
|
|
953
|
-
path: ".kiro/settings/mcp.json",
|
|
954
|
-
content: JSON.stringify(mcpConfig, null, 2) + "\n",
|
|
955
|
-
category: "machine",
|
|
956
|
-
};
|
|
957
|
-
}
|
|
958
|
-
// ---------------------------------------------------------------------------
|
|
959
|
-
// Trigger / prompt files
|
|
960
|
-
// ---------------------------------------------------------------------------
|
|
961
|
-
/**
|
|
962
|
-
* Generate `.kiro/prompts/<trigger-name>.md` — one file per trigger.
|
|
963
|
-
*/
|
|
964
|
-
function generatePromptFiles(ast) {
|
|
965
|
-
const files = [];
|
|
966
|
-
for (const trigger of ast.triggers) {
|
|
967
|
-
const sections = [];
|
|
968
|
-
sections.push(`# /${trigger.name}`);
|
|
969
|
-
sections.push("");
|
|
970
|
-
sections.push(trigger.pattern);
|
|
971
|
-
sections.push("");
|
|
972
|
-
if (trigger.argument) {
|
|
973
|
-
sections.push("## Arguments");
|
|
974
|
-
sections.push(`- ${trigger.argument}: extracted from the command pattern`);
|
|
975
|
-
sections.push("");
|
|
976
|
-
}
|
|
977
|
-
// Pipeline (from edges)
|
|
978
|
-
if (ast.edges.length > 0) {
|
|
979
|
-
sections.push("## Pipeline");
|
|
980
|
-
for (const edge of ast.edges) {
|
|
981
|
-
let line = `${edge.from} -> ${edge.to}`;
|
|
982
|
-
if (edge.condition)
|
|
983
|
-
line += ` [when ${edge.condition}]`;
|
|
984
|
-
sections.push(`- ${line}`);
|
|
985
|
-
}
|
|
986
|
-
sections.push("");
|
|
987
|
-
}
|
|
988
|
-
// Agents table
|
|
989
|
-
const agents = ast.nodes.filter((n) => n.type === "agent");
|
|
990
|
-
if (agents.length > 0) {
|
|
991
|
-
sections.push("## Agents");
|
|
992
|
-
sections.push("| Agent | Phase | Model | Role |");
|
|
993
|
-
sections.push("|-------|-------|-------|------|");
|
|
994
|
-
for (const agent of agents) {
|
|
995
|
-
const phase = agent.phase != null ? String(agent.phase) : "-";
|
|
996
|
-
const model = agent.model ?? "-";
|
|
997
|
-
const role = agent.role ?? "-";
|
|
998
|
-
sections.push(`| ${agent.id} | ${phase} | ${model} | ${role} |`);
|
|
999
|
-
}
|
|
1000
|
-
sections.push("");
|
|
1001
|
-
}
|
|
1002
|
-
files.push({
|
|
1003
|
-
path: `.kiro/prompts/${trigger.name}.md`,
|
|
1004
|
-
content: sections.join("\n") + "\n",
|
|
1005
|
-
category: "machine",
|
|
1006
|
-
});
|
|
1007
|
-
}
|
|
1008
|
-
return files;
|
|
1009
|
-
}
|
|
1010
|
-
// ---------------------------------------------------------------------------
|
|
1011
|
-
// AGENTS.md — top-level project context with flow narrative
|
|
1012
|
-
// ---------------------------------------------------------------------------
|
|
1013
|
-
/**
|
|
1014
|
-
* Generate `AGENTS.md` — top-level project context.
|
|
1015
|
-
*
|
|
1016
|
-
* Kiro has no native orchestration, so the flow graph is expressed as
|
|
1017
|
-
* prose in AGENTS.md to give the AI context about the multi-agent workflow.
|
|
1018
|
-
*/
|
|
1019
|
-
function generateAgentsMd(ast) {
|
|
1020
|
-
const sections = [];
|
|
1021
|
-
const name = ast.topology.name;
|
|
1022
|
-
sections.push(`# ${toTitle(name)} — Agent Topology`);
|
|
1023
|
-
sections.push("");
|
|
1024
|
-
if (ast.topology.description) {
|
|
1025
|
-
sections.push(ast.topology.description);
|
|
1026
|
-
sections.push("");
|
|
1027
|
-
}
|
|
1028
|
-
sections.push(`Version: ${ast.topology.version}`);
|
|
1029
|
-
if (ast.topology.patterns.length > 0) {
|
|
1030
|
-
sections.push(`Patterns: ${ast.topology.patterns.join(", ")}`);
|
|
1031
|
-
}
|
|
1032
|
-
sections.push("");
|
|
1033
|
-
// Orchestrator
|
|
1034
|
-
const orch = ast.nodes.find((n) => n.type === "orchestrator");
|
|
1035
|
-
if (orch) {
|
|
1036
|
-
sections.push("## Orchestrator");
|
|
1037
|
-
sections.push("");
|
|
1038
|
-
sections.push(`Model: ${orch.model}`);
|
|
1039
|
-
if (orch.handles?.length > 0) {
|
|
1040
|
-
sections.push(`Handles: ${orch.handles.join(", ")}`);
|
|
1041
|
-
}
|
|
1042
|
-
if (orch.generates) {
|
|
1043
|
-
sections.push(`Generates: ${orch.generates}`);
|
|
1044
|
-
}
|
|
1045
|
-
sections.push("");
|
|
1046
|
-
}
|
|
1047
|
-
// Flow (enhanced with Wave 2+ edge attributes)
|
|
1048
|
-
if (ast.edges.length > 0) {
|
|
1049
|
-
sections.push("## Flow");
|
|
1050
|
-
sections.push("");
|
|
1051
|
-
for (const edge of ast.edges) {
|
|
1052
|
-
const arrow = edge.isError ? `-x${edge.errorType ? `[${edge.errorType}]` : ""}->` : "->";
|
|
1053
|
-
let line = `${edge.from} ${arrow} ${edge.to}`;
|
|
1054
|
-
if (edge.condition)
|
|
1055
|
-
line += ` [when ${edge.condition}]`;
|
|
1056
|
-
if (edge.maxIterations)
|
|
1057
|
-
line += ` [max ${edge.maxIterations}]`;
|
|
1058
|
-
if (edge.weight != null)
|
|
1059
|
-
line += ` [weight ${edge.weight}]`;
|
|
1060
|
-
if (edge.race)
|
|
1061
|
-
line += ` [race]`;
|
|
1062
|
-
if (edge.tolerance != null)
|
|
1063
|
-
line += ` [tolerance: ${edge.tolerance}]`;
|
|
1064
|
-
if (edge.wait)
|
|
1065
|
-
line += ` [wait ${edge.wait}]`;
|
|
1066
|
-
if (edge.reflection)
|
|
1067
|
-
line += ` (reflection)`;
|
|
1068
|
-
sections.push(`- ${line}`);
|
|
1069
|
-
}
|
|
1070
|
-
sections.push("");
|
|
1071
|
-
}
|
|
1072
|
-
// Agent summary table
|
|
1073
|
-
const agents = ast.nodes.filter((n) => n.type === "agent");
|
|
1074
|
-
if (agents.length > 0) {
|
|
1075
|
-
sections.push("## Agents");
|
|
1076
|
-
sections.push("");
|
|
1077
|
-
for (const agent of agents) {
|
|
1078
|
-
sections.push(`### ${toTitle(agent.id)}`);
|
|
1079
|
-
sections.push("");
|
|
1080
|
-
const roleText = ast.roles[agent.role ?? ""] ?? ast.roles[agent.id] ?? agent.role;
|
|
1081
|
-
if (roleText) {
|
|
1082
|
-
sections.push(`**Role:** ${roleText}`);
|
|
1083
|
-
sections.push("");
|
|
1084
|
-
}
|
|
1085
|
-
if (agent.description) {
|
|
1086
|
-
sections.push(agent.description);
|
|
1087
|
-
sections.push("");
|
|
1088
|
-
}
|
|
1089
|
-
if (agent.model) {
|
|
1090
|
-
sections.push(`- **Model:** ${agent.model}`);
|
|
1091
|
-
}
|
|
1092
|
-
if (agent.phase != null) {
|
|
1093
|
-
sections.push(`- **Phase:** ${agent.phase}`);
|
|
1094
|
-
}
|
|
1095
|
-
if (agent.tools && agent.tools.length > 0) {
|
|
1096
|
-
sections.push(`- **Tools:** ${agent.tools.join(", ")}`);
|
|
1097
|
-
}
|
|
1098
|
-
if (agent.reads && agent.reads.length > 0) {
|
|
1099
|
-
sections.push(`- **Reads:** ${agent.reads.join(", ")}`);
|
|
1100
|
-
}
|
|
1101
|
-
if (agent.writes && agent.writes.length > 0) {
|
|
1102
|
-
sections.push(`- **Writes:** ${agent.writes.join(", ")}`);
|
|
1103
|
-
}
|
|
1104
|
-
if (agent.behavior) {
|
|
1105
|
-
sections.push(`- **Behavior:** ${agent.behavior}`);
|
|
1106
|
-
}
|
|
1107
|
-
sections.push("");
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
// Gates
|
|
1111
|
-
const gates = ast.nodes.filter((n) => n.type === "gate");
|
|
1112
|
-
if (gates.length > 0) {
|
|
1113
|
-
sections.push("## Gates");
|
|
1114
|
-
sections.push("");
|
|
1115
|
-
for (const gate of gates) {
|
|
1116
|
-
sections.push(`### ${toTitle(gate.id)}`);
|
|
1117
|
-
if (gate.after)
|
|
1118
|
-
sections.push(`After: ${gateAnchors(gate, "after").join(", ")}`);
|
|
1119
|
-
if (gate.before)
|
|
1120
|
-
sections.push(`Before: ${gateAnchors(gate, "before").join(", ")}`);
|
|
1121
|
-
if (gate.run)
|
|
1122
|
-
sections.push(`Run: ${gate.run}`);
|
|
1123
|
-
if (gate.checks && gate.checks.length > 0) {
|
|
1124
|
-
sections.push(`Checks: ${gate.checks.join(", ")}`);
|
|
1125
|
-
}
|
|
1126
|
-
if (gate.onFail)
|
|
1127
|
-
sections.push(`On fail: ${gate.onFail}`);
|
|
1128
|
-
sections.push("");
|
|
1129
|
-
}
|
|
1130
|
-
}
|
|
1131
|
-
// Human nodes
|
|
1132
|
-
const humans = ast.nodes.filter((n) => n.type === "human");
|
|
1133
|
-
if (humans.length > 0) {
|
|
1134
|
-
sections.push("## Human Pause Points");
|
|
1135
|
-
sections.push("");
|
|
1136
|
-
for (const human of humans) {
|
|
1137
|
-
sections.push(`### ${toTitle(human.id)}`);
|
|
1138
|
-
if (human.description)
|
|
1139
|
-
sections.push(human.description);
|
|
1140
|
-
if (human.timeout)
|
|
1141
|
-
sections.push(`- **Timeout:** ${human.timeout}`);
|
|
1142
|
-
if (human.onTimeout)
|
|
1143
|
-
sections.push(`- **On timeout:** ${human.onTimeout}`);
|
|
1144
|
-
sections.push("");
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
|
-
// Group nodes
|
|
1148
|
-
const groups = ast.nodes.filter((n) => n.type === "group");
|
|
1149
|
-
if (groups.length > 0) {
|
|
1150
|
-
sections.push("## Group Chats");
|
|
1151
|
-
sections.push("");
|
|
1152
|
-
for (const group of groups) {
|
|
1153
|
-
sections.push(`### ${toTitle(group.id)}`);
|
|
1154
|
-
if (group.description)
|
|
1155
|
-
sections.push(group.description);
|
|
1156
|
-
sections.push(`- **Members:** ${group.members.join(", ")}`);
|
|
1157
|
-
if (group.speakerSelection)
|
|
1158
|
-
sections.push(`- **Speaker selection:** ${group.speakerSelection}`);
|
|
1159
|
-
if (group.maxRounds != null)
|
|
1160
|
-
sections.push(`- **Max rounds:** ${group.maxRounds}`);
|
|
1161
|
-
if (group.termination)
|
|
1162
|
-
sections.push(`- **Termination:** ${group.termination}`);
|
|
1163
|
-
if (group.timeout)
|
|
1164
|
-
sections.push(`- **Timeout:** ${group.timeout}`);
|
|
1165
|
-
sections.push("");
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
|
-
// Triggers
|
|
1169
|
-
if (ast.triggers.length > 0) {
|
|
1170
|
-
sections.push("## Triggers");
|
|
1171
|
-
sections.push("");
|
|
1172
|
-
for (const trigger of ast.triggers) {
|
|
1173
|
-
sections.push(`### /${trigger.name}`);
|
|
1174
|
-
sections.push(`Pattern: \`${trigger.pattern}\``);
|
|
1175
|
-
if (trigger.argument)
|
|
1176
|
-
sections.push(`Argument: ${trigger.argument}`);
|
|
1177
|
-
sections.push("");
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
return {
|
|
1181
|
-
path: "AGENTS.md",
|
|
1182
|
-
content: sections.join("\n") + "\n",
|
|
1183
|
-
category: "agent",
|
|
1184
|
-
};
|
|
1185
|
-
}
|
|
1186
|
-
// ---------------------------------------------------------------------------
|
|
1187
|
-
// Hook scripts
|
|
1188
|
-
// ---------------------------------------------------------------------------
|
|
1189
|
-
/** Generate hook script stubs under .kiro/scripts/. */
|
|
1190
|
-
function generateHookScripts(ast) {
|
|
1191
|
-
const files = [];
|
|
1192
|
-
for (const hook of ast.hooks) {
|
|
1193
|
-
if (!hook.run)
|
|
1194
|
-
continue;
|
|
1195
|
-
const scriptName = hook.run.replace(/^.*\//, "").replace(/\s.*$/, "");
|
|
1196
|
-
files.push({
|
|
1197
|
-
path: `.kiro/scripts/${scriptName}`,
|
|
1198
|
-
content: [
|
|
1199
|
-
"#!/usr/bin/env bash",
|
|
1200
|
-
`# Hook: ${hook.name} — fires on ${mapHookEvent(hook.on)}`,
|
|
1201
|
-
"# Auto-generated by agentopology scaffold — edit as needed.",
|
|
1202
|
-
"set -euo pipefail",
|
|
1203
|
-
"",
|
|
1204
|
-
`echo "TODO: implement ${hook.name} hook"`,
|
|
1205
|
-
"",
|
|
1206
|
-
].join("\n"),
|
|
1207
|
-
category: "script",
|
|
1208
|
-
});
|
|
1209
|
-
}
|
|
1210
|
-
return files;
|
|
1211
|
-
}
|
|
1212
|
-
// ---------------------------------------------------------------------------
|
|
1213
|
-
// Gate scripts
|
|
1214
|
-
// ---------------------------------------------------------------------------
|
|
1215
|
-
/** Generate gate script stubs under .kiro/scripts/. */
|
|
1216
|
-
function generateGateScripts(ast) {
|
|
1217
|
-
const files = [];
|
|
1218
|
-
for (const node of ast.nodes) {
|
|
1219
|
-
if (node.type !== "gate")
|
|
1220
|
-
continue;
|
|
1221
|
-
const gate = node;
|
|
1222
|
-
if (gate.run) {
|
|
1223
|
-
const scriptName = gate.run.replace(/^.*\//, "").replace(/\s.*$/, "");
|
|
1224
|
-
files.push({
|
|
1225
|
-
path: `.kiro/scripts/${scriptName}`,
|
|
1226
|
-
content: shellStub(`Gate: ${gate.id} — ${gate.run}`),
|
|
1227
|
-
category: "script",
|
|
1228
|
-
});
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
return files;
|
|
1232
|
-
}
|
|
1233
|
-
// ---------------------------------------------------------------------------
|
|
1234
|
-
// Tool scripts
|
|
1235
|
-
// ---------------------------------------------------------------------------
|
|
1236
|
-
/** Generate tool script stubs under .kiro/scripts/. */
|
|
1237
|
-
function generateToolScripts(ast) {
|
|
1238
|
-
const files = [];
|
|
1239
|
-
for (const tool of ast.toolDefs) {
|
|
1240
|
-
const ext = tool.lang === "python" ? "py" : tool.lang === "node" ? "js" : "sh";
|
|
1241
|
-
const shebang = tool.lang === "python"
|
|
1242
|
-
? "#!/usr/bin/env python3"
|
|
1243
|
-
: tool.lang === "node"
|
|
1244
|
-
? "#!/usr/bin/env node"
|
|
1245
|
-
: "#!/usr/bin/env bash";
|
|
1246
|
-
const lines = [
|
|
1247
|
-
shebang,
|
|
1248
|
-
`# Tool: ${tool.id} — ${tool.description}`,
|
|
1249
|
-
"# Auto-generated by agentopology scaffold — edit as needed.",
|
|
1250
|
-
"",
|
|
1251
|
-
];
|
|
1252
|
-
if (tool.lang === "bash" || !tool.lang) {
|
|
1253
|
-
lines.push("set -euo pipefail");
|
|
1254
|
-
lines.push("");
|
|
1255
|
-
}
|
|
1256
|
-
if (tool.args && tool.args.length > 0) {
|
|
1257
|
-
lines.push(`# Args: ${tool.args.join(", ")}`);
|
|
1258
|
-
lines.push("");
|
|
1259
|
-
}
|
|
1260
|
-
if (tool.lang === "python") {
|
|
1261
|
-
lines.push(`print("TODO: implement ${tool.id}")`);
|
|
1262
|
-
}
|
|
1263
|
-
else if (tool.lang === "node") {
|
|
1264
|
-
lines.push(`console.log("TODO: implement ${tool.id}");`);
|
|
1265
|
-
}
|
|
1266
|
-
else {
|
|
1267
|
-
lines.push(`echo "TODO: implement ${tool.id}"`);
|
|
1268
|
-
}
|
|
1269
|
-
lines.push("");
|
|
1270
|
-
files.push({
|
|
1271
|
-
path: `.kiro/scripts/${tool.id}.${ext}`,
|
|
1272
|
-
content: lines.join("\n"),
|
|
1273
|
-
category: "script",
|
|
1274
|
-
});
|
|
1275
|
-
}
|
|
1276
|
-
return files;
|
|
1277
|
-
}
|
|
1278
|
-
// ---------------------------------------------------------------------------
|
|
1279
|
-
// Memory directories
|
|
1280
|
-
// ---------------------------------------------------------------------------
|
|
1281
|
-
/** Generate memory structure directories under .kiro/. */
|
|
1282
|
-
function generateMemory(ast) {
|
|
1283
|
-
const files = [];
|
|
1284
|
-
if (ast.memory.domains) {
|
|
1285
|
-
files.push(gitkeep(".kiro/domains"));
|
|
1286
|
-
}
|
|
1287
|
-
if (ast.memory.references) {
|
|
1288
|
-
files.push(gitkeep(".kiro/references"));
|
|
1289
|
-
}
|
|
1290
|
-
if (ast.memory.metrics) {
|
|
1291
|
-
files.push({
|
|
1292
|
-
path: ".kiro/metrics.jsonl",
|
|
1293
|
-
content: "",
|
|
1294
|
-
category: "machine",
|
|
1295
|
-
});
|
|
1296
|
-
}
|
|
1297
|
-
if (ast.memory.workspace) {
|
|
1298
|
-
files.push(gitkeep(".kiro/runs"));
|
|
1299
|
-
}
|
|
1300
|
-
return files;
|
|
1301
|
-
}
|
|
1302
|
-
// ---------------------------------------------------------------------------
|
|
1303
|
-
// Metering script
|
|
1304
|
-
// ---------------------------------------------------------------------------
|
|
1305
|
-
/** Generate metering script stub. */
|
|
1306
|
-
function generateMetering(ast) {
|
|
1307
|
-
if (!ast.metering)
|
|
1308
|
-
return null;
|
|
1309
|
-
const m = ast.metering;
|
|
1310
|
-
const lines = [
|
|
1311
|
-
"#!/usr/bin/env bash",
|
|
1312
|
-
"# Metering / cost tracking script",
|
|
1313
|
-
"# Auto-generated by agentopology scaffold — edit as needed.",
|
|
1314
|
-
"set -euo pipefail",
|
|
1315
|
-
"",
|
|
1316
|
-
`# Track: ${m.track.join(", ")}`,
|
|
1317
|
-
`# Per: ${m.per.join(", ")}`,
|
|
1318
|
-
`# Output: ${m.output} (${m.format})`,
|
|
1319
|
-
`# Pricing: ${m.pricing}`,
|
|
1320
|
-
"",
|
|
1321
|
-
'echo "TODO: implement metrics collection"',
|
|
1322
|
-
"",
|
|
1323
|
-
];
|
|
1324
|
-
return {
|
|
1325
|
-
path: "scripts/collect-metrics.sh",
|
|
1326
|
-
content: lines.join("\n"),
|
|
1327
|
-
category: "script",
|
|
1328
|
-
};
|
|
1329
|
-
}
|
|
1330
|
-
// ---------------------------------------------------------------------------
|
|
1331
|
-
// Gate hooks
|
|
1332
|
-
// ---------------------------------------------------------------------------
|
|
1333
|
-
/**
|
|
1334
|
-
* Generate `.kiro/hooks/gate-{id}.kiro.hook` JSON files for each enforced gate.
|
|
1335
|
-
*
|
|
1336
|
-
* Kiro hooks are individual JSON files in `.kiro/hooks/` with trigger metadata.
|
|
1337
|
-
* Each gate with `run:` and non-advisory behavior gets a hook file that
|
|
1338
|
-
* fires when files in the gate's `after` agent's writes paths are edited.
|
|
1339
|
-
*/
|
|
1340
|
-
function generateGateHooks(ast) {
|
|
1341
|
-
const files = [];
|
|
1342
|
-
// Build a map of agent writes paths for file pattern matching
|
|
1343
|
-
const agentWrites = new Map();
|
|
1344
|
-
for (const node of ast.nodes) {
|
|
1345
|
-
if (node.type !== "agent")
|
|
1346
|
-
continue;
|
|
1347
|
-
const agent = node;
|
|
1348
|
-
if (agent.writes && agent.writes.length > 0) {
|
|
1349
|
-
agentWrites.set(agent.id, agent.writes);
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
for (const node of ast.nodes) {
|
|
1353
|
-
if (node.type !== "gate")
|
|
1354
|
-
continue;
|
|
1355
|
-
const gate = node;
|
|
1356
|
-
if (!gate.run)
|
|
1357
|
-
continue;
|
|
1358
|
-
if (gate.behavior === "advisory")
|
|
1359
|
-
continue;
|
|
1360
|
-
const scriptName = gate.run.replace(/^.*\//, "").replace(/\s.*$/, "");
|
|
1361
|
-
// Derive file patterns from the `after` agent's writes paths
|
|
1362
|
-
const afterWrites = gate.after ? gateAnchors(gate, "after").flatMap((a) => agentWrites.get(a) ?? []) : undefined;
|
|
1363
|
-
const filePatterns = afterWrites
|
|
1364
|
-
? afterWrites.map((p) => p.replace(/\/$/, "/**"))
|
|
1365
|
-
: ["workspace/**"];
|
|
1366
|
-
const hookJson = {
|
|
1367
|
-
enabled: true,
|
|
1368
|
-
name: `${toTitle(gate.id)} Gate`,
|
|
1369
|
-
description: `Quality gate that runs after ${gateAnchors(gate, "after").join(", ") || "any agent"}${gate.before ? ` and before ${gateAnchors(gate, "before").join(", ")}` : ""}.${gate.checks && gate.checks.length > 0 ? ` Checks: ${gate.checks.join(", ")}.` : ""}`,
|
|
1370
|
-
version: "1",
|
|
1371
|
-
when: {
|
|
1372
|
-
type: "fileEdited",
|
|
1373
|
-
patterns: filePatterns,
|
|
1374
|
-
},
|
|
1375
|
-
then: {
|
|
1376
|
-
type: "runCommand",
|
|
1377
|
-
command: `.kiro/scripts/${scriptName}`,
|
|
1378
|
-
},
|
|
1379
|
-
};
|
|
1380
|
-
files.push({
|
|
1381
|
-
path: `.kiro/hooks/gate-${gate.id}.kiro.hook`,
|
|
1382
|
-
content: JSON.stringify(hookJson, null, 2) + "\n",
|
|
1383
|
-
category: "machine",
|
|
1384
|
-
});
|
|
1385
|
-
}
|
|
1386
|
-
return files;
|
|
1387
|
-
}
|
|
1388
|
-
// ---------------------------------------------------------------------------
|
|
1389
|
-
// Specs directory
|
|
1390
|
-
// ---------------------------------------------------------------------------
|
|
1391
|
-
/**
|
|
1392
|
-
* Generate `.kiro/specs/` directory with Kiro-standard spec files.
|
|
1393
|
-
*
|
|
1394
|
-
* Only generates files when the topology has sufficient content to populate
|
|
1395
|
-
* them meaningfully (description, agents, flow, etc.).
|
|
1396
|
-
*
|
|
1397
|
-
* - `requirements.md` — populated from topology description + agent roles
|
|
1398
|
-
* - `design.md` — populated from flow and architecture
|
|
1399
|
-
* - `tasks.md` — populated from agents and their phases
|
|
1400
|
-
*/
|
|
1401
|
-
function generateSpecs(ast) {
|
|
1402
|
-
const files = [];
|
|
1403
|
-
const agents = ast.nodes.filter((n) => n.type === "agent");
|
|
1404
|
-
// Only generate specs if there is meaningful content
|
|
1405
|
-
const hasDescription = !!ast.topology.description;
|
|
1406
|
-
const hasAgents = agents.length > 0;
|
|
1407
|
-
const hasEdges = ast.edges.length > 0;
|
|
1408
|
-
if (!hasDescription && !hasAgents)
|
|
1409
|
-
return files;
|
|
1410
|
-
// --- requirements.md ---
|
|
1411
|
-
if (hasDescription || hasAgents) {
|
|
1412
|
-
const req = [];
|
|
1413
|
-
req.push(`# Requirements — ${toTitle(ast.topology.name)}`);
|
|
1414
|
-
req.push("");
|
|
1415
|
-
if (ast.topology.description) {
|
|
1416
|
-
req.push("## Overview");
|
|
1417
|
-
req.push("");
|
|
1418
|
-
req.push(ast.topology.description);
|
|
1419
|
-
req.push("");
|
|
1420
|
-
}
|
|
1421
|
-
if (Object.keys(ast.roles).length > 0) {
|
|
1422
|
-
req.push("## Agent Roles");
|
|
1423
|
-
req.push("");
|
|
1424
|
-
for (const [role, desc] of Object.entries(ast.roles)) {
|
|
1425
|
-
req.push(`- **${toTitle(role)}**: ${desc}`);
|
|
1426
|
-
}
|
|
1427
|
-
req.push("");
|
|
1428
|
-
}
|
|
1429
|
-
if (agents.length > 0) {
|
|
1430
|
-
req.push("## Functional Requirements");
|
|
1431
|
-
req.push("");
|
|
1432
|
-
for (const agent of agents) {
|
|
1433
|
-
const desc = agent.description ??
|
|
1434
|
-
ast.roles[agent.role ?? ""] ??
|
|
1435
|
-
ast.roles[agent.id] ??
|
|
1436
|
-
"";
|
|
1437
|
-
if (desc) {
|
|
1438
|
-
req.push(`- **${toTitle(agent.id)}**: ${desc}`);
|
|
1439
|
-
}
|
|
1440
|
-
}
|
|
1441
|
-
req.push("");
|
|
1442
|
-
}
|
|
1443
|
-
// Gates as quality requirements
|
|
1444
|
-
const gates = ast.nodes.filter((n) => n.type === "gate");
|
|
1445
|
-
if (gates.length > 0) {
|
|
1446
|
-
req.push("## Quality Gates");
|
|
1447
|
-
req.push("");
|
|
1448
|
-
for (const gate of gates) {
|
|
1449
|
-
let line = `- **${toTitle(gate.id)}**`;
|
|
1450
|
-
if (gate.checks && gate.checks.length > 0) {
|
|
1451
|
-
line += `: checks ${gate.checks.join(", ")}`;
|
|
1452
|
-
}
|
|
1453
|
-
if (gate.onFail)
|
|
1454
|
-
line += ` (on fail: ${gate.onFail})`;
|
|
1455
|
-
req.push(line);
|
|
1456
|
-
}
|
|
1457
|
-
req.push("");
|
|
1458
|
-
}
|
|
1459
|
-
files.push({
|
|
1460
|
-
path: `.kiro/specs/${ast.topology.name}/requirements.md`,
|
|
1461
|
-
content: req.join("\n") + "\n",
|
|
1462
|
-
category: "machine",
|
|
1463
|
-
});
|
|
1464
|
-
}
|
|
1465
|
-
// --- design.md ---
|
|
1466
|
-
if (hasEdges || hasAgents) {
|
|
1467
|
-
const design = [];
|
|
1468
|
-
design.push(`# Design — ${toTitle(ast.topology.name)}`);
|
|
1469
|
-
design.push("");
|
|
1470
|
-
if (ast.topology.patterns.length > 0) {
|
|
1471
|
-
design.push("## Architecture Patterns");
|
|
1472
|
-
design.push("");
|
|
1473
|
-
design.push(ast.topology.patterns.map((p) => `- ${p}`).join("\n"));
|
|
1474
|
-
design.push("");
|
|
1475
|
-
}
|
|
1476
|
-
// Orchestrator
|
|
1477
|
-
const orch = ast.nodes.find((n) => n.type === "orchestrator");
|
|
1478
|
-
if (orch) {
|
|
1479
|
-
design.push("## Orchestrator");
|
|
1480
|
-
design.push("");
|
|
1481
|
-
design.push(`Model: ${orch.model}`);
|
|
1482
|
-
if (orch.handles?.length > 0) {
|
|
1483
|
-
design.push(`Handles: ${orch.handles.join(", ")}`);
|
|
1484
|
-
}
|
|
1485
|
-
design.push("");
|
|
1486
|
-
}
|
|
1487
|
-
if (hasEdges) {
|
|
1488
|
-
design.push("## Flow Graph");
|
|
1489
|
-
design.push("");
|
|
1490
|
-
for (const edge of ast.edges) {
|
|
1491
|
-
const arrow = edge.isError ? `-x->` : "->";
|
|
1492
|
-
let line = `- ${edge.from} ${arrow} ${edge.to}`;
|
|
1493
|
-
if (edge.condition)
|
|
1494
|
-
line += ` [when ${edge.condition}]`;
|
|
1495
|
-
if (edge.maxIterations)
|
|
1496
|
-
line += ` [max ${edge.maxIterations}]`;
|
|
1497
|
-
design.push(line);
|
|
1498
|
-
}
|
|
1499
|
-
design.push("");
|
|
1500
|
-
}
|
|
1501
|
-
// MCP servers as integration points
|
|
1502
|
-
if (Object.keys(ast.mcpServers).length > 0) {
|
|
1503
|
-
design.push("## Integration Points (MCP Servers)");
|
|
1504
|
-
design.push("");
|
|
1505
|
-
for (const [name, config] of Object.entries(ast.mcpServers)) {
|
|
1506
|
-
const stype = config.type ?? "stdio";
|
|
1507
|
-
design.push(`- **${name}** (${stype})`);
|
|
1508
|
-
}
|
|
1509
|
-
design.push("");
|
|
1510
|
-
}
|
|
1511
|
-
files.push({
|
|
1512
|
-
path: `.kiro/specs/${ast.topology.name}/design.md`,
|
|
1513
|
-
content: design.join("\n") + "\n",
|
|
1514
|
-
category: "machine",
|
|
1515
|
-
});
|
|
1516
|
-
}
|
|
1517
|
-
// --- tasks.md ---
|
|
1518
|
-
if (hasAgents) {
|
|
1519
|
-
const tasks = [];
|
|
1520
|
-
tasks.push(`# Tasks — ${toTitle(ast.topology.name)}`);
|
|
1521
|
-
tasks.push("");
|
|
1522
|
-
// Group agents by phase
|
|
1523
|
-
const phased = agents
|
|
1524
|
-
.filter((a) => a.phase != null)
|
|
1525
|
-
.sort(byPhase);
|
|
1526
|
-
const unphased = agents.filter((a) => a.phase == null);
|
|
1527
|
-
if (phased.length > 0) {
|
|
1528
|
-
let currentPhase = -1;
|
|
1529
|
-
for (const agent of phased) {
|
|
1530
|
-
if (agent.phase !== currentPhase) {
|
|
1531
|
-
currentPhase = agent.phase;
|
|
1532
|
-
tasks.push(`## Phase ${currentPhase}`);
|
|
1533
|
-
tasks.push("");
|
|
1534
|
-
}
|
|
1535
|
-
const desc = agent.description ??
|
|
1536
|
-
ast.roles[agent.role ?? ""] ??
|
|
1537
|
-
"";
|
|
1538
|
-
tasks.push(`- [ ] **${toTitle(agent.id)}**${desc ? `: ${desc}` : ""}`);
|
|
1539
|
-
if (agent.tools && agent.tools.length > 0) {
|
|
1540
|
-
tasks.push(` - Tools: ${agent.tools.join(", ")}`);
|
|
1541
|
-
}
|
|
1542
|
-
if (agent.mcpServers && agent.mcpServers.length > 0) {
|
|
1543
|
-
tasks.push(` - MCP: ${agent.mcpServers.join(", ")}`);
|
|
1544
|
-
}
|
|
1545
|
-
}
|
|
1546
|
-
tasks.push("");
|
|
1547
|
-
}
|
|
1548
|
-
if (unphased.length > 0) {
|
|
1549
|
-
tasks.push("## Unphased");
|
|
1550
|
-
tasks.push("");
|
|
1551
|
-
for (const agent of unphased) {
|
|
1552
|
-
const desc = agent.description ??
|
|
1553
|
-
ast.roles[agent.role ?? ""] ??
|
|
1554
|
-
"";
|
|
1555
|
-
tasks.push(`- [ ] **${toTitle(agent.id)}**${desc ? `: ${desc}` : ""}`);
|
|
1556
|
-
}
|
|
1557
|
-
tasks.push("");
|
|
1558
|
-
}
|
|
1559
|
-
files.push({
|
|
1560
|
-
path: `.kiro/specs/${ast.topology.name}/tasks.md`,
|
|
1561
|
-
content: tasks.join("\n") + "\n",
|
|
1562
|
-
category: "machine",
|
|
1563
|
-
});
|
|
1564
|
-
}
|
|
1565
|
-
return files;
|
|
1566
|
-
}
|
|
1567
|
-
// ---------------------------------------------------------------------------
|
|
1568
|
-
// Binding export
|
|
1569
|
-
// ---------------------------------------------------------------------------
|
|
1570
|
-
/** Kiro CLI binding — generates .kiro/ directory structure and AGENTS.md. */
|
|
1571
|
-
export const kiroBinding = {
|
|
1572
|
-
name: "kiro",
|
|
1573
|
-
description: "AWS Kiro CLI — generates .kiro/ directory with JSON agents, steering docs, MCP config, and prompts.",
|
|
1574
|
-
scaffold(ast) {
|
|
1575
|
-
const files = [];
|
|
1576
|
-
// 1. Agent JSON files
|
|
1577
|
-
files.push(...generateAgents(ast));
|
|
1578
|
-
// 2. Steering documents
|
|
1579
|
-
files.push(generateProductSteering(ast));
|
|
1580
|
-
files.push(generateTechSteering(ast));
|
|
1581
|
-
files.push(generateStructureSteering(ast));
|
|
1582
|
-
// 2b. Per-agent behavioral steering docs (Wave 1-7)
|
|
1583
|
-
files.push(...generateAgentSteering(ast));
|
|
1584
|
-
// 2c. Human node steering docs (Wave 5)
|
|
1585
|
-
files.push(...generateHumanSteering(ast));
|
|
1586
|
-
// 2d. Group node steering docs (Wave 5)
|
|
1587
|
-
files.push(...generateGroupSteering(ast));
|
|
1588
|
-
// 3. MCP configuration
|
|
1589
|
-
const mcpFile = generateMcpJson(ast);
|
|
1590
|
-
if (mcpFile)
|
|
1591
|
-
files.push(mcpFile);
|
|
1592
|
-
// 4. Prompt files (triggers)
|
|
1593
|
-
files.push(...generatePromptFiles(ast));
|
|
1594
|
-
// 5. AGENTS.md (top-level flow narrative)
|
|
1595
|
-
files.push(generateAgentsMd(ast));
|
|
1596
|
-
// 6. Hook scripts
|
|
1597
|
-
files.push(...generateHookScripts(ast));
|
|
1598
|
-
// 7. Gate scripts
|
|
1599
|
-
files.push(...generateGateScripts(ast));
|
|
1600
|
-
// 8. Gate hook files
|
|
1601
|
-
files.push(...generateGateHooks(ast));
|
|
1602
|
-
// 9. Tool scripts
|
|
1603
|
-
files.push(...generateToolScripts(ast));
|
|
1604
|
-
// 10. Memory directories
|
|
1605
|
-
files.push(...generateMemory(ast));
|
|
1606
|
-
// 11. Metering
|
|
1607
|
-
const meteringFile = generateMetering(ast);
|
|
1608
|
-
if (meteringFile)
|
|
1609
|
-
files.push(meteringFile);
|
|
1610
|
-
// 12. Specs directory (.kiro/specs/)
|
|
1611
|
-
files.push(...generateSpecs(ast));
|
|
1612
|
-
return deduplicateFiles(files);
|
|
1613
|
-
},
|
|
1614
|
-
};
|
|
1615
|
-
//# sourceMappingURL=kiro.js.map
|