prolog-trace-viz 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -0
- package/dist/analyzer.d.ts +64 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +903 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/build-info.d.ts +15 -0
- package/dist/build-info.d.ts.map +1 -0
- package/dist/build-info.js +26 -0
- package/dist/build-info.js.map +1 -0
- package/dist/clauses.d.ts +15 -0
- package/dist/clauses.d.ts.map +1 -0
- package/dist/clauses.js +80 -0
- package/dist/clauses.js.map +1 -0
- package/dist/cli.d.ts +34 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +162 -0
- package/dist/cli.js.map +1 -0
- package/dist/errors.d.ts +19 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +66 -0
- package/dist/errors.js.map +1 -0
- package/dist/executor.d.ts +25 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.js +115 -0
- package/dist/executor.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +128 -0
- package/dist/index.js.map +1 -0
- package/dist/mermaid.d.ts +47 -0
- package/dist/mermaid.d.ts.map +1 -0
- package/dist/mermaid.js +197 -0
- package/dist/mermaid.js.map +1 -0
- package/dist/output.d.ts +24 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +40 -0
- package/dist/output.js.map +1 -0
- package/dist/parser.d.ts +84 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +1007 -0
- package/dist/parser.js.map +1 -0
- package/dist/prolog-parser.d.ts +2 -0
- package/dist/prolog-parser.d.ts.map +1 -0
- package/dist/prolog-parser.js +2 -0
- package/dist/prolog-parser.js.map +1 -0
- package/dist/renderer.d.ts +33 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +131 -0
- package/dist/renderer.js.map +1 -0
- package/dist/wrapper.d.ts +30 -0
- package/dist/wrapper.d.ts.map +1 -0
- package/dist/wrapper.js +87 -0
- package/dist/wrapper.js.map +1 -0
- package/package.json +55 -0
- package/scripts/generate-build-info.js +63 -0
- package/scripts/release.js +151 -0
- package/tracer.pl +202 -0
package/dist/executor.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { createError, ErrorCode } from './errors.js';
|
|
5
|
+
/**
|
|
6
|
+
* Checks if SWI-Prolog is installed and gets its version.
|
|
7
|
+
*/
|
|
8
|
+
async function checkSwipl() {
|
|
9
|
+
return new Promise((resolve) => {
|
|
10
|
+
const proc = spawn('swipl', ['--version']);
|
|
11
|
+
let stdout = '';
|
|
12
|
+
proc.stdout.on('data', (data) => {
|
|
13
|
+
stdout += data.toString();
|
|
14
|
+
});
|
|
15
|
+
proc.on('error', () => resolve({ installed: false }));
|
|
16
|
+
proc.on('close', (code) => {
|
|
17
|
+
if (code === 0) {
|
|
18
|
+
// Extract version from output like "SWI-Prolog version 8.4.3"
|
|
19
|
+
const versionMatch = stdout.match(/version\s+(\d+\.\d+\.\d+)/i);
|
|
20
|
+
resolve({
|
|
21
|
+
installed: true,
|
|
22
|
+
version: versionMatch ? versionMatch[1] : undefined
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
resolve({ installed: false });
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Checks if SWI-Prolog version is >= 7.0 (required for prolog_trace_interception/4).
|
|
33
|
+
*/
|
|
34
|
+
function checkSwiplVersion(version) {
|
|
35
|
+
const parts = version.split('.').map(Number);
|
|
36
|
+
const major = parts[0] || 0;
|
|
37
|
+
return major >= 7;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Checks all required dependencies.
|
|
41
|
+
*/
|
|
42
|
+
export async function checkDependencies() {
|
|
43
|
+
const { installed, version } = await checkSwipl();
|
|
44
|
+
if (!installed) {
|
|
45
|
+
return {
|
|
46
|
+
swiplInstalled: false,
|
|
47
|
+
error: createError(ErrorCode.PROLOG_NOT_INSTALLED),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (version && !checkSwiplVersion(version)) {
|
|
51
|
+
return {
|
|
52
|
+
swiplInstalled: true,
|
|
53
|
+
swiplVersion: version,
|
|
54
|
+
error: createError(ErrorCode.PROLOG_VERSION_TOO_OLD, `SWI-Prolog version ${version} is too old. Version 7.0 or later is required for custom tracer support.`),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
swiplInstalled: true,
|
|
59
|
+
swiplVersion: version,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Executes the custom tracer with the given wrapper file and captures the JSON output.
|
|
64
|
+
*/
|
|
65
|
+
export async function executeTracer(wrapperPath) {
|
|
66
|
+
const wrapperDir = path.dirname(wrapperPath);
|
|
67
|
+
const jsonPath = path.join(wrapperDir, 'trace.json');
|
|
68
|
+
return new Promise((resolve, reject) => {
|
|
69
|
+
const proc = spawn('swipl', [wrapperPath], {
|
|
70
|
+
cwd: wrapperDir,
|
|
71
|
+
});
|
|
72
|
+
let stderr = '';
|
|
73
|
+
proc.stderr.on('data', (data) => {
|
|
74
|
+
stderr += data.toString();
|
|
75
|
+
});
|
|
76
|
+
proc.on('error', (err) => {
|
|
77
|
+
reject(createError(ErrorCode.PROLOG_NOT_INSTALLED, err.message));
|
|
78
|
+
});
|
|
79
|
+
proc.on('close', async (code) => {
|
|
80
|
+
if (code !== 0) {
|
|
81
|
+
resolve({
|
|
82
|
+
json: '',
|
|
83
|
+
exitCode: code ?? 1,
|
|
84
|
+
stderr,
|
|
85
|
+
});
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Read the generated trace.json file
|
|
89
|
+
try {
|
|
90
|
+
const json = await fs.readFile(jsonPath, 'utf-8');
|
|
91
|
+
resolve({
|
|
92
|
+
json,
|
|
93
|
+
exitCode: 0,
|
|
94
|
+
stderr,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
// trace.json file might not exist if tracer failed silently
|
|
99
|
+
resolve({
|
|
100
|
+
json: '',
|
|
101
|
+
exitCode: 0,
|
|
102
|
+
stderr: stderr || 'No JSON trace output generated',
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Legacy function for backward compatibility.
|
|
110
|
+
* @deprecated Use executeTracer instead.
|
|
111
|
+
*/
|
|
112
|
+
export async function executeSldnfdraw(wrapperPath) {
|
|
113
|
+
return executeTracer(wrapperPath);
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import { parseArgs, getHelpText, getVersion, getCopyright } from './cli.js';
|
|
4
|
+
import { formatError } from './errors.js';
|
|
5
|
+
import { createTempWrapper } from './wrapper.js';
|
|
6
|
+
import { executeTracer, checkDependencies } from './executor.js';
|
|
7
|
+
import { parseTraceJson } from './parser.js';
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
import { analyzeTree } from './analyzer.js';
|
|
10
|
+
import { generateMermaid } from './mermaid.js';
|
|
11
|
+
import { renderMarkdown } from './renderer.js';
|
|
12
|
+
import { writeOutput, logVerbose, logInfo, logError } from './output.js';
|
|
13
|
+
import { parsePrologFile } from './clauses.js';
|
|
14
|
+
async function main() {
|
|
15
|
+
const result = parseArgs(process.argv);
|
|
16
|
+
if (result.type === 'help') {
|
|
17
|
+
console.log(getHelpText());
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
if (result.type === 'version') {
|
|
21
|
+
console.log(getVersion());
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}
|
|
24
|
+
if (result.type === 'copyright') {
|
|
25
|
+
console.log(getCopyright());
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
if (result.type === 'error') {
|
|
29
|
+
logError(formatError(result.error));
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
const options = result.options;
|
|
33
|
+
try {
|
|
34
|
+
await run(options);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
logError(`Unexpected error: ${err instanceof Error ? err.message : String(err)}`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function run(options) {
|
|
42
|
+
logVerbose(`Processing ${options.prologFile} with query: ${options.query}`, options);
|
|
43
|
+
// Check dependencies
|
|
44
|
+
logVerbose('Checking dependencies...', options);
|
|
45
|
+
const deps = await checkDependencies();
|
|
46
|
+
if (deps.error) {
|
|
47
|
+
logError(formatError(deps.error));
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
// Read Prolog file
|
|
51
|
+
logVerbose(`Reading ${options.prologFile}...`, options);
|
|
52
|
+
let prologContent;
|
|
53
|
+
try {
|
|
54
|
+
prologContent = await fs.readFile(options.prologFile, 'utf-8');
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
const { createError, ErrorCode } = await import('./errors.js');
|
|
58
|
+
logError(formatError(createError(ErrorCode.FILE_NOT_FOUND, options.prologFile)));
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
// Parse Prolog clauses (for display purposes)
|
|
62
|
+
logVerbose('Parsing Prolog clauses...', options);
|
|
63
|
+
const clauses = parsePrologFile(prologContent);
|
|
64
|
+
// Get absolute path to tracer.pl from package installation
|
|
65
|
+
const tracerPath = path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', 'tracer.pl');
|
|
66
|
+
// Create wrapper (no instrumentation needed)
|
|
67
|
+
logVerbose('Creating tracer wrapper...', options);
|
|
68
|
+
const tempFile = await createTempWrapper({
|
|
69
|
+
prologContent,
|
|
70
|
+
query: options.query,
|
|
71
|
+
tracerPath,
|
|
72
|
+
});
|
|
73
|
+
try {
|
|
74
|
+
// Execute custom tracer
|
|
75
|
+
logVerbose('Executing custom tracer...', options);
|
|
76
|
+
const execResult = await executeTracer(tempFile.path);
|
|
77
|
+
if (execResult.exitCode !== 0 || !execResult.json) {
|
|
78
|
+
logError('Custom tracer execution failed');
|
|
79
|
+
if (execResult.stderr) {
|
|
80
|
+
logError(execResult.stderr);
|
|
81
|
+
}
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
// Determine output paths based on Prolog file location
|
|
85
|
+
const prologDir = options.prologFile.includes('/')
|
|
86
|
+
? options.prologFile.substring(0, options.prologFile.lastIndexOf('/'))
|
|
87
|
+
: '.';
|
|
88
|
+
const prologBasename = options.prologFile.includes('/')
|
|
89
|
+
? options.prologFile.substring(options.prologFile.lastIndexOf('/') + 1)
|
|
90
|
+
: options.prologFile;
|
|
91
|
+
const nameWithoutExt = prologBasename.replace(/\.pl$/, '');
|
|
92
|
+
// Parse JSON trace output
|
|
93
|
+
logVerbose('Parsing JSON trace output...', options);
|
|
94
|
+
const tree = parseTraceJson(execResult.json);
|
|
95
|
+
// Also parse raw events for clause extraction
|
|
96
|
+
const rawEvents = JSON.parse(execResult.json);
|
|
97
|
+
// Analyze tree
|
|
98
|
+
logVerbose('Analyzing execution tree...', options);
|
|
99
|
+
const analysis = analyzeTree(tree, clauses, { detailLevel: options.detail }, rawEvents);
|
|
100
|
+
// Generate Mermaid diagram
|
|
101
|
+
logVerbose('Generating Mermaid diagram...', options);
|
|
102
|
+
const diagram = generateMermaid(analysis);
|
|
103
|
+
// Render markdown
|
|
104
|
+
logVerbose('Rendering markdown...', options);
|
|
105
|
+
const markdown = renderMarkdown({
|
|
106
|
+
query: options.query,
|
|
107
|
+
diagram,
|
|
108
|
+
executionSteps: analysis.executionSteps,
|
|
109
|
+
finalAnswer: analysis.finalAnswer,
|
|
110
|
+
clausesUsed: analysis.clausesUsed,
|
|
111
|
+
});
|
|
112
|
+
// Write output - default to source file location if not specified
|
|
113
|
+
const outputPath = options.output || `${prologDir}/${nameWithoutExt}-output.md`;
|
|
114
|
+
await writeOutput({
|
|
115
|
+
content: markdown,
|
|
116
|
+
outputPath,
|
|
117
|
+
verbose: options.verbose,
|
|
118
|
+
quiet: options.quiet,
|
|
119
|
+
});
|
|
120
|
+
logInfo('Done!', options);
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
// Cleanup
|
|
124
|
+
await tempFile.cleanup();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
main();
|
|
128
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAc,MAAM,UAAU,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvC,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC;QAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC5B,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,KAAM,CAAC,CAAC,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,OAAQ,CAAC;IAEhC,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,QAAQ,CAAC,qBAAqB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,GAAG,CAAC,OAAmB;IACpC,UAAU,CAAC,cAAc,OAAO,CAAC,UAAU,gBAAgB,OAAO,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;IAErF,qBAAqB;IACrB,UAAU,CAAC,0BAA0B,EAAE,OAAO,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACvC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,mBAAmB;IACnB,UAAU,CAAC,WAAW,OAAO,CAAC,UAAU,KAAK,EAAE,OAAO,CAAC,CAAC;IACxD,IAAI,aAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,aAAa,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACjE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QAC/D,QAAQ,CAAC,WAAW,CAAC,WAAW,CAAC,SAAS,CAAC,cAAc,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,8CAA8C;IAC9C,UAAU,CAAC,2BAA2B,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC;IAE/C,2DAA2D;IAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;IAEpG,6CAA6C;IAC7C,UAAU,CAAC,4BAA4B,EAAE,OAAO,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC;QACvC,aAAa;QACb,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,UAAU;KACX,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,wBAAwB;QACxB,UAAU,CAAC,4BAA4B,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEtD,IAAI,UAAU,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;YAClD,QAAQ,CAAC,gCAAgC,CAAC,CAAC;YAC3C,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;gBACtB,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC9B,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,uDAAuD;QACvD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;YAChD,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YACtE,CAAC,CAAC,GAAG,CAAC;QACR,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;YACrD,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACvE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;QACvB,MAAM,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAE3D,0BAA0B;QAC1B,UAAU,CAAC,8BAA8B,EAAE,OAAO,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAE7C,8CAA8C;QAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAE9C,eAAe;QACf,UAAU,CAAC,6BAA6B,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,SAAS,CAAC,CAAC;QAExF,2BAA2B;QAC3B,UAAU,CAAC,+BAA+B,EAAE,OAAO,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QAE1C,kBAAkB;QAClB,UAAU,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,cAAc,CAAC;YAC9B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,OAAO;YACP,cAAc,EAAE,QAAQ,CAAC,cAAc;YACvC,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,WAAW,EAAE,QAAQ,CAAC,WAAW;SAClC,CAAC,CAAC;QAEH,kEAAkE;QAClE,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,IAAI,GAAG,SAAS,IAAI,cAAc,YAAY,CAAC;QAChF,MAAM,WAAW,CAAC;YAChB,OAAO,EAAE,QAAQ;YACjB,UAAU;YACV,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,CAAC;QAEH,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5B,CAAC;YAAS,CAAC;QACT,UAAU;QACV,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { AnalysisResult, VisualizationNode, VisualizationEdge } from './analyzer.js';
|
|
2
|
+
export interface MermaidDiagram {
|
|
3
|
+
nodes: string[];
|
|
4
|
+
edges: string[];
|
|
5
|
+
styles: string[];
|
|
6
|
+
linkStyles: string[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Generates a complete Mermaid diagram from analysis results.
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateMermaid(analysis: AnalysisResult): string;
|
|
12
|
+
/**
|
|
13
|
+
* Formats a node for Mermaid syntax.
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatNode(node: VisualizationNode): string;
|
|
16
|
+
/**
|
|
17
|
+
* Formats an edge for Mermaid syntax.
|
|
18
|
+
*/
|
|
19
|
+
export declare function formatEdge(edge: VisualizationEdge): string;
|
|
20
|
+
/**
|
|
21
|
+
* Gets a circled number for step numbering.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getCircledNumber(n: number): string;
|
|
24
|
+
/**
|
|
25
|
+
* Generates style directive for a node.
|
|
26
|
+
*/
|
|
27
|
+
export declare function generateNodeStyle(node: VisualizationNode): string;
|
|
28
|
+
/**
|
|
29
|
+
* Generates styles for all node types (for legend).
|
|
30
|
+
*/
|
|
31
|
+
export declare function generateStyles(nodes: VisualizationNode[]): string[];
|
|
32
|
+
/**
|
|
33
|
+
* Checks if a diagram contains all required node types for a given analysis.
|
|
34
|
+
*/
|
|
35
|
+
export declare function hasRequiredNodeTypes(analysis: AnalysisResult): {
|
|
36
|
+
hasQuery: boolean;
|
|
37
|
+
hasSuccess: boolean;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Validates that step numbers are sequential with no gaps.
|
|
41
|
+
*/
|
|
42
|
+
export declare function validateStepNumbers(edges: VisualizationEdge[]): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Checks if all edges with clause matches have proper labels.
|
|
45
|
+
*/
|
|
46
|
+
export declare function edgesHaveClauseInfo(edges: VisualizationEdge[]): boolean;
|
|
47
|
+
//# sourceMappingURL=mermaid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mermaid.d.ts","sourceRoot":"","sources":["../src/mermaid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAErF,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AA2BD;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAkBhE;AA6CD;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAsB1D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAc1D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAUjE;AAgBD;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,MAAM,EAAE,CAEnE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,cAAc,GAAG;IAC9D,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;CACrB,CAMA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAUvE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAMvE"}
|
package/dist/mermaid.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// Circled numbers for step numbering
|
|
2
|
+
const CIRCLED_NUMBERS = ['①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩',
|
|
3
|
+
'⑪', '⑫', '⑬', '⑭', '⑮', '⑯', '⑰', '⑱', '⑲', '⑳'];
|
|
4
|
+
// Color scheme - matching the steering guide
|
|
5
|
+
const COLORS = {
|
|
6
|
+
query: '#e1f5ff', // Light blue
|
|
7
|
+
solving: '#fff9c4', // Light yellow
|
|
8
|
+
pending: '#e0e0e0', // Gray
|
|
9
|
+
solved: '#c8e6c9', // Light green
|
|
10
|
+
success: '#c8e6c9', // Light green
|
|
11
|
+
'clause-body': '#e1bee7', // Light purple
|
|
12
|
+
match: '#ffe0b2', // Light orange
|
|
13
|
+
};
|
|
14
|
+
const STROKES = {
|
|
15
|
+
query: '#01579b',
|
|
16
|
+
solving: '#f57f17',
|
|
17
|
+
pending: '#616161',
|
|
18
|
+
solved: '#388e3c',
|
|
19
|
+
success: '#2e7d32',
|
|
20
|
+
'clause-body': '#7b1fa2',
|
|
21
|
+
match: '#e65100',
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Generates a complete Mermaid diagram from analysis results.
|
|
25
|
+
*/
|
|
26
|
+
export function generateMermaid(analysis) {
|
|
27
|
+
const diagram = buildDiagram(analysis);
|
|
28
|
+
const lines = [
|
|
29
|
+
'graph TD',
|
|
30
|
+
'',
|
|
31
|
+
'%% Nodes',
|
|
32
|
+
...diagram.nodes,
|
|
33
|
+
'',
|
|
34
|
+
'%% Edges',
|
|
35
|
+
...diagram.edges,
|
|
36
|
+
'',
|
|
37
|
+
'%% Styles',
|
|
38
|
+
...diagram.styles,
|
|
39
|
+
...diagram.linkStyles,
|
|
40
|
+
];
|
|
41
|
+
return lines.join('\n');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Builds the diagram components.
|
|
45
|
+
*/
|
|
46
|
+
function buildDiagram(analysis) {
|
|
47
|
+
const nodes = [];
|
|
48
|
+
const edges = [];
|
|
49
|
+
const styles = [];
|
|
50
|
+
const linkStyles = [];
|
|
51
|
+
// Generate nodes
|
|
52
|
+
for (const node of analysis.nodes) {
|
|
53
|
+
nodes.push(formatNode(node));
|
|
54
|
+
styles.push(generateNodeStyle(node));
|
|
55
|
+
}
|
|
56
|
+
// Generate edges
|
|
57
|
+
const queueIndices = [];
|
|
58
|
+
const activateIndices = [];
|
|
59
|
+
for (let i = 0; i < analysis.edges.length; i++) {
|
|
60
|
+
const edge = analysis.edges[i];
|
|
61
|
+
edges.push(formatEdge(edge));
|
|
62
|
+
if (edge.type === 'queue') {
|
|
63
|
+
queueIndices.push(i);
|
|
64
|
+
}
|
|
65
|
+
else if (edge.type === 'activate') {
|
|
66
|
+
activateIndices.push(i);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Group queue edges together
|
|
70
|
+
if (queueIndices.length > 0) {
|
|
71
|
+
linkStyles.push(`linkStyle ${queueIndices.join(',')} stroke:#999,stroke-width:2px,stroke-dasharray:5`);
|
|
72
|
+
}
|
|
73
|
+
// Group activate edges together
|
|
74
|
+
if (activateIndices.length > 0) {
|
|
75
|
+
linkStyles.push(`linkStyle ${activateIndices.join(',')} stroke:#4caf50,stroke-width:3px`);
|
|
76
|
+
}
|
|
77
|
+
return { nodes, edges, styles, linkStyles };
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Formats a node for Mermaid syntax.
|
|
81
|
+
*/
|
|
82
|
+
export function formatNode(node) {
|
|
83
|
+
const label = `${node.emoji} ${node.label}`;
|
|
84
|
+
// Use different shapes based on type
|
|
85
|
+
switch (node.type) {
|
|
86
|
+
case 'query':
|
|
87
|
+
return `${node.id}[["${label}"]]`; // Stadium shape
|
|
88
|
+
case 'success':
|
|
89
|
+
return `${node.id}(("${label}"))`; // Circle
|
|
90
|
+
case 'pending':
|
|
91
|
+
return `${node.id}["${label}"]`; // Rectangle (same as solving)
|
|
92
|
+
case 'solving':
|
|
93
|
+
return `${node.id}["${label}"]`; // Rectangle
|
|
94
|
+
case 'solved':
|
|
95
|
+
return `${node.id}("${label}")`; // Rounded rectangle
|
|
96
|
+
case 'clause-body':
|
|
97
|
+
return `${node.id}[/"${label}"/]`; // Trapezoid shape
|
|
98
|
+
case 'match':
|
|
99
|
+
return `${node.id}["${label}"]`; // Rectangle
|
|
100
|
+
default:
|
|
101
|
+
return `${node.id}["${label}"]`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Formats an edge for Mermaid syntax.
|
|
106
|
+
*/
|
|
107
|
+
export function formatEdge(edge) {
|
|
108
|
+
const stepNum = getCircledNumber(edge.stepNumber);
|
|
109
|
+
const label = edge.label ? `${stepNum} ${edge.label}` : stepNum;
|
|
110
|
+
switch (edge.type) {
|
|
111
|
+
case 'active':
|
|
112
|
+
return `${edge.from} -->|"${label}"| ${edge.to}`;
|
|
113
|
+
case 'queue':
|
|
114
|
+
return `${edge.from} -.->|"${label}"| ${edge.to}`;
|
|
115
|
+
case 'activate':
|
|
116
|
+
return `${edge.from} ==>|"${label}"| ${edge.to}`;
|
|
117
|
+
default:
|
|
118
|
+
return `${edge.from} -->|"${label}"| ${edge.to}`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Gets a circled number for step numbering.
|
|
123
|
+
*/
|
|
124
|
+
export function getCircledNumber(n) {
|
|
125
|
+
if (n >= 1 && n <= CIRCLED_NUMBERS.length) {
|
|
126
|
+
return CIRCLED_NUMBERS[n - 1];
|
|
127
|
+
}
|
|
128
|
+
// Fallback for numbers > 20
|
|
129
|
+
return `(${n})`;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Generates style directive for a node.
|
|
133
|
+
*/
|
|
134
|
+
export function generateNodeStyle(node) {
|
|
135
|
+
const fill = COLORS[node.type];
|
|
136
|
+
const stroke = STROKES[node.type];
|
|
137
|
+
// Only query and success nodes have explicit stroke-width
|
|
138
|
+
if (node.type === 'query' || node.type === 'success') {
|
|
139
|
+
return `style ${node.id} fill:${fill},stroke:${stroke},stroke-width:3px`;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
return `style ${node.id} fill:${fill},stroke:${stroke}`;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Generates style for a link/edge.
|
|
147
|
+
*/
|
|
148
|
+
function generateLinkStyle(edge, index) {
|
|
149
|
+
switch (edge.type) {
|
|
150
|
+
case 'queue':
|
|
151
|
+
return `linkStyle ${index} stroke:#999,stroke-width:2px,stroke-dasharray:5`;
|
|
152
|
+
case 'activate':
|
|
153
|
+
return `linkStyle ${index} stroke:#4caf50,stroke-width:3px`;
|
|
154
|
+
default:
|
|
155
|
+
return `linkStyle ${index} stroke:#333`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Generates styles for all node types (for legend).
|
|
160
|
+
*/
|
|
161
|
+
export function generateStyles(nodes) {
|
|
162
|
+
return nodes.map(generateNodeStyle);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Checks if a diagram contains all required node types for a given analysis.
|
|
166
|
+
*/
|
|
167
|
+
export function hasRequiredNodeTypes(analysis) {
|
|
168
|
+
const types = new Set(analysis.nodes.map(n => n.type));
|
|
169
|
+
return {
|
|
170
|
+
hasQuery: types.has('query'),
|
|
171
|
+
hasSuccess: types.has('success'),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Validates that step numbers are sequential with no gaps.
|
|
176
|
+
*/
|
|
177
|
+
export function validateStepNumbers(edges) {
|
|
178
|
+
if (edges.length === 0)
|
|
179
|
+
return true;
|
|
180
|
+
const stepNumbers = edges.map(e => e.stepNumber).sort((a, b) => a - b);
|
|
181
|
+
for (let i = 0; i < stepNumbers.length; i++) {
|
|
182
|
+
if (stepNumbers[i] !== i + 1)
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Checks if all edges with clause matches have proper labels.
|
|
189
|
+
*/
|
|
190
|
+
export function edgesHaveClauseInfo(edges) {
|
|
191
|
+
// Edges that represent clause matches should have labels
|
|
192
|
+
return edges.every(edge => {
|
|
193
|
+
// All edges should at least have a step number
|
|
194
|
+
return edge.stepNumber > 0;
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=mermaid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mermaid.js","sourceRoot":"","sources":["../src/mermaid.ts"],"names":[],"mappings":"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"}
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CLIOptions } from './cli.js';
|
|
2
|
+
export interface OutputOptions {
|
|
3
|
+
content: string;
|
|
4
|
+
outputPath?: string;
|
|
5
|
+
verbose: boolean;
|
|
6
|
+
quiet: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Writes output to file or stdout based on CLI options.
|
|
10
|
+
*/
|
|
11
|
+
export declare function writeOutput(options: OutputOptions): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Logs verbose information if verbose mode is enabled.
|
|
14
|
+
*/
|
|
15
|
+
export declare function logVerbose(message: string, options: Pick<CLIOptions, 'verbose' | 'quiet'>): void;
|
|
16
|
+
/**
|
|
17
|
+
* Logs info messages unless quiet mode is enabled.
|
|
18
|
+
*/
|
|
19
|
+
export declare function logInfo(message: string, options: Pick<CLIOptions, 'quiet'>): void;
|
|
20
|
+
/**
|
|
21
|
+
* Logs error messages (always shown).
|
|
22
|
+
*/
|
|
23
|
+
export declare function logError(message: string): void;
|
|
24
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAavE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG,IAAI,CAIhG;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,IAAI,CAIjF;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE9C"}
|
package/dist/output.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
/**
|
|
3
|
+
* Writes output to file or stdout based on CLI options.
|
|
4
|
+
*/
|
|
5
|
+
export async function writeOutput(options) {
|
|
6
|
+
const { content, outputPath, verbose, quiet } = options;
|
|
7
|
+
if (outputPath) {
|
|
8
|
+
await fs.writeFile(outputPath, content, 'utf-8');
|
|
9
|
+
if (!quiet) {
|
|
10
|
+
console.log(`Output written to: ${outputPath}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
// Write to stdout
|
|
15
|
+
console.log(content);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Logs verbose information if verbose mode is enabled.
|
|
20
|
+
*/
|
|
21
|
+
export function logVerbose(message, options) {
|
|
22
|
+
if (options.verbose && !options.quiet) {
|
|
23
|
+
console.log(`[verbose] ${message}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Logs info messages unless quiet mode is enabled.
|
|
28
|
+
*/
|
|
29
|
+
export function logInfo(message, options) {
|
|
30
|
+
if (!options.quiet) {
|
|
31
|
+
console.log(message);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Logs error messages (always shown).
|
|
36
|
+
*/
|
|
37
|
+
export function logError(message) {
|
|
38
|
+
console.error(message);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAUvC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAsB;IACtD,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAExD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAEjD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,sBAAsB,UAAU,EAAE,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;SAAM,CAAC;QACN,kBAAkB;QAClB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,OAA8C;IACxF,IAAI,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,OAAe,EAAE,OAAkC;IACzE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACzB,CAAC"}
|