javi-forge 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/.gitignore.template +105 -0
- package/.releaserc +44 -0
- package/README.md +45 -0
- package/ai-config/.skillignore +15 -0
- package/ai-config/AUTO_INVOKE.md +300 -0
- package/ai-config/agents/_TEMPLATE.md +93 -0
- package/ai-config/agents/business/api-designer.md +1657 -0
- package/ai-config/agents/business/business-analyst.md +1331 -0
- package/ai-config/agents/business/product-strategist.md +206 -0
- package/ai-config/agents/business/project-manager.md +178 -0
- package/ai-config/agents/business/requirements-analyst.md +1277 -0
- package/ai-config/agents/business/technical-writer.md +1679 -0
- package/ai-config/agents/creative/ux-designer.md +205 -0
- package/ai-config/agents/data-ai/ai-engineer.md +487 -0
- package/ai-config/agents/data-ai/analytics-engineer.md +953 -0
- package/ai-config/agents/data-ai/data-engineer.md +173 -0
- package/ai-config/agents/data-ai/data-scientist.md +672 -0
- package/ai-config/agents/data-ai/mlops-engineer.md +814 -0
- package/ai-config/agents/data-ai/prompt-engineer.md +772 -0
- package/ai-config/agents/development/angular-expert.md +620 -0
- package/ai-config/agents/development/backend-architect.md +795 -0
- package/ai-config/agents/development/database-specialist.md +212 -0
- package/ai-config/agents/development/frontend-specialist.md +686 -0
- package/ai-config/agents/development/fullstack-engineer.md +668 -0
- package/ai-config/agents/development/golang-pro.md +338 -0
- package/ai-config/agents/development/java-enterprise.md +400 -0
- package/ai-config/agents/development/javascript-pro.md +422 -0
- package/ai-config/agents/development/nextjs-pro.md +474 -0
- package/ai-config/agents/development/python-pro.md +570 -0
- package/ai-config/agents/development/react-pro.md +487 -0
- package/ai-config/agents/development/rust-pro.md +246 -0
- package/ai-config/agents/development/spring-boot-4-expert.md +326 -0
- package/ai-config/agents/development/typescript-pro.md +336 -0
- package/ai-config/agents/development/vue-specialist.md +605 -0
- package/ai-config/agents/infrastructure/cloud-architect.md +472 -0
- package/ai-config/agents/infrastructure/deployment-manager.md +358 -0
- package/ai-config/agents/infrastructure/devops-engineer.md +455 -0
- package/ai-config/agents/infrastructure/incident-responder.md +519 -0
- package/ai-config/agents/infrastructure/kubernetes-expert.md +705 -0
- package/ai-config/agents/infrastructure/monitoring-specialist.md +674 -0
- package/ai-config/agents/infrastructure/performance-engineer.md +658 -0
- package/ai-config/agents/orchestrator.md +241 -0
- package/ai-config/agents/quality/accessibility-auditor.md +1204 -0
- package/ai-config/agents/quality/code-reviewer-compact.md +123 -0
- package/ai-config/agents/quality/code-reviewer.md +363 -0
- package/ai-config/agents/quality/dependency-manager.md +743 -0
- package/ai-config/agents/quality/e2e-test-specialist.md +1005 -0
- package/ai-config/agents/quality/performance-tester.md +1086 -0
- package/ai-config/agents/quality/security-auditor.md +133 -0
- package/ai-config/agents/quality/test-engineer.md +453 -0
- package/ai-config/agents/specialists/api-designer.md +87 -0
- package/ai-config/agents/specialists/backend-architect.md +73 -0
- package/ai-config/agents/specialists/code-reviewer.md +77 -0
- package/ai-config/agents/specialists/db-optimizer.md +75 -0
- package/ai-config/agents/specialists/devops-engineer.md +83 -0
- package/ai-config/agents/specialists/documentation-writer.md +78 -0
- package/ai-config/agents/specialists/frontend-developer.md +75 -0
- package/ai-config/agents/specialists/performance-analyst.md +82 -0
- package/ai-config/agents/specialists/refactor-specialist.md +74 -0
- package/ai-config/agents/specialists/security-auditor.md +74 -0
- package/ai-config/agents/specialists/test-engineer.md +81 -0
- package/ai-config/agents/specialists/ux-consultant.md +76 -0
- package/ai-config/agents/specialized/agent-generator.md +1190 -0
- package/ai-config/agents/specialized/blockchain-developer.md +149 -0
- package/ai-config/agents/specialized/code-migrator.md +892 -0
- package/ai-config/agents/specialized/context-manager.md +978 -0
- package/ai-config/agents/specialized/documentation-writer.md +1078 -0
- package/ai-config/agents/specialized/ecommerce-expert.md +1756 -0
- package/ai-config/agents/specialized/embedded-engineer.md +1714 -0
- package/ai-config/agents/specialized/error-detective.md +1034 -0
- package/ai-config/agents/specialized/fintech-specialist.md +1659 -0
- package/ai-config/agents/specialized/freelance-project-planner-v2.md +1988 -0
- package/ai-config/agents/specialized/freelance-project-planner-v3.md +2136 -0
- package/ai-config/agents/specialized/freelance-project-planner-v4.md +4503 -0
- package/ai-config/agents/specialized/freelance-project-planner.md +722 -0
- package/ai-config/agents/specialized/game-developer.md +1963 -0
- package/ai-config/agents/specialized/healthcare-dev.md +1620 -0
- package/ai-config/agents/specialized/mobile-developer.md +188 -0
- package/ai-config/agents/specialized/parallel-plan-executor.md +506 -0
- package/ai-config/agents/specialized/plan-executor.md +485 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/00-INDEX.md +485 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/01-CORE.md +3493 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/02-SELF-CORRECTION.md +778 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/03-PROGRESSIVE-SETUP.md +918 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/04-DEPLOYMENT.md +1537 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/05-TESTING.md +2633 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/06-OPERATIONS.md +5610 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/INSTALL.md +335 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/QUICK-REFERENCE.txt +215 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/README.md +260 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/START-HERE.md +379 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/WORKFLOW-DIAGRAM.md +355 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/solo-dev-planner.md +279 -0
- package/ai-config/agents/specialized/template-writer.md +347 -0
- package/ai-config/agents/specialized/test-runner.md +99 -0
- package/ai-config/agents/specialized/vibekanban-smart-worker.md +244 -0
- package/ai-config/agents/specialized/wave-executor.md +138 -0
- package/ai-config/agents/specialized/workflow-optimizer.md +1114 -0
- package/ai-config/commands/git/changelog.md +32 -0
- package/ai-config/commands/git/ci-local.md +70 -0
- package/ai-config/commands/git/commit.md +35 -0
- package/ai-config/commands/git/fix-issue.md +23 -0
- package/ai-config/commands/git/pr-create.md +42 -0
- package/ai-config/commands/git/pr-review.md +50 -0
- package/ai-config/commands/git/worktree.md +39 -0
- package/ai-config/commands/refactoring/cleanup.md +24 -0
- package/ai-config/commands/refactoring/dead-code.md +40 -0
- package/ai-config/commands/refactoring/extract.md +31 -0
- package/ai-config/commands/testing/e2e.md +30 -0
- package/ai-config/commands/testing/tdd.md +36 -0
- package/ai-config/commands/testing/test-coverage.md +30 -0
- package/ai-config/commands/testing/test-fix.md +24 -0
- package/ai-config/commands/workflow/generate-agents-md.md +85 -0
- package/ai-config/commands/workflow/planning.md +47 -0
- package/ai-config/commands/workflows/compound.md +89 -0
- package/ai-config/commands/workflows/plan.md +77 -0
- package/ai-config/commands/workflows/review.md +78 -0
- package/ai-config/commands/workflows/work.md +75 -0
- package/ai-config/config.yaml +18 -0
- package/ai-config/hooks/_TEMPLATE.md +96 -0
- package/ai-config/hooks/block-dangerous-commands.md +75 -0
- package/ai-config/hooks/commit-guard.md +90 -0
- package/ai-config/hooks/context-loader.md +73 -0
- package/ai-config/hooks/improve-prompt.md +91 -0
- package/ai-config/hooks/learning-log.md +72 -0
- package/ai-config/hooks/model-router.md +86 -0
- package/ai-config/hooks/secret-scanner.md +64 -0
- package/ai-config/hooks/skill-validator.md +102 -0
- package/ai-config/hooks/task-artifact.md +114 -0
- package/ai-config/hooks/validate-workflow.md +100 -0
- package/ai-config/prompts/base.md +71 -0
- package/ai-config/prompts/modes/debug.md +34 -0
- package/ai-config/prompts/modes/deploy.md +40 -0
- package/ai-config/prompts/modes/research.md +32 -0
- package/ai-config/prompts/modes/review.md +33 -0
- package/ai-config/prompts/review-policy.md +79 -0
- package/ai-config/skills/_TEMPLATE.md +157 -0
- package/ai-config/skills/backend/api-gateway/SKILL.md +254 -0
- package/ai-config/skills/backend/bff-concepts/SKILL.md +239 -0
- package/ai-config/skills/backend/bff-spring/SKILL.md +364 -0
- package/ai-config/skills/backend/chi-router/SKILL.md +396 -0
- package/ai-config/skills/backend/error-handling/SKILL.md +255 -0
- package/ai-config/skills/backend/exceptions-spring/SKILL.md +323 -0
- package/ai-config/skills/backend/fastapi/SKILL.md +302 -0
- package/ai-config/skills/backend/gateway-spring/SKILL.md +390 -0
- package/ai-config/skills/backend/go-backend/SKILL.md +457 -0
- package/ai-config/skills/backend/gradle-multimodule/SKILL.md +274 -0
- package/ai-config/skills/backend/graphql-concepts/SKILL.md +352 -0
- package/ai-config/skills/backend/graphql-spring/SKILL.md +398 -0
- package/ai-config/skills/backend/grpc-concepts/SKILL.md +283 -0
- package/ai-config/skills/backend/grpc-spring/SKILL.md +445 -0
- package/ai-config/skills/backend/jwt-auth/SKILL.md +412 -0
- package/ai-config/skills/backend/notifications-concepts/SKILL.md +259 -0
- package/ai-config/skills/backend/recommendations-concepts/SKILL.md +261 -0
- package/ai-config/skills/backend/search-concepts/SKILL.md +263 -0
- package/ai-config/skills/backend/search-spring/SKILL.md +375 -0
- package/ai-config/skills/backend/spring-boot-4/SKILL.md +172 -0
- package/ai-config/skills/backend/websockets/SKILL.md +532 -0
- package/ai-config/skills/data-ai/ai-ml/SKILL.md +423 -0
- package/ai-config/skills/data-ai/analytics-concepts/SKILL.md +195 -0
- package/ai-config/skills/data-ai/analytics-spring/SKILL.md +340 -0
- package/ai-config/skills/data-ai/duckdb-analytics/SKILL.md +440 -0
- package/ai-config/skills/data-ai/langchain/SKILL.md +238 -0
- package/ai-config/skills/data-ai/mlflow/SKILL.md +302 -0
- package/ai-config/skills/data-ai/onnx-inference/SKILL.md +290 -0
- package/ai-config/skills/data-ai/powerbi/SKILL.md +352 -0
- package/ai-config/skills/data-ai/pytorch/SKILL.md +274 -0
- package/ai-config/skills/data-ai/scikit-learn/SKILL.md +321 -0
- package/ai-config/skills/data-ai/vector-db/SKILL.md +301 -0
- package/ai-config/skills/database/graph-databases/SKILL.md +218 -0
- package/ai-config/skills/database/graph-spring/SKILL.md +361 -0
- package/ai-config/skills/database/pgx-postgres/SKILL.md +512 -0
- package/ai-config/skills/database/redis-cache/SKILL.md +343 -0
- package/ai-config/skills/database/sqlite-embedded/SKILL.md +388 -0
- package/ai-config/skills/database/timescaledb/SKILL.md +320 -0
- package/ai-config/skills/docs/api-documentation/SKILL.md +293 -0
- package/ai-config/skills/docs/docs-spring/SKILL.md +377 -0
- package/ai-config/skills/docs/mustache-templates/SKILL.md +190 -0
- package/ai-config/skills/docs/technical-docs/SKILL.md +447 -0
- package/ai-config/skills/frontend/astro-ssr/SKILL.md +441 -0
- package/ai-config/skills/frontend/frontend-design/SKILL.md +54 -0
- package/ai-config/skills/frontend/frontend-web/SKILL.md +368 -0
- package/ai-config/skills/frontend/mantine-ui/SKILL.md +396 -0
- package/ai-config/skills/frontend/tanstack-query/SKILL.md +439 -0
- package/ai-config/skills/frontend/zod-validation/SKILL.md +417 -0
- package/ai-config/skills/frontend/zustand-state/SKILL.md +350 -0
- package/ai-config/skills/infrastructure/chaos-engineering/SKILL.md +244 -0
- package/ai-config/skills/infrastructure/chaos-spring/SKILL.md +378 -0
- package/ai-config/skills/infrastructure/devops-infra/SKILL.md +435 -0
- package/ai-config/skills/infrastructure/docker-containers/SKILL.md +420 -0
- package/ai-config/skills/infrastructure/kubernetes/SKILL.md +456 -0
- package/ai-config/skills/infrastructure/opentelemetry/SKILL.md +546 -0
- package/ai-config/skills/infrastructure/traefik-proxy/SKILL.md +474 -0
- package/ai-config/skills/infrastructure/woodpecker-ci/SKILL.md +315 -0
- package/ai-config/skills/mobile/ionic-capacitor/SKILL.md +504 -0
- package/ai-config/skills/mobile/mobile-ionic/SKILL.md +448 -0
- package/ai-config/skills/prompt-improver/SKILL.md +125 -0
- package/ai-config/skills/quality/ghagga-review/SKILL.md +216 -0
- package/ai-config/skills/references/hooks-patterns/SKILL.md +238 -0
- package/ai-config/skills/references/mcp-servers/SKILL.md +275 -0
- package/ai-config/skills/references/plugins-reference/SKILL.md +110 -0
- package/ai-config/skills/references/skills-reference/SKILL.md +420 -0
- package/ai-config/skills/references/subagent-templates/SKILL.md +193 -0
- package/ai-config/skills/systems-iot/modbus-protocol/SKILL.md +410 -0
- package/ai-config/skills/systems-iot/mqtt-rumqttc/SKILL.md +408 -0
- package/ai-config/skills/systems-iot/rust-systems/SKILL.md +386 -0
- package/ai-config/skills/systems-iot/tokio-async/SKILL.md +324 -0
- package/ai-config/skills/testing/playwright-e2e/SKILL.md +289 -0
- package/ai-config/skills/testing/testcontainers/SKILL.md +299 -0
- package/ai-config/skills/testing/vitest-testing/SKILL.md +381 -0
- package/ai-config/skills/workflow/ci-local-guide/SKILL.md +118 -0
- package/ai-config/skills/workflow/claude-automation-recommender/SKILL.md +299 -0
- package/ai-config/skills/workflow/claude-md-improver/SKILL.md +158 -0
- package/ai-config/skills/workflow/finishing-a-development-branch/SKILL.md +117 -0
- package/ai-config/skills/workflow/git-github/SKILL.md +334 -0
- package/ai-config/skills/workflow/git-github/references/examples.md +160 -0
- package/ai-config/skills/workflow/git-workflow/SKILL.md +214 -0
- package/ai-config/skills/workflow/ide-plugins/SKILL.md +277 -0
- package/ai-config/skills/workflow/ide-plugins-intellij/SKILL.md +401 -0
- package/ai-config/skills/workflow/obsidian-brain-workflow/SKILL.md +199 -0
- package/ai-config/skills/workflow/using-git-worktrees/SKILL.md +100 -0
- package/ai-config/skills/workflow/verification-before-completion/SKILL.md +73 -0
- package/ai-config/skills/workflow/wave-workflow/SKILL.md +178 -0
- package/ci-local/README.md +170 -0
- package/ci-local/ci-local.sh +297 -0
- package/ci-local/hooks/commit-msg +74 -0
- package/ci-local/hooks/pre-commit +162 -0
- package/ci-local/hooks/pre-push +41 -0
- package/ci-local/install.sh +49 -0
- package/ci-local/semgrep.yml +214 -0
- package/dist/commands/analyze.d.ts +9 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +55 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/analyze.test.d.ts +2 -0
- package/dist/commands/analyze.test.d.ts.map +1 -0
- package/dist/commands/analyze.test.js +145 -0
- package/dist/commands/analyze.test.js.map +1 -0
- package/dist/commands/doctor.d.ts +7 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +158 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/doctor.test.d.ts +2 -0
- package/dist/commands/doctor.test.d.ts.map +1 -0
- package/dist/commands/doctor.test.js +200 -0
- package/dist/commands/doctor.test.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +283 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/init.test.d.ts +2 -0
- package/dist/commands/init.test.d.ts.map +1 -0
- package/dist/commands/init.test.js +271 -0
- package/dist/commands/init.test.js.map +1 -0
- package/dist/commands/sync.d.ts +8 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +201 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/constants.d.ts +21 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +57 -0
- package/dist/constants.js.map +1 -0
- package/dist/e2e/aggressive.e2e.test.d.ts +2 -0
- package/dist/e2e/aggressive.e2e.test.d.ts.map +1 -0
- package/dist/e2e/aggressive.e2e.test.js +350 -0
- package/dist/e2e/aggressive.e2e.test.js.map +1 -0
- package/dist/e2e/commands.e2e.test.d.ts +2 -0
- package/dist/e2e/commands.e2e.test.d.ts.map +1 -0
- package/dist/e2e/commands.e2e.test.js +213 -0
- package/dist/e2e/commands.e2e.test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +82 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/common.d.ts +17 -0
- package/dist/lib/common.d.ts.map +1 -0
- package/dist/lib/common.js +111 -0
- package/dist/lib/common.js.map +1 -0
- package/dist/lib/common.test.d.ts +2 -0
- package/dist/lib/common.test.d.ts.map +1 -0
- package/dist/lib/common.test.js +316 -0
- package/dist/lib/common.test.js.map +1 -0
- package/dist/lib/frontmatter.d.ts +18 -0
- package/dist/lib/frontmatter.d.ts.map +1 -0
- package/dist/lib/frontmatter.js +61 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/frontmatter.test.d.ts +2 -0
- package/dist/lib/frontmatter.test.d.ts.map +1 -0
- package/dist/lib/frontmatter.test.js +257 -0
- package/dist/lib/frontmatter.test.js.map +1 -0
- package/dist/lib/template.d.ts +24 -0
- package/dist/lib/template.d.ts.map +1 -0
- package/dist/lib/template.js +78 -0
- package/dist/lib/template.js.map +1 -0
- package/dist/lib/template.test.d.ts +2 -0
- package/dist/lib/template.test.d.ts.map +1 -0
- package/dist/lib/template.test.js +201 -0
- package/dist/lib/template.test.js.map +1 -0
- package/dist/types/index.d.ts +48 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui/AnalyzeUI.d.ts +7 -0
- package/dist/ui/AnalyzeUI.d.ts.map +1 -0
- package/dist/ui/AnalyzeUI.js +100 -0
- package/dist/ui/AnalyzeUI.js.map +1 -0
- package/dist/ui/App.d.ts +13 -0
- package/dist/ui/App.d.ts.map +1 -0
- package/dist/ui/App.js +100 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/CIContext.d.ts +9 -0
- package/dist/ui/CIContext.d.ts.map +1 -0
- package/dist/ui/CIContext.js +9 -0
- package/dist/ui/CIContext.js.map +1 -0
- package/dist/ui/CISelector.d.ts +8 -0
- package/dist/ui/CISelector.d.ts.map +1 -0
- package/dist/ui/CISelector.js +45 -0
- package/dist/ui/CISelector.js.map +1 -0
- package/dist/ui/Doctor.d.ts +3 -0
- package/dist/ui/Doctor.d.ts.map +1 -0
- package/dist/ui/Doctor.js +89 -0
- package/dist/ui/Doctor.js.map +1 -0
- package/dist/ui/Header.d.ts +8 -0
- package/dist/ui/Header.d.ts.map +1 -0
- package/dist/ui/Header.js +30 -0
- package/dist/ui/Header.js.map +1 -0
- package/dist/ui/MemorySelector.d.ts +8 -0
- package/dist/ui/MemorySelector.d.ts.map +1 -0
- package/dist/ui/MemorySelector.js +46 -0
- package/dist/ui/MemorySelector.js.map +1 -0
- package/dist/ui/NameInput.d.ts +8 -0
- package/dist/ui/NameInput.d.ts.map +1 -0
- package/dist/ui/NameInput.js +69 -0
- package/dist/ui/NameInput.js.map +1 -0
- package/dist/ui/OptionSelector.d.ts +12 -0
- package/dist/ui/OptionSelector.d.ts.map +1 -0
- package/dist/ui/OptionSelector.js +69 -0
- package/dist/ui/OptionSelector.js.map +1 -0
- package/dist/ui/Progress.d.ts +11 -0
- package/dist/ui/Progress.d.ts.map +1 -0
- package/dist/ui/Progress.js +58 -0
- package/dist/ui/Progress.js.map +1 -0
- package/dist/ui/StackSelector.d.ts +9 -0
- package/dist/ui/StackSelector.d.ts.map +1 -0
- package/dist/ui/StackSelector.js +65 -0
- package/dist/ui/StackSelector.js.map +1 -0
- package/dist/ui/Summary.d.ts +12 -0
- package/dist/ui/Summary.d.ts.map +1 -0
- package/dist/ui/Summary.js +114 -0
- package/dist/ui/Summary.js.map +1 -0
- package/dist/ui/SyncUI.d.ts +10 -0
- package/dist/ui/SyncUI.d.ts.map +1 -0
- package/dist/ui/SyncUI.js +64 -0
- package/dist/ui/SyncUI.js.map +1 -0
- package/dist/ui/Welcome.d.ts +7 -0
- package/dist/ui/Welcome.d.ts.map +1 -0
- package/dist/ui/Welcome.js +45 -0
- package/dist/ui/Welcome.js.map +1 -0
- package/dist/ui/theme.d.ts +10 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js +9 -0
- package/dist/ui/theme.js.map +1 -0
- package/modules/engram/.gitignore-snippet.txt +6 -0
- package/modules/engram/.mcp-config-snippet.json +11 -0
- package/modules/engram/README.md +146 -0
- package/modules/engram/install-engram.sh +216 -0
- package/modules/ghagga/.env.example +43 -0
- package/modules/ghagga/README.md +153 -0
- package/modules/ghagga/docker-compose.yml +80 -0
- package/modules/ghagga/setup-ghagga.sh +139 -0
- package/modules/memory-simple/.project/NOTES.md +22 -0
- package/modules/memory-simple/README.md +23 -0
- package/modules/obsidian-brain/.obsidian/app.json +23 -0
- package/modules/obsidian-brain/.obsidian/appearance.json +5 -0
- package/modules/obsidian-brain/.obsidian/bookmarks.json +34 -0
- package/modules/obsidian-brain/.obsidian/community-plugins.json +1 -0
- package/modules/obsidian-brain/.obsidian/core-plugins-migration.json +21 -0
- package/modules/obsidian-brain/.obsidian/core-plugins.json +18 -0
- package/modules/obsidian-brain/.obsidian/daily-notes.json +5 -0
- package/modules/obsidian-brain/.obsidian/graph.json +37 -0
- package/modules/obsidian-brain/.obsidian/hotkeys.json +14 -0
- package/modules/obsidian-brain/.obsidian/plugins/dataview/data.json +25 -0
- package/modules/obsidian-brain/.obsidian/plugins/obsidian-kanban/data.json +29 -0
- package/modules/obsidian-brain/.obsidian/plugins/templater-obsidian/data.json +18 -0
- package/modules/obsidian-brain/.obsidian/snippets/project-memory.css +71 -0
- package/modules/obsidian-brain/.obsidian-gitignore-snippet.txt +8 -0
- package/modules/obsidian-brain/.project/Attachments/.gitkeep +0 -0
- package/modules/obsidian-brain/.project/Memory/BLOCKERS.md +78 -0
- package/modules/obsidian-brain/.project/Memory/CONTEXT.md +102 -0
- package/modules/obsidian-brain/.project/Memory/DASHBOARD.md +73 -0
- package/modules/obsidian-brain/.project/Memory/DECISIONS.md +87 -0
- package/modules/obsidian-brain/.project/Memory/KANBAN.md +15 -0
- package/modules/obsidian-brain/.project/Memory/README.md +61 -0
- package/modules/obsidian-brain/.project/Memory/WAVES.md +78 -0
- package/modules/obsidian-brain/.project/Sessions/TEMPLATE.md +99 -0
- package/modules/obsidian-brain/.project/Templates/ADR.md +33 -0
- package/modules/obsidian-brain/.project/Templates/Blocker.md +21 -0
- package/modules/obsidian-brain/.project/Templates/Session.md +88 -0
- package/modules/obsidian-brain/README.md +268 -0
- package/modules/obsidian-brain/new-wave.sh +182 -0
- package/package.json +51 -0
- package/schemas/agent.schema.json +34 -0
- package/schemas/ai-config.schema.json +28 -0
- package/schemas/skill.schema.json +44 -0
- package/src/commands/analyze.test.ts +145 -0
- package/src/commands/analyze.ts +69 -0
- package/src/commands/doctor.test.ts +208 -0
- package/src/commands/doctor.ts +163 -0
- package/src/commands/init.test.ts +298 -0
- package/src/commands/init.ts +285 -0
- package/src/constants.ts +69 -0
- package/src/e2e/aggressive.e2e.test.ts +557 -0
- package/src/e2e/commands.e2e.test.ts +298 -0
- package/src/index.tsx +106 -0
- package/src/lib/common.test.ts +318 -0
- package/src/lib/common.ts +127 -0
- package/src/lib/frontmatter.test.ts +291 -0
- package/src/lib/frontmatter.ts +77 -0
- package/src/lib/template.test.ts +226 -0
- package/src/lib/template.ts +99 -0
- package/src/types/index.ts +53 -0
- package/src/ui/AnalyzeUI.tsx +133 -0
- package/src/ui/App.tsx +175 -0
- package/src/ui/CIContext.tsx +25 -0
- package/src/ui/CISelector.tsx +72 -0
- package/src/ui/Doctor.tsx +122 -0
- package/src/ui/Header.tsx +48 -0
- package/src/ui/MemorySelector.tsx +73 -0
- package/src/ui/NameInput.tsx +82 -0
- package/src/ui/OptionSelector.tsx +100 -0
- package/src/ui/Progress.tsx +88 -0
- package/src/ui/StackSelector.tsx +101 -0
- package/src/ui/Summary.tsx +134 -0
- package/src/ui/Welcome.tsx +54 -0
- package/src/ui/theme.ts +10 -0
- package/stryker.config.json +19 -0
- package/tasks/_TEMPLATE/files-edited.md +3 -0
- package/tasks/_TEMPLATE/plan.md +3 -0
- package/tasks/_TEMPLATE/research.md +3 -0
- package/tasks/_TEMPLATE/verification.md +5 -0
- package/templates/common/dependabot/cargo.yml +11 -0
- package/templates/common/dependabot/github-actions.yml +16 -0
- package/templates/common/dependabot/gomod.yml +15 -0
- package/templates/common/dependabot/gradle.yml +15 -0
- package/templates/common/dependabot/header.yml +3 -0
- package/templates/common/dependabot/maven.yml +15 -0
- package/templates/common/dependabot/npm.yml +20 -0
- package/templates/common/dependabot/pip.yml +11 -0
- package/templates/dependabot.yml +162 -0
- package/templates/github/ci-go.yml +41 -0
- package/templates/github/ci-java.yml +45 -0
- package/templates/github/ci-monorepo.yml +150 -0
- package/templates/github/ci-node.yml +42 -0
- package/templates/github/ci-python.yml +42 -0
- package/templates/github/ci-rust.yml +42 -0
- package/templates/github/dependabot-automerge.yml +40 -0
- package/templates/gitlab/gitlab-ci-go.yml +88 -0
- package/templates/gitlab/gitlab-ci-java.yml +79 -0
- package/templates/gitlab/gitlab-ci-monorepo.yml +126 -0
- package/templates/gitlab/gitlab-ci-node.yml +63 -0
- package/templates/gitlab/gitlab-ci-python.yml +147 -0
- package/templates/gitlab/gitlab-ci-rust.yml +67 -0
- package/templates/global/claude-settings.json +98 -0
- package/templates/global/codex-config.toml +8 -0
- package/templates/global/copilot-instructions/base-rules.instructions.md +13 -0
- package/templates/global/copilot-instructions/sdd-orchestrator.instructions.md +37 -0
- package/templates/global/gemini-commands/cleanup.toml +20 -0
- package/templates/global/gemini-commands/commit.toml +15 -0
- package/templates/global/gemini-commands/dead-code.toml +22 -0
- package/templates/global/gemini-commands/plan.toml +30 -0
- package/templates/global/gemini-commands/review.toml +17 -0
- package/templates/global/gemini-commands/sdd-apply.toml +22 -0
- package/templates/global/gemini-commands/sdd-ff.toml +14 -0
- package/templates/global/gemini-commands/sdd-new.toml +21 -0
- package/templates/global/gemini-commands/sdd-verify.toml +21 -0
- package/templates/global/gemini-commands/tdd.toml +26 -0
- package/templates/global/gemini-settings.json +8 -0
- package/templates/global/opencode-config.json +44 -0
- package/templates/global/sdd-instructions.md +47 -0
- package/templates/global/sdd-orchestrator-claude.md +46 -0
- package/templates/global/sdd-orchestrator-copilot.md +34 -0
- package/templates/renovate.json +69 -0
- package/templates/woodpecker/monorepo/backend.yml +34 -0
- package/templates/woodpecker/monorepo/frontend.yml +34 -0
- package/templates/woodpecker/monorepo/summary.yml +25 -0
- package/templates/woodpecker/woodpecker-go.yml +51 -0
- package/templates/woodpecker/woodpecker-java.yml +67 -0
- package/templates/woodpecker/woodpecker-node.yml +47 -0
- package/templates/woodpecker/woodpecker-python.yml +108 -0
- package/templates/woodpecker/woodpecker-rust.yml +57 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +16 -0
- package/workflows/reusable-build-go.yml +111 -0
- package/workflows/reusable-build-java.yml +120 -0
- package/workflows/reusable-build-node.yml +145 -0
- package/workflows/reusable-build-python.yml +159 -0
- package/workflows/reusable-build-rust.yml +135 -0
- package/workflows/reusable-docker.yml +120 -0
- package/workflows/reusable-ghagga-review.yml +165 -0
- package/workflows/reusable-release.yml +91 -0
|
@@ -0,0 +1,978 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: context-manager
|
|
3
|
+
description: Advanced session continuity, memory management, context preservation, and intelligent state handling
|
|
4
|
+
trigger: >
|
|
5
|
+
context window, session state, memory management, context preservation,
|
|
6
|
+
long conversation, session continuity, state handling, context compression
|
|
7
|
+
category: specialized
|
|
8
|
+
color: purple
|
|
9
|
+
tools: Write, Read, MultiEdit, Bash, Grep, Glob, Task
|
|
10
|
+
config:
|
|
11
|
+
model: opus
|
|
12
|
+
metadata:
|
|
13
|
+
version: "2.0"
|
|
14
|
+
updated: "2026-02"
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
You are a context management specialist with expertise in session continuity, memory optimization, state preservation, and intelligent context handling for complex workflows.
|
|
18
|
+
|
|
19
|
+
## Core Expertise
|
|
20
|
+
- Session state management and persistence
|
|
21
|
+
- Context window optimization and compression
|
|
22
|
+
- Memory management and garbage collection
|
|
23
|
+
- State machine design and implementation
|
|
24
|
+
- Distributed session management
|
|
25
|
+
- Context switching and restoration
|
|
26
|
+
- Cache management and optimization
|
|
27
|
+
- Event sourcing and CQRS patterns
|
|
28
|
+
|
|
29
|
+
## Technical Stack
|
|
30
|
+
- **State Management**: Redux, MobX, Zustand, XState
|
|
31
|
+
- **Persistence**: Redis, Memcached, IndexedDB, LocalStorage
|
|
32
|
+
- **Session**: JWT, OAuth, Session cookies, WebSockets
|
|
33
|
+
- **Caching**: Varnish, CloudFlare, CDN strategies
|
|
34
|
+
- **Databases**: PostgreSQL, MongoDB, DynamoDB, Cassandra
|
|
35
|
+
- **Message Queues**: RabbitMQ, Kafka, Redis Pub/Sub
|
|
36
|
+
- **Monitoring**: OpenTelemetry, Jaeger, Datadog
|
|
37
|
+
|
|
38
|
+
## Advanced Context Management Framework
|
|
39
|
+
```typescript
|
|
40
|
+
// context-manager.ts
|
|
41
|
+
import { EventEmitter } from 'events';
|
|
42
|
+
import * as crypto from 'crypto';
|
|
43
|
+
import { LRUCache } from 'lru-cache';
|
|
44
|
+
import { compress, decompress } from 'lz-string';
|
|
45
|
+
|
|
46
|
+
interface ContextState {
|
|
47
|
+
id: string;
|
|
48
|
+
sessionId: string;
|
|
49
|
+
userId?: string;
|
|
50
|
+
data: Map<string, any>;
|
|
51
|
+
metadata: ContextMetadata;
|
|
52
|
+
history: ContextHistory[];
|
|
53
|
+
checkpoints: Checkpoint[];
|
|
54
|
+
created: Date;
|
|
55
|
+
lastAccessed: Date;
|
|
56
|
+
ttl?: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface ContextMetadata {
|
|
60
|
+
version: string;
|
|
61
|
+
environment: string;
|
|
62
|
+
features: Set<string>;
|
|
63
|
+
permissions: Map<string, boolean>;
|
|
64
|
+
tags: string[];
|
|
65
|
+
priority: number;
|
|
66
|
+
compressed: boolean;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface ContextHistory {
|
|
70
|
+
timestamp: Date;
|
|
71
|
+
action: string;
|
|
72
|
+
changes: Map<string, any>;
|
|
73
|
+
userId?: string;
|
|
74
|
+
metadata?: any;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
interface Checkpoint {
|
|
78
|
+
id: string;
|
|
79
|
+
timestamp: Date;
|
|
80
|
+
state: string; // Compressed state
|
|
81
|
+
description?: string;
|
|
82
|
+
automatic: boolean;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
class ContextManager extends EventEmitter {
|
|
86
|
+
private contexts: Map<string, ContextState>;
|
|
87
|
+
private cache: LRUCache<string, any>;
|
|
88
|
+
private compressionThreshold: number = 1024; // 1KB
|
|
89
|
+
private maxHistorySize: number = 100;
|
|
90
|
+
private maxCheckpoints: number = 10;
|
|
91
|
+
private autoSaveInterval: number = 60000; // 1 minute
|
|
92
|
+
private storage: StorageAdapter;
|
|
93
|
+
|
|
94
|
+
constructor(options: ContextManagerOptions = {}) {
|
|
95
|
+
super();
|
|
96
|
+
this.contexts = new Map();
|
|
97
|
+
this.cache = new LRUCache({
|
|
98
|
+
max: options.maxCacheSize || 500,
|
|
99
|
+
ttl: options.cacheTTL || 1000 * 60 * 60, // 1 hour
|
|
100
|
+
updateAgeOnGet: true,
|
|
101
|
+
updateAgeOnHas: true,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
this.storage = options.storage || new InMemoryStorage();
|
|
105
|
+
this.compressionThreshold = options.compressionThreshold || this.compressionThreshold;
|
|
106
|
+
|
|
107
|
+
if (options.autoSave) {
|
|
108
|
+
this.startAutoSave();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
this.setupEventHandlers();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async createContext(sessionId: string, initialData?: any): Promise<string> {
|
|
115
|
+
const contextId = this.generateContextId();
|
|
116
|
+
|
|
117
|
+
const context: ContextState = {
|
|
118
|
+
id: contextId,
|
|
119
|
+
sessionId,
|
|
120
|
+
data: new Map(Object.entries(initialData || {})),
|
|
121
|
+
metadata: {
|
|
122
|
+
version: '1.0.0',
|
|
123
|
+
environment: process.env.NODE_ENV || 'development',
|
|
124
|
+
features: new Set(),
|
|
125
|
+
permissions: new Map(),
|
|
126
|
+
tags: [],
|
|
127
|
+
priority: 0,
|
|
128
|
+
compressed: false,
|
|
129
|
+
},
|
|
130
|
+
history: [],
|
|
131
|
+
checkpoints: [],
|
|
132
|
+
created: new Date(),
|
|
133
|
+
lastAccessed: new Date(),
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
this.contexts.set(contextId, context);
|
|
137
|
+
await this.saveContext(contextId);
|
|
138
|
+
|
|
139
|
+
this.emit('context:created', { contextId, sessionId });
|
|
140
|
+
|
|
141
|
+
return contextId;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async getContext(contextId: string): Promise<ContextState | null> {
|
|
145
|
+
// Check in-memory first
|
|
146
|
+
let context = this.contexts.get(contextId);
|
|
147
|
+
|
|
148
|
+
// Check cache
|
|
149
|
+
if (!context) {
|
|
150
|
+
context = this.cache.get(contextId);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Load from storage
|
|
154
|
+
if (!context) {
|
|
155
|
+
context = await this.loadContext(contextId);
|
|
156
|
+
if (context) {
|
|
157
|
+
this.contexts.set(contextId, context);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (context) {
|
|
162
|
+
context.lastAccessed = new Date();
|
|
163
|
+
this.emit('context:accessed', { contextId });
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return context;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async updateContext(
|
|
170
|
+
contextId: string,
|
|
171
|
+
updates: Partial<any>,
|
|
172
|
+
options: UpdateOptions = {}
|
|
173
|
+
): Promise<void> {
|
|
174
|
+
const context = await this.getContext(contextId);
|
|
175
|
+
if (!context) {
|
|
176
|
+
throw new Error(`Context ${contextId} not found`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Record history
|
|
180
|
+
if (!options.skipHistory) {
|
|
181
|
+
this.addHistory(context, {
|
|
182
|
+
timestamp: new Date(),
|
|
183
|
+
action: options.action || 'update',
|
|
184
|
+
changes: new Map(Object.entries(updates)),
|
|
185
|
+
userId: options.userId,
|
|
186
|
+
metadata: options.metadata,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Apply updates
|
|
191
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
192
|
+
if (value === undefined) {
|
|
193
|
+
context.data.delete(key);
|
|
194
|
+
} else {
|
|
195
|
+
context.data.set(key, value);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Create checkpoint if needed
|
|
200
|
+
if (options.checkpoint) {
|
|
201
|
+
await this.createCheckpoint(contextId, options.checkpointDescription);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Save to storage
|
|
205
|
+
if (!options.skipSave) {
|
|
206
|
+
await this.saveContext(contextId);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
this.emit('context:updated', { contextId, updates });
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async createCheckpoint(
|
|
213
|
+
contextId: string,
|
|
214
|
+
description?: string
|
|
215
|
+
): Promise<string> {
|
|
216
|
+
const context = await this.getContext(contextId);
|
|
217
|
+
if (!context) {
|
|
218
|
+
throw new Error(`Context ${contextId} not found`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const checkpointId = this.generateCheckpointId();
|
|
222
|
+
const state = await this.serializeContext(context);
|
|
223
|
+
|
|
224
|
+
const checkpoint: Checkpoint = {
|
|
225
|
+
id: checkpointId,
|
|
226
|
+
timestamp: new Date(),
|
|
227
|
+
state: compress(state),
|
|
228
|
+
description,
|
|
229
|
+
automatic: !description,
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
context.checkpoints.push(checkpoint);
|
|
233
|
+
|
|
234
|
+
// Maintain max checkpoints
|
|
235
|
+
if (context.checkpoints.length > this.maxCheckpoints) {
|
|
236
|
+
context.checkpoints.shift();
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
await this.saveContext(contextId);
|
|
240
|
+
|
|
241
|
+
this.emit('checkpoint:created', { contextId, checkpointId });
|
|
242
|
+
|
|
243
|
+
return checkpointId;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async restoreCheckpoint(
|
|
247
|
+
contextId: string,
|
|
248
|
+
checkpointId: string
|
|
249
|
+
): Promise<void> {
|
|
250
|
+
const context = await this.getContext(contextId);
|
|
251
|
+
if (!context) {
|
|
252
|
+
throw new Error(`Context ${contextId} not found`);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const checkpoint = context.checkpoints.find(cp => cp.id === checkpointId);
|
|
256
|
+
if (!checkpoint) {
|
|
257
|
+
throw new Error(`Checkpoint ${checkpointId} not found`);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const restoredState = JSON.parse(decompress(checkpoint.state));
|
|
261
|
+
|
|
262
|
+
// Restore data
|
|
263
|
+
context.data = new Map(Object.entries(restoredState.data));
|
|
264
|
+
context.metadata = restoredState.metadata;
|
|
265
|
+
|
|
266
|
+
// Add restoration to history
|
|
267
|
+
this.addHistory(context, {
|
|
268
|
+
timestamp: new Date(),
|
|
269
|
+
action: 'restore_checkpoint',
|
|
270
|
+
changes: new Map([['checkpointId', checkpointId]]),
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
await this.saveContext(contextId);
|
|
274
|
+
|
|
275
|
+
this.emit('checkpoint:restored', { contextId, checkpointId });
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
async mergeContexts(
|
|
279
|
+
sourceIds: string[],
|
|
280
|
+
strategy: MergeStrategy = 'last-write-wins'
|
|
281
|
+
): Promise<string> {
|
|
282
|
+
const contexts = await Promise.all(
|
|
283
|
+
sourceIds.map(id => this.getContext(id))
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
const validContexts = contexts.filter(c => c !== null) as ContextState[];
|
|
287
|
+
|
|
288
|
+
if (validContexts.length === 0) {
|
|
289
|
+
throw new Error('No valid contexts to merge');
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const mergedData = new Map();
|
|
293
|
+
|
|
294
|
+
switch (strategy) {
|
|
295
|
+
case 'last-write-wins':
|
|
296
|
+
for (const context of validContexts) {
|
|
297
|
+
for (const [key, value] of context.data) {
|
|
298
|
+
mergedData.set(key, value);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
break;
|
|
302
|
+
|
|
303
|
+
case 'first-write-wins':
|
|
304
|
+
for (const context of validContexts.reverse()) {
|
|
305
|
+
for (const [key, value] of context.data) {
|
|
306
|
+
if (!mergedData.has(key)) {
|
|
307
|
+
mergedData.set(key, value);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
break;
|
|
312
|
+
|
|
313
|
+
case 'deep-merge':
|
|
314
|
+
for (const context of validContexts) {
|
|
315
|
+
for (const [key, value] of context.data) {
|
|
316
|
+
const existing = mergedData.get(key);
|
|
317
|
+
if (existing && typeof existing === 'object' && typeof value === 'object') {
|
|
318
|
+
mergedData.set(key, this.deepMerge(existing, value));
|
|
319
|
+
} else {
|
|
320
|
+
mergedData.set(key, value);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const newContextId = await this.createContext(
|
|
328
|
+
validContexts[0].sessionId,
|
|
329
|
+
Object.fromEntries(mergedData)
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
this.emit('contexts:merged', { sourceIds, newContextId });
|
|
333
|
+
|
|
334
|
+
return newContextId;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
private addHistory(context: ContextState, entry: ContextHistory): void {
|
|
338
|
+
context.history.push(entry);
|
|
339
|
+
|
|
340
|
+
// Maintain max history size
|
|
341
|
+
if (context.history.length > this.maxHistorySize) {
|
|
342
|
+
context.history.shift();
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
private async saveContext(contextId: string): Promise<void> {
|
|
347
|
+
const context = this.contexts.get(contextId);
|
|
348
|
+
if (!context) return;
|
|
349
|
+
|
|
350
|
+
const serialized = await this.serializeContext(context);
|
|
351
|
+
const shouldCompress = serialized.length > this.compressionThreshold;
|
|
352
|
+
|
|
353
|
+
const dataToStore = shouldCompress ? compress(serialized) : serialized;
|
|
354
|
+
|
|
355
|
+
await this.storage.set(contextId, {
|
|
356
|
+
data: dataToStore,
|
|
357
|
+
compressed: shouldCompress,
|
|
358
|
+
timestamp: new Date(),
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// Update cache
|
|
362
|
+
this.cache.set(contextId, context);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
private async loadContext(contextId: string): Promise<ContextState | null> {
|
|
366
|
+
const stored = await this.storage.get(contextId);
|
|
367
|
+
if (!stored) return null;
|
|
368
|
+
|
|
369
|
+
const serialized = stored.compressed
|
|
370
|
+
? decompress(stored.data)
|
|
371
|
+
: stored.data;
|
|
372
|
+
|
|
373
|
+
return this.deserializeContext(serialized);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
private async serializeContext(context: ContextState): Promise<string> {
|
|
377
|
+
return JSON.stringify({
|
|
378
|
+
...context,
|
|
379
|
+
data: Object.fromEntries(context.data),
|
|
380
|
+
metadata: {
|
|
381
|
+
...context.metadata,
|
|
382
|
+
features: Array.from(context.metadata.features),
|
|
383
|
+
permissions: Object.fromEntries(context.metadata.permissions),
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
private deserializeContext(serialized: string): ContextState {
|
|
389
|
+
const parsed = JSON.parse(serialized);
|
|
390
|
+
return {
|
|
391
|
+
...parsed,
|
|
392
|
+
data: new Map(Object.entries(parsed.data)),
|
|
393
|
+
metadata: {
|
|
394
|
+
...parsed.metadata,
|
|
395
|
+
features: new Set(parsed.metadata.features),
|
|
396
|
+
permissions: new Map(Object.entries(parsed.metadata.permissions)),
|
|
397
|
+
},
|
|
398
|
+
created: new Date(parsed.created),
|
|
399
|
+
lastAccessed: new Date(parsed.lastAccessed),
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
private generateContextId(): string {
|
|
404
|
+
return `ctx_${crypto.randomBytes(16).toString('hex')}`;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
private generateCheckpointId(): string {
|
|
408
|
+
return `chk_${crypto.randomBytes(8).toString('hex')}`;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
private deepMerge(target: any, source: any): any {
|
|
412
|
+
const output = { ...target };
|
|
413
|
+
|
|
414
|
+
if (isObject(target) && isObject(source)) {
|
|
415
|
+
Object.keys(source).forEach(key => {
|
|
416
|
+
if (isObject(source[key])) {
|
|
417
|
+
if (!(key in target)) {
|
|
418
|
+
Object.assign(output, { [key]: source[key] });
|
|
419
|
+
} else {
|
|
420
|
+
output[key] = this.deepMerge(target[key], source[key]);
|
|
421
|
+
}
|
|
422
|
+
} else {
|
|
423
|
+
Object.assign(output, { [key]: source[key] });
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return output;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
private startAutoSave(): void {
|
|
432
|
+
setInterval(async () => {
|
|
433
|
+
const promises = Array.from(this.contexts.keys()).map(
|
|
434
|
+
contextId => this.saveContext(contextId)
|
|
435
|
+
);
|
|
436
|
+
await Promise.all(promises);
|
|
437
|
+
this.emit('autosave:completed', { count: promises.length });
|
|
438
|
+
}, this.autoSaveInterval);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
private setupEventHandlers(): void {
|
|
442
|
+
this.on('error', (error) => {
|
|
443
|
+
console.error('ContextManager error:', error);
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
process.on('SIGINT', async () => {
|
|
447
|
+
await this.shutdown();
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
process.on('SIGTERM', async () => {
|
|
451
|
+
await this.shutdown();
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
async shutdown(): Promise<void> {
|
|
456
|
+
this.emit('shutdown:started');
|
|
457
|
+
|
|
458
|
+
// Save all contexts
|
|
459
|
+
const promises = Array.from(this.contexts.keys()).map(
|
|
460
|
+
contextId => this.saveContext(contextId)
|
|
461
|
+
);
|
|
462
|
+
await Promise.all(promises);
|
|
463
|
+
|
|
464
|
+
// Clear memory
|
|
465
|
+
this.contexts.clear();
|
|
466
|
+
this.cache.clear();
|
|
467
|
+
|
|
468
|
+
this.emit('shutdown:completed');
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Usage interfaces
|
|
473
|
+
interface ContextManagerOptions {
|
|
474
|
+
maxCacheSize?: number;
|
|
475
|
+
cacheTTL?: number;
|
|
476
|
+
storage?: StorageAdapter;
|
|
477
|
+
compressionThreshold?: number;
|
|
478
|
+
autoSave?: boolean;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
interface UpdateOptions {
|
|
482
|
+
skipHistory?: boolean;
|
|
483
|
+
skipSave?: boolean;
|
|
484
|
+
checkpoint?: boolean;
|
|
485
|
+
checkpointDescription?: string;
|
|
486
|
+
action?: string;
|
|
487
|
+
userId?: string;
|
|
488
|
+
metadata?: any;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
type MergeStrategy = 'last-write-wins' | 'first-write-wins' | 'deep-merge';
|
|
492
|
+
|
|
493
|
+
function isObject(item: any): boolean {
|
|
494
|
+
return item && typeof item === 'object' && !Array.isArray(item);
|
|
495
|
+
}
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
## Distributed Session Management
|
|
499
|
+
```typescript
|
|
500
|
+
// distributed-session.ts
|
|
501
|
+
import { Redis } from 'ioredis';
|
|
502
|
+
import { EventEmitter } from 'events';
|
|
503
|
+
|
|
504
|
+
class DistributedSessionManager extends EventEmitter {
|
|
505
|
+
private redis: Redis;
|
|
506
|
+
private pubClient: Redis;
|
|
507
|
+
private subClient: Redis;
|
|
508
|
+
private localSessions: Map<string, SessionData>;
|
|
509
|
+
private heartbeatInterval: number = 30000; // 30 seconds
|
|
510
|
+
private sessionTimeout: number = 3600000; // 1 hour
|
|
511
|
+
private nodeId: string;
|
|
512
|
+
|
|
513
|
+
constructor(redisConfig: RedisConfig) {
|
|
514
|
+
super();
|
|
515
|
+
this.redis = new Redis(redisConfig);
|
|
516
|
+
this.pubClient = new Redis(redisConfig);
|
|
517
|
+
this.subClient = new Redis(redisConfig);
|
|
518
|
+
this.localSessions = new Map();
|
|
519
|
+
this.nodeId = this.generateNodeId();
|
|
520
|
+
|
|
521
|
+
this.setupSubscriptions();
|
|
522
|
+
this.startHeartbeat();
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
async createSession(userId: string, metadata?: any): Promise<string> {
|
|
526
|
+
const sessionId = this.generateSessionId();
|
|
527
|
+
const session: SessionData = {
|
|
528
|
+
id: sessionId,
|
|
529
|
+
userId,
|
|
530
|
+
nodeId: this.nodeId,
|
|
531
|
+
data: {},
|
|
532
|
+
metadata: metadata || {},
|
|
533
|
+
created: Date.now(),
|
|
534
|
+
lastAccessed: Date.now(),
|
|
535
|
+
expiresAt: Date.now() + this.sessionTimeout,
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
// Store locally
|
|
539
|
+
this.localSessions.set(sessionId, session);
|
|
540
|
+
|
|
541
|
+
// Store in Redis
|
|
542
|
+
await this.redis.setex(
|
|
543
|
+
`session:${sessionId}`,
|
|
544
|
+
Math.floor(this.sessionTimeout / 1000),
|
|
545
|
+
JSON.stringify(session)
|
|
546
|
+
);
|
|
547
|
+
|
|
548
|
+
// Publish session creation event
|
|
549
|
+
await this.pubClient.publish('session:created', JSON.stringify({
|
|
550
|
+
sessionId,
|
|
551
|
+
nodeId: this.nodeId,
|
|
552
|
+
userId,
|
|
553
|
+
}));
|
|
554
|
+
|
|
555
|
+
this.emit('session:created', session);
|
|
556
|
+
|
|
557
|
+
return sessionId;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
async getSession(sessionId: string): Promise<SessionData | null> {
|
|
561
|
+
// Check local cache first
|
|
562
|
+
let session = this.localSessions.get(sessionId);
|
|
563
|
+
|
|
564
|
+
if (!session) {
|
|
565
|
+
// Fetch from Redis
|
|
566
|
+
const data = await this.redis.get(`session:${sessionId}`);
|
|
567
|
+
if (data) {
|
|
568
|
+
session = JSON.parse(data);
|
|
569
|
+
// Cache locally
|
|
570
|
+
this.localSessions.set(sessionId, session);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
if (session) {
|
|
575
|
+
// Update last accessed time
|
|
576
|
+
session.lastAccessed = Date.now();
|
|
577
|
+
await this.updateSession(sessionId, session);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return session || null;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
async updateSession(sessionId: string, updates: Partial<SessionData>): Promise<void> {
|
|
584
|
+
const session = await this.getSession(sessionId);
|
|
585
|
+
if (!session) {
|
|
586
|
+
throw new Error(`Session ${sessionId} not found`);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
const updatedSession = { ...session, ...updates };
|
|
590
|
+
|
|
591
|
+
// Update locally
|
|
592
|
+
this.localSessions.set(sessionId, updatedSession);
|
|
593
|
+
|
|
594
|
+
// Update in Redis
|
|
595
|
+
const ttl = Math.max(0, updatedSession.expiresAt - Date.now());
|
|
596
|
+
await this.redis.setex(
|
|
597
|
+
`session:${sessionId}`,
|
|
598
|
+
Math.floor(ttl / 1000),
|
|
599
|
+
JSON.stringify(updatedSession)
|
|
600
|
+
);
|
|
601
|
+
|
|
602
|
+
// Publish update event
|
|
603
|
+
await this.pubClient.publish('session:updated', JSON.stringify({
|
|
604
|
+
sessionId,
|
|
605
|
+
nodeId: this.nodeId,
|
|
606
|
+
updates,
|
|
607
|
+
}));
|
|
608
|
+
|
|
609
|
+
this.emit('session:updated', updatedSession);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
async destroySession(sessionId: string): Promise<void> {
|
|
613
|
+
// Remove locally
|
|
614
|
+
this.localSessions.delete(sessionId);
|
|
615
|
+
|
|
616
|
+
// Remove from Redis
|
|
617
|
+
await this.redis.del(`session:${sessionId}`);
|
|
618
|
+
|
|
619
|
+
// Publish destroy event
|
|
620
|
+
await this.pubClient.publish('session:destroyed', JSON.stringify({
|
|
621
|
+
sessionId,
|
|
622
|
+
nodeId: this.nodeId,
|
|
623
|
+
}));
|
|
624
|
+
|
|
625
|
+
this.emit('session:destroyed', { sessionId });
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
async transferSession(sessionId: string, targetNodeId: string): Promise<void> {
|
|
629
|
+
const session = await this.getSession(sessionId);
|
|
630
|
+
if (!session) {
|
|
631
|
+
throw new Error(`Session ${sessionId} not found`);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// Update session node ownership
|
|
635
|
+
session.nodeId = targetNodeId;
|
|
636
|
+
await this.updateSession(sessionId, { nodeId: targetNodeId });
|
|
637
|
+
|
|
638
|
+
// Remove from local cache
|
|
639
|
+
this.localSessions.delete(sessionId);
|
|
640
|
+
|
|
641
|
+
// Publish transfer event
|
|
642
|
+
await this.pubClient.publish('session:transferred', JSON.stringify({
|
|
643
|
+
sessionId,
|
|
644
|
+
fromNodeId: this.nodeId,
|
|
645
|
+
toNodeId: targetNodeId,
|
|
646
|
+
}));
|
|
647
|
+
|
|
648
|
+
this.emit('session:transferred', { sessionId, targetNodeId });
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
private setupSubscriptions(): void {
|
|
652
|
+
this.subClient.subscribe(
|
|
653
|
+
'session:created',
|
|
654
|
+
'session:updated',
|
|
655
|
+
'session:destroyed',
|
|
656
|
+
'session:transferred'
|
|
657
|
+
);
|
|
658
|
+
|
|
659
|
+
this.subClient.on('message', (channel, message) => {
|
|
660
|
+
const data = JSON.parse(message);
|
|
661
|
+
|
|
662
|
+
// Skip events from this node
|
|
663
|
+
if (data.nodeId === this.nodeId) return;
|
|
664
|
+
|
|
665
|
+
switch (channel) {
|
|
666
|
+
case 'session:created':
|
|
667
|
+
this.handleRemoteSessionCreated(data);
|
|
668
|
+
break;
|
|
669
|
+
case 'session:updated':
|
|
670
|
+
this.handleRemoteSessionUpdated(data);
|
|
671
|
+
break;
|
|
672
|
+
case 'session:destroyed':
|
|
673
|
+
this.handleRemoteSessionDestroyed(data);
|
|
674
|
+
break;
|
|
675
|
+
case 'session:transferred':
|
|
676
|
+
this.handleRemoteSessionTransferred(data);
|
|
677
|
+
break;
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
private handleRemoteSessionCreated(data: any): void {
|
|
683
|
+
// Invalidate local cache if exists
|
|
684
|
+
this.localSessions.delete(data.sessionId);
|
|
685
|
+
this.emit('remote:session:created', data);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
private handleRemoteSessionUpdated(data: any): void {
|
|
689
|
+
// Invalidate local cache
|
|
690
|
+
this.localSessions.delete(data.sessionId);
|
|
691
|
+
this.emit('remote:session:updated', data);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
private handleRemoteSessionDestroyed(data: any): void {
|
|
695
|
+
this.localSessions.delete(data.sessionId);
|
|
696
|
+
this.emit('remote:session:destroyed', data);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
private handleRemoteSessionTransferred(data: any): void {
|
|
700
|
+
if (data.toNodeId === this.nodeId) {
|
|
701
|
+
// Session transferred to this node
|
|
702
|
+
this.emit('session:received', data);
|
|
703
|
+
} else {
|
|
704
|
+
// Invalidate local cache
|
|
705
|
+
this.localSessions.delete(data.sessionId);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
private startHeartbeat(): void {
|
|
710
|
+
setInterval(async () => {
|
|
711
|
+
const now = Date.now();
|
|
712
|
+
|
|
713
|
+
// Clean up expired local sessions
|
|
714
|
+
for (const [sessionId, session] of this.localSessions) {
|
|
715
|
+
if (session.expiresAt < now) {
|
|
716
|
+
await this.destroySession(sessionId);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// Update node heartbeat
|
|
721
|
+
await this.redis.setex(
|
|
722
|
+
`node:${this.nodeId}:heartbeat`,
|
|
723
|
+
60, // 1 minute TTL
|
|
724
|
+
JSON.stringify({
|
|
725
|
+
nodeId: this.nodeId,
|
|
726
|
+
timestamp: now,
|
|
727
|
+
sessionCount: this.localSessions.size,
|
|
728
|
+
})
|
|
729
|
+
);
|
|
730
|
+
|
|
731
|
+
this.emit('heartbeat', { nodeId: this.nodeId, sessionCount: this.localSessions.size });
|
|
732
|
+
}, this.heartbeatInterval);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
private generateSessionId(): string {
|
|
736
|
+
return `sess_${crypto.randomBytes(16).toString('hex')}_${Date.now()}`;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
private generateNodeId(): string {
|
|
740
|
+
return `node_${process.pid}_${crypto.randomBytes(8).toString('hex')}`;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
async shutdown(): Promise<void> {
|
|
744
|
+
// Transfer all sessions to other nodes
|
|
745
|
+
const activeNodes = await this.getActiveNodes();
|
|
746
|
+
|
|
747
|
+
if (activeNodes.length > 0) {
|
|
748
|
+
const sessions = Array.from(this.localSessions.keys());
|
|
749
|
+
for (let i = 0; i < sessions.length; i++) {
|
|
750
|
+
const targetNode = activeNodes[i % activeNodes.length];
|
|
751
|
+
await this.transferSession(sessions[i], targetNode);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Clean up
|
|
756
|
+
await this.redis.del(`node:${this.nodeId}:heartbeat`);
|
|
757
|
+
this.redis.disconnect();
|
|
758
|
+
this.pubClient.disconnect();
|
|
759
|
+
this.subClient.disconnect();
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
private async getActiveNodes(): Promise<string[]> {
|
|
763
|
+
const keys = await this.redis.keys('node:*:heartbeat');
|
|
764
|
+
return keys.map(key => key.split(':')[1]).filter(id => id !== this.nodeId);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
interface SessionData {
|
|
769
|
+
id: string;
|
|
770
|
+
userId: string;
|
|
771
|
+
nodeId: string;
|
|
772
|
+
data: any;
|
|
773
|
+
metadata: any;
|
|
774
|
+
created: number;
|
|
775
|
+
lastAccessed: number;
|
|
776
|
+
expiresAt: number;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
interface RedisConfig {
|
|
780
|
+
host: string;
|
|
781
|
+
port: number;
|
|
782
|
+
password?: string;
|
|
783
|
+
db?: number;
|
|
784
|
+
}
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
## Memory Optimization Strategies
|
|
788
|
+
```typescript
|
|
789
|
+
// memory-optimizer.ts
|
|
790
|
+
import { performance } from 'perf_hooks';
|
|
791
|
+
import v8 from 'v8';
|
|
792
|
+
import { Worker } from 'worker_threads';
|
|
793
|
+
|
|
794
|
+
class MemoryOptimizer {
|
|
795
|
+
private gcThreshold: number = 0.8; // 80% memory usage
|
|
796
|
+
private compressionThreshold: number = 10240; // 10KB
|
|
797
|
+
private weakRefs: WeakMap<object, any> = new WeakMap();
|
|
798
|
+
private objectPool: Map<string, any[]> = new Map();
|
|
799
|
+
private monitoringInterval: number = 5000; // 5 seconds
|
|
800
|
+
|
|
801
|
+
constructor() {
|
|
802
|
+
this.startMonitoring();
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
optimizeObject(obj: any): any {
|
|
806
|
+
const size = this.getObjectSize(obj);
|
|
807
|
+
|
|
808
|
+
if (size > this.compressionThreshold) {
|
|
809
|
+
return this.compressObject(obj);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// Use object pooling for frequently created objects
|
|
813
|
+
if (this.isPoolableObject(obj)) {
|
|
814
|
+
return this.poolObject(obj);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
// Use weak references for large objects
|
|
818
|
+
if (size > 1024) {
|
|
819
|
+
this.weakRefs.set(obj, true);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
return obj;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
private compressObject(obj: any): CompressedObject {
|
|
826
|
+
const json = JSON.stringify(obj);
|
|
827
|
+
const buffer = Buffer.from(json);
|
|
828
|
+
const compressed = zlib.gzipSync(buffer);
|
|
829
|
+
|
|
830
|
+
return {
|
|
831
|
+
_compressed: true,
|
|
832
|
+
data: compressed.toString('base64'),
|
|
833
|
+
originalSize: buffer.length,
|
|
834
|
+
compressedSize: compressed.length,
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
decompressObject(compressed: CompressedObject): any {
|
|
839
|
+
if (!compressed._compressed) return compressed;
|
|
840
|
+
|
|
841
|
+
const buffer = Buffer.from(compressed.data, 'base64');
|
|
842
|
+
const decompressed = zlib.gunzipSync(buffer);
|
|
843
|
+
return JSON.parse(decompressed.toString());
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
private isPoolableObject(obj: any): boolean {
|
|
847
|
+
// Check if object is suitable for pooling
|
|
848
|
+
return obj.constructor &&
|
|
849
|
+
obj.constructor.name &&
|
|
850
|
+
this.objectPool.has(obj.constructor.name);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
private poolObject(obj: any): any {
|
|
854
|
+
const className = obj.constructor.name;
|
|
855
|
+
let pool = this.objectPool.get(className);
|
|
856
|
+
|
|
857
|
+
if (!pool) {
|
|
858
|
+
pool = [];
|
|
859
|
+
this.objectPool.set(className, pool);
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// Reuse from pool if available
|
|
863
|
+
if (pool.length > 0) {
|
|
864
|
+
const pooled = pool.pop();
|
|
865
|
+
Object.assign(pooled, obj);
|
|
866
|
+
return pooled;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
return obj;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
releaseToPool(obj: any): void {
|
|
873
|
+
const className = obj.constructor.name;
|
|
874
|
+
let pool = this.objectPool.get(className);
|
|
875
|
+
|
|
876
|
+
if (!pool) {
|
|
877
|
+
pool = [];
|
|
878
|
+
this.objectPool.set(className, pool);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
// Reset object
|
|
882
|
+
for (const key in obj) {
|
|
883
|
+
if (obj.hasOwnProperty(key)) {
|
|
884
|
+
delete obj[key];
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
pool.push(obj);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
private getObjectSize(obj: any): number {
|
|
892
|
+
const str = JSON.stringify(obj);
|
|
893
|
+
return Buffer.byteLength(str, 'utf8');
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
private startMonitoring(): void {
|
|
897
|
+
setInterval(() => {
|
|
898
|
+
const memUsage = process.memoryUsage();
|
|
899
|
+
const heapStats = v8.getHeapStatistics();
|
|
900
|
+
|
|
901
|
+
const usageRatio = memUsage.heapUsed / heapStats.heap_size_limit;
|
|
902
|
+
|
|
903
|
+
if (usageRatio > this.gcThreshold) {
|
|
904
|
+
this.triggerGarbageCollection();
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
this.emit('memory:stats', {
|
|
908
|
+
heapUsed: memUsage.heapUsed,
|
|
909
|
+
heapTotal: memUsage.heapTotal,
|
|
910
|
+
external: memUsage.external,
|
|
911
|
+
usageRatio,
|
|
912
|
+
});
|
|
913
|
+
}, this.monitoringInterval);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
private triggerGarbageCollection(): void {
|
|
917
|
+
if (global.gc) {
|
|
918
|
+
global.gc();
|
|
919
|
+
this.emit('gc:triggered');
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
analyzeMemoryLeaks(): MemoryLeakReport {
|
|
924
|
+
const snapshot = v8.writeHeapSnapshot();
|
|
925
|
+
// Analyze snapshot for potential leaks
|
|
926
|
+
// This is a simplified version
|
|
927
|
+
return {
|
|
928
|
+
potentialLeaks: [],
|
|
929
|
+
recommendations: [],
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
interface CompressedObject {
|
|
935
|
+
_compressed: boolean;
|
|
936
|
+
data: string;
|
|
937
|
+
originalSize: number;
|
|
938
|
+
compressedSize: number;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
interface MemoryLeakReport {
|
|
942
|
+
potentialLeaks: any[];
|
|
943
|
+
recommendations: string[];
|
|
944
|
+
}
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
## Best Practices
|
|
948
|
+
1. **State Isolation**: Keep context states isolated and immutable
|
|
949
|
+
2. **Compression**: Automatically compress large context data
|
|
950
|
+
3. **Checkpointing**: Regular automatic checkpoints for recovery
|
|
951
|
+
4. **Distributed Sessions**: Support for horizontal scaling
|
|
952
|
+
5. **Memory Management**: Proactive memory optimization and leak detection
|
|
953
|
+
6. **Event Sourcing**: Complete audit trail of all context changes
|
|
954
|
+
7. **Cache Strategy**: Multi-layer caching with TTL and LRU
|
|
955
|
+
|
|
956
|
+
## Context Preservation Strategies
|
|
957
|
+
- Automatic session persistence across restarts
|
|
958
|
+
- Checkpoint and restore capabilities
|
|
959
|
+
- Context merging and splitting
|
|
960
|
+
- Cross-service context propagation
|
|
961
|
+
- Intelligent garbage collection
|
|
962
|
+
- Memory pressure handling
|
|
963
|
+
|
|
964
|
+
## Approach
|
|
965
|
+
- Design robust state management architecture
|
|
966
|
+
- Implement efficient serialization and compression
|
|
967
|
+
- Create distributed session capabilities
|
|
968
|
+
- Build comprehensive monitoring and alerting
|
|
969
|
+
- Establish automatic recovery mechanisms
|
|
970
|
+
- Optimize for memory and performance
|
|
971
|
+
|
|
972
|
+
## Output Format
|
|
973
|
+
- Provide complete context management systems
|
|
974
|
+
- Include distributed session handling
|
|
975
|
+
- Document memory optimization strategies
|
|
976
|
+
- Add monitoring and debugging tools
|
|
977
|
+
- Include recovery and backup procedures
|
|
978
|
+
- Provide performance benchmarks and metrics
|