@vheins/local-memory-mcp 0.5.33 → 0.6.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/README.md +9 -6
- package/dist/chunk-XIJO63UU.js +3618 -0
- package/dist/dashboard/public/assets/{index-C8FB4maW.css → index-Bd7v94SO.css} +1 -1
- package/dist/dashboard/public/assets/index-Df97JpLg.js +84 -0
- package/dist/dashboard/public/index.html +2 -2
- package/dist/dashboard/server.js +790 -451
- package/dist/mcp/server.js +2121 -305
- package/dist/{mcp/prompts/definitions → prompts}/create-task.md +4 -3
- package/dist/{mcp/prompts/definitions → prompts}/memory-agent-core.md +2 -0
- package/dist/{mcp/prompts/definitions → prompts}/memory-index-policy.md +2 -0
- package/dist/{mcp/prompts/definitions → prompts}/review-and-audit.md +3 -1
- package/dist/{mcp/prompts/definitions → prompts}/review-and-post-issue.md +3 -1
- package/dist/prompts/task-management-guidelines.md +28 -0
- package/dist/{mcp/prompts/definitions → prompts}/task-memory-executor.md +6 -5
- package/package.json +22 -6
- package/dist/capabilities.d.ts +0 -22
- package/dist/capabilities.d.ts.map +0 -1
- package/dist/capabilities.js +0 -38
- package/dist/capabilities.js.map +0 -1
- package/dist/completion.d.ts +0 -25
- package/dist/completion.d.ts.map +0 -1
- package/dist/completion.js +0 -127
- package/dist/completion.js.map +0 -1
- package/dist/dashboard/dashboard.test.d.ts +0 -2
- package/dist/dashboard/dashboard.test.d.ts.map +0 -1
- package/dist/dashboard/dashboard.test.js +0 -370
- package/dist/dashboard/dashboard.test.js.map +0 -1
- package/dist/dashboard/public/assets/index-DIhCu9qA.js +0 -78
- package/dist/dashboard/server.d.ts +0 -3
- package/dist/dashboard/server.d.ts.map +0 -1
- package/dist/dashboard/server.js.map +0 -1
- package/dist/e2e.test.d.ts +0 -2
- package/dist/e2e.test.d.ts.map +0 -1
- package/dist/e2e.test.js +0 -250
- package/dist/e2e.test.js.map +0 -1
- package/dist/mcp/capabilities.d.ts +0 -22
- package/dist/mcp/capabilities.d.ts.map +0 -1
- package/dist/mcp/capabilities.js +0 -38
- package/dist/mcp/capabilities.js.map +0 -1
- package/dist/mcp/client.d.ts +0 -34
- package/dist/mcp/client.d.ts.map +0 -1
- package/dist/mcp/client.js +0 -188
- package/dist/mcp/client.js.map +0 -1
- package/dist/mcp/client.test.d.ts +0 -2
- package/dist/mcp/client.test.d.ts.map +0 -1
- package/dist/mcp/client.test.js +0 -130
- package/dist/mcp/client.test.js.map +0 -1
- package/dist/mcp/completion.d.ts +0 -25
- package/dist/mcp/completion.d.ts.map +0 -1
- package/dist/mcp/completion.js +0 -127
- package/dist/mcp/completion.js.map +0 -1
- package/dist/mcp/elicitation.d.ts +0 -24
- package/dist/mcp/elicitation.d.ts.map +0 -1
- package/dist/mcp/elicitation.js +0 -13
- package/dist/mcp/elicitation.js.map +0 -1
- package/dist/mcp/prompts/definitions/task-management-guidelines.md +0 -30
- package/dist/mcp/prompts/loader.d.ts +0 -10
- package/dist/mcp/prompts/loader.d.ts.map +0 -1
- package/dist/mcp/prompts/loader.js +0 -31
- package/dist/mcp/prompts/loader.js.map +0 -1
- package/dist/mcp/prompts/registry.d.ts +0 -35
- package/dist/mcp/prompts/registry.d.ts.map +0 -1
- package/dist/mcp/prompts/registry.js +0 -95
- package/dist/mcp/prompts/registry.js.map +0 -1
- package/dist/mcp/resources/index.d.ts +0 -68
- package/dist/mcp/resources/index.d.ts.map +0 -1
- package/dist/mcp/resources/index.js +0 -359
- package/dist/mcp/resources/index.js.map +0 -1
- package/dist/mcp/router.d.ts +0 -14
- package/dist/mcp/router.d.ts.map +0 -1
- package/dist/mcp/router.js +0 -255
- package/dist/mcp/router.js.map +0 -1
- package/dist/mcp/sampling.d.ts +0 -69
- package/dist/mcp/sampling.d.ts.map +0 -1
- package/dist/mcp/sampling.js +0 -13
- package/dist/mcp/sampling.js.map +0 -1
- package/dist/mcp/server.d.ts +0 -3
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js.map +0 -1
- package/dist/mcp/session.d.ts +0 -28
- package/dist/mcp/session.d.ts.map +0 -1
- package/dist/mcp/session.js +0 -106
- package/dist/mcp/session.js.map +0 -1
- package/dist/mcp/storage/sqlite.d.ts +0 -87
- package/dist/mcp/storage/sqlite.d.ts.map +0 -1
- package/dist/mcp/storage/sqlite.js +0 -1327
- package/dist/mcp/storage/sqlite.js.map +0 -1
- package/dist/mcp/storage/vectors.d.ts +0 -19
- package/dist/mcp/storage/vectors.d.ts.map +0 -1
- package/dist/mcp/storage/vectors.js +0 -74
- package/dist/mcp/storage/vectors.js.map +0 -1
- package/dist/mcp/storage/vectors.stub.d.ts +0 -12
- package/dist/mcp/storage/vectors.stub.d.ts.map +0 -1
- package/dist/mcp/storage/vectors.stub.js +0 -88
- package/dist/mcp/storage/vectors.stub.js.map +0 -1
- package/dist/mcp/tests/client.test.d.ts +0 -2
- package/dist/mcp/tests/client.test.d.ts.map +0 -1
- package/dist/mcp/tests/client.test.js +0 -130
- package/dist/mcp/tests/client.test.js.map +0 -1
- package/dist/mcp/tests/dashboard.test.d.ts +0 -2
- package/dist/mcp/tests/dashboard.test.d.ts.map +0 -1
- package/dist/mcp/tests/dashboard.test.js +0 -370
- package/dist/mcp/tests/dashboard.test.js.map +0 -1
- package/dist/mcp/tests/detail-tools.test.d.ts +0 -2
- package/dist/mcp/tests/detail-tools.test.d.ts.map +0 -1
- package/dist/mcp/tests/detail-tools.test.js +0 -109
- package/dist/mcp/tests/detail-tools.test.js.map +0 -1
- package/dist/mcp/tests/e2e.test.d.ts +0 -2
- package/dist/mcp/tests/e2e.test.d.ts.map +0 -1
- package/dist/mcp/tests/e2e.test.js +0 -255
- package/dist/mcp/tests/e2e.test.js.map +0 -1
- package/dist/mcp/tests/index.test.d.ts +0 -2
- package/dist/mcp/tests/index.test.d.ts.map +0 -1
- package/dist/mcp/tests/index.test.js +0 -185
- package/dist/mcp/tests/index.test.js.map +0 -1
- package/dist/mcp/tests/logger.test.d.ts +0 -2
- package/dist/mcp/tests/logger.test.d.ts.map +0 -1
- package/dist/mcp/tests/logger.test.js +0 -104
- package/dist/mcp/tests/logger.test.js.map +0 -1
- package/dist/mcp/tests/memory.bulk.test.d.ts +0 -2
- package/dist/mcp/tests/memory.bulk.test.d.ts.map +0 -1
- package/dist/mcp/tests/memory.bulk.test.js +0 -53
- package/dist/mcp/tests/memory.bulk.test.js.map +0 -1
- package/dist/mcp/tests/memory.search.test.d.ts +0 -2
- package/dist/mcp/tests/memory.search.test.d.ts.map +0 -1
- package/dist/mcp/tests/memory.search.test.js +0 -181
- package/dist/mcp/tests/memory.search.test.js.map +0 -1
- package/dist/mcp/tests/normalize.test.d.ts +0 -2
- package/dist/mcp/tests/normalize.test.d.ts.map +0 -1
- package/dist/mcp/tests/normalize.test.js +0 -181
- package/dist/mcp/tests/normalize.test.js.map +0 -1
- package/dist/mcp/tests/query-expander.test.d.ts +0 -2
- package/dist/mcp/tests/query-expander.test.d.ts.map +0 -1
- package/dist/mcp/tests/query-expander.test.js +0 -33
- package/dist/mcp/tests/query-expander.test.js.map +0 -1
- package/dist/mcp/tests/router.test.d.ts +0 -2
- package/dist/mcp/tests/router.test.d.ts.map +0 -1
- package/dist/mcp/tests/router.test.js +0 -481
- package/dist/mcp/tests/router.test.js.map +0 -1
- package/dist/mcp/tests/spec_compliance.test.d.ts +0 -2
- package/dist/mcp/tests/spec_compliance.test.d.ts.map +0 -1
- package/dist/mcp/tests/spec_compliance.test.js +0 -61
- package/dist/mcp/tests/spec_compliance.test.js.map +0 -1
- package/dist/mcp/tests/sqlite.test.d.ts +0 -2
- package/dist/mcp/tests/sqlite.test.d.ts.map +0 -1
- package/dist/mcp/tests/sqlite.test.js +0 -367
- package/dist/mcp/tests/sqlite.test.js.map +0 -1
- package/dist/mcp/tests/tasks-search.test.d.ts +0 -2
- package/dist/mcp/tests/tasks-search.test.d.ts.map +0 -1
- package/dist/mcp/tests/tasks-search.test.js +0 -156
- package/dist/mcp/tests/tasks-search.test.js.map +0 -1
- package/dist/mcp/tests/tasks-transition.test.d.ts +0 -2
- package/dist/mcp/tests/tasks-transition.test.d.ts.map +0 -1
- package/dist/mcp/tests/tasks-transition.test.js +0 -174
- package/dist/mcp/tests/tasks-transition.test.js.map +0 -1
- package/dist/mcp/tests/tasks.bulk.test.d.ts +0 -2
- package/dist/mcp/tests/tasks.bulk.test.d.ts.map +0 -1
- package/dist/mcp/tests/tasks.bulk.test.js +0 -410
- package/dist/mcp/tests/tasks.bulk.test.js.map +0 -1
- package/dist/mcp/tests/tasks.e2e.test.d.ts +0 -2
- package/dist/mcp/tests/tasks.e2e.test.d.ts.map +0 -1
- package/dist/mcp/tests/tasks.e2e.test.js +0 -289
- package/dist/mcp/tests/tasks.e2e.test.js.map +0 -1
- package/dist/mcp/tests/tasks.pending-limit-refined.test.d.ts +0 -2
- package/dist/mcp/tests/tasks.pending-limit-refined.test.d.ts.map +0 -1
- package/dist/mcp/tests/tasks.pending-limit-refined.test.js +0 -72
- package/dist/mcp/tests/tasks.pending-limit-refined.test.js.map +0 -1
- package/dist/mcp/tests/v2-features.test.d.ts +0 -2
- package/dist/mcp/tests/v2-features.test.d.ts.map +0 -1
- package/dist/mcp/tests/v2-features.test.js +0 -209
- package/dist/mcp/tests/v2-features.test.js.map +0 -1
- package/dist/mcp/tools/memory.acknowledge.d.ts +0 -4
- package/dist/mcp/tools/memory.acknowledge.d.ts.map +0 -1
- package/dist/mcp/tools/memory.acknowledge.js +0 -32
- package/dist/mcp/tools/memory.acknowledge.js.map +0 -1
- package/dist/mcp/tools/memory.bulk-delete.d.ts +0 -4
- package/dist/mcp/tools/memory.bulk-delete.d.ts.map +0 -1
- package/dist/mcp/tools/memory.bulk-delete.js +0 -40
- package/dist/mcp/tools/memory.bulk-delete.js.map +0 -1
- package/dist/mcp/tools/memory.delete.d.ts +0 -9
- package/dist/mcp/tools/memory.delete.d.ts.map +0 -1
- package/dist/mcp/tools/memory.delete.js +0 -40
- package/dist/mcp/tools/memory.delete.js.map +0 -1
- package/dist/mcp/tools/memory.get.d.ts +0 -3
- package/dist/mcp/tools/memory.get.d.ts.map +0 -1
- package/dist/mcp/tools/memory.get.js +0 -24
- package/dist/mcp/tools/memory.get.js.map +0 -1
- package/dist/mcp/tools/memory.recap.d.ts +0 -4
- package/dist/mcp/tools/memory.recap.d.ts.map +0 -1
- package/dist/mcp/tools/memory.recap.js +0 -52
- package/dist/mcp/tools/memory.recap.js.map +0 -1
- package/dist/mcp/tools/memory.search.d.ts +0 -5
- package/dist/mcp/tools/memory.search.d.ts.map +0 -1
- package/dist/mcp/tools/memory.search.js +0 -144
- package/dist/mcp/tools/memory.search.js.map +0 -1
- package/dist/mcp/tools/memory.store.d.ts +0 -5
- package/dist/mcp/tools/memory.store.d.ts.map +0 -1
- package/dist/mcp/tools/memory.store.js +0 -120
- package/dist/mcp/tools/memory.store.js.map +0 -1
- package/dist/mcp/tools/memory.summarize.d.ts +0 -4
- package/dist/mcp/tools/memory.summarize.d.ts.map +0 -1
- package/dist/mcp/tools/memory.summarize.js +0 -32
- package/dist/mcp/tools/memory.summarize.js.map +0 -1
- package/dist/mcp/tools/memory.synthesize.d.ts +0 -14
- package/dist/mcp/tools/memory.synthesize.d.ts.map +0 -1
- package/dist/mcp/tools/memory.synthesize.js +0 -230
- package/dist/mcp/tools/memory.synthesize.js.map +0 -1
- package/dist/mcp/tools/memory.update.d.ts +0 -5
- package/dist/mcp/tools/memory.update.d.ts.map +0 -1
- package/dist/mcp/tools/memory.update.js +0 -74
- package/dist/mcp/tools/memory.update.js.map +0 -1
- package/dist/mcp/tools/schemas.d.ts +0 -3177
- package/dist/mcp/tools/schemas.d.ts.map +0 -1
- package/dist/mcp/tools/schemas.js +0 -1081
- package/dist/mcp/tools/schemas.js.map +0 -1
- package/dist/mcp/tools/task.bulk-manage.d.ts +0 -4
- package/dist/mcp/tools/task.bulk-manage.d.ts.map +0 -1
- package/dist/mcp/tools/task.bulk-manage.js +0 -190
- package/dist/mcp/tools/task.bulk-manage.js.map +0 -1
- package/dist/mcp/tools/task.get.d.ts +0 -3
- package/dist/mcp/tools/task.get.d.ts.map +0 -1
- package/dist/mcp/tools/task.get.js +0 -32
- package/dist/mcp/tools/task.get.js.map +0 -1
- package/dist/mcp/tools/task.manage.d.ts +0 -18
- package/dist/mcp/tools/task.manage.d.ts.map +0 -1
- package/dist/mcp/tools/task.manage.js +0 -477
- package/dist/mcp/tools/task.manage.js.map +0 -1
- package/dist/mcp/types.d.ts +0 -87
- package/dist/mcp/types.d.ts.map +0 -1
- package/dist/mcp/types.js +0 -3
- package/dist/mcp/types.js.map +0 -1
- package/dist/mcp/utils/completion.d.ts +0 -2
- package/dist/mcp/utils/completion.d.ts.map +0 -1
- package/dist/mcp/utils/completion.js +0 -28
- package/dist/mcp/utils/completion.js.map +0 -1
- package/dist/mcp/utils/git-scope.d.ts +0 -8
- package/dist/mcp/utils/git-scope.d.ts.map +0 -1
- package/dist/mcp/utils/git-scope.js +0 -38
- package/dist/mcp/utils/git-scope.js.map +0 -1
- package/dist/mcp/utils/logger.d.ts +0 -25
- package/dist/mcp/utils/logger.d.ts.map +0 -1
- package/dist/mcp/utils/logger.js +0 -152
- package/dist/mcp/utils/logger.js.map +0 -1
- package/dist/mcp/utils/mcp-response.d.ts +0 -82
- package/dist/mcp/utils/mcp-response.d.ts.map +0 -1
- package/dist/mcp/utils/mcp-response.js +0 -182
- package/dist/mcp/utils/mcp-response.js.map +0 -1
- package/dist/mcp/utils/normalize.d.ts +0 -9
- package/dist/mcp/utils/normalize.d.ts.map +0 -1
- package/dist/mcp/utils/normalize.js +0 -62
- package/dist/mcp/utils/normalize.js.map +0 -1
- package/dist/mcp/utils/pagination.d.ts +0 -6
- package/dist/mcp/utils/pagination.d.ts.map +0 -1
- package/dist/mcp/utils/pagination.js +0 -32
- package/dist/mcp/utils/pagination.js.map +0 -1
- package/dist/mcp/utils/query-expander.d.ts +0 -2
- package/dist/mcp/utils/query-expander.d.ts.map +0 -1
- package/dist/mcp/utils/query-expander.js +0 -29
- package/dist/mcp/utils/query-expander.js.map +0 -1
- package/dist/memory.bulk.test.d.ts +0 -2
- package/dist/memory.bulk.test.d.ts.map +0 -1
- package/dist/memory.bulk.test.js +0 -52
- package/dist/memory.bulk.test.js.map +0 -1
- package/dist/memory.db +0 -0
- package/dist/prompts/registry.d.ts +0 -314
- package/dist/prompts/registry.d.ts.map +0 -1
- package/dist/prompts/registry.js +0 -936
- package/dist/prompts/registry.js.map +0 -1
- package/dist/resources/index.d.ts +0 -68
- package/dist/resources/index.d.ts.map +0 -1
- package/dist/resources/index.js +0 -323
- package/dist/resources/index.js.map +0 -1
- package/dist/resources/index.test.d.ts +0 -2
- package/dist/resources/index.test.d.ts.map +0 -1
- package/dist/resources/index.test.js +0 -105
- package/dist/resources/index.test.js.map +0 -1
- package/dist/router.d.ts +0 -14
- package/dist/router.d.ts.map +0 -1
- package/dist/router.js +0 -242
- package/dist/router.js.map +0 -1
- package/dist/router.test.d.ts +0 -2
- package/dist/router.test.d.ts.map +0 -1
- package/dist/router.test.js +0 -122
- package/dist/router.test.js.map +0 -1
- package/dist/server.d.ts +0 -3
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -338
- package/dist/server.js.map +0 -1
- package/dist/storage/sqlite.d.ts +0 -79
- package/dist/storage/sqlite.d.ts.map +0 -1
- package/dist/storage/sqlite.js +0 -1148
- package/dist/storage/sqlite.js.map +0 -1
- package/dist/storage/sqlite.test.d.ts +0 -2
- package/dist/storage/sqlite.test.d.ts.map +0 -1
- package/dist/storage/sqlite.test.js +0 -367
- package/dist/storage/sqlite.test.js.map +0 -1
- package/dist/storage/vectors.d.ts +0 -19
- package/dist/storage/vectors.d.ts.map +0 -1
- package/dist/storage/vectors.js +0 -74
- package/dist/storage/vectors.js.map +0 -1
- package/dist/storage/vectors.stub.d.ts +0 -12
- package/dist/storage/vectors.stub.d.ts.map +0 -1
- package/dist/storage/vectors.stub.js +0 -88
- package/dist/storage/vectors.stub.js.map +0 -1
- package/dist/tasks.archive.test.d.ts +0 -2
- package/dist/tasks.archive.test.d.ts.map +0 -1
- package/dist/tasks.archive.test.js +0 -75
- package/dist/tasks.archive.test.js.map +0 -1
- package/dist/tasks.bulk.test.d.ts +0 -2
- package/dist/tasks.bulk.test.d.ts.map +0 -1
- package/dist/tasks.bulk.test.js +0 -250
- package/dist/tasks.bulk.test.js.map +0 -1
- package/dist/tasks.e2e.test.d.ts +0 -2
- package/dist/tasks.e2e.test.d.ts.map +0 -1
- package/dist/tasks.e2e.test.js +0 -289
- package/dist/tasks.e2e.test.js.map +0 -1
- package/dist/tests/client.test.d.ts +0 -2
- package/dist/tests/client.test.d.ts.map +0 -1
- package/dist/tests/client.test.js +0 -130
- package/dist/tests/client.test.js.map +0 -1
- package/dist/tests/dashboard.test.d.ts +0 -2
- package/dist/tests/dashboard.test.d.ts.map +0 -1
- package/dist/tests/dashboard.test.js +0 -370
- package/dist/tests/dashboard.test.js.map +0 -1
- package/dist/tests/e2e.test.d.ts +0 -2
- package/dist/tests/e2e.test.d.ts.map +0 -1
- package/dist/tests/e2e.test.js +0 -250
- package/dist/tests/e2e.test.js.map +0 -1
- package/dist/tests/index.test.d.ts +0 -2
- package/dist/tests/index.test.d.ts.map +0 -1
- package/dist/tests/index.test.js +0 -185
- package/dist/tests/index.test.js.map +0 -1
- package/dist/tests/logger.test.d.ts +0 -2
- package/dist/tests/logger.test.d.ts.map +0 -1
- package/dist/tests/logger.test.js +0 -104
- package/dist/tests/logger.test.js.map +0 -1
- package/dist/tests/memory.bulk.test.d.ts +0 -2
- package/dist/tests/memory.bulk.test.d.ts.map +0 -1
- package/dist/tests/memory.bulk.test.js +0 -52
- package/dist/tests/memory.bulk.test.js.map +0 -1
- package/dist/tests/memory.search.test.d.ts +0 -2
- package/dist/tests/memory.search.test.d.ts.map +0 -1
- package/dist/tests/memory.search.test.js +0 -181
- package/dist/tests/memory.search.test.js.map +0 -1
- package/dist/tests/normalize.test.d.ts +0 -2
- package/dist/tests/normalize.test.d.ts.map +0 -1
- package/dist/tests/normalize.test.js +0 -181
- package/dist/tests/normalize.test.js.map +0 -1
- package/dist/tests/query-expander.test.d.ts +0 -2
- package/dist/tests/query-expander.test.d.ts.map +0 -1
- package/dist/tests/query-expander.test.js +0 -33
- package/dist/tests/query-expander.test.js.map +0 -1
- package/dist/tests/router.test.d.ts +0 -2
- package/dist/tests/router.test.d.ts.map +0 -1
- package/dist/tests/router.test.js +0 -470
- package/dist/tests/router.test.js.map +0 -1
- package/dist/tests/sqlite.test.d.ts +0 -2
- package/dist/tests/sqlite.test.d.ts.map +0 -1
- package/dist/tests/sqlite.test.js +0 -367
- package/dist/tests/sqlite.test.js.map +0 -1
- package/dist/tests/tasks-search.test.d.ts +0 -2
- package/dist/tests/tasks-search.test.d.ts.map +0 -1
- package/dist/tests/tasks-search.test.js +0 -154
- package/dist/tests/tasks-search.test.js.map +0 -1
- package/dist/tests/tasks-transition.test.d.ts +0 -2
- package/dist/tests/tasks-transition.test.d.ts.map +0 -1
- package/dist/tests/tasks-transition.test.js +0 -174
- package/dist/tests/tasks-transition.test.js.map +0 -1
- package/dist/tests/tasks.bulk.test.d.ts +0 -2
- package/dist/tests/tasks.bulk.test.d.ts.map +0 -1
- package/dist/tests/tasks.bulk.test.js +0 -254
- package/dist/tests/tasks.bulk.test.js.map +0 -1
- package/dist/tests/tasks.e2e.test.d.ts +0 -2
- package/dist/tests/tasks.e2e.test.d.ts.map +0 -1
- package/dist/tests/tasks.e2e.test.js +0 -289
- package/dist/tests/tasks.e2e.test.js.map +0 -1
- package/dist/tests/tasks.pending-limit-refined.test.d.ts +0 -2
- package/dist/tests/tasks.pending-limit-refined.test.d.ts.map +0 -1
- package/dist/tests/tasks.pending-limit-refined.test.js +0 -72
- package/dist/tests/tasks.pending-limit-refined.test.js.map +0 -1
- package/dist/tests/v2-features.test.d.ts +0 -2
- package/dist/tests/v2-features.test.d.ts.map +0 -1
- package/dist/tests/v2-features.test.js +0 -209
- package/dist/tests/v2-features.test.js.map +0 -1
- package/dist/tools/memory.acknowledge.d.ts +0 -4
- package/dist/tools/memory.acknowledge.d.ts.map +0 -1
- package/dist/tools/memory.acknowledge.js +0 -30
- package/dist/tools/memory.acknowledge.js.map +0 -1
- package/dist/tools/memory.bulk-delete.d.ts +0 -4
- package/dist/tools/memory.bulk-delete.d.ts.map +0 -1
- package/dist/tools/memory.bulk-delete.js +0 -39
- package/dist/tools/memory.bulk-delete.js.map +0 -1
- package/dist/tools/memory.delete.d.ts +0 -9
- package/dist/tools/memory.delete.d.ts.map +0 -1
- package/dist/tools/memory.delete.js +0 -39
- package/dist/tools/memory.delete.js.map +0 -1
- package/dist/tools/memory.recap.d.ts +0 -4
- package/dist/tools/memory.recap.d.ts.map +0 -1
- package/dist/tools/memory.recap.js +0 -90
- package/dist/tools/memory.recap.js.map +0 -1
- package/dist/tools/memory.search.d.ts +0 -5
- package/dist/tools/memory.search.d.ts.map +0 -1
- package/dist/tools/memory.search.js +0 -134
- package/dist/tools/memory.search.js.map +0 -1
- package/dist/tools/memory.search.test.d.ts +0 -2
- package/dist/tools/memory.search.test.d.ts.map +0 -1
- package/dist/tools/memory.search.test.js +0 -181
- package/dist/tools/memory.search.test.js.map +0 -1
- package/dist/tools/memory.store.d.ts +0 -5
- package/dist/tools/memory.store.d.ts.map +0 -1
- package/dist/tools/memory.store.js +0 -117
- package/dist/tools/memory.store.js.map +0 -1
- package/dist/tools/memory.summarize.d.ts +0 -4
- package/dist/tools/memory.summarize.d.ts.map +0 -1
- package/dist/tools/memory.summarize.js +0 -31
- package/dist/tools/memory.summarize.js.map +0 -1
- package/dist/tools/memory.synthesize.d.ts +0 -14
- package/dist/tools/memory.synthesize.d.ts.map +0 -1
- package/dist/tools/memory.synthesize.js +0 -228
- package/dist/tools/memory.synthesize.js.map +0 -1
- package/dist/tools/memory.update.d.ts +0 -5
- package/dist/tools/memory.update.d.ts.map +0 -1
- package/dist/tools/memory.update.js +0 -73
- package/dist/tools/memory.update.js.map +0 -1
- package/dist/tools/schemas.d.ts +0 -2762
- package/dist/tools/schemas.d.ts.map +0 -1
- package/dist/tools/schemas.js +0 -952
- package/dist/tools/schemas.js.map +0 -1
- package/dist/tools/task.bulk-manage.d.ts +0 -4
- package/dist/tools/task.bulk-manage.d.ts.map +0 -1
- package/dist/tools/task.bulk-manage.js +0 -146
- package/dist/tools/task.bulk-manage.js.map +0 -1
- package/dist/tools/task.manage.d.ts +0 -16
- package/dist/tools/task.manage.d.ts.map +0 -1
- package/dist/tools/task.manage.js +0 -395
- package/dist/tools/task.manage.js.map +0 -1
- package/dist/tools/tasks-transition.test.d.ts +0 -2
- package/dist/tools/tasks-transition.test.d.ts.map +0 -1
- package/dist/tools/tasks-transition.test.js +0 -174
- package/dist/tools/tasks-transition.test.js.map +0 -1
- package/dist/tools/tasks.pending-limit-refined.test.d.ts +0 -2
- package/dist/tools/tasks.pending-limit-refined.test.d.ts.map +0 -1
- package/dist/tools/tasks.pending-limit-refined.test.js +0 -72
- package/dist/tools/tasks.pending-limit-refined.test.js.map +0 -1
- package/dist/types.d.ts +0 -87
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
- package/dist/utils/completion.d.ts +0 -2
- package/dist/utils/completion.d.ts.map +0 -1
- package/dist/utils/completion.js +0 -28
- package/dist/utils/completion.js.map +0 -1
- package/dist/utils/git-scope.d.ts +0 -8
- package/dist/utils/git-scope.d.ts.map +0 -1
- package/dist/utils/git-scope.js +0 -38
- package/dist/utils/git-scope.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -25
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -152
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/logger.test.d.ts +0 -2
- package/dist/utils/logger.test.d.ts.map +0 -1
- package/dist/utils/logger.test.js +0 -76
- package/dist/utils/logger.test.js.map +0 -1
- package/dist/utils/mcp-response.d.ts +0 -96
- package/dist/utils/mcp-response.d.ts.map +0 -1
- package/dist/utils/mcp-response.js +0 -131
- package/dist/utils/mcp-response.js.map +0 -1
- package/dist/utils/normalize.d.ts +0 -9
- package/dist/utils/normalize.d.ts.map +0 -1
- package/dist/utils/normalize.js +0 -62
- package/dist/utils/normalize.js.map +0 -1
- package/dist/utils/normalize.test.d.ts +0 -2
- package/dist/utils/normalize.test.d.ts.map +0 -1
- package/dist/utils/normalize.test.js +0 -159
- package/dist/utils/normalize.test.js.map +0 -1
- package/dist/utils/pagination.d.ts +0 -6
- package/dist/utils/pagination.d.ts.map +0 -1
- package/dist/utils/pagination.js +0 -32
- package/dist/utils/pagination.js.map +0 -1
- package/dist/utils/query-expander.d.ts +0 -2
- package/dist/utils/query-expander.d.ts.map +0 -1
- package/dist/utils/query-expander.js +0 -29
- package/dist/utils/query-expander.js.map +0 -1
- package/dist/utils/query-expander.test.d.ts +0 -2
- package/dist/utils/query-expander.test.d.ts.map +0 -1
- package/dist/utils/query-expander.test.js +0 -33
- package/dist/utils/query-expander.test.js.map +0 -1
- package/dist/v2-features.test.d.ts +0 -2
- package/dist/v2-features.test.d.ts.map +0 -1
- package/dist/v2-features.test.js +0 -209
- package/dist/v2-features.test.js.map +0 -1
- /package/dist/{mcp/prompts/definitions → prompts}/architecture-design.md +0 -0
- /package/dist/{mcp/prompts/definitions → prompts}/documentation-sync.md +0 -0
- /package/dist/{mcp/prompts/definitions → prompts}/fix-suggestion.md +0 -0
- /package/dist/{mcp/prompts/definitions → prompts}/import-github-issues.md +0 -0
- /package/dist/{mcp/prompts/definitions → prompts}/learning-retrospective.md +0 -0
- /package/dist/{mcp/prompts/definitions → prompts}/memory-guided-review.md +0 -0
- /package/dist/{mcp/prompts/definitions → prompts}/project-briefing.md +0 -0
- /package/dist/{mcp/prompts/definitions → prompts}/root-cause-analysis.md +0 -0
- /package/dist/{mcp/prompts/definitions → prompts}/security-triage.md +0 -0
- /package/dist/{mcp/prompts/definitions → prompts}/senior-code-review.md +0 -0
- /package/dist/{mcp/prompts/definitions → prompts}/session-planner.md +0 -0
- /package/dist/{mcp/prompts/definitions → prompts}/tech-affinity-scout.md +0 -0
- /package/dist/{mcp/prompts/definitions → prompts}/technical-planning.md +0 -0
- /package/dist/{mcp/prompts/definitions → prompts}/tool-usage-guidelines.md +0 -0
package/dist/storage/sqlite.js
DELETED
|
@@ -1,1148 +0,0 @@
|
|
|
1
|
-
import Database from "better-sqlite3";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import fs from "fs";
|
|
4
|
-
import os from "os";
|
|
5
|
-
import { fileURLToPath } from "url";
|
|
6
|
-
import { tokenize } from "../utils/normalize.js";
|
|
7
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
/**
|
|
9
|
-
* Resolve database path with following priority:
|
|
10
|
-
* 1. MEMORY_DB_PATH env var
|
|
11
|
-
* 2. ~/.config/local-memory-mcp/memory.db (standard user config)
|
|
12
|
-
* 3. Local storage/ folder in CWD (for npx/global usage)
|
|
13
|
-
* 4. Project root storage/ folder
|
|
14
|
-
*/
|
|
15
|
-
function resolveDbPath() {
|
|
16
|
-
if (process.env.MEMORY_DB_PATH) {
|
|
17
|
-
return process.env.MEMORY_DB_PATH;
|
|
18
|
-
}
|
|
19
|
-
// 1. Define the standard global path for this platform
|
|
20
|
-
const standardConfigDir = process.platform === "win32"
|
|
21
|
-
? path.join(os.homedir(), ".local-memory-mcp")
|
|
22
|
-
: process.platform === "darwin"
|
|
23
|
-
? path.join(os.homedir(), "Library", "Application Support", "local-memory-mcp")
|
|
24
|
-
: path.join(os.homedir(), ".config", "local-memory-mcp");
|
|
25
|
-
const standardPath = path.join(standardConfigDir, "memory.db");
|
|
26
|
-
// 2. If the global database already exists, ALWAYS use it to ensure consistency
|
|
27
|
-
if (fs.existsSync(standardPath)) {
|
|
28
|
-
return standardPath;
|
|
29
|
-
}
|
|
30
|
-
// 3. Migration/Legacy check: ~/.config/local-memory-mcp/memory.db
|
|
31
|
-
const legacyPath = path.join(os.homedir(), ".config", "local-memory-mcp", "memory.db");
|
|
32
|
-
if (fs.existsSync(legacyPath)) {
|
|
33
|
-
return legacyPath;
|
|
34
|
-
}
|
|
35
|
-
// 4. Development/Portable check: ONLY use local storage if the FILE actually exists.
|
|
36
|
-
// This prevents divergence when one process sees a 'storage/' folder and another doesn't.
|
|
37
|
-
const localCwdFile = path.join(process.cwd(), "storage", "memory.db");
|
|
38
|
-
if (fs.existsSync(localCwdFile)) {
|
|
39
|
-
return localCwdFile;
|
|
40
|
-
}
|
|
41
|
-
const localProjFile = path.join(__dirname, "../../storage", "memory.db");
|
|
42
|
-
if (fs.existsSync(localProjFile)) {
|
|
43
|
-
return localProjFile;
|
|
44
|
-
}
|
|
45
|
-
// 5. Default: Return the standard global path (it will be created by the constructor)
|
|
46
|
-
return standardPath;
|
|
47
|
-
}
|
|
48
|
-
const DB_PATH = resolveDbPath();
|
|
49
|
-
export class SQLiteStore {
|
|
50
|
-
db;
|
|
51
|
-
constructor(dbPath) {
|
|
52
|
-
const finalPath = dbPath ?? DB_PATH;
|
|
53
|
-
const dbDir = path.dirname(finalPath);
|
|
54
|
-
if (!fs.existsSync(dbDir)) {
|
|
55
|
-
fs.mkdirSync(dbDir, { recursive: true });
|
|
56
|
-
}
|
|
57
|
-
this.db = new Database(finalPath);
|
|
58
|
-
this.db.pragma("journal_mode = WAL");
|
|
59
|
-
this.db.pragma("synchronous = NORMAL");
|
|
60
|
-
this.db.pragma("busy_timeout = 5000");
|
|
61
|
-
this.migrate();
|
|
62
|
-
}
|
|
63
|
-
getDbPath() {
|
|
64
|
-
return DB_PATH;
|
|
65
|
-
}
|
|
66
|
-
migrate() {
|
|
67
|
-
// 1. Create base tables first
|
|
68
|
-
this.db.exec(`
|
|
69
|
-
CREATE TABLE IF NOT EXISTS memories (
|
|
70
|
-
id TEXT PRIMARY KEY,
|
|
71
|
-
repo TEXT NOT NULL,
|
|
72
|
-
type TEXT NOT NULL,
|
|
73
|
-
title TEXT,
|
|
74
|
-
content TEXT NOT NULL,
|
|
75
|
-
importance INTEGER NOT NULL CHECK (importance BETWEEN 1 AND 5),
|
|
76
|
-
folder TEXT,
|
|
77
|
-
language TEXT,
|
|
78
|
-
created_at TEXT NOT NULL,
|
|
79
|
-
updated_at TEXT NOT NULL,
|
|
80
|
-
hit_count INTEGER NOT NULL DEFAULT 0,
|
|
81
|
-
recall_count INTEGER NOT NULL DEFAULT 0,
|
|
82
|
-
last_used_at TEXT,
|
|
83
|
-
agent TEXT NOT NULL DEFAULT 'unknown',
|
|
84
|
-
role TEXT NOT NULL DEFAULT 'unknown',
|
|
85
|
-
model TEXT NOT NULL DEFAULT 'unknown',
|
|
86
|
-
completed_at TEXT
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
CREATE INDEX IF NOT EXISTS idx_memories_repo ON memories(repo);
|
|
90
|
-
CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(type);
|
|
91
|
-
CREATE INDEX IF NOT EXISTS idx_memories_importance ON memories(importance);
|
|
92
|
-
CREATE INDEX IF NOT EXISTS idx_memories_hit_count ON memories(hit_count);
|
|
93
|
-
CREATE INDEX IF NOT EXISTS idx_memories_created_at ON memories(created_at);
|
|
94
|
-
CREATE INDEX IF NOT EXISTS idx_memories_updated_at ON memories(updated_at);
|
|
95
|
-
CREATE INDEX IF NOT EXISTS idx_memories_repo_created_at ON memories(repo, created_at DESC);
|
|
96
|
-
CREATE INDEX IF NOT EXISTS idx_memories_repo_hit_count ON memories(repo, hit_count DESC);
|
|
97
|
-
CREATE INDEX IF NOT EXISTS idx_memories_title ON memories(title);
|
|
98
|
-
|
|
99
|
-
CREATE TABLE IF NOT EXISTS memory_summary (
|
|
100
|
-
repo TEXT PRIMARY KEY,
|
|
101
|
-
summary TEXT NOT NULL,
|
|
102
|
-
updated_at TEXT NOT NULL
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
CREATE TABLE IF NOT EXISTS memory_vectors (
|
|
106
|
-
memory_id TEXT PRIMARY KEY,
|
|
107
|
-
vector TEXT NOT NULL,
|
|
108
|
-
updated_at TEXT NOT NULL,
|
|
109
|
-
FOREIGN KEY (memory_id) REFERENCES memories(id) ON DELETE CASCADE
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
CREATE TABLE IF NOT EXISTS tasks (
|
|
113
|
-
id TEXT PRIMARY KEY,
|
|
114
|
-
repo TEXT NOT NULL,
|
|
115
|
-
task_code TEXT NOT NULL,
|
|
116
|
-
phase TEXT,
|
|
117
|
-
title TEXT NOT NULL,
|
|
118
|
-
description TEXT,
|
|
119
|
-
status TEXT NOT NULL DEFAULT 'backlog',
|
|
120
|
-
priority INTEGER NOT NULL DEFAULT 3,
|
|
121
|
-
agent TEXT NOT NULL DEFAULT 'unknown',
|
|
122
|
-
role TEXT NOT NULL DEFAULT 'unknown',
|
|
123
|
-
doc_path TEXT,
|
|
124
|
-
created_at TEXT NOT NULL,
|
|
125
|
-
updated_at TEXT NOT NULL,
|
|
126
|
-
finished_at TEXT,
|
|
127
|
-
canceled_at TEXT,
|
|
128
|
-
tags TEXT,
|
|
129
|
-
metadata TEXT,
|
|
130
|
-
parent_id TEXT,
|
|
131
|
-
depends_on TEXT,
|
|
132
|
-
est_tokens INTEGER NOT NULL DEFAULT 0,
|
|
133
|
-
in_progress_at TEXT,
|
|
134
|
-
FOREIGN KEY (parent_id) REFERENCES tasks(id) ON DELETE SET NULL,
|
|
135
|
-
FOREIGN KEY (depends_on) REFERENCES tasks(id) ON DELETE SET NULL
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
CREATE INDEX IF NOT EXISTS idx_tasks_repo ON tasks(repo);
|
|
139
|
-
CREATE INDEX IF NOT EXISTS idx_tasks_code ON tasks(task_code);
|
|
140
|
-
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
|
141
|
-
CREATE INDEX IF NOT EXISTS idx_tasks_phase ON tasks(phase);
|
|
142
|
-
CREATE INDEX IF NOT EXISTS idx_tasks_priority ON tasks(priority);
|
|
143
|
-
CREATE INDEX IF NOT EXISTS idx_tasks_created_at ON tasks(created_at);
|
|
144
|
-
|
|
145
|
-
CREATE TABLE IF NOT EXISTS task_comments (
|
|
146
|
-
id TEXT PRIMARY KEY,
|
|
147
|
-
task_id TEXT NOT NULL,
|
|
148
|
-
repo TEXT NOT NULL,
|
|
149
|
-
comment TEXT NOT NULL,
|
|
150
|
-
agent TEXT NOT NULL DEFAULT 'unknown',
|
|
151
|
-
role TEXT NOT NULL DEFAULT 'unknown',
|
|
152
|
-
model TEXT NOT NULL DEFAULT 'unknown',
|
|
153
|
-
previous_status TEXT,
|
|
154
|
-
next_status TEXT,
|
|
155
|
-
created_at TEXT NOT NULL,
|
|
156
|
-
FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
CREATE INDEX IF NOT EXISTS idx_task_comments_task_id ON task_comments(task_id);
|
|
160
|
-
CREATE INDEX IF NOT EXISTS idx_task_comments_repo ON task_comments(repo);
|
|
161
|
-
CREATE INDEX IF NOT EXISTS idx_task_comments_created_at ON task_comments(created_at DESC);
|
|
162
|
-
|
|
163
|
-
CREATE TABLE IF NOT EXISTS memories_archive (
|
|
164
|
-
id TEXT PRIMARY KEY,
|
|
165
|
-
repo TEXT NOT NULL,
|
|
166
|
-
type TEXT NOT NULL,
|
|
167
|
-
content TEXT NOT NULL,
|
|
168
|
-
importance INTEGER NOT NULL,
|
|
169
|
-
folder TEXT,
|
|
170
|
-
language TEXT,
|
|
171
|
-
created_at TEXT NOT NULL,
|
|
172
|
-
updated_at TEXT NOT NULL,
|
|
173
|
-
hit_count INTEGER NOT NULL DEFAULT 0,
|
|
174
|
-
recall_count INTEGER NOT NULL DEFAULT 0,
|
|
175
|
-
last_used_at TEXT,
|
|
176
|
-
expires_at TEXT,
|
|
177
|
-
archived_at TEXT NOT NULL,
|
|
178
|
-
agent TEXT NOT NULL DEFAULT 'unknown',
|
|
179
|
-
role TEXT NOT NULL DEFAULT 'unknown',
|
|
180
|
-
model TEXT NOT NULL DEFAULT 'unknown',
|
|
181
|
-
completed_at TEXT
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
CREATE TABLE IF NOT EXISTS action_log (
|
|
185
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
186
|
-
action TEXT NOT NULL,
|
|
187
|
-
query TEXT,
|
|
188
|
-
response TEXT,
|
|
189
|
-
memory_id TEXT,
|
|
190
|
-
task_id TEXT,
|
|
191
|
-
repo TEXT NOT NULL,
|
|
192
|
-
result_count INTEGER NOT NULL DEFAULT 0,
|
|
193
|
-
created_at TEXT NOT NULL
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
CREATE INDEX IF NOT EXISTS idx_action_log_repo ON action_log(repo);
|
|
197
|
-
CREATE INDEX IF NOT EXISTS idx_action_log_created_at ON action_log(created_at);
|
|
198
|
-
`);
|
|
199
|
-
// 2. Safely add missing columns for existing tables
|
|
200
|
-
const columnsToAdd = [
|
|
201
|
-
{ name: "title", table: "memories", definition: "ALTER TABLE memories ADD COLUMN title TEXT" },
|
|
202
|
-
{ name: "hit_count", table: "memories", definition: "ALTER TABLE memories ADD COLUMN hit_count INTEGER NOT NULL DEFAULT 0" },
|
|
203
|
-
{ name: "recall_count", table: "memories", definition: "ALTER TABLE memories ADD COLUMN recall_count INTEGER NOT NULL DEFAULT 0" },
|
|
204
|
-
{ name: "last_used_at", table: "memories", definition: "ALTER TABLE memories ADD COLUMN last_used_at TEXT" },
|
|
205
|
-
{ name: "expires_at", table: "memories", definition: "ALTER TABLE memories ADD COLUMN expires_at TEXT" },
|
|
206
|
-
{ name: "supersedes", table: "memories", definition: "ALTER TABLE memories ADD COLUMN supersedes TEXT" },
|
|
207
|
-
{ name: "status", table: "memories", definition: "ALTER TABLE memories ADD COLUMN status TEXT NOT NULL DEFAULT 'active'" },
|
|
208
|
-
{ name: "is_global", table: "memories", definition: "ALTER TABLE memories ADD COLUMN is_global INTEGER NOT NULL DEFAULT 0" },
|
|
209
|
-
{ name: "tags", table: "memories", definition: "ALTER TABLE memories ADD COLUMN tags TEXT" },
|
|
210
|
-
{ name: "metadata", table: "memories", definition: "ALTER TABLE memories ADD COLUMN metadata TEXT" },
|
|
211
|
-
{ name: "vector_version", table: "memory_vectors", definition: "ALTER TABLE memory_vectors ADD COLUMN vector_version INTEGER NOT NULL DEFAULT 1" },
|
|
212
|
-
{ name: "depends_on", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN depends_on TEXT" },
|
|
213
|
-
{ name: "est_tokens", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN est_tokens INTEGER NOT NULL DEFAULT 0" },
|
|
214
|
-
{ name: "in_progress_at", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN in_progress_at TEXT" },
|
|
215
|
-
{ name: "task_code", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN task_code TEXT" },
|
|
216
|
-
{ name: "task_id", table: "action_log", definition: "ALTER TABLE action_log ADD COLUMN task_id TEXT" },
|
|
217
|
-
{ name: "agent", table: "memories", definition: "ALTER TABLE memories ADD COLUMN agent TEXT NOT NULL DEFAULT 'unknown'" },
|
|
218
|
-
{ name: "role", table: "memories", definition: "ALTER TABLE memories ADD COLUMN role TEXT NOT NULL DEFAULT 'unknown'" },
|
|
219
|
-
{ name: "model", table: "memories", definition: "ALTER TABLE memories ADD COLUMN model TEXT NOT NULL DEFAULT 'unknown'" },
|
|
220
|
-
{ name: "completed_at", table: "memories", definition: "ALTER TABLE memories ADD COLUMN completed_at TEXT" },
|
|
221
|
-
{ name: "agent", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN agent TEXT NOT NULL DEFAULT 'unknown'" },
|
|
222
|
-
{ name: "role", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN role TEXT NOT NULL DEFAULT 'unknown'" },
|
|
223
|
-
{ name: "doc_path", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN doc_path TEXT" },
|
|
224
|
-
{ name: "response", table: "action_log", definition: "ALTER TABLE action_log ADD COLUMN response TEXT" },
|
|
225
|
-
];
|
|
226
|
-
for (const col of columnsToAdd) {
|
|
227
|
-
try {
|
|
228
|
-
const tableInfo = this.db.prepare(`PRAGMA table_info(${col.table})`).all();
|
|
229
|
-
const existingTableColumns = tableInfo.map((c) => c.name);
|
|
230
|
-
// Only run ALTER TABLE if table exists and column doesn't
|
|
231
|
-
if (tableInfo.length > 0 && !existingTableColumns.includes(col.name)) {
|
|
232
|
-
this.db.exec(col.definition);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
catch (e) {
|
|
236
|
-
// Skip safely
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
this.ensureMemoryTypeConstraint();
|
|
240
|
-
this.ensureTaskStatusConstraintRemoved();
|
|
241
|
-
this.ensureMemoryStatusConstraintRemoved();
|
|
242
|
-
this.db.exec(`
|
|
243
|
-
CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status);
|
|
244
|
-
CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes);
|
|
245
|
-
CREATE INDEX IF NOT EXISTS idx_memories_is_global ON memories(is_global);
|
|
246
|
-
`);
|
|
247
|
-
// Backfill task_code if it was added via migration
|
|
248
|
-
try {
|
|
249
|
-
this.db.exec("UPDATE tasks SET task_code = substr(id, 1, 8) WHERE task_code IS NULL");
|
|
250
|
-
}
|
|
251
|
-
catch (e) { }
|
|
252
|
-
}
|
|
253
|
-
insert(entry) {
|
|
254
|
-
const stmt = this.db.prepare(`
|
|
255
|
-
INSERT INTO memories (
|
|
256
|
-
id, repo, type, title, content, importance, folder, language,
|
|
257
|
-
created_at, updated_at, hit_count, recall_count, last_used_at, expires_at,
|
|
258
|
-
supersedes, status, is_global, tags, metadata, agent, role, model, completed_at
|
|
259
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
260
|
-
`);
|
|
261
|
-
stmt.run(entry.id, entry.scope.repo, entry.type, entry.title || null, entry.content, entry.importance, entry.scope.folder || null, entry.scope.language || null, entry.created_at, entry.updated_at, entry.expires_at ?? null, entry.supersedes ?? null, entry.status || "active", entry.is_global ? 1 : 0, entry.tags ? JSON.stringify(entry.tags) : null, entry.metadata ? JSON.stringify(entry.metadata) : null, entry.agent || 'unknown', entry.role || 'unknown', entry.model || 'unknown', entry.completed_at || null);
|
|
262
|
-
}
|
|
263
|
-
update(id, updates) {
|
|
264
|
-
const fields = [];
|
|
265
|
-
const values = [];
|
|
266
|
-
Object.keys(updates).forEach(key => {
|
|
267
|
-
if (updates[key] !== undefined) {
|
|
268
|
-
if (key === 'tags') {
|
|
269
|
-
fields.push(`tags = ?`);
|
|
270
|
-
values.push(JSON.stringify(updates[key]));
|
|
271
|
-
}
|
|
272
|
-
else if (key === 'metadata') {
|
|
273
|
-
fields.push(`metadata = ?`);
|
|
274
|
-
values.push(JSON.stringify(updates[key]));
|
|
275
|
-
}
|
|
276
|
-
else if (key === 'is_global') {
|
|
277
|
-
fields.push(`is_global = ?`);
|
|
278
|
-
values.push(updates[key] ? 1 : 0);
|
|
279
|
-
}
|
|
280
|
-
else {
|
|
281
|
-
fields.push(`${key} = ?`);
|
|
282
|
-
values.push(updates[key]);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
});
|
|
286
|
-
if (fields.length === 0)
|
|
287
|
-
return;
|
|
288
|
-
fields.push("updated_at = ?");
|
|
289
|
-
values.push(new Date().toISOString());
|
|
290
|
-
values.push(id);
|
|
291
|
-
const stmt = this.db.prepare(`UPDATE memories SET ${fields.join(", ")} WHERE id = ?`);
|
|
292
|
-
stmt.run(...values);
|
|
293
|
-
}
|
|
294
|
-
ensureMemoryTypeConstraint() {
|
|
295
|
-
const tableSql = this.db
|
|
296
|
-
.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'memories'")
|
|
297
|
-
.get();
|
|
298
|
-
if (!tableSql?.sql || !tableSql.sql.includes("CHECK (type IN")) {
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
this.db.exec(`
|
|
302
|
-
BEGIN TRANSACTION;
|
|
303
|
-
|
|
304
|
-
CREATE TABLE memories__migrated (
|
|
305
|
-
id TEXT PRIMARY KEY,
|
|
306
|
-
repo TEXT NOT NULL,
|
|
307
|
-
type TEXT NOT NULL,
|
|
308
|
-
title TEXT,
|
|
309
|
-
content TEXT NOT NULL,
|
|
310
|
-
importance INTEGER NOT NULL CHECK (importance BETWEEN 1 AND 5),
|
|
311
|
-
folder TEXT,
|
|
312
|
-
language TEXT,
|
|
313
|
-
created_at TEXT NOT NULL,
|
|
314
|
-
updated_at TEXT NOT NULL,
|
|
315
|
-
hit_count INTEGER NOT NULL DEFAULT 0,
|
|
316
|
-
recall_count INTEGER NOT NULL DEFAULT 0,
|
|
317
|
-
last_used_at TEXT,
|
|
318
|
-
expires_at TEXT,
|
|
319
|
-
supersedes TEXT,
|
|
320
|
-
status TEXT NOT NULL DEFAULT 'active',
|
|
321
|
-
is_global INTEGER NOT NULL DEFAULT 0,
|
|
322
|
-
tags TEXT,
|
|
323
|
-
metadata TEXT,
|
|
324
|
-
agent TEXT NOT NULL DEFAULT 'unknown',
|
|
325
|
-
role TEXT NOT NULL DEFAULT 'unknown',
|
|
326
|
-
model TEXT NOT NULL DEFAULT 'unknown',
|
|
327
|
-
completed_at TEXT
|
|
328
|
-
);
|
|
329
|
-
|
|
330
|
-
INSERT INTO memories__migrated (
|
|
331
|
-
id, repo, type, title, content, importance, folder, language,
|
|
332
|
-
created_at, updated_at, hit_count, recall_count, last_used_at, expires_at,
|
|
333
|
-
supersedes, status, is_global, tags, metadata, agent, role, model, completed_at
|
|
334
|
-
)
|
|
335
|
-
SELECT
|
|
336
|
-
id, repo, type, title, content, importance, folder, language,
|
|
337
|
-
created_at, updated_at, hit_count, recall_count, last_used_at, expires_at,
|
|
338
|
-
supersedes, status, is_global, tags, metadata, agent, role, model, completed_at
|
|
339
|
-
FROM memories;
|
|
340
|
-
|
|
341
|
-
DROP TABLE memories;
|
|
342
|
-
ALTER TABLE memories__migrated RENAME TO memories;
|
|
343
|
-
|
|
344
|
-
COMMIT;
|
|
345
|
-
`);
|
|
346
|
-
}
|
|
347
|
-
ensureTaskStatusConstraintRemoved() {
|
|
348
|
-
const tableSql = this.db
|
|
349
|
-
.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'tasks'")
|
|
350
|
-
.get();
|
|
351
|
-
// Check if status column has the old restrictive CHECK constraint or old default 'pending'
|
|
352
|
-
if (!tableSql?.sql || (!tableSql.sql.includes("CHECK (status IN") && !tableSql.sql.includes("DEFAULT 'pending'"))) {
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
this.db.exec(`
|
|
356
|
-
BEGIN TRANSACTION;
|
|
357
|
-
|
|
358
|
-
CREATE TABLE tasks__migrated (
|
|
359
|
-
id TEXT PRIMARY KEY,
|
|
360
|
-
repo TEXT NOT NULL,
|
|
361
|
-
task_code TEXT NOT NULL,
|
|
362
|
-
phase TEXT,
|
|
363
|
-
title TEXT NOT NULL,
|
|
364
|
-
description TEXT,
|
|
365
|
-
status TEXT NOT NULL DEFAULT 'backlog',
|
|
366
|
-
priority INTEGER NOT NULL DEFAULT 3,
|
|
367
|
-
agent TEXT NOT NULL DEFAULT 'unknown',
|
|
368
|
-
role TEXT NOT NULL DEFAULT 'unknown',
|
|
369
|
-
doc_path TEXT,
|
|
370
|
-
created_at TEXT NOT NULL,
|
|
371
|
-
updated_at TEXT NOT NULL,
|
|
372
|
-
finished_at TEXT,
|
|
373
|
-
canceled_at TEXT,
|
|
374
|
-
tags TEXT,
|
|
375
|
-
metadata TEXT,
|
|
376
|
-
parent_id TEXT,
|
|
377
|
-
depends_on TEXT,
|
|
378
|
-
est_tokens INTEGER NOT NULL DEFAULT 0,
|
|
379
|
-
in_progress_at TEXT,
|
|
380
|
-
FOREIGN KEY (parent_id) REFERENCES tasks(id) ON DELETE SET NULL,
|
|
381
|
-
FOREIGN KEY (depends_on) REFERENCES tasks(id) ON DELETE SET NULL
|
|
382
|
-
);
|
|
383
|
-
|
|
384
|
-
INSERT INTO tasks__migrated (
|
|
385
|
-
id, repo, task_code, phase, title, description, status, priority,
|
|
386
|
-
agent, role, doc_path, created_at, updated_at, finished_at, canceled_at, tags, metadata, parent_id, depends_on, est_tokens, in_progress_at
|
|
387
|
-
)
|
|
388
|
-
SELECT
|
|
389
|
-
id, repo, task_code, phase, title, description, status, priority,
|
|
390
|
-
agent, role, doc_path, created_at, updated_at, finished_at, canceled_at, tags, metadata, parent_id, depends_on, est_tokens, in_progress_at
|
|
391
|
-
FROM tasks;
|
|
392
|
-
|
|
393
|
-
DROP TABLE tasks;
|
|
394
|
-
ALTER TABLE tasks__migrated RENAME TO tasks;
|
|
395
|
-
|
|
396
|
-
COMMIT;
|
|
397
|
-
`);
|
|
398
|
-
}
|
|
399
|
-
ensureMemoryStatusConstraintRemoved() {
|
|
400
|
-
const tableSql = this.db
|
|
401
|
-
.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'memories'")
|
|
402
|
-
.get();
|
|
403
|
-
// Check if status column has any check constraint
|
|
404
|
-
if (!tableSql?.sql || !tableSql.sql.includes("status TEXT NOT NULL DEFAULT 'active' CHECK")) {
|
|
405
|
-
if (!tableSql?.sql?.includes("status TEXT NOT NULL DEFAULT 'active'")) {
|
|
406
|
-
// If it doesn't even have the status column, it will be added by the general migration loop anyway
|
|
407
|
-
}
|
|
408
|
-
else if (!tableSql.sql.includes("CHECK")) {
|
|
409
|
-
// Already removed or not present
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
else {
|
|
414
|
-
// Continue to migration
|
|
415
|
-
}
|
|
416
|
-
// Re-use ensureMemoryTypeConstraint logic or specifically target status if needed.
|
|
417
|
-
// Since ensureMemoryTypeConstraint already rebuilds the table without checks on type,
|
|
418
|
-
// we just need to make sure it also doesn't have checks on status in its target schema.
|
|
419
|
-
// The ensureMemoryTypeConstraint target schema (memories__migrated) already has no status check.
|
|
420
|
-
}
|
|
421
|
-
getById(id) {
|
|
422
|
-
const row = this.db.prepare("SELECT * FROM memories WHERE id = ?").get(id);
|
|
423
|
-
return row ? this.rowToMemoryEntry(row) : null;
|
|
424
|
-
}
|
|
425
|
-
getByIdWithStats(id) {
|
|
426
|
-
const row = this.db.prepare(`
|
|
427
|
-
SELECT *, CASE WHEN hit_count > 0 THEN CAST(recall_count AS REAL) / hit_count ELSE 0 END AS recall_rate
|
|
428
|
-
FROM memories WHERE id = ?
|
|
429
|
-
`).get(id);
|
|
430
|
-
return row ? { ...this.rowToMemoryEntry(row), recall_rate: row.recall_rate ?? 0 } : null;
|
|
431
|
-
}
|
|
432
|
-
getByIds(ids, filters) {
|
|
433
|
-
if (ids.length === 0)
|
|
434
|
-
return [];
|
|
435
|
-
let query = "SELECT * FROM memories WHERE id IN (" + ids.map(() => "?").join(",") + ")";
|
|
436
|
-
const params = [...ids];
|
|
437
|
-
if (filters?.type) {
|
|
438
|
-
query += " AND type = ?";
|
|
439
|
-
params.push(filters.type);
|
|
440
|
-
}
|
|
441
|
-
if (filters?.status) {
|
|
442
|
-
query += " AND status = ?";
|
|
443
|
-
params.push(filters.status);
|
|
444
|
-
}
|
|
445
|
-
const rows = this.db.prepare(query).all(...params);
|
|
446
|
-
return rows.map(r => this.rowToMemoryEntry(r));
|
|
447
|
-
}
|
|
448
|
-
searchByRepo(repo, options = {}) {
|
|
449
|
-
let where = ["(repo = ? OR is_global = 1)"];
|
|
450
|
-
const params = [repo];
|
|
451
|
-
if (options.tags?.length) {
|
|
452
|
-
const tagConditions = options.tags.map(() => "tags LIKE ?").join(" OR ");
|
|
453
|
-
where.push(`(${tagConditions})`);
|
|
454
|
-
options.tags.forEach((tag) => params.push(`%${tag}%`));
|
|
455
|
-
}
|
|
456
|
-
let query = `SELECT * FROM memories WHERE ${where.join(" AND ")} AND (expires_at IS NULL OR expires_at > datetime('now'))`;
|
|
457
|
-
if (!options.includeArchived)
|
|
458
|
-
query += " AND status = 'active'";
|
|
459
|
-
if (options.types?.length) {
|
|
460
|
-
query += ` AND type IN (${options.types.map(() => "?").join(",")})`;
|
|
461
|
-
params.push(...options.types);
|
|
462
|
-
}
|
|
463
|
-
if (options.minImportance) {
|
|
464
|
-
query += " AND importance >= ?";
|
|
465
|
-
params.push(options.minImportance);
|
|
466
|
-
}
|
|
467
|
-
query += " ORDER BY CASE WHEN repo = ? THEN 0 ELSE 1 END, importance DESC, created_at DESC";
|
|
468
|
-
params.push(repo);
|
|
469
|
-
if (options.limit) {
|
|
470
|
-
query += " LIMIT ?";
|
|
471
|
-
params.push(options.limit);
|
|
472
|
-
}
|
|
473
|
-
const rows = this.db.prepare(query).all(...params);
|
|
474
|
-
return rows.map(r => this.rowToMemoryEntry(r));
|
|
475
|
-
}
|
|
476
|
-
searchBySimilarity(query, repo, limit = 10, includeArchived = false, currentTags = []) {
|
|
477
|
-
const queryVector = this.computeVector(query);
|
|
478
|
-
const now = new Date();
|
|
479
|
-
let where = ["(repo = ? OR is_global = 1)"];
|
|
480
|
-
const params = [repo];
|
|
481
|
-
if (currentTags.length > 0) {
|
|
482
|
-
const tagConditions = currentTags.map(() => "tags LIKE ?").join(" OR ");
|
|
483
|
-
where.push(`(${tagConditions})`);
|
|
484
|
-
currentTags.forEach(tag => params.push(`%${tag}%`));
|
|
485
|
-
}
|
|
486
|
-
let sql = `SELECT * FROM memories WHERE (${where.join(" OR ")}) AND (expires_at IS NULL OR expires_at > ?)`;
|
|
487
|
-
if (!includeArchived)
|
|
488
|
-
sql += " AND status = 'active'";
|
|
489
|
-
sql += ` ORDER BY CASE WHEN repo = ? THEN 0 ELSE 1 END, importance DESC, created_at DESC LIMIT 100`;
|
|
490
|
-
let candidates = this.db.prepare(sql).all(...params, now.toISOString(), repo);
|
|
491
|
-
// Ensure we have at least some candidates for re-ranking
|
|
492
|
-
if (candidates.length < 5) {
|
|
493
|
-
const recentSql = `SELECT * FROM memories WHERE (${where.join(" OR ")}) AND status = 'active' AND (expires_at IS NULL OR expires_at > ?) ORDER BY created_at DESC LIMIT 10`;
|
|
494
|
-
const recent = this.db.prepare(recentSql).all(...params, now.toISOString());
|
|
495
|
-
for (const r of recent) {
|
|
496
|
-
if (!candidates.find(c => c.id === r.id))
|
|
497
|
-
candidates.push(r);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
return candidates.map(row => {
|
|
501
|
-
const memory = this.rowToMemoryEntry(row);
|
|
502
|
-
// Strict validity check
|
|
503
|
-
const isExpired = row.expires_at && new Date(row.expires_at) <= now;
|
|
504
|
-
const isArchived = row.status === 'archived' && !includeArchived;
|
|
505
|
-
if (isExpired || isArchived) {
|
|
506
|
-
return { ...memory, similarity: 0 };
|
|
507
|
-
}
|
|
508
|
-
const similarity = this.cosineSimilarity(queryVector, this.computeVector(memory.content));
|
|
509
|
-
let score = similarity;
|
|
510
|
-
if (!score) {
|
|
511
|
-
score = 0.16; // Baseline for active candidates
|
|
512
|
-
}
|
|
513
|
-
if (row.repo === repo)
|
|
514
|
-
score += 0.1;
|
|
515
|
-
return { ...memory, similarity: score };
|
|
516
|
-
}).filter(r => r.similarity > 0)
|
|
517
|
-
.sort((a, b) => b.similarity - a.similarity)
|
|
518
|
-
.slice(0, limit);
|
|
519
|
-
}
|
|
520
|
-
archiveExpiredMemories(force = false) {
|
|
521
|
-
if (process.env.ENABLE_AUTO_ARCHIVE !== "true" && !force)
|
|
522
|
-
return 0;
|
|
523
|
-
const now = new Date().toISOString();
|
|
524
|
-
const result = this.db.prepare(`
|
|
525
|
-
UPDATE memories SET status = 'archived', updated_at = ?
|
|
526
|
-
WHERE expires_at IS NOT NULL AND expires_at <= ? AND status = 'active'
|
|
527
|
-
`).run(now, now);
|
|
528
|
-
return result.changes;
|
|
529
|
-
}
|
|
530
|
-
archiveLowScoreMemories(force = false) {
|
|
531
|
-
if (process.env.ENABLE_AUTO_ARCHIVE !== "true" && !force)
|
|
532
|
-
return 0;
|
|
533
|
-
const result = this.db.prepare(`
|
|
534
|
-
UPDATE memories SET status = 'archived', updated_at = ?
|
|
535
|
-
WHERE status = 'active' AND (
|
|
536
|
-
(julianday('now') - julianday(COALESCE(last_used_at, created_at)) > 90 AND importance < 3)
|
|
537
|
-
OR (hit_count > 10 AND recall_count = 0)
|
|
538
|
-
)
|
|
539
|
-
`).run(new Date().toISOString());
|
|
540
|
-
return result.changes;
|
|
541
|
-
}
|
|
542
|
-
listRecent(limit = 10) {
|
|
543
|
-
const stmt = this.db.prepare("SELECT id, type, repo FROM memories ORDER BY created_at DESC LIMIT ?");
|
|
544
|
-
return stmt.all(limit);
|
|
545
|
-
}
|
|
546
|
-
getStats(repo) {
|
|
547
|
-
let query = "SELECT type, COUNT(*) as count FROM memories";
|
|
548
|
-
const params = [];
|
|
549
|
-
if (repo) {
|
|
550
|
-
query += " WHERE repo = ?";
|
|
551
|
-
params.push(repo);
|
|
552
|
-
}
|
|
553
|
-
query += " GROUP BY type";
|
|
554
|
-
const rows = this.db.prepare(query).all(...params);
|
|
555
|
-
const byType = {};
|
|
556
|
-
let total = 0;
|
|
557
|
-
for (const row of rows) {
|
|
558
|
-
byType[row.type] = row.count;
|
|
559
|
-
total += row.count;
|
|
560
|
-
}
|
|
561
|
-
const unusedStmt = repo
|
|
562
|
-
? this.db.prepare("SELECT COUNT(*) as count FROM memories WHERE hit_count = 0 AND repo = ?")
|
|
563
|
-
: this.db.prepare("SELECT COUNT(*) as count FROM memories WHERE hit_count = 0");
|
|
564
|
-
const unused = (repo ? unusedStmt.get(repo) : unusedStmt.get());
|
|
565
|
-
return { total, byType, unused: unused?.count || 0 };
|
|
566
|
-
}
|
|
567
|
-
getTaskStats(repo) {
|
|
568
|
-
let query = "SELECT status, COUNT(*) as count FROM tasks";
|
|
569
|
-
const params = [];
|
|
570
|
-
if (repo) {
|
|
571
|
-
query += " WHERE repo = ?";
|
|
572
|
-
params.push(repo);
|
|
573
|
-
}
|
|
574
|
-
query += " GROUP BY status";
|
|
575
|
-
const rows = this.db.prepare(query).all(...params);
|
|
576
|
-
const stats = {
|
|
577
|
-
total: 0,
|
|
578
|
-
backlog: 0,
|
|
579
|
-
todo: 0,
|
|
580
|
-
inProgress: 0,
|
|
581
|
-
completed: 0,
|
|
582
|
-
blocked: 0,
|
|
583
|
-
canceled: 0
|
|
584
|
-
};
|
|
585
|
-
for (const row of rows) {
|
|
586
|
-
stats.total += row.count;
|
|
587
|
-
if (row.status === "backlog")
|
|
588
|
-
stats.backlog = row.count;
|
|
589
|
-
else if (row.status === "pending")
|
|
590
|
-
stats.todo = row.count;
|
|
591
|
-
else if (row.status === "in_progress")
|
|
592
|
-
stats.inProgress = row.count;
|
|
593
|
-
else if (row.status === "completed")
|
|
594
|
-
stats.completed = row.count;
|
|
595
|
-
else if (row.status === "blocked")
|
|
596
|
-
stats.blocked = row.count;
|
|
597
|
-
else if (row.status === "canceled")
|
|
598
|
-
stats.canceled = row.count;
|
|
599
|
-
}
|
|
600
|
-
return stats;
|
|
601
|
-
}
|
|
602
|
-
getDashboardStats(repo) {
|
|
603
|
-
const memoryStats = this.getStats(repo);
|
|
604
|
-
const taskStats = this.getTaskStats(repo);
|
|
605
|
-
// Additional stats for dashboard
|
|
606
|
-
let importanceSql = "SELECT AVG(importance) as avg FROM memories";
|
|
607
|
-
let hitsSql = "SELECT SUM(hit_count) as totalHits FROM memories";
|
|
608
|
-
let expiringSql = "SELECT COUNT(*) as count FROM memories WHERE expires_at IS NOT NULL AND expires_at < date('now', '+7 days')";
|
|
609
|
-
const params = [];
|
|
610
|
-
if (repo) {
|
|
611
|
-
importanceSql += " WHERE repo = ?";
|
|
612
|
-
hitsSql += " WHERE repo = ?";
|
|
613
|
-
expiringSql += " AND repo = ?";
|
|
614
|
-
params.push(repo);
|
|
615
|
-
}
|
|
616
|
-
const avgImportance = this.db.prepare(importanceSql).get(...params)?.avg || 0;
|
|
617
|
-
const totalHitCount = this.db.prepare(hitsSql).get(...params)?.totalHits || 0;
|
|
618
|
-
const expiringSoon = this.db.prepare(expiringSql).get(...params)?.count || 0;
|
|
619
|
-
// Today's stats
|
|
620
|
-
const today = new Date().toISOString().split('T')[0];
|
|
621
|
-
let todayAddedSql = "SELECT COUNT(*) as count FROM tasks WHERE date(created_at) = ?";
|
|
622
|
-
let todayCompletedSql = "SELECT COUNT(*) as count FROM tasks WHERE status = 'completed' AND date(updated_at) = ?";
|
|
623
|
-
let todayProcessedSql = "SELECT COUNT(*) as count FROM task_comments WHERE date(created_at) = ?";
|
|
624
|
-
const todayParams = [today];
|
|
625
|
-
if (repo) {
|
|
626
|
-
todayAddedSql += " AND repo = ?";
|
|
627
|
-
todayCompletedSql += " AND repo = ?";
|
|
628
|
-
todayProcessedSql += " AND repo = ?";
|
|
629
|
-
todayParams.push(repo);
|
|
630
|
-
}
|
|
631
|
-
const todayAdded = this.db.prepare(todayAddedSql).get(...todayParams)?.count || 0;
|
|
632
|
-
const todayCompleted = this.db.prepare(todayCompletedSql).get(...todayParams)?.count || 0;
|
|
633
|
-
const todayProcessed = this.db.prepare(todayProcessedSql).get(...todayParams)?.count || 0;
|
|
634
|
-
let todayTokensSql = "SELECT SUM(est_tokens) as total FROM tasks WHERE date(updated_at) = ?";
|
|
635
|
-
if (repo) {
|
|
636
|
-
todayTokensSql += " AND repo = ?";
|
|
637
|
-
}
|
|
638
|
-
const todayTokens = this.db.prepare(todayTokensSql).get(...todayParams)?.total || 0;
|
|
639
|
-
let avgDurationSql = `
|
|
640
|
-
SELECT AVG(
|
|
641
|
-
(julianday(finished_at) - julianday(in_progress_at)) * 86400.0
|
|
642
|
-
) as avg_seconds
|
|
643
|
-
FROM tasks
|
|
644
|
-
WHERE status = 'completed'
|
|
645
|
-
AND in_progress_at IS NOT NULL
|
|
646
|
-
AND finished_at IS NOT NULL
|
|
647
|
-
AND date(finished_at) = ?
|
|
648
|
-
`;
|
|
649
|
-
if (repo) {
|
|
650
|
-
avgDurationSql += " AND repo = ?";
|
|
651
|
-
}
|
|
652
|
-
const avgDurationSeconds = this.db.prepare(avgDurationSql).get(...todayParams)?.avg_seconds || 0;
|
|
653
|
-
return {
|
|
654
|
-
...memoryStats,
|
|
655
|
-
avgImportance: avgImportance.toFixed(1),
|
|
656
|
-
totalHitCount,
|
|
657
|
-
expiringSoon,
|
|
658
|
-
todayAdded,
|
|
659
|
-
todayCompleted,
|
|
660
|
-
todayProcessed,
|
|
661
|
-
todayTokens,
|
|
662
|
-
todayAvgDuration: avgDurationSeconds,
|
|
663
|
-
taskStats
|
|
664
|
-
};
|
|
665
|
-
}
|
|
666
|
-
listRepoNavigation() {
|
|
667
|
-
return this.db.prepare(`
|
|
668
|
-
SELECT
|
|
669
|
-
m.repo,
|
|
670
|
-
COUNT(m.id) AS memory_count,
|
|
671
|
-
MAX(COALESCE(m.updated_at, m.created_at)) AS last_updated_at,
|
|
672
|
-
COALESCE(t.pending_count, 0) AS pending_count,
|
|
673
|
-
COALESCE(t.in_progress_count, 0) AS in_progress_count,
|
|
674
|
-
COALESCE(t.blocked_count, 0) AS blocked_count,
|
|
675
|
-
COALESCE(t.backlog_count, 0) AS backlog_count
|
|
676
|
-
FROM memories m
|
|
677
|
-
LEFT JOIN (
|
|
678
|
-
SELECT repo,
|
|
679
|
-
SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) AS pending_count,
|
|
680
|
-
SUM(CASE WHEN status = 'in_progress' THEN 1 ELSE 0 END) AS in_progress_count,
|
|
681
|
-
SUM(CASE WHEN status = 'blocked' THEN 1 ELSE 0 END) AS blocked_count,
|
|
682
|
-
SUM(CASE WHEN status = 'backlog' THEN 1 ELSE 0 END) AS backlog_count
|
|
683
|
-
FROM tasks
|
|
684
|
-
GROUP BY repo
|
|
685
|
-
) t ON t.repo = m.repo
|
|
686
|
-
GROUP BY m.repo
|
|
687
|
-
ORDER BY last_updated_at DESC, m.repo ASC
|
|
688
|
-
`).all();
|
|
689
|
-
}
|
|
690
|
-
getAllMemoriesWithStats(repo) {
|
|
691
|
-
let sql = `SELECT *, CASE WHEN hit_count > 0 THEN CAST(recall_count AS REAL) / hit_count ELSE 0 END AS recall_rate FROM memories`;
|
|
692
|
-
if (repo)
|
|
693
|
-
return this.db.prepare(sql + " WHERE repo = ?").all(repo);
|
|
694
|
-
return this.db.prepare(sql).all();
|
|
695
|
-
}
|
|
696
|
-
getLastActionId() {
|
|
697
|
-
const row = this.db.prepare("SELECT MAX(id) as id FROM action_log").get();
|
|
698
|
-
return row?.id || 0;
|
|
699
|
-
}
|
|
700
|
-
getActionsAfter(id) {
|
|
701
|
-
return this.db.prepare(`
|
|
702
|
-
SELECT a.*, m.title as memory_title, m.type as memory_type
|
|
703
|
-
FROM action_log a LEFT JOIN memories m ON a.memory_id = m.id
|
|
704
|
-
WHERE a.id > ? ORDER BY a.created_at ASC
|
|
705
|
-
`).all(id);
|
|
706
|
-
}
|
|
707
|
-
getActionStatsByDate(repo, days = 30) {
|
|
708
|
-
let sql = `
|
|
709
|
-
SELECT
|
|
710
|
-
strftime('%Y-%m-%d', created_at) as date,
|
|
711
|
-
action,
|
|
712
|
-
COUNT(*) as count
|
|
713
|
-
FROM action_log
|
|
714
|
-
WHERE created_at >= date('now', '-' || ? || ' days')
|
|
715
|
-
`;
|
|
716
|
-
const params = [days];
|
|
717
|
-
if (repo) {
|
|
718
|
-
sql += " AND repo = ?";
|
|
719
|
-
params.push(repo);
|
|
720
|
-
}
|
|
721
|
-
sql += " GROUP BY date, action ORDER BY date ASC";
|
|
722
|
-
return this.db.prepare(sql).all(...params);
|
|
723
|
-
}
|
|
724
|
-
listMemoriesForDashboard(options) {
|
|
725
|
-
const { repo, type, tag, isGlobal, minImportance, search, offset = 0, limit = 50, sortBy = 'created_at', sortOrder = 'DESC' } = options;
|
|
726
|
-
let where = ["1=1"];
|
|
727
|
-
const params = [];
|
|
728
|
-
if (repo) {
|
|
729
|
-
where.push("repo = ?");
|
|
730
|
-
params.push(repo);
|
|
731
|
-
}
|
|
732
|
-
if (type) {
|
|
733
|
-
where.push("type = ?");
|
|
734
|
-
params.push(type);
|
|
735
|
-
}
|
|
736
|
-
if (tag) {
|
|
737
|
-
where.push("tags LIKE ?");
|
|
738
|
-
params.push(`%${tag}%`);
|
|
739
|
-
}
|
|
740
|
-
if (isGlobal !== undefined) {
|
|
741
|
-
where.push("is_global = ?");
|
|
742
|
-
params.push(isGlobal ? 1 : 0);
|
|
743
|
-
}
|
|
744
|
-
if (minImportance) {
|
|
745
|
-
where.push("importance >= ?");
|
|
746
|
-
params.push(minImportance);
|
|
747
|
-
}
|
|
748
|
-
if (search) {
|
|
749
|
-
where.push("(title LIKE ? OR content LIKE ? OR tags LIKE ?)");
|
|
750
|
-
params.push(`%${search}%`, `%${search}%`, `%${search}%`);
|
|
751
|
-
}
|
|
752
|
-
const countStmt = this.db.prepare(`SELECT COUNT(*) as count FROM memories WHERE ${where.join(" AND ")}`);
|
|
753
|
-
const total = countStmt.get(...params).count;
|
|
754
|
-
let orderBy = "";
|
|
755
|
-
if (sortBy && sortOrder) {
|
|
756
|
-
orderBy = `ORDER BY ${sortBy} ${sortOrder}`;
|
|
757
|
-
}
|
|
758
|
-
else {
|
|
759
|
-
orderBy = `ORDER BY importance DESC, created_at ASC`;
|
|
760
|
-
}
|
|
761
|
-
const dataStmt = this.db.prepare(`
|
|
762
|
-
SELECT *, CASE WHEN hit_count > 0 THEN CAST(recall_count AS REAL) / hit_count ELSE 0 END AS recall_rate
|
|
763
|
-
FROM memories WHERE ${where.join(" AND ")}
|
|
764
|
-
${orderBy} LIMIT ? OFFSET ?
|
|
765
|
-
`);
|
|
766
|
-
const rows = dataStmt.all(...params, limit, offset);
|
|
767
|
-
const items = rows.map(row => ({
|
|
768
|
-
...this.rowToMemoryEntry(row),
|
|
769
|
-
recall_rate: row.recall_rate ?? 0
|
|
770
|
-
}));
|
|
771
|
-
return { items, memories: items, total, limit, offset };
|
|
772
|
-
}
|
|
773
|
-
getSummary(repo) {
|
|
774
|
-
return this.db.prepare("SELECT summary, updated_at FROM memory_summary WHERE repo = ?").get(repo);
|
|
775
|
-
}
|
|
776
|
-
upsertSummary(repo, summary) {
|
|
777
|
-
this.db.prepare(`
|
|
778
|
-
INSERT INTO memory_summary (repo, summary, updated_at) VALUES (?, ?, ?)
|
|
779
|
-
ON CONFLICT(repo) DO UPDATE SET summary = excluded.summary, updated_at = excluded.updated_at
|
|
780
|
-
`).run(repo, summary, new Date().toISOString());
|
|
781
|
-
}
|
|
782
|
-
delete(id) {
|
|
783
|
-
this.db.prepare("DELETE FROM memories WHERE id = ?").run(id);
|
|
784
|
-
}
|
|
785
|
-
listRepos() {
|
|
786
|
-
return this.db.prepare("SELECT DISTINCT repo FROM memories ORDER BY repo").all().map(r => r.repo);
|
|
787
|
-
}
|
|
788
|
-
incrementHitCount(id) {
|
|
789
|
-
this.db.prepare("UPDATE memories SET hit_count = hit_count + 1, last_used_at = ? WHERE id = ?").run(new Date().toISOString(), id);
|
|
790
|
-
}
|
|
791
|
-
incrementRecallCount(id) {
|
|
792
|
-
this.db.prepare("UPDATE memories SET recall_count = recall_count + 1, last_used_at = ? WHERE id = ?").run(new Date().toISOString(), id);
|
|
793
|
-
}
|
|
794
|
-
insertTask(task) {
|
|
795
|
-
const stmt = this.db.prepare(`
|
|
796
|
-
INSERT INTO tasks (
|
|
797
|
-
id, repo, task_code, phase, title, description, status, priority,
|
|
798
|
-
agent, role, doc_path, created_at, updated_at, finished_at, canceled_at, tags, metadata, parent_id, depends_on, est_tokens, in_progress_at
|
|
799
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
800
|
-
`);
|
|
801
|
-
stmt.run(task.id, task.repo, task.task_code, task.phase || null, task.title, task.description || null, task.status || "backlog", task.priority || 3, task.agent || 'unknown', task.role || 'unknown', task.doc_path || null, task.created_at, task.updated_at, task.finished_at || null, task.canceled_at || null, task.tags ? JSON.stringify(task.tags) : null, task.metadata ? JSON.stringify(task.metadata) : null, task.parent_id || null, task.depends_on || null, task.est_tokens || 0, task.in_progress_at || null);
|
|
802
|
-
}
|
|
803
|
-
updateTask(id, updates) {
|
|
804
|
-
const fields = [];
|
|
805
|
-
const values = [];
|
|
806
|
-
Object.keys(updates).forEach(key => {
|
|
807
|
-
if (key !== "comment" && key !== "model" && updates[key] !== undefined) {
|
|
808
|
-
if (key === 'tags' || key === 'metadata') {
|
|
809
|
-
fields.push(`${key} = ?`);
|
|
810
|
-
values.push(JSON.stringify(updates[key]));
|
|
811
|
-
}
|
|
812
|
-
else {
|
|
813
|
-
fields.push(`${key} = ?`);
|
|
814
|
-
values.push(updates[key]);
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
});
|
|
818
|
-
if (fields.length === 0)
|
|
819
|
-
return;
|
|
820
|
-
fields.push("updated_at = ?");
|
|
821
|
-
values.push(new Date().toISOString());
|
|
822
|
-
values.push(id);
|
|
823
|
-
const stmt = this.db.prepare(`UPDATE tasks SET ${fields.join(", ")} WHERE id = ?`);
|
|
824
|
-
stmt.run(...values);
|
|
825
|
-
}
|
|
826
|
-
getTasksByRepo(repo, status, limit, offset, search) {
|
|
827
|
-
let query = `
|
|
828
|
-
SELECT t.*, d.task_code as depends_on_code
|
|
829
|
-
FROM tasks t
|
|
830
|
-
LEFT JOIN tasks d ON t.depends_on = d.id
|
|
831
|
-
WHERE t.repo = ?
|
|
832
|
-
`;
|
|
833
|
-
const params = [repo];
|
|
834
|
-
if (status) {
|
|
835
|
-
query += " AND t.status = ?";
|
|
836
|
-
params.push(status);
|
|
837
|
-
}
|
|
838
|
-
if (search) {
|
|
839
|
-
query += " AND (t.title LIKE ? OR t.description LIKE ? OR t.task_code LIKE ?)";
|
|
840
|
-
const searchPattern = `%${search}%`;
|
|
841
|
-
params.push(searchPattern, searchPattern, searchPattern);
|
|
842
|
-
}
|
|
843
|
-
// Default sorting logic for the unified list:
|
|
844
|
-
// 1. Completed tasks at the bottom (or top if specified)
|
|
845
|
-
// 2. Priority for others
|
|
846
|
-
// 3. Updated date (newest first for completed)
|
|
847
|
-
query += ` ORDER BY
|
|
848
|
-
CASE WHEN t.status = 'completed' THEN 1 ELSE 0 END ASC,
|
|
849
|
-
CASE WHEN t.status = 'completed' THEN t.updated_at ELSE NULL END DESC,
|
|
850
|
-
CASE WHEN t.status = 'in_progress' THEN 0
|
|
851
|
-
WHEN t.status = 'pending' THEN 1
|
|
852
|
-
WHEN t.status = 'backlog' THEN 2
|
|
853
|
-
WHEN t.status = 'blocked' THEN 3
|
|
854
|
-
WHEN t.status = 'canceled' THEN 4
|
|
855
|
-
ELSE 5 END ASC,
|
|
856
|
-
t.priority DESC,
|
|
857
|
-
t.created_at ASC`;
|
|
858
|
-
if (limit !== undefined) {
|
|
859
|
-
query += " LIMIT ?";
|
|
860
|
-
params.push(limit);
|
|
861
|
-
if (offset !== undefined) {
|
|
862
|
-
query += " OFFSET ?";
|
|
863
|
-
params.push(offset);
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
const rows = this.db.prepare(query).all(...params);
|
|
867
|
-
return rows.map(r => this.rowToTask(r));
|
|
868
|
-
}
|
|
869
|
-
getTasksByMultipleStatuses(repo, statuses, limit, offset, search) {
|
|
870
|
-
if (!statuses.length)
|
|
871
|
-
return this.getTasksByRepo(repo, undefined, limit, offset, search);
|
|
872
|
-
let query = `
|
|
873
|
-
SELECT t.*, d.task_code as depends_on_code
|
|
874
|
-
FROM tasks t
|
|
875
|
-
LEFT JOIN tasks d ON t.depends_on = d.id
|
|
876
|
-
WHERE t.repo = ? AND t.status IN (${statuses.map(() => '?').join(',')})
|
|
877
|
-
`;
|
|
878
|
-
const params = [repo, ...statuses];
|
|
879
|
-
if (search) {
|
|
880
|
-
query += " AND (t.title LIKE ? OR t.description LIKE ? OR t.task_code LIKE ?)";
|
|
881
|
-
const searchPattern = `%${search}%`;
|
|
882
|
-
params.push(searchPattern, searchPattern, searchPattern);
|
|
883
|
-
}
|
|
884
|
-
query += ` ORDER BY
|
|
885
|
-
CASE WHEN t.status = 'completed' THEN 1 ELSE 0 END ASC,
|
|
886
|
-
CASE WHEN t.status = 'completed' THEN t.updated_at ELSE NULL END DESC,
|
|
887
|
-
CASE WHEN t.status = 'in_progress' THEN 0
|
|
888
|
-
WHEN t.status = 'pending' THEN 1
|
|
889
|
-
WHEN t.status = 'backlog' THEN 2
|
|
890
|
-
WHEN t.status = 'blocked' THEN 3
|
|
891
|
-
WHEN t.status = 'canceled' THEN 4
|
|
892
|
-
ELSE 5 END ASC,
|
|
893
|
-
t.priority DESC,
|
|
894
|
-
t.created_at ASC`;
|
|
895
|
-
if (limit !== undefined) {
|
|
896
|
-
query += " LIMIT ?";
|
|
897
|
-
params.push(limit);
|
|
898
|
-
if (offset !== undefined) {
|
|
899
|
-
query += " OFFSET ?";
|
|
900
|
-
params.push(offset);
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
const rows = this.db.prepare(query).all(...params);
|
|
904
|
-
return rows.map(r => this.rowToTask(r));
|
|
905
|
-
}
|
|
906
|
-
deleteTask(id) {
|
|
907
|
-
this.db.prepare("DELETE FROM task_comments WHERE task_id = ?").run(id);
|
|
908
|
-
this.db.prepare("DELETE FROM tasks WHERE id = ?").run(id);
|
|
909
|
-
}
|
|
910
|
-
getTaskById(id) {
|
|
911
|
-
const row = this.db.prepare(`
|
|
912
|
-
SELECT t.*, d.task_code as depends_on_code
|
|
913
|
-
FROM tasks t
|
|
914
|
-
LEFT JOIN tasks d ON t.depends_on = d.id
|
|
915
|
-
WHERE t.id = ?
|
|
916
|
-
`).get(id);
|
|
917
|
-
return row ? { ...this.rowToTask(row), comments: this.getTaskCommentsByTaskId(id) } : null;
|
|
918
|
-
}
|
|
919
|
-
isTaskCodeDuplicate(repo, task_code, excludeId) {
|
|
920
|
-
let query = "SELECT COUNT(*) as count FROM tasks WHERE repo = ? AND task_code = ?";
|
|
921
|
-
const params = [repo, task_code];
|
|
922
|
-
if (excludeId) {
|
|
923
|
-
query += " AND id != ?";
|
|
924
|
-
params.push(excludeId);
|
|
925
|
-
}
|
|
926
|
-
const row = this.db.prepare(query).get(...params);
|
|
927
|
-
return row.count > 0;
|
|
928
|
-
}
|
|
929
|
-
rowToTask(row) {
|
|
930
|
-
let tags = [];
|
|
931
|
-
let metadata = {};
|
|
932
|
-
try {
|
|
933
|
-
if (row.tags)
|
|
934
|
-
tags = JSON.parse(row.tags);
|
|
935
|
-
if (row.metadata)
|
|
936
|
-
metadata = JSON.parse(row.metadata);
|
|
937
|
-
}
|
|
938
|
-
catch (e) { }
|
|
939
|
-
return {
|
|
940
|
-
...row,
|
|
941
|
-
agent: row.agent || 'unknown',
|
|
942
|
-
role: row.role || 'unknown',
|
|
943
|
-
doc_path: row.doc_path || null,
|
|
944
|
-
tags,
|
|
945
|
-
metadata,
|
|
946
|
-
est_tokens: row.est_tokens || 0,
|
|
947
|
-
in_progress_at: row.in_progress_at || null
|
|
948
|
-
};
|
|
949
|
-
}
|
|
950
|
-
insertTaskComment(comment) {
|
|
951
|
-
this.db.prepare(`
|
|
952
|
-
INSERT INTO task_comments (
|
|
953
|
-
id, task_id, repo, comment, agent, role, model, previous_status, next_status, created_at
|
|
954
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
955
|
-
`).run(comment.id, comment.task_id, comment.repo, comment.comment, comment.agent || "unknown", comment.role || "unknown", comment.model || "unknown", comment.previous_status || null, comment.next_status || null, comment.created_at);
|
|
956
|
-
}
|
|
957
|
-
getTaskCommentsByTaskId(taskId) {
|
|
958
|
-
return this.db.prepare(`
|
|
959
|
-
SELECT * FROM task_comments
|
|
960
|
-
WHERE task_id = ?
|
|
961
|
-
ORDER BY created_at DESC, id DESC
|
|
962
|
-
`).all(taskId);
|
|
963
|
-
}
|
|
964
|
-
getRecentMemories(repo, limit, offset = 0, includeArchived = false) {
|
|
965
|
-
let query = "SELECT * FROM memories WHERE repo = ?";
|
|
966
|
-
if (!includeArchived) {
|
|
967
|
-
query += " AND status = 'active'";
|
|
968
|
-
}
|
|
969
|
-
query += " ORDER BY created_at DESC LIMIT ? OFFSET ?";
|
|
970
|
-
const stmt = this.db.prepare(query);
|
|
971
|
-
const rows = stmt.all(repo, limit, offset);
|
|
972
|
-
return rows.map((row) => this.rowToMemoryEntry(row));
|
|
973
|
-
}
|
|
974
|
-
getTotalCount(repo, includeArchived = false) {
|
|
975
|
-
let sql = "SELECT COUNT(*) as count FROM memories WHERE repo = ?";
|
|
976
|
-
if (!includeArchived)
|
|
977
|
-
sql += " AND status = 'active'";
|
|
978
|
-
return this.db.prepare(sql).get(repo).count;
|
|
979
|
-
}
|
|
980
|
-
getVectorCandidates(repo, limit = 100) {
|
|
981
|
-
let sql = `SELECT mv.memory_id, mv.vector FROM memory_vectors mv JOIN memories m ON mv.memory_id = m.id`;
|
|
982
|
-
const params = [];
|
|
983
|
-
if (repo) {
|
|
984
|
-
sql += " WHERE m.repo = ?";
|
|
985
|
-
params.push(repo);
|
|
986
|
-
}
|
|
987
|
-
sql += " LIMIT ?";
|
|
988
|
-
params.push(limit);
|
|
989
|
-
return this.db.prepare(sql).all(...params);
|
|
990
|
-
}
|
|
991
|
-
upsertVectorEmbedding(memoryId, vector) {
|
|
992
|
-
this.db.prepare(`
|
|
993
|
-
INSERT INTO memory_vectors (memory_id, vector, updated_at) VALUES (?, ?, ?)
|
|
994
|
-
ON CONFLICT(memory_id) DO UPDATE SET vector = excluded.vector, updated_at = excluded.updated_at
|
|
995
|
-
`).run(memoryId, JSON.stringify(vector), new Date().toISOString());
|
|
996
|
-
}
|
|
997
|
-
async checkConflicts(content, repo, type, vectors, threshold = 0.55) {
|
|
998
|
-
const vectorResults = await vectors.search(content, 10, repo);
|
|
999
|
-
const candidateIds = vectorResults
|
|
1000
|
-
.filter((vr) => vr.score > threshold)
|
|
1001
|
-
.map((vr) => vr.id);
|
|
1002
|
-
if (candidateIds.length === 0)
|
|
1003
|
-
return null;
|
|
1004
|
-
const memories = this.getByIds(candidateIds, { type, status: "active" });
|
|
1005
|
-
const memoryMap = new Map(memories.map(m => [m.id, m]));
|
|
1006
|
-
// Iterate through original vector results to maintain score priority
|
|
1007
|
-
for (const vr of vectorResults) {
|
|
1008
|
-
if (vr.score > threshold) {
|
|
1009
|
-
const memory = memoryMap.get(vr.id);
|
|
1010
|
-
if (memory)
|
|
1011
|
-
return memory;
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
return null;
|
|
1015
|
-
}
|
|
1016
|
-
logAction(action, repo, options = {}) {
|
|
1017
|
-
this.db.prepare(`INSERT INTO action_log (action, query, response, memory_id, task_id, repo, result_count, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(action, options.query || null, options.response ? (typeof options.response === 'string' ? options.response : JSON.stringify(options.response)) : null, options.memoryId || null, options.taskId || null, repo, options.resultCount || 0, new Date().toISOString());
|
|
1018
|
-
}
|
|
1019
|
-
getRecentActions(repo, limit = 20) {
|
|
1020
|
-
let sql = `
|
|
1021
|
-
SELECT
|
|
1022
|
-
a.*,
|
|
1023
|
-
m.title as memory_title,
|
|
1024
|
-
m.type as memory_type,
|
|
1025
|
-
t.title as task_title,
|
|
1026
|
-
t.task_code as task_code
|
|
1027
|
-
FROM action_log a
|
|
1028
|
-
LEFT JOIN memories m ON a.memory_id = m.id
|
|
1029
|
-
LEFT JOIN tasks t ON a.task_id = t.id
|
|
1030
|
-
`;
|
|
1031
|
-
const params = [];
|
|
1032
|
-
if (repo) {
|
|
1033
|
-
sql += ` WHERE a.repo = ?`;
|
|
1034
|
-
params.push(repo);
|
|
1035
|
-
}
|
|
1036
|
-
sql += ` ORDER BY a.created_at DESC, a.id DESC LIMIT ?`;
|
|
1037
|
-
params.push(limit);
|
|
1038
|
-
return this.db.prepare(sql).all(...params);
|
|
1039
|
-
}
|
|
1040
|
-
computeVector(text) {
|
|
1041
|
-
const tokens = tokenize(text);
|
|
1042
|
-
const vector = {};
|
|
1043
|
-
for (const token of tokens)
|
|
1044
|
-
vector[token] = (vector[token] || 0) + 1;
|
|
1045
|
-
return vector;
|
|
1046
|
-
}
|
|
1047
|
-
cosineSimilarity(v1, v2) {
|
|
1048
|
-
const keys1 = Object.keys(v1);
|
|
1049
|
-
if (!keys1.length || !Object.keys(v2).length)
|
|
1050
|
-
return 0;
|
|
1051
|
-
let dotProduct = 0;
|
|
1052
|
-
for (const key of keys1)
|
|
1053
|
-
if (v2[key])
|
|
1054
|
-
dotProduct += v1[key] * v2[key];
|
|
1055
|
-
const mag1 = Math.sqrt(keys1.reduce((sum, k) => sum + v1[k] * v1[k], 0));
|
|
1056
|
-
const mag2 = Math.sqrt(Object.keys(v2).reduce((sum, k) => sum + v2[k] * v2[k], 0));
|
|
1057
|
-
return (mag1 && mag2) ? dotProduct / (mag1 * mag2) : 0;
|
|
1058
|
-
}
|
|
1059
|
-
rowToMemoryEntry(row) {
|
|
1060
|
-
let tags = [];
|
|
1061
|
-
let metadata = {};
|
|
1062
|
-
try {
|
|
1063
|
-
if (row.tags)
|
|
1064
|
-
tags = JSON.parse(row.tags);
|
|
1065
|
-
if (row.metadata)
|
|
1066
|
-
metadata = JSON.parse(row.metadata);
|
|
1067
|
-
}
|
|
1068
|
-
catch (e) { }
|
|
1069
|
-
return {
|
|
1070
|
-
id: row.id, type: row.type, title: row.title || "Untitled", content: row.content, importance: row.importance,
|
|
1071
|
-
agent: row.agent || 'unknown',
|
|
1072
|
-
role: row.role || 'unknown',
|
|
1073
|
-
model: row.model || 'unknown',
|
|
1074
|
-
scope: { repo: row.repo, folder: row.folder || undefined, language: row.language || undefined },
|
|
1075
|
-
created_at: row.created_at, updated_at: row.updated_at,
|
|
1076
|
-
completed_at: row.completed_at || null,
|
|
1077
|
-
hit_count: row.hit_count ?? 0, recall_count: row.recall_count ?? 0,
|
|
1078
|
-
last_used_at: row.last_used_at ?? null, expires_at: row.expires_at ?? null, supersedes: row.supersedes ?? null, status: row.status || "active",
|
|
1079
|
-
is_global: row.is_global === 1, tags, metadata
|
|
1080
|
-
};
|
|
1081
|
-
}
|
|
1082
|
-
getTaskTimeStats(repo, period) {
|
|
1083
|
-
let dateFilter = "";
|
|
1084
|
-
if (period === 'daily')
|
|
1085
|
-
dateFilter = "AND date(COALESCE(finished_at, updated_at)) = date('now')";
|
|
1086
|
-
else if (period === 'weekly')
|
|
1087
|
-
dateFilter = "AND date(COALESCE(finished_at, updated_at)) >= date('now', '-7 days')";
|
|
1088
|
-
else if (period === 'monthly')
|
|
1089
|
-
dateFilter = "AND date(COALESCE(finished_at, updated_at)) >= date('now', '-30 days')";
|
|
1090
|
-
const stats = this.db.prepare(`
|
|
1091
|
-
SELECT
|
|
1092
|
-
COUNT(*) as completed_count,
|
|
1093
|
-
SUM(est_tokens) as total_tokens,
|
|
1094
|
-
AVG(
|
|
1095
|
-
CASE
|
|
1096
|
-
WHEN in_progress_at IS NOT NULL AND finished_at IS NOT NULL
|
|
1097
|
-
THEN (julianday(finished_at) - julianday(in_progress_at)) * 86400.0
|
|
1098
|
-
ELSE NULL
|
|
1099
|
-
END
|
|
1100
|
-
) as avg_duration_seconds
|
|
1101
|
-
FROM tasks
|
|
1102
|
-
WHERE repo = ?
|
|
1103
|
-
AND status = 'completed'
|
|
1104
|
-
${dateFilter}
|
|
1105
|
-
`).get(repo);
|
|
1106
|
-
let addedDateFilter = "";
|
|
1107
|
-
if (period === 'daily')
|
|
1108
|
-
addedDateFilter = "AND date(created_at) = date('now')";
|
|
1109
|
-
else if (period === 'weekly')
|
|
1110
|
-
addedDateFilter = "AND date(created_at) >= date('now', '-7 days')";
|
|
1111
|
-
else if (period === 'monthly')
|
|
1112
|
-
addedDateFilter = "AND date(created_at) >= date('now', '-30 days')";
|
|
1113
|
-
const added = this.db.prepare(`
|
|
1114
|
-
SELECT COUNT(*) as count FROM tasks
|
|
1115
|
-
WHERE repo = ?
|
|
1116
|
-
${addedDateFilter}
|
|
1117
|
-
`).get(repo);
|
|
1118
|
-
return {
|
|
1119
|
-
completed: stats?.completed_count || 0,
|
|
1120
|
-
tokens: stats?.total_tokens || 0,
|
|
1121
|
-
avgDuration: stats?.avg_duration_seconds || 0,
|
|
1122
|
-
added: added?.count || 0
|
|
1123
|
-
};
|
|
1124
|
-
}
|
|
1125
|
-
updateTaskComment(id, updates) {
|
|
1126
|
-
const fields = [];
|
|
1127
|
-
const values = [];
|
|
1128
|
-
Object.keys(updates).forEach(key => {
|
|
1129
|
-
if (updates[key] !== undefined) {
|
|
1130
|
-
fields.push(`${key} = ?`);
|
|
1131
|
-
values.push(updates[key]);
|
|
1132
|
-
}
|
|
1133
|
-
});
|
|
1134
|
-
if (fields.length === 0)
|
|
1135
|
-
return;
|
|
1136
|
-
values.push(id);
|
|
1137
|
-
const stmt = this.db.prepare(`UPDATE task_comments SET ${fields.join(", ")} WHERE id = ?`);
|
|
1138
|
-
stmt.run(...values);
|
|
1139
|
-
}
|
|
1140
|
-
deleteTaskComment(id) {
|
|
1141
|
-
this.db.prepare("DELETE FROM task_comments WHERE id = ?").run(id);
|
|
1142
|
-
}
|
|
1143
|
-
getTaskCommentById(id) {
|
|
1144
|
-
return this.db.prepare("SELECT * FROM task_comments WHERE id = ?").get(id);
|
|
1145
|
-
}
|
|
1146
|
-
close() { this.db.close(); }
|
|
1147
|
-
}
|
|
1148
|
-
//# sourceMappingURL=sqlite.js.map
|