tribunal-kit 4.4.0 → 4.4.2
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/.agent/agents/api-architect.md +66 -66
- package/.agent/agents/db-latency-auditor.md +216 -216
- package/.agent/agents/precedence-reviewer.md +250 -250
- package/.agent/agents/resilience-reviewer.md +88 -88
- package/.agent/agents/schema-reviewer.md +67 -67
- package/.agent/agents/throughput-optimizer.md +299 -299
- package/.agent/agents/ui-ux-auditor.md +292 -292
- package/.agent/agents/vitals-reviewer.md +223 -223
- package/.agent/history/architecture-graph.yaml +32 -1
- package/.agent/history/graph-cache.json +66 -19
- package/.agent/history/snapshots/bin__tribunal-kit.js.json +19 -0
- package/.agent/history/snapshots/eslint.config.js.json +9 -0
- package/.agent/history/snapshots/migrate_refs.js.json +3 -3
- package/.agent/history/snapshots/scripts__changelog.js.json +2 -1
- package/.agent/history/snapshots/scripts__sync-version.js.json +2 -1
- package/.agent/history/snapshots/scripts__validate-payload.js.json +1 -0
- package/.agent/history/snapshots/test__integration__bridges.test.js.json +2 -1
- package/.agent/history/snapshots/test__integration__init.test.js.json +1 -0
- package/.agent/history/snapshots/test__integration__routing.test.js.json +1 -0
- package/.agent/history/snapshots/test__integration__swarm_dispatcher.test.js.json +2 -1
- package/.agent/history/snapshots/test__integration__wave2.test.js.json +2 -1
- package/.agent/history/snapshots/test__unit__args.test.js.json +11 -1
- package/.agent/history/snapshots/test__unit__case_law_manager.test.js.json +1 -0
- package/.agent/history/snapshots/test__unit__context_broker.test.js.json +11 -0
- package/.agent/history/snapshots/test__unit__copyDir.test.js.json +11 -1
- package/.agent/history/snapshots/test__unit__graph_tools.test.js.json +1 -0
- package/.agent/history/snapshots/test__unit__inner_loop_validator.test.js.json +11 -0
- package/.agent/history/snapshots/test__unit__selfInstall.test.js.json +11 -1
- package/.agent/history/snapshots/test__unit__semver.test.js.json +11 -1
- package/.agent/history/snapshots/test__unit__swarm_dispatcher.test.js.json +1 -0
- package/.agent/scripts/_colors.js +154 -2
- package/.agent/scripts/_utils.js +205 -3
- package/.agent/scripts/append_flow.js +72 -72
- package/.agent/scripts/auto_preview.js +197 -197
- package/.agent/scripts/bundle_analyzer.js +90 -119
- package/.agent/scripts/case_law_manager.js +18 -13
- package/.agent/scripts/checklist.js +100 -88
- package/.agent/scripts/colors.js +7 -13
- package/.agent/scripts/compress_skills.js +141 -141
- package/.agent/scripts/consolidate_skills.js +149 -149
- package/.agent/scripts/context_broker.js +605 -609
- package/.agent/scripts/deep_compress.js +150 -150
- package/.agent/scripts/dependency_analyzer.js +68 -106
- package/.agent/scripts/graph_builder.js +341 -311
- package/.agent/scripts/graph_visualizer.js +390 -384
- package/.agent/scripts/graph_zoom.js +6 -4
- package/.agent/scripts/inner_loop_validator.js +445 -465
- package/.agent/scripts/lint_runner.js +27 -28
- package/.agent/scripts/minify_context.js +100 -100
- package/.agent/scripts/mutation_runner.js +280 -280
- package/.agent/scripts/patch_skills_meta.js +156 -156
- package/.agent/scripts/patch_skills_output.js +244 -244
- package/.agent/scripts/schema_validator.js +280 -297
- package/.agent/scripts/security_scan.js +37 -64
- package/.agent/scripts/session_manager.js +270 -276
- package/.agent/scripts/skill_evolution.js +637 -644
- package/.agent/scripts/skill_integrator.js +307 -313
- package/.agent/scripts/strengthen_skills.js +193 -193
- package/.agent/scripts/strip_tribunal.js +47 -47
- package/.agent/scripts/swarm_dispatcher.js +360 -360
- package/.agent/scripts/test_runner.js +32 -39
- package/.agent/scripts/utils.js +10 -25
- package/.agent/scripts/verify_all.js +84 -92
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +1 -1
- package/.agent/skills/doc.md +1 -1
- package/.agent/skills/knowledge-graph/SKILL.md +52 -52
- package/.agent/skills/ui-ux-pro-max/SKILL.md +562 -562
- package/.agent/workflows/generate.md +183 -183
- package/.agent/workflows/tribunal-speed.md +183 -183
- package/README.md +1 -1
- package/bin/tribunal-kit.js +76 -87
- package/package.json +6 -3
- package/scripts/changelog.js +167 -167
- package/scripts/sync-version.js +81 -81
- package/.agent/history/architecture-explorer.html +0 -352
- package/.agent/scripts/__pycache__/_colors.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/_utils.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/case_law_manager.cpython-311.pyc +0 -0
|
@@ -14,25 +14,16 @@ const fs = require('fs');
|
|
|
14
14
|
const path = require('path');
|
|
15
15
|
const { spawnSync } = require('child_process');
|
|
16
16
|
|
|
17
|
-
const {
|
|
17
|
+
const {
|
|
18
|
+
RED, GREEN, YELLOW, BLUE, BOLD, DIM, CYAN, RESET,
|
|
19
|
+
banner, sectionHeader, summaryTable, timer, formatMs,
|
|
20
|
+
ok, fail, skip,
|
|
21
|
+
} = require('./_colors');
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
console.log(`\n${BOLD}${BLUE}━━━ ${title} ━━━${RESET}`);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function ok(msg) {
|
|
24
|
-
console.log(` ${GREEN}✅ ${msg}${RESET}`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function fail(msg) {
|
|
28
|
-
console.log(` ${RED}❌ ${msg}${RESET}`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function skip(msg) {
|
|
32
|
-
console.log(` ${YELLOW}⏭️ ${msg}${RESET}`);
|
|
33
|
-
}
|
|
23
|
+
const RESULTS = [];
|
|
34
24
|
|
|
35
25
|
function runLinter(label, cmd, cwd) {
|
|
26
|
+
const elapsed = timer();
|
|
36
27
|
try {
|
|
37
28
|
const executable = process.platform === 'win32' && cmd[0] === 'npx' ? 'npx.cmd' : cmd[0];
|
|
38
29
|
const result = spawnSync(executable, cmd.slice(1), {
|
|
@@ -42,12 +33,15 @@ function runLinter(label, cmd, cwd) {
|
|
|
42
33
|
shell: process.platform === 'win32'
|
|
43
34
|
});
|
|
44
35
|
|
|
36
|
+
const ms = elapsed();
|
|
45
37
|
if (result.status === 0) {
|
|
46
|
-
ok(`${label} — clean`);
|
|
38
|
+
ok(`${label} — clean ${DIM}(${formatMs(ms)})${RESET}`);
|
|
39
|
+
RESULTS.push({ name: label, status: 'pass', ms });
|
|
47
40
|
return true;
|
|
48
41
|
}
|
|
49
42
|
|
|
50
|
-
fail(`${label} — issues found`);
|
|
43
|
+
fail(`${label} — issues found ${DIM}(${formatMs(ms)})${RESET}`);
|
|
44
|
+
RESULTS.push({ name: label, status: 'fail', ms });
|
|
51
45
|
if (result.error) {
|
|
52
46
|
console.log(` Error: ${result.error.message}`);
|
|
53
47
|
}
|
|
@@ -66,6 +60,7 @@ function runLinter(label, cmd, cwd) {
|
|
|
66
60
|
return false;
|
|
67
61
|
} catch {
|
|
68
62
|
skip(`${label} — tool not installed`);
|
|
63
|
+
RESULTS.push({ name: label, status: 'skip' });
|
|
69
64
|
return true;
|
|
70
65
|
}
|
|
71
66
|
}
|
|
@@ -120,8 +115,7 @@ function main() {
|
|
|
120
115
|
process.exit(1);
|
|
121
116
|
}
|
|
122
117
|
|
|
123
|
-
console.log(
|
|
124
|
-
console.log(`Project: ${projectRoot}`);
|
|
118
|
+
console.log(banner('lint_runner.js', { Project: projectRoot, Mode: fixFlag ? 'fix' : 'check' }));
|
|
125
119
|
|
|
126
120
|
const available = detectLinters(projectRoot);
|
|
127
121
|
if (!Object.values(available).some(Boolean)) {
|
|
@@ -129,10 +123,11 @@ function main() {
|
|
|
129
123
|
process.exit(0);
|
|
130
124
|
}
|
|
131
125
|
|
|
126
|
+
RESULTS.length = 0;
|
|
132
127
|
let failures = 0;
|
|
133
128
|
|
|
134
129
|
if (available.eslint) {
|
|
135
|
-
|
|
130
|
+
console.log(sectionHeader('ESLint'));
|
|
136
131
|
const cmd = ["npx", "eslint"];
|
|
137
132
|
if (fixFlag) cmd.push("--fix");
|
|
138
133
|
if (fileArgs.length) cmd.push(...fileArgs);
|
|
@@ -141,7 +136,7 @@ function main() {
|
|
|
141
136
|
}
|
|
142
137
|
|
|
143
138
|
if (available.prettier) {
|
|
144
|
-
|
|
139
|
+
console.log(sectionHeader('Prettier'));
|
|
145
140
|
const cmd = ["npx", "prettier"];
|
|
146
141
|
if (fixFlag) cmd.push("--write");
|
|
147
142
|
else cmd.push("--check");
|
|
@@ -151,7 +146,7 @@ function main() {
|
|
|
151
146
|
}
|
|
152
147
|
|
|
153
148
|
if (available.ruff) {
|
|
154
|
-
|
|
149
|
+
console.log(sectionHeader('Ruff (Python)'));
|
|
155
150
|
const cmd = ["ruff", "check"];
|
|
156
151
|
if (fixFlag) cmd.push("--fix");
|
|
157
152
|
if (fileArgs.length) cmd.push(...fileArgs);
|
|
@@ -160,7 +155,7 @@ function main() {
|
|
|
160
155
|
}
|
|
161
156
|
|
|
162
157
|
if (available.flake8 && !available.ruff) {
|
|
163
|
-
|
|
158
|
+
console.log(sectionHeader('Flake8 (Python)'));
|
|
164
159
|
const cmd = ["flake8"];
|
|
165
160
|
if (fileArgs.length) cmd.push(...fileArgs);
|
|
166
161
|
else cmd.push(".");
|
|
@@ -168,15 +163,19 @@ function main() {
|
|
|
168
163
|
}
|
|
169
164
|
|
|
170
165
|
if (fs.existsSync(path.join(projectRoot, "tsconfig.json"))) {
|
|
171
|
-
|
|
166
|
+
console.log(sectionHeader('TypeScript'));
|
|
172
167
|
if (!runLinter("TypeScript", ["npx", "tsc", "--noEmit"], projectRoot)) failures++;
|
|
173
168
|
}
|
|
174
169
|
|
|
175
|
-
console.log(`\n${BOLD}━━━ Lint Summary ━━━${RESET}`);
|
|
170
|
+
console.log(`\n${BOLD}${CYAN}━━━ Lint Summary ━━━${RESET}`);
|
|
171
|
+
if (RESULTS.length > 0) {
|
|
172
|
+
summaryTable(RESULTS);
|
|
173
|
+
}
|
|
174
|
+
|
|
176
175
|
if (failures === 0) {
|
|
177
|
-
|
|
176
|
+
console.log(`\n${GREEN}${BOLD} ✔ All linters passed.${RESET}\n`);
|
|
178
177
|
} else {
|
|
179
|
-
|
|
178
|
+
console.log(`\n${RED}${BOLD} ✖ ${failures} linter(s) reported issues.${RESET}\n`);
|
|
180
179
|
}
|
|
181
180
|
|
|
182
181
|
process.exit(failures > 0 ? 1 : 0);
|
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* minify_context.js
|
|
4
|
-
* Minifies markdown documentation in the .agent directory to save tokens.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
'use strict';
|
|
8
|
-
|
|
9
|
-
const fs = require('fs');
|
|
10
|
-
const path = require('path');
|
|
11
|
-
|
|
12
|
-
function minifyMarkdown(filePath) {
|
|
13
|
-
let content = fs.readFileSync(filePath, 'utf8');
|
|
14
|
-
const originalLen = content.length;
|
|
15
|
-
|
|
16
|
-
// 1. Strip repetitive Output Format templates
|
|
17
|
-
content = content.replace(/## Output Format\n\n```[\s\S]*?```\n/g, '');
|
|
18
|
-
|
|
19
|
-
// 2. Convert bloated Cross-Workflow Navigation tables to dense YAML lists
|
|
20
|
-
content = content.replace(/## Cross-Workflow Navigation\n\n\|.*?\|[\s\S]*?(?=\n## |\Z)/g, match => {
|
|
21
|
-
const lines = match.trim().split('\n');
|
|
22
|
-
const out = [];
|
|
23
|
-
for (const line of lines) {
|
|
24
|
-
if (line.startsWith('|') && !line.startsWith('|:') && !line.startsWith('| After')) {
|
|
25
|
-
const parts = line.split('|').map(p => p.trim()).filter(Boolean);
|
|
26
|
-
if (parts.length >= 2) {
|
|
27
|
-
out.push(`- ${parts[0]} -> ${parts[1]}`);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return '## Cross-Workflow Navigation\n' + out.join('\n') + '\n';
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
// 3. Collapse multiple empty lines into a single one
|
|
35
|
-
content = content.replace(/\n{3,}/g, '\n\n');
|
|
36
|
-
|
|
37
|
-
// 4. Remove padding from remaining tables to save space tokens
|
|
38
|
-
content = content.replace(/^\|.+|$/gm, match => {
|
|
39
|
-
let line = match;
|
|
40
|
-
// remove spaces around |
|
|
41
|
-
line = line.replace(/\s+\|\s+/g, '|');
|
|
42
|
-
line = line.replace(/\|\s+/g, '|');
|
|
43
|
-
line = line.replace(/\s+\|/g, '|');
|
|
44
|
-
return line;
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
// 5. Remove conversational blockquotes > if they don't contain WARNING/NOTE/IMPORTANT
|
|
48
|
-
content = content.replace(/^>.*$/gm, match => {
|
|
49
|
-
if (match.includes('⚠️') || match.includes('WARNING') || match.includes('CRITICAL') || match.includes('!')) {
|
|
50
|
-
return match;
|
|
51
|
-
}
|
|
52
|
-
return match.replace(/> /g, '').replace(/>/g, '');
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
// 6. Dense Examples (convert ❌ Bad: and ✅ Good: blocks to single lines)
|
|
56
|
-
content = content.replace(/\n❌ Bad:/g, ' ❌');
|
|
57
|
-
content = content.replace(/\n✅ Good:/g, ' ✅');
|
|
58
|
-
|
|
59
|
-
fs.writeFileSync(filePath, content, 'utf8');
|
|
60
|
-
return [originalLen, content.length];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function walkDir(dir, callback) {
|
|
64
|
-
if (!fs.existsSync(dir)) return;
|
|
65
|
-
const items = fs.readdirSync(dir, { withFileTypes: true });
|
|
66
|
-
for (const item of items) {
|
|
67
|
-
const fullPath = path.join(dir, item.name);
|
|
68
|
-
if (item.isDirectory()) {
|
|
69
|
-
walkDir(fullPath, callback);
|
|
70
|
-
} else {
|
|
71
|
-
callback(fullPath);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function main() {
|
|
77
|
-
const agentDir = path.join('.agent');
|
|
78
|
-
let totalOriginal = 0;
|
|
79
|
-
let totalNew = 0;
|
|
80
|
-
|
|
81
|
-
walkDir(agentDir, file => {
|
|
82
|
-
if (file.endsWith('.md')) {
|
|
83
|
-
const [orig, newLen] = minifyMarkdown(file);
|
|
84
|
-
totalOriginal += orig;
|
|
85
|
-
totalNew += newLen;
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
const saved = totalOriginal - totalNew;
|
|
90
|
-
const percent = totalOriginal > 0 ? (saved / totalOriginal * 100) : 0;
|
|
91
|
-
|
|
92
|
-
console.log("Minification Complete.");
|
|
93
|
-
console.log(`Original size: ${totalOriginal} bytes`);
|
|
94
|
-
console.log(`New size: ${totalNew} bytes`);
|
|
95
|
-
console.log(`Saved: ${saved} bytes (${percent.toFixed(1)}%)`);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (require.main === module) {
|
|
99
|
-
main();
|
|
100
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* minify_context.js
|
|
4
|
+
* Minifies markdown documentation in the .agent directory to save tokens.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
function minifyMarkdown(filePath) {
|
|
13
|
+
let content = fs.readFileSync(filePath, 'utf8');
|
|
14
|
+
const originalLen = content.length;
|
|
15
|
+
|
|
16
|
+
// 1. Strip repetitive Output Format templates
|
|
17
|
+
content = content.replace(/## Output Format\n\n```[\s\S]*?```\n/g, '');
|
|
18
|
+
|
|
19
|
+
// 2. Convert bloated Cross-Workflow Navigation tables to dense YAML lists
|
|
20
|
+
content = content.replace(/## Cross-Workflow Navigation\n\n\|.*?\|[\s\S]*?(?=\n## |\Z)/g, match => {
|
|
21
|
+
const lines = match.trim().split('\n');
|
|
22
|
+
const out = [];
|
|
23
|
+
for (const line of lines) {
|
|
24
|
+
if (line.startsWith('|') && !line.startsWith('|:') && !line.startsWith('| After')) {
|
|
25
|
+
const parts = line.split('|').map(p => p.trim()).filter(Boolean);
|
|
26
|
+
if (parts.length >= 2) {
|
|
27
|
+
out.push(`- ${parts[0]} -> ${parts[1]}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return '## Cross-Workflow Navigation\n' + out.join('\n') + '\n';
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// 3. Collapse multiple empty lines into a single one
|
|
35
|
+
content = content.replace(/\n{3,}/g, '\n\n');
|
|
36
|
+
|
|
37
|
+
// 4. Remove padding from remaining tables to save space tokens
|
|
38
|
+
content = content.replace(/^\|.+|$/gm, match => {
|
|
39
|
+
let line = match;
|
|
40
|
+
// remove spaces around |
|
|
41
|
+
line = line.replace(/\s+\|\s+/g, '|');
|
|
42
|
+
line = line.replace(/\|\s+/g, '|');
|
|
43
|
+
line = line.replace(/\s+\|/g, '|');
|
|
44
|
+
return line;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// 5. Remove conversational blockquotes > if they don't contain WARNING/NOTE/IMPORTANT
|
|
48
|
+
content = content.replace(/^>.*$/gm, match => {
|
|
49
|
+
if (match.includes('⚠️') || match.includes('WARNING') || match.includes('CRITICAL') || match.includes('!')) {
|
|
50
|
+
return match;
|
|
51
|
+
}
|
|
52
|
+
return match.replace(/> /g, '').replace(/>/g, '');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// 6. Dense Examples (convert ❌ Bad: and ✅ Good: blocks to single lines)
|
|
56
|
+
content = content.replace(/\n❌ Bad:/g, ' ❌');
|
|
57
|
+
content = content.replace(/\n✅ Good:/g, ' ✅');
|
|
58
|
+
|
|
59
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
60
|
+
return [originalLen, content.length];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function walkDir(dir, callback) {
|
|
64
|
+
if (!fs.existsSync(dir)) return;
|
|
65
|
+
const items = fs.readdirSync(dir, { withFileTypes: true });
|
|
66
|
+
for (const item of items) {
|
|
67
|
+
const fullPath = path.join(dir, item.name);
|
|
68
|
+
if (item.isDirectory()) {
|
|
69
|
+
walkDir(fullPath, callback);
|
|
70
|
+
} else {
|
|
71
|
+
callback(fullPath);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function main() {
|
|
77
|
+
const agentDir = path.join('.agent');
|
|
78
|
+
let totalOriginal = 0;
|
|
79
|
+
let totalNew = 0;
|
|
80
|
+
|
|
81
|
+
walkDir(agentDir, file => {
|
|
82
|
+
if (file.endsWith('.md')) {
|
|
83
|
+
const [orig, newLen] = minifyMarkdown(file);
|
|
84
|
+
totalOriginal += orig;
|
|
85
|
+
totalNew += newLen;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const saved = totalOriginal - totalNew;
|
|
90
|
+
const percent = totalOriginal > 0 ? (saved / totalOriginal * 100) : 0;
|
|
91
|
+
|
|
92
|
+
console.log("Minification Complete.");
|
|
93
|
+
console.log(`Original size: ${totalOriginal} bytes`);
|
|
94
|
+
console.log(`New size: ${totalNew} bytes`);
|
|
95
|
+
console.log(`Saved: ${saved} bytes (${percent.toFixed(1)}%)`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (require.main === module) {
|
|
99
|
+
main();
|
|
100
|
+
}
|