tribunal-kit 6.0.1 → 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/ARCHITECTURE.md +9 -6
- package/.agent/agents/accessibility-reviewer.md +23 -16
- package/.agent/agents/ai-code-reviewer.md +25 -21
- package/.agent/agents/anti-pattern-reviewer.md +12 -7
- package/.agent/agents/api-architect.md +1 -0
- package/.agent/agents/backend-specialist.md +23 -22
- package/.agent/agents/cloud-engineer.md +1 -0
- package/.agent/agents/code-archaeologist.md +1 -0
- package/.agent/agents/complexity-reviewer.md +10 -7
- package/.agent/agents/database-architect.md +3 -2
- package/.agent/agents/db-latency-auditor.md +6 -2
- package/.agent/agents/debugger.md +3 -2
- package/.agent/agents/dependency-reviewer.md +1 -0
- package/.agent/agents/devops-engineer.md +9 -8
- package/.agent/agents/documentation-writer.md +6 -5
- package/.agent/agents/explorer-agent.md +1 -0
- package/.agent/agents/frontend-reviewer.md +21 -17
- package/.agent/agents/frontend-specialist.md +23 -20
- package/.agent/agents/game-developer.md +1 -0
- package/.agent/agents/interaction-reviewer.md +10 -5
- package/.agent/agents/logic-reviewer.md +3 -0
- package/.agent/agents/minimalist-reviewer.md +6 -0
- package/.agent/agents/mobile-developer.md +7 -6
- package/.agent/agents/mobile-reviewer.md +14 -13
- package/.agent/agents/orchestrator.md +3 -0
- package/.agent/agents/penetration-tester.md +1 -0
- package/.agent/agents/performance-optimizer.md +6 -5
- package/.agent/agents/performance-reviewer.md +6 -6
- package/.agent/agents/pipeline-reviewer.md +144 -0
- package/.agent/agents/precedence-reviewer.md +1 -0
- package/.agent/agents/product-manager.md +1 -0
- package/.agent/agents/product-owner.md +1 -0
- package/.agent/agents/product-reviewer.md +12 -7
- package/.agent/agents/project-planner.md +3 -0
- package/.agent/agents/qa-automation-engineer.md +50 -43
- package/.agent/agents/resilience-reviewer.md +1 -0
- package/.agent/agents/schema-reviewer.md +1 -0
- package/.agent/agents/security-auditor.md +24 -24
- package/.agent/agents/seo-specialist.md +33 -23
- package/.agent/agents/sql-reviewer.md +5 -4
- package/.agent/agents/supervisor-agent.md +12 -2
- package/.agent/agents/swarm-worker-contracts.md +13 -13
- package/.agent/agents/swarm-worker-registry.md +51 -51
- package/.agent/agents/system-architect.md +1 -0
- package/.agent/agents/test-coverage-reviewer.md +25 -22
- package/.agent/agents/test-engineer.md +12 -11
- package/.agent/agents/throughput-optimizer.md +45 -40
- package/.agent/agents/type-safety-reviewer.md +5 -4
- package/.agent/agents/ui-ux-auditor.md +6 -4
- package/.agent/agents/ui-visual-auditor.md +3 -0
- package/.agent/agents/ux-reviewer.md +11 -6
- package/.agent/agents/visual-reviewer.md +11 -6
- package/.agent/agents/vitals-reviewer.md +5 -4
- 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/.memory.idx +1532 -1
- package/.agent/history/memory/MEMORY.md +102 -1
- 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/mcp_config.json +1 -6
- package/.agent/routing_index.json +2033 -263
- package/.agent/rules/GEMINI.md +11 -9
- package/.agent/rules/GEMINI_PLANNER.md +19 -21
- package/.agent/scripts/_colors.js +52 -54
- package/.agent/scripts/_utils.js +52 -53
- package/.agent/scripts/ast_context_loader.js +137 -0
- package/.agent/scripts/auto_preview.js +39 -43
- package/.agent/scripts/bundle_analyzer.js +47 -60
- package/.agent/scripts/case_law_manager.js +200 -294
- package/.agent/scripts/checklist.js +73 -94
- package/.agent/scripts/cicd_validator.js +305 -0
- package/.agent/scripts/context_broker.js +317 -412
- package/.agent/scripts/contract_engine.js +402 -0
- package/.agent/scripts/dependency_analyzer.js +112 -124
- package/.agent/scripts/graph_builder.js +75 -103
- package/.agent/scripts/graph_visualizer.js +10 -12
- package/.agent/scripts/graph_zoom.js +38 -55
- package/.agent/scripts/guardrail_engine.js +195 -145
- package/.agent/scripts/impact_classifier.js +55 -30
- package/.agent/scripts/inner_loop_validator.js +108 -159
- package/.agent/scripts/integrity_manifest.js +59 -67
- package/.agent/scripts/lint_runner.js +65 -75
- package/.agent/scripts/marathon_harness.js +131 -208
- package/.agent/scripts/memory_engine.js +581 -0
- package/.agent/scripts/minify_context.js +29 -33
- package/.agent/scripts/minimal_change_engine.js +95 -87
- package/.agent/scripts/mutation_runner.js +46 -62
- package/.agent/scripts/payload_schemas.js +146 -0
- package/.agent/scripts/pipeline_engine.js +320 -209
- package/.agent/scripts/prompt_compiler.js +166 -93
- package/.agent/scripts/schema_validator.js +73 -121
- package/.agent/scripts/security_scan.js +88 -117
- package/.agent/scripts/session_manager.js +52 -69
- package/.agent/scripts/signal_detector.js +24 -22
- package/.agent/scripts/skill_evolution.js +184 -245
- package/.agent/scripts/skill_integrator.js +35 -48
- package/.agent/scripts/socratic_gate_policy.js +15 -12
- package/.agent/scripts/strengthen_skills.js +29 -33
- package/.agent/scripts/swarm_dispatcher.js +397 -200
- package/.agent/scripts/test_runner.js +54 -56
- package/.agent/scripts/token_budget_broker.js +126 -13
- package/.agent/scripts/trace_engine.js +126 -0
- package/.agent/scripts/verify_all.js +76 -93
- package/.agent/scripts/visual_audit.js +16 -21
- package/.agent/skill_topic_map.json +22 -3
- package/.agent/skills/12-principles-of-animation/SKILL.md +7 -0
- package/.agent/skills/60fps-animation/SKILL.md +7 -0
- package/.agent/skills/accessible-animation/SKILL.md +5 -1
- package/.agent/skills/adapt/SKILL.md +7 -1
- package/.agent/skills/advanced-rag-pipelines/SKILL.md +1 -0
- package/.agent/skills/agent-organizer/SKILL.md +1 -0
- package/.agent/skills/agentic-patterns/SKILL.md +33 -25
- package/.agent/skills/agentic-workflows-2026/SKILL.md +6 -2
- package/.agent/skills/ai-app-hardening/SKILL.md +9 -8
- package/.agent/skills/ai-prompt-injection-defense/SKILL.md +7 -6
- package/.agent/skills/animation-on-scroll/SKILL.md +24 -15
- package/.agent/skills/animation-systems/SKILL.md +11 -10
- package/.agent/skills/antfu-conventions/SKILL.md +7 -2
- package/.agent/skills/api-patterns/SKILL.md +14 -10
- package/.agent/skills/api-security-auditor/SKILL.md +15 -14
- package/.agent/skills/app-builder/SKILL.md +1 -0
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +2 -2
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +12 -12
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +3 -3
- package/.agent/skills/apple-design/SKILL.md +8 -7
- package/.agent/skills/architecture/SKILL.md +3 -2
- package/.agent/skills/audit-and-fix/SKILL.md +8 -5
- package/.agent/skills/authentication-best-practices/SKILL.md +9 -8
- package/.agent/skills/backend-security-expert/SKILL.md +1 -0
- package/.agent/skills/baseline-ui/SKILL.md +8 -7
- package/.agent/skills/bash-linux/SKILL.md +1 -0
- package/.agent/skills/behavioral-modes/SKILL.md +1 -0
- package/.agent/skills/better-colors/SKILL.md +11 -7
- package/.agent/skills/better-typography/SKILL.md +30 -16
- package/.agent/skills/better-ui/SKILL.md +17 -10
- package/.agent/skills/bolder/SKILL.md +6 -0
- package/.agent/skills/brainstorming/SKILL.md +6 -4
- package/.agent/skills/browser-native-ai/SKILL.md +5 -4
- package/.agent/skills/build-primitive/SKILL.md +5 -0
- package/.agent/skills/building-native-ui/SKILL.md +1 -0
- package/.agent/skills/cicd-pro/SKILL.md +2 -1
- package/.agent/skills/clarify/SKILL.md +19 -14
- package/.agent/skills/clean-code/SKILL.md +16 -15
- package/.agent/skills/cloud-architect/SKILL.md +1 -0
- package/.agent/skills/cobejs/SKILL.md +7 -9
- package/.agent/skills/code-review-checklist/SKILL.md +1 -0
- package/.agent/skills/codebase-design/SKILL.md +7 -2
- package/.agent/skills/colorize/SKILL.md +8 -3
- package/.agent/skills/compact-landing/SKILL.md +8 -3
- package/.agent/skills/company-logos/SKILL.md +6 -0
- package/.agent/skills/config-validator/SKILL.md +10 -9
- package/.agent/skills/containerization-pro/SKILL.md +6 -5
- package/.agent/skills/context-engineering-pro/SKILL.md +5 -4
- package/.agent/skills/create-design-md/SKILL.md +13 -5
- package/.agent/skills/critique/SKILL.md +10 -8
- package/.agent/skills/csharp-developer/SKILL.md +1 -0
- package/.agent/skills/data-validation-schemas/SKILL.md +28 -23
- package/.agent/skills/database-design/SKILL.md +2 -1
- package/.agent/skills/delight/SKILL.md +6 -0
- package/.agent/skills/deployment-procedures/SKILL.md +2 -1
- package/.agent/skills/design-lab/SKILL.md +5 -0
- package/.agent/skills/devops-engineer/SKILL.md +3 -2
- package/.agent/skills/devops-incident-responder/SKILL.md +2 -1
- package/.agent/skills/diagnosing-bugs/SKILL.md +12 -2
- package/.agent/skills/distill/SKILL.md +7 -2
- package/.agent/skills/documentation-templates/SKILL.md +3 -2
- package/.agent/skills/domain-modeling/SKILL.md +12 -4
- package/.agent/skills/duckdb-analytical-sql/SKILL.md +7 -3
- package/.agent/skills/edge-ai-mobile/SKILL.md +5 -1
- package/.agent/skills/edge-computing/SKILL.md +9 -8
- package/.agent/skills/emil-design-eng/SKILL.md +43 -27
- package/.agent/skills/error-resilience/SKILL.md +34 -16
- package/.agent/skills/expo-router-v4/SKILL.md +2 -1
- package/.agent/skills/extract-design-system/SKILL.md +12 -11
- package/.agent/skills/fabel-protocol/SKILL.md +24 -17
- package/.agent/skills/fixing-accessibility/SKILL.md +23 -16
- package/.agent/skills/fixing-metadata/SKILL.md +24 -13
- package/.agent/skills/fixing-motion-performance/SKILL.md +7 -5
- package/.agent/skills/framer-motion-expert/SKILL.md +29 -15
- package/.agent/skills/frontend-design/SKILL.md +21 -13
- package/.agent/skills/frontend-security-expert/SKILL.md +1 -0
- package/.agent/skills/game-design-expert/SKILL.md +1 -0
- package/.agent/skills/game-engineering-expert/SKILL.md +1 -0
- package/.agent/skills/generative-ui-expert/SKILL.md +3 -2
- package/.agent/skills/geo-fundamentals/SKILL.md +2 -1
- package/.agent/skills/git-pro/SKILL.md +10 -9
- package/.agent/skills/github-operations/SKILL.md +2 -1
- package/.agent/skills/gpt-taste/SKILL.md +7 -0
- package/.agent/skills/gsap-core/SKILL.md +26 -22
- package/.agent/skills/gsap-frameworks/SKILL.md +6 -5
- package/.agent/skills/gsap-performance/SKILL.md +4 -3
- package/.agent/skills/gsap-plugins/SKILL.md +34 -33
- package/.agent/skills/gsap-react/SKILL.md +9 -8
- package/.agent/skills/gsap-scrolltrigger/SKILL.md +34 -33
- package/.agent/skills/gsap-timeline/SKILL.md +18 -15
- package/.agent/skills/gsap-utils/SKILL.md +25 -24
- package/.agent/skills/harden/SKILL.md +9 -3
- package/.agent/skills/harness-protocol/SKILL.md +1 -0
- package/.agent/skills/i18n-localization/SKILL.md +10 -9
- package/.agent/skills/impeccable/SKILL.md +5 -0
- package/.agent/skills/improve-codebase-architecture/SKILL.md +10 -5
- package/.agent/skills/improve-ui/SKILL.md +12 -5
- package/.agent/skills/intelligent-routing/SKILL.md +7 -6
- package/.agent/skills/knowledge-graph/SKILL.md +1 -0
- package/.agent/skills/landing-page/SKILL.md +1 -0
- package/.agent/skills/lint-and-validate/SKILL.md +9 -4
- package/.agent/skills/llm-engineering/SKILL.md +55 -54
- package/.agent/skills/local-first/SKILL.md +20 -19
- package/.agent/skills/local-first-architecture/SKILL.md +6 -1
- package/.agent/skills/lottie-animation/SKILL.md +7 -3
- package/.agent/skills/marquee-loop/SKILL.md +1 -0
- package/.agent/skills/masked-reveal/SKILL.md +17 -4
- package/.agent/skills/mcp-builder/SKILL.md +13 -10
- package/.agent/skills/micro-interaction/SKILL.md +20 -5
- package/.agent/skills/mobile-design/SKILL.md +26 -15
- package/.agent/skills/monorepo-management/SKILL.md +3 -2
- package/.agent/skills/morphing-icons/SKILL.md +16 -6
- package/.agent/skills/motion-engineering/SKILL.md +19 -15
- package/.agent/skills/nextjs-react-expert/SKILL.md +26 -21
- package/.agent/skills/nodejs-best-practices/SKILL.md +89 -76
- package/.agent/skills/observability/SKILL.md +45 -44
- package/.agent/skills/opentelemetry-observability/SKILL.md +2 -1
- package/.agent/skills/page-transition-animation/SKILL.md +6 -3
- package/.agent/skills/parallel-agents/SKILL.md +7 -2
- package/.agent/skills/performance-profiling/SKILL.md +24 -13
- package/.agent/skills/plan-writing/SKILL.md +1 -0
- package/.agent/skills/platform-engineer/SKILL.md +3 -2
- package/.agent/skills/platform-engineering-opentofu/SKILL.md +1 -0
- package/.agent/skills/playwright-ai-e2e/SKILL.md +3 -2
- package/.agent/skills/playwright-best-practices/SKILL.md +29 -28
- package/.agent/skills/polish/SKILL.md +13 -12
- package/.agent/skills/powershell-windows/SKILL.md +1 -0
- package/.agent/skills/pricing-page/SKILL.md +8 -3
- package/.agent/skills/product-aware-heuristics/SKILL.md +122 -72
- package/.agent/skills/progressive-blur/SKILL.md +9 -4
- package/.agent/skills/project-idioms/SKILL.md +1 -0
- package/.agent/skills/property-based-testing/SKILL.md +10 -12
- package/.agent/skills/python-patterns/SKILL.md +1 -0
- package/.agent/skills/python-pro/SKILL.md +1 -0
- package/.agent/skills/quieter/SKILL.md +6 -0
- package/.agent/skills/react-doctor/SKILL.md +6 -0
- package/.agent/skills/react-specialist/SKILL.md +32 -28
- package/.agent/skills/readme-builder/SKILL.md +1 -0
- package/.agent/skills/realtime-patterns/SKILL.md +34 -33
- package/.agent/skills/red-team-tactics/SKILL.md +1 -0
- package/.agent/skills/redesign-skill/SKILL.md +6 -0
- package/.agent/skills/review-animations/SKILL.md +5 -2
- package/.agent/skills/review-animations/STANDARDS.md +37 -23
- package/.agent/skills/rust-pro/SKILL.md +1 -0
- package/.agent/skills/seo-fundamentals/SKILL.md +4 -3
- package/.agent/skills/server-management/SKILL.md +1 -0
- package/.agent/skills/shadcn-ui-expert/SKILL.md +28 -22
- package/.agent/skills/shape/SKILL.md +9 -2
- package/.agent/skills/skill-creator/SKILL.md +1 -0
- package/.agent/skills/soft-skill/SKILL.md +6 -0
- package/.agent/skills/sounds-on-the-web/SKILL.md +1 -0
- package/.agent/skills/sql-pro/SKILL.md +1 -0
- package/.agent/skills/supabase-postgres-best-practices/SKILL.md +1 -0
- package/.agent/skills/svg-animation/SKILL.md +16 -7
- package/.agent/skills/swiftui-expert/SKILL.md +1 -0
- package/.agent/skills/swiss-design/SKILL.md +5 -0
- package/.agent/skills/system-design-pro/SKILL.md +1 -0
- package/.agent/skills/systematic-debugging/SKILL.md +1 -0
- package/.agent/skills/tailwind-patterns/SKILL.md +25 -11
- package/.agent/skills/taste-skill/SKILL.md +6 -0
- package/.agent/skills/tdd-workflow/SKILL.md +5 -0
- package/.agent/skills/test-result-analyzer/SKILL.md +1 -0
- package/.agent/skills/testing-patterns/SKILL.md +123 -115
- package/.agent/skills/thermo-nuclear-code-quality-review/SKILL.md +5 -0
- package/.agent/skills/thinking-protocol/SKILL.md +3 -0
- package/.agent/skills/to-spring-or-not-to-spring/SKILL.md +9 -8
- package/.agent/skills/transitions-dev/SKILL.md +19 -6
- package/.agent/skills/trend-researcher/SKILL.md +1 -0
- package/.agent/skills/typescript-advanced/SKILL.md +23 -18
- package/.agent/skills/typeset/SKILL.md +10 -1
- package/.agent/skills/ui-reasoning-engine/SKILL.md +67 -48
- package/.agent/skills/ui-skill-packs/SKILL.md +6 -1
- package/.agent/skills/ui-skills-root/SKILL.md +39 -38
- package/.agent/skills/ui-ux-pro-max/SKILL.md +34 -26
- package/.agent/skills/ui-ux-researcher/SKILL.md +1 -0
- package/.agent/skills/vector-search-pgvector/SKILL.md +3 -2
- package/.agent/skills/vue-expert/SKILL.md +22 -19
- package/.agent/skills/vulnerability-scanner/SKILL.md +22 -21
- package/.agent/skills/web-accessibility-auditor/SKILL.md +2 -1
- package/.agent/skills/web-design-guidelines/SKILL.md +16 -10
- package/.agent/skills/web-quality-audit/SKILL.md +5 -0
- package/.agent/skills/webapp-testing/SKILL.md +14 -13
- package/.agent/skills/webgpu-performance/SKILL.md +1 -0
- package/.agent/skills/whimsy-injector/SKILL.md +9 -5
- package/.agent/skills/workflow-optimizer/SKILL.md +1 -0
- package/.agent/skills/zero-trust-passkeys/SKILL.md +11 -6
- package/.agent/templates/DESIGN.md +119 -110
- package/.agent/templates/design-tokens.json +9 -6
- package/.agent/workflows/acf.md +1 -0
- package/.agent/workflows/api-tester.md +1 -0
- package/.agent/workflows/audit.md +1 -0
- package/.agent/workflows/brainstorm.md +1 -0
- package/.agent/workflows/changelog.md +1 -0
- package/.agent/workflows/contract.md +60 -0
- package/.agent/workflows/create.md +1 -0
- package/.agent/workflows/debug.md +1 -0
- package/.agent/workflows/deploy.md +1 -0
- package/.agent/workflows/enhance.md +1 -0
- package/.agent/workflows/fix-ci.md +89 -0
- package/.agent/workflows/fix.md +1 -0
- package/.agent/workflows/generate.md +1 -0
- package/.agent/workflows/marathon.md +1 -0
- package/.agent/workflows/migrate.md +1 -0
- package/.agent/workflows/minimal.md +9 -7
- package/.agent/workflows/orchestrate.md +1 -0
- package/.agent/workflows/performance-benchmarker.md +1 -0
- package/.agent/workflows/pipeline.md +26 -21
- package/.agent/workflows/plan.md +1 -0
- package/.agent/workflows/preview.md +1 -0
- package/.agent/workflows/refactor.md +3 -2
- package/.agent/workflows/review-ai.md +4 -3
- package/.agent/workflows/review.md +1 -0
- package/.agent/workflows/session.md +1 -0
- package/.agent/workflows/status.md +1 -0
- package/.agent/workflows/strengthen-skills.md +1 -0
- package/.agent/workflows/super-prompt.md +1 -0
- package/.agent/workflows/swarm.md +15 -3
- package/.agent/workflows/test.md +8 -7
- package/.agent/workflows/tribunal-backend.md +3 -2
- package/.agent/workflows/tribunal-cicd.md +104 -0
- package/.agent/workflows/tribunal-database.md +1 -0
- package/.agent/workflows/tribunal-frontend.md +8 -6
- package/.agent/workflows/tribunal-full.md +2 -1
- package/.agent/workflows/tribunal-mobile.md +6 -5
- package/.agent/workflows/tribunal-performance.md +1 -0
- package/.agent/workflows/tribunal-speed.md +1 -0
- package/.agent/workflows/tribunal-ui.md +29 -21
- package/.agent/workflows/ui-ux-pro-max.md +19 -15
- package/.claude/CLAUDE.md +442 -0
- package/CONTRIBUTING.md +3 -3
- package/README.md +105 -45
- package/SECURITY.md +11 -11
- package/bin/adapter-install.js +240 -0
- package/bin/global-store.js +48 -0
- package/bin/mcp-server.js +781 -332
- package/bin/proxy-server.js +113 -0
- package/bin/spawn-agent.js +39 -0
- package/bin/tk-proxy.js +34 -0
- package/bin/tribunal-kit.js +29 -30
- package/bin/wrapper.js +40 -46
- package/dist/cli.js +6 -0
- package/dist/commands/case.js +2 -0
- package/dist/commands/contract.js +440 -0
- package/dist/commands/init.js +8 -51
- package/dist/commands/status.js +61 -30
- package/dist/commands/validate.js +22 -31
- package/dist/index.d.ts +8 -1
- 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 +33 -15
- package/scripts/benchmark.js +62 -86
- package/scripts/build-graph.js +71 -0
- package/scripts/changelog.js +67 -73
- package/scripts/fix-vbc.js +13 -15
- package/scripts/fix-vbc.ps1 +2 -118
- package/scripts/stress_benchmark.js +358 -0
- package/scripts/sync-version.js +71 -41
- package/scripts/validate-payload.js +23 -30
- package/scripts/visual_audit.js +23 -13
- package/.agent/history/snapshots/migrate_refs.js.json +0 -11
- package/.agent/scripts/compile_router.py +0 -112
- package/.agent/scripts/migrate_skills_frontmatter.py +0 -64
package/bin/mcp-server.js
CHANGED
|
@@ -13,16 +13,79 @@
|
|
|
13
13
|
* Protocol: MCP 2024-11-05 over JSON-RPC 2.0 / stdio
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
const path = require(
|
|
17
|
-
const { spawnSync } = require(
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const { spawnSync } = require('child_process');
|
|
18
18
|
|
|
19
|
-
const PKG = require(path.resolve(__dirname,
|
|
19
|
+
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();
|
|
78
|
+
|
|
79
|
+
class RpcError extends Error {
|
|
80
|
+
constructor(code, message) {
|
|
81
|
+
super(message);
|
|
82
|
+
this.code = code;
|
|
83
|
+
this.name = 'RpcError';
|
|
84
|
+
}
|
|
85
|
+
}
|
|
23
86
|
|
|
24
87
|
// Minimal JSON-RPC 2.0 over stdio
|
|
25
|
-
const readline = require(
|
|
88
|
+
const readline = require('readline');
|
|
26
89
|
|
|
27
90
|
const rl = readline.createInterface({
|
|
28
91
|
input: process.stdin,
|
|
@@ -36,17 +99,12 @@ const rl = readline.createInterface({
|
|
|
36
99
|
* explicitly supplied payload and schema.
|
|
37
100
|
*/
|
|
38
101
|
function runTribunalAudit() {
|
|
39
|
-
const fs = require(
|
|
102
|
+
const fs = require('fs');
|
|
40
103
|
const projectRoot = process.cwd();
|
|
41
|
-
const manifestScript = path.join(
|
|
42
|
-
projectRoot,
|
|
43
|
-
".agent",
|
|
44
|
-
"scripts",
|
|
45
|
-
"integrity_manifest.js",
|
|
46
|
-
);
|
|
104
|
+
const manifestScript = path.join(projectRoot, '.agent', 'scripts', 'integrity_manifest.js');
|
|
47
105
|
|
|
48
106
|
if (!fs.existsSync(manifestScript)) {
|
|
49
|
-
return
|
|
107
|
+
return 'Error: .agent/scripts/integrity_manifest.js was not found. Run `tk init` first.';
|
|
50
108
|
}
|
|
51
109
|
|
|
52
110
|
try {
|
|
@@ -56,7 +114,7 @@ function runTribunalAudit() {
|
|
|
56
114
|
|
|
57
115
|
const { integrity } = manifest;
|
|
58
116
|
const lines = [
|
|
59
|
-
|
|
117
|
+
'Tribunal audit complete.',
|
|
60
118
|
`Agents: ${manifest.agents.total} (${manifest.agents.reviewer_count} reviewers)`,
|
|
61
119
|
`Skills: ${manifest.skills.total}`,
|
|
62
120
|
`Scripts: ${manifest.scripts.total}`,
|
|
@@ -66,11 +124,13 @@ function runTribunalAudit() {
|
|
|
66
124
|
];
|
|
67
125
|
|
|
68
126
|
if (integrity.phantom_references > 0 || integrity.invalid_claims > 0) {
|
|
69
|
-
lines.push(
|
|
127
|
+
lines.push(
|
|
128
|
+
'Audit found integrity issues; run `tk guardrail --scan` for remediation details.',
|
|
129
|
+
);
|
|
70
130
|
} else {
|
|
71
|
-
lines.push(
|
|
131
|
+
lines.push('All discovered references and global asset-count claims are valid.');
|
|
72
132
|
}
|
|
73
|
-
return lines.join(
|
|
133
|
+
return lines.join('\n');
|
|
74
134
|
} catch (error) {
|
|
75
135
|
return `Audit failed: ${error.message}`;
|
|
76
136
|
}
|
|
@@ -80,100 +140,96 @@ function runTribunalAudit() {
|
|
|
80
140
|
* Search case law in an isolated process because its CLI owns persistent state.
|
|
81
141
|
*/
|
|
82
142
|
function searchCaseLaw(query) {
|
|
83
|
-
const caseLawScript = path.resolve(
|
|
84
|
-
__dirname,
|
|
85
|
-
"../.agent/scripts/case_law_manager.js",
|
|
86
|
-
);
|
|
143
|
+
const caseLawScript = path.resolve(__dirname, '../.agent/scripts/case_law_manager.js');
|
|
87
144
|
// case_law_manager is a standalone stateful CLI, so retain its process boundary.
|
|
88
|
-
const result = spawnSync(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
encoding: "utf8",
|
|
93
|
-
timeout: SPAWN_TIMEOUT_MS,
|
|
94
|
-
},
|
|
95
|
-
);
|
|
145
|
+
const result = spawnSync(process.execPath, [caseLawScript, 'search-cases', '--query', query], {
|
|
146
|
+
encoding: 'utf8',
|
|
147
|
+
timeout: SPAWN_TIMEOUT_MS,
|
|
148
|
+
});
|
|
96
149
|
if (result.error) {
|
|
97
|
-
if (result.error.code ===
|
|
150
|
+
if (result.error.code === 'ETIMEDOUT')
|
|
151
|
+
return 'Error: Case law search timed out (exceeded 30s limit)';
|
|
98
152
|
return `Error executing case law search: ${result.error.message}`;
|
|
99
153
|
}
|
|
100
|
-
return result.stdout || result.stderr ||
|
|
154
|
+
return result.stdout || result.stderr || 'No results';
|
|
101
155
|
}
|
|
102
156
|
|
|
103
|
-
|
|
104
157
|
function stripBoilerplate(text) {
|
|
105
158
|
if (!text) return text;
|
|
106
|
-
let minified = text.replace(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
159
|
+
let minified = text.replace(
|
|
160
|
+
/AI coding assistants often fall into specific bad habits[\s\S]*$/g,
|
|
161
|
+
'',
|
|
162
|
+
);
|
|
163
|
+
minified = minified.replace(/## 🤖 LLM-Specific Traps[\s\S]*$/g, '');
|
|
164
|
+
minified = minified.replace(/## 🏛️ Tribunal Integration[\s\S]*$/g, '');
|
|
165
|
+
minified = minified.replace(/## Pre-Flight Checklist[\s\S]*$/g, '');
|
|
110
166
|
return minified.trim();
|
|
111
167
|
}
|
|
112
168
|
|
|
113
169
|
function getAgentDir() {
|
|
114
|
-
const fs = require(
|
|
115
|
-
const local = path.join(process.cwd(),
|
|
170
|
+
const fs = require('fs');
|
|
171
|
+
const local = path.join(process.cwd(), '.agent');
|
|
116
172
|
if (fs.existsSync(local)) return local;
|
|
117
|
-
return path.resolve(__dirname,
|
|
173
|
+
return path.resolve(__dirname, '../.agent');
|
|
118
174
|
}
|
|
119
175
|
|
|
120
|
-
function handleRequest(req) {
|
|
121
|
-
const fs = require(
|
|
122
|
-
if (req.method ===
|
|
176
|
+
async function handleRequest(req) {
|
|
177
|
+
const fs = require('fs');
|
|
178
|
+
if (req.method === 'notifications/initialized' || req.method === 'notifications/cancelled') {
|
|
123
179
|
return null;
|
|
124
180
|
}
|
|
125
|
-
if (req.method ===
|
|
181
|
+
if (req.method === 'ping') {
|
|
126
182
|
return {};
|
|
127
183
|
}
|
|
128
184
|
|
|
129
185
|
// MCP spec: method names follow path-style convention
|
|
130
|
-
if (req.method ===
|
|
186
|
+
if (req.method === 'initialize') {
|
|
131
187
|
return {
|
|
132
|
-
protocolVersion:
|
|
188
|
+
protocolVersion: '2025-03-26',
|
|
133
189
|
capabilities: {
|
|
134
190
|
tools: {},
|
|
135
191
|
resources: { subscribe: false, listChanged: false },
|
|
136
192
|
prompts: { listChanged: false },
|
|
137
193
|
},
|
|
138
194
|
serverInfo: {
|
|
139
|
-
name:
|
|
195
|
+
name: 'tribunal-kit-mcp',
|
|
140
196
|
version: PKG.version,
|
|
141
197
|
},
|
|
142
198
|
};
|
|
143
199
|
}
|
|
144
200
|
|
|
145
|
-
if (req.method ===
|
|
201
|
+
if (req.method === 'resources/list') {
|
|
146
202
|
const agentDir = getAgentDir();
|
|
147
203
|
const resources = [];
|
|
148
|
-
|
|
204
|
+
|
|
149
205
|
// Agents
|
|
150
|
-
const agentsDir = path.join(agentDir,
|
|
206
|
+
const agentsDir = path.join(agentDir, 'agents');
|
|
151
207
|
if (fs.existsSync(agentsDir)) {
|
|
152
|
-
const files = fs.readdirSync(agentsDir).filter(
|
|
208
|
+
const files = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md'));
|
|
153
209
|
for (const f of files) {
|
|
154
|
-
const name = path.basename(f,
|
|
210
|
+
const name = path.basename(f, '.md');
|
|
155
211
|
resources.push({
|
|
156
212
|
uri: `tribunal://agent/${name}`,
|
|
157
213
|
name: `Agent: ${name}`,
|
|
158
214
|
description: `Tribunal Specialist Agent rule file for ${name}`,
|
|
159
|
-
mimeType:
|
|
215
|
+
mimeType: 'text/markdown',
|
|
160
216
|
});
|
|
161
217
|
}
|
|
162
218
|
}
|
|
163
219
|
|
|
164
220
|
// Skills
|
|
165
|
-
const skillsDir = path.join(agentDir,
|
|
221
|
+
const skillsDir = path.join(agentDir, 'skills');
|
|
166
222
|
if (fs.existsSync(skillsDir)) {
|
|
167
223
|
const dirs = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
168
224
|
for (const d of dirs) {
|
|
169
225
|
if (d.isDirectory()) {
|
|
170
|
-
const skillFile = path.join(skillsDir, d.name,
|
|
226
|
+
const skillFile = path.join(skillsDir, d.name, 'SKILL.md');
|
|
171
227
|
if (fs.existsSync(skillFile)) {
|
|
172
228
|
resources.push({
|
|
173
229
|
uri: `tribunal://skill/${d.name}`,
|
|
174
230
|
name: `Skill: ${d.name}`,
|
|
175
231
|
description: `Tribunal Skill instruction file for ${d.name}`,
|
|
176
|
-
mimeType:
|
|
232
|
+
mimeType: 'text/markdown',
|
|
177
233
|
});
|
|
178
234
|
}
|
|
179
235
|
}
|
|
@@ -181,16 +237,16 @@ function handleRequest(req) {
|
|
|
181
237
|
}
|
|
182
238
|
|
|
183
239
|
// Workflows
|
|
184
|
-
const workflowsDir = path.join(agentDir,
|
|
240
|
+
const workflowsDir = path.join(agentDir, 'workflows');
|
|
185
241
|
if (fs.existsSync(workflowsDir)) {
|
|
186
|
-
const files = fs.readdirSync(workflowsDir).filter(
|
|
242
|
+
const files = fs.readdirSync(workflowsDir).filter(f => f.endsWith('.md'));
|
|
187
243
|
for (const f of files) {
|
|
188
|
-
const name = path.basename(f,
|
|
244
|
+
const name = path.basename(f, '.md');
|
|
189
245
|
resources.push({
|
|
190
246
|
uri: `tribunal://workflow/${name}`,
|
|
191
247
|
name: `Workflow: ${name}`,
|
|
192
248
|
description: `Tribunal Workflow guide for ${name}`,
|
|
193
|
-
mimeType:
|
|
249
|
+
mimeType: 'text/markdown',
|
|
194
250
|
});
|
|
195
251
|
}
|
|
196
252
|
}
|
|
@@ -198,55 +254,55 @@ function handleRequest(req) {
|
|
|
198
254
|
return { resources };
|
|
199
255
|
}
|
|
200
256
|
|
|
201
|
-
if (req.method ===
|
|
257
|
+
if (req.method === 'resources/read') {
|
|
202
258
|
const uri = req.params && req.params.uri;
|
|
203
|
-
if (!uri) throw new Error(
|
|
259
|
+
if (!uri) throw new Error('Missing uri parameter');
|
|
204
260
|
const agentDir = getAgentDir();
|
|
205
261
|
let filePath = null;
|
|
206
262
|
|
|
207
|
-
if (uri.startsWith(
|
|
208
|
-
const name = uri.replace(
|
|
209
|
-
filePath = path.join(agentDir,
|
|
210
|
-
} else if (uri.startsWith(
|
|
211
|
-
const name = uri.replace(
|
|
212
|
-
filePath = path.join(agentDir,
|
|
213
|
-
} else if (uri.startsWith(
|
|
214
|
-
const name = uri.replace(
|
|
215
|
-
filePath = path.join(agentDir,
|
|
263
|
+
if (uri.startsWith('tribunal://agent/')) {
|
|
264
|
+
const name = uri.replace('tribunal://agent/', '');
|
|
265
|
+
filePath = path.join(agentDir, 'agents', `${name}.md`);
|
|
266
|
+
} else if (uri.startsWith('tribunal://skill/')) {
|
|
267
|
+
const name = uri.replace('tribunal://skill/', '');
|
|
268
|
+
filePath = path.join(agentDir, 'skills', name, 'SKILL.md');
|
|
269
|
+
} else if (uri.startsWith('tribunal://workflow/')) {
|
|
270
|
+
const name = uri.replace('tribunal://workflow/', '');
|
|
271
|
+
filePath = path.join(agentDir, 'workflows', `${name}.md`);
|
|
216
272
|
}
|
|
217
273
|
|
|
218
274
|
if (!filePath || !fs.existsSync(filePath)) {
|
|
219
275
|
throw new Error(`Resource not found: ${uri}`);
|
|
220
276
|
}
|
|
221
277
|
|
|
222
|
-
const text = fs.readFileSync(filePath,
|
|
278
|
+
const text = fs.readFileSync(filePath, 'utf8');
|
|
223
279
|
return {
|
|
224
280
|
contents: [
|
|
225
281
|
{
|
|
226
282
|
uri,
|
|
227
|
-
mimeType:
|
|
283
|
+
mimeType: 'text/markdown',
|
|
228
284
|
text,
|
|
229
285
|
},
|
|
230
286
|
],
|
|
231
287
|
};
|
|
232
288
|
}
|
|
233
289
|
|
|
234
|
-
if (req.method ===
|
|
290
|
+
if (req.method === 'prompts/list') {
|
|
235
291
|
const agentDir = getAgentDir();
|
|
236
292
|
const prompts = [];
|
|
237
|
-
const workflowsDir = path.join(agentDir,
|
|
293
|
+
const workflowsDir = path.join(agentDir, 'workflows');
|
|
238
294
|
|
|
239
295
|
if (fs.existsSync(workflowsDir)) {
|
|
240
|
-
const files = fs.readdirSync(workflowsDir).filter(
|
|
296
|
+
const files = fs.readdirSync(workflowsDir).filter(f => f.endsWith('.md'));
|
|
241
297
|
for (const f of files) {
|
|
242
|
-
const name = path.basename(f,
|
|
298
|
+
const name = path.basename(f, '.md');
|
|
243
299
|
prompts.push({
|
|
244
300
|
name,
|
|
245
301
|
description: `Execute tribunal workflow /${name}`,
|
|
246
302
|
arguments: [
|
|
247
303
|
{
|
|
248
|
-
name:
|
|
249
|
-
description:
|
|
304
|
+
name: 'task',
|
|
305
|
+
description: 'The task or target file to execute the workflow against',
|
|
250
306
|
required: false,
|
|
251
307
|
},
|
|
252
308
|
],
|
|
@@ -257,26 +313,26 @@ function handleRequest(req) {
|
|
|
257
313
|
return { prompts };
|
|
258
314
|
}
|
|
259
315
|
|
|
260
|
-
if (req.method ===
|
|
316
|
+
if (req.method === 'prompts/get') {
|
|
261
317
|
const name = req.params && req.params.name;
|
|
262
|
-
const task = (req.params && req.params.arguments && req.params.arguments.task) ||
|
|
263
|
-
if (!name) throw new Error(
|
|
318
|
+
const task = (req.params && req.params.arguments && req.params.arguments.task) || '';
|
|
319
|
+
if (!name) throw new Error('Missing prompt name parameter');
|
|
264
320
|
|
|
265
321
|
const agentDir = getAgentDir();
|
|
266
|
-
const workflowPath = path.join(agentDir,
|
|
322
|
+
const workflowPath = path.join(agentDir, 'workflows', `${name}.md`);
|
|
267
323
|
if (!fs.existsSync(workflowPath)) {
|
|
268
324
|
throw new Error(`Prompt workflow not found: ${name}`);
|
|
269
325
|
}
|
|
270
326
|
|
|
271
|
-
const content = fs.readFileSync(workflowPath,
|
|
327
|
+
const content = fs.readFileSync(workflowPath, 'utf8');
|
|
272
328
|
const promptText = task ? `${content}\n\nTarget Task/File: ${task}` : content;
|
|
273
329
|
|
|
274
330
|
return {
|
|
275
331
|
messages: [
|
|
276
332
|
{
|
|
277
|
-
role:
|
|
333
|
+
role: 'user',
|
|
278
334
|
content: {
|
|
279
|
-
type:
|
|
335
|
+
type: 'text',
|
|
280
336
|
text: promptText,
|
|
281
337
|
},
|
|
282
338
|
},
|
|
@@ -284,168 +340,224 @@ function handleRequest(req) {
|
|
|
284
340
|
};
|
|
285
341
|
}
|
|
286
342
|
|
|
287
|
-
if (req.method ===
|
|
343
|
+
if (req.method === 'tools/list') {
|
|
288
344
|
return {
|
|
289
345
|
tools: [
|
|
290
346
|
{
|
|
291
|
-
name:
|
|
292
|
-
description:
|
|
293
|
-
"Runs a full anti-hallucination audit across the workspace.",
|
|
347
|
+
name: 'run_tribunal_audit',
|
|
348
|
+
description: 'Runs a full anti-hallucination audit across the workspace.',
|
|
294
349
|
inputSchema: {
|
|
295
|
-
type:
|
|
350
|
+
type: 'object',
|
|
296
351
|
properties: {},
|
|
297
352
|
additionalProperties: false,
|
|
298
353
|
},
|
|
299
354
|
},
|
|
300
355
|
{
|
|
301
|
-
name:
|
|
302
|
-
description:
|
|
303
|
-
"Synchronize IDE bridge files with the current GEMINI.md rules.",
|
|
356
|
+
name: 'sync_ide_bridges',
|
|
357
|
+
description: 'Synchronize IDE bridge files with the current GEMINI.md rules.',
|
|
304
358
|
inputSchema: {
|
|
305
|
-
type:
|
|
359
|
+
type: 'object',
|
|
306
360
|
properties: {},
|
|
307
361
|
additionalProperties: false,
|
|
308
362
|
},
|
|
309
363
|
},
|
|
310
364
|
{
|
|
311
|
-
name:
|
|
365
|
+
name: 'search_case_law',
|
|
312
366
|
description:
|
|
313
|
-
|
|
367
|
+
'Search historical code rejections and legal precedent. Use this before writing code to avoid past mistakes.',
|
|
314
368
|
inputSchema: {
|
|
315
|
-
type:
|
|
369
|
+
type: 'object',
|
|
316
370
|
properties: {
|
|
317
371
|
query: {
|
|
318
|
-
type:
|
|
372
|
+
type: 'string',
|
|
319
373
|
description: "Search query (e.g. 'useEffect state')",
|
|
320
374
|
},
|
|
321
375
|
},
|
|
322
|
-
required: [
|
|
376
|
+
required: ['query'],
|
|
323
377
|
additionalProperties: false,
|
|
324
378
|
},
|
|
325
379
|
},
|
|
326
380
|
{
|
|
327
|
-
name:
|
|
328
|
-
description:
|
|
381
|
+
name: 'list_tribunal_agents',
|
|
382
|
+
description: 'List all available Tribunal Kit agents.',
|
|
329
383
|
inputSchema: {
|
|
330
|
-
type:
|
|
384
|
+
type: 'object',
|
|
331
385
|
properties: {},
|
|
332
386
|
additionalProperties: false,
|
|
333
387
|
},
|
|
334
388
|
},
|
|
335
389
|
{
|
|
336
|
-
name:
|
|
337
|
-
description:
|
|
390
|
+
name: 'get_tribunal_agent',
|
|
391
|
+
description: 'Get the full markdown rules for a specific Tribunal agent.',
|
|
338
392
|
inputSchema: {
|
|
339
|
-
type:
|
|
393
|
+
type: 'object',
|
|
340
394
|
properties: {
|
|
341
|
-
name: { type:
|
|
395
|
+
name: { type: 'string', description: "The agent name (e.g. 'frontend-specialist')" },
|
|
342
396
|
},
|
|
343
|
-
required: [
|
|
397
|
+
required: ['name'],
|
|
344
398
|
additionalProperties: false,
|
|
345
399
|
},
|
|
346
400
|
},
|
|
347
401
|
{
|
|
348
|
-
name:
|
|
349
|
-
description:
|
|
402
|
+
name: 'list_tribunal_skills',
|
|
403
|
+
description: 'List all available Tribunal Kit skills.',
|
|
350
404
|
inputSchema: {
|
|
351
|
-
type:
|
|
405
|
+
type: 'object',
|
|
352
406
|
properties: {},
|
|
353
407
|
additionalProperties: false,
|
|
354
408
|
},
|
|
355
409
|
},
|
|
356
410
|
{
|
|
357
|
-
name:
|
|
358
|
-
description:
|
|
411
|
+
name: 'get_tribunal_skill',
|
|
412
|
+
description: 'Get the full markdown instructions for a specific Tribunal skill.',
|
|
359
413
|
inputSchema: {
|
|
360
|
-
type:
|
|
414
|
+
type: 'object',
|
|
361
415
|
properties: {
|
|
362
|
-
name: { type:
|
|
416
|
+
name: { type: 'string', description: "The skill name (e.g. 'react-specialist')" },
|
|
363
417
|
},
|
|
364
|
-
required: [
|
|
418
|
+
required: ['name'],
|
|
365
419
|
additionalProperties: false,
|
|
366
420
|
},
|
|
367
421
|
},
|
|
368
422
|
{
|
|
369
|
-
name:
|
|
370
|
-
description:
|
|
423
|
+
name: 'recall_memory',
|
|
424
|
+
description:
|
|
425
|
+
'Budget-constrained memory recall from the 4-Type Taxonomy Persistent Memory Engine. Returns the most relevant memories that fit within the token budget, ranked by relevance × recency × priority. Use this BEFORE writing code to recall project guidelines without bloating context.',
|
|
371
426
|
inputSchema: {
|
|
372
|
-
type:
|
|
427
|
+
type: 'object',
|
|
373
428
|
properties: {
|
|
374
429
|
query: {
|
|
375
|
-
type:
|
|
430
|
+
type: 'string',
|
|
376
431
|
description: "Search query (e.g. 'database', 'auth', 'deploy')",
|
|
377
432
|
},
|
|
378
433
|
budget: {
|
|
379
|
-
type:
|
|
380
|
-
description:
|
|
434
|
+
type: 'number',
|
|
435
|
+
description:
|
|
436
|
+
'Maximum token budget for recall (default: 2000). Only the top-ranked memories that fit within this budget are returned.',
|
|
381
437
|
},
|
|
382
438
|
},
|
|
383
|
-
required: [
|
|
439
|
+
required: ['query'],
|
|
384
440
|
additionalProperties: false,
|
|
385
441
|
},
|
|
386
442
|
},
|
|
387
443
|
{
|
|
388
|
-
name:
|
|
389
|
-
description:
|
|
444
|
+
name: 'store_memory',
|
|
445
|
+
description:
|
|
446
|
+
'Store a new memory entry in the 4-Type Taxonomy Persistent Memory Engine. Memories are schema-validated and persisted across sessions. Types: semantic (permanent facts), procedural (how-to recipes), episodic (30-day TTL events), working (session scratch).',
|
|
390
447
|
inputSchema: {
|
|
391
|
-
type:
|
|
448
|
+
type: 'object',
|
|
392
449
|
properties: {
|
|
393
450
|
type: {
|
|
394
|
-
type:
|
|
395
|
-
enum: [
|
|
396
|
-
description:
|
|
451
|
+
type: 'string',
|
|
452
|
+
enum: ['semantic', 'procedural', 'episodic', 'working'],
|
|
453
|
+
description:
|
|
454
|
+
'Memory type: semantic (facts), procedural (recipes), episodic (events), working (scratch)',
|
|
397
455
|
},
|
|
398
456
|
content: {
|
|
399
|
-
type:
|
|
400
|
-
description:
|
|
457
|
+
type: 'string',
|
|
458
|
+
description: 'The memory content to store',
|
|
401
459
|
},
|
|
402
460
|
tags: {
|
|
403
|
-
type:
|
|
404
|
-
items: { type:
|
|
405
|
-
description:
|
|
461
|
+
type: 'array',
|
|
462
|
+
items: { type: 'string' },
|
|
463
|
+
description: 'Searchable tags for this memory',
|
|
406
464
|
},
|
|
407
465
|
},
|
|
408
|
-
required: [
|
|
466
|
+
required: ['type', 'content'],
|
|
409
467
|
additionalProperties: false,
|
|
410
468
|
},
|
|
411
469
|
},
|
|
412
470
|
{
|
|
413
|
-
name:
|
|
414
|
-
description:
|
|
471
|
+
name: 'get_sparse_context',
|
|
472
|
+
description:
|
|
473
|
+
'Get a JIT, token-optimized context prompt tailored to the active task and files. Uses the Context Density Broker to score and select relevant skills, stripping duplicate boilerplate and saving up to 85% in prompt tokens.',
|
|
415
474
|
inputSchema: {
|
|
416
|
-
type:
|
|
475
|
+
type: 'object',
|
|
417
476
|
properties: {
|
|
418
477
|
task: {
|
|
419
|
-
type:
|
|
478
|
+
type: 'string',
|
|
420
479
|
description: "The user task description (e.g. 'JWT auth API')",
|
|
421
480
|
},
|
|
422
481
|
files: {
|
|
423
|
-
type:
|
|
424
|
-
items: { type:
|
|
482
|
+
type: 'array',
|
|
483
|
+
items: { type: 'string' },
|
|
425
484
|
description: "List of files being touched (e.g. ['src/auth.js'])",
|
|
426
485
|
},
|
|
427
486
|
model: {
|
|
428
|
-
type:
|
|
429
|
-
enum: [
|
|
430
|
-
description:
|
|
487
|
+
type: 'string',
|
|
488
|
+
enum: ['large', 'small'],
|
|
489
|
+
description:
|
|
490
|
+
'Model tier: large (default, includes key rules of supplementary skills) or small (essential skills only)',
|
|
431
491
|
},
|
|
432
492
|
},
|
|
433
|
-
required: [
|
|
493
|
+
required: ['task'],
|
|
434
494
|
additionalProperties: false,
|
|
435
495
|
},
|
|
436
496
|
},
|
|
437
497
|
{
|
|
438
|
-
name:
|
|
439
|
-
description:
|
|
498
|
+
name: 'align_output',
|
|
499
|
+
description:
|
|
500
|
+
'Align model outputs to Fabel-5 constraints: strips conversational introductions and conclusions, collapses single/double bullet items to prose, and checks for code traps (unawaited dynamic functions in Next.js 15, deprecated hooks in React 19, or non-existent models).',
|
|
440
501
|
inputSchema: {
|
|
441
|
-
type:
|
|
502
|
+
type: 'object',
|
|
442
503
|
properties: {
|
|
443
504
|
text: {
|
|
444
|
-
type:
|
|
445
|
-
description:
|
|
505
|
+
type: 'string',
|
|
506
|
+
description: 'The raw output text generated by the model to be aligned.',
|
|
446
507
|
},
|
|
447
508
|
},
|
|
448
|
-
required: [
|
|
509
|
+
required: ['text'],
|
|
510
|
+
additionalProperties: false,
|
|
511
|
+
},
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
name: 'verify_contracts',
|
|
515
|
+
description:
|
|
516
|
+
'Verify proposed code changes against project behavioral contracts. Use BEFORE writing code to ensure compliance with team conventions.',
|
|
517
|
+
inputSchema: {
|
|
518
|
+
type: 'object',
|
|
519
|
+
properties: {
|
|
520
|
+
file: {
|
|
521
|
+
type: 'string',
|
|
522
|
+
description: "Relative or absolute file path to verify (e.g. 'src/api/user.ts')",
|
|
523
|
+
},
|
|
524
|
+
content: {
|
|
525
|
+
type: 'string',
|
|
526
|
+
description: 'Proposed file content to verify against loaded contracts',
|
|
527
|
+
},
|
|
528
|
+
},
|
|
529
|
+
required: ['file', 'content'],
|
|
530
|
+
additionalProperties: false,
|
|
531
|
+
},
|
|
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'],
|
|
449
561
|
additionalProperties: false,
|
|
450
562
|
},
|
|
451
563
|
},
|
|
@@ -453,253 +565,590 @@ function handleRequest(req) {
|
|
|
453
565
|
};
|
|
454
566
|
}
|
|
455
567
|
|
|
456
|
-
if (req.method ===
|
|
568
|
+
if (req.method === 'tools/call') {
|
|
457
569
|
const toolName = req.params && req.params.name;
|
|
570
|
+
const argsObj = req.params && req.params.arguments;
|
|
458
571
|
if (!toolName) {
|
|
459
|
-
throw
|
|
460
|
-
code: -32602,
|
|
461
|
-
message: "Missing required parameter: params.name",
|
|
462
|
-
};
|
|
572
|
+
throw new RpcError(-32602, 'Missing required parameter: params.name');
|
|
463
573
|
}
|
|
464
574
|
|
|
465
|
-
|
|
466
|
-
const text = runTribunalAudit();
|
|
467
|
-
return { content: [{ type: "text", text }] };
|
|
468
|
-
}
|
|
575
|
+
const reminder = repeatGuard.observe(toolName, argsObj);
|
|
469
576
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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.
|
|
475
584
|
return {
|
|
476
585
|
content: [
|
|
477
586
|
{
|
|
478
|
-
type:
|
|
479
|
-
text:
|
|
587
|
+
type: '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.',
|
|
480
589
|
},
|
|
481
590
|
],
|
|
482
591
|
};
|
|
483
592
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
593
|
+
|
|
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
|
+
}
|
|
607
|
+
|
|
608
|
+
if (payload && file) {
|
|
609
|
+
throw new RpcError(-32602, 'Invalid arguments: provide either payload or file, not both');
|
|
610
|
+
}
|
|
611
|
+
|
|
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
|
+
}
|
|
621
|
+
|
|
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
|
+
}
|
|
633
|
+
|
|
634
|
+
// Import swarm dispatcher functions
|
|
635
|
+
const _swarmDispatcher = require(path.join(agentDir, 'scripts', 'swarm_dispatcher.js'));
|
|
636
|
+
|
|
637
|
+
// Execute the swarm dispatcher
|
|
638
|
+
const originalArgv = process.argv;
|
|
639
|
+
process.argv = ['node', 'swarm_dispatcher.js', '--mode', mode, '--workspace', workspace];
|
|
640
|
+
|
|
641
|
+
if (useTui) {
|
|
642
|
+
process.argv.push('--tui');
|
|
643
|
+
}
|
|
644
|
+
|
|
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
|
+
}
|
|
652
|
+
|
|
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)],
|
|
490
658
|
{
|
|
491
|
-
|
|
492
|
-
|
|
659
|
+
encoding: 'utf8',
|
|
660
|
+
timeout: 30000,
|
|
493
661
|
},
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
662
|
+
);
|
|
663
|
+
|
|
664
|
+
// Restore argv
|
|
665
|
+
process.argv = originalArgv;
|
|
666
|
+
|
|
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
|
+
}
|
|
681
|
+
}
|
|
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],
|
|
499
689
|
{
|
|
500
|
-
|
|
501
|
-
|
|
690
|
+
encoding: 'utf8',
|
|
691
|
+
timeout: 10000,
|
|
502
692
|
},
|
|
503
|
-
|
|
504
|
-
|
|
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
|
+
}
|
|
505
699
|
}
|
|
506
|
-
}
|
|
507
700
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
if (!query || typeof query !== "string") {
|
|
512
|
-
throw {
|
|
513
|
-
code: -32602,
|
|
514
|
-
message: "Missing or invalid required argument: query (string)",
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
const text = searchCaseLaw(query);
|
|
518
|
-
return { content: [{ type: "text", text }] };
|
|
519
|
-
}
|
|
701
|
+
if (toolName === 'validate_payload') {
|
|
702
|
+
const payloadStr = req.params?.arguments?.payload;
|
|
703
|
+
const schemaType = req.params?.arguments?.schemaType;
|
|
520
704
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
}
|
|
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)');
|
|
710
|
+
}
|
|
528
711
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
if (!fs.existsSync(agentPath)) return { content: [{ type: "text", text: `Agent '${sanitizedName}' not found.` }] };
|
|
539
|
-
const text = fs.readFileSync(agentPath, "utf8");
|
|
540
|
-
return { content: [{ type: "text", text: stripBoilerplate(text) }] };
|
|
541
|
-
}
|
|
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
|
+
};
|
|
720
|
+
}
|
|
542
721
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
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'));
|
|
550
730
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
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
|
+
}
|
|
564
766
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
767
|
+
if (toolName === 'run_tribunal_audit') {
|
|
768
|
+
const text = runTribunalAudit();
|
|
769
|
+
return { content: [{ type: 'text', text }] };
|
|
770
|
+
}
|
|
771
|
+
|
|
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
|
+
}
|
|
810
|
+
}
|
|
569
811
|
|
|
570
|
-
if (
|
|
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 }] };
|
|
819
|
+
}
|
|
571
820
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
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- ') }] };
|
|
576
833
|
}
|
|
577
834
|
|
|
578
|
-
|
|
579
|
-
const
|
|
580
|
-
const
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
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) }] };
|
|
585
850
|
}
|
|
586
|
-
}
|
|
587
851
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
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- ') }] };
|
|
592
864
|
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
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) }] };
|
|
598
881
|
}
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
const
|
|
602
|
-
|
|
603
|
-
|
|
882
|
+
|
|
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';
|
|
887
|
+
|
|
888
|
+
if (!task) throw new RpcError(-32602, 'Missing required argument: task');
|
|
889
|
+
|
|
890
|
+
const agentDest = getAgentDir();
|
|
891
|
+
const fs = require('fs');
|
|
892
|
+
if (!fs.existsSync(agentDest)) {
|
|
893
|
+
return {
|
|
894
|
+
content: [
|
|
895
|
+
{ type: 'text', text: 'Error: .agent/ directory not found. Run `tk init` first.' },
|
|
896
|
+
],
|
|
897
|
+
};
|
|
604
898
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
899
|
+
|
|
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
|
+
};
|
|
610
909
|
}
|
|
611
|
-
return { content: [{ type: "text", text }] };
|
|
612
|
-
} catch (e) {
|
|
613
|
-
return { content: [{ type: "text", text: `Memory recall failed: ${e.message}` }] };
|
|
614
910
|
}
|
|
615
|
-
}
|
|
616
911
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
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)) {
|
|
921
|
+
return {
|
|
922
|
+
content: [
|
|
923
|
+
{ type: 'text', text: 'Error: .agent/ directory not found. Run `tk init` first.' },
|
|
924
|
+
],
|
|
925
|
+
};
|
|
926
|
+
}
|
|
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`;
|
|
938
|
+
}
|
|
939
|
+
return { content: [{ type: 'text', text }] };
|
|
940
|
+
} catch (e) {
|
|
941
|
+
return { content: [{ type: 'text', text: `Memory recall failed: ${e.message}` }] };
|
|
942
|
+
}
|
|
627
943
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
944
|
+
|
|
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);
|
|
971
|
+
return {
|
|
972
|
+
content: [
|
|
973
|
+
{
|
|
974
|
+
type: 'text',
|
|
975
|
+
text: `Memory stored: #${result.id} (${memType}, ~${result.token_estimate} tokens)`,
|
|
976
|
+
},
|
|
977
|
+
],
|
|
978
|
+
};
|
|
979
|
+
} catch (e) {
|
|
980
|
+
return { content: [{ type: 'text', text: `Memory store failed: ${e.message}` }] };
|
|
981
|
+
}
|
|
632
982
|
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
const
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
983
|
+
|
|
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}` }] };
|
|
999
|
+
}
|
|
639
1000
|
}
|
|
640
|
-
}
|
|
641
1001
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
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
|
+
}
|
|
646
1023
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
const
|
|
650
|
-
const
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
1024
|
+
|
|
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
|
+
};
|
|
657
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
|
+
};
|
|
658
1093
|
}
|
|
659
|
-
return { content: [{ type: "text", text: outputText }] };
|
|
660
|
-
} catch (e) {
|
|
661
|
-
return { content: [{ type: "text", text: `Alignment failed: ${e.message}` }] };
|
|
662
1094
|
}
|
|
663
|
-
}
|
|
664
1095
|
|
|
665
|
-
|
|
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
|
+
}
|
|
666
1114
|
}
|
|
667
1115
|
|
|
668
|
-
throw
|
|
1116
|
+
throw new RpcError(-32601, `Unknown method: ${req.method}`);
|
|
669
1117
|
}
|
|
670
1118
|
|
|
671
|
-
function processSingleRequest(req) {
|
|
1119
|
+
async function processSingleRequest(req) {
|
|
672
1120
|
try {
|
|
673
|
-
const result = handleRequest(req);
|
|
1121
|
+
const result = await handleRequest(req);
|
|
674
1122
|
// If it's a notification, do not send a response
|
|
675
1123
|
if (req.id === undefined || req.id === null) {
|
|
676
1124
|
return null;
|
|
677
1125
|
}
|
|
678
|
-
return { jsonrpc:
|
|
1126
|
+
return { jsonrpc: '2.0', id: req.id, result };
|
|
679
1127
|
} catch (e) {
|
|
680
|
-
const code = e && typeof e.code ===
|
|
681
|
-
const message = e && e.message ? e.message :
|
|
1128
|
+
const code = e && typeof e.code === 'number' ? e.code : -32603;
|
|
1129
|
+
const message = e && e.message ? e.message : 'Internal server error';
|
|
682
1130
|
if (req.id === undefined || req.id === null) {
|
|
683
1131
|
return {
|
|
684
|
-
jsonrpc:
|
|
1132
|
+
jsonrpc: '2.0',
|
|
685
1133
|
id: null,
|
|
686
1134
|
error: { code, message },
|
|
687
1135
|
};
|
|
688
1136
|
}
|
|
689
1137
|
return {
|
|
690
|
-
jsonrpc:
|
|
1138
|
+
jsonrpc: '2.0',
|
|
691
1139
|
id: req.id,
|
|
692
1140
|
error: { code, message },
|
|
693
1141
|
};
|
|
694
1142
|
}
|
|
695
1143
|
}
|
|
696
1144
|
|
|
697
|
-
rl.on(
|
|
698
|
-
if (line.length > 1048576) {
|
|
1145
|
+
rl.on('line', async line => {
|
|
1146
|
+
if (line.length > 1048576) {
|
|
1147
|
+
// 1MB limit
|
|
699
1148
|
const errorRes = {
|
|
700
|
-
jsonrpc:
|
|
1149
|
+
jsonrpc: '2.0',
|
|
701
1150
|
id: null,
|
|
702
|
-
error: { code: -32700, message:
|
|
1151
|
+
error: { code: -32700, message: 'Parse error: input line too long (exceeds 1MB limit)' },
|
|
703
1152
|
};
|
|
704
1153
|
console.log(JSON.stringify(errorRes));
|
|
705
1154
|
return;
|
|
@@ -712,9 +1161,9 @@ rl.on("line", (line) => {
|
|
|
712
1161
|
} catch (parseErr) {
|
|
713
1162
|
// Invalid JSON — send a parse error
|
|
714
1163
|
const errorRes = {
|
|
715
|
-
jsonrpc:
|
|
1164
|
+
jsonrpc: '2.0',
|
|
716
1165
|
id: null,
|
|
717
|
-
error: { code: -32700, message:
|
|
1166
|
+
error: { code: -32700, message: 'Parse error: ' + parseErr.message },
|
|
718
1167
|
};
|
|
719
1168
|
console.log(JSON.stringify(errorRes));
|
|
720
1169
|
return;
|
|
@@ -723,7 +1172,7 @@ rl.on("line", (line) => {
|
|
|
723
1172
|
if (Array.isArray(req)) {
|
|
724
1173
|
const responses = [];
|
|
725
1174
|
for (const singleReq of req) {
|
|
726
|
-
const response = processSingleRequest(singleReq);
|
|
1175
|
+
const response = await processSingleRequest(singleReq);
|
|
727
1176
|
if (response) {
|
|
728
1177
|
responses.push(response);
|
|
729
1178
|
}
|
|
@@ -732,14 +1181,14 @@ rl.on("line", (line) => {
|
|
|
732
1181
|
console.log(JSON.stringify(responses));
|
|
733
1182
|
}
|
|
734
1183
|
} else {
|
|
735
|
-
const response = processSingleRequest(req);
|
|
1184
|
+
const response = await processSingleRequest(req);
|
|
736
1185
|
if (response) {
|
|
737
1186
|
console.log(JSON.stringify(response));
|
|
738
1187
|
}
|
|
739
1188
|
}
|
|
740
1189
|
});
|
|
741
1190
|
|
|
742
|
-
if (process.env.NODE_ENV ===
|
|
1191
|
+
if (process.env.NODE_ENV === 'test') {
|
|
743
1192
|
module.exports = {
|
|
744
1193
|
handleRequest,
|
|
745
1194
|
stripBoilerplate,
|