taskflow-mcp-core 0.1.6
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 +21 -0
- package/README.md +951 -0
- package/dist/mcp/jsonrpc.d.ts +54 -0
- package/dist/mcp/jsonrpc.d.ts.map +1 -0
- package/dist/mcp/jsonrpc.js +118 -0
- package/dist/mcp/jsonrpc.js.map +1 -0
- package/dist/mcp/server.d.ts +38 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +538 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/svg.d.ts +52 -0
- package/dist/mcp/svg.d.ts.map +1 -0
- package/dist/mcp/svg.js +312 -0
- package/dist/mcp/svg.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* taskflow as an MCP server (host-neutral core).
|
|
3
|
+
*
|
|
4
|
+
* Exposes the taskflow engine as MCP tools so an MCP host (Codex, Claude Code,
|
|
5
|
+
* or any MCP client) can declare and run verifiable task DAGs from inside its
|
|
6
|
+
* own session. Each host adapter binds this server to its own `SubagentRunner`
|
|
7
|
+
* (codex → `codex exec` subagents, claude → `claude -p` subagents), so the
|
|
8
|
+
* whole thing closes the loop with no pi process required.
|
|
9
|
+
*
|
|
10
|
+
* Protocol: MCP over stdio, JSON-RPC 2.0 (newline-delimited). Implemented on the
|
|
11
|
+
* dependency-free transport in ./jsonrpc.ts — taskflow-core keeps its zero-
|
|
12
|
+
* runtime-deps guarantee; we do NOT use @modelcontextprotocol/sdk.
|
|
13
|
+
*
|
|
14
|
+
* This module is intentionally NOT in the barrel (index.ts) — hosts import it
|
|
15
|
+
* via the `taskflow-mcp` package (it is NOT re-exported from taskflow-core.
|
|
16
|
+
*
|
|
17
|
+
* Tools exposed:
|
|
18
|
+
* - taskflow_run : run an inline or saved flow, return the final output
|
|
19
|
+
* - taskflow_list : list saved flows discoverable in this cwd
|
|
20
|
+
* - taskflow_show : show a saved flow's definition
|
|
21
|
+
* - taskflow_verify : statically verify a flow (no execution)
|
|
22
|
+
* - taskflow_compile : render a flow as a DAG diagram (SVG image) + status line
|
|
23
|
+
* - taskflow_peek : inspect a stored run's intermediate phase output
|
|
24
|
+
*/
|
|
25
|
+
import { RpcError, RPC, serveStdio } from "./jsonrpc.js";
|
|
26
|
+
import { renderFlowSvg, renderFlowOutline, svgToBase64 } from "./svg.js";
|
|
27
|
+
import { discoverAgents, executeTaskflow, getFlow, listFlows, newRunId, peekRun, saveRun, DEFAULT_KEPT_RUNS, DEFAULT_RUN_AGE_DAYS, readDefineFile, compileTaskflow, verifyTaskflow, desugar, isShorthand, validateTaskflow, readSubagentSettings, readMeta, saveFlowWithMeta, bumpReuseInSidecar, deriveMeta, searchLibrary, } from "taskflow-core";
|
|
28
|
+
const PROTOCOL_VERSION = "2025-06-18";
|
|
29
|
+
const SERVER_INFO = { name: "taskflow", title: "Taskflow", version: "0.1.5" };
|
|
30
|
+
/**
|
|
31
|
+
* MCP tools/call result with a single text block.
|
|
32
|
+
*
|
|
33
|
+
* IMPORTANT (rendering): the Codex desktop app renders a `text` content block
|
|
34
|
+
* as a fixed grey "plaintext" <pre> box — it does NOT parse markdown or
|
|
35
|
+
* highlight code, wraps on whitespace, and caps the box at ~192px tall with an
|
|
36
|
+
* inner scroll; Claude Code's TUI shows tool results as monospace text. So
|
|
37
|
+
* text here is written as *plain text*: no ```fences```, no markdown tables,
|
|
38
|
+
* conclusion-first, and near-duplicate lines collapsed. Rich rendering
|
|
39
|
+
* (structuredContent/_meta) is gated to Codex's first-party "Apps" server, so
|
|
40
|
+
* third-party MCP output can't opt into it. See docs/codex-mcp.md.
|
|
41
|
+
*/
|
|
42
|
+
function textContent(text, isError = false) {
|
|
43
|
+
return { content: [{ type: "text", text }], isError };
|
|
44
|
+
}
|
|
45
|
+
/** An MCP `image` content block, optionally followed by text blocks. Codex's
|
|
46
|
+
* desktop app renders the image as `<img src="data:…">` (an inline SVG shows as
|
|
47
|
+
* a real diagram) and shows the trailing text as a caption. The CLI/TUI can't
|
|
48
|
+
* render images — it prints a bare `<image content>` placeholder — so the
|
|
49
|
+
* trailing text MUST be self-sufficient there (and for vision-less models). */
|
|
50
|
+
function imageContent(base64, mimeType, texts, isError = false) {
|
|
51
|
+
const content = [{ type: "image", data: base64, mimeType }];
|
|
52
|
+
for (const t of texts)
|
|
53
|
+
if (t)
|
|
54
|
+
content.push({ type: "text", text: t });
|
|
55
|
+
return { content, isError };
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Collapse near-identical validation messages so N phases hitting the same rule
|
|
59
|
+
* render as one line with a count instead of N wall-of-text repeats (the exact
|
|
60
|
+
* ugliness this file is fighting). Strips a leading `Phase '<id>': ` / `Phase
|
|
61
|
+
* '<id>' ` prefix, groups by the remaining message, and lists the affected ids.
|
|
62
|
+
*/
|
|
63
|
+
function dedupeMessages(msgs) {
|
|
64
|
+
const groups = new Map();
|
|
65
|
+
const order = [];
|
|
66
|
+
for (const raw of msgs) {
|
|
67
|
+
const m = raw.match(/^Phase '([^']+)':?\s+(.*)$/s);
|
|
68
|
+
const key = m ? m[2] : raw;
|
|
69
|
+
const id = m ? m[1] : "";
|
|
70
|
+
if (!groups.has(key)) {
|
|
71
|
+
groups.set(key, []);
|
|
72
|
+
order.push(key);
|
|
73
|
+
}
|
|
74
|
+
if (id)
|
|
75
|
+
groups.get(key).push(id);
|
|
76
|
+
}
|
|
77
|
+
return order.map((key) => {
|
|
78
|
+
const ids = groups.get(key);
|
|
79
|
+
if (ids.length === 0)
|
|
80
|
+
return key;
|
|
81
|
+
if (ids.length === 1)
|
|
82
|
+
return `${key} (phase ${ids[0]})`;
|
|
83
|
+
const shown = ids.slice(0, 4).join(", ");
|
|
84
|
+
const more = ids.length > 4 ? ` +${ids.length - 4} more` : "";
|
|
85
|
+
return `${key} (${ids.length} phases: ${shown}${more})`;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Render verification issues as deduped, conclusion-friendly "Errors:" /
|
|
90
|
+
* "Warnings:" plaintext blocks. `extraErrors`/`extraWarnings` fold in the raw
|
|
91
|
+
* string messages from `validateTaskflow` so structural + quality issues share
|
|
92
|
+
* one deduped view. Shared by taskflow_verify and taskflow_compile's fallback.
|
|
93
|
+
*/
|
|
94
|
+
function issueBlocks(issues, extraErrors = [], extraWarnings = []) {
|
|
95
|
+
const toStr = (i) =>
|
|
96
|
+
// verifyTaskflow messages already embed the phase id in prose ("Phase 'x'
|
|
97
|
+
// is a terminal phase…"); only prepend the id for messages that don't, so
|
|
98
|
+
// dedupeMessages can strip one consistent prefix and collapse same-rule hits.
|
|
99
|
+
i.phaseId && !/^Phase '/.test(i.message) ? `Phase '${i.phaseId}': ${i.message}` : i.message;
|
|
100
|
+
const rawErrors = [...extraErrors, ...issues.filter((i) => i.severity === "error").map(toStr)];
|
|
101
|
+
const rawWarnings = [...extraWarnings, ...issues.filter((i) => i.severity === "warning").map(toStr)];
|
|
102
|
+
// Count reflects the true number of issues; the lines below are the *deduped*
|
|
103
|
+
// compact view (N same-rule hits collapse to one line + a phase list).
|
|
104
|
+
const errors = dedupeMessages(rawErrors);
|
|
105
|
+
const warnings = dedupeMessages(rawWarnings);
|
|
106
|
+
const errBlock = errors.length ? `\n\nErrors:\n${errors.map((e) => `- ${e}`).join("\n")}` : "";
|
|
107
|
+
const warnBlock = warnings.length ? `\n\nWarnings:\n${warnings.map((w) => `- ${w}`).join("\n")}` : "";
|
|
108
|
+
return { errorCount: rawErrors.length, warningCount: rawWarnings.length, text: `${errBlock}${warnBlock}` };
|
|
109
|
+
}
|
|
110
|
+
/** Pluralize a count for a compact status line. */
|
|
111
|
+
function count(n, noun) {
|
|
112
|
+
return `${n} ${noun}${n === 1 ? "" : "s"}`;
|
|
113
|
+
}
|
|
114
|
+
const TOOLS = [
|
|
115
|
+
{
|
|
116
|
+
name: "taskflow_run",
|
|
117
|
+
title: "Run a taskflow",
|
|
118
|
+
description: "Run a taskflow DAG and return its final output. Provide EITHER `name` (a saved flow) OR `define` (an inline flow definition: {name, phases:[…]} or a shorthand {task} / {tasks} / {chain}). Subagents execute as isolated host sessions. Intermediate phase outputs stay in the runtime; only the final phase output is returned — the reported runId can be passed to taskflow_peek to inspect intermediate phase outputs afterwards.",
|
|
119
|
+
inputSchema: {
|
|
120
|
+
type: "object",
|
|
121
|
+
additionalProperties: false,
|
|
122
|
+
properties: {
|
|
123
|
+
name: { type: "string", description: "Name of a saved flow to run." },
|
|
124
|
+
define: { type: "object", description: "Inline flow definition (full DAG or shorthand)." },
|
|
125
|
+
defineFile: { type: "string", description: "Path to a file holding the flow definition (raw JSON, or Markdown with a ```json fence). Lets you verify/compile/run share ONE persisted draft (e.g. in the OS tmp dir) — edit the file between calls instead of re-sending the whole definition. Precedence: define > defineFile > name." },
|
|
126
|
+
args: { type: "object", description: "Invocation arguments interpolated as {args.X}." },
|
|
127
|
+
incremental: { type: "boolean", description: "Default every phase to cross-run cache reuse." },
|
|
128
|
+
reusedFromSearch: { type: "boolean", description: "Set true when this run was chosen because of a prior taskflow_search → bumps the flow's reuseCount (the reuse flywheel). Default false; direct run-by-name does not bump." },
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: "taskflow_list",
|
|
134
|
+
title: "List saved taskflows",
|
|
135
|
+
description: "List the saved taskflows discoverable from the current working directory (user + project scope).",
|
|
136
|
+
inputSchema: { type: "object", additionalProperties: false, properties: {} },
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: "taskflow_show",
|
|
140
|
+
title: "Show a saved taskflow",
|
|
141
|
+
description: "Show a saved flow's full definition as JSON.",
|
|
142
|
+
inputSchema: {
|
|
143
|
+
type: "object",
|
|
144
|
+
additionalProperties: false,
|
|
145
|
+
properties: { name: { type: "string", description: "Name of the saved flow." } },
|
|
146
|
+
required: ["name"],
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: "taskflow_verify",
|
|
151
|
+
title: "Verify a taskflow",
|
|
152
|
+
description: "Statically verify a flow (cycles, missing deps, undefined refs, …) WITHOUT executing it. Provide `name`, `define`, or `defineFile`.",
|
|
153
|
+
inputSchema: {
|
|
154
|
+
type: "object",
|
|
155
|
+
additionalProperties: false,
|
|
156
|
+
properties: {
|
|
157
|
+
name: { type: "string" },
|
|
158
|
+
define: { type: "object" },
|
|
159
|
+
defineFile: { type: "string", description: "Path to a JSON (or fenced-Markdown) flow file. See taskflow_run.defineFile." },
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: "taskflow_compile",
|
|
165
|
+
title: "Compile a taskflow to a diagram",
|
|
166
|
+
description: "Render a flow's DAG as a diagram (an inline SVG image) with issues overlaid (red=error, amber=warning, green=final), plus a compact status line. No execution. Provide `name`, `define`, or `defineFile`.",
|
|
167
|
+
inputSchema: {
|
|
168
|
+
type: "object",
|
|
169
|
+
additionalProperties: false,
|
|
170
|
+
properties: {
|
|
171
|
+
name: { type: "string" },
|
|
172
|
+
define: { type: "object" },
|
|
173
|
+
defineFile: { type: "string", description: "Path to a JSON (or fenced-Markdown) flow file. See taskflow_run.defineFile." },
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: "taskflow_peek",
|
|
179
|
+
title: "Peek at a run's phase output",
|
|
180
|
+
description: "Inspect one phase's intermediate output from a stored run (post-hoc debugging). Use the runId reported by taskflow_run. Omit `phaseId` to list the run's phases. Output is hard-truncated (default 4000 chars) so a peek never floods the context window. Read-only.",
|
|
181
|
+
inputSchema: {
|
|
182
|
+
type: "object",
|
|
183
|
+
additionalProperties: false,
|
|
184
|
+
properties: {
|
|
185
|
+
runId: { type: "string", description: "The run to inspect (from a prior taskflow_run or the runs index)." },
|
|
186
|
+
phaseId: { type: "string", description: "Phase to peek at. Omit to list all phases with status + output size." },
|
|
187
|
+
json: { type: "boolean", description: "Return the phase's parsed JSON instead of its text output." },
|
|
188
|
+
item: { type: "number", description: "For map/parallel phases: the 1-based item section to extract." },
|
|
189
|
+
limit: { type: "number", description: "Truncation cap in chars (default 4000, max 32000)." },
|
|
190
|
+
},
|
|
191
|
+
required: ["runId"],
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
name: "taskflow_save",
|
|
196
|
+
title: "Save a reusable taskflow",
|
|
197
|
+
description: "Save a flow as a reusable library asset: persists the flow AND a sidecar .meta.json with purpose/tags/notes + auto-derived structural metadata (phase signature, generality score) so taskflow_search can retrieve it later. Pass purpose + 2-4 tags for any flow you expect to reuse — this is what makes search recall work.",
|
|
198
|
+
inputSchema: {
|
|
199
|
+
type: "object",
|
|
200
|
+
additionalProperties: false,
|
|
201
|
+
properties: {
|
|
202
|
+
name: { type: "string", description: "Flow name (also the filename stem)." },
|
|
203
|
+
definition: { type: "object", description: "Full taskflow DSL object ({name, phases:[...]}) or shorthand ({task}|{tasks}|{chain})." },
|
|
204
|
+
purpose: { type: "string", description: "One-line purpose — the single most important field for search recall. Write what the flow DOES and WHEN to use it." },
|
|
205
|
+
tags: { type: "array", items: { type: "string" }, description: "2-4 reuse tags (e.g. audit, fan-out, migration, security)." },
|
|
206
|
+
notes: { type: "string", description: "Free-form reuse notes (when NOT to use, required args, gotchas)." },
|
|
207
|
+
scope: { type: "string", enum: ["project", "user"], description: "project (default) or user-global." },
|
|
208
|
+
},
|
|
209
|
+
required: ["name", "definition"],
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
name: "taskflow_search",
|
|
214
|
+
title: "Search the taskflow library",
|
|
215
|
+
description: "Search saved flows by purpose BEFORE authoring a new one — the reuse flywheel. Returns ranked matches with a score, why it matched, and a reuse hint (direct-reuse / copy-and-generalize / write-fresh). Falls back to keyword+structural ranking when no embedding backend is configured (structural mode); uses cosine similarity when one is (semantic/mixed mode).",
|
|
216
|
+
inputSchema: {
|
|
217
|
+
type: "object",
|
|
218
|
+
additionalProperties: false,
|
|
219
|
+
properties: {
|
|
220
|
+
query: { type: "string", description: "Natural-language purpose string (what you want the flow to do)." },
|
|
221
|
+
limit: { type: "number", description: "Max results (default 5, max 20)." },
|
|
222
|
+
structureOnly: { type: "boolean", description: "Skip embedding, use keyword+structural ranking only (zero latency)." },
|
|
223
|
+
minScore: { type: "number", description: "Drop results below this score (0-1)." },
|
|
224
|
+
scope: { type: "string", enum: ["project", "user", "both"], description: "Which scopes to search (default from settings: both)." },
|
|
225
|
+
},
|
|
226
|
+
required: ["query"],
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
];
|
|
230
|
+
/** Resolve a flow from params: inline `define` (desugared), `defineFile` (disk), or saved `name`. */
|
|
231
|
+
function resolveFlow(cwd, params) {
|
|
232
|
+
if (params.define === undefined && typeof params.defineFile === "string" && params.defineFile.trim()) {
|
|
233
|
+
const fromFile = readDefineFile(params.defineFile);
|
|
234
|
+
if (fromFile === null)
|
|
235
|
+
throw new RpcError(RPC.INVALID_PARAMS, `defineFile not found or unparseable: ${params.defineFile}`);
|
|
236
|
+
params = { ...params, define: fromFile };
|
|
237
|
+
}
|
|
238
|
+
if (params.define !== undefined && params.define !== null) {
|
|
239
|
+
return isShorthand(params.define) ? desugar(params.define) : params.define;
|
|
240
|
+
}
|
|
241
|
+
if (params.name) {
|
|
242
|
+
const saved = getFlow(cwd, params.name);
|
|
243
|
+
if (!saved)
|
|
244
|
+
throw new RpcError(RPC.INVALID_PARAMS, `No saved flow named "${params.name}" found from ${cwd}.`);
|
|
245
|
+
return saved.def;
|
|
246
|
+
}
|
|
247
|
+
throw new RpcError(RPC.INVALID_PARAMS, "Provide either `name` (a saved flow) or `define` (an inline flow).");
|
|
248
|
+
}
|
|
249
|
+
function mkRunState(def, args, cwd) {
|
|
250
|
+
return {
|
|
251
|
+
runId: newRunId(def.name ?? "flow"),
|
|
252
|
+
flowName: def.name ?? "flow",
|
|
253
|
+
def,
|
|
254
|
+
args,
|
|
255
|
+
status: "running",
|
|
256
|
+
phases: {},
|
|
257
|
+
createdAt: Date.now(),
|
|
258
|
+
updatedAt: Date.now(),
|
|
259
|
+
cwd,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Build the per-call tool handlers. `cwd` is the directory the server was
|
|
264
|
+
* launched in (where saved flows + agents are discovered, and where subagents
|
|
265
|
+
* run). `runner` is the host's SubagentRunner (codex/claude) — each phase's
|
|
266
|
+
* subagent executes through it.
|
|
267
|
+
*/
|
|
268
|
+
export function makeToolHandlers(cwd, runner) {
|
|
269
|
+
return {
|
|
270
|
+
taskflow_run: async (args) => {
|
|
271
|
+
const def = resolveFlow(cwd, args);
|
|
272
|
+
const v = validateTaskflow(def);
|
|
273
|
+
if (!v.ok)
|
|
274
|
+
return textContent(`Flow is invalid:\n- ${v.errors.join("\n- ")}`, true);
|
|
275
|
+
// Resolve model roles (e.g. {{fast}} -> a real model id) so the built-in
|
|
276
|
+
// agents' placeholder models map to something the host can launch. This is
|
|
277
|
+
// the same lookup the pi adapter does; without it every phase fails with
|
|
278
|
+
// "Model metadata for {{fast}} not found".
|
|
279
|
+
const settings = readSubagentSettings();
|
|
280
|
+
const { agents } = discoverAgents(cwd, "both", settings.modelRoles, settings.taskflow);
|
|
281
|
+
const deps = {
|
|
282
|
+
cwd,
|
|
283
|
+
agents,
|
|
284
|
+
runTask: runner.runTask,
|
|
285
|
+
};
|
|
286
|
+
const state = mkRunState(def, args.args ?? {}, cwd);
|
|
287
|
+
if (args.incremental === true)
|
|
288
|
+
deps.cacheScopeDefault = "cross-run";
|
|
289
|
+
// Persist run state (throttled + final) so taskflow_peek / resume can read
|
|
290
|
+
// intermediate phase outputs after the run — same contract as the pi adapter.
|
|
291
|
+
const cleanupConfig = { maxKeep: DEFAULT_KEPT_RUNS, maxAgeDays: DEFAULT_RUN_AGE_DAYS };
|
|
292
|
+
let lastPersist = 0;
|
|
293
|
+
deps.persist = (s) => {
|
|
294
|
+
const now = Date.now();
|
|
295
|
+
if (now - lastPersist >= 1000) {
|
|
296
|
+
lastPersist = now;
|
|
297
|
+
saveRun(s, cleanupConfig);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
const res = await executeTaskflow(state, deps).finally(() => {
|
|
301
|
+
// Terminal persist must survive a throwing runtime ("never lose work") —
|
|
302
|
+
// and persistence itself must never sink a completed run.
|
|
303
|
+
try {
|
|
304
|
+
saveRun(state, cleanupConfig);
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
/* fail-open */
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
if (res.ok && args.reusedFromSearch === true && typeof args.name === "string" && args.name.trim()) {
|
|
311
|
+
try {
|
|
312
|
+
bumpReuseInSidecar(cwd, args.name);
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
/* fail-open: reuse bookkeeping is best-effort */
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
const header = res.ok ? "✓ taskflow complete" : "✗ taskflow did not fully succeed";
|
|
319
|
+
const u = res.totalUsage;
|
|
320
|
+
const usageLine = `\n\n— ${u.turns} turns · in ${u.input} · out ${u.output} tokens · run ${state.runId}`;
|
|
321
|
+
return textContent(`${header}\n\n${res.finalOutput}${usageLine}`, !res.ok);
|
|
322
|
+
},
|
|
323
|
+
taskflow_peek: async (args) => {
|
|
324
|
+
const runId = String(args.runId ?? "");
|
|
325
|
+
if (!runId)
|
|
326
|
+
return textContent("taskflow_peek requires `runId`.", true);
|
|
327
|
+
const res = peekRun(cwd, runId, {
|
|
328
|
+
phaseId: typeof args.phaseId === "string" ? args.phaseId : undefined,
|
|
329
|
+
json: args.json === true,
|
|
330
|
+
item: typeof args.item === "number" ? args.item : undefined,
|
|
331
|
+
limit: typeof args.limit === "number" ? args.limit : undefined,
|
|
332
|
+
});
|
|
333
|
+
return textContent(res.text, !res.ok);
|
|
334
|
+
},
|
|
335
|
+
taskflow_list: async () => {
|
|
336
|
+
const flows = listFlows(cwd);
|
|
337
|
+
if (flows.length === 0)
|
|
338
|
+
return textContent("No saved taskflows found from this directory.");
|
|
339
|
+
const lines = flows.map((f) => {
|
|
340
|
+
const meta = readMeta(cwd, f.name);
|
|
341
|
+
if (meta?.purpose) {
|
|
342
|
+
const purpose = meta.purpose.length > 20 ? meta.purpose.slice(0, 20) + "…" : meta.purpose;
|
|
343
|
+
return `- ${f.name} (${f.scope}) — ${f.def.phases.length} phase(s) · ${purpose} · g=${meta.generality?.toFixed(2) ?? "?"} · used ${meta.reuseCount ?? 0}×`;
|
|
344
|
+
}
|
|
345
|
+
return `- ${f.name} (${f.scope}) — ${f.def.phases.length} phase(s)`;
|
|
346
|
+
});
|
|
347
|
+
return textContent(`Saved taskflows:\n${lines.join("\n")}`);
|
|
348
|
+
},
|
|
349
|
+
taskflow_show: async (args) => {
|
|
350
|
+
const name = String(args.name ?? "");
|
|
351
|
+
const saved = getFlow(cwd, name);
|
|
352
|
+
if (!saved)
|
|
353
|
+
return textContent(`No saved flow named "${name}".`, true);
|
|
354
|
+
const meta = readMeta(cwd, name);
|
|
355
|
+
if (meta) {
|
|
356
|
+
const out = { definition: saved.def, library: { purpose: meta.purpose, tags: meta.tags, notes: meta.notes, generality: meta.generality, reuseCount: meta.reuseCount, version: meta.version, phaseSignature: meta.phaseSignature } };
|
|
357
|
+
return textContent(JSON.stringify(out, null, 2));
|
|
358
|
+
}
|
|
359
|
+
// No ```json``` fence: Codex shows text blocks as raw plaintext, so a fence
|
|
360
|
+
// would render as literal backticks. The JSON is already monospaced there.
|
|
361
|
+
return textContent(JSON.stringify(saved.def, null, 2));
|
|
362
|
+
},
|
|
363
|
+
taskflow_save: async (args) => {
|
|
364
|
+
const name = String(args.name ?? "");
|
|
365
|
+
if (!name.trim())
|
|
366
|
+
return textContent("taskflow_save requires `name`.", true);
|
|
367
|
+
if (!args.definition)
|
|
368
|
+
return textContent("taskflow_save requires `definition` (the DSL object or shorthand).", true);
|
|
369
|
+
// Resolve + validate the definition (mirrors resolveFlow + run's validation).
|
|
370
|
+
let def;
|
|
371
|
+
try {
|
|
372
|
+
def = resolveFlow(cwd, { define: args.definition });
|
|
373
|
+
}
|
|
374
|
+
catch (e) {
|
|
375
|
+
return textContent(`Invalid flow definition: ${e instanceof Error ? e.message : String(e)}`, true);
|
|
376
|
+
}
|
|
377
|
+
// Force the name to match the argument (resolveFlow/shorthand may synthesize one).
|
|
378
|
+
def = { ...def, name };
|
|
379
|
+
const v = validateTaskflow(def);
|
|
380
|
+
if (!v.ok)
|
|
381
|
+
return textContent(`Flow is invalid:\n- ${v.errors.join("\n- ")}`, true);
|
|
382
|
+
const scope = args.scope === "user" ? "user" : "project";
|
|
383
|
+
const prevMeta = readMeta(cwd, name) ?? undefined;
|
|
384
|
+
const meta = deriveMeta(def, {
|
|
385
|
+
purpose: typeof args.purpose === "string" ? args.purpose : undefined,
|
|
386
|
+
tags: Array.isArray(args.tags) ? args.tags.filter((t) => typeof t === "string") : undefined,
|
|
387
|
+
notes: typeof args.notes === "string" ? args.notes : undefined,
|
|
388
|
+
prevMeta,
|
|
389
|
+
});
|
|
390
|
+
const { filePath } = saveFlowWithMeta(cwd, def, meta, scope);
|
|
391
|
+
return textContent(`Saved taskflow '${name}' → ${filePath}\n purpose: ${meta.purpose ?? "(none)"}\n tags: ${(meta.tags ?? []).join(", ") || "(none)"}\n phaseSignature: ${meta.phaseSignature}\n generality: ${meta.generality.toFixed(2)}`);
|
|
392
|
+
},
|
|
393
|
+
taskflow_search: async (args) => {
|
|
394
|
+
const query = String(args.query ?? "").trim();
|
|
395
|
+
if (!query)
|
|
396
|
+
return textContent("taskflow_search requires `query`.", true);
|
|
397
|
+
const settings = readSubagentSettings();
|
|
398
|
+
if (!settings.taskflow.library.enabled) {
|
|
399
|
+
return textContent("Library is disabled (settings.json → taskflow.library.enabled = false).", true);
|
|
400
|
+
}
|
|
401
|
+
const deps = { settings: settings.taskflow.library, cwd };
|
|
402
|
+
const input = {
|
|
403
|
+
query,
|
|
404
|
+
limit: typeof args.limit === "number" ? args.limit : undefined,
|
|
405
|
+
structureOnly: args.structureOnly === true,
|
|
406
|
+
minScore: typeof args.minScore === "number" ? args.minScore : undefined,
|
|
407
|
+
scope: args.scope === "project" || args.scope === "user" || args.scope === "both" ? args.scope : undefined,
|
|
408
|
+
};
|
|
409
|
+
const res = await searchLibrary(deps, input);
|
|
410
|
+
const lines = [];
|
|
411
|
+
lines.push(`Library search — ${res.counts.scanned} flow(s) scanned · ${res.searchMode} mode${res.embedder ? ` · ${res.embedder}` : ""}`);
|
|
412
|
+
if (res.results.length === 0) {
|
|
413
|
+
lines.push("No matches. Consider authoring a new flow and saving it (taskflow_save with purpose+tags).");
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
for (const r of res.results) {
|
|
417
|
+
lines.push(`- ${r.name} (${r.scope}) — score ${r.score.toFixed(2)} · ${r.phaseSignature || "?"} · g=${r.generality.toFixed(2)} · v${r.version} · used ${r.reuseCount}×`);
|
|
418
|
+
if (r.purpose)
|
|
419
|
+
lines.push(` purpose: ${r.purpose}`);
|
|
420
|
+
if (r.tags?.length)
|
|
421
|
+
lines.push(` tags: ${r.tags.join(", ")}`);
|
|
422
|
+
lines.push(` why: ${r.why}`);
|
|
423
|
+
lines.push(` → ${r.reuseHint}`);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return textContent(lines.join("\n"));
|
|
427
|
+
},
|
|
428
|
+
taskflow_verify: async (args) => {
|
|
429
|
+
const def = resolveFlow(cwd, args);
|
|
430
|
+
const val = validateTaskflow(def);
|
|
431
|
+
// verifyTaskflow iterates flow.phases and throws if it isn't an array
|
|
432
|
+
// (e.g. a missing `phases`). Only skip it in that unsafe case; otherwise
|
|
433
|
+
// run it so its static-quality warnings (e.g. terminal-not-final) still
|
|
434
|
+
// surface alongside validateTaskflow's structural errors.
|
|
435
|
+
const phasesIterable = Array.isArray(def.phases);
|
|
436
|
+
const result = phasesIterable
|
|
437
|
+
? verifyTaskflow(def)
|
|
438
|
+
: { ok: false, issues: [] };
|
|
439
|
+
const { errorCount, warningCount, text } = issueBlocks(result.issues, val.errors, val.warnings);
|
|
440
|
+
const passed = val.ok && result.ok && errorCount === 0;
|
|
441
|
+
// Conclusion-first (the plaintext box is short + scrolls): verdict + counts
|
|
442
|
+
// on line 1, deduped detail below.
|
|
443
|
+
const head = passed
|
|
444
|
+
? warningCount
|
|
445
|
+
? `✓ verification PASSED — ${count(warningCount, "warning")}`
|
|
446
|
+
: "✓ verification PASSED"
|
|
447
|
+
: `✗ verification FAILED — ${count(errorCount, "error")}, ${count(warningCount, "warning")}`;
|
|
448
|
+
return textContent(`${head}${text}`, !passed);
|
|
449
|
+
},
|
|
450
|
+
taskflow_compile: async (args) => {
|
|
451
|
+
const def = resolveFlow(cwd, args);
|
|
452
|
+
const val = validateTaskflow(def);
|
|
453
|
+
// compileTaskflow / verifyTaskflow / renderFlowSvg all assume phases is an
|
|
454
|
+
// array of objects that each have a string id (they iterate it and index
|
|
455
|
+
// id.replace(...)). A hard-malformed def (non-array phases, a phase missing
|
|
456
|
+
// its id) would throw, so when the shape isn't renderable we return the
|
|
457
|
+
// structured validation errors as text instead of rendering.
|
|
458
|
+
const phases = def.phases;
|
|
459
|
+
const renderable = Array.isArray(phases) && phases.every((p) => p != null && typeof p.id === "string");
|
|
460
|
+
if (!renderable) {
|
|
461
|
+
const { errorCount, warningCount, text } = issueBlocks([], val.errors, val.warnings);
|
|
462
|
+
const caption = `${def.name ?? "taskflow"} — ${count(errorCount, "error")} · ${count(warningCount, "warning")} · ✗ FAIL`;
|
|
463
|
+
return textContent(`${caption}${text}`, true);
|
|
464
|
+
}
|
|
465
|
+
// Merge structural validation into the compile report. compileTaskflow's
|
|
466
|
+
// own verification.ok is true even for a structurally-invalid (but
|
|
467
|
+
// renderable) flow, so a validate-clean check is what stops a false ✓ PASS.
|
|
468
|
+
// We still render the diagram + outline so such a flow can be inspected
|
|
469
|
+
// visually; truncate coerces non-string fields so the renderer won't throw.
|
|
470
|
+
const result = compileTaskflow(def);
|
|
471
|
+
const v = result.verification;
|
|
472
|
+
const { errorCount, warningCount, text } = issueBlocks(v.issues, val.errors, val.warnings);
|
|
473
|
+
const passed = val.ok && v.ok && errorCount === 0;
|
|
474
|
+
const status = passed ? "✓ PASS" : "✗ FAIL";
|
|
475
|
+
const caption = `${def.name ?? "taskflow"} — ${count(def.phases?.length ?? 0, "phase")} · ${count(errorCount, "error")} · ${count(warningCount, "warning")} · ${status}`;
|
|
476
|
+
// A text outline that stands on its own — the CLI/TUI can't render images
|
|
477
|
+
// (it shows a bare `<image content>` placeholder), and a vision-less model
|
|
478
|
+
// would otherwise see nothing. Includes the layered DAG + deduped issues.
|
|
479
|
+
const outline = renderFlowOutline(def, v);
|
|
480
|
+
const textReport = `${caption}\n\n${outline}${text}`;
|
|
481
|
+
// Fold validation errors into the issue set the SVG colors by, so node
|
|
482
|
+
// coloring matches the text report (a phase with only a validation error
|
|
483
|
+
// still shows red). Validation messages start with `Phase '<id>':`.
|
|
484
|
+
const mergedVerification = {
|
|
485
|
+
...v,
|
|
486
|
+
ok: passed,
|
|
487
|
+
issues: [
|
|
488
|
+
...v.issues,
|
|
489
|
+
...val.errors.map((message) => {
|
|
490
|
+
const m = /^Phase '([^']+)'/.exec(message);
|
|
491
|
+
return { phaseId: m?.[1], message, severity: "error", category: "ref-integrity" };
|
|
492
|
+
}),
|
|
493
|
+
],
|
|
494
|
+
};
|
|
495
|
+
// Desktop app: the SVG image renders as a real diagram; the outline rides
|
|
496
|
+
// along as its caption/fallback. Oversized graphs skip the image and rely
|
|
497
|
+
// on the text report alone.
|
|
498
|
+
const svg = renderFlowSvg(def, mergedVerification);
|
|
499
|
+
if (svg)
|
|
500
|
+
return imageContent(svgToBase64(svg), "image/svg+xml", [textReport], !passed);
|
|
501
|
+
return textContent(textReport, !passed);
|
|
502
|
+
},
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
/** Build the full MCP method dispatch table (protocol + tools). */
|
|
506
|
+
export function makeMcpHandlers(cwd, runner) {
|
|
507
|
+
const tools = makeToolHandlers(cwd, runner);
|
|
508
|
+
let initialized = false;
|
|
509
|
+
return {
|
|
510
|
+
initialize: () => {
|
|
511
|
+
initialized = true;
|
|
512
|
+
return {
|
|
513
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
514
|
+
capabilities: { tools: { listChanged: false } },
|
|
515
|
+
serverInfo: SERVER_INFO,
|
|
516
|
+
};
|
|
517
|
+
},
|
|
518
|
+
// Client tells us it's ready — notification, no response.
|
|
519
|
+
"notifications/initialized": () => {
|
|
520
|
+
initialized = true;
|
|
521
|
+
},
|
|
522
|
+
ping: () => ({}),
|
|
523
|
+
"tools/list": () => ({ tools: TOOLS }),
|
|
524
|
+
"tools/call": async (params) => {
|
|
525
|
+
const p = (params ?? {});
|
|
526
|
+
const tool = tools[p.name ?? ""];
|
|
527
|
+
if (!tool)
|
|
528
|
+
throw new RpcError(RPC.INVALID_PARAMS, `Unknown tool: ${p.name}`);
|
|
529
|
+
void initialized; // tolerant: we don't hard-gate on initialize ordering
|
|
530
|
+
return await tool(p.arguments ?? {});
|
|
531
|
+
},
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
/** Start the stdio MCP server. Resolves when the client disconnects. */
|
|
535
|
+
export function startMcpServer(runner, cwd = process.cwd()) {
|
|
536
|
+
return serveStdio(makeMcpHandlers(cwd, runner));
|
|
537
|
+
}
|
|
538
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAmB,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACzE,OAAO,EACN,cAAc,EACd,eAAe,EACf,OAAO,EACP,SAAS,EACT,QAAQ,EACR,OAAO,EACP,OAAO,EACP,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,cAAc,EACd,OAAO,EACP,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,UAAU,EACV,aAAa,GAOb,MAAM,eAAe,CAAC;AAGvB,MAAM,gBAAgB,GAAG,YAAY,CAAC;AACtC,MAAM,WAAW,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAW,CAAC;AAUvF;;;;;;;;;;;GAWG;AACH,SAAS,WAAW,CAAC,IAAY,EAAE,OAAO,GAAG,KAAK;IACjD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;AACvD,CAAC;AAED;;;;gFAIgF;AAChF,SAAS,YAAY,CAAC,MAAc,EAAE,QAAgB,EAAE,KAAe,EAAE,OAAO,GAAG,KAAK;IACvF,MAAM,OAAO,GAAmC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5F,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,IAAI,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;IACtE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,IAAc;IACrC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC3C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACnD,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAC3B,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACpB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,CAAC;QACD,IAAI,EAAE;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACxB,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QAC7B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,GAAG,CAAC;QACjC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,GAAG,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACxD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,OAAO,GAAG,GAAG,KAAK,GAAG,CAAC,MAAM,YAAY,KAAK,GAAG,IAAI,GAAG,CAAC;IACzD,CAAC,CAAC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CACnB,MAA2B,EAC3B,cAAwB,EAAE,EAC1B,gBAA0B,EAAE;IAE5B,MAAM,KAAK,GAAG,CAAC,CAAoB,EAAE,EAAE;IACtC,0EAA0E;IAC1E,0EAA0E;IAC1E,8EAA8E;IAC9E,CAAC,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC7F,MAAM,SAAS,GAAG,CAAC,GAAG,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/F,MAAM,WAAW,GAAG,CAAC,GAAG,aAAa,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACrG,8EAA8E;IAC9E,uEAAuE;IACvE,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/F,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtG,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,GAAG,SAAS,EAAE,EAAE,CAAC;AAC5G,CAAC;AAED,mDAAmD;AACnD,SAAS,KAAK,CAAC,CAAS,EAAE,IAAY;IACrC,OAAO,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AAC5C,CAAC;AAED,MAAM,KAAK,GAAc;IACxB;QACC,IAAI,EAAE,cAAc;QACpB,KAAK,EAAE,gBAAgB;QACvB,WAAW,EACV,waAAwa;QACza,WAAW,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,oBAAoB,EAAE,KAAK;YAC3B,UAAU,EAAE;gBACX,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8BAA8B,EAAE;gBACrE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iDAAiD,EAAE;gBAC1F,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,2RAA2R,EAAE;gBACxU,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gDAAgD,EAAE;gBACvF,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,+CAA+C,EAAE;gBAC9F,gBAAgB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,2KAA2K,EAAE;aAC/N;SACD;KACD;IACD;QACC,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,kGAAkG;QAC/G,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE;KAC5E;IACD;QACC,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE,8CAA8C;QAC3D,WAAW,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,oBAAoB,EAAE,KAAK;YAC3B,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE,EAAE;YAChF,QAAQ,EAAE,CAAC,MAAM,CAAC;SAClB;KACD;IACD;QACC,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EAAE,qIAAqI;QAClJ,WAAW,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,oBAAoB,EAAE,KAAK;YAC3B,UAAU,EAAE;gBACX,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACxB,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC1B,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6EAA6E,EAAE;aAC1H;SACD;KACD;IACD;QACC,IAAI,EAAE,kBAAkB;QACxB,KAAK,EAAE,iCAAiC;QACxC,WAAW,EAAE,2MAA2M;QACxN,WAAW,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,oBAAoB,EAAE,KAAK;YAC3B,UAAU,EAAE;gBACX,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACxB,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC1B,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6EAA6E,EAAE;aAC1H;SACD;KACD;IACD;QACC,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,8BAA8B;QACrC,WAAW,EACV,sQAAsQ;QACvQ,WAAW,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,oBAAoB,EAAE,KAAK;YAC3B,UAAU,EAAE;gBACX,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mEAAmE,EAAE;gBAC3G,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sEAAsE,EAAE;gBAChH,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,4DAA4D,EAAE;gBACpG,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+DAA+D,EAAE;gBACtG,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oDAAoD,EAAE;aAC5F;YACD,QAAQ,EAAE,CAAC,OAAO,CAAC;SACnB;KACD;IACD;QACC,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,0BAA0B;QACjC,WAAW,EACV,gUAAgU;QACjU,WAAW,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,oBAAoB,EAAE,KAAK;YAC3B,UAAU,EAAE;gBACX,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,qCAAqC,EAAE;gBAC5E,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wFAAwF,EAAE;gBACrI,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oHAAoH,EAAE;gBAC9J,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,4DAA4D,EAAE;gBAC7H,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kEAAkE,EAAE;gBAC1G,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,mCAAmC,EAAE;aACtG;YACD,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC;SAChC;KACD;IACD;QACC,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,6BAA6B;QACpC,WAAW,EACV,wWAAwW;QACzW,WAAW,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,oBAAoB,EAAE,KAAK;YAC3B,UAAU,EAAE;gBACX,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iEAAiE,EAAE;gBACzG,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kCAAkC,EAAE;gBAC1E,aAAa,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,qEAAqE,EAAE;gBACtH,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sCAAsC,EAAE;gBACjF,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,uDAAuD,EAAE;aAClI;YACD,QAAQ,EAAE,CAAC,OAAO,CAAC;SACnB;KACD;CACD,CAAC;AAEF,qGAAqG;AACrG,SAAS,WAAW,CAAC,GAAW,EAAE,MAAiE;IAClG,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;QACtG,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACnD,IAAI,QAAQ,KAAK,IAAI;YAAE,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,wCAAwC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QAC3H,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC1C,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC3D,OAAO,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,MAAM,CAAC,MAAmB,CAAC;IAC1F,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,wBAAwB,MAAM,CAAC,IAAI,gBAAgB,GAAG,GAAG,CAAC,CAAC;QAC9G,OAAO,KAAK,CAAC,GAAG,CAAC;IAClB,CAAC;IACD,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,oEAAoE,CAAC,CAAC;AAC9G,CAAC;AAED,SAAS,UAAU,CAAC,GAAa,EAAE,IAA6B,EAAE,GAAW;IAC5E,OAAO;QACN,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC;QACnC,QAAQ,EAAE,GAAG,CAAC,IAAI,IAAI,MAAM;QAC5B,GAAG;QACH,IAAI;QACJ,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,EAAE;QACV,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,GAAG;KACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC/B,GAAW,EACX,MAAmC;IAEnC,OAAO;QACN,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC5B,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACnC,MAAM,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAChC,IAAI,CAAC,CAAC,CAAC,EAAE;gBAAE,OAAO,WAAW,CAAC,uBAAuB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YAEpF,yEAAyE;YACzE,2EAA2E;YAC3E,yEAAyE;YACzE,2CAA2C;YAC3C,MAAM,QAAQ,GAAG,oBAAoB,EAAE,CAAC;YACxC,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACvF,MAAM,IAAI,GAAgB;gBACzB,GAAG;gBACH,MAAM;gBACN,OAAO,EAAE,MAAM,CAAC,OAAO;aACvB,CAAC;YACF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAG,IAAI,CAAC,IAAgC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;YACjF,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;gBAAG,IAAqD,CAAC,iBAAiB,GAAG,WAAW,CAAC;YAEtH,2EAA2E;YAC3E,8EAA8E;YAC9E,MAAM,aAAa,GAAG,EAAE,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,oBAAoB,EAAE,CAAC;YACvF,IAAI,WAAW,GAAG,CAAC,CAAC;YACpB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,EAAE;gBACpB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACvB,IAAI,GAAG,GAAG,WAAW,IAAI,IAAI,EAAE,CAAC;oBAC/B,WAAW,GAAG,GAAG,CAAC;oBAClB,OAAO,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;gBAC3B,CAAC;YACF,CAAC,CAAC;YAEF,MAAM,GAAG,GAAG,MAAM,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;gBAC3D,yEAAyE;gBACzE,0DAA0D;gBAC1D,IAAI,CAAC;oBACJ,OAAO,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;gBAC/B,CAAC;gBAAC,MAAM,CAAC;oBACR,eAAe;gBAChB,CAAC;YACF,CAAC,CAAC,CAAC;YACH,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,gBAAgB,KAAK,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBACnG,IAAI,CAAC;oBACJ,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;gBACpC,CAAC;gBAAC,MAAM,CAAC;oBACR,iDAAiD;gBAClD,CAAC;YACF,CAAC;YACD,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,kCAAkC,CAAC;YACnF,MAAM,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC;YACzB,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,MAAM,iBAAiB,KAAK,CAAC,KAAK,EAAE,CAAC;YACzG,OAAO,WAAW,CAAC,GAAG,MAAM,OAAO,GAAG,CAAC,WAAW,GAAG,SAAS,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5E,CAAC;QAED,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;YACvC,IAAI,CAAC,KAAK;gBAAE,OAAO,WAAW,CAAC,iCAAiC,EAAE,IAAI,CAAC,CAAC;YACxE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE;gBAC/B,OAAO,EAAE,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;gBACpE,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,IAAI;gBACxB,IAAI,EAAE,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;gBAC3D,KAAK,EAAE,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;aAC9D,CAAC,CAAC;YACH,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvC,CAAC;QAED,aAAa,EAAE,KAAK,IAAI,EAAE;YACzB,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;YAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,WAAW,CAAC,+CAA+C,CAAC,CAAC;YAC5F,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC7B,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;gBACnC,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC;oBACnB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;oBAC1F,OAAO,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,eAAe,OAAO,QAAQ,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,WAAW,IAAI,CAAC,UAAU,IAAI,CAAC,GAAG,CAAC;gBAC5J,CAAC;gBACD,OAAO,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,WAAW,CAAC;YACrE,CAAC,CAAC,CAAC;YACH,OAAO,WAAW,CAAC,qBAAqB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;QAED,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YACrC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACjC,IAAI,CAAC,KAAK;gBAAE,OAAO,WAAW,CAAC,wBAAwB,IAAI,IAAI,EAAE,IAAI,CAAC,CAAC;YACvE,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACjC,IAAI,IAAI,EAAE,CAAC;gBACV,MAAM,GAAG,GAAG,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;gBACpO,OAAO,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAClD,CAAC;YACD,4EAA4E;YAC5E,2EAA2E;YAC3E,OAAO,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACxD,CAAC;QAED,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YACrC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;gBAAE,OAAO,WAAW,CAAC,gCAAgC,EAAE,IAAI,CAAC,CAAC;YAC7E,IAAI,CAAC,IAAI,CAAC,UAAU;gBAAE,OAAO,WAAW,CAAC,oEAAoE,EAAE,IAAI,CAAC,CAAC;YACrH,8EAA8E;YAC9E,IAAI,GAAa,CAAC;YAClB,IAAI,CAAC;gBACJ,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YACrD,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACZ,OAAO,WAAW,CAAC,4BAA4B,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACpG,CAAC;YACD,mFAAmF;YACnF,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAChC,IAAI,CAAC,CAAC,CAAC,EAAE;gBAAE,OAAO,WAAW,CAAC,uBAAuB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACpF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;YACzD,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,SAAS,CAAC;YAClD,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,OAAO,EAAE,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;gBACpE,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS;gBACxG,KAAK,EAAE,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;gBAC9D,QAAQ;aACR,CAAC,CAAC;YACH,MAAM,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YAC7D,OAAO,WAAW,CAAC,mBAAmB,IAAI,OAAO,QAAQ,gBAAgB,IAAI,CAAC,OAAO,IAAI,QAAQ,aAAa,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,uBAAuB,IAAI,CAAC,cAAc,mBAAmB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAClP,CAAC;QAED,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC9C,IAAI,CAAC,KAAK;gBAAE,OAAO,WAAW,CAAC,mCAAmC,EAAE,IAAI,CAAC,CAAC;YAC1E,MAAM,QAAQ,GAAG,oBAAoB,EAAE,CAAC;YACxC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBACxC,OAAO,WAAW,CAAC,yEAAyE,EAAE,IAAI,CAAC,CAAC;YACrG,CAAC;YACD,MAAM,IAAI,GAAgB,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC;YACvE,MAAM,KAAK,GAAgB;gBAC1B,KAAK;gBACL,KAAK,EAAE,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;gBAC9D,aAAa,EAAE,IAAI,CAAC,aAAa,KAAK,IAAI;gBAC1C,QAAQ,EAAE,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;gBACvE,KAAK,EAAE,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;aAC1G,CAAC;YACF,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC7C,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,MAAM,CAAC,OAAO,sBAAsB,GAAG,CAAC,UAAU,QAAQ,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACzI,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,KAAK,CAAC,IAAI,CAAC,4FAA4F,CAAC,CAAC;YAC1G,CAAC;iBAAM,CAAC;gBACP,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;oBAC7B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,cAAc,IAAI,GAAG,QAAQ,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,WAAW,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC;oBACzK,IAAI,CAAC,CAAC,OAAO;wBAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;oBACvD,IAAI,CAAC,CAAC,IAAI,EAAE,MAAM;wBAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBACjE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;oBAChC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;gBACpC,CAAC;YACF,CAAC;YACD,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;QAED,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC/B,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACnC,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAClC,sEAAsE;YACtE,yEAAyE;YACzE,wEAAwE;YACxE,0DAA0D;YAC1D,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAE,GAA4B,CAAC,MAAM,CAAC,CAAC;YAC3E,MAAM,MAAM,GAAG,cAAc;gBAC5B,CAAC,CAAC,cAAc,CAAC,GAA2C,CAAC;gBAC7D,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAiD,EAAE,CAAC;YAC5E,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;YAChG,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,IAAI,MAAM,CAAC,EAAE,IAAI,UAAU,KAAK,CAAC,CAAC;YACvD,4EAA4E;YAC5E,mCAAmC;YACnC,MAAM,IAAI,GAAG,MAAM;gBAClB,CAAC,CAAC,YAAY;oBACb,CAAC,CAAC,2BAA2B,KAAK,CAAC,YAAY,EAAE,SAAS,CAAC,EAAE;oBAC7D,CAAC,CAAC,uBAAuB;gBAC1B,CAAC,CAAC,2BAA2B,KAAK,CAAC,UAAU,EAAE,OAAO,CAAC,KAAK,KAAK,CAAC,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC;YAC9F,OAAO,WAAW,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;QAC/C,CAAC;QAED,gBAAgB,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAChC,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACnC,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAClC,2EAA2E;YAC3E,yEAAyE;YACzE,4EAA4E;YAC5E,wEAAwE;YACxE,6DAA6D;YAC7D,MAAM,MAAM,GAAI,GAA4B,CAAC,MAAM,CAAC;YACpD,MAAM,UAAU,GACf,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,OAAQ,CAAsB,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;YAC3G,IAAI,CAAC,UAAU,EAAE,CAAC;gBACjB,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,EAAE,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACrF,MAAM,OAAO,GAAG,GAAG,GAAG,CAAC,IAAI,IAAI,UAAU,MAAM,KAAK,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,YAAY,EAAE,SAAS,CAAC,WAAW,CAAC;gBACzH,OAAO,WAAW,CAAC,GAAG,OAAO,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;YAC/C,CAAC;YACD,yEAAyE;YACzE,mEAAmE;YACnE,4EAA4E;YAC5E,wEAAwE;YACxE,4EAA4E;YAC5E,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;YACpC,MAAM,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC;YAC9B,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC3F,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,UAAU,KAAK,CAAC,CAAC;YAClD,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC5C,MAAM,OAAO,GAAG,GAAG,GAAG,CAAC,IAAI,IAAI,UAAU,MAAM,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,YAAY,EAAE,SAAS,CAAC,MAAM,MAAM,EAAE,CAAC;YACzK,0EAA0E;YAC1E,2EAA2E;YAC3E,0EAA0E;YAC1E,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC1C,MAAM,UAAU,GAAG,GAAG,OAAO,OAAO,OAAO,GAAG,IAAI,EAAE,CAAC;YACrD,uEAAuE;YACvE,yEAAyE;YACzE,oEAAoE;YACpE,MAAM,kBAAkB,GAAG;gBAC1B,GAAG,CAAC;gBACJ,EAAE,EAAE,MAAM;gBACV,MAAM,EAAE;oBACP,GAAG,CAAC,CAAC,MAAM;oBACX,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;wBAC7B,MAAM,CAAC,GAAG,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;wBAC3C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAgB,EAAE,QAAQ,EAAE,eAAwB,EAAE,CAAC;oBACrG,CAAC,CAAC;iBACF;aACD,CAAC;YACF,0EAA0E;YAC1E,0EAA0E;YAC1E,4BAA4B;YAC5B,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;YACnD,IAAI,GAAG;gBAAE,OAAO,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,eAAe,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;YACvF,OAAO,WAAW,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;KACD,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,MAAmC;IAC/E,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC5C,IAAI,WAAW,GAAG,KAAK,CAAC;IAExB,OAAO;QACN,UAAU,EAAE,GAAG,EAAE;YAChB,WAAW,GAAG,IAAI,CAAC;YACnB,OAAO;gBACN,eAAe,EAAE,gBAAgB;gBACjC,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE;gBAC/C,UAAU,EAAE,WAAW;aACvB,CAAC;QACH,CAAC;QACD,0DAA0D;QAC1D,2BAA2B,EAAE,GAAG,EAAE;YACjC,WAAW,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;QAChB,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QACtC,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAC9B,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAA2D,CAAC;YACnF,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YACjC,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7E,KAAK,WAAW,CAAC,CAAC,sDAAsD;YACxE,OAAO,MAAM,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;KACD,CAAC;AACH,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,cAAc,CAAC,MAAmC,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IAC9F,OAAO,UAAU,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render a taskflow DAG for the Codex hosts, in two forms:
|
|
3
|
+
*
|
|
4
|
+
* - `renderFlowSvg` — a self-contained SVG "card" for the Codex **desktop
|
|
5
|
+
* app**, which renders an MCP `image` content block
|
|
6
|
+
* as `<img src="data:…">` in Chromium (an inline SVG
|
|
7
|
+
* data URI shows as an actual diagram).
|
|
8
|
+
* - `renderFlowOutline` — a compact monospace ASCII outline for the Codex
|
|
9
|
+
* **CLI/TUI**, which cannot render images: the Rust
|
|
10
|
+
* binary substitutes a bare `<image content>`
|
|
11
|
+
* placeholder for image blocks, so a picture is
|
|
12
|
+
* useless there (and a vision-less model would see
|
|
13
|
+
* only that placeholder). The outline is plain text
|
|
14
|
+
* that reads in the terminal AND feeds the model.
|
|
15
|
+
*
|
|
16
|
+
* We can't tell the two hosts apart from inside the server (every Codex
|
|
17
|
+
* frontend connects with the same MCP client id, `codex-mcp-client`), so
|
|
18
|
+
* `taskflow_compile` returns BOTH blocks: the desktop app shows the image and
|
|
19
|
+
* ignores the trailing text, while the CLI/TUI shows the text and renders the
|
|
20
|
+
* image as a harmless placeholder. One payload, correct on every host. Claude
|
|
21
|
+
* Code behaves like the CLI case: the text outline is what the model reads.
|
|
22
|
+
*
|
|
23
|
+
* This is MCP presentation shared by every MCP host adapter (codex, claude),
|
|
24
|
+
* so it lives in core next to the MCP server — core keeps its portable
|
|
25
|
+
* Mermaid/markdown artifact (`compileTaskflow`) and its zero-runtime-deps
|
|
26
|
+
* guarantee. Both renderers reuse core's exported `topoLayers` (layout)
|
|
27
|
+
* and `dependenciesOf` (edges) so they share the engine's exact DAG semantics.
|
|
28
|
+
* Pure functions, no I/O.
|
|
29
|
+
*/
|
|
30
|
+
import { type Taskflow, type VerificationResult } from "taskflow-core";
|
|
31
|
+
/** Above this phase count the card stops being legible once scaled — the caller
|
|
32
|
+
* should fall back to the text report instead of embedding a postage stamp. */
|
|
33
|
+
export declare const SVG_PHASE_LIMIT = 60;
|
|
34
|
+
/**
|
|
35
|
+
* Render `flow` (annotated with `verification`) as an SVG string. Layered
|
|
36
|
+
* top-down using core's `topoLayers`; edges follow `dependenciesOf`. Returns a
|
|
37
|
+
* complete `<svg …>…</svg>` document (no XML prolog — it's inlined as a data
|
|
38
|
+
* URI). Returns `null` when the flow is too large to render legibly.
|
|
39
|
+
*/
|
|
40
|
+
export declare function renderFlowSvg(flow: Taskflow, verification: VerificationResult): string | null;
|
|
41
|
+
/** Base64 of an SVG string, for an MCP `image` content block (`image/svg+xml`). */
|
|
42
|
+
export declare function svgToBase64(svg: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Render the DAG as a compact monospace outline: one line per phase, grouped by
|
|
45
|
+
* topological layer (phases in the same layer run concurrently), each showing
|
|
46
|
+
* its id, type tag, agent, and upstream deps. This is the CLI/TUI counterpart
|
|
47
|
+
* to `renderFlowSvg` — it degrades to readable text where images can't render,
|
|
48
|
+
* and (unlike an image placeholder) still tells a vision-less model the shape
|
|
49
|
+
* of the graph. Deterministic; issue markers mirror the SVG overlay.
|
|
50
|
+
*/
|
|
51
|
+
export declare function renderFlowOutline(flow: Taskflow, verification: VerificationResult): string;
|
|
52
|
+
//# sourceMappingURL=svg.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svg.d.ts","sourceRoot":"","sources":["../../src/mcp/svg.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAMN,KAAK,QAAQ,EACb,KAAK,kBAAkB,EAEvB,MAAM,eAAe,CAAC;AAmBvB;gFACgF;AAChF,eAAO,MAAM,eAAe,KAAK,CAAC;AAqHlC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,kBAAkB,GAAG,MAAM,GAAG,IAAI,CA2H7F;AAED,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAYD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,kBAAkB,GAAG,MAAM,CA0B1F"}
|