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
package/src/index.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// index.ts — B19
|
|
3
|
+
// Entry point for the dk-forge-server MCP server.
|
|
4
|
+
// Starts the server on stdio transport for use with Claude and other MCP clients.
|
|
5
|
+
|
|
6
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
7
|
+
import { createForgeServer } from './server.js';
|
|
8
|
+
|
|
9
|
+
async function main(): Promise<void> {
|
|
10
|
+
const server = await createForgeServer();
|
|
11
|
+
const transport = new StdioServerTransport();
|
|
12
|
+
|
|
13
|
+
// Connect the server to the stdio transport
|
|
14
|
+
await server.connect(transport);
|
|
15
|
+
|
|
16
|
+
// Handle graceful shutdown on SIGINT (Ctrl-C) and SIGTERM
|
|
17
|
+
const shutdown = async (signal: string) => {
|
|
18
|
+
process.stderr.write(`\ndk-forge-server: received ${signal}, shutting down...\n`);
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// Close storage connections if the server exposes a close method
|
|
22
|
+
const serverWithClose = server as typeof server & {
|
|
23
|
+
_closeConnections?: () => Promise<void>;
|
|
24
|
+
};
|
|
25
|
+
if (typeof serverWithClose._closeConnections === 'function') {
|
|
26
|
+
await serverWithClose._closeConnections();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
await server.close();
|
|
30
|
+
} catch (err) {
|
|
31
|
+
process.stderr.write(`dk-forge-server: shutdown error: ${String(err)}\n`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
process.exit(0);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
process.on('SIGINT', () => { void shutdown('SIGINT'); });
|
|
38
|
+
process.on('SIGTERM', () => { void shutdown('SIGTERM'); });
|
|
39
|
+
|
|
40
|
+
// Keep the process alive — stdio transport reads from stdin
|
|
41
|
+
// Node.js will keep running while stdin is open
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
main().catch((err) => {
|
|
45
|
+
process.stderr.write(`dk-forge-server: fatal error: ${String(err)}\n`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
});
|
|
File without changes
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AST-aware code chunker (ADR-5).
|
|
3
|
+
* Primary strategy: each top-level entity becomes one chunk (function, class, interface, etc.)
|
|
4
|
+
* Fallback: fixed-size 512-token chunks with 64-token overlap for non-parseable files.
|
|
5
|
+
* Large entities (>1024 tokens) are split at method boundaries.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createHash } from 'crypto';
|
|
9
|
+
import { randomUUID } from 'crypto';
|
|
10
|
+
import { extname } from 'path';
|
|
11
|
+
import type { ParsedEntity, ParsedImport, CodeChunk, ChunkType } from '../util/types.js';
|
|
12
|
+
import { estimateTokens } from '../util/token-counter.js';
|
|
13
|
+
|
|
14
|
+
const CHUNK_MAX_TOKENS = 1024;
|
|
15
|
+
const FIXED_CHUNK_SIZE_TOKENS = 512;
|
|
16
|
+
const FIXED_CHUNK_OVERLAP_TOKENS = 64;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Generate chunks from parsed AST entities.
|
|
20
|
+
* Called when we have a successful AST parse result.
|
|
21
|
+
*/
|
|
22
|
+
export function chunkFromEntities(
|
|
23
|
+
entities: ParsedEntity[],
|
|
24
|
+
imports: ParsedImport[],
|
|
25
|
+
fileContent: string,
|
|
26
|
+
filePath: string,
|
|
27
|
+
repoId: string,
|
|
28
|
+
language: string,
|
|
29
|
+
indexedAt: number
|
|
30
|
+
): CodeChunk[] {
|
|
31
|
+
const chunks: CodeChunk[] = [];
|
|
32
|
+
|
|
33
|
+
// Generate the file-level chunk (imports + any top-level statements not in entities)
|
|
34
|
+
const fileLevelChunk = buildFileLevelChunk(imports, fileContent, filePath, repoId, language, indexedAt, entities);
|
|
35
|
+
if (fileLevelChunk) chunks.push(fileLevelChunk);
|
|
36
|
+
|
|
37
|
+
// Generate one chunk per entity
|
|
38
|
+
for (const entity of entities) {
|
|
39
|
+
const entityChunks = buildEntityChunks(entity, filePath, repoId, language, indexedAt);
|
|
40
|
+
chunks.push(...entityChunks);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return chunks;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Generate fixed-size chunks for non-parseable files (markdown, JSON, YAML, config).
|
|
48
|
+
*/
|
|
49
|
+
export function chunkFixed(
|
|
50
|
+
content: string,
|
|
51
|
+
filePath: string,
|
|
52
|
+
repoId: string,
|
|
53
|
+
language: string,
|
|
54
|
+
indexedAt: number
|
|
55
|
+
): CodeChunk[] {
|
|
56
|
+
const ext = extname(filePath).toLowerCase();
|
|
57
|
+
const chunkType = detectNonCodeType(ext);
|
|
58
|
+
|
|
59
|
+
// Split content into lines for better boundary detection
|
|
60
|
+
const lines = content.split('\n');
|
|
61
|
+
const chunks: CodeChunk[] = [];
|
|
62
|
+
|
|
63
|
+
let currentLines: string[] = [];
|
|
64
|
+
let currentTokens = 0;
|
|
65
|
+
let startLine = 1;
|
|
66
|
+
|
|
67
|
+
const flushChunk = (endLine: number) => {
|
|
68
|
+
if (currentLines.length === 0) return;
|
|
69
|
+
const chunkContent = buildChunkHeader(filePath, null, chunkType, startLine, endLine) +
|
|
70
|
+
currentLines.join('\n');
|
|
71
|
+
chunks.push(makeChunk(chunkContent, filePath, repoId, chunkType, startLine, endLine, language, indexedAt));
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
for (const line of lines) {
|
|
75
|
+
const lineTokens = estimateTokens(line);
|
|
76
|
+
|
|
77
|
+
if (currentTokens + lineTokens > FIXED_CHUNK_SIZE_TOKENS && currentLines.length > 0) {
|
|
78
|
+
flushChunk(startLine + currentLines.length - 1);
|
|
79
|
+
|
|
80
|
+
// Overlap: keep last N token-equivalent lines
|
|
81
|
+
const overlapLines = getOverlapLines(currentLines, FIXED_CHUNK_OVERLAP_TOKENS);
|
|
82
|
+
startLine = startLine + currentLines.length - overlapLines.length;
|
|
83
|
+
currentLines = overlapLines;
|
|
84
|
+
currentTokens = estimateTokensForLines(overlapLines);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
currentLines.push(line);
|
|
88
|
+
currentTokens += lineTokens;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (currentLines.length > 0) {
|
|
92
|
+
flushChunk(startLine + currentLines.length - 1);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return chunks;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function buildFileLevelChunk(
|
|
99
|
+
imports: ParsedImport[],
|
|
100
|
+
fileContent: string,
|
|
101
|
+
filePath: string,
|
|
102
|
+
repoId: string,
|
|
103
|
+
language: string,
|
|
104
|
+
indexedAt: number,
|
|
105
|
+
entities: ParsedEntity[]
|
|
106
|
+
): CodeChunk | null {
|
|
107
|
+
if (imports.length === 0 && entities.length > 0) return null;
|
|
108
|
+
|
|
109
|
+
// Build import block
|
|
110
|
+
const importLines = imports.map(imp => {
|
|
111
|
+
if (imp.isDefault) {
|
|
112
|
+
return `import ${imp.specifiers} from '${imp.fromPath}';`;
|
|
113
|
+
}
|
|
114
|
+
return `import ${imp.specifiers} from '${imp.fromPath}';`;
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Find the last line of the last import to get file-level lines
|
|
118
|
+
const importBlock = importLines.join('\n');
|
|
119
|
+
if (!importBlock.trim()) return null;
|
|
120
|
+
|
|
121
|
+
const header = buildChunkHeader(filePath, null, 'file_level', 1, importLines.length);
|
|
122
|
+
const content = header + importBlock;
|
|
123
|
+
|
|
124
|
+
if (estimateTokens(content) < 10) return null;
|
|
125
|
+
|
|
126
|
+
return makeChunk(content, filePath, repoId, 'file_level', 1, importLines.length, language, indexedAt);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function buildEntityChunks(
|
|
130
|
+
entity: ParsedEntity,
|
|
131
|
+
filePath: string,
|
|
132
|
+
repoId: string,
|
|
133
|
+
language: string,
|
|
134
|
+
indexedAt: number
|
|
135
|
+
): CodeChunk[] {
|
|
136
|
+
const chunkType = entityTypeToChunkType(entity.type);
|
|
137
|
+
const header = buildChunkHeader(filePath, entity.name, chunkType, entity.startLine, entity.endLine);
|
|
138
|
+
const content = header + entity.sourceText;
|
|
139
|
+
|
|
140
|
+
const tokens = estimateTokens(content);
|
|
141
|
+
|
|
142
|
+
if (tokens <= CHUNK_MAX_TOKENS) {
|
|
143
|
+
// Single chunk for this entity
|
|
144
|
+
return [makeChunk(content, filePath, repoId, chunkType, entity.startLine, entity.endLine, language, indexedAt)];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Entity is too large - split at method/property boundaries (heuristic line split)
|
|
148
|
+
return splitLargeEntity(content, entity, filePath, repoId, chunkType, language, indexedAt);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function splitLargeEntity(
|
|
152
|
+
content: string,
|
|
153
|
+
entity: ParsedEntity,
|
|
154
|
+
filePath: string,
|
|
155
|
+
repoId: string,
|
|
156
|
+
chunkType: ChunkType,
|
|
157
|
+
language: string,
|
|
158
|
+
indexedAt: number
|
|
159
|
+
): CodeChunk[] {
|
|
160
|
+
const chunks: CodeChunk[] = [];
|
|
161
|
+
const lines = content.split('\n');
|
|
162
|
+
let currentLines: string[] = [];
|
|
163
|
+
let currentTokens = 0;
|
|
164
|
+
let chunkIndex = 0;
|
|
165
|
+
let chunkStartLine = entity.startLine;
|
|
166
|
+
|
|
167
|
+
const flush = () => {
|
|
168
|
+
if (currentLines.length === 0) return;
|
|
169
|
+
const chunkContent = currentLines.join('\n');
|
|
170
|
+
const chunkEndLine = chunkStartLine + currentLines.length - 1;
|
|
171
|
+
chunks.push(makeChunk(
|
|
172
|
+
chunkContent,
|
|
173
|
+
filePath, repoId, chunkType,
|
|
174
|
+
chunkStartLine, chunkEndLine,
|
|
175
|
+
language, indexedAt,
|
|
176
|
+
`${entity.name}_part${chunkIndex++}`
|
|
177
|
+
));
|
|
178
|
+
chunkStartLine = chunkEndLine + 1;
|
|
179
|
+
currentLines = [];
|
|
180
|
+
currentTokens = 0;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
for (const line of lines) {
|
|
184
|
+
const lineTokens = estimateTokens(line);
|
|
185
|
+
|
|
186
|
+
if (currentTokens + lineTokens > CHUNK_MAX_TOKENS && currentLines.length > 0) {
|
|
187
|
+
flush();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
currentLines.push(line);
|
|
191
|
+
currentTokens += lineTokens;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
flush();
|
|
195
|
+
return chunks;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function makeChunk(
|
|
199
|
+
content: string,
|
|
200
|
+
filePath: string,
|
|
201
|
+
repoId: string,
|
|
202
|
+
entityType: ChunkType,
|
|
203
|
+
startLine: number,
|
|
204
|
+
endLine: number,
|
|
205
|
+
language: string,
|
|
206
|
+
indexedAt: number,
|
|
207
|
+
entityName?: string
|
|
208
|
+
): CodeChunk {
|
|
209
|
+
const id = randomUUID();
|
|
210
|
+
const contentHash = createHash('sha256').update(content, 'utf8').digest('hex');
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
id,
|
|
214
|
+
repoId,
|
|
215
|
+
filePath,
|
|
216
|
+
entityName: entityName ?? null,
|
|
217
|
+
entityType,
|
|
218
|
+
startLine,
|
|
219
|
+
endLine,
|
|
220
|
+
language,
|
|
221
|
+
contentHash,
|
|
222
|
+
content,
|
|
223
|
+
contentPreview: content.slice(0, 200),
|
|
224
|
+
indexedAt,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function buildChunkHeader(
|
|
229
|
+
filePath: string,
|
|
230
|
+
entityName: string | null,
|
|
231
|
+
entityType: ChunkType,
|
|
232
|
+
startLine: number,
|
|
233
|
+
endLine: number
|
|
234
|
+
): string {
|
|
235
|
+
const nameStr = entityName ? ` ${entityName}` : '';
|
|
236
|
+
return `// [dk-forge] file: ${filePath} | entity:${nameStr} (${entityType}) | lines: ${startLine}-${endLine}\n`;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function entityTypeToChunkType(type: string): ChunkType {
|
|
240
|
+
const map: Record<string, ChunkType> = {
|
|
241
|
+
function: 'function',
|
|
242
|
+
class: 'class',
|
|
243
|
+
interface: 'interface',
|
|
244
|
+
type_alias: 'type_alias',
|
|
245
|
+
variable: 'variable',
|
|
246
|
+
module: 'file_level',
|
|
247
|
+
file: 'file_level',
|
|
248
|
+
};
|
|
249
|
+
return map[type] ?? 'file_level';
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function detectNonCodeType(ext: string): ChunkType {
|
|
253
|
+
if (ext === '.md' || ext === '.mdx') return 'markdown';
|
|
254
|
+
if (ext === '.json' || ext === '.yaml' || ext === '.yml' || ext === '.toml') return 'config';
|
|
255
|
+
if (ext === '.graphql' || ext === '.gql') return 'config';
|
|
256
|
+
if (ext === '.sql') return 'config';
|
|
257
|
+
return 'config';
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function getOverlapLines(lines: string[], targetTokens: number): string[] {
|
|
261
|
+
let tokens = 0;
|
|
262
|
+
const result: string[] = [];
|
|
263
|
+
|
|
264
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
265
|
+
const line = lines[i] ?? '';
|
|
266
|
+
const t = estimateTokens(line);
|
|
267
|
+
if (tokens + t > targetTokens) break;
|
|
268
|
+
result.unshift(line);
|
|
269
|
+
tokens += t;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return result;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function estimateTokensForLines(lines: string[]): number {
|
|
276
|
+
return lines.reduce((sum, line) => sum + estimateTokens(line), 0);
|
|
277
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding pipeline using Transformers.js with ONNX backend (ADR-2).
|
|
3
|
+
* Model: all-MiniLM-L6-v2 (384-dim, ~23 MB quantized, ~5ms/embed).
|
|
4
|
+
* Singleton pattern - expensive to initialize, reuse across all calls.
|
|
5
|
+
* Batch embedding: adaptive batch size (32 for long, 64 for short texts).
|
|
6
|
+
*
|
|
7
|
+
* Phase 5 changes:
|
|
8
|
+
* - Lazy initialization: model loads on first real query, not at startup.
|
|
9
|
+
* - isReady() lets callers surface "model loading..." status.
|
|
10
|
+
* - Adaptive batching: short texts (<100 chars) use batch size 64.
|
|
11
|
+
* - Throughput logging at info level during indexing.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { logger } from '../util/logger.js';
|
|
15
|
+
|
|
16
|
+
const BASE_BATCH_SIZE = 32;
|
|
17
|
+
const SHORT_TEXT_BATCH_SIZE = 64;
|
|
18
|
+
const SHORT_TEXT_THRESHOLD = 100; // chars
|
|
19
|
+
const MODEL_NAME = 'Xenova/all-MiniLM-L6-v2';
|
|
20
|
+
const EMBEDDING_DIMENSION = 384;
|
|
21
|
+
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
+
let pipelineInstance: any = null;
|
|
24
|
+
let initPromise: Promise<void> | null = null;
|
|
25
|
+
let modelReady = false;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Returns true when the embedding pipeline has been initialized and is ready.
|
|
29
|
+
* False means the first embed call will trigger model load (adds ~3-5 seconds).
|
|
30
|
+
*/
|
|
31
|
+
export function isReady(): boolean {
|
|
32
|
+
return modelReady;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Initialize the embedding pipeline (singleton).
|
|
37
|
+
* Lazy: only called on first embed request, not at server startup.
|
|
38
|
+
* Downloads model on first use, uses cached copy thereafter.
|
|
39
|
+
*/
|
|
40
|
+
async function ensurePipeline(): Promise<void> {
|
|
41
|
+
if (pipelineInstance) return;
|
|
42
|
+
if (initPromise) return initPromise;
|
|
43
|
+
|
|
44
|
+
initPromise = (async () => {
|
|
45
|
+
try {
|
|
46
|
+
logger.info('Initializing embedding model (lazy load)', { model: MODEL_NAME });
|
|
47
|
+
const { pipeline, env } = await import('@huggingface/transformers');
|
|
48
|
+
|
|
49
|
+
// Configure cache location
|
|
50
|
+
const cacheDir = process.env.TRANSFORMERS_CACHE ?? undefined;
|
|
51
|
+
if (cacheDir) {
|
|
52
|
+
env.cacheDir = cacheDir;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Use ONNX backend (default in Transformers.js)
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
57
|
+
pipelineInstance = await (pipeline as any)('feature-extraction', MODEL_NAME, {
|
|
58
|
+
dtype: 'q8', // Quantized INT8 for smaller memory footprint
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
modelReady = true;
|
|
62
|
+
logger.info('Embedding model initialized', { model: MODEL_NAME, dimension: EMBEDDING_DIMENSION });
|
|
63
|
+
} catch (err) {
|
|
64
|
+
logger.error('Failed to initialize embedding model', { error: String(err) });
|
|
65
|
+
initPromise = null;
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
})();
|
|
69
|
+
|
|
70
|
+
return initPromise;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Choose optimal batch size based on average text length.
|
|
75
|
+
* Short texts (<100 chars on average) pack more efficiently at batch 64.
|
|
76
|
+
*/
|
|
77
|
+
function chooseBatchSize(texts: string[]): number {
|
|
78
|
+
if (texts.length === 0) return BASE_BATCH_SIZE;
|
|
79
|
+
const avgLen = texts.reduce((s, t) => s + t.length, 0) / texts.length;
|
|
80
|
+
return avgLen < SHORT_TEXT_THRESHOLD ? SHORT_TEXT_BATCH_SIZE : BASE_BATCH_SIZE;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Embed a single text string.
|
|
85
|
+
* Returns a 384-dimensional float array.
|
|
86
|
+
*/
|
|
87
|
+
export async function embedText(text: string): Promise<number[]> {
|
|
88
|
+
await ensurePipeline();
|
|
89
|
+
const result = await pipelineInstance(text, { pooling: 'mean', normalize: true });
|
|
90
|
+
return Array.from(result.data as Float32Array);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Embed multiple texts in adaptive batches.
|
|
95
|
+
* Short texts (< SHORT_TEXT_THRESHOLD chars average) use batch size 64.
|
|
96
|
+
* Long texts use batch size 32.
|
|
97
|
+
* Returns arrays in the same order as input.
|
|
98
|
+
* Logs embedding throughput (texts/sec) at info level.
|
|
99
|
+
*/
|
|
100
|
+
export async function embedBatch(texts: string[]): Promise<number[][]> {
|
|
101
|
+
if (texts.length === 0) return [];
|
|
102
|
+
await ensurePipeline();
|
|
103
|
+
|
|
104
|
+
const batchSize = chooseBatchSize(texts);
|
|
105
|
+
const results: number[][] = [];
|
|
106
|
+
const startTime = Date.now();
|
|
107
|
+
|
|
108
|
+
for (let i = 0; i < texts.length; i += batchSize) {
|
|
109
|
+
const batch = texts.slice(i, i + batchSize);
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
const output = await pipelineInstance(batch, { pooling: 'mean', normalize: true });
|
|
113
|
+
|
|
114
|
+
// output.data is a flat Float32Array: [batch_size * dim]
|
|
115
|
+
const data = output.data as Float32Array;
|
|
116
|
+
const dim = data.length / batch.length;
|
|
117
|
+
|
|
118
|
+
for (let j = 0; j < batch.length; j++) {
|
|
119
|
+
const vector = Array.from(data.slice(j * dim, (j + 1) * dim));
|
|
120
|
+
results.push(vector);
|
|
121
|
+
}
|
|
122
|
+
} catch (err) {
|
|
123
|
+
logger.warn('Embedding batch failed, using zero vectors', {
|
|
124
|
+
batchStart: i,
|
|
125
|
+
batchSize: batch.length,
|
|
126
|
+
error: String(err),
|
|
127
|
+
});
|
|
128
|
+
// Fallback: push zero vectors for failed batch
|
|
129
|
+
for (let j = 0; j < batch.length; j++) {
|
|
130
|
+
results.push(new Array(EMBEDDING_DIMENSION).fill(0));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const elapsedMs = Date.now() - startTime;
|
|
136
|
+
const throughput = elapsedMs > 0 ? Math.round((texts.length / elapsedMs) * 1000) : texts.length;
|
|
137
|
+
logger.info('Embedding batch complete', {
|
|
138
|
+
totalTexts: texts.length,
|
|
139
|
+
batchSize,
|
|
140
|
+
elapsedMs,
|
|
141
|
+
throughputTextsPerSec: throughput,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
return results;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Get the embedding dimension.
|
|
149
|
+
*/
|
|
150
|
+
export function getEmbeddingDimension(): number {
|
|
151
|
+
return EMBEDDING_DIMENSION;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Optionally pre-warm the embedding pipeline in the background.
|
|
156
|
+
*
|
|
157
|
+
* Phase 5: This is now a no-op at the call site — initialization is lazy.
|
|
158
|
+
* The model will load on the first real embed call instead.
|
|
159
|
+
* This function is kept for backward compatibility; callers that previously
|
|
160
|
+
* awaited it will continue to work. The model loads asynchronously without
|
|
161
|
+
* blocking the MCP server startup.
|
|
162
|
+
*/
|
|
163
|
+
export async function warmupEmbedder(): Promise<void> {
|
|
164
|
+
// Do not eagerly load — lazy initialization is handled by ensurePipeline().
|
|
165
|
+
// Log a message so callers know the model will warm on first use.
|
|
166
|
+
logger.info('Embedding pipeline will warm on first use (lazy mode)', { model: MODEL_NAME });
|
|
167
|
+
}
|