forge-server 0.1.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/.claude/hooks/worktree-create.sh +64 -0
- package/.claude/hooks/worktree-remove.sh +57 -0
- package/.claude/settings.local.json +29 -0
- package/.forge/knowledge/conventions.yaml +1 -0
- package/.forge/knowledge/decisions.yaml +1 -0
- package/.forge/knowledge/gotchas.yaml +1 -0
- package/.forge/knowledge/patterns.yaml +1 -0
- package/.forge/manifest.yaml +6 -0
- package/CLAUDE.md +144 -0
- package/bin/setup-forge.sh +132 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +553 -0
- package/dist/cli.js.map +1 -0
- package/dist/context/codebase.d.ts +57 -0
- package/dist/context/codebase.d.ts.map +1 -0
- package/dist/context/codebase.js +301 -0
- package/dist/context/codebase.js.map +1 -0
- package/dist/context/injector.d.ts +147 -0
- package/dist/context/injector.d.ts.map +1 -0
- package/dist/context/injector.js +533 -0
- package/dist/context/injector.js.map +1 -0
- package/dist/context/memory.d.ts +32 -0
- package/dist/context/memory.d.ts.map +1 -0
- package/dist/context/memory.js +140 -0
- package/dist/context/memory.js.map +1 -0
- package/dist/context/session-index.d.ts +54 -0
- package/dist/context/session-index.d.ts.map +1 -0
- package/dist/context/session-index.js +265 -0
- package/dist/context/session-index.js.map +1 -0
- package/dist/context/session.d.ts +42 -0
- package/dist/context/session.d.ts.map +1 -0
- package/dist/context/session.js +121 -0
- package/dist/context/session.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/ingestion/chunker.d.ts +19 -0
- package/dist/ingestion/chunker.d.ts.map +1 -0
- package/dist/ingestion/chunker.js +189 -0
- package/dist/ingestion/chunker.js.map +1 -0
- package/dist/ingestion/embedder.d.ts +45 -0
- package/dist/ingestion/embedder.d.ts.map +1 -0
- package/dist/ingestion/embedder.js +152 -0
- package/dist/ingestion/embedder.js.map +1 -0
- package/dist/ingestion/git-analyzer.d.ts +77 -0
- package/dist/ingestion/git-analyzer.d.ts.map +1 -0
- package/dist/ingestion/git-analyzer.js +437 -0
- package/dist/ingestion/git-analyzer.js.map +1 -0
- package/dist/ingestion/indexer.d.ts +79 -0
- package/dist/ingestion/indexer.d.ts.map +1 -0
- package/dist/ingestion/indexer.js +766 -0
- package/dist/ingestion/indexer.js.map +1 -0
- package/dist/ingestion/markdown-chunker.d.ts +19 -0
- package/dist/ingestion/markdown-chunker.d.ts.map +1 -0
- package/dist/ingestion/markdown-chunker.js +243 -0
- package/dist/ingestion/markdown-chunker.js.map +1 -0
- package/dist/ingestion/markdown-knowledge.d.ts +21 -0
- package/dist/ingestion/markdown-knowledge.d.ts.map +1 -0
- package/dist/ingestion/markdown-knowledge.js +129 -0
- package/dist/ingestion/markdown-knowledge.js.map +1 -0
- package/dist/ingestion/parser.d.ts +20 -0
- package/dist/ingestion/parser.d.ts.map +1 -0
- package/dist/ingestion/parser.js +429 -0
- package/dist/ingestion/parser.js.map +1 -0
- package/dist/ingestion/watcher.d.ts +28 -0
- package/dist/ingestion/watcher.d.ts.map +1 -0
- package/dist/ingestion/watcher.js +147 -0
- package/dist/ingestion/watcher.js.map +1 -0
- package/dist/knowledge/hydrator.d.ts +37 -0
- package/dist/knowledge/hydrator.d.ts.map +1 -0
- package/dist/knowledge/hydrator.js +220 -0
- package/dist/knowledge/hydrator.js.map +1 -0
- package/dist/knowledge/registry.d.ts +129 -0
- package/dist/knowledge/registry.d.ts.map +1 -0
- package/dist/knowledge/registry.js +361 -0
- package/dist/knowledge/registry.js.map +1 -0
- package/dist/knowledge/search.d.ts +114 -0
- package/dist/knowledge/search.d.ts.map +1 -0
- package/dist/knowledge/search.js +428 -0
- package/dist/knowledge/search.js.map +1 -0
- package/dist/knowledge/store.d.ts +76 -0
- package/dist/knowledge/store.d.ts.map +1 -0
- package/dist/knowledge/store.js +230 -0
- package/dist/knowledge/store.js.map +1 -0
- package/dist/learning/confidence.d.ts +30 -0
- package/dist/learning/confidence.d.ts.map +1 -0
- package/dist/learning/confidence.js +165 -0
- package/dist/learning/confidence.js.map +1 -0
- package/dist/learning/patterns.d.ts +52 -0
- package/dist/learning/patterns.d.ts.map +1 -0
- package/dist/learning/patterns.js +290 -0
- package/dist/learning/patterns.js.map +1 -0
- package/dist/learning/trajectory.d.ts +55 -0
- package/dist/learning/trajectory.d.ts.map +1 -0
- package/dist/learning/trajectory.js +200 -0
- package/dist/learning/trajectory.js.map +1 -0
- package/dist/memory/memory-compat.d.ts +100 -0
- package/dist/memory/memory-compat.d.ts.map +1 -0
- package/dist/memory/memory-compat.js +146 -0
- package/dist/memory/memory-compat.js.map +1 -0
- package/dist/memory/observation-store.d.ts +57 -0
- package/dist/memory/observation-store.d.ts.map +1 -0
- package/dist/memory/observation-store.js +154 -0
- package/dist/memory/observation-store.js.map +1 -0
- package/dist/memory/session-tracker.d.ts +81 -0
- package/dist/memory/session-tracker.d.ts.map +1 -0
- package/dist/memory/session-tracker.js +262 -0
- package/dist/memory/session-tracker.js.map +1 -0
- package/dist/pipeline/engine.d.ts +179 -0
- package/dist/pipeline/engine.d.ts.map +1 -0
- package/dist/pipeline/engine.js +691 -0
- package/dist/pipeline/engine.js.map +1 -0
- package/dist/pipeline/events.d.ts +54 -0
- package/dist/pipeline/events.d.ts.map +1 -0
- package/dist/pipeline/events.js +157 -0
- package/dist/pipeline/events.js.map +1 -0
- package/dist/pipeline/parallel.d.ts +83 -0
- package/dist/pipeline/parallel.d.ts.map +1 -0
- package/dist/pipeline/parallel.js +277 -0
- package/dist/pipeline/parallel.js.map +1 -0
- package/dist/pipeline/state-machine.d.ts +65 -0
- package/dist/pipeline/state-machine.d.ts.map +1 -0
- package/dist/pipeline/state-machine.js +176 -0
- package/dist/pipeline/state-machine.js.map +1 -0
- package/dist/query/graph-queries.d.ts +84 -0
- package/dist/query/graph-queries.d.ts.map +1 -0
- package/dist/query/graph-queries.js +216 -0
- package/dist/query/graph-queries.js.map +1 -0
- package/dist/query/hybrid-search.d.ts +34 -0
- package/dist/query/hybrid-search.d.ts.map +1 -0
- package/dist/query/hybrid-search.js +263 -0
- package/dist/query/hybrid-search.js.map +1 -0
- package/dist/query/intent-detector.d.ts +35 -0
- package/dist/query/intent-detector.d.ts.map +1 -0
- package/dist/query/intent-detector.js +115 -0
- package/dist/query/intent-detector.js.map +1 -0
- package/dist/query/ranking.d.ts +57 -0
- package/dist/query/ranking.d.ts.map +1 -0
- package/dist/query/ranking.js +109 -0
- package/dist/query/ranking.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +291 -0
- package/dist/server.js.map +1 -0
- package/dist/storage/falkordb-store.d.ts +73 -0
- package/dist/storage/falkordb-store.d.ts.map +1 -0
- package/dist/storage/falkordb-store.js +346 -0
- package/dist/storage/falkordb-store.js.map +1 -0
- package/dist/storage/file-cache.d.ts +32 -0
- package/dist/storage/file-cache.d.ts.map +1 -0
- package/dist/storage/file-cache.js +115 -0
- package/dist/storage/file-cache.js.map +1 -0
- package/dist/storage/interfaces.d.ts +151 -0
- package/dist/storage/interfaces.d.ts.map +1 -0
- package/dist/storage/interfaces.js +7 -0
- package/dist/storage/interfaces.js.map +1 -0
- package/dist/storage/qdrant-store.d.ts +110 -0
- package/dist/storage/qdrant-store.d.ts.map +1 -0
- package/dist/storage/qdrant-store.js +467 -0
- package/dist/storage/qdrant-store.js.map +1 -0
- package/dist/storage/schema.d.ts +4 -0
- package/dist/storage/schema.d.ts.map +1 -0
- package/dist/storage/schema.js +136 -0
- package/dist/storage/schema.js.map +1 -0
- package/dist/storage/sqlite.d.ts +35 -0
- package/dist/storage/sqlite.d.ts.map +1 -0
- package/dist/storage/sqlite.js +132 -0
- package/dist/storage/sqlite.js.map +1 -0
- package/dist/tools/collaboration-tools.d.ts +111 -0
- package/dist/tools/collaboration-tools.d.ts.map +1 -0
- package/dist/tools/collaboration-tools.js +174 -0
- package/dist/tools/collaboration-tools.js.map +1 -0
- package/dist/tools/context-tools.d.ts +293 -0
- package/dist/tools/context-tools.d.ts.map +1 -0
- package/dist/tools/context-tools.js +437 -0
- package/dist/tools/context-tools.js.map +1 -0
- package/dist/tools/graph-tools.d.ts +129 -0
- package/dist/tools/graph-tools.d.ts.map +1 -0
- package/dist/tools/graph-tools.js +237 -0
- package/dist/tools/graph-tools.js.map +1 -0
- package/dist/tools/ingestion-tools.d.ts +96 -0
- package/dist/tools/ingestion-tools.d.ts.map +1 -0
- package/dist/tools/ingestion-tools.js +90 -0
- package/dist/tools/ingestion-tools.js.map +1 -0
- package/dist/tools/learning-tools.d.ts +168 -0
- package/dist/tools/learning-tools.d.ts.map +1 -0
- package/dist/tools/learning-tools.js +158 -0
- package/dist/tools/learning-tools.js.map +1 -0
- package/dist/tools/memory-tools.d.ts +183 -0
- package/dist/tools/memory-tools.d.ts.map +1 -0
- package/dist/tools/memory-tools.js +197 -0
- package/dist/tools/memory-tools.js.map +1 -0
- package/dist/tools/phase-tools.d.ts +954 -0
- package/dist/tools/phase-tools.d.ts.map +1 -0
- package/dist/tools/phase-tools.js +1215 -0
- package/dist/tools/phase-tools.js.map +1 -0
- package/dist/tools/pipeline-tools.d.ts +140 -0
- package/dist/tools/pipeline-tools.d.ts.map +1 -0
- package/dist/tools/pipeline-tools.js +162 -0
- package/dist/tools/pipeline-tools.js.map +1 -0
- package/dist/tools/registration-tools.d.ts +220 -0
- package/dist/tools/registration-tools.d.ts.map +1 -0
- package/dist/tools/registration-tools.js +391 -0
- package/dist/tools/registration-tools.js.map +1 -0
- package/dist/util/circuit-breaker.d.ts +75 -0
- package/dist/util/circuit-breaker.d.ts.map +1 -0
- package/dist/util/circuit-breaker.js +159 -0
- package/dist/util/circuit-breaker.js.map +1 -0
- package/dist/util/config.d.ts +23 -0
- package/dist/util/config.d.ts.map +1 -0
- package/dist/util/config.js +164 -0
- package/dist/util/config.js.map +1 -0
- package/dist/util/logger.d.ts +13 -0
- package/dist/util/logger.d.ts.map +1 -0
- package/dist/util/logger.js +45 -0
- package/dist/util/logger.js.map +1 -0
- package/dist/util/token-counter.d.ts +24 -0
- package/dist/util/token-counter.d.ts.map +1 -0
- package/dist/util/token-counter.js +48 -0
- package/dist/util/token-counter.js.map +1 -0
- package/dist/util/types.d.ts +525 -0
- package/dist/util/types.d.ts.map +1 -0
- package/dist/util/types.js +5 -0
- package/dist/util/types.js.map +1 -0
- package/docker-compose.yml +20 -0
- package/docs/plans/2026-02-27-swarm-coordination/architecture.md +203 -0
- package/docs/plans/2026-02-27-swarm-coordination/vision.md +57 -0
- package/docs/plans/completed/2026-02-26-forge-plugin-bundling/architecture.md +1 -0
- package/docs/plans/completed/2026-02-26-forge-plugin-bundling/vision.md +300 -0
- package/docs/plans/completed/2026-02-27-forge-swarm-learning/architecture.md +480 -0
- package/docs/plans/completed/2026-02-27-forge-swarm-learning/verification-checklist.md +462 -0
- package/docs/plans/completed/2026-02-27-git-history-atlassian/git-jira-plan.md +181 -0
- package/package.json +39 -0
- package/plugin/.claude-plugin/plugin.json +8 -0
- package/plugin/.mcp.json +15 -0
- package/plugin/README.md +134 -0
- package/plugin/agents/architect.md +367 -0
- package/plugin/agents/backend-specialist.md +263 -0
- package/plugin/agents/brainstormer.md +122 -0
- package/plugin/agents/data-specialist.md +266 -0
- package/plugin/agents/designer.md +408 -0
- package/plugin/agents/frontend-specialist.md +241 -0
- package/plugin/agents/inspector.md +406 -0
- package/plugin/agents/knowledge-keeper.md +443 -0
- package/plugin/agents/platform-engineer.md +326 -0
- package/plugin/agents/product-manager.md +268 -0
- package/plugin/agents/product-owner.md +438 -0
- package/plugin/agents/pulse-checker.md +73 -0
- package/plugin/agents/qa-strategist.md +500 -0
- package/plugin/agents/self-improver.md +310 -0
- package/plugin/agents/strategist.md +360 -0
- package/plugin/agents/supervisor.md +380 -0
- package/plugin/commands/brainstorm.md +25 -0
- package/plugin/commands/forge.md +88 -0
- package/plugin/docs/atlassian-integration.md +110 -0
- package/plugin/docs/workflow.md +126 -0
- package/plugin/skills/agent-development/.skillfish.json +10 -0
- package/plugin/skills/agent-development/SKILL.md +415 -0
- package/plugin/skills/agent-development/examples/agent-creation-prompt.md +238 -0
- package/plugin/skills/agent-development/examples/complete-agent-examples.md +427 -0
- package/plugin/skills/agent-development/references/agent-creation-system-prompt.md +207 -0
- package/plugin/skills/agent-development/references/system-prompt-design.md +411 -0
- package/plugin/skills/agent-development/references/triggering-examples.md +491 -0
- package/plugin/skills/agent-development/scripts/validate-agent.sh +217 -0
- package/plugin/skills/agent-handoff/SKILL.md +335 -0
- package/plugin/skills/anti-stub/SKILL.md +317 -0
- package/plugin/skills/brainstorm/SKILL.md +31 -0
- package/plugin/skills/debugging/SKILL.md +276 -0
- package/plugin/skills/fix/SKILL.md +62 -0
- package/plugin/skills/frontend-design/.skillfish.json +10 -0
- package/plugin/skills/frontend-design/SKILL.md +42 -0
- package/plugin/skills/gotchas/SKILL.md +61 -0
- package/plugin/skills/graph-orchestrator/SKILL.md +38 -0
- package/plugin/skills/history/SKILL.md +58 -0
- package/plugin/skills/impact/SKILL.md +59 -0
- package/plugin/skills/implementation-execution/SKILL.md +291 -0
- package/plugin/skills/index-repo/SKILL.md +55 -0
- package/plugin/skills/interviewing/SKILL.md +225 -0
- package/plugin/skills/knowledge-curation/SKILL.md +393 -0
- package/plugin/skills/learn/SKILL.md +69 -0
- package/plugin/skills/mcp-integration/.skillfish.json +10 -0
- package/plugin/skills/mcp-integration/SKILL.md +554 -0
- package/plugin/skills/mcp-integration/examples/http-server.json +20 -0
- package/plugin/skills/mcp-integration/examples/sse-server.json +19 -0
- package/plugin/skills/mcp-integration/examples/stdio-server.json +26 -0
- package/plugin/skills/mcp-integration/references/authentication.md +549 -0
- package/plugin/skills/mcp-integration/references/server-types.md +536 -0
- package/plugin/skills/mcp-integration/references/tool-usage.md +538 -0
- package/plugin/skills/nestjs/.skillfish.json +10 -0
- package/plugin/skills/nestjs/SKILL.md +669 -0
- package/plugin/skills/nestjs/drizzle-reference.md +1894 -0
- package/plugin/skills/nestjs/reference.md +1447 -0
- package/plugin/skills/nestjs/workflow-optimization.md +229 -0
- package/plugin/skills/parallel-dispatch/SKILL.md +308 -0
- package/plugin/skills/project-discovery/SKILL.md +304 -0
- package/plugin/skills/search/SKILL.md +56 -0
- package/plugin/skills/security-audit/SKILL.md +362 -0
- package/plugin/skills/skill-development/.skillfish.json +10 -0
- package/plugin/skills/skill-development/SKILL.md +637 -0
- package/plugin/skills/skill-development/references/skill-creator-original.md +209 -0
- package/plugin/skills/tdd/SKILL.md +273 -0
- package/plugin/skills/terminal-presentation/SKILL.md +395 -0
- package/plugin/skills/test-strategy/SKILL.md +365 -0
- package/plugin/skills/verification-protocol/SKILL.md +256 -0
- package/plugin/skills/visual-explainer/CHANGELOG.md +97 -0
- package/plugin/skills/visual-explainer/LICENSE +21 -0
- package/plugin/skills/visual-explainer/README.md +137 -0
- package/plugin/skills/visual-explainer/SKILL.md +352 -0
- package/plugin/skills/visual-explainer/banner.png +0 -0
- package/plugin/skills/visual-explainer/package.json +11 -0
- package/plugin/skills/visual-explainer/prompts/diff-review.md +68 -0
- package/plugin/skills/visual-explainer/prompts/fact-check.md +63 -0
- package/plugin/skills/visual-explainer/prompts/generate-slides.md +18 -0
- package/plugin/skills/visual-explainer/prompts/generate-web-diagram.md +10 -0
- package/plugin/skills/visual-explainer/prompts/plan-review.md +86 -0
- package/plugin/skills/visual-explainer/prompts/project-recap.md +61 -0
- package/plugin/skills/visual-explainer/references/css-patterns.md +1188 -0
- package/plugin/skills/visual-explainer/references/libraries.md +470 -0
- package/plugin/skills/visual-explainer/references/responsive-nav.md +212 -0
- package/plugin/skills/visual-explainer/references/slide-patterns.md +1403 -0
- package/plugin/skills/visual-explainer/templates/architecture.html +596 -0
- package/plugin/skills/visual-explainer/templates/data-table.html +540 -0
- package/plugin/skills/visual-explainer/templates/mermaid-flowchart.html +435 -0
- package/plugin/skills/visual-explainer/templates/slide-deck.html +913 -0
- package/src/cli.ts +655 -0
- package/src/context/.gitkeep +0 -0
- package/src/context/codebase.ts +393 -0
- package/src/context/injector.ts +797 -0
- package/src/context/memory.ts +187 -0
- package/src/context/session-index.ts +327 -0
- package/src/context/session.ts +152 -0
- package/src/index.ts +47 -0
- package/src/ingestion/.gitkeep +0 -0
- package/src/ingestion/chunker.ts +277 -0
- package/src/ingestion/embedder.ts +167 -0
- package/src/ingestion/git-analyzer.ts +545 -0
- package/src/ingestion/indexer.ts +984 -0
- package/src/ingestion/markdown-chunker.ts +337 -0
- package/src/ingestion/markdown-knowledge.ts +175 -0
- package/src/ingestion/parser.ts +475 -0
- package/src/ingestion/watcher.ts +182 -0
- package/src/knowledge/.gitkeep +0 -0
- package/src/knowledge/hydrator.ts +246 -0
- package/src/knowledge/registry.ts +463 -0
- package/src/knowledge/search.ts +565 -0
- package/src/knowledge/store.ts +262 -0
- package/src/learning/.gitkeep +0 -0
- package/src/learning/confidence.ts +193 -0
- package/src/learning/patterns.ts +360 -0
- package/src/learning/trajectory.ts +268 -0
- package/src/memory/.gitkeep +0 -0
- package/src/memory/memory-compat.ts +233 -0
- package/src/memory/observation-store.ts +224 -0
- package/src/memory/session-tracker.ts +332 -0
- package/src/pipeline/.gitkeep +0 -0
- package/src/pipeline/engine.ts +1139 -0
- package/src/pipeline/events.ts +253 -0
- package/src/pipeline/parallel.ts +394 -0
- package/src/pipeline/state-machine.ts +199 -0
- package/src/query/.gitkeep +0 -0
- package/src/query/graph-queries.ts +262 -0
- package/src/query/hybrid-search.ts +337 -0
- package/src/query/intent-detector.ts +131 -0
- package/src/query/ranking.ts +161 -0
- package/src/server.ts +352 -0
- package/src/storage/.gitkeep +0 -0
- package/src/storage/falkordb-store.ts +388 -0
- package/src/storage/file-cache.ts +141 -0
- package/src/storage/interfaces.ts +201 -0
- package/src/storage/qdrant-store.ts +557 -0
- package/src/storage/schema.ts +139 -0
- package/src/storage/sqlite.ts +168 -0
- package/src/tools/.gitkeep +0 -0
- package/src/tools/collaboration-tools.ts +208 -0
- package/src/tools/context-tools.ts +493 -0
- package/src/tools/graph-tools.ts +295 -0
- package/src/tools/ingestion-tools.ts +122 -0
- package/src/tools/learning-tools.ts +181 -0
- package/src/tools/memory-tools.ts +234 -0
- package/src/tools/phase-tools.ts +1452 -0
- package/src/tools/pipeline-tools.ts +188 -0
- package/src/tools/registration-tools.ts +450 -0
- package/src/util/.gitkeep +0 -0
- package/src/util/circuit-breaker.ts +193 -0
- package/src/util/config.ts +177 -0
- package/src/util/logger.ts +53 -0
- package/src/util/token-counter.ts +52 -0
- package/src/util/types.ts +710 -0
- package/tests/context/.gitkeep +0 -0
- package/tests/integration/.gitkeep +0 -0
- package/tests/knowledge/.gitkeep +0 -0
- package/tests/learning/.gitkeep +0 -0
- package/tests/pipeline/.gitkeep +0 -0
- package/tests/tools/.gitkeep +0 -0
- package/tsconfig.json +21 -0
- package/vitest.config.ts +10 -0
- package/vscode-extension/.vscodeignore +7 -0
- package/vscode-extension/README.md +43 -0
- package/vscode-extension/out/edge-collector.js +274 -0
- package/vscode-extension/out/edge-collector.js.map +1 -0
- package/vscode-extension/out/extension.js +264 -0
- package/vscode-extension/out/extension.js.map +1 -0
- package/vscode-extension/out/forge-client.js +318 -0
- package/vscode-extension/out/forge-client.js.map +1 -0
- package/vscode-extension/package-lock.json +59 -0
- package/vscode-extension/package.json +71 -0
- package/vscode-extension/src/edge-collector.ts +320 -0
- package/vscode-extension/src/extension.ts +269 -0
- package/vscode-extension/src/forge-client.ts +364 -0
- package/vscode-extension/tsconfig.json +19 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
// graph-tools.ts — Swarm Learning Phase 1
|
|
2
|
+
// MCP tool handlers for graph-based code analysis.
|
|
3
|
+
// Tools: get_impact_graph, search_logic_flow
|
|
4
|
+
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import type { GraphStore } from '../storage/interfaces.js';
|
|
7
|
+
import {
|
|
8
|
+
QUERY_INBOUND_IMPACT,
|
|
9
|
+
QUERY_OUTBOUND_IMPACT,
|
|
10
|
+
QUERY_SHORTEST_PATH,
|
|
11
|
+
} from '../query/graph-queries.js';
|
|
12
|
+
import { logger } from '../util/logger.js';
|
|
13
|
+
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Input schemas
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
export const getImpactGraphSchema = z.object({
|
|
19
|
+
symbol: z.string().min(1, 'symbol name is required'),
|
|
20
|
+
repo_id: z.string().min(1, 'repo_id is required'),
|
|
21
|
+
direction: z.enum(['inbound', 'outbound', 'both']).default('both'),
|
|
22
|
+
depth: z.number().int().min(1).max(5).default(3),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const searchLogicFlowSchema = z.object({
|
|
26
|
+
from_symbol: z.string().min(1, 'from_symbol is required'),
|
|
27
|
+
to_symbol: z.string().min(1, 'to_symbol is required'),
|
|
28
|
+
repo_id: z.string().min(1, 'repo_id is required'),
|
|
29
|
+
max_depth: z.number().int().min(1).max(10).default(5),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Tool factory
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
export function createGraphTools(graphStore: GraphStore | null) {
|
|
37
|
+
return {
|
|
38
|
+
'get_impact_graph': {
|
|
39
|
+
schema: getImpactGraphSchema,
|
|
40
|
+
description: 'Get the impact graph (callers/dependents) for a code symbol. PREFER THIS over manual Grep for "who uses X" questions — it traverses the actual call/import graph with depth control, not just text matches. Requires FalkorDB graph store.',
|
|
41
|
+
handler: async (input: z.infer<typeof getImpactGraphSchema>) => {
|
|
42
|
+
if (!graphStore) {
|
|
43
|
+
return {
|
|
44
|
+
error: 'GRAPH_UNAVAILABLE',
|
|
45
|
+
message: 'FalkorDB graph store is not available. Impact graph requires a running FalkorDB instance.',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const healthy = await graphStore.isHealthy();
|
|
50
|
+
if (!healthy) {
|
|
51
|
+
return {
|
|
52
|
+
error: 'GRAPH_UNAVAILABLE',
|
|
53
|
+
message: 'FalkorDB is not healthy. Impact graph unavailable.',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
const nodes: Array<{ name: string; label: string; file_path?: string }> = [];
|
|
59
|
+
const edges: Array<{ from: string; to: string; type: string; depth: number }> = [];
|
|
60
|
+
|
|
61
|
+
// Inbound: who calls/imports/uses this symbol?
|
|
62
|
+
if (input.direction === 'inbound' || input.direction === 'both') {
|
|
63
|
+
try {
|
|
64
|
+
const result = await graphStore.query(
|
|
65
|
+
QUERY_INBOUND_IMPACT(input.symbol, input.repo_id, input.depth)
|
|
66
|
+
);
|
|
67
|
+
parseImpactResult(result, nodes, edges, 'inbound');
|
|
68
|
+
} catch (err) {
|
|
69
|
+
logger.warn('get_impact_graph: inbound query failed', { error: String(err) });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Outbound: what does this symbol depend on?
|
|
74
|
+
if (input.direction === 'outbound' || input.direction === 'both') {
|
|
75
|
+
try {
|
|
76
|
+
const result = await graphStore.query(
|
|
77
|
+
QUERY_OUTBOUND_IMPACT(input.symbol, input.repo_id, input.depth)
|
|
78
|
+
);
|
|
79
|
+
parseImpactResult(result, nodes, edges, 'outbound');
|
|
80
|
+
} catch (err) {
|
|
81
|
+
logger.warn('get_impact_graph: outbound query failed', { error: String(err) });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Deduplicate nodes by name
|
|
86
|
+
const uniqueNodes = deduplicateNodes(nodes);
|
|
87
|
+
|
|
88
|
+
logger.debug('graph-tools.get_impact_graph: completed', {
|
|
89
|
+
symbol: input.symbol,
|
|
90
|
+
direction: input.direction,
|
|
91
|
+
nodes: uniqueNodes.length,
|
|
92
|
+
edges: edges.length,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
symbol: input.symbol,
|
|
97
|
+
direction: input.direction,
|
|
98
|
+
nodes: uniqueNodes,
|
|
99
|
+
edges,
|
|
100
|
+
total_nodes: uniqueNodes.length,
|
|
101
|
+
total_edges: edges.length,
|
|
102
|
+
};
|
|
103
|
+
} catch (err) {
|
|
104
|
+
logger.error('graph-tools.get_impact_graph: error', { error: String(err) });
|
|
105
|
+
return {
|
|
106
|
+
error: 'GET_IMPACT_GRAPH_FAILED',
|
|
107
|
+
message: String(err),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
'search_logic_flow': {
|
|
114
|
+
schema: searchLogicFlowSchema,
|
|
115
|
+
description: 'Find the shortest path between two code symbols in the call/dependency graph. Use this to understand how data or control flows from A to B through the codebase — much faster than manually tracing imports. Requires FalkorDB graph store.',
|
|
116
|
+
handler: async (input: z.infer<typeof searchLogicFlowSchema>) => {
|
|
117
|
+
if (!graphStore) {
|
|
118
|
+
return {
|
|
119
|
+
error: 'GRAPH_UNAVAILABLE',
|
|
120
|
+
message: 'FalkorDB graph store is not available. Logic flow search requires a running FalkorDB instance.',
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const healthy = await graphStore.isHealthy();
|
|
125
|
+
if (!healthy) {
|
|
126
|
+
return {
|
|
127
|
+
error: 'GRAPH_UNAVAILABLE',
|
|
128
|
+
message: 'FalkorDB is not healthy. Logic flow search unavailable.',
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
const result = await graphStore.query(
|
|
134
|
+
QUERY_SHORTEST_PATH(input.from_symbol, input.to_symbol, input.repo_id, input.max_depth)
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const paths = parsePathResult(result);
|
|
138
|
+
|
|
139
|
+
logger.debug('graph-tools.search_logic_flow: completed', {
|
|
140
|
+
from: input.from_symbol,
|
|
141
|
+
to: input.to_symbol,
|
|
142
|
+
pathCount: paths.length,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
from_symbol: input.from_symbol,
|
|
147
|
+
to_symbol: input.to_symbol,
|
|
148
|
+
paths,
|
|
149
|
+
connected: paths.length > 0,
|
|
150
|
+
};
|
|
151
|
+
} catch (err) {
|
|
152
|
+
logger.error('graph-tools.search_logic_flow: error', { error: String(err) });
|
|
153
|
+
return {
|
|
154
|
+
error: 'SEARCH_LOGIC_FLOW_FAILED',
|
|
155
|
+
message: String(err),
|
|
156
|
+
from_symbol: input.from_symbol,
|
|
157
|
+
to_symbol: input.to_symbol,
|
|
158
|
+
paths: [],
|
|
159
|
+
connected: false,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
// Result parsers for FalkorDB raw responses
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
|
|
171
|
+
interface GraphQueryResult {
|
|
172
|
+
nodes: Array<{ label: string; properties: Record<string, unknown> }>;
|
|
173
|
+
edges: Array<{ type: string; from: string; to: string; properties?: Record<string, unknown> }>;
|
|
174
|
+
raw?: unknown[];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function parseImpactResult(
|
|
178
|
+
result: GraphQueryResult,
|
|
179
|
+
nodes: Array<{ name: string; label: string; file_path?: string }>,
|
|
180
|
+
edges: Array<{ from: string; to: string; type: string; depth: number }>,
|
|
181
|
+
_direction: 'inbound' | 'outbound',
|
|
182
|
+
): void {
|
|
183
|
+
// Parse nodes from the result
|
|
184
|
+
for (const node of result.nodes ?? []) {
|
|
185
|
+
const name = String(node.properties?.['name'] ?? '');
|
|
186
|
+
const filePath = node.properties?.['file_path'] as string | undefined;
|
|
187
|
+
if (name) {
|
|
188
|
+
nodes.push({ name, label: node.label, file_path: filePath });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Parse edges from the result
|
|
193
|
+
for (const edge of result.edges ?? []) {
|
|
194
|
+
edges.push({
|
|
195
|
+
from: edge.from,
|
|
196
|
+
to: edge.to,
|
|
197
|
+
type: edge.type,
|
|
198
|
+
depth: 1,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Also try to parse from raw results (FalkorDB returns varying formats)
|
|
203
|
+
for (const row of result.raw ?? []) {
|
|
204
|
+
if (!row || !Array.isArray(row)) continue;
|
|
205
|
+
|
|
206
|
+
// Expected columns: [caller/dep, relationship_array, depth]
|
|
207
|
+
const entity = row[0];
|
|
208
|
+
const depth = typeof row[2] === 'number' ? row[2] : 1;
|
|
209
|
+
|
|
210
|
+
if (entity && typeof entity === 'object') {
|
|
211
|
+
const props = (entity as Record<string, unknown>).properties as Record<string, unknown> | undefined;
|
|
212
|
+
if (props) {
|
|
213
|
+
const name = String(props['name'] ?? '');
|
|
214
|
+
const filePath = props['file_path'] as string | undefined;
|
|
215
|
+
if (name) {
|
|
216
|
+
nodes.push({ name, label: 'unknown', file_path: filePath });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function parsePathResult(
|
|
224
|
+
result: GraphQueryResult,
|
|
225
|
+
): Array<{ nodes: string[]; edges: string[]; length: number }> {
|
|
226
|
+
const paths: Array<{ nodes: string[]; edges: string[]; length: number }> = [];
|
|
227
|
+
|
|
228
|
+
// Try to parse from raw results
|
|
229
|
+
for (const row of result.raw ?? []) {
|
|
230
|
+
if (!row) continue;
|
|
231
|
+
|
|
232
|
+
// The QUERY_SHORTEST_PATH returns path objects
|
|
233
|
+
// Different FalkorDB parsers represent these differently
|
|
234
|
+
if (Array.isArray(row)) {
|
|
235
|
+
const pathObj = row[0];
|
|
236
|
+
if (pathObj && typeof pathObj === 'object') {
|
|
237
|
+
const pathNodes: string[] = [];
|
|
238
|
+
const pathEdges: string[] = [];
|
|
239
|
+
|
|
240
|
+
// Extract from FalkorDB path representation
|
|
241
|
+
const pNodes = (pathObj as Record<string, unknown>).nodes as Array<Record<string, unknown>> | undefined;
|
|
242
|
+
const pEdges = (pathObj as Record<string, unknown>).edges as Array<Record<string, unknown>> | undefined;
|
|
243
|
+
|
|
244
|
+
if (pNodes) {
|
|
245
|
+
for (const n of pNodes) {
|
|
246
|
+
const props = n.properties as Record<string, unknown> | undefined;
|
|
247
|
+
pathNodes.push(String(props?.['name'] ?? 'unknown'));
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (pEdges) {
|
|
252
|
+
for (const e of pEdges) {
|
|
253
|
+
pathEdges.push(String(e.type ?? e.relation ?? 'unknown'));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (pathNodes.length > 0) {
|
|
258
|
+
paths.push({
|
|
259
|
+
nodes: pathNodes,
|
|
260
|
+
edges: pathEdges,
|
|
261
|
+
length: pathNodes.length - 1,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Fallback: build from the standard node/edge arrays
|
|
269
|
+
if (paths.length === 0 && (result.nodes.length > 0 || result.edges.length > 0)) {
|
|
270
|
+
const nodeNames = result.nodes.map(n => String(n.properties?.['name'] ?? 'unknown'));
|
|
271
|
+
const edgeTypes = result.edges.map(e => e.type);
|
|
272
|
+
|
|
273
|
+
if (nodeNames.length > 0) {
|
|
274
|
+
paths.push({
|
|
275
|
+
nodes: nodeNames,
|
|
276
|
+
edges: edgeTypes,
|
|
277
|
+
length: Math.max(0, nodeNames.length - 1),
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return paths;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function deduplicateNodes(
|
|
286
|
+
nodes: Array<{ name: string; label: string; file_path?: string }>,
|
|
287
|
+
): Array<{ name: string; label: string; file_path?: string }> {
|
|
288
|
+
const seen = new Map<string, { name: string; label: string; file_path?: string }>();
|
|
289
|
+
for (const node of nodes) {
|
|
290
|
+
if (!seen.has(node.name)) {
|
|
291
|
+
seen.set(node.name, node);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return Array.from(seen.values());
|
|
295
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// ingestion-tools.ts — Swarm Learning Phase 4
|
|
2
|
+
// MCP tool handlers for ingesting external data into the graph store.
|
|
3
|
+
// Tools: submit_lsp_edges
|
|
4
|
+
// Designed for VS Code extension and CI pipelines to push type-resolved
|
|
5
|
+
// call edges that supplement the static AST parsing.
|
|
6
|
+
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import type { GraphStore } from '../storage/interfaces.js';
|
|
9
|
+
import { logger } from '../util/logger.js';
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Input schemas
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
const lspEdgeSchema = z.object({
|
|
16
|
+
from_file: z.string().min(1),
|
|
17
|
+
from_symbol: z.string().min(1),
|
|
18
|
+
to_file: z.string().min(1),
|
|
19
|
+
to_symbol: z.string().min(1),
|
|
20
|
+
edge_type: z.string().min(1),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const submitLspEdgesSchema = z.object({
|
|
24
|
+
repo_id: z.string().min(1, 'repo_id is required'),
|
|
25
|
+
edges: z.array(lspEdgeSchema).min(1, 'at least one edge is required'),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Tool factory
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
export function createIngestionTools(graphStore: GraphStore | null) {
|
|
33
|
+
return {
|
|
34
|
+
'submit_lsp_edges': {
|
|
35
|
+
schema: submitLspEdgesSchema,
|
|
36
|
+
description:
|
|
37
|
+
'Submit LSP-resolved call/reference edges to enrich the code graph. ' +
|
|
38
|
+
'Designed for the VS Code extension and CI pipelines. Each edge describes ' +
|
|
39
|
+
'a typed relationship between two symbols (e.g. calls, imports, implements).',
|
|
40
|
+
handler: async (input: z.infer<typeof submitLspEdgesSchema>) => {
|
|
41
|
+
if (!graphStore) {
|
|
42
|
+
return {
|
|
43
|
+
error: 'GRAPH_UNAVAILABLE',
|
|
44
|
+
message:
|
|
45
|
+
'FalkorDB graph store is not available. LSP edges require a running FalkorDB instance.',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const healthy = await graphStore.isHealthy();
|
|
50
|
+
if (!healthy) {
|
|
51
|
+
return {
|
|
52
|
+
error: 'GRAPH_UNAVAILABLE',
|
|
53
|
+
message: 'FalkorDB is not healthy. Cannot ingest LSP edges.',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let accepted = 0;
|
|
58
|
+
let failed = 0;
|
|
59
|
+
const errors: string[] = [];
|
|
60
|
+
|
|
61
|
+
for (const edge of input.edges) {
|
|
62
|
+
try {
|
|
63
|
+
// Upsert the source node (Symbol)
|
|
64
|
+
await graphStore.upsertNode(
|
|
65
|
+
'Symbol',
|
|
66
|
+
{ name: edge.from_symbol, repo_id: input.repo_id },
|
|
67
|
+
{ file_path: edge.from_file, source: 'lsp' },
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
// Upsert the target node (Symbol)
|
|
71
|
+
await graphStore.upsertNode(
|
|
72
|
+
'Symbol',
|
|
73
|
+
{ name: edge.to_symbol, repo_id: input.repo_id },
|
|
74
|
+
{ file_path: edge.to_file, source: 'lsp' },
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// Upsert the edge between the two symbols
|
|
78
|
+
await graphStore.upsertEdge(
|
|
79
|
+
'Symbol',
|
|
80
|
+
{ name: edge.from_symbol, repo_id: input.repo_id },
|
|
81
|
+
edge.edge_type,
|
|
82
|
+
{ source: 'lsp', repo_id: input.repo_id },
|
|
83
|
+
'Symbol',
|
|
84
|
+
{ name: edge.to_symbol, repo_id: input.repo_id },
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
accepted++;
|
|
88
|
+
} catch (err) {
|
|
89
|
+
failed++;
|
|
90
|
+
const msg = `${edge.from_symbol} -[${edge.edge_type}]-> ${edge.to_symbol}: ${String(err)}`;
|
|
91
|
+
errors.push(msg);
|
|
92
|
+
logger.warn('ingestion-tools.submit_lsp_edges: edge failed', {
|
|
93
|
+
from: edge.from_symbol,
|
|
94
|
+
to: edge.to_symbol,
|
|
95
|
+
edgeType: edge.edge_type,
|
|
96
|
+
error: String(err),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
logger.debug('ingestion-tools.submit_lsp_edges: completed', {
|
|
102
|
+
repoId: input.repo_id,
|
|
103
|
+
total: input.edges.length,
|
|
104
|
+
accepted,
|
|
105
|
+
failed,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const result: { accepted: number; failed: number; errors?: string[] } = {
|
|
109
|
+
accepted,
|
|
110
|
+
failed,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
if (errors.length > 0) {
|
|
114
|
+
// Cap error messages to avoid oversized responses
|
|
115
|
+
result.errors = errors.slice(0, 20);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return result;
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// learning-tools.ts — B17
|
|
2
|
+
// MCP tool handlers for knowledge retrieval and confidence management.
|
|
3
|
+
// Tools: get_patterns, get_gotchas, boost_knowledge, decay_knowledge
|
|
4
|
+
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import type { KnowledgeSearch } from '../knowledge/search.js';
|
|
7
|
+
import type { ConfidenceManager } from '../learning/confidence.js';
|
|
8
|
+
import type { QdrantVectorStore } from '../storage/qdrant-store.js';
|
|
9
|
+
import { logger } from '../util/logger.js';
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Input schemas
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
export const getPatternsSchema = z.object({
|
|
16
|
+
domain: z.string().optional(),
|
|
17
|
+
min_confidence: z.number().min(0).max(1).default(0.5),
|
|
18
|
+
limit: z.number().int().min(1).max(50).default(20),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const getGotchasSchema = z.object({
|
|
22
|
+
stack: z.array(z.string()).optional(),
|
|
23
|
+
min_confidence: z.number().min(0).max(1).default(0.3),
|
|
24
|
+
limit: z.number().int().min(1).max(50).default(20),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export const boostKnowledgeSchema = z.object({
|
|
28
|
+
knowledge_id: z.string().min(1, 'knowledge_id is required'),
|
|
29
|
+
amount: z.number().min(0).max(1).default(0.05),
|
|
30
|
+
reason: z.string().optional(),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export const decayKnowledgeSchema = z.object({
|
|
34
|
+
decay_rate: z.number().min(0).max(1).default(0.01),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Tool factory
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
export function createLearningTools(
|
|
42
|
+
knowledgeSearch: KnowledgeSearch,
|
|
43
|
+
confidenceManager?: ConfidenceManager,
|
|
44
|
+
vectorStore?: QdrantVectorStore | null,
|
|
45
|
+
) {
|
|
46
|
+
return {
|
|
47
|
+
'get_patterns': {
|
|
48
|
+
schema: getPatternsSchema,
|
|
49
|
+
description: 'Retrieve established code patterns from the knowledge base. PREFER THIS over ad-hoc code exploration when looking for "how do we do X in this codebase" — it returns curated, high-confidence patterns from past pipeline runs. Optionally filtered by domain/stack.',
|
|
50
|
+
handler: async (input: z.infer<typeof getPatternsSchema>) => {
|
|
51
|
+
try {
|
|
52
|
+
const patterns = await knowledgeSearch.getPatterns(input.domain, input.limit, input.min_confidence);
|
|
53
|
+
|
|
54
|
+
logger.debug('learning-tools.get_patterns: completed', {
|
|
55
|
+
domain: input.domain,
|
|
56
|
+
count: patterns.length,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
patterns: patterns.map(p => ({
|
|
61
|
+
title: p.title,
|
|
62
|
+
content: p.content,
|
|
63
|
+
confidence: p.confidence,
|
|
64
|
+
stack_tags: Array.isArray(p.stack_tags) ? p.stack_tags : [],
|
|
65
|
+
source_repo: (p as { source_repo?: string }).source_repo ?? p.source_agent ?? 'unknown',
|
|
66
|
+
times_confirmed: 1, // Qdrant payload doesn't track this yet
|
|
67
|
+
})),
|
|
68
|
+
};
|
|
69
|
+
} catch (err) {
|
|
70
|
+
logger.error('learning-tools.get_patterns: error', { error: String(err) });
|
|
71
|
+
return {
|
|
72
|
+
error: 'GET_PATTERNS_FAILED',
|
|
73
|
+
message: String(err),
|
|
74
|
+
patterns: [],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
'get_gotchas': {
|
|
81
|
+
schema: getGotchasSchema,
|
|
82
|
+
description: 'Retrieve known gotchas and pitfalls from the knowledge base. ALWAYS CHECK THIS before starting implementation in an indexed repo — avoids repeating past mistakes. Optionally filtered by stack tags.',
|
|
83
|
+
handler: async (input: z.infer<typeof getGotchasSchema>) => {
|
|
84
|
+
try {
|
|
85
|
+
const gotchas = await knowledgeSearch.getGotchas(input.stack, input.limit, input.min_confidence);
|
|
86
|
+
|
|
87
|
+
logger.debug('learning-tools.get_gotchas: completed', {
|
|
88
|
+
stack: input.stack,
|
|
89
|
+
count: gotchas.length,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
gotchas: gotchas.map(g => ({
|
|
94
|
+
title: g.title,
|
|
95
|
+
content: g.content,
|
|
96
|
+
confidence: g.confidence,
|
|
97
|
+
stack_tags: Array.isArray(g.stack_tags) ? g.stack_tags : [],
|
|
98
|
+
source_repo: (g as { source_repo?: string }).source_repo ?? g.source_agent ?? 'unknown',
|
|
99
|
+
})),
|
|
100
|
+
};
|
|
101
|
+
} catch (err) {
|
|
102
|
+
logger.error('learning-tools.get_gotchas: error', { error: String(err) });
|
|
103
|
+
return {
|
|
104
|
+
error: 'GET_GOTCHAS_FAILED',
|
|
105
|
+
message: String(err),
|
|
106
|
+
gotchas: [],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
'boost_knowledge': {
|
|
113
|
+
schema: boostKnowledgeSchema,
|
|
114
|
+
description: 'Boost the confidence score of a specific knowledge item. Used by Knowledge Keeper when a knowledge item proves valuable.',
|
|
115
|
+
handler: async (input: z.infer<typeof boostKnowledgeSchema>) => {
|
|
116
|
+
if (!confidenceManager || !vectorStore) {
|
|
117
|
+
return {
|
|
118
|
+
error: 'CONFIDENCE_UNAVAILABLE',
|
|
119
|
+
message: 'ConfidenceManager or vector store not available. Qdrant may be down.',
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
await confidenceManager.boost(vectorStore, input.knowledge_id, input.amount);
|
|
125
|
+
|
|
126
|
+
logger.debug('learning-tools.boost_knowledge: completed', {
|
|
127
|
+
knowledge_id: input.knowledge_id,
|
|
128
|
+
amount: input.amount,
|
|
129
|
+
reason: input.reason,
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
knowledge_id: input.knowledge_id,
|
|
134
|
+
boosted: true,
|
|
135
|
+
amount: input.amount,
|
|
136
|
+
reason: input.reason,
|
|
137
|
+
};
|
|
138
|
+
} catch (err) {
|
|
139
|
+
logger.error('learning-tools.boost_knowledge: error', { error: String(err) });
|
|
140
|
+
return {
|
|
141
|
+
error: 'BOOST_KNOWLEDGE_FAILED',
|
|
142
|
+
message: String(err),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
'decay_knowledge': {
|
|
149
|
+
schema: decayKnowledgeSchema,
|
|
150
|
+
description: 'Apply time-based confidence decay to all knowledge items. Items not accessed within 30 days lose confidence. Used by Knowledge Keeper for maintenance.',
|
|
151
|
+
handler: async (input: z.infer<typeof decayKnowledgeSchema>) => {
|
|
152
|
+
if (!confidenceManager || !vectorStore) {
|
|
153
|
+
return {
|
|
154
|
+
error: 'CONFIDENCE_UNAVAILABLE',
|
|
155
|
+
message: 'ConfidenceManager or vector store not available. Qdrant may be down.',
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
const decayedCount = await confidenceManager.decayAll(vectorStore, input.decay_rate);
|
|
161
|
+
|
|
162
|
+
logger.debug('learning-tools.decay_knowledge: completed', {
|
|
163
|
+
decay_rate: input.decay_rate,
|
|
164
|
+
decayed_count: decayedCount,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
decayed_count: decayedCount,
|
|
169
|
+
decay_rate: input.decay_rate,
|
|
170
|
+
};
|
|
171
|
+
} catch (err) {
|
|
172
|
+
logger.error('learning-tools.decay_knowledge: error', { error: String(err) });
|
|
173
|
+
return {
|
|
174
|
+
error: 'DECAY_KNOWLEDGE_FAILED',
|
|
175
|
+
message: String(err),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|