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,400 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for Scheduler module
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
6
|
-
import { Scheduler, type SchedulerOptions } from '../../src/server/scheduler.js'
|
|
7
|
-
|
|
8
|
-
// Mock logger
|
|
9
|
-
vi.mock('../../src/utils/logger.js', () => ({
|
|
10
|
-
logger: {
|
|
11
|
-
info: vi.fn(),
|
|
12
|
-
warning: vi.fn(),
|
|
13
|
-
error: vi.fn(),
|
|
14
|
-
debug: vi.fn(),
|
|
15
|
-
},
|
|
16
|
-
}))
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Creates a mock DatabaseAdapter with the methods used by Scheduler.
|
|
20
|
-
*/
|
|
21
|
-
function createMockDb() {
|
|
22
|
-
return {
|
|
23
|
-
exportToFile: vi.fn().mockReturnValue({
|
|
24
|
-
filename: 'backup_2026-03-01.db',
|
|
25
|
-
path: '/data/backups/backup_2026-03-01.db',
|
|
26
|
-
sizeBytes: 4096,
|
|
27
|
-
}),
|
|
28
|
-
deleteOldBackups: vi.fn().mockReturnValue({
|
|
29
|
-
deleted: ['old_backup.db'],
|
|
30
|
-
kept: 5,
|
|
31
|
-
}),
|
|
32
|
-
getRawDb: vi.fn().mockReturnValue({
|
|
33
|
-
run: vi.fn(),
|
|
34
|
-
}),
|
|
35
|
-
pragma: vi.fn(),
|
|
36
|
-
flushSave: vi.fn(),
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Creates a mock VectorSearchManager with rebuildIndex.
|
|
42
|
-
*/
|
|
43
|
-
function createMockVectorManager() {
|
|
44
|
-
return {
|
|
45
|
-
rebuildIndex: vi.fn().mockResolvedValue(42),
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function defaultOptions(overrides: Partial<SchedulerOptions> = {}): SchedulerOptions {
|
|
50
|
-
return {
|
|
51
|
-
backupIntervalMinutes: 0,
|
|
52
|
-
keepBackups: 5,
|
|
53
|
-
vacuumIntervalMinutes: 0,
|
|
54
|
-
rebuildIndexIntervalMinutes: 0,
|
|
55
|
-
...overrides,
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
describe('Scheduler', () => {
|
|
60
|
-
beforeEach(() => {
|
|
61
|
-
vi.useFakeTimers()
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
afterEach(() => {
|
|
65
|
-
vi.useRealTimers()
|
|
66
|
-
vi.restoreAllMocks()
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
// ========================================================================
|
|
70
|
-
// Construction & start/stop
|
|
71
|
-
// ========================================================================
|
|
72
|
-
|
|
73
|
-
describe('start and stop', () => {
|
|
74
|
-
it('should start with no jobs when all intervals are 0', () => {
|
|
75
|
-
const db = createMockDb()
|
|
76
|
-
const scheduler = new Scheduler(defaultOptions(), db as never)
|
|
77
|
-
scheduler.start()
|
|
78
|
-
|
|
79
|
-
const status = scheduler.getStatus()
|
|
80
|
-
expect(status.active).toBe(true)
|
|
81
|
-
expect(status.jobs).toHaveLength(0)
|
|
82
|
-
|
|
83
|
-
scheduler.stop()
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
it('should create timers for enabled jobs', () => {
|
|
87
|
-
const db = createMockDb()
|
|
88
|
-
const vectorManager = createMockVectorManager()
|
|
89
|
-
const scheduler = new Scheduler(
|
|
90
|
-
defaultOptions({
|
|
91
|
-
backupIntervalMinutes: 60,
|
|
92
|
-
vacuumIntervalMinutes: 120,
|
|
93
|
-
rebuildIndexIntervalMinutes: 180,
|
|
94
|
-
}),
|
|
95
|
-
db as never,
|
|
96
|
-
vectorManager as never
|
|
97
|
-
)
|
|
98
|
-
scheduler.start()
|
|
99
|
-
|
|
100
|
-
const status = scheduler.getStatus()
|
|
101
|
-
expect(status.active).toBe(true)
|
|
102
|
-
expect(status.jobs).toHaveLength(3)
|
|
103
|
-
expect(status.jobs.map((j) => j.name)).toEqual(['backup', 'vacuum', 'rebuild-index'])
|
|
104
|
-
|
|
105
|
-
scheduler.stop()
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
it('should ignore duplicate start calls', () => {
|
|
109
|
-
const db = createMockDb()
|
|
110
|
-
const scheduler = new Scheduler(
|
|
111
|
-
defaultOptions({ backupIntervalMinutes: 60 }),
|
|
112
|
-
db as never
|
|
113
|
-
)
|
|
114
|
-
scheduler.start()
|
|
115
|
-
scheduler.start() // duplicate — should be ignored
|
|
116
|
-
|
|
117
|
-
const status = scheduler.getStatus()
|
|
118
|
-
expect(status.jobs).toHaveLength(1) // still just 1
|
|
119
|
-
|
|
120
|
-
scheduler.stop()
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
it('should clear all timers on stop', () => {
|
|
124
|
-
const db = createMockDb()
|
|
125
|
-
const scheduler = new Scheduler(
|
|
126
|
-
defaultOptions({ backupIntervalMinutes: 30, vacuumIntervalMinutes: 60 }),
|
|
127
|
-
db as never
|
|
128
|
-
)
|
|
129
|
-
scheduler.start()
|
|
130
|
-
expect(scheduler.getStatus().jobs).toHaveLength(2)
|
|
131
|
-
|
|
132
|
-
scheduler.stop()
|
|
133
|
-
expect(scheduler.getStatus().active).toBe(false)
|
|
134
|
-
expect(scheduler.getStatus().jobs).toHaveLength(0)
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
it('should be safe to stop multiple times', () => {
|
|
138
|
-
const db = createMockDb()
|
|
139
|
-
const scheduler = new Scheduler(
|
|
140
|
-
defaultOptions({ backupIntervalMinutes: 30 }),
|
|
141
|
-
db as never
|
|
142
|
-
)
|
|
143
|
-
scheduler.start()
|
|
144
|
-
scheduler.stop()
|
|
145
|
-
scheduler.stop() // should not throw
|
|
146
|
-
|
|
147
|
-
expect(scheduler.getStatus().active).toBe(false)
|
|
148
|
-
})
|
|
149
|
-
|
|
150
|
-
it('should skip rebuild-index when vectorManager is not provided', () => {
|
|
151
|
-
const db = createMockDb()
|
|
152
|
-
const scheduler = new Scheduler(
|
|
153
|
-
defaultOptions({ rebuildIndexIntervalMinutes: 60 }),
|
|
154
|
-
db as never
|
|
155
|
-
// no vectorManager
|
|
156
|
-
)
|
|
157
|
-
scheduler.start()
|
|
158
|
-
|
|
159
|
-
const status = scheduler.getStatus()
|
|
160
|
-
expect(status.jobs).toHaveLength(0) // skipped
|
|
161
|
-
|
|
162
|
-
scheduler.stop()
|
|
163
|
-
})
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
// ========================================================================
|
|
167
|
-
// Job execution
|
|
168
|
-
// ========================================================================
|
|
169
|
-
|
|
170
|
-
describe('backup job', () => {
|
|
171
|
-
it('should call exportToFile and deleteOldBackups on interval', async () => {
|
|
172
|
-
const db = createMockDb()
|
|
173
|
-
const scheduler = new Scheduler(
|
|
174
|
-
defaultOptions({ backupIntervalMinutes: 1, keepBackups: 3 }),
|
|
175
|
-
db as never
|
|
176
|
-
)
|
|
177
|
-
scheduler.start()
|
|
178
|
-
|
|
179
|
-
// Advance by 1 minute
|
|
180
|
-
await vi.advanceTimersByTimeAsync(60_000)
|
|
181
|
-
|
|
182
|
-
expect(db.exportToFile).toHaveBeenCalledOnce()
|
|
183
|
-
expect(db.deleteOldBackups).toHaveBeenCalledWith(3)
|
|
184
|
-
|
|
185
|
-
// Advance another minute
|
|
186
|
-
await vi.advanceTimersByTimeAsync(60_000)
|
|
187
|
-
|
|
188
|
-
expect(db.exportToFile).toHaveBeenCalledTimes(2)
|
|
189
|
-
expect(db.deleteOldBackups).toHaveBeenCalledTimes(2)
|
|
190
|
-
|
|
191
|
-
scheduler.stop()
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
it('should track job status after successful run', async () => {
|
|
195
|
-
const db = createMockDb()
|
|
196
|
-
const scheduler = new Scheduler(
|
|
197
|
-
defaultOptions({ backupIntervalMinutes: 1 }),
|
|
198
|
-
db as never
|
|
199
|
-
)
|
|
200
|
-
scheduler.start()
|
|
201
|
-
|
|
202
|
-
await vi.advanceTimersByTimeAsync(60_000)
|
|
203
|
-
|
|
204
|
-
const status = scheduler.getStatus()
|
|
205
|
-
const backupJob = status.jobs.find((j) => j.name === 'backup')
|
|
206
|
-
expect(backupJob).toBeDefined()
|
|
207
|
-
expect(backupJob!.lastResult).toBe('success')
|
|
208
|
-
expect(backupJob!.lastError).toBeNull()
|
|
209
|
-
expect(backupJob!.runCount).toBe(1)
|
|
210
|
-
expect(backupJob!.lastRun).toBeTruthy()
|
|
211
|
-
|
|
212
|
-
scheduler.stop()
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
it('should track error status when backup fails', async () => {
|
|
216
|
-
const db = createMockDb()
|
|
217
|
-
db.exportToFile.mockImplementation(() => {
|
|
218
|
-
throw new Error('Disk full')
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
const scheduler = new Scheduler(
|
|
222
|
-
defaultOptions({ backupIntervalMinutes: 1 }),
|
|
223
|
-
db as never
|
|
224
|
-
)
|
|
225
|
-
scheduler.start()
|
|
226
|
-
|
|
227
|
-
await vi.advanceTimersByTimeAsync(60_000)
|
|
228
|
-
|
|
229
|
-
const status = scheduler.getStatus()
|
|
230
|
-
const backupJob = status.jobs.find((j) => j.name === 'backup')
|
|
231
|
-
expect(backupJob!.lastResult).toBe('error')
|
|
232
|
-
expect(backupJob!.lastError).toBe('Disk full')
|
|
233
|
-
expect(backupJob!.runCount).toBe(1)
|
|
234
|
-
|
|
235
|
-
scheduler.stop()
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
it('should continue running after a failure', async () => {
|
|
239
|
-
const db = createMockDb()
|
|
240
|
-
db.exportToFile
|
|
241
|
-
.mockImplementationOnce(() => {
|
|
242
|
-
throw new Error('Disk full')
|
|
243
|
-
})
|
|
244
|
-
.mockReturnValue({
|
|
245
|
-
filename: 'backup.db',
|
|
246
|
-
path: '/data/backups/backup.db',
|
|
247
|
-
sizeBytes: 4096,
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
const scheduler = new Scheduler(
|
|
251
|
-
defaultOptions({ backupIntervalMinutes: 1 }),
|
|
252
|
-
db as never
|
|
253
|
-
)
|
|
254
|
-
scheduler.start()
|
|
255
|
-
|
|
256
|
-
// First run — fails
|
|
257
|
-
await vi.advanceTimersByTimeAsync(60_000)
|
|
258
|
-
expect(scheduler.getStatus().jobs[0].lastResult).toBe('error')
|
|
259
|
-
|
|
260
|
-
// Second run — succeeds
|
|
261
|
-
await vi.advanceTimersByTimeAsync(60_000)
|
|
262
|
-
expect(scheduler.getStatus().jobs[0].lastResult).toBe('success')
|
|
263
|
-
expect(scheduler.getStatus().jobs[0].runCount).toBe(2)
|
|
264
|
-
|
|
265
|
-
scheduler.stop()
|
|
266
|
-
})
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
describe('vacuum job', () => {
|
|
270
|
-
it('should call pragma optimize and flushSave on interval', async () => {
|
|
271
|
-
const db = createMockDb()
|
|
272
|
-
|
|
273
|
-
const scheduler = new Scheduler(
|
|
274
|
-
defaultOptions({ vacuumIntervalMinutes: 1 }),
|
|
275
|
-
db as never
|
|
276
|
-
)
|
|
277
|
-
scheduler.start()
|
|
278
|
-
|
|
279
|
-
await vi.advanceTimersByTimeAsync(60_000)
|
|
280
|
-
|
|
281
|
-
expect(db.pragma).toHaveBeenCalledWith('optimize')
|
|
282
|
-
expect(db.flushSave).toHaveBeenCalledOnce()
|
|
283
|
-
|
|
284
|
-
scheduler.stop()
|
|
285
|
-
})
|
|
286
|
-
})
|
|
287
|
-
|
|
288
|
-
describe('rebuild-index job', () => {
|
|
289
|
-
it('should call vectorManager.rebuildIndex on interval', async () => {
|
|
290
|
-
const db = createMockDb()
|
|
291
|
-
const vectorManager = createMockVectorManager()
|
|
292
|
-
|
|
293
|
-
const scheduler = new Scheduler(
|
|
294
|
-
defaultOptions({ rebuildIndexIntervalMinutes: 1 }),
|
|
295
|
-
db as never,
|
|
296
|
-
vectorManager as never
|
|
297
|
-
)
|
|
298
|
-
scheduler.start()
|
|
299
|
-
|
|
300
|
-
await vi.advanceTimersByTimeAsync(60_000)
|
|
301
|
-
|
|
302
|
-
expect(vectorManager.rebuildIndex).toHaveBeenCalledWith(db)
|
|
303
|
-
|
|
304
|
-
const status = scheduler.getStatus()
|
|
305
|
-
const job = status.jobs.find((j) => j.name === 'rebuild-index')
|
|
306
|
-
expect(job!.lastResult).toBe('success')
|
|
307
|
-
|
|
308
|
-
scheduler.stop()
|
|
309
|
-
})
|
|
310
|
-
})
|
|
311
|
-
|
|
312
|
-
// ========================================================================
|
|
313
|
-
// getStatus
|
|
314
|
-
// ========================================================================
|
|
315
|
-
|
|
316
|
-
describe('getStatus', () => {
|
|
317
|
-
it('should return inactive status before start', () => {
|
|
318
|
-
const db = createMockDb()
|
|
319
|
-
const scheduler = new Scheduler(
|
|
320
|
-
defaultOptions({ backupIntervalMinutes: 60 }),
|
|
321
|
-
db as never
|
|
322
|
-
)
|
|
323
|
-
|
|
324
|
-
const status = scheduler.getStatus()
|
|
325
|
-
expect(status.active).toBe(false)
|
|
326
|
-
expect(status.jobs).toHaveLength(0)
|
|
327
|
-
})
|
|
328
|
-
|
|
329
|
-
it('should include nextRun for jobs that have not run yet', () => {
|
|
330
|
-
const db = createMockDb()
|
|
331
|
-
const scheduler = new Scheduler(
|
|
332
|
-
defaultOptions({ backupIntervalMinutes: 60 }),
|
|
333
|
-
db as never
|
|
334
|
-
)
|
|
335
|
-
scheduler.start()
|
|
336
|
-
|
|
337
|
-
const status = scheduler.getStatus()
|
|
338
|
-
const job = status.jobs[0]
|
|
339
|
-
expect(job.lastRun).toBeNull()
|
|
340
|
-
expect(job.nextRun).toBeTruthy()
|
|
341
|
-
|
|
342
|
-
scheduler.stop()
|
|
343
|
-
})
|
|
344
|
-
|
|
345
|
-
it('should correctly report interval for each job', () => {
|
|
346
|
-
const db = createMockDb()
|
|
347
|
-
const vectorManager = createMockVectorManager()
|
|
348
|
-
const scheduler = new Scheduler(
|
|
349
|
-
defaultOptions({
|
|
350
|
-
backupIntervalMinutes: 10,
|
|
351
|
-
vacuumIntervalMinutes: 20,
|
|
352
|
-
rebuildIndexIntervalMinutes: 30,
|
|
353
|
-
}),
|
|
354
|
-
db as never,
|
|
355
|
-
vectorManager as never
|
|
356
|
-
)
|
|
357
|
-
scheduler.start()
|
|
358
|
-
|
|
359
|
-
const status = scheduler.getStatus()
|
|
360
|
-
expect(status.jobs[0].intervalMinutes).toBe(10)
|
|
361
|
-
expect(status.jobs[1].intervalMinutes).toBe(20)
|
|
362
|
-
expect(status.jobs[2].intervalMinutes).toBe(30)
|
|
363
|
-
|
|
364
|
-
scheduler.stop()
|
|
365
|
-
})
|
|
366
|
-
})
|
|
367
|
-
|
|
368
|
-
// ========================================================================
|
|
369
|
-
// Error isolation
|
|
370
|
-
// ========================================================================
|
|
371
|
-
|
|
372
|
-
describe('error isolation', () => {
|
|
373
|
-
it('should not stop other jobs when one fails', async () => {
|
|
374
|
-
const db = createMockDb()
|
|
375
|
-
db.exportToFile.mockImplementation(() => {
|
|
376
|
-
throw new Error('Backup failed')
|
|
377
|
-
})
|
|
378
|
-
|
|
379
|
-
const scheduler = new Scheduler(
|
|
380
|
-
defaultOptions({
|
|
381
|
-
backupIntervalMinutes: 1,
|
|
382
|
-
vacuumIntervalMinutes: 1,
|
|
383
|
-
}),
|
|
384
|
-
db as never
|
|
385
|
-
)
|
|
386
|
-
scheduler.start()
|
|
387
|
-
|
|
388
|
-
await vi.advanceTimersByTimeAsync(60_000)
|
|
389
|
-
|
|
390
|
-
// Backup failed but vacuum should still have run
|
|
391
|
-
const status = scheduler.getStatus()
|
|
392
|
-
const backupJob = status.jobs.find((j) => j.name === 'backup')
|
|
393
|
-
const vacuumJob = status.jobs.find((j) => j.name === 'vacuum')
|
|
394
|
-
expect(backupJob!.lastResult).toBe('error')
|
|
395
|
-
expect(vacuumJob!.lastResult).toBe('success')
|
|
396
|
-
|
|
397
|
-
scheduler.stop()
|
|
398
|
-
})
|
|
399
|
-
})
|
|
400
|
-
})
|
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* memory-journal-mcp — HTTP Legacy SSE Transport Tests
|
|
3
|
-
*
|
|
4
|
-
* Tests for setupLegacySSE: GET /sse and POST /messages handlers.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
8
|
-
|
|
9
|
-
// ============================================================================
|
|
10
|
-
// Hoisted mocks
|
|
11
|
-
// ============================================================================
|
|
12
|
-
|
|
13
|
-
const { MockSSEServerTransport } = vi.hoisted(() => {
|
|
14
|
-
const handlePostMessage = vi.fn().mockResolvedValue(undefined)
|
|
15
|
-
|
|
16
|
-
class SSEMock {
|
|
17
|
-
sessionId = 'sse-test-session'
|
|
18
|
-
onclose: (() => void) | null = null
|
|
19
|
-
handlePostMessage = handlePostMessage
|
|
20
|
-
close = vi.fn().mockResolvedValue(undefined)
|
|
21
|
-
|
|
22
|
-
constructor(_path: string, _res: unknown) {
|
|
23
|
-
// SSEServerTransport takes path and response
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
MockSSEServerTransport: SSEMock,
|
|
29
|
-
mockHandlePostMessage: handlePostMessage,
|
|
30
|
-
}
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
vi.mock('@modelcontextprotocol/sdk/server/sse.js', () => ({
|
|
34
|
-
SSEServerTransport: MockSSEServerTransport,
|
|
35
|
-
}))
|
|
36
|
-
|
|
37
|
-
vi.mock('../../../src/utils/logger.js', () => ({
|
|
38
|
-
logger: {
|
|
39
|
-
info: vi.fn(),
|
|
40
|
-
warning: vi.fn(),
|
|
41
|
-
error: vi.fn(),
|
|
42
|
-
debug: vi.fn(),
|
|
43
|
-
},
|
|
44
|
-
}))
|
|
45
|
-
|
|
46
|
-
import { setupLegacySSE } from '../../../src/transports/http/server/legacy-sse.js'
|
|
47
|
-
import type { StatefulContext } from '../../../src/transports/http/server/stateful.js'
|
|
48
|
-
|
|
49
|
-
// ============================================================================
|
|
50
|
-
// Helpers
|
|
51
|
-
// ============================================================================
|
|
52
|
-
|
|
53
|
-
function createMockCtx(): StatefulContext {
|
|
54
|
-
return {
|
|
55
|
-
transports: new Map(),
|
|
56
|
-
sseTransports: new Map(),
|
|
57
|
-
sessionLastActivity: new Map(),
|
|
58
|
-
touchSession: vi.fn(),
|
|
59
|
-
serverConnected: false,
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function mockReq(overrides: Partial<Record<string, unknown>> = {}): Record<string, unknown> {
|
|
64
|
-
return {
|
|
65
|
-
method: 'GET',
|
|
66
|
-
headers: {},
|
|
67
|
-
query: {},
|
|
68
|
-
body: {},
|
|
69
|
-
on: vi.fn(),
|
|
70
|
-
ip: '127.0.0.1',
|
|
71
|
-
socket: { remoteAddress: '127.0.0.1' },
|
|
72
|
-
...overrides,
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function mockRes(): Record<string, unknown> {
|
|
77
|
-
const res: Record<string, unknown> = {
|
|
78
|
-
headersSent: false,
|
|
79
|
-
setHeader: vi.fn(),
|
|
80
|
-
json: vi.fn(),
|
|
81
|
-
send: vi.fn(),
|
|
82
|
-
end: vi.fn(),
|
|
83
|
-
}
|
|
84
|
-
res['status'] = vi.fn().mockReturnValue(res)
|
|
85
|
-
return res
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function createMockApp() {
|
|
89
|
-
const routes: Record<string, Record<string, Function>> = {
|
|
90
|
-
get: {},
|
|
91
|
-
post: {},
|
|
92
|
-
}
|
|
93
|
-
return {
|
|
94
|
-
get: vi.fn().mockImplementation((path: string, handler: Function) => {
|
|
95
|
-
routes['get']![path] = handler
|
|
96
|
-
}),
|
|
97
|
-
post: vi.fn().mockImplementation((path: string, handler: Function) => {
|
|
98
|
-
routes['post']![path] = handler
|
|
99
|
-
}),
|
|
100
|
-
routes,
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function createMockServer() {
|
|
105
|
-
return {
|
|
106
|
-
connect: vi.fn().mockResolvedValue(undefined),
|
|
107
|
-
close: vi.fn().mockResolvedValue(undefined),
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// ============================================================================
|
|
112
|
-
// Tests
|
|
113
|
-
// ============================================================================
|
|
114
|
-
|
|
115
|
-
describe('setupLegacySSE', () => {
|
|
116
|
-
beforeEach(() => {
|
|
117
|
-
vi.clearAllMocks()
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
it('should register GET /sse and POST /messages routes', () => {
|
|
121
|
-
const ctx = createMockCtx()
|
|
122
|
-
const app = createMockApp()
|
|
123
|
-
const server = createMockServer()
|
|
124
|
-
|
|
125
|
-
setupLegacySSE(ctx, app as never, server as never)
|
|
126
|
-
|
|
127
|
-
expect(app.get).toHaveBeenCalledWith('/sse', expect.any(Function))
|
|
128
|
-
expect(app.post).toHaveBeenCalledWith('/messages', expect.any(Function))
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
// ========================================================================
|
|
132
|
-
// GET /sse
|
|
133
|
-
// ========================================================================
|
|
134
|
-
|
|
135
|
-
it('should establish SSE connection on GET /sse', async () => {
|
|
136
|
-
const ctx = createMockCtx()
|
|
137
|
-
const app = createMockApp()
|
|
138
|
-
const server = createMockServer()
|
|
139
|
-
|
|
140
|
-
setupLegacySSE(ctx, app as never, server as never)
|
|
141
|
-
const handler = app.routes['get']!['/sse']!
|
|
142
|
-
|
|
143
|
-
const req = mockReq()
|
|
144
|
-
const res = mockRes()
|
|
145
|
-
handler(req, res)
|
|
146
|
-
|
|
147
|
-
// Wait for async connect
|
|
148
|
-
await vi.waitFor(() => {
|
|
149
|
-
expect(server.connect).toHaveBeenCalled()
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
// Verify transport was registered
|
|
153
|
-
expect(ctx.sseTransports.has('sse-test-session')).toBe(true)
|
|
154
|
-
expect(ctx.touchSession).toHaveBeenCalledWith('sse-test-session')
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
it('should handle clean up on client disconnect', async () => {
|
|
158
|
-
const ctx = createMockCtx()
|
|
159
|
-
const app = createMockApp()
|
|
160
|
-
const server = createMockServer()
|
|
161
|
-
|
|
162
|
-
setupLegacySSE(ctx, app as never, server as never)
|
|
163
|
-
const handler = app.routes['get']!['/sse']!
|
|
164
|
-
|
|
165
|
-
const req = mockReq()
|
|
166
|
-
const onCallback = vi.fn()
|
|
167
|
-
;(req as Record<string, unknown>)['on'] = onCallback
|
|
168
|
-
const res = mockRes()
|
|
169
|
-
handler(req, res)
|
|
170
|
-
|
|
171
|
-
// Wait for connect
|
|
172
|
-
await vi.waitFor(() => {
|
|
173
|
-
expect(server.connect).toHaveBeenCalled()
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
// Simulate client disconnect
|
|
177
|
-
const closeCallback = onCallback.mock.calls.find(
|
|
178
|
-
(call: unknown[]) => call[0] === 'close'
|
|
179
|
-
)?.[1] as (() => void) | undefined
|
|
180
|
-
expect(closeCallback).toBeDefined()
|
|
181
|
-
|
|
182
|
-
closeCallback!()
|
|
183
|
-
expect(ctx.sseTransports.has('sse-test-session')).toBe(false)
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
it('should handle server connect error with headersSent=false', async () => {
|
|
187
|
-
const ctx = createMockCtx()
|
|
188
|
-
const app = createMockApp()
|
|
189
|
-
const server = createMockServer()
|
|
190
|
-
server.connect.mockRejectedValue(new Error('connect error'))
|
|
191
|
-
server.close.mockRejectedValue(new Error('close also fails'))
|
|
192
|
-
|
|
193
|
-
setupLegacySSE(ctx, app as never, server as never)
|
|
194
|
-
const handler = app.routes['get']!['/sse']!
|
|
195
|
-
|
|
196
|
-
const req = mockReq()
|
|
197
|
-
const res = mockRes()
|
|
198
|
-
handler(req, res)
|
|
199
|
-
|
|
200
|
-
// Wait for error handling
|
|
201
|
-
await vi.waitFor(() => {
|
|
202
|
-
expect(res['status'] as ReturnType<typeof vi.fn>).toHaveBeenCalledWith(500)
|
|
203
|
-
})
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
// ========================================================================
|
|
207
|
-
// POST /messages
|
|
208
|
-
// ========================================================================
|
|
209
|
-
|
|
210
|
-
it('should return 400 for POST /messages without sessionId', () => {
|
|
211
|
-
const ctx = createMockCtx()
|
|
212
|
-
const app = createMockApp()
|
|
213
|
-
const server = createMockServer()
|
|
214
|
-
|
|
215
|
-
setupLegacySSE(ctx, app as never, server as never)
|
|
216
|
-
const handler = app.routes['post']!['/messages']!
|
|
217
|
-
|
|
218
|
-
const req = mockReq({ query: {} })
|
|
219
|
-
const res = mockRes()
|
|
220
|
-
handler(req, res)
|
|
221
|
-
|
|
222
|
-
expect(res['status'] as ReturnType<typeof vi.fn>).toHaveBeenCalledWith(400)
|
|
223
|
-
expect(res['json'] as ReturnType<typeof vi.fn>).toHaveBeenCalledWith(
|
|
224
|
-
expect.objectContaining({
|
|
225
|
-
error: expect.objectContaining({
|
|
226
|
-
message: expect.stringContaining('Missing sessionId'),
|
|
227
|
-
}),
|
|
228
|
-
})
|
|
229
|
-
)
|
|
230
|
-
})
|
|
231
|
-
|
|
232
|
-
it('should return 404 for POST /messages with unknown sessionId', () => {
|
|
233
|
-
const ctx = createMockCtx()
|
|
234
|
-
const app = createMockApp()
|
|
235
|
-
const server = createMockServer()
|
|
236
|
-
|
|
237
|
-
setupLegacySSE(ctx, app as never, server as never)
|
|
238
|
-
const handler = app.routes['post']!['/messages']!
|
|
239
|
-
|
|
240
|
-
const req = mockReq({ query: { sessionId: 'unknown-session' } })
|
|
241
|
-
const res = mockRes()
|
|
242
|
-
handler(req, res)
|
|
243
|
-
|
|
244
|
-
expect(res['status'] as ReturnType<typeof vi.fn>).toHaveBeenCalledWith(404)
|
|
245
|
-
expect(res['json'] as ReturnType<typeof vi.fn>).toHaveBeenCalledWith(
|
|
246
|
-
expect.objectContaining({
|
|
247
|
-
error: expect.objectContaining({
|
|
248
|
-
message: expect.stringContaining('Session not found'),
|
|
249
|
-
}),
|
|
250
|
-
})
|
|
251
|
-
)
|
|
252
|
-
})
|
|
253
|
-
|
|
254
|
-
it('should forward message to transport for valid sessionId', () => {
|
|
255
|
-
const ctx = createMockCtx()
|
|
256
|
-
const mockTransport = { handlePostMessage: vi.fn().mockResolvedValue(undefined) }
|
|
257
|
-
ctx.sseTransports.set('valid-session', mockTransport as never)
|
|
258
|
-
|
|
259
|
-
const app = createMockApp()
|
|
260
|
-
const server = createMockServer()
|
|
261
|
-
|
|
262
|
-
setupLegacySSE(ctx, app as never, server as never)
|
|
263
|
-
const handler = app.routes['post']!['/messages']!
|
|
264
|
-
|
|
265
|
-
const req = mockReq({
|
|
266
|
-
query: { sessionId: 'valid-session' },
|
|
267
|
-
body: { method: 'tools/list' },
|
|
268
|
-
})
|
|
269
|
-
const res = mockRes()
|
|
270
|
-
handler(req, res)
|
|
271
|
-
|
|
272
|
-
expect(ctx.touchSession).toHaveBeenCalledWith('valid-session')
|
|
273
|
-
expect(mockTransport.handlePostMessage).toHaveBeenCalled()
|
|
274
|
-
})
|
|
275
|
-
})
|