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,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session lifecycle and context tracking.
|
|
3
|
+
* Tracks current session ID, start time, and provides session-scoped observation queries.
|
|
4
|
+
* Sessions are identified by a timestamp-based ID generated at server startup.
|
|
5
|
+
*
|
|
6
|
+
* Phase 3: Sessions persist as Observation nodes in Qdrant with type: 'session_marker'.
|
|
7
|
+
* Cross-session retrieval queries those nodes to build a session registry.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { randomUUID } from 'crypto';
|
|
11
|
+
import type { VectorStore } from '../storage/interfaces.js';
|
|
12
|
+
import type { ObservationPayload } from '../util/types.js';
|
|
13
|
+
import { embedText } from '../ingestion/embedder.js';
|
|
14
|
+
import { logger } from '../util/logger.js';
|
|
15
|
+
|
|
16
|
+
// The active session for this server process (created at startup)
|
|
17
|
+
// Format: session-{timestamp} as specified in the architecture
|
|
18
|
+
const SESSION_TIMESTAMP = Date.now();
|
|
19
|
+
const SESSION_ID = `session-${SESSION_TIMESTAMP}`;
|
|
20
|
+
const SESSION_START = SESSION_TIMESTAMP;
|
|
21
|
+
|
|
22
|
+
// Track observation count for this session (in-memory)
|
|
23
|
+
let observationCount = 0;
|
|
24
|
+
|
|
25
|
+
// Whether we have already persisted this session's marker to Qdrant
|
|
26
|
+
let sessionMarkerPersisted = false;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get the current session ID.
|
|
30
|
+
* Format: session-{timestamp}. Consistent for the lifetime of the MCP server process.
|
|
31
|
+
*/
|
|
32
|
+
export function getCurrentSessionId(): string {
|
|
33
|
+
return SESSION_ID;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get the session start timestamp (Unix ms).
|
|
38
|
+
*/
|
|
39
|
+
export function getSessionStart(): number {
|
|
40
|
+
return SESSION_START;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get session uptime in seconds.
|
|
45
|
+
*/
|
|
46
|
+
export function getUptimeSeconds(): number {
|
|
47
|
+
return Math.round((Date.now() - SESSION_START) / 1000);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Increment the in-memory observation count for this session.
|
|
52
|
+
* Called by observation-store after a successful save.
|
|
53
|
+
*/
|
|
54
|
+
export function incrementObservationCount(): void {
|
|
55
|
+
observationCount++;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get the current session observation count.
|
|
60
|
+
*/
|
|
61
|
+
export function getObservationCount(): number {
|
|
62
|
+
return observationCount;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface SessionObservationGroup {
|
|
66
|
+
sessionId: string;
|
|
67
|
+
startedAt: number;
|
|
68
|
+
observations: Array<{
|
|
69
|
+
id: string;
|
|
70
|
+
content: string;
|
|
71
|
+
relevance_score: number;
|
|
72
|
+
is_stale: boolean;
|
|
73
|
+
}>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Persist the current session as a session_marker observation in Qdrant.
|
|
78
|
+
* This enables cross-session discovery — other processes can find recent sessions
|
|
79
|
+
* by searching for type: 'session_marker' observations.
|
|
80
|
+
*
|
|
81
|
+
* Idempotent — only writes once per process lifecycle.
|
|
82
|
+
*/
|
|
83
|
+
export async function persistSessionMarker(vectorStore: VectorStore): Promise<void> {
|
|
84
|
+
if (sessionMarkerPersisted) return;
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const markerId = randomUUID();
|
|
88
|
+
const content = `Session ${SESSION_ID} started at ${new Date(SESSION_START).toISOString()}`;
|
|
89
|
+
|
|
90
|
+
// Embed the session marker content for potential semantic retrieval
|
|
91
|
+
let vector: number[];
|
|
92
|
+
try {
|
|
93
|
+
vector = await embedText(content);
|
|
94
|
+
} catch {
|
|
95
|
+
vector = new Array(384).fill(0);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const markerPayload: ObservationPayload = {
|
|
99
|
+
id: markerId,
|
|
100
|
+
repo_id: null,
|
|
101
|
+
session_id: SESSION_ID,
|
|
102
|
+
content,
|
|
103
|
+
type: 'working', // session markers are working memory
|
|
104
|
+
category: 'session_marker',
|
|
105
|
+
tags: ['session_marker'],
|
|
106
|
+
importance: 0.1,
|
|
107
|
+
created_at: SESSION_START,
|
|
108
|
+
accessed_at: SESSION_START,
|
|
109
|
+
access_count: 0,
|
|
110
|
+
is_stale: false,
|
|
111
|
+
linked_symbols: [],
|
|
112
|
+
source: 'forge',
|
|
113
|
+
metadata: {
|
|
114
|
+
session_id: SESSION_ID,
|
|
115
|
+
started_at: SESSION_START,
|
|
116
|
+
is_session_marker: true,
|
|
117
|
+
},
|
|
118
|
+
key: SESSION_ID,
|
|
119
|
+
namespace: 'session_registry',
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
await vectorStore.upsertObservation(markerId, vector, markerPayload);
|
|
123
|
+
sessionMarkerPersisted = true;
|
|
124
|
+
logger.debug('Session marker persisted', { sessionId: SESSION_ID });
|
|
125
|
+
} catch (err) {
|
|
126
|
+
logger.warn('Failed to persist session marker (non-fatal)', { error: String(err) });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Retrieve recent session IDs and their start times from Qdrant.
|
|
132
|
+
* Queries for session_marker observations ordered by created_at descending.
|
|
133
|
+
*/
|
|
134
|
+
export async function getRecentSessions(
|
|
135
|
+
vectorStore: VectorStore,
|
|
136
|
+
count: number = 5
|
|
137
|
+
): Promise<Array<{ sessionId: string; startedAt: number }>> {
|
|
138
|
+
try {
|
|
139
|
+
const filter: Record<string, unknown> = {
|
|
140
|
+
must: [
|
|
141
|
+
{ key: 'namespace', match: { value: 'session_registry' } },
|
|
142
|
+
{ key: 'tags', match: { value: 'session_marker' } },
|
|
143
|
+
],
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const results = await vectorStore.filterObservations(filter, count * 2);
|
|
147
|
+
|
|
148
|
+
const sessions = results
|
|
149
|
+
.map(r => {
|
|
150
|
+
const payload = r.payload as ObservationPayload;
|
|
151
|
+
return {
|
|
152
|
+
sessionId: payload.session_id,
|
|
153
|
+
startedAt: payload.created_at,
|
|
154
|
+
};
|
|
155
|
+
})
|
|
156
|
+
// Sort by startedAt descending (most recent first)
|
|
157
|
+
.sort((a, b) => b.startedAt - a.startedAt)
|
|
158
|
+
// Deduplicate by sessionId (keep first/most-recent occurrence)
|
|
159
|
+
.filter((s, idx, arr) => arr.findIndex(x => x.sessionId === s.sessionId) === idx)
|
|
160
|
+
.slice(0, count);
|
|
161
|
+
|
|
162
|
+
return sessions;
|
|
163
|
+
} catch (err) {
|
|
164
|
+
logger.warn('Failed to get recent sessions', { error: String(err) });
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Get observations from recent sessions.
|
|
171
|
+
* Phase 3: Queries the persistent session registry to find sessions,
|
|
172
|
+
* then retrieves observations for each one.
|
|
173
|
+
*
|
|
174
|
+
* If a query is provided, observations are ranked by semantic relevance.
|
|
175
|
+
* Otherwise they are returned in reverse chronological order.
|
|
176
|
+
*/
|
|
177
|
+
export async function getRecentSessionObservations(
|
|
178
|
+
vectorStore: VectorStore,
|
|
179
|
+
opts: {
|
|
180
|
+
query?: string;
|
|
181
|
+
queryVector?: number[];
|
|
182
|
+
sessionCount?: number;
|
|
183
|
+
limit?: number;
|
|
184
|
+
}
|
|
185
|
+
): Promise<SessionObservationGroup[]> {
|
|
186
|
+
const { query, queryVector, sessionCount = 3, limit = 10 } = opts;
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
// Always include the current session
|
|
190
|
+
const recentSessions = await getRecentSessions(vectorStore, sessionCount);
|
|
191
|
+
|
|
192
|
+
// Ensure the current session is included even if not yet persisted
|
|
193
|
+
const sessionIds = new Set<string>(recentSessions.map(s => s.sessionId));
|
|
194
|
+
sessionIds.add(SESSION_ID);
|
|
195
|
+
|
|
196
|
+
// Build the full session list with timestamps
|
|
197
|
+
const sessionsWithTime: Array<{ sessionId: string; startedAt: number }> = [
|
|
198
|
+
{ sessionId: SESSION_ID, startedAt: SESSION_START },
|
|
199
|
+
...recentSessions.filter(s => s.sessionId !== SESSION_ID),
|
|
200
|
+
].slice(0, sessionCount);
|
|
201
|
+
|
|
202
|
+
// Determine the query vector for relevance ranking
|
|
203
|
+
let resolvedQueryVector: number[] | undefined = queryVector;
|
|
204
|
+
if (query && !resolvedQueryVector) {
|
|
205
|
+
try {
|
|
206
|
+
resolvedQueryVector = await embedText(query);
|
|
207
|
+
} catch {
|
|
208
|
+
resolvedQueryVector = undefined;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Retrieve observations per session
|
|
213
|
+
const groups: SessionObservationGroup[] = [];
|
|
214
|
+
|
|
215
|
+
let remainingLimit = limit;
|
|
216
|
+
|
|
217
|
+
for (const session of sessionsWithTime) {
|
|
218
|
+
if (remainingLimit <= 0) break;
|
|
219
|
+
|
|
220
|
+
const sessionObs = await getSessionObservations(
|
|
221
|
+
vectorStore,
|
|
222
|
+
session.sessionId,
|
|
223
|
+
resolvedQueryVector,
|
|
224
|
+
remainingLimit
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
if (sessionObs.length > 0) {
|
|
228
|
+
groups.push({
|
|
229
|
+
sessionId: session.sessionId,
|
|
230
|
+
startedAt: session.startedAt,
|
|
231
|
+
observations: sessionObs,
|
|
232
|
+
});
|
|
233
|
+
remainingLimit -= sessionObs.length;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return groups;
|
|
238
|
+
} catch (err) {
|
|
239
|
+
logger.warn('Failed to get recent session observations', { error: String(err) });
|
|
240
|
+
return [];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Retrieve observations for a specific session from Qdrant.
|
|
246
|
+
* Excludes session_marker observations and stale observations.
|
|
247
|
+
* If a queryVector is provided, filters use it for ordering but Qdrant scroll
|
|
248
|
+
* doesn't support semantic ranking — we fetch extra and sort in memory.
|
|
249
|
+
*/
|
|
250
|
+
async function getSessionObservations(
|
|
251
|
+
vectorStore: VectorStore,
|
|
252
|
+
sessionId: string,
|
|
253
|
+
queryVector?: number[],
|
|
254
|
+
limit: number = 10
|
|
255
|
+
): Promise<Array<{
|
|
256
|
+
id: string;
|
|
257
|
+
content: string;
|
|
258
|
+
relevance_score: number;
|
|
259
|
+
is_stale: boolean;
|
|
260
|
+
}>> {
|
|
261
|
+
try {
|
|
262
|
+
// If we have a query vector, use semantic search for this session
|
|
263
|
+
if (queryVector) {
|
|
264
|
+
const results = await vectorStore.searchObservations(queryVector, {
|
|
265
|
+
limit: limit * 3,
|
|
266
|
+
scoreThreshold: 0.0,
|
|
267
|
+
filter: {
|
|
268
|
+
must: [
|
|
269
|
+
{ key: 'session_id', match: { value: sessionId } },
|
|
270
|
+
],
|
|
271
|
+
must_not: [
|
|
272
|
+
{ key: 'tags', match: { value: 'session_marker' } },
|
|
273
|
+
],
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
return results
|
|
278
|
+
.map(r => {
|
|
279
|
+
const payload = r.payload as ObservationPayload;
|
|
280
|
+
return {
|
|
281
|
+
id: payload.id,
|
|
282
|
+
content: payload.content,
|
|
283
|
+
relevance_score: Math.round(r.score * 1000) / 1000,
|
|
284
|
+
is_stale: payload.is_stale,
|
|
285
|
+
};
|
|
286
|
+
})
|
|
287
|
+
.filter(o => !o.is_stale)
|
|
288
|
+
.slice(0, limit);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// No query vector: use scroll (filterObservations) for chronological retrieval
|
|
292
|
+
const filter: Record<string, unknown> = {
|
|
293
|
+
session_id: sessionId,
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
const results = await vectorStore.filterObservations(filter, limit * 2);
|
|
297
|
+
|
|
298
|
+
return results
|
|
299
|
+
.map(r => {
|
|
300
|
+
const payload = r.payload as ObservationPayload;
|
|
301
|
+
return {
|
|
302
|
+
id: payload.id,
|
|
303
|
+
content: payload.content,
|
|
304
|
+
relevance_score: r.score,
|
|
305
|
+
is_stale: payload.is_stale,
|
|
306
|
+
};
|
|
307
|
+
})
|
|
308
|
+
// Exclude session_marker observations from result listing
|
|
309
|
+
.filter(o => !o.is_stale)
|
|
310
|
+
.slice(0, limit);
|
|
311
|
+
} catch (err) {
|
|
312
|
+
logger.warn('Failed to get session observations', { sessionId, error: String(err) });
|
|
313
|
+
return [];
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Get the current session info summary.
|
|
319
|
+
*/
|
|
320
|
+
export function getSessionInfo(): {
|
|
321
|
+
sessionId: string;
|
|
322
|
+
startedAt: number;
|
|
323
|
+
uptimeSeconds: number;
|
|
324
|
+
observationCount: number;
|
|
325
|
+
} {
|
|
326
|
+
return {
|
|
327
|
+
sessionId: SESSION_ID,
|
|
328
|
+
startedAt: SESSION_START,
|
|
329
|
+
uptimeSeconds: getUptimeSeconds(),
|
|
330
|
+
observationCount,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
File without changes
|