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,929 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GitHub Resource Handler Tests
|
|
3
|
-
*
|
|
4
|
-
* Tests GitHub-dependent resources using a mock GitHubIntegration object.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest'
|
|
8
|
-
import { readResource } from '../../src/handlers/resources/index.js'
|
|
9
|
-
import { DatabaseAdapter } from '../../src/database/sqlite-adapter/index.js'
|
|
10
|
-
import type { GitHubIntegration } from '../../src/github/github-integration.js'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Creates a minimal mock GitHubIntegration with sensible defaults.
|
|
14
|
-
*/
|
|
15
|
-
function createMockGitHub(overrides: Partial<Record<string, unknown>> = {}): GitHubIntegration {
|
|
16
|
-
const mock = {
|
|
17
|
-
isApiAvailable: vi.fn().mockReturnValue(true),
|
|
18
|
-
getRepoInfo: vi.fn().mockResolvedValue({
|
|
19
|
-
owner: 'testowner',
|
|
20
|
-
repo: 'testrepo',
|
|
21
|
-
branch: 'main',
|
|
22
|
-
remoteUrl: 'git@github.com:testowner/testrepo.git',
|
|
23
|
-
}),
|
|
24
|
-
getRepoContext: vi.fn().mockResolvedValue({
|
|
25
|
-
repoName: 'testrepo',
|
|
26
|
-
branch: 'main',
|
|
27
|
-
commit: 'abc1234',
|
|
28
|
-
remoteUrl: 'url',
|
|
29
|
-
projects: [],
|
|
30
|
-
issues: [],
|
|
31
|
-
pullRequests: [],
|
|
32
|
-
workflowRuns: [],
|
|
33
|
-
milestones: [],
|
|
34
|
-
}),
|
|
35
|
-
getIssues: vi
|
|
36
|
-
.fn()
|
|
37
|
-
.mockResolvedValue([
|
|
38
|
-
{ number: 1, title: 'Bug fix needed', url: 'url1', state: 'OPEN', milestone: null },
|
|
39
|
-
]),
|
|
40
|
-
getPullRequests: vi
|
|
41
|
-
.fn()
|
|
42
|
-
.mockResolvedValue([{ number: 10, title: 'Feature PR', url: 'url10', state: 'OPEN' }]),
|
|
43
|
-
getWorkflowRuns: vi.fn().mockResolvedValue([
|
|
44
|
-
{
|
|
45
|
-
id: 100,
|
|
46
|
-
name: 'CI',
|
|
47
|
-
status: 'completed',
|
|
48
|
-
conclusion: 'success',
|
|
49
|
-
url: 'url',
|
|
50
|
-
headBranch: 'main',
|
|
51
|
-
headSha: 'abc1234',
|
|
52
|
-
createdAt: '2025-01-01T00:00:00Z',
|
|
53
|
-
updatedAt: '2025-01-01T01:00:00Z',
|
|
54
|
-
},
|
|
55
|
-
]),
|
|
56
|
-
getProjectKanban: vi.fn().mockResolvedValue(null),
|
|
57
|
-
getMilestones: vi.fn().mockResolvedValue([
|
|
58
|
-
{
|
|
59
|
-
number: 1,
|
|
60
|
-
title: 'v1.0',
|
|
61
|
-
description: 'First release',
|
|
62
|
-
state: 'open',
|
|
63
|
-
url: 'url',
|
|
64
|
-
dueOn: '2025-06-01T00:00:00Z',
|
|
65
|
-
openIssues: 5,
|
|
66
|
-
closedIssues: 10,
|
|
67
|
-
createdAt: '2025-01-01T00:00:00Z',
|
|
68
|
-
updatedAt: '2025-01-02T00:00:00Z',
|
|
69
|
-
creator: 'owner1',
|
|
70
|
-
},
|
|
71
|
-
]),
|
|
72
|
-
getMilestone: vi.fn().mockResolvedValue({
|
|
73
|
-
number: 1,
|
|
74
|
-
title: 'v1.0',
|
|
75
|
-
description: 'First release',
|
|
76
|
-
state: 'open',
|
|
77
|
-
url: 'url',
|
|
78
|
-
dueOn: '2025-06-01T00:00:00Z',
|
|
79
|
-
openIssues: 5,
|
|
80
|
-
closedIssues: 10,
|
|
81
|
-
createdAt: '2025-01-01T00:00:00Z',
|
|
82
|
-
updatedAt: '2025-01-02T00:00:00Z',
|
|
83
|
-
creator: 'owner1',
|
|
84
|
-
}),
|
|
85
|
-
getCachedRepoInfo: vi.fn().mockReturnValue({
|
|
86
|
-
owner: 'testowner',
|
|
87
|
-
repo: 'testrepo',
|
|
88
|
-
branch: 'main',
|
|
89
|
-
remoteUrl: 'git@github.com:testowner/testrepo.git',
|
|
90
|
-
}),
|
|
91
|
-
getRepoStats: vi.fn().mockResolvedValue({
|
|
92
|
-
stars: 42,
|
|
93
|
-
forks: 7,
|
|
94
|
-
watchers: 3,
|
|
95
|
-
}),
|
|
96
|
-
getTrafficData: vi.fn().mockResolvedValue({
|
|
97
|
-
clones: { total: 120, uniqueCloners: 30 },
|
|
98
|
-
views: { total: 500, uniqueVisitors: 80 },
|
|
99
|
-
}),
|
|
100
|
-
...overrides,
|
|
101
|
-
}
|
|
102
|
-
return mock as unknown as GitHubIntegration
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
describe('GitHub Resource Handlers', () => {
|
|
106
|
-
let db: DatabaseAdapter
|
|
107
|
-
const testDbPath = './test-gh-resources.db'
|
|
108
|
-
|
|
109
|
-
beforeAll(async () => {
|
|
110
|
-
db = new DatabaseAdapter(testDbPath)
|
|
111
|
-
await db.initialize()
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
afterAll(() => {
|
|
115
|
-
db.close()
|
|
116
|
-
try {
|
|
117
|
-
const fs = require('node:fs')
|
|
118
|
-
if (fs.existsSync(testDbPath)) fs.unlinkSync(testDbPath)
|
|
119
|
-
} catch {
|
|
120
|
-
// Ignore cleanup errors
|
|
121
|
-
}
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
// ========================================================================
|
|
125
|
-
// memory://github/status
|
|
126
|
-
// ========================================================================
|
|
127
|
-
|
|
128
|
-
describe('memory://github/status', () => {
|
|
129
|
-
it('should return status with repo info, CI, issues, PRs', async () => {
|
|
130
|
-
const github = createMockGitHub()
|
|
131
|
-
const result = await readResource(
|
|
132
|
-
'memory://github/status',
|
|
133
|
-
db,
|
|
134
|
-
undefined,
|
|
135
|
-
undefined,
|
|
136
|
-
github
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
const data = result.data as {
|
|
140
|
-
repository: string
|
|
141
|
-
branch: string
|
|
142
|
-
ci: { status: string }
|
|
143
|
-
issues: { openCount: number }
|
|
144
|
-
pullRequests: { openCount: number }
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
expect(data.repository).toBe('testowner/testrepo')
|
|
148
|
-
expect(data.branch).toBe('main')
|
|
149
|
-
expect(data.ci.status).toBe('passing')
|
|
150
|
-
expect(data.issues.openCount).toBe(1)
|
|
151
|
-
expect(data.pullRequests.openCount).toBe(1)
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
it('should return error when no github integration', async () => {
|
|
155
|
-
const result = await readResource(
|
|
156
|
-
'memory://github/status',
|
|
157
|
-
db,
|
|
158
|
-
undefined,
|
|
159
|
-
undefined,
|
|
160
|
-
null
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
const data = result.data as { error: string; hint: string }
|
|
164
|
-
expect(data.error).toContain('GitHub integration not available')
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
it('should handle missing owner/repo', async () => {
|
|
168
|
-
const github = createMockGitHub({
|
|
169
|
-
getRepoInfo: vi.fn().mockResolvedValue({
|
|
170
|
-
owner: null,
|
|
171
|
-
repo: null,
|
|
172
|
-
branch: 'main',
|
|
173
|
-
remoteUrl: null,
|
|
174
|
-
}),
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
const result = await readResource(
|
|
178
|
-
'memory://github/status',
|
|
179
|
-
db,
|
|
180
|
-
undefined,
|
|
181
|
-
undefined,
|
|
182
|
-
github
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
const data = result.data as { error: string }
|
|
186
|
-
expect(data.error).toContain('Could not detect repository')
|
|
187
|
-
})
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
// ========================================================================
|
|
191
|
-
// memory://github/milestones
|
|
192
|
-
// ========================================================================
|
|
193
|
-
|
|
194
|
-
describe('memory://github/milestones', () => {
|
|
195
|
-
it('should return milestones with completion percentages', async () => {
|
|
196
|
-
const github = createMockGitHub()
|
|
197
|
-
const result = await readResource(
|
|
198
|
-
'memory://github/milestones',
|
|
199
|
-
db,
|
|
200
|
-
undefined,
|
|
201
|
-
undefined,
|
|
202
|
-
github
|
|
203
|
-
)
|
|
204
|
-
|
|
205
|
-
const data = result.data as {
|
|
206
|
-
repository: string
|
|
207
|
-
milestones: { completionPercentage: number }[]
|
|
208
|
-
count: number
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
expect(data.repository).toBe('testowner/testrepo')
|
|
212
|
-
expect(data.count).toBe(1)
|
|
213
|
-
// 10 closed / (5 open + 10 closed) = 66.67% => 67%
|
|
214
|
-
expect(data.milestones[0]!.completionPercentage).toBe(67)
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
it('should return error when no github', async () => {
|
|
218
|
-
const result = await readResource(
|
|
219
|
-
'memory://github/milestones',
|
|
220
|
-
db,
|
|
221
|
-
undefined,
|
|
222
|
-
undefined,
|
|
223
|
-
null
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
const data = result.data as { error: string }
|
|
227
|
-
expect(data.error).toContain('GitHub integration not available')
|
|
228
|
-
})
|
|
229
|
-
})
|
|
230
|
-
|
|
231
|
-
// ========================================================================
|
|
232
|
-
// memory://milestones/{number}
|
|
233
|
-
// ========================================================================
|
|
234
|
-
|
|
235
|
-
describe('memory://milestones/{number}', () => {
|
|
236
|
-
it('should return single milestone detail', async () => {
|
|
237
|
-
const github = createMockGitHub()
|
|
238
|
-
const result = await readResource(
|
|
239
|
-
'memory://milestones/1',
|
|
240
|
-
db,
|
|
241
|
-
undefined,
|
|
242
|
-
undefined,
|
|
243
|
-
github
|
|
244
|
-
)
|
|
245
|
-
|
|
246
|
-
const data = result.data as {
|
|
247
|
-
repository: string
|
|
248
|
-
milestone: { number: number; completionPercentage: number }
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
expect(data.repository).toBe('testowner/testrepo')
|
|
252
|
-
expect(data.milestone.number).toBe(1)
|
|
253
|
-
expect(data.milestone.completionPercentage).toBe(67)
|
|
254
|
-
})
|
|
255
|
-
|
|
256
|
-
it('should return error for not found milestone', async () => {
|
|
257
|
-
const github = createMockGitHub({
|
|
258
|
-
getMilestone: vi.fn().mockResolvedValue(null),
|
|
259
|
-
})
|
|
260
|
-
const result = await readResource(
|
|
261
|
-
'memory://milestones/999',
|
|
262
|
-
db,
|
|
263
|
-
undefined,
|
|
264
|
-
undefined,
|
|
265
|
-
github
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
const data = result.data as { error: string }
|
|
269
|
-
expect(data.error).toContain('not found')
|
|
270
|
-
})
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
// ========================================================================
|
|
274
|
-
// memory://kanban/{project_number}
|
|
275
|
-
// ========================================================================
|
|
276
|
-
|
|
277
|
-
describe('memory://kanban/{project_number}', () => {
|
|
278
|
-
it('should return kanban board when available', async () => {
|
|
279
|
-
const github = createMockGitHub({
|
|
280
|
-
getProjectKanban: vi.fn().mockResolvedValue({
|
|
281
|
-
projectId: 'PVT_1',
|
|
282
|
-
projectTitle: 'My Board',
|
|
283
|
-
columns: [
|
|
284
|
-
{
|
|
285
|
-
status: 'Todo',
|
|
286
|
-
items: [{ id: 'I1', type: 'ISSUE', title: 'Task', number: 1 }],
|
|
287
|
-
},
|
|
288
|
-
],
|
|
289
|
-
statusOptions: [],
|
|
290
|
-
totalItems: 1,
|
|
291
|
-
}),
|
|
292
|
-
})
|
|
293
|
-
|
|
294
|
-
const result = await readResource('memory://kanban/1', db, undefined, undefined, github)
|
|
295
|
-
|
|
296
|
-
const data = result.data as { projectTitle: string; totalItems: number }
|
|
297
|
-
expect(data.projectTitle).toBe('My Board')
|
|
298
|
-
expect(data.totalItems).toBe(1)
|
|
299
|
-
})
|
|
300
|
-
|
|
301
|
-
it('should return error when project not found', async () => {
|
|
302
|
-
const github = createMockGitHub()
|
|
303
|
-
const result = await readResource(
|
|
304
|
-
'memory://kanban/999',
|
|
305
|
-
db,
|
|
306
|
-
undefined,
|
|
307
|
-
undefined,
|
|
308
|
-
github
|
|
309
|
-
)
|
|
310
|
-
|
|
311
|
-
const data = result.data as { error: string }
|
|
312
|
-
expect(data.error).toContain('not found')
|
|
313
|
-
})
|
|
314
|
-
|
|
315
|
-
it('should return error when no github', async () => {
|
|
316
|
-
const result = await readResource('memory://kanban/1', db, undefined, undefined, null)
|
|
317
|
-
|
|
318
|
-
const data = result.data as { error: string }
|
|
319
|
-
expect(data.error).toContain('GitHub integration not available')
|
|
320
|
-
})
|
|
321
|
-
})
|
|
322
|
-
|
|
323
|
-
// ========================================================================
|
|
324
|
-
// memory://kanban/{project_number}/diagram
|
|
325
|
-
// ========================================================================
|
|
326
|
-
|
|
327
|
-
describe('memory://kanban/{project_number}/diagram', () => {
|
|
328
|
-
it('should return mermaid diagram', async () => {
|
|
329
|
-
const github = createMockGitHub({
|
|
330
|
-
getProjectKanban: vi.fn().mockResolvedValue({
|
|
331
|
-
projectId: 'PVT_1',
|
|
332
|
-
projectTitle: 'Board',
|
|
333
|
-
columns: [
|
|
334
|
-
{
|
|
335
|
-
status: 'Done',
|
|
336
|
-
items: [
|
|
337
|
-
{
|
|
338
|
-
id: 'PVTITEM_A1B2C3D4',
|
|
339
|
-
type: 'ISSUE',
|
|
340
|
-
title: 'Completed task',
|
|
341
|
-
number: 5,
|
|
342
|
-
},
|
|
343
|
-
],
|
|
344
|
-
},
|
|
345
|
-
],
|
|
346
|
-
statusOptions: [],
|
|
347
|
-
totalItems: 1,
|
|
348
|
-
}),
|
|
349
|
-
})
|
|
350
|
-
|
|
351
|
-
const result = await readResource(
|
|
352
|
-
'memory://kanban/1/diagram',
|
|
353
|
-
db,
|
|
354
|
-
undefined,
|
|
355
|
-
undefined,
|
|
356
|
-
github
|
|
357
|
-
)
|
|
358
|
-
|
|
359
|
-
const data = result.data as string
|
|
360
|
-
|
|
361
|
-
expect(typeof data).toBe('string')
|
|
362
|
-
expect(data).toContain('graph LR')
|
|
363
|
-
expect(data).toContain('Done')
|
|
364
|
-
})
|
|
365
|
-
|
|
366
|
-
it('should show fallback when no github', async () => {
|
|
367
|
-
const result = await readResource(
|
|
368
|
-
'memory://kanban/1/diagram',
|
|
369
|
-
db,
|
|
370
|
-
undefined,
|
|
371
|
-
undefined,
|
|
372
|
-
null
|
|
373
|
-
)
|
|
374
|
-
|
|
375
|
-
expect(typeof result.data).toBe('string')
|
|
376
|
-
expect(result.data as string).toContain('NoGitHub')
|
|
377
|
-
})
|
|
378
|
-
})
|
|
379
|
-
|
|
380
|
-
// ========================================================================
|
|
381
|
-
// memory://briefing with GitHub insights
|
|
382
|
-
// ========================================================================
|
|
383
|
-
|
|
384
|
-
describe('memory://briefing with GitHub', () => {
|
|
385
|
-
it('should include insights with stars, forks, and traffic', async () => {
|
|
386
|
-
const github = createMockGitHub()
|
|
387
|
-
const result = await readResource('memory://briefing', db, undefined, undefined, github)
|
|
388
|
-
|
|
389
|
-
const data = result.data as {
|
|
390
|
-
github: {
|
|
391
|
-
repo: string
|
|
392
|
-
insights?: {
|
|
393
|
-
stars: number | null
|
|
394
|
-
forks: number | null
|
|
395
|
-
clones14d?: number
|
|
396
|
-
views14d?: number
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
userMessage: string
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
expect(data.github.repo).toBe('testowner/testrepo')
|
|
403
|
-
expect(data.github.insights).toBeDefined()
|
|
404
|
-
expect(data.github.insights!.stars).toBe(42)
|
|
405
|
-
expect(data.github.insights!.forks).toBe(7)
|
|
406
|
-
expect(data.github.insights!.clones14d).toBe(120)
|
|
407
|
-
expect(data.github.insights!.views14d).toBe(500)
|
|
408
|
-
expect(data.userMessage).toContain('stars')
|
|
409
|
-
expect(data.userMessage).toContain('forks')
|
|
410
|
-
expect(data.userMessage).toContain('clones')
|
|
411
|
-
})
|
|
412
|
-
|
|
413
|
-
it('should include insights without traffic when getTrafficData fails', async () => {
|
|
414
|
-
const github = createMockGitHub({
|
|
415
|
-
getTrafficData: vi.fn().mockRejectedValue(new Error('403 Forbidden')),
|
|
416
|
-
})
|
|
417
|
-
const result = await readResource('memory://briefing', db, undefined, undefined, github)
|
|
418
|
-
|
|
419
|
-
const data = result.data as {
|
|
420
|
-
github: {
|
|
421
|
-
insights?: {
|
|
422
|
-
stars: number | null
|
|
423
|
-
forks: number | null
|
|
424
|
-
clones14d?: number
|
|
425
|
-
views14d?: number
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
userMessage: string
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// Stars and forks should still be present
|
|
432
|
-
expect(data.github.insights).toBeDefined()
|
|
433
|
-
expect(data.github.insights!.stars).toBe(42)
|
|
434
|
-
expect(data.github.insights!.forks).toBe(7)
|
|
435
|
-
// Traffic should be absent
|
|
436
|
-
expect(data.github.insights!.clones14d).toBeUndefined()
|
|
437
|
-
expect(data.github.insights!.views14d).toBeUndefined()
|
|
438
|
-
})
|
|
439
|
-
|
|
440
|
-
it('should omit insights when getRepoStats fails', async () => {
|
|
441
|
-
const github = createMockGitHub({
|
|
442
|
-
getRepoStats: vi.fn().mockRejectedValue(new Error('API error')),
|
|
443
|
-
})
|
|
444
|
-
const result = await readResource('memory://briefing', db, undefined, undefined, github)
|
|
445
|
-
|
|
446
|
-
const data = result.data as {
|
|
447
|
-
github: {
|
|
448
|
-
insights?: unknown
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
expect(data.github.insights).toBeUndefined()
|
|
453
|
-
})
|
|
454
|
-
|
|
455
|
-
it('should include repoInsights in more section', async () => {
|
|
456
|
-
const github = createMockGitHub()
|
|
457
|
-
const result = await readResource('memory://briefing', db, undefined, undefined, github)
|
|
458
|
-
|
|
459
|
-
const data = result.data as {
|
|
460
|
-
more: { repoInsights: string }
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
expect(data.more.repoInsights).toBe('memory://github/insights')
|
|
464
|
-
})
|
|
465
|
-
})
|
|
466
|
-
|
|
467
|
-
// ========================================================================
|
|
468
|
-
// memory://github/insights
|
|
469
|
-
// ========================================================================
|
|
470
|
-
|
|
471
|
-
describe('memory://github/insights', () => {
|
|
472
|
-
it('should return insights with stars and traffic', async () => {
|
|
473
|
-
const github = createMockGitHub()
|
|
474
|
-
const result = await readResource(
|
|
475
|
-
'memory://github/insights',
|
|
476
|
-
db,
|
|
477
|
-
undefined,
|
|
478
|
-
undefined,
|
|
479
|
-
github
|
|
480
|
-
)
|
|
481
|
-
|
|
482
|
-
const data = result.data as {
|
|
483
|
-
repository: string
|
|
484
|
-
stars: number
|
|
485
|
-
forks: number
|
|
486
|
-
clones14d?: number
|
|
487
|
-
views14d?: number
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
expect(data.repository).toBe('testowner/testrepo')
|
|
491
|
-
expect(data.stars).toBe(42)
|
|
492
|
-
expect(data.forks).toBe(7)
|
|
493
|
-
expect(data.clones14d).toBe(120)
|
|
494
|
-
expect(data.views14d).toBe(500)
|
|
495
|
-
})
|
|
496
|
-
|
|
497
|
-
it('should return error when no github', async () => {
|
|
498
|
-
const result = await readResource(
|
|
499
|
-
'memory://github/insights',
|
|
500
|
-
db,
|
|
501
|
-
undefined,
|
|
502
|
-
undefined,
|
|
503
|
-
null
|
|
504
|
-
)
|
|
505
|
-
|
|
506
|
-
const data = result.data as { error: string }
|
|
507
|
-
expect(data.error).toContain('GitHub integration not available')
|
|
508
|
-
})
|
|
509
|
-
|
|
510
|
-
it('should return error when no owner/repo', async () => {
|
|
511
|
-
const github = createMockGitHub({
|
|
512
|
-
getRepoInfo: vi.fn().mockResolvedValue({ owner: null, repo: null, branch: null }),
|
|
513
|
-
})
|
|
514
|
-
|
|
515
|
-
const result = await readResource(
|
|
516
|
-
'memory://github/insights',
|
|
517
|
-
db,
|
|
518
|
-
undefined,
|
|
519
|
-
undefined,
|
|
520
|
-
github
|
|
521
|
-
)
|
|
522
|
-
|
|
523
|
-
const data = result.data as { error: string }
|
|
524
|
-
expect(data.error).toContain('Could not detect repository')
|
|
525
|
-
})
|
|
526
|
-
|
|
527
|
-
it('should handle traffic data failure gracefully', async () => {
|
|
528
|
-
const github = createMockGitHub({
|
|
529
|
-
getTrafficData: vi.fn().mockRejectedValue(new Error('403')),
|
|
530
|
-
})
|
|
531
|
-
|
|
532
|
-
const result = await readResource(
|
|
533
|
-
'memory://github/insights',
|
|
534
|
-
db,
|
|
535
|
-
undefined,
|
|
536
|
-
undefined,
|
|
537
|
-
github
|
|
538
|
-
)
|
|
539
|
-
|
|
540
|
-
const data = result.data as {
|
|
541
|
-
stars: number
|
|
542
|
-
hint?: string
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
expect(data.stars).toBe(42)
|
|
546
|
-
expect(data.hint).toBeDefined()
|
|
547
|
-
})
|
|
548
|
-
})
|
|
549
|
-
|
|
550
|
-
// ========================================================================
|
|
551
|
-
// memory://graph/actions
|
|
552
|
-
// ========================================================================
|
|
553
|
-
|
|
554
|
-
describe('memory://graph/actions', () => {
|
|
555
|
-
it('should return mermaid diagram with workflow runs', async () => {
|
|
556
|
-
const github = createMockGitHub()
|
|
557
|
-
const result = await readResource(
|
|
558
|
-
'memory://graph/actions',
|
|
559
|
-
db,
|
|
560
|
-
undefined,
|
|
561
|
-
undefined,
|
|
562
|
-
github
|
|
563
|
-
)
|
|
564
|
-
|
|
565
|
-
const data = result.data as string
|
|
566
|
-
|
|
567
|
-
expect(typeof data).toBe('string')
|
|
568
|
-
expect(data).toContain('graph LR')
|
|
569
|
-
})
|
|
570
|
-
|
|
571
|
-
it('should return fallback when no github', async () => {
|
|
572
|
-
const result = await readResource(
|
|
573
|
-
'memory://graph/actions',
|
|
574
|
-
db,
|
|
575
|
-
undefined,
|
|
576
|
-
undefined,
|
|
577
|
-
null
|
|
578
|
-
)
|
|
579
|
-
|
|
580
|
-
expect(typeof result.data).toBe('string')
|
|
581
|
-
expect(result.data as string).toContain('NoGitHub')
|
|
582
|
-
})
|
|
583
|
-
|
|
584
|
-
it('should return fallback when no repo detected', async () => {
|
|
585
|
-
const github = createMockGitHub({
|
|
586
|
-
getRepoInfo: vi.fn().mockResolvedValue({ owner: null, repo: null, branch: null }),
|
|
587
|
-
})
|
|
588
|
-
|
|
589
|
-
const result = await readResource(
|
|
590
|
-
'memory://graph/actions',
|
|
591
|
-
db,
|
|
592
|
-
undefined,
|
|
593
|
-
undefined,
|
|
594
|
-
github
|
|
595
|
-
)
|
|
596
|
-
|
|
597
|
-
expect(typeof result.data).toBe('string')
|
|
598
|
-
expect(result.data as string).toContain('NoRepo')
|
|
599
|
-
})
|
|
600
|
-
|
|
601
|
-
it('should return fallback when no workflow runs', async () => {
|
|
602
|
-
const github = createMockGitHub({
|
|
603
|
-
getWorkflowRuns: vi.fn().mockResolvedValue([]),
|
|
604
|
-
})
|
|
605
|
-
|
|
606
|
-
const result = await readResource(
|
|
607
|
-
'memory://graph/actions',
|
|
608
|
-
db,
|
|
609
|
-
undefined,
|
|
610
|
-
undefined,
|
|
611
|
-
github
|
|
612
|
-
)
|
|
613
|
-
|
|
614
|
-
expect(typeof result.data).toBe('string')
|
|
615
|
-
expect(result.data as string).toContain('NoRuns')
|
|
616
|
-
})
|
|
617
|
-
})
|
|
618
|
-
|
|
619
|
-
// ========================================================================
|
|
620
|
-
// memory://actions/recent
|
|
621
|
-
// ========================================================================
|
|
622
|
-
|
|
623
|
-
describe('memory://actions/recent', () => {
|
|
624
|
-
it('should return entries from GitHub API when available', async () => {
|
|
625
|
-
const github = createMockGitHub()
|
|
626
|
-
const result = await readResource(
|
|
627
|
-
'memory://actions/recent',
|
|
628
|
-
db,
|
|
629
|
-
undefined,
|
|
630
|
-
undefined,
|
|
631
|
-
github
|
|
632
|
-
)
|
|
633
|
-
|
|
634
|
-
const data = result.data as {
|
|
635
|
-
entries: unknown[]
|
|
636
|
-
count: number
|
|
637
|
-
source: string
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
expect(data.source).toBe('github_api')
|
|
641
|
-
expect(data.count).toBe(1)
|
|
642
|
-
})
|
|
643
|
-
|
|
644
|
-
it('should fallback to database when no github', async () => {
|
|
645
|
-
const result = await readResource(
|
|
646
|
-
'memory://actions/recent',
|
|
647
|
-
db,
|
|
648
|
-
undefined,
|
|
649
|
-
undefined,
|
|
650
|
-
null
|
|
651
|
-
)
|
|
652
|
-
|
|
653
|
-
const data = result.data as { source: string }
|
|
654
|
-
expect(data.source).toBe('database')
|
|
655
|
-
})
|
|
656
|
-
|
|
657
|
-
it('should fallback to database when github API fails', async () => {
|
|
658
|
-
const github = createMockGitHub({
|
|
659
|
-
getRepoInfo: vi.fn().mockRejectedValue(new Error('API error')),
|
|
660
|
-
})
|
|
661
|
-
|
|
662
|
-
const result = await readResource(
|
|
663
|
-
'memory://actions/recent',
|
|
664
|
-
db,
|
|
665
|
-
undefined,
|
|
666
|
-
undefined,
|
|
667
|
-
github
|
|
668
|
-
)
|
|
669
|
-
|
|
670
|
-
const data = result.data as { source: string }
|
|
671
|
-
expect(data.source).toBe('database')
|
|
672
|
-
})
|
|
673
|
-
})
|
|
674
|
-
|
|
675
|
-
// ========================================================================
|
|
676
|
-
// memory://prs/{n}/timeline
|
|
677
|
-
// ========================================================================
|
|
678
|
-
|
|
679
|
-
describe('memory://prs/{n}/timeline', () => {
|
|
680
|
-
it('should return timeline with PR metadata from GitHub', async () => {
|
|
681
|
-
const github = createMockGitHub({
|
|
682
|
-
getPullRequest: vi.fn().mockResolvedValue({
|
|
683
|
-
number: 10,
|
|
684
|
-
title: 'Feature PR',
|
|
685
|
-
state: 'open',
|
|
686
|
-
draft: false,
|
|
687
|
-
mergedAt: null,
|
|
688
|
-
closedAt: null,
|
|
689
|
-
author: 'dev1',
|
|
690
|
-
headBranch: 'feature',
|
|
691
|
-
baseBranch: 'main',
|
|
692
|
-
}),
|
|
693
|
-
})
|
|
694
|
-
|
|
695
|
-
const result = await readResource(
|
|
696
|
-
'memory://prs/10/timeline',
|
|
697
|
-
db,
|
|
698
|
-
undefined,
|
|
699
|
-
undefined,
|
|
700
|
-
github
|
|
701
|
-
)
|
|
702
|
-
|
|
703
|
-
const data = result.data as {
|
|
704
|
-
prNumber: number
|
|
705
|
-
prMetadata: { title: string; state: string }
|
|
706
|
-
timelineNote: string
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
expect(data.prNumber).toBe(10)
|
|
710
|
-
expect(data.prMetadata).toBeDefined()
|
|
711
|
-
expect(data.prMetadata.title).toBe('Feature PR')
|
|
712
|
-
expect(data.timelineNote).toContain('open')
|
|
713
|
-
})
|
|
714
|
-
|
|
715
|
-
it('should return timeline without PR metadata when no github', async () => {
|
|
716
|
-
const result = await readResource(
|
|
717
|
-
'memory://prs/10/timeline',
|
|
718
|
-
db,
|
|
719
|
-
undefined,
|
|
720
|
-
undefined,
|
|
721
|
-
null
|
|
722
|
-
)
|
|
723
|
-
|
|
724
|
-
const data = result.data as {
|
|
725
|
-
prNumber: number
|
|
726
|
-
prMetadata: unknown
|
|
727
|
-
timelineNote: string
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
expect(data.prNumber).toBe(10)
|
|
731
|
-
expect(data.prMetadata).toBeNull()
|
|
732
|
-
expect(data.timelineNote).toContain('unavailable')
|
|
733
|
-
})
|
|
734
|
-
|
|
735
|
-
it('should return error for invalid PR number', async () => {
|
|
736
|
-
const result = await readResource(
|
|
737
|
-
'memory://prs/abc/timeline',
|
|
738
|
-
db,
|
|
739
|
-
undefined,
|
|
740
|
-
undefined,
|
|
741
|
-
null
|
|
742
|
-
)
|
|
743
|
-
|
|
744
|
-
const data = result.data as { error: string }
|
|
745
|
-
expect(data.error).toContain('Invalid PR number')
|
|
746
|
-
})
|
|
747
|
-
})
|
|
748
|
-
|
|
749
|
-
// ========================================================================
|
|
750
|
-
// memory://health
|
|
751
|
-
// ========================================================================
|
|
752
|
-
|
|
753
|
-
describe('memory://health', () => {
|
|
754
|
-
it('should return health status with vector and scheduler info', async () => {
|
|
755
|
-
const mockVectorManager = {
|
|
756
|
-
getStats: vi.fn().mockReturnValue({
|
|
757
|
-
itemCount: 50,
|
|
758
|
-
modelName: 'test-model',
|
|
759
|
-
dimensions: 384,
|
|
760
|
-
}),
|
|
761
|
-
}
|
|
762
|
-
const mockScheduler = {
|
|
763
|
-
getStatus: vi.fn().mockReturnValue({
|
|
764
|
-
active: true,
|
|
765
|
-
jobs: [{ name: 'backup', intervalMinutes: 60 }],
|
|
766
|
-
}),
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
const result = await readResource(
|
|
770
|
-
'memory://health',
|
|
771
|
-
db,
|
|
772
|
-
mockVectorManager as any,
|
|
773
|
-
null,
|
|
774
|
-
null,
|
|
775
|
-
mockScheduler as any
|
|
776
|
-
)
|
|
777
|
-
|
|
778
|
-
const data = result.data as {
|
|
779
|
-
vectorIndex: { available: boolean; itemCount: number }
|
|
780
|
-
scheduler: { active: boolean }
|
|
781
|
-
toolFilter: { active: boolean }
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
expect(data.vectorIndex).toBeDefined()
|
|
785
|
-
expect(data.vectorIndex.available).toBe(true)
|
|
786
|
-
expect(data.vectorIndex.itemCount).toBe(50)
|
|
787
|
-
expect(data.scheduler.active).toBe(true)
|
|
788
|
-
expect(data.toolFilter.active).toBe(false) // filterConfig is null
|
|
789
|
-
})
|
|
790
|
-
|
|
791
|
-
it('should handle vector manager error gracefully', async () => {
|
|
792
|
-
const mockVectorManager = {
|
|
793
|
-
getStats: vi.fn().mockImplementation(() => {
|
|
794
|
-
throw new Error('Not initialized')
|
|
795
|
-
}),
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
const result = await readResource(
|
|
799
|
-
'memory://health',
|
|
800
|
-
db,
|
|
801
|
-
mockVectorManager as any,
|
|
802
|
-
null,
|
|
803
|
-
null,
|
|
804
|
-
null
|
|
805
|
-
)
|
|
806
|
-
|
|
807
|
-
const data = result.data as {
|
|
808
|
-
vectorIndex: { available: boolean }
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
expect(data.vectorIndex.available).toBe(false)
|
|
812
|
-
})
|
|
813
|
-
})
|
|
814
|
-
|
|
815
|
-
// ========================================================================
|
|
816
|
-
// memory://github/status CI edge cases
|
|
817
|
-
// ========================================================================
|
|
818
|
-
|
|
819
|
-
describe('memory://github/status CI edge cases', () => {
|
|
820
|
-
it('should report failing CI when latest completed run failed', async () => {
|
|
821
|
-
const github = createMockGitHub({
|
|
822
|
-
getWorkflowRuns: vi.fn().mockResolvedValue([
|
|
823
|
-
{
|
|
824
|
-
id: 200,
|
|
825
|
-
name: 'CI',
|
|
826
|
-
status: 'completed',
|
|
827
|
-
conclusion: 'failure',
|
|
828
|
-
url: 'url',
|
|
829
|
-
headBranch: 'main',
|
|
830
|
-
headSha: 'def5678',
|
|
831
|
-
createdAt: '2025-01-02T00:00:00Z',
|
|
832
|
-
updatedAt: '2025-01-02T01:00:00Z',
|
|
833
|
-
},
|
|
834
|
-
]),
|
|
835
|
-
})
|
|
836
|
-
|
|
837
|
-
const result = await readResource(
|
|
838
|
-
'memory://github/status',
|
|
839
|
-
db,
|
|
840
|
-
undefined,
|
|
841
|
-
undefined,
|
|
842
|
-
github
|
|
843
|
-
)
|
|
844
|
-
|
|
845
|
-
const data = result.data as {
|
|
846
|
-
ci: { status: string }
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
expect(data.ci.status).toBe('failing')
|
|
850
|
-
})
|
|
851
|
-
|
|
852
|
-
it('should report pending CI when runs are in progress', async () => {
|
|
853
|
-
const github = createMockGitHub({
|
|
854
|
-
getWorkflowRuns: vi.fn().mockResolvedValue([
|
|
855
|
-
{
|
|
856
|
-
id: 300,
|
|
857
|
-
name: 'CI',
|
|
858
|
-
status: 'in_progress',
|
|
859
|
-
conclusion: null,
|
|
860
|
-
url: 'url',
|
|
861
|
-
headBranch: 'main',
|
|
862
|
-
headSha: 'ghi9012',
|
|
863
|
-
createdAt: '2025-01-03T00:00:00Z',
|
|
864
|
-
updatedAt: '2025-01-03T00:30:00Z',
|
|
865
|
-
},
|
|
866
|
-
]),
|
|
867
|
-
})
|
|
868
|
-
|
|
869
|
-
const result = await readResource(
|
|
870
|
-
'memory://github/status',
|
|
871
|
-
db,
|
|
872
|
-
undefined,
|
|
873
|
-
undefined,
|
|
874
|
-
github
|
|
875
|
-
)
|
|
876
|
-
|
|
877
|
-
const data = result.data as {
|
|
878
|
-
ci: { status: string }
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
expect(data.ci.status).toBe('pending')
|
|
882
|
-
})
|
|
883
|
-
|
|
884
|
-
it('should include kanban summary and milestones in status', async () => {
|
|
885
|
-
const github = createMockGitHub({
|
|
886
|
-
getProjectKanban: vi.fn().mockResolvedValue({
|
|
887
|
-
projectId: 'PVT_1',
|
|
888
|
-
columns: [
|
|
889
|
-
{ status: 'Todo', items: [{ id: 'I1' }, { id: 'I2' }] },
|
|
890
|
-
{ status: 'Done', items: [{ id: 'I3' }] },
|
|
891
|
-
],
|
|
892
|
-
statusOptions: [],
|
|
893
|
-
totalItems: 3,
|
|
894
|
-
}),
|
|
895
|
-
})
|
|
896
|
-
|
|
897
|
-
const result = await readResource(
|
|
898
|
-
'memory://github/status',
|
|
899
|
-
db,
|
|
900
|
-
undefined,
|
|
901
|
-
undefined,
|
|
902
|
-
github,
|
|
903
|
-
undefined,
|
|
904
|
-
undefined,
|
|
905
|
-
{
|
|
906
|
-
entryCount: 3,
|
|
907
|
-
includeTeam: false,
|
|
908
|
-
issueCount: 0,
|
|
909
|
-
prCount: 0,
|
|
910
|
-
prStatusBreakdown: false,
|
|
911
|
-
workflowCount: 0,
|
|
912
|
-
workflowStatusBreakdown: false,
|
|
913
|
-
copilotReviews: false,
|
|
914
|
-
defaultProjectNumber: 1,
|
|
915
|
-
}
|
|
916
|
-
)
|
|
917
|
-
|
|
918
|
-
const data = result.data as {
|
|
919
|
-
kanbanSummary: Record<string, number> | null
|
|
920
|
-
milestones: unknown[] | null
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
expect(data.kanbanSummary).toBeDefined()
|
|
924
|
-
expect(data.kanbanSummary!['Todo']).toBe(2)
|
|
925
|
-
expect(data.kanbanSummary!['Done']).toBe(1)
|
|
926
|
-
expect(data.milestones).toBeDefined()
|
|
927
|
-
})
|
|
928
|
-
})
|
|
929
|
-
})
|