tribunal-kit 7.0.0 → 8.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/.agent/config/claude.json +18 -0
- package/.agent/config/plugin.json +102 -0
- package/.agent/config/slash-commands.json +103 -0
- package/.agent/config/specialist-registry.json +415 -0
- package/.agent/config/system-prompt.md +191 -0
- package/.agent/history/architecture-graph.yaml +302 -3
- package/.agent/history/graph-cache.json +515 -45
- package/.agent/history/memory.db +0 -0
- package/.agent/history/snapshots/bin__adapter-install.js.json +13 -0
- package/.agent/history/snapshots/bin__global-store.js.json +15 -0
- package/.agent/history/snapshots/bin__mcp-server.js.json +19 -0
- package/.agent/history/snapshots/bin__proxy-server.js.json +20 -0
- package/.agent/history/snapshots/bin__spawn-agent.js.json +12 -0
- package/.agent/history/snapshots/bin__tk-proxy.js.json +21 -0
- package/.agent/history/snapshots/bin__tribunal-kit.js.json +9 -7
- package/.agent/history/snapshots/bin__wrapper.js.json +14 -0
- package/.agent/history/snapshots/eslint.config.js.json +1 -2
- package/.agent/history/snapshots/scripts__benchmark.js.json +14 -0
- package/.agent/history/snapshots/scripts__changelog.js.json +1 -2
- package/.agent/history/snapshots/scripts__fix-vbc.js.json +11 -0
- package/.agent/history/snapshots/scripts__stress_benchmark.js.json +15 -0
- package/.agent/history/snapshots/scripts__sync-version.js.json +1 -2
- package/.agent/history/snapshots/scripts__validate-payload.js.json +1 -2
- package/.agent/history/snapshots/scripts__visual_audit.js.json +11 -0
- package/.agent/history/snapshots/test__integration__bridges.test.js.json +1 -2
- package/.agent/history/snapshots/test__integration__graceful_degradation.test.js.json +12 -0
- package/.agent/history/snapshots/test__integration__init.test.js.json +1 -2
- package/.agent/history/snapshots/test__integration__minimal_change_pipeline.test.js.json +13 -0
- package/.agent/history/snapshots/test__integration__parallel_tribunal.test.js.json +12 -0
- package/.agent/history/snapshots/test__integration__routing.test.js.json +1 -2
- package/.agent/history/snapshots/test__integration__swarm_dispatcher.test.js.json +1 -2
- package/.agent/history/snapshots/test__integration__sync_status.test.js.json +13 -0
- package/.agent/history/snapshots/test__integration__wave2.test.js.json +1 -2
- package/.agent/history/snapshots/test__integration__wrapper.test.js.json +13 -0
- package/.agent/history/snapshots/test__unit__align.test.js.json +10 -0
- package/.agent/history/snapshots/test__unit__args.test.js.json +3 -3
- package/.agent/history/snapshots/test__unit__audit_release.test.js.json +16 -0
- package/.agent/history/snapshots/test__unit__case_law_manager.test.js.json +1 -2
- package/.agent/history/snapshots/test__unit__cicd_validator.test.js.json +12 -0
- package/.agent/history/snapshots/test__unit__compile.test.js.json +10 -0
- package/.agent/history/snapshots/test__unit__context_broker.test.js.json +1 -2
- package/.agent/history/snapshots/test__unit__contract_engine.test.js.json +13 -0
- package/.agent/history/snapshots/test__unit__copyDir.test.js.json +3 -3
- package/.agent/history/snapshots/test__unit__graph_tools.test.js.json +1 -2
- package/.agent/history/snapshots/test__unit__guardrail_engine.test.js.json +10 -0
- package/.agent/history/snapshots/test__unit__impact_classifier.test.js.json +12 -0
- package/.agent/history/snapshots/test__unit__init.test.js.json +14 -0
- package/.agent/history/snapshots/test__unit__inner_loop_validator.test.js.json +1 -2
- package/.agent/history/snapshots/test__unit__integrity_manifest.test.js.json +13 -0
- package/.agent/history/snapshots/test__unit__learn.test.js.json +11 -0
- package/.agent/history/snapshots/test__unit__marathon.test.js.json +22 -0
- package/.agent/history/snapshots/test__unit__mcp_server.test.js.json +16 -0
- package/.agent/history/snapshots/test__unit__memory.test.js.json +13 -0
- package/.agent/history/snapshots/test__unit__minimal_change.test.js.json +10 -0
- package/.agent/history/snapshots/test__unit__native.test.js.json +10 -0
- package/.agent/history/snapshots/test__unit__optimize.test.js.json +13 -0
- package/.agent/history/snapshots/test__unit__path_resolution.test.js.json +14 -0
- package/.agent/history/snapshots/test__unit__production_readiness_evidence.test.js.json +21 -0
- package/.agent/history/snapshots/test__unit__selfInstall.test.js.json +3 -3
- package/.agent/history/snapshots/test__unit__semver.test.js.json +3 -3
- package/.agent/history/snapshots/test__unit__skill_evolution.test.js.json +11 -0
- package/.agent/history/snapshots/test__unit__stress.test.js.json +15 -0
- package/.agent/history/snapshots/test__unit__swarm_dispatcher.test.js.json +3 -3
- package/.agent/history/snapshots/test__unit__utils.test.js.json +10 -0
- package/.agent/scripts/ast_context_loader.js +137 -0
- package/.agent/scripts/memory_engine.js +581 -0
- package/.agent/scripts/payload_schemas.js +146 -0
- package/.agent/scripts/prompt_compiler.js +59 -11
- package/.agent/scripts/swarm_dispatcher.js +295 -67
- package/.agent/scripts/token_budget_broker.js +117 -6
- package/.claude/CLAUDE.md +442 -0
- package/README.md +22 -12
- package/SECURITY.md +3 -3
- package/bin/adapter-install.js +240 -0
- package/bin/global-store.js +48 -0
- package/bin/mcp-server.js +568 -252
- package/bin/proxy-server.js +113 -0
- package/bin/spawn-agent.js +39 -0
- package/bin/tk-proxy.js +34 -0
- package/dist/commands/init.js +8 -51
- package/dist/commands/status.js +61 -36
- package/dist/commands/validate.js +22 -31
- package/dist/tui/banner.js +77 -0
- package/dist/tui/index.js +21 -0
- package/dist/tui/reviewer-grid.js +90 -0
- package/dist/tui/shimmer.js +91 -0
- package/dist/tui/theme.js +130 -0
- package/dist/tui/tree.js +93 -0
- package/dist/tui/wizard.js +148 -0
- package/dist/utils/helpers.js +5 -41
- package/package.json +27 -10
- package/scripts/build-graph.js +71 -0
- package/.agent/history/snapshots/migrate_refs.js.json +0 -11
- package/.agent/scripts/compile_router.py +0 -5
- package/.agent/scripts/migrate_skills_frontmatter.py +0 -5
package/bin/mcp-server.js
CHANGED
|
@@ -20,6 +20,61 @@ const PKG = require(path.resolve(__dirname, '../package.json'));
|
|
|
20
20
|
|
|
21
21
|
// Timeout for intentionally isolated child processes (30 seconds).
|
|
22
22
|
const SPAWN_TIMEOUT_MS = 30000;
|
|
23
|
+
const GENERAL_TOOL_TIMEOUT_MS = 60000;
|
|
24
|
+
|
|
25
|
+
// --- DSH Guard: Cooperative Timeout ---
|
|
26
|
+
async function withToolTimeout(fn, timeoutMs) {
|
|
27
|
+
let timeoutId;
|
|
28
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
29
|
+
timeoutId = setTimeout(() => {
|
|
30
|
+
reject(new Error('TOOL_TIMEOUT'));
|
|
31
|
+
}, timeoutMs);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const result = await Promise.race([Promise.resolve().then(fn), timeoutPromise]);
|
|
36
|
+
return result;
|
|
37
|
+
} finally {
|
|
38
|
+
clearTimeout(timeoutId);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// --- DSH Guard: Loop Detection ---
|
|
43
|
+
class ToolRepeatGuard {
|
|
44
|
+
constructor() {
|
|
45
|
+
this.history = new Map();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
observe(toolName, argsObj) {
|
|
49
|
+
const canonicalize = obj => {
|
|
50
|
+
if (Array.isArray(obj)) return obj.map(canonicalize);
|
|
51
|
+
if (obj !== null && typeof obj === 'object') {
|
|
52
|
+
const sorted = {};
|
|
53
|
+
for (const key of Object.keys(obj).sort()) {
|
|
54
|
+
sorted[key] = canonicalize(obj[key]);
|
|
55
|
+
}
|
|
56
|
+
return sorted;
|
|
57
|
+
}
|
|
58
|
+
return obj;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const canonicalArgs = JSON.stringify(canonicalize(argsObj) || {});
|
|
62
|
+
const key = `${toolName}::${canonicalArgs}`;
|
|
63
|
+
|
|
64
|
+
const currentCount = (this.history.get(key) || 0) + 1;
|
|
65
|
+
this.history.clear();
|
|
66
|
+
this.history.set(key, currentCount);
|
|
67
|
+
|
|
68
|
+
if (currentCount === 3) {
|
|
69
|
+
return 'SYSTEM NOTIFICATION: You are repeating the exact same tool call with identical arguments. Carefully analyze the previous result before calling again: if the task is not complete, try a different approach or different arguments instead of repeating the call.';
|
|
70
|
+
}
|
|
71
|
+
if (currentCount >= 5) {
|
|
72
|
+
return `SYSTEM NOTIFICATION: Repeated tool call detected:\n- tool: ${toolName}\n- consecutive_calls: ${currentCount}\n- arguments: ${canonicalArgs}\nThe repeated calls are not making progress. Do not call this tool with these exact arguments again. Inspect the latest result and choose a different action, different arguments, or finish the task.`;
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const repeatGuard = new ToolRepeatGuard();
|
|
23
78
|
|
|
24
79
|
class RpcError extends Error {
|
|
25
80
|
constructor(code, message) {
|
|
@@ -118,7 +173,7 @@ function getAgentDir() {
|
|
|
118
173
|
return path.resolve(__dirname, '../.agent');
|
|
119
174
|
}
|
|
120
175
|
|
|
121
|
-
function handleRequest(req) {
|
|
176
|
+
async function handleRequest(req) {
|
|
122
177
|
const fs = require('fs');
|
|
123
178
|
if (req.method === 'notifications/initialized' || req.method === 'notifications/cancelled') {
|
|
124
179
|
return null;
|
|
@@ -475,334 +530,595 @@ function handleRequest(req) {
|
|
|
475
530
|
additionalProperties: false,
|
|
476
531
|
},
|
|
477
532
|
},
|
|
533
|
+
{
|
|
534
|
+
name: 'query_semantic_graph',
|
|
535
|
+
description:
|
|
536
|
+
'Query the Ahead-of-Time (AOT) Semantic Context Graph to quickly resolve function signatures, dependencies, and file structures without inflating context windows.',
|
|
537
|
+
inputSchema: {
|
|
538
|
+
type: 'object',
|
|
539
|
+
properties: {
|
|
540
|
+
targetPath: {
|
|
541
|
+
type: 'string',
|
|
542
|
+
description: 'The directory to query (defaults to current workspace).',
|
|
543
|
+
},
|
|
544
|
+
},
|
|
545
|
+
additionalProperties: false,
|
|
546
|
+
},
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
name: 'exit_plan_mode',
|
|
550
|
+
description:
|
|
551
|
+
'Present your finished plan for human reviewed designing your approach. Execution will suspend until the user approves or requests changes.',
|
|
552
|
+
inputSchema: {
|
|
553
|
+
type: 'object',
|
|
554
|
+
properties: {
|
|
555
|
+
plan_content: {
|
|
556
|
+
type: 'string',
|
|
557
|
+
description: 'The markdown content of your proposed plan.',
|
|
558
|
+
},
|
|
559
|
+
},
|
|
560
|
+
required: ['plan_content'],
|
|
561
|
+
additionalProperties: false,
|
|
562
|
+
},
|
|
563
|
+
},
|
|
478
564
|
],
|
|
479
565
|
};
|
|
480
566
|
}
|
|
481
567
|
|
|
482
568
|
if (req.method === 'tools/call') {
|
|
483
569
|
const toolName = req.params && req.params.name;
|
|
570
|
+
const argsObj = req.params && req.params.arguments;
|
|
484
571
|
if (!toolName) {
|
|
485
572
|
throw new RpcError(-32602, 'Missing required parameter: params.name');
|
|
486
573
|
}
|
|
487
574
|
|
|
488
|
-
|
|
489
|
-
const text = runTribunalAudit();
|
|
490
|
-
return { content: [{ type: 'text', text }] };
|
|
491
|
-
}
|
|
575
|
+
const reminder = repeatGuard.observe(toolName, argsObj);
|
|
492
576
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
{
|
|
501
|
-
type: 'text',
|
|
502
|
-
text: 'Error: .agent/ directory not found. Run `tk init` first.',
|
|
503
|
-
},
|
|
504
|
-
],
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
try {
|
|
508
|
-
const { generateIDEBridges } = require(path.resolve(__dirname, '../dist/commands/init.js'));
|
|
509
|
-
// generateIDEBridges is async — execute synchronously in MCP context
|
|
510
|
-
generateIDEBridges(cwd, agentDest, true)
|
|
511
|
-
.then(() => {})
|
|
512
|
-
.catch(() => {});
|
|
513
|
-
return {
|
|
514
|
-
content: [
|
|
515
|
-
{
|
|
516
|
-
type: 'text',
|
|
517
|
-
text: 'Sync complete',
|
|
518
|
-
},
|
|
519
|
-
],
|
|
520
|
-
};
|
|
521
|
-
} catch (e) {
|
|
577
|
+
const executeTool = async () => {
|
|
578
|
+
if (toolName === 'exit_plan_mode') {
|
|
579
|
+
const planContent = req.params?.arguments?.plan_content;
|
|
580
|
+
if (typeof planContent !== 'string') {
|
|
581
|
+
throw new RpcError(-32602, 'Missing or invalid required argument: plan_content (string)');
|
|
582
|
+
}
|
|
583
|
+
// The wrapper CLI can intercept this, but for the LLM context, we explicitly tell it to wait.
|
|
522
584
|
return {
|
|
523
585
|
content: [
|
|
524
586
|
{
|
|
525
587
|
type: 'text',
|
|
526
|
-
text:
|
|
588
|
+
text: 'PLAN_SUBMITTED_FOR_REVIEW: The plan has been presented to the human. Please suspend execution and wait for the human to approve or provide feedback in the next turn. Do not call any further tools until you receive a response.',
|
|
527
589
|
},
|
|
528
590
|
],
|
|
529
591
|
};
|
|
530
592
|
}
|
|
531
|
-
}
|
|
532
593
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
594
|
+
if (toolName === 'dispatch_swarm') {
|
|
595
|
+
const payload = req.params?.arguments?.payload;
|
|
596
|
+
const file = req.params?.arguments?.file;
|
|
597
|
+
const workspace = req.params?.arguments?.workspace || '.';
|
|
598
|
+
const mode = req.params?.arguments?.mode || 'legacy';
|
|
599
|
+
const useTui = req.params?.arguments?.use_tui || false;
|
|
600
|
+
|
|
601
|
+
if (!payload && !file) {
|
|
602
|
+
throw new RpcError(
|
|
603
|
+
-32602,
|
|
604
|
+
'Missing required argument: either payload or file must be provided',
|
|
605
|
+
);
|
|
606
|
+
}
|
|
541
607
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
if (!fs.existsSync(agentDir))
|
|
546
|
-
return {
|
|
547
|
-
content: [{ type: 'text', text: 'No agents found or .agent directory missing.' }],
|
|
548
|
-
};
|
|
549
|
-
const agents = fs
|
|
550
|
-
.readdirSync(agentDir)
|
|
551
|
-
.filter(f => f.endsWith('.md'))
|
|
552
|
-
.map(f => f.replace('.md', ''));
|
|
553
|
-
return { content: [{ type: 'text', text: 'Available Agents:\n- ' + agents.join('\n- ') }] };
|
|
554
|
-
}
|
|
608
|
+
if (payload && file) {
|
|
609
|
+
throw new RpcError(-32602, 'Invalid arguments: provide either payload or file, not both');
|
|
610
|
+
}
|
|
555
611
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
if (!agentPath.startsWith(agentsDir))
|
|
566
|
-
throw new RpcError(-32602, 'Invalid agent name: path traversal detected');
|
|
567
|
-
if (!fs.existsSync(agentPath))
|
|
568
|
-
return { content: [{ type: 'text', text: `Agent '${sanitizedName}' not found.` }] };
|
|
569
|
-
const text = fs.readFileSync(agentPath, 'utf8');
|
|
570
|
-
return { content: [{ type: 'text', text: stripBoilerplate(text) }] };
|
|
571
|
-
}
|
|
612
|
+
const agentDir = getAgentDir();
|
|
613
|
+
const fs = require('fs');
|
|
614
|
+
if (!fs.existsSync(agentDir)) {
|
|
615
|
+
return {
|
|
616
|
+
content: [
|
|
617
|
+
{ type: 'text', text: 'Error: .agent/ directory not found. Run `tk init` first.' },
|
|
618
|
+
],
|
|
619
|
+
};
|
|
620
|
+
}
|
|
572
621
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
return { content: [{ type: 'text', text: 'Available Skills:\n- ' + skills.join('\n- ') }] };
|
|
585
|
-
}
|
|
622
|
+
try {
|
|
623
|
+
let _payloadData;
|
|
624
|
+
if (file) {
|
|
625
|
+
const filePath = path.resolve(workspace, file);
|
|
626
|
+
if (!fs.existsSync(filePath)) {
|
|
627
|
+
throw new Error(`File not found: ${filePath}`);
|
|
628
|
+
}
|
|
629
|
+
_payloadData = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
630
|
+
} else {
|
|
631
|
+
_payloadData = JSON.parse(payload);
|
|
632
|
+
}
|
|
586
633
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
const name = req.params?.arguments?.name;
|
|
590
|
-
if (!name || typeof name !== 'string')
|
|
591
|
-
throw new RpcError(-32602, 'Missing or invalid argument: name (string)');
|
|
592
|
-
const sanitizedName = path.basename(name);
|
|
593
|
-
const skillsDir = path.resolve(getAgentDir(), 'skills');
|
|
594
|
-
const skillPath = path.resolve(skillsDir, sanitizedName, 'SKILL.md');
|
|
595
|
-
// Path containment: ensure resolved path stays within skills directory
|
|
596
|
-
if (!skillPath.startsWith(skillsDir))
|
|
597
|
-
throw new RpcError(-32602, 'Invalid skill name: path traversal detected');
|
|
598
|
-
if (!fs.existsSync(skillPath))
|
|
599
|
-
return { content: [{ type: 'text', text: `Skill '${sanitizedName}' not found.` }] };
|
|
600
|
-
const text = fs.readFileSync(skillPath, 'utf8');
|
|
601
|
-
return { content: [{ type: 'text', text: stripBoilerplate(text) }] };
|
|
602
|
-
}
|
|
634
|
+
// Import swarm dispatcher functions
|
|
635
|
+
const _swarmDispatcher = require(path.join(agentDir, 'scripts', 'swarm_dispatcher.js'));
|
|
603
636
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
const model = req.params?.arguments?.model || 'large';
|
|
637
|
+
// Execute the swarm dispatcher
|
|
638
|
+
const originalArgv = process.argv;
|
|
639
|
+
process.argv = ['node', 'swarm_dispatcher.js', '--mode', mode, '--workspace', workspace];
|
|
608
640
|
|
|
609
|
-
|
|
641
|
+
if (useTui) {
|
|
642
|
+
process.argv.push('--tui');
|
|
643
|
+
}
|
|
610
644
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
};
|
|
619
|
-
}
|
|
645
|
+
if (file) {
|
|
646
|
+
process.argv.push('--file');
|
|
647
|
+
process.argv.push(file);
|
|
648
|
+
} else if (payload) {
|
|
649
|
+
process.argv.push('--payload');
|
|
650
|
+
process.argv.push(payload);
|
|
651
|
+
}
|
|
620
652
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
653
|
+
// Capture output
|
|
654
|
+
const { spawnSync } = require('child_process');
|
|
655
|
+
const result = spawnSync(
|
|
656
|
+
process.execPath,
|
|
657
|
+
[path.join(agentDir, 'scripts', 'swarm_dispatcher.js'), ...process.argv.slice(2)],
|
|
658
|
+
{
|
|
659
|
+
encoding: 'utf8',
|
|
660
|
+
timeout: 30000,
|
|
661
|
+
},
|
|
662
|
+
);
|
|
663
|
+
|
|
664
|
+
// Restore argv
|
|
665
|
+
process.argv = originalArgv;
|
|
632
666
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
667
|
+
if (result.error) {
|
|
668
|
+
throw result.error;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
return {
|
|
672
|
+
content: [
|
|
673
|
+
{ type: 'text', text: result.stdout || result.stderr || 'Swarm dispatch completed' },
|
|
674
|
+
],
|
|
675
|
+
};
|
|
676
|
+
} catch (e) {
|
|
677
|
+
return {
|
|
678
|
+
content: [{ type: 'text', text: `Swarm dispatch failed: ${e.message}` }],
|
|
679
|
+
};
|
|
680
|
+
}
|
|
637
681
|
}
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
682
|
+
|
|
683
|
+
if (toolName === 'get_ast_context') {
|
|
684
|
+
const targetPath = req.params?.arguments?.targetPath || process.cwd();
|
|
685
|
+
try {
|
|
686
|
+
const result = spawnSync(
|
|
687
|
+
'node',
|
|
688
|
+
[path.join(__dirname, '../scripts/build-graph.js'), targetPath],
|
|
689
|
+
{
|
|
690
|
+
encoding: 'utf8',
|
|
691
|
+
timeout: 10000,
|
|
692
|
+
},
|
|
693
|
+
);
|
|
694
|
+
if (result.error) throw result.error;
|
|
695
|
+
return { content: [{ type: 'text', text: result.stdout || result.stderr }] };
|
|
696
|
+
} catch (e) {
|
|
697
|
+
return { content: [{ type: 'text', text: `Failed to query graph: ${e.message}` }] };
|
|
698
|
+
}
|
|
647
699
|
}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
const
|
|
651
|
-
|
|
652
|
-
|
|
700
|
+
|
|
701
|
+
if (toolName === 'validate_payload') {
|
|
702
|
+
const payloadStr = req.params?.arguments?.payload;
|
|
703
|
+
const schemaType = req.params?.arguments?.schemaType;
|
|
704
|
+
|
|
705
|
+
if (!payloadStr || typeof payloadStr !== 'string') {
|
|
706
|
+
throw new RpcError(-32602, 'Missing or invalid required argument: payload (string)');
|
|
707
|
+
}
|
|
708
|
+
if (!schemaType || typeof schemaType !== 'string') {
|
|
709
|
+
throw new RpcError(-32602, 'Missing or invalid required argument: schemaType (string)');
|
|
653
710
|
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
711
|
+
|
|
712
|
+
const agentDir = getAgentDir();
|
|
713
|
+
const fs = require('fs');
|
|
714
|
+
if (!fs.existsSync(agentDir)) {
|
|
715
|
+
return {
|
|
716
|
+
content: [
|
|
717
|
+
{ type: 'text', text: 'Error: .agent/ directory not found. Run `tk init` first.' },
|
|
718
|
+
],
|
|
719
|
+
};
|
|
659
720
|
}
|
|
721
|
+
|
|
722
|
+
try {
|
|
723
|
+
const payloadData = JSON.parse(payloadStr);
|
|
724
|
+
const {
|
|
725
|
+
WorkerRequestSchema,
|
|
726
|
+
WorkerResultSchema,
|
|
727
|
+
SwarmPayloadSchema,
|
|
728
|
+
validatePayloadOrThrow,
|
|
729
|
+
} = require(path.join(agentDir, 'scripts', 'payload_schemas.js'));
|
|
730
|
+
|
|
731
|
+
let schema;
|
|
732
|
+
switch (schemaType) {
|
|
733
|
+
case 'worker-request':
|
|
734
|
+
schema = WorkerRequestSchema;
|
|
735
|
+
break;
|
|
736
|
+
case 'worker-result':
|
|
737
|
+
schema = WorkerResultSchema;
|
|
738
|
+
break;
|
|
739
|
+
case 'swarm-payload':
|
|
740
|
+
schema = SwarmPayloadSchema;
|
|
741
|
+
break;
|
|
742
|
+
default:
|
|
743
|
+
throw new RpcError(
|
|
744
|
+
-32602,
|
|
745
|
+
`Invalid schemaType: ${schemaType}. Must be one of: worker-request, worker-result, swarm-payload`,
|
|
746
|
+
);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
const validatedData = validatePayloadOrThrow(payloadData, schema);
|
|
750
|
+
return {
|
|
751
|
+
content: [
|
|
752
|
+
{
|
|
753
|
+
type: 'text',
|
|
754
|
+
text: `Payload validation successful.\n\nValidated payload:\n${JSON.stringify(validatedData, null, 2)}`,
|
|
755
|
+
},
|
|
756
|
+
],
|
|
757
|
+
};
|
|
758
|
+
} catch (e) {
|
|
759
|
+
if (e instanceof SyntaxError) {
|
|
760
|
+
return { content: [{ type: 'text', text: `Invalid JSON payload: ${e.message}` }] };
|
|
761
|
+
} else {
|
|
762
|
+
return { content: [{ type: 'text', text: `Payload validation failed: ${e.message}` }] };
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
if (toolName === 'run_tribunal_audit') {
|
|
768
|
+
const text = runTribunalAudit();
|
|
660
769
|
return { content: [{ type: 'text', text }] };
|
|
661
|
-
} catch (e) {
|
|
662
|
-
return { content: [{ type: 'text', text: `Memory recall failed: ${e.message}` }] };
|
|
663
770
|
}
|
|
664
|
-
}
|
|
665
771
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
772
|
+
if (toolName === 'sync_ide_bridges') {
|
|
773
|
+
const fs = require('fs');
|
|
774
|
+
const cwd = process.cwd();
|
|
775
|
+
const agentDest = path.join(cwd, '.agent');
|
|
776
|
+
if (!fs.existsSync(agentDest)) {
|
|
777
|
+
return {
|
|
778
|
+
content: [
|
|
779
|
+
{
|
|
780
|
+
type: 'text',
|
|
781
|
+
text: 'Error: .agent/ directory not found. Run `tk init` first.',
|
|
782
|
+
},
|
|
783
|
+
],
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
try {
|
|
787
|
+
const { generateIDEBridges } = require(
|
|
788
|
+
path.resolve(__dirname, '../dist/commands/init.js'),
|
|
789
|
+
);
|
|
790
|
+
// generateIDEBridges is async
|
|
791
|
+
await generateIDEBridges(cwd, agentDest, true);
|
|
792
|
+
return {
|
|
793
|
+
content: [
|
|
794
|
+
{
|
|
795
|
+
type: 'text',
|
|
796
|
+
text: 'Sync complete',
|
|
797
|
+
},
|
|
798
|
+
],
|
|
799
|
+
};
|
|
800
|
+
} catch (e) {
|
|
801
|
+
return {
|
|
802
|
+
content: [
|
|
803
|
+
{
|
|
804
|
+
type: 'text',
|
|
805
|
+
text: `Sync failed: ${e.message}`,
|
|
806
|
+
},
|
|
807
|
+
],
|
|
808
|
+
};
|
|
809
|
+
}
|
|
672
810
|
}
|
|
673
|
-
|
|
674
|
-
if (
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
811
|
+
|
|
812
|
+
if (toolName === 'search_case_law') {
|
|
813
|
+
const query = req.params && req.params.arguments && req.params.arguments.query;
|
|
814
|
+
if (!query || typeof query !== 'string') {
|
|
815
|
+
throw new RpcError(-32602, 'Missing or invalid required argument: query (string)');
|
|
816
|
+
}
|
|
817
|
+
const text = searchCaseLaw(query);
|
|
818
|
+
return { content: [{ type: 'text', text }] };
|
|
679
819
|
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
820
|
+
|
|
821
|
+
if (toolName === 'list_tribunal_agents') {
|
|
822
|
+
const fs = require('fs');
|
|
823
|
+
const agentDir = path.join(getAgentDir(), 'agents');
|
|
824
|
+
if (!fs.existsSync(agentDir))
|
|
825
|
+
return {
|
|
826
|
+
content: [{ type: 'text', text: 'No agents found or .agent directory missing.' }],
|
|
827
|
+
};
|
|
828
|
+
const agents = fs
|
|
829
|
+
.readdirSync(agentDir)
|
|
830
|
+
.filter(f => f.endsWith('.md'))
|
|
831
|
+
.map(f => f.replace('.md', ''));
|
|
832
|
+
return { content: [{ type: 'text', text: 'Available Agents:\n- ' + agents.join('\n- ') }] };
|
|
688
833
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
const
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
834
|
+
|
|
835
|
+
if (toolName === 'get_tribunal_agent') {
|
|
836
|
+
const fs = require('fs');
|
|
837
|
+
const name = req.params?.arguments?.name;
|
|
838
|
+
if (!name || typeof name !== 'string')
|
|
839
|
+
throw new RpcError(-32602, 'Missing or invalid argument: name (string)');
|
|
840
|
+
const sanitizedName = path.basename(name);
|
|
841
|
+
const agentsDir = path.resolve(getAgentDir(), 'agents');
|
|
842
|
+
const agentPath = path.resolve(agentsDir, `${sanitizedName}.md`);
|
|
843
|
+
// Path containment: ensure resolved path stays within agents directory
|
|
844
|
+
if (!agentPath.startsWith(agentsDir))
|
|
845
|
+
throw new RpcError(-32602, 'Invalid agent name: path traversal detected');
|
|
846
|
+
if (!fs.existsSync(agentPath))
|
|
847
|
+
return { content: [{ type: 'text', text: `Agent '${sanitizedName}' not found.` }] };
|
|
848
|
+
const text = fs.readFileSync(agentPath, 'utf8');
|
|
849
|
+
return { content: [{ type: 'text', text: stripBoilerplate(text) }] };
|
|
702
850
|
}
|
|
703
|
-
}
|
|
704
851
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
852
|
+
if (toolName === 'list_tribunal_skills') {
|
|
853
|
+
const fs = require('fs');
|
|
854
|
+
const skillsDir = path.join(getAgentDir(), 'skills');
|
|
855
|
+
if (!fs.existsSync(skillsDir))
|
|
856
|
+
return {
|
|
857
|
+
content: [{ type: 'text', text: 'No skills found or .agent directory missing.' }],
|
|
858
|
+
};
|
|
859
|
+
const skills = fs
|
|
860
|
+
.readdirSync(skillsDir, { withFileTypes: true })
|
|
861
|
+
.filter(d => d.isDirectory())
|
|
862
|
+
.map(d => d.name);
|
|
863
|
+
return { content: [{ type: 'text', text: 'Available Skills:\n- ' + skills.join('\n- ') }] };
|
|
709
864
|
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
const
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
865
|
+
|
|
866
|
+
if (toolName === 'get_tribunal_skill') {
|
|
867
|
+
const fs = require('fs');
|
|
868
|
+
const name = req.params?.arguments?.name;
|
|
869
|
+
if (!name || typeof name !== 'string')
|
|
870
|
+
throw new RpcError(-32602, 'Missing or invalid argument: name (string)');
|
|
871
|
+
const sanitizedName = path.basename(name);
|
|
872
|
+
const skillsDir = path.resolve(getAgentDir(), 'skills');
|
|
873
|
+
const skillPath = path.resolve(skillsDir, sanitizedName, 'SKILL.md');
|
|
874
|
+
// Path containment: ensure resolved path stays within skills directory
|
|
875
|
+
if (!skillPath.startsWith(skillsDir))
|
|
876
|
+
throw new RpcError(-32602, 'Invalid skill name: path traversal detected');
|
|
877
|
+
if (!fs.existsSync(skillPath))
|
|
878
|
+
return { content: [{ type: 'text', text: `Skill '${sanitizedName}' not found.` }] };
|
|
879
|
+
const text = fs.readFileSync(skillPath, 'utf8');
|
|
880
|
+
return { content: [{ type: 'text', text: stripBoilerplate(text) }] };
|
|
725
881
|
}
|
|
726
|
-
}
|
|
727
882
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
883
|
+
if (toolName === 'get_sparse_context') {
|
|
884
|
+
const task = req.params?.arguments?.task;
|
|
885
|
+
const files = req.params?.arguments?.files || [];
|
|
886
|
+
const model = req.params?.arguments?.model || 'large';
|
|
731
887
|
|
|
732
|
-
|
|
733
|
-
throw new RpcError(
|
|
734
|
-
-32602,
|
|
735
|
-
'Missing or invalid required arguments: file (string), content (string)',
|
|
736
|
-
);
|
|
737
|
-
}
|
|
888
|
+
if (!task) throw new RpcError(-32602, 'Missing required argument: task');
|
|
738
889
|
|
|
739
|
-
|
|
740
|
-
const
|
|
741
|
-
|
|
742
|
-
if (!require('fs').existsSync(contractEnginePath)) {
|
|
890
|
+
const agentDest = getAgentDir();
|
|
891
|
+
const fs = require('fs');
|
|
892
|
+
if (!fs.existsSync(agentDest)) {
|
|
743
893
|
return {
|
|
744
894
|
content: [
|
|
745
|
-
{ type: 'text', text: 'Error:
|
|
895
|
+
{ type: 'text', text: 'Error: .agent/ directory not found. Run `tk init` first.' },
|
|
746
896
|
],
|
|
747
897
|
};
|
|
748
898
|
}
|
|
749
899
|
|
|
750
|
-
|
|
751
|
-
|
|
900
|
+
try {
|
|
901
|
+
const brokerScript = path.join(agentDest, 'scripts', 'context_broker.js');
|
|
902
|
+
const { broker } = require(brokerScript);
|
|
903
|
+
const brokerResult = broker(task, files, model, agentDest);
|
|
904
|
+
return { content: [{ type: 'text', text: stripBoilerplate(brokerResult.promptText) }] };
|
|
905
|
+
} catch (e) {
|
|
906
|
+
return {
|
|
907
|
+
content: [{ type: 'text', text: `Failed to retrieve sparse context: ${e.message}` }],
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
}
|
|
752
911
|
|
|
753
|
-
|
|
912
|
+
if (toolName === 'recall_memory') {
|
|
913
|
+
const query = req.params?.arguments?.query;
|
|
914
|
+
if (!query || typeof query !== 'string') {
|
|
915
|
+
throw new RpcError(-32602, 'Missing or invalid required argument: query (string)');
|
|
916
|
+
}
|
|
917
|
+
const budget = req.params?.arguments?.budget || 2000;
|
|
918
|
+
const agentDest = getAgentDir();
|
|
919
|
+
const fs = require('fs');
|
|
920
|
+
if (!fs.existsSync(agentDest)) {
|
|
754
921
|
return {
|
|
755
922
|
content: [
|
|
756
|
-
{
|
|
757
|
-
type: 'text',
|
|
758
|
-
text: 'No active behavioral contracts found in .tribunal/contracts/.',
|
|
759
|
-
},
|
|
923
|
+
{ type: 'text', text: 'Error: .agent/ directory not found. Run `tk init` first.' },
|
|
760
924
|
],
|
|
761
925
|
};
|
|
762
926
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
927
|
+
try {
|
|
928
|
+
const { _memoryRecall } = require('../dist/commands/memory.js');
|
|
929
|
+
const { results, tokens_used } = _memoryRecall(agentDest, query, budget);
|
|
930
|
+
if (results.length === 0) {
|
|
931
|
+
return { content: [{ type: 'text', text: `No memories match query: "${query}"` }] };
|
|
932
|
+
}
|
|
933
|
+
let text = `## Memory Recall (${results.length} results, ~${tokens_used}/${budget} tokens)\n\n`;
|
|
934
|
+
for (const entry of results) {
|
|
935
|
+
text += `- **[${entry.memory_type.toUpperCase()}]** #${entry.id}: ${entry.content}`;
|
|
936
|
+
if (entry.tags.length > 0) text += ` _(${entry.tags.join(', ')})_`;
|
|
937
|
+
text += `\n`;
|
|
771
938
|
}
|
|
939
|
+
return { content: [{ type: 'text', text }] };
|
|
940
|
+
} catch (e) {
|
|
941
|
+
return { content: [{ type: 'text', text: `Memory recall failed: ${e.message}` }] };
|
|
772
942
|
}
|
|
943
|
+
}
|
|
773
944
|
|
|
774
|
-
|
|
945
|
+
if (toolName === 'store_memory') {
|
|
946
|
+
const memType = req.params?.arguments?.type;
|
|
947
|
+
const content = req.params?.arguments?.content;
|
|
948
|
+
const tags = req.params?.arguments?.tags || [];
|
|
949
|
+
if (!memType || !content) {
|
|
950
|
+
throw new RpcError(-32602, 'Missing required arguments: type (string), content (string)');
|
|
951
|
+
}
|
|
952
|
+
const validTypes = ['semantic', 'procedural', 'episodic', 'working'];
|
|
953
|
+
if (!validTypes.includes(memType)) {
|
|
954
|
+
throw new RpcError(
|
|
955
|
+
-32602,
|
|
956
|
+
`Invalid memory type: "${memType}". Must be one of: ${validTypes.join(', ')}`,
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
const agentDest = getAgentDir();
|
|
960
|
+
const fs = require('fs');
|
|
961
|
+
if (!fs.existsSync(agentDest)) {
|
|
962
|
+
return {
|
|
963
|
+
content: [
|
|
964
|
+
{ type: 'text', text: 'Error: .agent/ directory not found. Run `tk init` first.' },
|
|
965
|
+
],
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
try {
|
|
969
|
+
const { _memoryStore } = require('../dist/commands/memory.js');
|
|
970
|
+
const result = _memoryStore(agentDest, memType, content, tags, null);
|
|
775
971
|
return {
|
|
776
972
|
content: [
|
|
777
973
|
{
|
|
778
974
|
type: 'text',
|
|
779
|
-
text:
|
|
975
|
+
text: `Memory stored: #${result.id} (${memType}, ~${result.token_estimate} tokens)`,
|
|
780
976
|
},
|
|
781
977
|
],
|
|
782
978
|
};
|
|
979
|
+
} catch (e) {
|
|
980
|
+
return { content: [{ type: 'text', text: `Memory store failed: ${e.message}` }] };
|
|
783
981
|
}
|
|
982
|
+
}
|
|
784
983
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
984
|
+
if (toolName === 'query_semantic_graph') {
|
|
985
|
+
const targetPath = req.params?.arguments?.targetPath || process.cwd();
|
|
986
|
+
try {
|
|
987
|
+
const result = spawnSync(
|
|
988
|
+
'node',
|
|
989
|
+
[path.join(__dirname, '../scripts/build-graph.js'), targetPath],
|
|
990
|
+
{
|
|
991
|
+
encoding: 'utf8',
|
|
992
|
+
timeout: 10000,
|
|
993
|
+
},
|
|
994
|
+
);
|
|
995
|
+
if (result.error) throw result.error;
|
|
996
|
+
return { content: [{ type: 'text', text: result.stdout || result.stderr }] };
|
|
997
|
+
} catch (e) {
|
|
998
|
+
return { content: [{ type: 'text', text: `Failed to query graph: ${e.message}` }] };
|
|
789
999
|
}
|
|
1000
|
+
}
|
|
790
1001
|
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
1002
|
+
if (toolName === 'align_output') {
|
|
1003
|
+
const text = req.params?.arguments?.text;
|
|
1004
|
+
if (typeof text !== 'string') {
|
|
1005
|
+
throw new RpcError(-32602, 'Missing or invalid required argument: text (string)');
|
|
1006
|
+
}
|
|
1007
|
+
try {
|
|
1008
|
+
const { alignText, validateCodeContent } = require('../dist/commands/align.js');
|
|
1009
|
+
const aligned = alignText(text);
|
|
1010
|
+
const warnings = validateCodeContent(aligned);
|
|
1011
|
+
|
|
1012
|
+
let outputText = aligned;
|
|
1013
|
+
if (warnings.length > 0) {
|
|
1014
|
+
outputText += '\n\n⚠️ OCAE Alignment Validator Warnings:\n';
|
|
1015
|
+
for (const warnMsg of warnings) {
|
|
1016
|
+
outputText += `● ${warnMsg}\n`;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
return { content: [{ type: 'text', text: outputText }] };
|
|
1020
|
+
} catch (e) {
|
|
1021
|
+
return { content: [{ type: 'text', text: `Output alignment failed: ${e.message}` }] };
|
|
1022
|
+
}
|
|
794
1023
|
}
|
|
795
|
-
}
|
|
796
1024
|
|
|
797
|
-
|
|
1025
|
+
if (toolName === 'verify_contracts') {
|
|
1026
|
+
const file = req.params?.arguments?.file;
|
|
1027
|
+
const content = req.params?.arguments?.content;
|
|
1028
|
+
|
|
1029
|
+
if (!file || typeof file !== 'string' || typeof content !== 'string') {
|
|
1030
|
+
throw new RpcError(
|
|
1031
|
+
-32602,
|
|
1032
|
+
'Missing or invalid required arguments: file (string), content (string)',
|
|
1033
|
+
);
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
try {
|
|
1037
|
+
const projectRoot = process.cwd();
|
|
1038
|
+
const contractEnginePath = path.join(getAgentDir(), 'scripts', 'contract_engine.js');
|
|
1039
|
+
if (!require('fs').existsSync(contractEnginePath)) {
|
|
1040
|
+
return {
|
|
1041
|
+
content: [
|
|
1042
|
+
{ type: 'text', text: 'Error: contract_engine.js not found. Run `tk init` first.' },
|
|
1043
|
+
],
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
const contractEngine = require(contractEnginePath);
|
|
1048
|
+
const contracts = contractEngine.loadContracts(projectRoot);
|
|
1049
|
+
|
|
1050
|
+
if (contracts.length === 0) {
|
|
1051
|
+
return {
|
|
1052
|
+
content: [
|
|
1053
|
+
{
|
|
1054
|
+
type: 'text',
|
|
1055
|
+
text: 'No active behavioral contracts found in .tribunal/contracts/.',
|
|
1056
|
+
},
|
|
1057
|
+
],
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
const relativePath = path.relative(projectRoot, file).replace(/\\/g, '/');
|
|
1062
|
+
const allViolations = [];
|
|
1063
|
+
|
|
1064
|
+
for (const contract of contracts) {
|
|
1065
|
+
const vList = contractEngine.evaluateContract(contract, relativePath, content);
|
|
1066
|
+
if (vList.length > 0) {
|
|
1067
|
+
allViolations.push(...vList);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
if (allViolations.length === 0) {
|
|
1072
|
+
return {
|
|
1073
|
+
content: [
|
|
1074
|
+
{
|
|
1075
|
+
type: 'text',
|
|
1076
|
+
text: '✅ Contract check passed. Zero behavioral violations detected.',
|
|
1077
|
+
},
|
|
1078
|
+
],
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
let report = `📜 Contract Verification Results (${allViolations.length} violations):\n`;
|
|
1083
|
+
for (const v of allViolations) {
|
|
1084
|
+
report += `● [${v.severity.toUpperCase()}] ${v.contract}: ${v.message}\n`;
|
|
1085
|
+
if (v.line) report += ` Line ${v.line}: ${v.snippet || ''}\n`;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
return { content: [{ type: 'text', text: report }] };
|
|
1089
|
+
} catch (e) {
|
|
1090
|
+
return {
|
|
1091
|
+
content: [{ type: 'text', text: `Contract verification failed: ${e.message}` }],
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
throw new RpcError(-32601, `Unknown tool: ${toolName}`);
|
|
1097
|
+
};
|
|
1098
|
+
|
|
1099
|
+
try {
|
|
1100
|
+
const result = await withToolTimeout(executeTool, GENERAL_TOOL_TIMEOUT_MS);
|
|
1101
|
+
if (reminder) {
|
|
1102
|
+
result.content.push({ type: 'text', text: '\n\n' + reminder });
|
|
1103
|
+
}
|
|
1104
|
+
return result;
|
|
1105
|
+
} catch (e) {
|
|
1106
|
+
if (e.message === 'TOOL_TIMEOUT') {
|
|
1107
|
+
const errorMsg = `Error: Tool execution timed out after ${GENERAL_TOOL_TIMEOUT_MS}ms`;
|
|
1108
|
+
const result = { content: [{ type: 'text', text: errorMsg }] };
|
|
1109
|
+
if (reminder) result.content.push({ type: 'text', text: '\n\n' + reminder });
|
|
1110
|
+
return result;
|
|
1111
|
+
}
|
|
1112
|
+
throw e;
|
|
1113
|
+
}
|
|
798
1114
|
}
|
|
799
1115
|
|
|
800
1116
|
throw new RpcError(-32601, `Unknown method: ${req.method}`);
|
|
801
1117
|
}
|
|
802
1118
|
|
|
803
|
-
function processSingleRequest(req) {
|
|
1119
|
+
async function processSingleRequest(req) {
|
|
804
1120
|
try {
|
|
805
|
-
const result = handleRequest(req);
|
|
1121
|
+
const result = await handleRequest(req);
|
|
806
1122
|
// If it's a notification, do not send a response
|
|
807
1123
|
if (req.id === undefined || req.id === null) {
|
|
808
1124
|
return null;
|
|
@@ -826,7 +1142,7 @@ function processSingleRequest(req) {
|
|
|
826
1142
|
}
|
|
827
1143
|
}
|
|
828
1144
|
|
|
829
|
-
rl.on('line', line => {
|
|
1145
|
+
rl.on('line', async line => {
|
|
830
1146
|
if (line.length > 1048576) {
|
|
831
1147
|
// 1MB limit
|
|
832
1148
|
const errorRes = {
|
|
@@ -856,7 +1172,7 @@ rl.on('line', line => {
|
|
|
856
1172
|
if (Array.isArray(req)) {
|
|
857
1173
|
const responses = [];
|
|
858
1174
|
for (const singleReq of req) {
|
|
859
|
-
const response = processSingleRequest(singleReq);
|
|
1175
|
+
const response = await processSingleRequest(singleReq);
|
|
860
1176
|
if (response) {
|
|
861
1177
|
responses.push(response);
|
|
862
1178
|
}
|
|
@@ -865,7 +1181,7 @@ rl.on('line', line => {
|
|
|
865
1181
|
console.log(JSON.stringify(responses));
|
|
866
1182
|
}
|
|
867
1183
|
} else {
|
|
868
|
-
const response = processSingleRequest(req);
|
|
1184
|
+
const response = await processSingleRequest(req);
|
|
869
1185
|
if (response) {
|
|
870
1186
|
console.log(JSON.stringify(response));
|
|
871
1187
|
}
|