agentopology 0.1.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/LICENSE +191 -0
- package/README.md +450 -0
- package/dist/analyzer/__tests__/analyzer.test.d.ts +2 -0
- package/dist/analyzer/__tests__/analyzer.test.d.ts.map +1 -0
- package/dist/analyzer/__tests__/analyzer.test.js +258 -0
- package/dist/analyzer/__tests__/analyzer.test.js.map +1 -0
- package/dist/analyzer/index.d.ts +44 -0
- package/dist/analyzer/index.d.ts.map +1 -0
- package/dist/analyzer/index.js +308 -0
- package/dist/analyzer/index.js.map +1 -0
- package/dist/bindings/__tests__/bindings.test.d.ts +2 -0
- package/dist/bindings/__tests__/bindings.test.d.ts.map +1 -0
- package/dist/bindings/__tests__/bindings.test.js +2089 -0
- package/dist/bindings/__tests__/bindings.test.js.map +1 -0
- package/dist/bindings/claude-code.d.ts +12 -0
- package/dist/bindings/claude-code.d.ts.map +1 -0
- package/dist/bindings/claude-code.js +2063 -0
- package/dist/bindings/claude-code.js.map +1 -0
- package/dist/bindings/codex.d.ts +18 -0
- package/dist/bindings/codex.d.ts.map +1 -0
- package/dist/bindings/codex.js +1633 -0
- package/dist/bindings/codex.js.map +1 -0
- package/dist/bindings/copilot-cli.d.ts +20 -0
- package/dist/bindings/copilot-cli.d.ts.map +1 -0
- package/dist/bindings/copilot-cli.js +1515 -0
- package/dist/bindings/copilot-cli.js.map +1 -0
- package/dist/bindings/cursor.d.ts +17 -0
- package/dist/bindings/cursor.d.ts.map +1 -0
- package/dist/bindings/cursor.js +1715 -0
- package/dist/bindings/cursor.js.map +1 -0
- package/dist/bindings/gemini-cli.d.ts +18 -0
- package/dist/bindings/gemini-cli.d.ts.map +1 -0
- package/dist/bindings/gemini-cli.js +1327 -0
- package/dist/bindings/gemini-cli.js.map +1 -0
- package/dist/bindings/index.d.ts +20 -0
- package/dist/bindings/index.d.ts.map +1 -0
- package/dist/bindings/index.js +33 -0
- package/dist/bindings/index.js.map +1 -0
- package/dist/bindings/kiro.d.ts +17 -0
- package/dist/bindings/kiro.d.ts.map +1 -0
- package/dist/bindings/kiro.js +1624 -0
- package/dist/bindings/kiro.js.map +1 -0
- package/dist/bindings/openclaw.d.ts +18 -0
- package/dist/bindings/openclaw.d.ts.map +1 -0
- package/dist/bindings/openclaw.js +1578 -0
- package/dist/bindings/openclaw.js.map +1 -0
- package/dist/bindings/types.d.ts +33 -0
- package/dist/bindings/types.d.ts.map +1 -0
- package/dist/bindings/types.js +23 -0
- package/dist/bindings/types.js.map +1 -0
- package/dist/cli/index.d.ts +19 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +679 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/docs/__tests__/docs.test.d.ts +2 -0
- package/dist/docs/__tests__/docs.test.d.ts.map +1 -0
- package/dist/docs/__tests__/docs.test.js +438 -0
- package/dist/docs/__tests__/docs.test.js.map +1 -0
- package/dist/docs/content.d.ts +16 -0
- package/dist/docs/content.d.ts.map +1 -0
- package/dist/docs/content.js +3273 -0
- package/dist/docs/content.js.map +1 -0
- package/dist/docs/index.d.ts +17 -0
- package/dist/docs/index.d.ts.map +1 -0
- package/dist/docs/index.js +117 -0
- package/dist/docs/index.js.map +1 -0
- package/dist/exporters/__tests__/exporters.test.d.ts +2 -0
- package/dist/exporters/__tests__/exporters.test.d.ts.map +1 -0
- package/dist/exporters/__tests__/exporters.test.js +731 -0
- package/dist/exporters/__tests__/exporters.test.js.map +1 -0
- package/dist/exporters/index.d.ts +13 -0
- package/dist/exporters/index.d.ts.map +1 -0
- package/dist/exporters/index.js +18 -0
- package/dist/exporters/index.js.map +1 -0
- package/dist/exporters/json.d.ts +8 -0
- package/dist/exporters/json.d.ts.map +1 -0
- package/dist/exporters/json.js +25 -0
- package/dist/exporters/json.js.map +1 -0
- package/dist/exporters/markdown.d.ts +9 -0
- package/dist/exporters/markdown.d.ts.map +1 -0
- package/dist/exporters/markdown.js +686 -0
- package/dist/exporters/markdown.js.map +1 -0
- package/dist/exporters/mermaid.d.ts +11 -0
- package/dist/exporters/mermaid.d.ts.map +1 -0
- package/dist/exporters/mermaid.js +161 -0
- package/dist/exporters/mermaid.js.map +1 -0
- package/dist/exporters/types.d.ts +22 -0
- package/dist/exporters/types.d.ts.map +1 -0
- package/dist/exporters/types.js +10 -0
- package/dist/exporters/types.js.map +1 -0
- package/dist/import/__tests__/import.test.d.ts +2 -0
- package/dist/import/__tests__/import.test.d.ts.map +1 -0
- package/dist/import/__tests__/import.test.js +781 -0
- package/dist/import/__tests__/import.test.js.map +1 -0
- package/dist/import/claude-code.d.ts +38 -0
- package/dist/import/claude-code.d.ts.map +1 -0
- package/dist/import/claude-code.js +897 -0
- package/dist/import/claude-code.js.map +1 -0
- package/dist/import/index.d.ts +18 -0
- package/dist/import/index.d.ts.map +1 -0
- package/dist/import/index.js +28 -0
- package/dist/import/index.js.map +1 -0
- package/dist/import/serializer.d.ts +11 -0
- package/dist/import/serializer.d.ts.map +1 -0
- package/dist/import/serializer.js +960 -0
- package/dist/import/serializer.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/__tests__/parser.test.d.ts +2 -0
- package/dist/parser/__tests__/parser.test.d.ts.map +1 -0
- package/dist/parser/__tests__/parser.test.js +6514 -0
- package/dist/parser/__tests__/parser.test.js.map +1 -0
- package/dist/parser/ast.d.ts +708 -0
- package/dist/parser/ast.d.ts.map +1 -0
- package/dist/parser/ast.js +12 -0
- package/dist/parser/ast.js.map +1 -0
- package/dist/parser/index.d.ts +253 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +1985 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/lexer.d.ts +100 -0
- package/dist/parser/lexer.d.ts.map +1 -0
- package/dist/parser/lexer.js +304 -0
- package/dist/parser/lexer.js.map +1 -0
- package/dist/parser/validator.d.ts +42 -0
- package/dist/parser/validator.d.ts.map +1 -0
- package/dist/parser/validator.js +2568 -0
- package/dist/parser/validator.js.map +1 -0
- package/dist/scaffold/__tests__/scaffold.test.d.ts +7 -0
- package/dist/scaffold/__tests__/scaffold.test.d.ts.map +1 -0
- package/dist/scaffold/__tests__/scaffold.test.js +295 -0
- package/dist/scaffold/__tests__/scaffold.test.js.map +1 -0
- package/dist/scaffold/incremental.d.ts +43 -0
- package/dist/scaffold/incremental.d.ts.map +1 -0
- package/dist/scaffold/incremental.js +185 -0
- package/dist/scaffold/incremental.js.map +1 -0
- package/dist/scaffold/index.d.ts +13 -0
- package/dist/scaffold/index.d.ts.map +1 -0
- package/dist/scaffold/index.js +13 -0
- package/dist/scaffold/index.js.map +1 -0
- package/dist/scaffold/manifest.d.ts +30 -0
- package/dist/scaffold/manifest.d.ts.map +1 -0
- package/dist/scaffold/manifest.js +71 -0
- package/dist/scaffold/manifest.js.map +1 -0
- package/dist/scaffold/merge.d.ts +52 -0
- package/dist/scaffold/merge.d.ts.map +1 -0
- package/dist/scaffold/merge.js +134 -0
- package/dist/scaffold/merge.js.map +1 -0
- package/dist/scaffold/types.d.ts +51 -0
- package/dist/scaffold/types.d.ts.map +1 -0
- package/dist/scaffold/types.js +10 -0
- package/dist/scaffold/types.js.map +1 -0
- package/dist/sync/index.d.ts +34 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +392 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/visualizer/index.d.ts +17 -0
- package/dist/visualizer/index.d.ts.map +1 -0
- package/dist/visualizer/index.js +1976 -0
- package/dist/visualizer/index.js.map +1 -0
- package/examples/code-review.at +167 -0
- package/examples/data-processing.at +296 -0
- package/examples/openclaw-assistant.at +142 -0
- package/examples/scheduled-monitor.at +193 -0
- package/examples/simple-pipeline.at +163 -0
- package/package.json +77 -0
- package/skill/SKILL.md +403 -0
- package/skill/scripts/emit.ts +853 -0
- package/skill/scripts/visualize.ts +89 -0
- package/spec/grammar.md +1466 -0
- package/spec/reserved-keywords.md +147 -0
- package/spec/validation.md +535 -0
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown exporter — converts a TopologyAST into a beautiful, shareable
|
|
3
|
+
* Markdown document suitable for stakeholders, documentation, and onboarding.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Helpers
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
function toTitle(s) {
|
|
11
|
+
return s
|
|
12
|
+
.split("-")
|
|
13
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
14
|
+
.join(" ");
|
|
15
|
+
}
|
|
16
|
+
function edgeLabel(edge) {
|
|
17
|
+
const parts = [];
|
|
18
|
+
if (edge.isError) {
|
|
19
|
+
parts.push(edge.errorType ? `error(${edge.errorType})` : "error");
|
|
20
|
+
}
|
|
21
|
+
if (edge.condition)
|
|
22
|
+
parts.push(`when ${edge.condition}`);
|
|
23
|
+
if (edge.maxIterations)
|
|
24
|
+
parts.push(`max ${edge.maxIterations}`);
|
|
25
|
+
if (edge.race)
|
|
26
|
+
parts.push("race");
|
|
27
|
+
if (edge.tolerance != null)
|
|
28
|
+
parts.push(`tolerance: ${edge.tolerance}`);
|
|
29
|
+
if (edge.wait)
|
|
30
|
+
parts.push(`wait ${edge.wait}`);
|
|
31
|
+
if (edge.weight != null)
|
|
32
|
+
parts.push(`weight ${edge.weight}`);
|
|
33
|
+
if (edge.reflection)
|
|
34
|
+
parts.push("reflection");
|
|
35
|
+
return parts.length > 0 ? parts.join(", ") : "";
|
|
36
|
+
}
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Section renderers
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
function renderHeader(ast) {
|
|
41
|
+
const t = ast.topology;
|
|
42
|
+
const lines = [];
|
|
43
|
+
// Title block
|
|
44
|
+
lines.push(`<div align="center">`);
|
|
45
|
+
lines.push("");
|
|
46
|
+
lines.push(`# ${toTitle(t.name)}`);
|
|
47
|
+
lines.push("");
|
|
48
|
+
if (t.description) {
|
|
49
|
+
lines.push(`*${t.description}*`);
|
|
50
|
+
lines.push("");
|
|
51
|
+
}
|
|
52
|
+
// Badges row
|
|
53
|
+
const badges = [];
|
|
54
|
+
badges.push(``);
|
|
55
|
+
for (const p of t.patterns) {
|
|
56
|
+
badges.push(`}-purple)`);
|
|
57
|
+
}
|
|
58
|
+
if (t.domain) {
|
|
59
|
+
badges.push(`}-green)`);
|
|
60
|
+
}
|
|
61
|
+
lines.push(badges.join(" "));
|
|
62
|
+
lines.push("");
|
|
63
|
+
lines.push(`</div>`);
|
|
64
|
+
lines.push("");
|
|
65
|
+
// Extra metadata as a clean list if present
|
|
66
|
+
const extra = [];
|
|
67
|
+
if (t.foundations && t.foundations.length > 0) {
|
|
68
|
+
extra.push(`**Foundations:** ${t.foundations.map((f) => `\`${f}\``).join(", ")}`);
|
|
69
|
+
}
|
|
70
|
+
if (t.advanced && t.advanced.length > 0) {
|
|
71
|
+
extra.push(`**Advanced:** ${t.advanced.map((a) => `\`${a}\``).join(", ")}`);
|
|
72
|
+
}
|
|
73
|
+
if (t.timeout)
|
|
74
|
+
extra.push(`**Timeout:** ${t.timeout}`);
|
|
75
|
+
if (t.durable)
|
|
76
|
+
extra.push(`**Durable:** Yes`);
|
|
77
|
+
if (t.errorHandler)
|
|
78
|
+
extra.push(`**Error Handler:** \`${t.errorHandler}\``);
|
|
79
|
+
if (extra.length > 0) {
|
|
80
|
+
for (const e of extra)
|
|
81
|
+
lines.push(`> ${e}`);
|
|
82
|
+
lines.push("");
|
|
83
|
+
}
|
|
84
|
+
return lines.join("\n");
|
|
85
|
+
}
|
|
86
|
+
function renderOverview(ast) {
|
|
87
|
+
const agents = ast.nodes.filter((n) => n.type === "agent");
|
|
88
|
+
const actions = ast.nodes.filter((n) => n.type === "action");
|
|
89
|
+
const gates = ast.nodes.filter((n) => n.type === "gate");
|
|
90
|
+
const orchestrators = ast.nodes.filter((n) => n.type === "orchestrator");
|
|
91
|
+
const humans = ast.nodes.filter((n) => n.type === "human");
|
|
92
|
+
const groups = ast.nodes.filter((n) => n.type === "group");
|
|
93
|
+
const lines = [];
|
|
94
|
+
lines.push("## At a Glance");
|
|
95
|
+
lines.push("");
|
|
96
|
+
const items = [];
|
|
97
|
+
if (orchestrators.length)
|
|
98
|
+
items.push(`**${orchestrators.length}** Orchestrator${orchestrators.length > 1 ? "s" : ""}`);
|
|
99
|
+
if (agents.length)
|
|
100
|
+
items.push(`**${agents.length}** Agent${agents.length > 1 ? "s" : ""}`);
|
|
101
|
+
if (actions.length)
|
|
102
|
+
items.push(`**${actions.length}** Action${actions.length > 1 ? "s" : ""}`);
|
|
103
|
+
if (gates.length)
|
|
104
|
+
items.push(`**${gates.length}** Gate${gates.length > 1 ? "s" : ""}`);
|
|
105
|
+
if (humans.length)
|
|
106
|
+
items.push(`**${humans.length}** Human Node${humans.length > 1 ? "s" : ""}`);
|
|
107
|
+
if (groups.length)
|
|
108
|
+
items.push(`**${groups.length}** Group${groups.length > 1 ? "s" : ""}`);
|
|
109
|
+
items.push(`**${ast.edges.length}** Edge${ast.edges.length !== 1 ? "s" : ""}`);
|
|
110
|
+
lines.push(`> ${items.join(" • ")}`);
|
|
111
|
+
lines.push("");
|
|
112
|
+
return lines.join("\n");
|
|
113
|
+
}
|
|
114
|
+
function renderRoles(ast) {
|
|
115
|
+
const entries = Object.entries(ast.roles);
|
|
116
|
+
if (entries.length === 0)
|
|
117
|
+
return "";
|
|
118
|
+
const lines = [];
|
|
119
|
+
lines.push("## Roles");
|
|
120
|
+
lines.push("");
|
|
121
|
+
for (const [name, desc] of entries) {
|
|
122
|
+
lines.push(`- **${toTitle(name)}** — ${desc}`);
|
|
123
|
+
}
|
|
124
|
+
lines.push("");
|
|
125
|
+
return lines.join("\n");
|
|
126
|
+
}
|
|
127
|
+
function renderOrchestrator(node) {
|
|
128
|
+
const lines = [];
|
|
129
|
+
lines.push(`### Orchestrator`);
|
|
130
|
+
lines.push("");
|
|
131
|
+
const details = [];
|
|
132
|
+
details.push(`Model: \`${node.model}\``);
|
|
133
|
+
if (node.generates)
|
|
134
|
+
details.push(`Generates: \`${node.generates}\``);
|
|
135
|
+
if (node.handles.length)
|
|
136
|
+
details.push(`Handles: ${node.handles.map((h) => `\`${h}\``).join(", ")}`);
|
|
137
|
+
lines.push(`> ${details.join(" · ")}`);
|
|
138
|
+
lines.push("");
|
|
139
|
+
if (node.outputs) {
|
|
140
|
+
lines.push("**Outputs:**");
|
|
141
|
+
lines.push("");
|
|
142
|
+
for (const [key, values] of Object.entries(node.outputs)) {
|
|
143
|
+
lines.push(`- \`${key}\` — ${values.map((v) => `\`${v}\``).join(" / ")}`);
|
|
144
|
+
}
|
|
145
|
+
lines.push("");
|
|
146
|
+
}
|
|
147
|
+
return lines.join("\n");
|
|
148
|
+
}
|
|
149
|
+
function renderAgent(node, roles) {
|
|
150
|
+
const lines = [];
|
|
151
|
+
// Agent heading with model badge inline
|
|
152
|
+
const modelBadge = node.model ? ` \`${node.model}\`` : "";
|
|
153
|
+
lines.push(`#### ${toTitle(node.id)}${modelBadge}`);
|
|
154
|
+
lines.push("");
|
|
155
|
+
// Role description as italic subtitle
|
|
156
|
+
if (node.role && roles[node.role]) {
|
|
157
|
+
lines.push(`*${roles[node.role]}*`);
|
|
158
|
+
lines.push("");
|
|
159
|
+
}
|
|
160
|
+
// Compact key-value line
|
|
161
|
+
const kvParts = [];
|
|
162
|
+
if (node.phase != null)
|
|
163
|
+
kvParts.push(`Phase **${node.phase}**`);
|
|
164
|
+
if (node.permissions)
|
|
165
|
+
kvParts.push(`Permissions: \`${node.permissions}\``);
|
|
166
|
+
if (node.behavior)
|
|
167
|
+
kvParts.push(`Behavior: \`${node.behavior}\``);
|
|
168
|
+
if (node.isolation)
|
|
169
|
+
kvParts.push(`Isolation: \`${node.isolation}\``);
|
|
170
|
+
if (node.background)
|
|
171
|
+
kvParts.push(`Background`);
|
|
172
|
+
if (node.sandbox != null)
|
|
173
|
+
kvParts.push(`Sandbox: \`${String(node.sandbox)}\``);
|
|
174
|
+
if (node.maxTurns != null)
|
|
175
|
+
kvParts.push(`Max turns: ${node.maxTurns}`);
|
|
176
|
+
if (node.timeout)
|
|
177
|
+
kvParts.push(`Timeout: ${node.timeout}`);
|
|
178
|
+
if (node.temperature != null)
|
|
179
|
+
kvParts.push(`Temperature: ${node.temperature}`);
|
|
180
|
+
if (node.thinking)
|
|
181
|
+
kvParts.push(`Thinking: \`${node.thinking}\``);
|
|
182
|
+
if (node.rateLimit)
|
|
183
|
+
kvParts.push(`Rate limit: ${node.rateLimit}`);
|
|
184
|
+
if (node.onFail)
|
|
185
|
+
kvParts.push(`On fail: \`${node.onFail}\``);
|
|
186
|
+
if (node.compensates)
|
|
187
|
+
kvParts.push(`Compensates: \`${node.compensates}\``);
|
|
188
|
+
if (node.invocation)
|
|
189
|
+
kvParts.push(`Invocation: \`${node.invocation}\``);
|
|
190
|
+
if (kvParts.length) {
|
|
191
|
+
lines.push(kvParts.join(" · "));
|
|
192
|
+
lines.push("");
|
|
193
|
+
}
|
|
194
|
+
// Tools & access in a compact block
|
|
195
|
+
const accessLines = [];
|
|
196
|
+
if (node.tools && node.tools.length) {
|
|
197
|
+
accessLines.push(`**Tools:** ${node.tools.map((t) => `\`${t}\``).join(", ")}`);
|
|
198
|
+
}
|
|
199
|
+
if (node.disallowedTools && node.disallowedTools.length) {
|
|
200
|
+
accessLines.push(`**Denied:** ${node.disallowedTools.map((t) => `~~\`${t}\`~~`).join(", ")}`);
|
|
201
|
+
}
|
|
202
|
+
if (node.reads && node.reads.length) {
|
|
203
|
+
accessLines.push(`**Reads:** ${node.reads.map((r) => `\`${r}\``).join(", ")}`);
|
|
204
|
+
}
|
|
205
|
+
if (node.writes && node.writes.length) {
|
|
206
|
+
accessLines.push(`**Writes:** ${node.writes.map((w) => `\`${w}\``).join(", ")}`);
|
|
207
|
+
}
|
|
208
|
+
if (node.skills && node.skills.length) {
|
|
209
|
+
accessLines.push(`**Skills:** ${node.skills.map((s) => `\`${s}\``).join(", ")}`);
|
|
210
|
+
}
|
|
211
|
+
if (node.mcpServers && node.mcpServers.length) {
|
|
212
|
+
accessLines.push(`**MCP Servers:** ${node.mcpServers.map((s) => `\`${s}\``).join(", ")}`);
|
|
213
|
+
}
|
|
214
|
+
if (accessLines.length) {
|
|
215
|
+
for (const l of accessLines)
|
|
216
|
+
lines.push(l + " ");
|
|
217
|
+
lines.push("");
|
|
218
|
+
}
|
|
219
|
+
// Fallback chain
|
|
220
|
+
if (node.fallbackChain && node.fallbackChain.length) {
|
|
221
|
+
lines.push(`**Fallback:** ${node.fallbackChain.map((m) => `\`${m}\``).join(" → ")}`);
|
|
222
|
+
lines.push("");
|
|
223
|
+
}
|
|
224
|
+
// Outputs
|
|
225
|
+
if (node.outputs) {
|
|
226
|
+
lines.push("**Outputs:**");
|
|
227
|
+
for (const [key, values] of Object.entries(node.outputs)) {
|
|
228
|
+
lines.push(`- \`${key}\` — ${values.map((v) => `\`${v}\``).join(" / ")}`);
|
|
229
|
+
}
|
|
230
|
+
lines.push("");
|
|
231
|
+
}
|
|
232
|
+
// Scale
|
|
233
|
+
if (node.scale) {
|
|
234
|
+
lines.push(`**Scale:** \`${node.scale.mode}\` by \`${node.scale.by}\` (${node.scale.min}–${node.scale.max}${node.scale.batchSize ? `, batch ${node.scale.batchSize}` : ""})`);
|
|
235
|
+
lines.push("");
|
|
236
|
+
}
|
|
237
|
+
// Circuit breaker
|
|
238
|
+
if (node.circuitBreaker) {
|
|
239
|
+
lines.push(`**Circuit Breaker:** threshold=${node.circuitBreaker.threshold}, window=${node.circuitBreaker.window}, cooldown=${node.circuitBreaker.cooldown}`);
|
|
240
|
+
lines.push("");
|
|
241
|
+
}
|
|
242
|
+
// Retry
|
|
243
|
+
if (node.retry) {
|
|
244
|
+
if (typeof node.retry === "number") {
|
|
245
|
+
lines.push(`**Retry:** ${node.retry}x`);
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
const retryParts = [`max ${node.retry.max}`];
|
|
249
|
+
if (node.retry.backoff)
|
|
250
|
+
retryParts.push(node.retry.backoff);
|
|
251
|
+
if (node.retry.interval)
|
|
252
|
+
retryParts.push(node.retry.interval);
|
|
253
|
+
lines.push(`**Retry:** ${retryParts.join(", ")}`);
|
|
254
|
+
}
|
|
255
|
+
lines.push("");
|
|
256
|
+
}
|
|
257
|
+
// Prompt
|
|
258
|
+
if (node.prompt) {
|
|
259
|
+
lines.push("<details>");
|
|
260
|
+
lines.push("<summary>Prompt</summary>");
|
|
261
|
+
lines.push("");
|
|
262
|
+
lines.push("```");
|
|
263
|
+
lines.push(node.prompt.trim());
|
|
264
|
+
lines.push("```");
|
|
265
|
+
lines.push("");
|
|
266
|
+
lines.push("</details>");
|
|
267
|
+
lines.push("");
|
|
268
|
+
}
|
|
269
|
+
return lines.join("\n");
|
|
270
|
+
}
|
|
271
|
+
function renderAction(node) {
|
|
272
|
+
const lines = [];
|
|
273
|
+
const kindBadge = node.kind ? ` \`${node.kind}\`` : "";
|
|
274
|
+
lines.push(`#### ${toTitle(node.id)}${kindBadge}`);
|
|
275
|
+
lines.push("");
|
|
276
|
+
if (node.description) {
|
|
277
|
+
lines.push(node.description);
|
|
278
|
+
lines.push("");
|
|
279
|
+
}
|
|
280
|
+
const extra = [];
|
|
281
|
+
if (node.source)
|
|
282
|
+
extra.push(`Source: \`${node.source}\``);
|
|
283
|
+
if (node.timeout)
|
|
284
|
+
extra.push(`Timeout: ${node.timeout}`);
|
|
285
|
+
if (node.onFail)
|
|
286
|
+
extra.push(`On fail: \`${node.onFail}\``);
|
|
287
|
+
if (node.join)
|
|
288
|
+
extra.push(`Join: \`${node.join}\``);
|
|
289
|
+
if (extra.length) {
|
|
290
|
+
lines.push(extra.join(" · "));
|
|
291
|
+
lines.push("");
|
|
292
|
+
}
|
|
293
|
+
if (node.commands && node.commands.length) {
|
|
294
|
+
lines.push("```bash");
|
|
295
|
+
lines.push(node.commands.join("\n"));
|
|
296
|
+
lines.push("```");
|
|
297
|
+
lines.push("");
|
|
298
|
+
}
|
|
299
|
+
return lines.join("\n");
|
|
300
|
+
}
|
|
301
|
+
function renderGate(node) {
|
|
302
|
+
const lines = [];
|
|
303
|
+
lines.push(`#### ${toTitle(node.id)}`);
|
|
304
|
+
lines.push("");
|
|
305
|
+
const parts = [];
|
|
306
|
+
if (node.after)
|
|
307
|
+
parts.push(`After: \`${node.after}\``);
|
|
308
|
+
if (node.before)
|
|
309
|
+
parts.push(`Before: \`${node.before}\``);
|
|
310
|
+
if (node.run)
|
|
311
|
+
parts.push(`Run: \`${node.run}\``);
|
|
312
|
+
if (node.onFail)
|
|
313
|
+
parts.push(`On fail: \`${node.onFail}\``);
|
|
314
|
+
if (node.retry)
|
|
315
|
+
parts.push(`Retry: ${node.retry}x`);
|
|
316
|
+
if (node.timeout)
|
|
317
|
+
parts.push(`Timeout: ${node.timeout}`);
|
|
318
|
+
if (parts.length) {
|
|
319
|
+
lines.push(parts.join(" · "));
|
|
320
|
+
lines.push("");
|
|
321
|
+
}
|
|
322
|
+
if (node.checks && node.checks.length) {
|
|
323
|
+
lines.push(`Checks: ${node.checks.map((c) => `\`${c}\``).join(", ")}`);
|
|
324
|
+
lines.push("");
|
|
325
|
+
}
|
|
326
|
+
return lines.join("\n");
|
|
327
|
+
}
|
|
328
|
+
function renderHuman(node) {
|
|
329
|
+
const lines = [];
|
|
330
|
+
lines.push(`#### ${toTitle(node.id)}`);
|
|
331
|
+
lines.push("");
|
|
332
|
+
if (node.description) {
|
|
333
|
+
lines.push(node.description);
|
|
334
|
+
lines.push("");
|
|
335
|
+
}
|
|
336
|
+
const parts = [];
|
|
337
|
+
if (node.timeout)
|
|
338
|
+
parts.push(`Timeout: ${node.timeout}`);
|
|
339
|
+
if (node.onTimeout)
|
|
340
|
+
parts.push(`On timeout: \`${node.onTimeout}\``);
|
|
341
|
+
if (parts.length) {
|
|
342
|
+
lines.push(parts.join(" · "));
|
|
343
|
+
lines.push("");
|
|
344
|
+
}
|
|
345
|
+
return lines.join("\n");
|
|
346
|
+
}
|
|
347
|
+
function renderGroup(node) {
|
|
348
|
+
const lines = [];
|
|
349
|
+
lines.push(`#### ${toTitle(node.id)}`);
|
|
350
|
+
lines.push("");
|
|
351
|
+
if (node.description) {
|
|
352
|
+
lines.push(node.description);
|
|
353
|
+
lines.push("");
|
|
354
|
+
}
|
|
355
|
+
if (node.members.length) {
|
|
356
|
+
lines.push(`**Members:** ${node.members.map((m) => `\`${m}\``).join(", ")}`);
|
|
357
|
+
lines.push("");
|
|
358
|
+
}
|
|
359
|
+
const parts = [];
|
|
360
|
+
if (node.speakerSelection)
|
|
361
|
+
parts.push(`Speaker: \`${node.speakerSelection}\``);
|
|
362
|
+
if (node.maxRounds)
|
|
363
|
+
parts.push(`Max rounds: ${node.maxRounds}`);
|
|
364
|
+
if (node.termination)
|
|
365
|
+
parts.push(`Termination: ${node.termination}`);
|
|
366
|
+
if (node.timeout)
|
|
367
|
+
parts.push(`Timeout: ${node.timeout}`);
|
|
368
|
+
if (parts.length) {
|
|
369
|
+
lines.push(parts.join(" · "));
|
|
370
|
+
lines.push("");
|
|
371
|
+
}
|
|
372
|
+
return lines.join("\n");
|
|
373
|
+
}
|
|
374
|
+
function renderNodes(ast) {
|
|
375
|
+
const lines = [];
|
|
376
|
+
// Orchestrators
|
|
377
|
+
const orchestrators = ast.nodes.filter((n) => n.type === "orchestrator");
|
|
378
|
+
if (orchestrators.length) {
|
|
379
|
+
for (const n of orchestrators)
|
|
380
|
+
lines.push(renderOrchestrator(n));
|
|
381
|
+
}
|
|
382
|
+
// Agents by phase
|
|
383
|
+
const agents = ast.nodes.filter((n) => n.type === "agent");
|
|
384
|
+
if (agents.length) {
|
|
385
|
+
lines.push("## Agents");
|
|
386
|
+
lines.push("");
|
|
387
|
+
const sorted = [...agents].sort((a, b) => (a.phase ?? 0) - (b.phase ?? 0));
|
|
388
|
+
for (const n of sorted)
|
|
389
|
+
lines.push(renderAgent(n, ast.roles));
|
|
390
|
+
}
|
|
391
|
+
// Actions
|
|
392
|
+
const actions = ast.nodes.filter((n) => n.type === "action");
|
|
393
|
+
if (actions.length) {
|
|
394
|
+
lines.push("## Actions");
|
|
395
|
+
lines.push("");
|
|
396
|
+
for (const n of actions)
|
|
397
|
+
lines.push(renderAction(n));
|
|
398
|
+
}
|
|
399
|
+
// Gates
|
|
400
|
+
const gates = ast.nodes.filter((n) => n.type === "gate");
|
|
401
|
+
if (gates.length) {
|
|
402
|
+
lines.push("## Gates");
|
|
403
|
+
lines.push("");
|
|
404
|
+
for (const n of gates)
|
|
405
|
+
lines.push(renderGate(n));
|
|
406
|
+
}
|
|
407
|
+
// Humans
|
|
408
|
+
const humans = ast.nodes.filter((n) => n.type === "human");
|
|
409
|
+
if (humans.length) {
|
|
410
|
+
lines.push("## Human Nodes");
|
|
411
|
+
lines.push("");
|
|
412
|
+
for (const n of humans)
|
|
413
|
+
lines.push(renderHuman(n));
|
|
414
|
+
}
|
|
415
|
+
// Groups
|
|
416
|
+
const groups = ast.nodes.filter((n) => n.type === "group");
|
|
417
|
+
if (groups.length) {
|
|
418
|
+
lines.push("## Groups");
|
|
419
|
+
lines.push("");
|
|
420
|
+
for (const n of groups)
|
|
421
|
+
lines.push(renderGroup(n));
|
|
422
|
+
}
|
|
423
|
+
return lines.join("\n");
|
|
424
|
+
}
|
|
425
|
+
function renderFlow(ast) {
|
|
426
|
+
if (ast.edges.length === 0)
|
|
427
|
+
return "";
|
|
428
|
+
const lines = [];
|
|
429
|
+
lines.push("## Flow");
|
|
430
|
+
lines.push("");
|
|
431
|
+
lines.push("```");
|
|
432
|
+
for (const edge of ast.edges) {
|
|
433
|
+
const arrow = edge.isError ? " ─✗─> " : " ───> ";
|
|
434
|
+
const label = edgeLabel(edge);
|
|
435
|
+
const suffix = label ? ` [${label}]` : "";
|
|
436
|
+
lines.push(` ${edge.from}${arrow}${edge.to}${suffix}`);
|
|
437
|
+
}
|
|
438
|
+
lines.push("```");
|
|
439
|
+
lines.push("");
|
|
440
|
+
return lines.join("\n");
|
|
441
|
+
}
|
|
442
|
+
function renderMemory(ast) {
|
|
443
|
+
const entries = Object.entries(ast.memory);
|
|
444
|
+
if (entries.length === 0)
|
|
445
|
+
return "";
|
|
446
|
+
const lines = [];
|
|
447
|
+
lines.push("## Memory");
|
|
448
|
+
lines.push("");
|
|
449
|
+
for (const [name, config] of entries) {
|
|
450
|
+
lines.push(`**${toTitle(name)}**`);
|
|
451
|
+
if (typeof config === "object" && config !== null) {
|
|
452
|
+
const rec = config;
|
|
453
|
+
for (const [k, v] of Object.entries(rec)) {
|
|
454
|
+
if (Array.isArray(v)) {
|
|
455
|
+
lines.push(`- ${k}: ${v.map((i) => `\`${i}\``).join(", ")}`);
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
lines.push(`- ${k}: \`${String(v)}\``);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
lines.push("");
|
|
463
|
+
}
|
|
464
|
+
return lines.join("\n");
|
|
465
|
+
}
|
|
466
|
+
function renderTriggers(ast) {
|
|
467
|
+
if (ast.triggers.length === 0)
|
|
468
|
+
return "";
|
|
469
|
+
const lines = [];
|
|
470
|
+
lines.push("## Triggers");
|
|
471
|
+
lines.push("");
|
|
472
|
+
for (const t of ast.triggers) {
|
|
473
|
+
lines.push(`- **\`${t.name}\`** — \`${t.pattern}\`${t.argument ? ` (argument: \`${t.argument}\`)` : ""}`);
|
|
474
|
+
}
|
|
475
|
+
lines.push("");
|
|
476
|
+
return lines.join("\n");
|
|
477
|
+
}
|
|
478
|
+
function renderHooks(ast) {
|
|
479
|
+
if (ast.hooks.length === 0)
|
|
480
|
+
return "";
|
|
481
|
+
const lines = [];
|
|
482
|
+
lines.push("## Hooks");
|
|
483
|
+
lines.push("");
|
|
484
|
+
for (const h of ast.hooks) {
|
|
485
|
+
const matcher = h.matcher ? ` matching \`${h.matcher}\`` : "";
|
|
486
|
+
lines.push(`- **\`${h.name}\`** — on \`${h.on}\`${matcher} runs \`${h.run}\``);
|
|
487
|
+
}
|
|
488
|
+
lines.push("");
|
|
489
|
+
return lines.join("\n");
|
|
490
|
+
}
|
|
491
|
+
function renderSchedules(ast) {
|
|
492
|
+
if (ast.schedules.length === 0)
|
|
493
|
+
return "";
|
|
494
|
+
const lines = [];
|
|
495
|
+
lines.push("## Schedules");
|
|
496
|
+
lines.push("");
|
|
497
|
+
for (const s of ast.schedules) {
|
|
498
|
+
const schedule = s.cron ? `cron \`${s.cron}\`` : s.every ? `every \`${s.every}\`` : "";
|
|
499
|
+
const target = s.agent ? `agent \`${s.agent}\`` : s.action ? `action \`${s.action}\`` : "";
|
|
500
|
+
const enabled = s.enabled ? "" : " *(disabled)*";
|
|
501
|
+
lines.push(`- **\`${s.id}\`** — ${schedule} → ${target}${enabled}`);
|
|
502
|
+
}
|
|
503
|
+
lines.push("");
|
|
504
|
+
return lines.join("\n");
|
|
505
|
+
}
|
|
506
|
+
function renderSchemas(ast) {
|
|
507
|
+
if (ast.schemas.length === 0)
|
|
508
|
+
return "";
|
|
509
|
+
const lines = [];
|
|
510
|
+
lines.push("## Schemas");
|
|
511
|
+
lines.push("");
|
|
512
|
+
for (const schema of ast.schemas) {
|
|
513
|
+
lines.push(`**${toTitle(schema.id)}**`);
|
|
514
|
+
lines.push("");
|
|
515
|
+
for (const field of schema.fields) {
|
|
516
|
+
const typeStr = formatSchemaType(field.type);
|
|
517
|
+
const opt = field.optional ? " *(optional)*" : "";
|
|
518
|
+
lines.push(`- \`${field.name}\` — ${typeStr}${opt}`);
|
|
519
|
+
}
|
|
520
|
+
lines.push("");
|
|
521
|
+
}
|
|
522
|
+
return lines.join("\n");
|
|
523
|
+
}
|
|
524
|
+
function formatSchemaType(t) {
|
|
525
|
+
switch (t.kind) {
|
|
526
|
+
case "primitive": return `\`${t.value}\``;
|
|
527
|
+
case "array": return `\`${formatSchemaTypeRaw(t.itemType)}[]\``;
|
|
528
|
+
case "enum": return t.values.map((v) => `\`${v}\``).join(" / ");
|
|
529
|
+
case "ref": return `\`@${t.name}\``;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
function formatSchemaTypeRaw(t) {
|
|
533
|
+
switch (t.kind) {
|
|
534
|
+
case "primitive": return t.value;
|
|
535
|
+
case "array": return `${formatSchemaTypeRaw(t.itemType)}[]`;
|
|
536
|
+
case "enum": return t.values.join(" / ");
|
|
537
|
+
case "ref": return `@${t.name}`;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
function renderSkills(ast) {
|
|
541
|
+
if (ast.skills.length === 0)
|
|
542
|
+
return "";
|
|
543
|
+
const lines = [];
|
|
544
|
+
lines.push("## Skills");
|
|
545
|
+
lines.push("");
|
|
546
|
+
for (const s of ast.skills) {
|
|
547
|
+
lines.push(`- **${toTitle(s.id)}** — ${s.description}`);
|
|
548
|
+
if (s.scripts && s.scripts.length) {
|
|
549
|
+
lines.push(` - Scripts: ${s.scripts.map((x) => `\`${x}\``).join(", ")}`);
|
|
550
|
+
}
|
|
551
|
+
if (s.domains && s.domains.length) {
|
|
552
|
+
lines.push(` - Domains: ${s.domains.map((x) => `\`${x}\``).join(", ")}`);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
lines.push("");
|
|
556
|
+
return lines.join("\n");
|
|
557
|
+
}
|
|
558
|
+
function renderTools(ast) {
|
|
559
|
+
if (ast.toolDefs.length === 0)
|
|
560
|
+
return "";
|
|
561
|
+
const lines = [];
|
|
562
|
+
lines.push("## Custom Tools");
|
|
563
|
+
lines.push("");
|
|
564
|
+
for (const t of ast.toolDefs) {
|
|
565
|
+
const lang = t.lang ? ` (\`${t.lang}\`)` : "";
|
|
566
|
+
lines.push(`- **\`${t.id}\`**${lang} — ${t.description} `);
|
|
567
|
+
lines.push(` Script: \`${t.script}\``);
|
|
568
|
+
}
|
|
569
|
+
lines.push("");
|
|
570
|
+
return lines.join("\n");
|
|
571
|
+
}
|
|
572
|
+
function renderMetering(ast) {
|
|
573
|
+
if (!ast.metering)
|
|
574
|
+
return "";
|
|
575
|
+
const m = ast.metering;
|
|
576
|
+
const lines = [];
|
|
577
|
+
lines.push("## Metering");
|
|
578
|
+
lines.push("");
|
|
579
|
+
lines.push(`- **Track:** ${m.track.map((t) => `\`${t}\``).join(", ")}`);
|
|
580
|
+
lines.push(`- **Per:** ${m.per.map((p) => `\`${p}\``).join(", ")}`);
|
|
581
|
+
lines.push(`- **Output:** \`${m.output}\` (\`${m.format}\`)`);
|
|
582
|
+
lines.push("");
|
|
583
|
+
return lines.join("\n");
|
|
584
|
+
}
|
|
585
|
+
function renderSettings(ast) {
|
|
586
|
+
const entries = Object.entries(ast.settings);
|
|
587
|
+
if (entries.length === 0)
|
|
588
|
+
return "";
|
|
589
|
+
const lines = [];
|
|
590
|
+
lines.push("## Settings");
|
|
591
|
+
lines.push("");
|
|
592
|
+
for (const [key, value] of entries) {
|
|
593
|
+
if (Array.isArray(value)) {
|
|
594
|
+
const arr = value;
|
|
595
|
+
if (arr.length === 0) {
|
|
596
|
+
lines.push(`- **${toTitle(key)}:** *(none)*`);
|
|
597
|
+
}
|
|
598
|
+
else {
|
|
599
|
+
lines.push(`- **${toTitle(key)}:** ${arr.map((v) => `\`${v}\``).join(", ")}`);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
else {
|
|
603
|
+
lines.push(`- **${toTitle(key)}:** \`${String(value)}\``);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
lines.push("");
|
|
607
|
+
return lines.join("\n");
|
|
608
|
+
}
|
|
609
|
+
function renderMcpServers(ast) {
|
|
610
|
+
const entries = Object.entries(ast.mcpServers);
|
|
611
|
+
if (entries.length === 0)
|
|
612
|
+
return "";
|
|
613
|
+
const lines = [];
|
|
614
|
+
lines.push("## MCP Servers");
|
|
615
|
+
lines.push("");
|
|
616
|
+
for (const [name, config] of entries) {
|
|
617
|
+
const configEntries = Object.entries(config);
|
|
618
|
+
const summary = configEntries.map(([k, v]) => {
|
|
619
|
+
if (Array.isArray(v))
|
|
620
|
+
return `${k}: ${v.map((i) => `\`${String(i)}\``).join(", ")}`;
|
|
621
|
+
return `${k}: \`${String(v)}\``;
|
|
622
|
+
}).join(" · ");
|
|
623
|
+
lines.push(`- **${toTitle(name)}** — ${summary}`);
|
|
624
|
+
}
|
|
625
|
+
lines.push("");
|
|
626
|
+
return lines.join("\n");
|
|
627
|
+
}
|
|
628
|
+
function renderEnvironments(ast) {
|
|
629
|
+
const entries = Object.entries(ast.environments);
|
|
630
|
+
if (entries.length === 0)
|
|
631
|
+
return "";
|
|
632
|
+
const lines = [];
|
|
633
|
+
lines.push("## Environments");
|
|
634
|
+
lines.push("");
|
|
635
|
+
for (const [name, config] of entries) {
|
|
636
|
+
const summary = Object.entries(config).map(([k, v]) => `\`${k}\`=\`${String(v)}\``).join(", ");
|
|
637
|
+
lines.push(`- **${toTitle(name)}** — ${summary}`);
|
|
638
|
+
}
|
|
639
|
+
lines.push("");
|
|
640
|
+
return lines.join("\n");
|
|
641
|
+
}
|
|
642
|
+
function renderFooter() {
|
|
643
|
+
const lines = [];
|
|
644
|
+
lines.push("---");
|
|
645
|
+
lines.push("");
|
|
646
|
+
lines.push(`<sub>Generated by <a href="https://agentopology.com">AgenTopology</a></sub>`);
|
|
647
|
+
lines.push("");
|
|
648
|
+
return lines.join("\n");
|
|
649
|
+
}
|
|
650
|
+
// ---------------------------------------------------------------------------
|
|
651
|
+
// Main export function
|
|
652
|
+
// ---------------------------------------------------------------------------
|
|
653
|
+
function exportMarkdown(ast) {
|
|
654
|
+
const sections = [];
|
|
655
|
+
sections.push(renderHeader(ast));
|
|
656
|
+
sections.push(renderOverview(ast));
|
|
657
|
+
sections.push(renderRoles(ast));
|
|
658
|
+
sections.push(renderNodes(ast));
|
|
659
|
+
sections.push(renderFlow(ast));
|
|
660
|
+
sections.push(renderMemory(ast));
|
|
661
|
+
sections.push(renderTriggers(ast));
|
|
662
|
+
sections.push(renderHooks(ast));
|
|
663
|
+
sections.push(renderSchedules(ast));
|
|
664
|
+
sections.push(renderSchemas(ast));
|
|
665
|
+
sections.push(renderSkills(ast));
|
|
666
|
+
sections.push(renderTools(ast));
|
|
667
|
+
sections.push(renderMetering(ast));
|
|
668
|
+
sections.push(renderMcpServers(ast));
|
|
669
|
+
sections.push(renderEnvironments(ast));
|
|
670
|
+
sections.push(renderSettings(ast));
|
|
671
|
+
sections.push(renderFooter());
|
|
672
|
+
// Filter empty sections and join
|
|
673
|
+
const content = sections.filter((s) => s.trim().length > 0).join("\n");
|
|
674
|
+
const stem = ast.topology.name;
|
|
675
|
+
return [{ path: `${stem}.md`, content }];
|
|
676
|
+
}
|
|
677
|
+
// ---------------------------------------------------------------------------
|
|
678
|
+
// Exporter instance
|
|
679
|
+
// ---------------------------------------------------------------------------
|
|
680
|
+
export const markdownExporter = {
|
|
681
|
+
name: "markdown",
|
|
682
|
+
description: "Markdown documentation — shareable topology reference",
|
|
683
|
+
extension: ".md",
|
|
684
|
+
export: exportMarkdown,
|
|
685
|
+
};
|
|
686
|
+
//# sourceMappingURL=markdown.js.map
|