memory-journal-mcp 6.1.2 → 6.2.1
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 +44 -28
- package/dist/{chunk-X4SWFATC.js → chunk-BI4ZNSKA.js} +38 -24
- package/dist/{chunk-HCEWINSB.js → chunk-N6EBIDN7.js} +99 -102
- package/dist/cli.js +2 -2
- package/dist/index.js +2 -2
- package/dist/tools-WPRY5MJ6.js +2 -0
- package/package.json +10 -1
- package/skills/github-commander/SKILL.md +151 -0
- package/skills/github-commander/config/project-config.example.md +125 -0
- package/skills/github-commander/workflows/code-quality-audit.md +80 -0
- package/skills/github-commander/workflows/full-audit.md +134 -0
- package/skills/github-commander/workflows/issue-triage.md +239 -0
- package/skills/github-commander/workflows/milestone-sprint.md +81 -0
- package/skills/github-commander/workflows/perf-audit.md +142 -0
- package/skills/github-commander/workflows/pr-review.md +123 -0
- package/skills/github-commander/workflows/security-audit.md +170 -0
- package/skills/github-commander/workflows/update-deps.md +109 -0
- package/.dockerignore +0 -139
- package/.gitattributes +0 -20
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -95
- package/.github/ISSUE_TEMPLATE/config.yml +0 -11
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -110
- package/.github/ISSUE_TEMPLATE/question.md +0 -78
- package/.github/aw/actions-lock.json +0 -14
- package/.github/copilot-instructions.md +0 -122
- package/.github/dependabot.yml +0 -93
- package/.github/pull_request_template.md +0 -135
- package/.github/workflows/README.md +0 -133
- package/.github/workflows/agentics-maintenance.yml +0 -141
- package/.github/workflows/auto-release.yml +0 -68
- package/.github/workflows/ci-health-monitor.lock.yml +0 -1121
- package/.github/workflows/ci-health-monitor.md +0 -87
- package/.github/workflows/codeql.yml +0 -41
- package/.github/workflows/dependabot-auto-merge.yml +0 -42
- package/.github/workflows/dependency-maintenance.lock.yml +0 -1182
- package/.github/workflows/dependency-maintenance.md +0 -147
- package/.github/workflows/docker-publish.yml +0 -254
- package/.github/workflows/docs-drift-detector.lock.yml +0 -1142
- package/.github/workflows/docs-drift-detector.md +0 -115
- package/.github/workflows/lint-and-test.yml +0 -60
- package/.github/workflows/publish-npm.yml +0 -85
- package/.github/workflows/secrets-scanning.yml +0 -32
- package/.github/workflows/security-update.yml +0 -127
- package/.gitleaks.toml +0 -9
- package/.prettierignore +0 -21
- package/.prettierrc +0 -33
- package/.scout-ignore +0 -12
- package/.trivyignore +0 -21
- package/CHANGELOG.md +0 -1814
- package/CODE_OF_CONDUCT.md +0 -133
- package/CONTRIBUTING.md +0 -263
- package/DOCKER_README.md +0 -331
- package/Dockerfile +0 -128
- package/SECURITY.md +0 -227
- package/UNRELEASED.md +0 -1
- package/dist/tools-T4U5A3X4.js +0 -2
- package/docker-compose.yml +0 -71
- package/docs/README.md +0 -18
- package/docs/agentic-journal-synergy.md +0 -175
- package/docs/copilot-setup.md +0 -72
- package/eslint.config.js +0 -110
- package/mcp-config-example.json +0 -21
- package/playwright.config.ts +0 -35
- package/releases/v2.1.0.md +0 -220
- package/releases/v2.2.0.md +0 -168
- package/releases/v3.0.0.md +0 -237
- package/releases/v3.1.0.md +0 -104
- package/releases/v3.1.1.md +0 -42
- package/releases/v3.1.2.md +0 -40
- package/releases/v3.1.3.md +0 -64
- package/releases/v3.1.4.md +0 -32
- package/releases/v3.1.5.md +0 -44
- package/releases/v4.0.0.md +0 -71
- package/releases/v4.1.0.md +0 -88
- package/releases/v4.2.0.md +0 -90
- package/releases/v4.3.0.md +0 -92
- package/releases/v4.3.1.md +0 -69
- package/releases/v4.4.0.md +0 -120
- package/releases/v4.4.1.md +0 -33
- package/releases/v4.4.2.md +0 -31
- package/releases/v4.5.0.md +0 -116
- package/releases/v5.0.0.md +0 -105
- package/releases/v5.0.1.md +0 -25
- package/releases/v5.1.0.md +0 -83
- package/releases/v5.1.1.md +0 -10
- package/releases/v6.0.0.md +0 -48
- package/releases/v6.0.1.md +0 -36
- package/releases/v6.1.0.md +0 -68
- package/releases/v6.1.1.md +0 -30
- package/releases/v6.1.2.md +0 -23
- package/scripts/generate-server-instructions.ts +0 -306
- package/scripts/server-instructions-function-body.ts +0 -107
- package/scripts/server-instructions-gotchas.ts +0 -45
- package/server.json +0 -42
- package/social-preview.png +0 -0
- package/src/auth/auth-context.ts +0 -78
- package/src/auth/authorization-server-discovery.ts +0 -263
- package/src/auth/errors.ts +0 -215
- package/src/auth/index.ts +0 -58
- package/src/auth/middleware.ts +0 -392
- package/src/auth/oauth-resource-server.ts +0 -170
- package/src/auth/scope-map.ts +0 -46
- package/src/auth/scopes.ts +0 -256
- package/src/auth/token-validator.ts +0 -293
- package/src/auth/transport-agnostic.ts +0 -164
- package/src/auth/types.ts +0 -372
- package/src/cli.ts +0 -279
- package/src/codemode/api-constants.ts +0 -263
- package/src/codemode/api.ts +0 -302
- package/src/codemode/auto-return.ts +0 -65
- package/src/codemode/index.ts +0 -47
- package/src/codemode/sandbox-factory.ts +0 -144
- package/src/codemode/sandbox.ts +0 -220
- package/src/codemode/security.ts +0 -155
- package/src/codemode/types.ts +0 -228
- package/src/codemode/worker-sandbox.ts +0 -277
- package/src/codemode/worker-script.ts +0 -239
- package/src/constants/icons.ts +0 -183
- package/src/constants/server-instructions.md +0 -166
- package/src/constants/server-instructions.ts +0 -514
- package/src/database/adapter-factory.ts +0 -16
- package/src/database/core/entry-columns.ts +0 -10
- package/src/database/core/interfaces.ts +0 -188
- package/src/database/core/schema.ts +0 -152
- package/src/database/sqlite-adapter/backup.ts +0 -167
- package/src/database/sqlite-adapter/entries/crud.ts +0 -233
- package/src/database/sqlite-adapter/entries/importance.ts +0 -76
- package/src/database/sqlite-adapter/entries/index.ts +0 -142
- package/src/database/sqlite-adapter/entries/search.ts +0 -294
- package/src/database/sqlite-adapter/entries/shared.ts +0 -102
- package/src/database/sqlite-adapter/entries/statistics.ts +0 -162
- package/src/database/sqlite-adapter/index.ts +0 -265
- package/src/database/sqlite-adapter/native-connection.ts +0 -301
- package/src/database/sqlite-adapter/relationships.ts +0 -70
- package/src/database/sqlite-adapter/tags.ts +0 -182
- package/src/filtering/tool-filter.ts +0 -312
- package/src/github/github-integration/client.ts +0 -114
- package/src/github/github-integration/index.ts +0 -297
- package/src/github/github-integration/insights.ts +0 -155
- package/src/github/github-integration/issues.ts +0 -213
- package/src/github/github-integration/milestones.ts +0 -262
- package/src/github/github-integration/projects.ts +0 -414
- package/src/github/github-integration/pull-requests.ts +0 -235
- package/src/github/github-integration/repository.ts +0 -110
- package/src/github/github-integration/types.ts +0 -43
- package/src/handlers/prompts/github.ts +0 -210
- package/src/handlers/prompts/index.ts +0 -97
- package/src/handlers/prompts/workflow.ts +0 -361
- package/src/handlers/resources/core/briefing/context-section.ts +0 -182
- package/src/handlers/resources/core/briefing/github-section.ts +0 -354
- package/src/handlers/resources/core/briefing/index.ts +0 -106
- package/src/handlers/resources/core/briefing/user-message.ts +0 -114
- package/src/handlers/resources/core/health.ts +0 -75
- package/src/handlers/resources/core/index.ts +0 -31
- package/src/handlers/resources/core/instructions.ts +0 -45
- package/src/handlers/resources/core/utilities.ts +0 -310
- package/src/handlers/resources/github.ts +0 -340
- package/src/handlers/resources/graph.ts +0 -218
- package/src/handlers/resources/help.ts +0 -410
- package/src/handlers/resources/index.ts +0 -143
- package/src/handlers/resources/shared.ts +0 -219
- package/src/handlers/resources/team.ts +0 -134
- package/src/handlers/resources/templates.ts +0 -334
- package/src/handlers/tools/admin.ts +0 -351
- package/src/handlers/tools/analytics.ts +0 -346
- package/src/handlers/tools/backup.ts +0 -272
- package/src/handlers/tools/codemode.ts +0 -188
- package/src/handlers/tools/core.ts +0 -359
- package/src/handlers/tools/error-fields-mixin.ts +0 -10
- package/src/handlers/tools/export.ts +0 -150
- package/src/handlers/tools/github/copilot-tools.ts +0 -72
- package/src/handlers/tools/github/helpers.ts +0 -125
- package/src/handlers/tools/github/insights-tools.ts +0 -112
- package/src/handlers/tools/github/issue-tools.ts +0 -442
- package/src/handlers/tools/github/kanban-tools.ts +0 -153
- package/src/handlers/tools/github/milestone-tools.ts +0 -371
- package/src/handlers/tools/github/mutation-tools.ts +0 -17
- package/src/handlers/tools/github/read-tools.ts +0 -302
- package/src/handlers/tools/github/schemas.ts +0 -435
- package/src/handlers/tools/github.ts +0 -39
- package/src/handlers/tools/index.ts +0 -255
- package/src/handlers/tools/relationships.ts +0 -390
- package/src/handlers/tools/schemas.ts +0 -165
- package/src/handlers/tools/search.ts +0 -448
- package/src/handlers/tools/team/admin-tools.ts +0 -164
- package/src/handlers/tools/team/analytics-tools.ts +0 -233
- package/src/handlers/tools/team/backup-tools.ts +0 -83
- package/src/handlers/tools/team/core-tools.ts +0 -197
- package/src/handlers/tools/team/export-tools.ts +0 -130
- package/src/handlers/tools/team/helpers.ts +0 -66
- package/src/handlers/tools/team/index.ts +0 -45
- package/src/handlers/tools/team/relationship-tools.ts +0 -219
- package/src/handlers/tools/team/schemas.ts +0 -558
- package/src/handlers/tools/team/search-tools.ts +0 -145
- package/src/handlers/tools/team/vector-tools.ts +0 -261
- package/src/index.ts +0 -57
- package/src/server/mcp-server.ts +0 -446
- package/src/server/registration.ts +0 -141
- package/src/server/scheduler.ts +0 -283
- package/src/transports/http/handlers.ts +0 -78
- package/src/transports/http/index.ts +0 -8
- package/src/transports/http/security.ts +0 -147
- package/src/transports/http/server/index.ts +0 -397
- package/src/transports/http/server/legacy-sse.ts +0 -87
- package/src/transports/http/server/stateful.ts +0 -222
- package/src/transports/http/server/stateless.ts +0 -42
- package/src/transports/http/types.ts +0 -132
- package/src/types/entities.ts +0 -145
- package/src/types/error-types.ts +0 -92
- package/src/types/errors.ts +0 -200
- package/src/types/filtering.ts +0 -55
- package/src/types/github.ts +0 -216
- package/src/types/index.ts +0 -348
- package/src/utils/error-helpers.ts +0 -78
- package/src/utils/errors/error-response-fields.ts +0 -29
- package/src/utils/errors/suggestions.ts +0 -94
- package/src/utils/github-helpers.ts +0 -33
- package/src/utils/logger.ts +0 -107
- package/src/utils/mcp-logger.ts +0 -155
- package/src/utils/progress-utils.ts +0 -100
- package/src/utils/query-helpers.ts +0 -78
- package/src/utils/resource-annotations.ts +0 -75
- package/src/utils/security-utils.ts +0 -198
- package/src/utils/vector-index-helpers.ts +0 -24
- package/src/vector/vector-search-manager.ts +0 -409
- package/src/version.ts +0 -15
- package/test-server/README.md +0 -193
- package/test-server/code-map.md +0 -399
- package/test-server/test-agent-experience.md +0 -213
- package/test-server/test-filter-instructions.mjs +0 -295
- package/test-server/test-instruction-levels.mjs +0 -102
- package/test-server/test-preflight.md +0 -55
- package/test-server/test-prompts.mjs +0 -185
- package/test-server/test-scheduler.mjs +0 -174
- package/test-server/test-tool-annotations.mjs +0 -115
- package/test-server/test-tools-codemode.md +0 -632
- package/test-server/test-tools-codemode2.md +0 -1218
- package/test-server/test-tools-team.md +0 -215
- package/test-server/test-tools.md +0 -429
- package/test-server/test-tools2.md +0 -361
- package/test-server/test-tools3.md +0 -396
- package/test-server/tool-reference.md +0 -231
- package/tests/README.md +0 -54
- package/tests/auth/auth-context.test.ts +0 -162
- package/tests/auth/authorization-server-discovery.test.ts +0 -265
- package/tests/auth/errors.test.ts +0 -170
- package/tests/auth/middleware.test.ts +0 -585
- package/tests/auth/oauth-resource-server.test.ts +0 -173
- package/tests/auth/scope-map.test.ts +0 -66
- package/tests/auth/scopes.test.ts +0 -347
- package/tests/auth/token-validator.test.ts +0 -271
- package/tests/codemode/api.test.ts +0 -396
- package/tests/codemode/auto-return.test.ts +0 -167
- package/tests/codemode/codemode-tool-handlers.test.ts +0 -197
- package/tests/codemode/sandbox-factory.test.ts +0 -152
- package/tests/codemode/sandbox.test.ts +0 -190
- package/tests/codemode/security.test.ts +0 -242
- package/tests/codemode/worker-sandbox.test.ts +0 -106
- package/tests/constants/icons.test.ts +0 -101
- package/tests/constants/server-instructions.test.ts +0 -514
- package/tests/database/crud-workflow-branches.test.ts +0 -418
- package/tests/database/database-branches.test.ts +0 -132
- package/tests/database/entries-auth-branches.test.ts +0 -390
- package/tests/database/native-connection.test.ts +0 -249
- package/tests/database/shared-helpers.test.ts +0 -103
- package/tests/database/sqlite-adapter.bench.ts +0 -63
- package/tests/database/sqlite-adapter.test.ts +0 -690
- package/tests/database/tags.test.ts +0 -134
- package/tests/e2e/README.md +0 -39
- package/tests/e2e/auth.spec.ts +0 -106
- package/tests/e2e/codemode-abuse.spec.ts +0 -75
- package/tests/e2e/health.spec.ts +0 -63
- package/tests/e2e/helpers.ts +0 -139
- package/tests/e2e/oauth-discovery.spec.ts +0 -102
- package/tests/e2e/oauth-scopes.spec.ts +0 -222
- package/tests/e2e/payloads-admin.spec.ts +0 -76
- package/tests/e2e/payloads-analytics.spec.ts +0 -37
- package/tests/e2e/payloads-backup-restore.spec.ts +0 -102
- package/tests/e2e/payloads-backup.spec.ts +0 -44
- package/tests/e2e/payloads-codemode-api.spec.ts +0 -131
- package/tests/e2e/payloads-codemode-readonly.spec.ts +0 -116
- package/tests/e2e/payloads-codemode.spec.ts +0 -116
- package/tests/e2e/payloads-core.spec.ts +0 -82
- package/tests/e2e/payloads-error-contracts.spec.ts +0 -159
- package/tests/e2e/payloads-export.spec.ts +0 -46
- package/tests/e2e/payloads-github-degradation.spec.ts +0 -73
- package/tests/e2e/payloads-github.spec.ts +0 -176
- package/tests/e2e/payloads-relationships.spec.ts +0 -56
- package/tests/e2e/payloads-search.spec.ts +0 -64
- package/tests/e2e/payloads-team-happy.spec.ts +0 -231
- package/tests/e2e/payloads-team.spec.ts +0 -174
- package/tests/e2e/prompts-expanded.spec.ts +0 -137
- package/tests/e2e/prompts.spec.ts +0 -62
- package/tests/e2e/protocols.spec.ts +0 -134
- package/tests/e2e/rate-limiting.spec.ts +0 -291
- package/tests/e2e/resources-briefing-env.spec.ts +0 -106
- package/tests/e2e/resources-complete.spec.ts +0 -180
- package/tests/e2e/resources-expanded.spec.ts +0 -83
- package/tests/e2e/resources-instructions-levels.spec.ts +0 -145
- package/tests/e2e/resources-templates.spec.ts +0 -123
- package/tests/e2e/resources.spec.ts +0 -103
- package/tests/e2e/scheduler.spec.ts +0 -79
- package/tests/e2e/security.spec.ts +0 -112
- package/tests/e2e/session-advanced.spec.ts +0 -152
- package/tests/e2e/sessions.spec.ts +0 -95
- package/tests/e2e/stateless.spec.ts +0 -79
- package/tests/e2e/streaming.spec.ts +0 -176
- package/tests/e2e/tool-filtering-presets.spec.ts +0 -192
- package/tests/e2e/tool-filtering.spec.ts +0 -77
- package/tests/e2e/tools.spec.ts +0 -111
- package/tests/filtering/tool-filter.test.ts +0 -314
- package/tests/github/client-issues-errors.test.ts +0 -433
- package/tests/github/github-integration-branches.test.ts +0 -490
- package/tests/github/github-integration.test.ts +0 -1015
- package/tests/github/github-managers-branches.test.ts +0 -907
- package/tests/github/pull-requests.test.ts +0 -334
- package/tests/handlers/analytics-branches.test.ts +0 -222
- package/tests/handlers/backup-branches.test.ts +0 -270
- package/tests/handlers/briefing-context-section.test.ts +0 -388
- package/tests/handlers/briefing-github-section.test.ts +0 -392
- package/tests/handlers/briefing-user-message.test.ts +0 -405
- package/tests/handlers/codemode-tools.test.ts +0 -85
- package/tests/handlers/copilot-tools.test.ts +0 -126
- package/tests/handlers/error-path-coverage.test.ts +0 -324
- package/tests/handlers/export-tools.test.ts +0 -203
- package/tests/handlers/github-resource-handlers.test.ts +0 -929
- package/tests/handlers/github-tool-handlers.test.ts +0 -1452
- package/tests/handlers/handler-error-branches.test.ts +0 -346
- package/tests/handlers/help-resource.test.ts +0 -92
- package/tests/handlers/prompt-handler-coverage.test.ts +0 -108
- package/tests/handlers/prompt-handlers.test.ts +0 -131
- package/tests/handlers/resource-handler-coverage.test.ts +0 -281
- package/tests/handlers/resource-handlers.test.ts +0 -357
- package/tests/handlers/resource-prompt-branches.test.ts +0 -495
- package/tests/handlers/search-tool-handlers.test.ts +0 -379
- package/tests/handlers/targeted-gap-closure.test.ts +0 -387
- package/tests/handlers/team-admin.test.ts +0 -291
- package/tests/handlers/team-analytics.test.ts +0 -220
- package/tests/handlers/team-core.test.ts +0 -148
- package/tests/handlers/team-data.test.ts +0 -198
- package/tests/handlers/team-relationships.test.ts +0 -271
- package/tests/handlers/team-resource-handlers.test.ts +0 -161
- package/tests/handlers/team-search.test.ts +0 -134
- package/tests/handlers/team-tool-handlers.test.ts +0 -301
- package/tests/handlers/team-vector.test.ts +0 -213
- package/tests/handlers/template-github-branches.test.ts +0 -676
- package/tests/handlers/tool-annotations.test.ts +0 -90
- package/tests/handlers/tool-handler-coverage.test.ts +0 -514
- package/tests/handlers/tool-handlers.test.ts +0 -510
- package/tests/handlers/tool-output-schemas.test.ts +0 -116
- package/tests/handlers/vector-tool-handlers.test.ts +0 -238
- package/tests/security/sql-injection.test.ts +0 -284
- package/tests/server/mcp-server.bench.ts +0 -55
- package/tests/server/mcp-server.test.ts +0 -1326
- package/tests/server/scheduler.test.ts +0 -400
- package/tests/transports/http-legacy-sse.test.ts +0 -275
- package/tests/transports/http-security.test.ts +0 -322
- package/tests/transports/http-stateful.test.ts +0 -487
- package/tests/transports/http-transport-server.test.ts +0 -301
- package/tests/transports/http-transport.test.ts +0 -771
- package/tests/utils/github-helpers.test.ts +0 -58
- package/tests/utils/logger.test.ts +0 -180
- package/tests/utils/mcp-logger.test.ts +0 -211
- package/tests/utils/progress-utils.test.ts +0 -156
- package/tests/utils/query-helpers.test.ts +0 -80
- package/tests/utils/security-utils.test.ts +0 -82
- package/tests/vector/vector-search-branches.test.ts +0 -111
- package/tests/vector/vector-search-manager.test.ts +0 -375
- package/tests/vector/vector-search.bench.ts +0 -48
- package/tsconfig.json +0 -42
- package/tsup.config.ts +0 -19
- package/vitest.config.ts +0 -25
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Security Utilities Tests - sanitizeErrorForLogging
|
|
3
|
-
*
|
|
4
|
-
* Covers the token scrubbing function not tested by sql-injection.test.ts.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect } from 'vitest'
|
|
8
|
-
import { sanitizeErrorForLogging } from '../../src/utils/security-utils.js'
|
|
9
|
-
|
|
10
|
-
describe('sanitizeErrorForLogging', () => {
|
|
11
|
-
it('should redact GitHub classic PATs (ghp_)', () => {
|
|
12
|
-
const token = 'ghp_' + 'A'.repeat(36)
|
|
13
|
-
const message = `Request failed: token ${token} is invalid`
|
|
14
|
-
const result = sanitizeErrorForLogging(message)
|
|
15
|
-
|
|
16
|
-
expect(result).not.toContain(token)
|
|
17
|
-
expect(result).toContain('[REDACTED]')
|
|
18
|
-
expect(result).toBe('Request failed: token [REDACTED] is invalid')
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('should redact GitHub fine-grained PATs (github_pat_)', () => {
|
|
22
|
-
const token = 'github_pat_' + 'B'.repeat(82)
|
|
23
|
-
const message = `Auth error with ${token}`
|
|
24
|
-
const result = sanitizeErrorForLogging(message)
|
|
25
|
-
|
|
26
|
-
expect(result).not.toContain(token)
|
|
27
|
-
expect(result).toContain('[REDACTED]')
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('should redact Authorization headers with token', () => {
|
|
31
|
-
const message =
|
|
32
|
-
'Failed request with Authorization: token ghp_secret123456789012345678901234567890'
|
|
33
|
-
const result = sanitizeErrorForLogging(message)
|
|
34
|
-
|
|
35
|
-
expect(result).toContain('[REDACTED]')
|
|
36
|
-
expect(result).not.toContain('ghp_secret')
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('should redact Authorization headers with Bearer', () => {
|
|
40
|
-
const message = 'Error: Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.payload.sig'
|
|
41
|
-
const result = sanitizeErrorForLogging(message)
|
|
42
|
-
|
|
43
|
-
expect(result).toContain('[REDACTED]')
|
|
44
|
-
expect(result).not.toContain('eyJhbGciOiJIUzI1NiJ9')
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
it('should redact generic Bearer tokens', () => {
|
|
48
|
-
const message = 'Token expired: Bearer abc123.def456.ghi789+/=='
|
|
49
|
-
const result = sanitizeErrorForLogging(message)
|
|
50
|
-
|
|
51
|
-
expect(result).toContain('[REDACTED]')
|
|
52
|
-
expect(result).not.toContain('abc123.def456')
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('should pass through clean messages unchanged', () => {
|
|
56
|
-
const message = 'Database connection failed at localhost:5432'
|
|
57
|
-
expect(sanitizeErrorForLogging(message)).toBe(message)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it('should pass through empty string', () => {
|
|
61
|
-
expect(sanitizeErrorForLogging('')).toBe('')
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
it('should handle multiple tokens in one message', () => {
|
|
65
|
-
const token1 = 'ghp_' + 'C'.repeat(36)
|
|
66
|
-
const token2 = 'ghp_' + 'D'.repeat(36)
|
|
67
|
-
const message = `Token1: ${token1}, Token2: ${token2}`
|
|
68
|
-
const result = sanitizeErrorForLogging(message)
|
|
69
|
-
|
|
70
|
-
expect(result).not.toContain(token1)
|
|
71
|
-
expect(result).not.toContain(token2)
|
|
72
|
-
expect(result).toBe('Token1: [REDACTED], Token2: [REDACTED]')
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
it('should be idempotent - calling twice yields same result', () => {
|
|
76
|
-
const token = 'ghp_' + 'E'.repeat(36)
|
|
77
|
-
const message = `Error with ${token}`
|
|
78
|
-
const first = sanitizeErrorForLogging(message)
|
|
79
|
-
const second = sanitizeErrorForLogging(first)
|
|
80
|
-
expect(first).toBe(second)
|
|
81
|
-
})
|
|
82
|
-
})
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* memory-journal-mcp — Vector Search Manager Branch Coverage Tests
|
|
3
|
-
*
|
|
4
|
-
* Targets uncovered branches: not-initialized auto-init, no-db guard,
|
|
5
|
-
* embedding error during rebuild, insert error during rebuild,
|
|
6
|
-
* and progress reporting.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
10
|
-
|
|
11
|
-
vi.mock('../../src/utils/logger.js', () => ({
|
|
12
|
-
logger: { info: vi.fn(), warning: vi.fn(), error: vi.fn(), debug: vi.fn() },
|
|
13
|
-
}))
|
|
14
|
-
|
|
15
|
-
vi.mock('../../src/utils/progress-utils.js', () => ({
|
|
16
|
-
sendProgress: vi.fn().mockResolvedValue(undefined),
|
|
17
|
-
}))
|
|
18
|
-
|
|
19
|
-
import { VectorSearchManager } from '../../src/vector/vector-search-manager.js'
|
|
20
|
-
|
|
21
|
-
// ============================================================================
|
|
22
|
-
// Tests
|
|
23
|
-
// ============================================================================
|
|
24
|
-
|
|
25
|
-
describe('VectorSearchManager — branch coverage', () => {
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
vi.clearAllMocks()
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('should return false from addEntry when no db after initialize', async () => {
|
|
31
|
-
const manager = new VectorSearchManager('/nonexistent/path.db')
|
|
32
|
-
|
|
33
|
-
// Force skipping real initialization by marking it as initialized
|
|
34
|
-
// but with no db connection
|
|
35
|
-
Object.assign(manager, { initialized: true, db: null })
|
|
36
|
-
|
|
37
|
-
const result = await manager.addEntry(1, 'test content')
|
|
38
|
-
expect(result).toEqual({ success: false, error: 'Vector database not available' })
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('should return empty results from search when no db after initialize', async () => {
|
|
42
|
-
const manager = new VectorSearchManager('/nonexistent/path.db')
|
|
43
|
-
Object.assign(manager, { initialized: true, db: null })
|
|
44
|
-
|
|
45
|
-
const result = await manager.search('test query')
|
|
46
|
-
expect(result).toEqual([])
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
it('should return 0 from rebuildIndex when no db', async () => {
|
|
50
|
-
const manager = new VectorSearchManager('/nonexistent/path.db')
|
|
51
|
-
Object.assign(manager, { initialized: true, db: null })
|
|
52
|
-
|
|
53
|
-
const mockDbAdapter = {
|
|
54
|
-
getActiveEntryCount: vi.fn().mockReturnValue(0),
|
|
55
|
-
getEntriesPage: vi.fn().mockReturnValue([]),
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const result = await manager.rebuildIndex(mockDbAdapter as never)
|
|
59
|
-
expect(result).toEqual({ indexed: 0, failed: 0, firstError: null })
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
it('should return stats with zero values when no db', async () => {
|
|
63
|
-
const manager = new VectorSearchManager('/nonexistent/path.db')
|
|
64
|
-
Object.assign(manager, { initialized: true, db: null })
|
|
65
|
-
|
|
66
|
-
const result = manager.getStats()
|
|
67
|
-
expect(result.itemCount).toBe(0)
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
it('should auto-initialize when calling addEntry on uninitialized manager', async () => {
|
|
71
|
-
const manager = new VectorSearchManager('/nonexistent/path.db')
|
|
72
|
-
|
|
73
|
-
// Mock initialize to just set initialized flag without connecting
|
|
74
|
-
const initSpy = vi.spyOn(manager, 'initialize').mockImplementation(async () => {
|
|
75
|
-
Object.assign(manager, { initialized: true, db: null })
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
const result = await manager.addEntry(1, 'test')
|
|
79
|
-
expect(initSpy).toHaveBeenCalled()
|
|
80
|
-
expect(result).toEqual({ success: false, error: 'Vector database not available' }) // no db, so returns structured error
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it('should auto-initialize when calling search on uninitialized manager', async () => {
|
|
84
|
-
const manager = new VectorSearchManager('/nonexistent/path.db')
|
|
85
|
-
|
|
86
|
-
const initSpy = vi.spyOn(manager, 'initialize').mockImplementation(async () => {
|
|
87
|
-
Object.assign(manager, { initialized: true, db: null })
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
const result = await manager.search('query')
|
|
91
|
-
expect(initSpy).toHaveBeenCalled()
|
|
92
|
-
expect(result).toEqual([])
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
it('should auto-initialize when calling rebuildIndex on uninitialized manager', async () => {
|
|
96
|
-
const manager = new VectorSearchManager('/nonexistent/path.db')
|
|
97
|
-
|
|
98
|
-
const initSpy = vi.spyOn(manager, 'initialize').mockImplementation(async () => {
|
|
99
|
-
Object.assign(manager, { initialized: true, db: null })
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
const mockDbAdapter = {
|
|
103
|
-
getActiveEntryCount: vi.fn().mockReturnValue(0),
|
|
104
|
-
getEntriesPage: vi.fn().mockReturnValue([]),
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const result = await manager.rebuildIndex(mockDbAdapter as never)
|
|
108
|
-
expect(initSpy).toHaveBeenCalled()
|
|
109
|
-
expect(result).toEqual({ indexed: 0, failed: 0, firstError: null })
|
|
110
|
-
})
|
|
111
|
-
})
|
|
@@ -1,375 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* VectorSearchManager Tests
|
|
3
|
-
*
|
|
4
|
-
* Tests VectorSearchManager with mocked @huggingface/transformers pipeline
|
|
5
|
-
* and mocked better-sqlite3 database. No real model loading or extension I/O needed.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
9
|
-
|
|
10
|
-
// ============================================================================
|
|
11
|
-
// Hoisted mock functions (must be declared before vi.mock)
|
|
12
|
-
// ============================================================================
|
|
13
|
-
|
|
14
|
-
const { mockEmbedderFn, mockPrepare, mockRun, mockAll, mockGet } = vi.hoisted(() => ({
|
|
15
|
-
mockEmbedderFn: vi.fn(),
|
|
16
|
-
mockPrepare: vi.fn(),
|
|
17
|
-
mockRun: vi.fn(),
|
|
18
|
-
mockAll: vi.fn(),
|
|
19
|
-
mockGet: vi.fn(),
|
|
20
|
-
}))
|
|
21
|
-
|
|
22
|
-
// ============================================================================
|
|
23
|
-
// Module mocks
|
|
24
|
-
// ============================================================================
|
|
25
|
-
|
|
26
|
-
vi.mock('@huggingface/transformers', () => ({
|
|
27
|
-
pipeline: vi.fn().mockResolvedValue(mockEmbedderFn),
|
|
28
|
-
}))
|
|
29
|
-
|
|
30
|
-
// Import AFTER mocks are set up
|
|
31
|
-
import { VectorSearchManager } from '../../src/vector/vector-search-manager.js'
|
|
32
|
-
import type { IDatabaseAdapter } from '../../src/database/core/interfaces.js'
|
|
33
|
-
import type { DatabaseAdapter } from '../../src/database/sqlite-adapter/index.js'
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Creates a mock IDatabaseAdapter whose getRawDb() returns a mock better-sqlite3 Database.
|
|
37
|
-
*/
|
|
38
|
-
function createMockDbAdapter() {
|
|
39
|
-
// Mock the prepare().run() / prepare().all() / prepare().get() chain
|
|
40
|
-
mockPrepare.mockReturnValue({
|
|
41
|
-
run: mockRun,
|
|
42
|
-
all: mockAll,
|
|
43
|
-
get: mockGet,
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
const mockDb = {
|
|
47
|
-
prepare: mockPrepare,
|
|
48
|
-
exec: vi.fn(),
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const adapter = {
|
|
52
|
-
getRawDb: vi.fn().mockReturnValue(mockDb),
|
|
53
|
-
getActiveEntryCount: vi.fn().mockReturnValue(0),
|
|
54
|
-
getEntriesPage: vi.fn().mockReturnValue([]),
|
|
55
|
-
} as unknown as IDatabaseAdapter
|
|
56
|
-
|
|
57
|
-
return { adapter, mockDb }
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Helper to make the VectorSearchManager think it's initialized
|
|
62
|
-
*/
|
|
63
|
-
async function initManager(vm: VectorSearchManager): Promise<void> {
|
|
64
|
-
mockEmbedderFn.mockResolvedValue({ data: new Float32Array(384) })
|
|
65
|
-
await vm.initialize()
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** Generate a fake embedding vector of length 384 */
|
|
69
|
-
function fakeEmbedding(seed = 0): Float32Array {
|
|
70
|
-
const arr = new Float32Array(384)
|
|
71
|
-
for (let i = 0; i < 384; i++) arr[i] = Math.sin(i + seed) * 0.1
|
|
72
|
-
return arr
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
describe('VectorSearchManager', () => {
|
|
76
|
-
let vm: VectorSearchManager
|
|
77
|
-
let adapter: IDatabaseAdapter
|
|
78
|
-
|
|
79
|
-
beforeEach(() => {
|
|
80
|
-
vi.clearAllMocks()
|
|
81
|
-
const mocks = createMockDbAdapter()
|
|
82
|
-
adapter = mocks.adapter
|
|
83
|
-
vm = new VectorSearchManager(adapter)
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
// ========================================================================
|
|
87
|
-
// Initialization
|
|
88
|
-
// ========================================================================
|
|
89
|
-
|
|
90
|
-
describe('isInitialized', () => {
|
|
91
|
-
it('should return false before initialize()', () => {
|
|
92
|
-
expect(vm.isInitialized()).toBe(false)
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
it('should return true after initialize()', async () => {
|
|
96
|
-
await initManager(vm)
|
|
97
|
-
expect(vm.isInitialized()).toBe(true)
|
|
98
|
-
})
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
describe('initialize', () => {
|
|
102
|
-
it('should load pipeline and get raw database', async () => {
|
|
103
|
-
mockEmbedderFn.mockResolvedValue({ data: new Float32Array(384) })
|
|
104
|
-
await vm.initialize()
|
|
105
|
-
|
|
106
|
-
expect(adapter.getRawDb).toHaveBeenCalled()
|
|
107
|
-
expect(vm.isInitialized()).toBe(true)
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
it('should be idempotent', async () => {
|
|
111
|
-
await initManager(vm)
|
|
112
|
-
await vm.initialize()
|
|
113
|
-
expect(vm.isInitialized()).toBe(true)
|
|
114
|
-
})
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
// ========================================================================
|
|
118
|
-
// Generate Embedding
|
|
119
|
-
// ========================================================================
|
|
120
|
-
|
|
121
|
-
describe('generateEmbedding', () => {
|
|
122
|
-
it('should generate embedding array from text', async () => {
|
|
123
|
-
await initManager(vm)
|
|
124
|
-
mockEmbedderFn.mockResolvedValue({ data: fakeEmbedding(42) })
|
|
125
|
-
|
|
126
|
-
const embedding = await vm.generateEmbedding('test text')
|
|
127
|
-
expect(embedding).toHaveLength(384)
|
|
128
|
-
expect(typeof embedding[0]).toBe('number')
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
it('should throw if not initialized', async () => {
|
|
132
|
-
await expect(vm.generateEmbedding('test')).rejects.toThrow('not initialized')
|
|
133
|
-
})
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
// ========================================================================
|
|
137
|
-
// Add Entry
|
|
138
|
-
// ========================================================================
|
|
139
|
-
|
|
140
|
-
describe('addEntry', () => {
|
|
141
|
-
it('should insert entry via SQL prepared statement', async () => {
|
|
142
|
-
await initManager(vm)
|
|
143
|
-
mockEmbedderFn.mockResolvedValue({ data: fakeEmbedding(1) })
|
|
144
|
-
mockRun.mockReturnValue(undefined)
|
|
145
|
-
|
|
146
|
-
const result = await vm.addEntry(42, 'Some content')
|
|
147
|
-
expect(result.success).toBe(true)
|
|
148
|
-
|
|
149
|
-
// Should prepare DELETE then INSERT statements
|
|
150
|
-
expect(mockPrepare).toHaveBeenCalledWith(
|
|
151
|
-
'DELETE FROM vec_embeddings WHERE entry_id = ?'
|
|
152
|
-
)
|
|
153
|
-
expect(mockPrepare).toHaveBeenCalledWith(
|
|
154
|
-
'INSERT INTO vec_embeddings(entry_id, embedding) VALUES (?, ?)'
|
|
155
|
-
)
|
|
156
|
-
// Should call run with BigInt entryId for DELETE, and BigInt + Float32Array for INSERT
|
|
157
|
-
expect(mockRun).toHaveBeenCalledWith(BigInt(42))
|
|
158
|
-
expect(mockRun).toHaveBeenCalledWith(BigInt(42), expect.any(Float32Array))
|
|
159
|
-
})
|
|
160
|
-
|
|
161
|
-
it('should return false on error', async () => {
|
|
162
|
-
await initManager(vm)
|
|
163
|
-
mockEmbedderFn.mockRejectedValue(new Error('Embedding failed'))
|
|
164
|
-
|
|
165
|
-
const result = await vm.addEntry(99, 'Content')
|
|
166
|
-
expect(result.success).toBe(false)
|
|
167
|
-
expect(result.error).toBeDefined()
|
|
168
|
-
})
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
// ========================================================================
|
|
172
|
-
// Search
|
|
173
|
-
// ========================================================================
|
|
174
|
-
|
|
175
|
-
describe('search', () => {
|
|
176
|
-
it('should return filtered results above threshold', async () => {
|
|
177
|
-
await initManager(vm)
|
|
178
|
-
mockEmbedderFn.mockResolvedValue({ data: fakeEmbedding(0) })
|
|
179
|
-
|
|
180
|
-
// sqlite-vec returns distance (lower = more similar)
|
|
181
|
-
// score = 1 / (1 + distance)
|
|
182
|
-
// distance=0.1 -> score≈0.91, distance=1.0 -> score=0.5, distance=9.0 -> score=0.1
|
|
183
|
-
mockAll.mockReturnValue([
|
|
184
|
-
{ entry_id: 1, distance: 0.1 },
|
|
185
|
-
{ entry_id: 2, distance: 1.0 },
|
|
186
|
-
{ entry_id: 3, distance: 9.0 },
|
|
187
|
-
])
|
|
188
|
-
|
|
189
|
-
const results = await vm.search('query text', 10, 0.3)
|
|
190
|
-
expect(results).toHaveLength(2)
|
|
191
|
-
expect(results[0]!.entryId).toBe(1)
|
|
192
|
-
expect(results[0]!.score).toBeCloseTo(1 / 1.1, 2)
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
it('should limit results to limit param', async () => {
|
|
196
|
-
await initManager(vm)
|
|
197
|
-
mockEmbedderFn.mockResolvedValue({ data: fakeEmbedding(0) })
|
|
198
|
-
mockAll.mockReturnValue([
|
|
199
|
-
{ entry_id: 1, distance: 0.1 },
|
|
200
|
-
{ entry_id: 2, distance: 0.2 },
|
|
201
|
-
{ entry_id: 3, distance: 0.3 },
|
|
202
|
-
])
|
|
203
|
-
|
|
204
|
-
const results = await vm.search('query', 2, 0.3)
|
|
205
|
-
expect(results).toHaveLength(2)
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
it('should return empty on error', async () => {
|
|
209
|
-
await initManager(vm)
|
|
210
|
-
mockEmbedderFn.mockRejectedValue(new Error('Embed fail'))
|
|
211
|
-
|
|
212
|
-
const results = await vm.search('query')
|
|
213
|
-
expect(results).toEqual([])
|
|
214
|
-
})
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
// ========================================================================
|
|
218
|
-
// Remove Entry
|
|
219
|
-
// ========================================================================
|
|
220
|
-
|
|
221
|
-
describe('removeEntry', () => {
|
|
222
|
-
it('should delete entry via SQL', async () => {
|
|
223
|
-
await initManager(vm)
|
|
224
|
-
mockRun.mockReturnValue(undefined)
|
|
225
|
-
|
|
226
|
-
const result = await vm.removeEntry(42)
|
|
227
|
-
expect(result).toBe(true)
|
|
228
|
-
expect(mockPrepare).toHaveBeenCalledWith(
|
|
229
|
-
'DELETE FROM vec_embeddings WHERE entry_id = ?'
|
|
230
|
-
)
|
|
231
|
-
expect(mockRun).toHaveBeenCalledWith(BigInt(42))
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
it('should return false if db not available', async () => {
|
|
235
|
-
const result = await vm.removeEntry(42)
|
|
236
|
-
expect(result).toBe(false)
|
|
237
|
-
})
|
|
238
|
-
|
|
239
|
-
it('should return false on delete error', async () => {
|
|
240
|
-
await initManager(vm)
|
|
241
|
-
mockRun.mockImplementation(() => {
|
|
242
|
-
throw new Error('SQL error')
|
|
243
|
-
})
|
|
244
|
-
|
|
245
|
-
const result = await vm.removeEntry(999)
|
|
246
|
-
expect(result).toBe(false)
|
|
247
|
-
})
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
// ========================================================================
|
|
251
|
-
// Get Stats
|
|
252
|
-
// ========================================================================
|
|
253
|
-
|
|
254
|
-
describe('getStats', () => {
|
|
255
|
-
it('should return count from SQL', async () => {
|
|
256
|
-
await initManager(vm)
|
|
257
|
-
mockGet.mockReturnValue({ count: 100 })
|
|
258
|
-
|
|
259
|
-
const stats = await vm.getStats()
|
|
260
|
-
expect(stats.itemCount).toBe(100)
|
|
261
|
-
expect(stats.modelName).toBe('Xenova/all-MiniLM-L6-v2')
|
|
262
|
-
expect(stats.dimensions).toBe(384)
|
|
263
|
-
})
|
|
264
|
-
|
|
265
|
-
it('should return zero count when no db', async () => {
|
|
266
|
-
const stats = await vm.getStats()
|
|
267
|
-
expect(stats.itemCount).toBe(0)
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
it('should return zero count on error', async () => {
|
|
271
|
-
await initManager(vm)
|
|
272
|
-
mockGet.mockImplementation(() => {
|
|
273
|
-
throw new Error('SQL error')
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
const stats = await vm.getStats()
|
|
277
|
-
expect(stats.itemCount).toBe(0)
|
|
278
|
-
})
|
|
279
|
-
})
|
|
280
|
-
|
|
281
|
-
// ========================================================================
|
|
282
|
-
// Rebuild Index
|
|
283
|
-
// ========================================================================
|
|
284
|
-
|
|
285
|
-
describe('rebuildIndex', () => {
|
|
286
|
-
it('should rebuild from database entries', async () => {
|
|
287
|
-
await initManager(vm)
|
|
288
|
-
mockEmbedderFn.mockResolvedValue({ data: fakeEmbedding(0) })
|
|
289
|
-
mockRun.mockReturnValue(undefined)
|
|
290
|
-
|
|
291
|
-
const mockDb = {
|
|
292
|
-
getActiveEntryCount: vi.fn().mockReturnValue(2),
|
|
293
|
-
getEntriesPage: vi.fn().mockReturnValue([
|
|
294
|
-
{ id: 1, content: 'Entry one' },
|
|
295
|
-
{ id: 2, content: 'Entry two' },
|
|
296
|
-
]),
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const result = await vm.rebuildIndex(mockDb as unknown as DatabaseAdapter)
|
|
300
|
-
expect(result.indexed).toBe(2)
|
|
301
|
-
expect(result.failed).toBe(0)
|
|
302
|
-
expect(result.firstError).toBeNull()
|
|
303
|
-
// DELETE to clear + 2 INSERTs
|
|
304
|
-
expect(mockRun).toHaveBeenCalledTimes(3)
|
|
305
|
-
})
|
|
306
|
-
|
|
307
|
-
it('should clear existing embeddings before rebuild', async () => {
|
|
308
|
-
await initManager(vm)
|
|
309
|
-
mockEmbedderFn.mockResolvedValue({ data: fakeEmbedding(0) })
|
|
310
|
-
mockRun.mockReturnValue(undefined)
|
|
311
|
-
|
|
312
|
-
const mockDb = {
|
|
313
|
-
getActiveEntryCount: vi.fn().mockReturnValue(1),
|
|
314
|
-
getEntriesPage: vi.fn().mockReturnValue([{ id: 1, content: 'Active entry' }]),
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
const result = await vm.rebuildIndex(mockDb as unknown as DatabaseAdapter)
|
|
318
|
-
expect(result.indexed).toBe(1)
|
|
319
|
-
|
|
320
|
-
// First call should be DELETE FROM vec_embeddings
|
|
321
|
-
expect(mockPrepare).toHaveBeenCalledWith('DELETE FROM vec_embeddings')
|
|
322
|
-
})
|
|
323
|
-
|
|
324
|
-
it('should return 0 when db not available', async () => {
|
|
325
|
-
const mockDb = {
|
|
326
|
-
getActiveEntryCount: vi.fn().mockReturnValue(0),
|
|
327
|
-
getEntriesPage: vi.fn().mockReturnValue([]),
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
const result = await vm.rebuildIndex(mockDb as unknown as DatabaseAdapter)
|
|
331
|
-
expect(result.indexed).toBe(0)
|
|
332
|
-
expect(result.failed).toBe(0)
|
|
333
|
-
})
|
|
334
|
-
|
|
335
|
-
it('should skip entries with embedding failures', async () => {
|
|
336
|
-
await initManager(vm)
|
|
337
|
-
// First call succeeds, second fails
|
|
338
|
-
mockEmbedderFn
|
|
339
|
-
.mockResolvedValueOnce({ data: fakeEmbedding(1) })
|
|
340
|
-
.mockRejectedValueOnce(new Error('Embedding failed'))
|
|
341
|
-
mockRun.mockReturnValue(undefined)
|
|
342
|
-
|
|
343
|
-
const mockDb = {
|
|
344
|
-
getActiveEntryCount: vi.fn().mockReturnValue(2),
|
|
345
|
-
getEntriesPage: vi.fn().mockReturnValue([
|
|
346
|
-
{ id: 1, content: 'Good entry' },
|
|
347
|
-
{ id: 2, content: 'Will fail embedding' },
|
|
348
|
-
]),
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
const result = await vm.rebuildIndex(mockDb as unknown as DatabaseAdapter)
|
|
352
|
-
// Only 1 should be indexed (the other failed)
|
|
353
|
-
expect(result.indexed).toBe(1)
|
|
354
|
-
expect(result.failed).toBe(1)
|
|
355
|
-
expect(result.firstError).toBe('Embedding failed')
|
|
356
|
-
})
|
|
357
|
-
})
|
|
358
|
-
|
|
359
|
-
// ========================================================================
|
|
360
|
-
// Initialize Error
|
|
361
|
-
// ========================================================================
|
|
362
|
-
|
|
363
|
-
describe('initialize error', () => {
|
|
364
|
-
it('should rethrow pipeline errors', async () => {
|
|
365
|
-
const { pipeline: pipelineMock } = await import('@huggingface/transformers')
|
|
366
|
-
;(pipelineMock as ReturnType<typeof vi.fn>).mockRejectedValueOnce(
|
|
367
|
-
new Error('Model not found')
|
|
368
|
-
)
|
|
369
|
-
|
|
370
|
-
const vm2 = new VectorSearchManager(adapter)
|
|
371
|
-
await expect(vm2.initialize()).rejects.toThrow('Model not found')
|
|
372
|
-
expect(vm2.isInitialized()).toBe(false)
|
|
373
|
-
})
|
|
374
|
-
})
|
|
375
|
-
})
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { bench, beforeAll, afterAll } from 'vitest'
|
|
2
|
-
import { VectorSearchManager } from '../../src/vector/vector-search-manager.js'
|
|
3
|
-
import { DatabaseAdapter } from '../../src/database/sqlite-adapter/index.js'
|
|
4
|
-
import * as fs from 'node:fs'
|
|
5
|
-
|
|
6
|
-
let vm: VectorSearchManager
|
|
7
|
-
let db: DatabaseAdapter
|
|
8
|
-
const testDbPath = './benchmark-vector.db'
|
|
9
|
-
|
|
10
|
-
beforeAll(async () => {
|
|
11
|
-
db = new DatabaseAdapter(testDbPath)
|
|
12
|
-
await db.initialize()
|
|
13
|
-
|
|
14
|
-
vm = new VectorSearchManager(db)
|
|
15
|
-
|
|
16
|
-
// Mock the embedding generation to skip transformer inference delay
|
|
17
|
-
vm.generateEmbedding = async () => Array.from(new Float32Array(384).fill(Math.random()))
|
|
18
|
-
|
|
19
|
-
await vm.initialize()
|
|
20
|
-
|
|
21
|
-
// Setup some data
|
|
22
|
-
for (let i = 0; i < 100; i++) {
|
|
23
|
-
const entry = db.createEntry({
|
|
24
|
-
content: `Vector benchmark entry ${i} content`,
|
|
25
|
-
})
|
|
26
|
-
await vm.addEntry(entry.id, entry.content)
|
|
27
|
-
}
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
afterAll(() => {
|
|
31
|
-
db.close()
|
|
32
|
-
try {
|
|
33
|
-
if (fs.existsSync(testDbPath)) {
|
|
34
|
-
fs.unlinkSync(testDbPath)
|
|
35
|
-
}
|
|
36
|
-
} catch {
|
|
37
|
-
// ignore
|
|
38
|
-
}
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
bench('addEntry', async () => {
|
|
42
|
-
const id = Math.floor(Math.random() * 1000000)
|
|
43
|
-
await vm.addEntry(id, `New content for adding id ${id}`)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
bench('search', async () => {
|
|
47
|
-
await vm.search('Vector benchmark entry 42', 10, 0.1)
|
|
48
|
-
})
|
package/tsconfig.json
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "NodeNext",
|
|
5
|
-
"moduleResolution": "NodeNext",
|
|
6
|
-
"lib": ["ES2022"],
|
|
7
|
-
"outDir": "./dist",
|
|
8
|
-
"rootDir": "./src",
|
|
9
|
-
"skipLibCheck": true,
|
|
10
|
-
/* Strict Type-Checking Options */
|
|
11
|
-
"strict": true,
|
|
12
|
-
"noImplicitAny": true,
|
|
13
|
-
"strictNullChecks": true,
|
|
14
|
-
"strictFunctionTypes": true,
|
|
15
|
-
"strictBindCallApply": true,
|
|
16
|
-
"strictPropertyInitialization": true,
|
|
17
|
-
"noImplicitThis": true,
|
|
18
|
-
"useUnknownInCatchVariables": true,
|
|
19
|
-
"alwaysStrict": true,
|
|
20
|
-
"exactOptionalPropertyTypes": false,
|
|
21
|
-
/* Additional Checks */
|
|
22
|
-
"noUnusedLocals": true,
|
|
23
|
-
"noUnusedParameters": true,
|
|
24
|
-
"noImplicitReturns": true,
|
|
25
|
-
"noFallthroughCasesInSwitch": true,
|
|
26
|
-
"noUncheckedIndexedAccess": true,
|
|
27
|
-
"noImplicitOverride": true,
|
|
28
|
-
"noPropertyAccessFromIndexSignature": true,
|
|
29
|
-
"allowUnusedLabels": false,
|
|
30
|
-
"allowUnreachableCode": false,
|
|
31
|
-
"noUncheckedSideEffectImports": true,
|
|
32
|
-
/* Module Resolution */
|
|
33
|
-
"forceConsistentCasingInFileNames": true,
|
|
34
|
-
"resolveJsonModule": true,
|
|
35
|
-
"esModuleInterop": true,
|
|
36
|
-
"declaration": true,
|
|
37
|
-
"declarationMap": true,
|
|
38
|
-
"sourceMap": false
|
|
39
|
-
},
|
|
40
|
-
"include": ["src/**/*"],
|
|
41
|
-
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
|
42
|
-
}
|
package/tsup.config.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'tsup'
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
entry: {
|
|
5
|
-
index: 'src/index.ts',
|
|
6
|
-
cli: 'src/cli.ts',
|
|
7
|
-
'worker-script': 'src/codemode/worker-script.ts',
|
|
8
|
-
},
|
|
9
|
-
format: ['esm'],
|
|
10
|
-
dts: true,
|
|
11
|
-
clean: true,
|
|
12
|
-
treeshake: true,
|
|
13
|
-
splitting: true,
|
|
14
|
-
sourcemap: false,
|
|
15
|
-
minify: false,
|
|
16
|
-
outDir: 'dist',
|
|
17
|
-
target: 'es2022',
|
|
18
|
-
external: ['better-sqlite3', 'sqlite-vec', '@huggingface/transformers'],
|
|
19
|
-
})
|