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,510 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool Handler Tests
|
|
3
|
-
*
|
|
4
|
-
* Tests getTools listing, callTool for non-GitHub tools,
|
|
5
|
-
* and Zod output schema validation.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { describe, it, expect, beforeAll, afterAll } from 'vitest'
|
|
9
|
-
import { getTools, callTool } from '../../src/handlers/tools/index.js'
|
|
10
|
-
import { DatabaseAdapter } from '../../src/database/sqlite-adapter/index.js'
|
|
11
|
-
|
|
12
|
-
describe('Tool Handlers', () => {
|
|
13
|
-
let db: DatabaseAdapter
|
|
14
|
-
const testDbPath = './test-tools.db'
|
|
15
|
-
|
|
16
|
-
beforeAll(async () => {
|
|
17
|
-
db = new DatabaseAdapter(testDbPath)
|
|
18
|
-
await db.initialize()
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
afterAll(() => {
|
|
22
|
-
db.close()
|
|
23
|
-
try {
|
|
24
|
-
const fs = require('node:fs')
|
|
25
|
-
if (fs.existsSync(testDbPath)) fs.unlinkSync(testDbPath)
|
|
26
|
-
} catch {
|
|
27
|
-
// Ignore cleanup errors
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
// ========================================================================
|
|
32
|
-
// getTools
|
|
33
|
-
// ========================================================================
|
|
34
|
-
|
|
35
|
-
describe('getTools', () => {
|
|
36
|
-
it('should return all tools when no filter', () => {
|
|
37
|
-
const tools = getTools(db, null)
|
|
38
|
-
expect(tools.length).toBeGreaterThan(30)
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('should have name, description, and inputSchema on each tool', () => {
|
|
42
|
-
const tools = getTools(db, null)
|
|
43
|
-
for (const t of tools) {
|
|
44
|
-
const tool = t as {
|
|
45
|
-
name: string
|
|
46
|
-
description: string
|
|
47
|
-
inputSchema: object
|
|
48
|
-
}
|
|
49
|
-
expect(typeof tool.name).toBe('string')
|
|
50
|
-
expect(typeof tool.description).toBe('string')
|
|
51
|
-
expect(tool.inputSchema).toBeDefined()
|
|
52
|
-
}
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('should have outputSchema on each tool (MCP 2025-11-25)', () => {
|
|
56
|
-
const tools = getTools(db, null)
|
|
57
|
-
for (const t of tools) {
|
|
58
|
-
const tool = t as { name: string; outputSchema?: object }
|
|
59
|
-
// mj_execute_code omits outputSchema (z.unknown() in JSON Schema
|
|
60
|
-
// causes structuredContent processing failures in MCP clients)
|
|
61
|
-
if (tool.name === 'mj_execute_code') continue
|
|
62
|
-
expect(tool.outputSchema).toBeDefined()
|
|
63
|
-
}
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
it('should include known tool names', () => {
|
|
67
|
-
const tools = getTools(db, null)
|
|
68
|
-
const names = tools.map((t) => (t as { name: string }).name)
|
|
69
|
-
|
|
70
|
-
expect(names).toContain('create_entry')
|
|
71
|
-
expect(names).toContain('search_entries')
|
|
72
|
-
expect(names).toContain('get_recent_entries')
|
|
73
|
-
expect(names).toContain('get_statistics')
|
|
74
|
-
expect(names).toContain('link_entries')
|
|
75
|
-
expect(names).toContain('backup_journal')
|
|
76
|
-
})
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
// ========================================================================
|
|
80
|
-
// callTool - core tools
|
|
81
|
-
// ========================================================================
|
|
82
|
-
|
|
83
|
-
describe('callTool - create_entry', () => {
|
|
84
|
-
it('should create a basic entry', async () => {
|
|
85
|
-
const result = (await callTool(
|
|
86
|
-
'create_entry',
|
|
87
|
-
{ content: 'Tool handler test entry' },
|
|
88
|
-
db
|
|
89
|
-
)) as { success: boolean; entry: { id: number; content: string } }
|
|
90
|
-
|
|
91
|
-
expect(result.success).toBe(true)
|
|
92
|
-
expect(result.entry).toBeDefined()
|
|
93
|
-
expect(result.entry.id).toBeGreaterThan(0)
|
|
94
|
-
expect(result.entry.content).toBe('Tool handler test entry')
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
it('should create entry with all fields', async () => {
|
|
98
|
-
const result = (await callTool(
|
|
99
|
-
'create_entry',
|
|
100
|
-
{
|
|
101
|
-
content: 'Full tool entry',
|
|
102
|
-
entry_type: 'project_decision',
|
|
103
|
-
tags: ['tool-tag-a', 'tool-tag-b'],
|
|
104
|
-
is_personal: false,
|
|
105
|
-
significance_type: 'milestone',
|
|
106
|
-
},
|
|
107
|
-
db
|
|
108
|
-
)) as { success: boolean; entry: { entryType: string; tags: string[] } }
|
|
109
|
-
|
|
110
|
-
expect(result.success).toBe(true)
|
|
111
|
-
expect(result.entry.entryType).toBe('project_decision')
|
|
112
|
-
expect(result.entry.tags).toContain('tool-tag-a')
|
|
113
|
-
})
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
describe('callTool - create_entry_minimal', () => {
|
|
117
|
-
it('should create a minimal entry', async () => {
|
|
118
|
-
const result = (await callTool(
|
|
119
|
-
'create_entry_minimal',
|
|
120
|
-
{ content: 'Quick note' },
|
|
121
|
-
db
|
|
122
|
-
)) as { success: boolean; entry: { content: string } }
|
|
123
|
-
|
|
124
|
-
expect(result.success).toBe(true)
|
|
125
|
-
expect(result.entry.content).toBe('Quick note')
|
|
126
|
-
})
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
describe('callTool - get_entry_by_id', () => {
|
|
130
|
-
it('should retrieve an entry by ID', async () => {
|
|
131
|
-
const created = (await callTool(
|
|
132
|
-
'create_entry',
|
|
133
|
-
{ content: 'Retrievable entry' },
|
|
134
|
-
db
|
|
135
|
-
)) as { entry: { id: number } }
|
|
136
|
-
|
|
137
|
-
const result = (await callTool(
|
|
138
|
-
'get_entry_by_id',
|
|
139
|
-
{ entry_id: created.entry.id },
|
|
140
|
-
db
|
|
141
|
-
)) as { entry: { content: string }; importance: number }
|
|
142
|
-
|
|
143
|
-
expect(result.entry.content).toBe('Retrievable entry')
|
|
144
|
-
expect(typeof result.importance).toBe('number')
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
it('should return error for nonexistent entry', async () => {
|
|
148
|
-
const result = (await callTool('get_entry_by_id', { entry_id: 99999 }, db)) as {
|
|
149
|
-
error: string
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
expect(result.error).toContain('not found')
|
|
153
|
-
})
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
describe('callTool - get_recent_entries', () => {
|
|
157
|
-
it('should return recent entries', async () => {
|
|
158
|
-
const result = (await callTool('get_recent_entries', { limit: 3 }, db)) as {
|
|
159
|
-
entries: unknown[]
|
|
160
|
-
count: number
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
expect(result.entries.length).toBeLessThanOrEqual(3)
|
|
164
|
-
expect(result.count).toBeGreaterThan(0)
|
|
165
|
-
})
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
describe('callTool - test_simple', () => {
|
|
169
|
-
it('should echo message back', async () => {
|
|
170
|
-
const result = (await callTool('test_simple', { message: 'ping' }, db)) as {
|
|
171
|
-
message: string
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
expect(result.message).toContain('ping')
|
|
175
|
-
})
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
// ========================================================================
|
|
179
|
-
// callTool - search tools
|
|
180
|
-
// ========================================================================
|
|
181
|
-
|
|
182
|
-
describe('callTool - search_entries', () => {
|
|
183
|
-
it('should search by content', async () => {
|
|
184
|
-
await callTool('create_entry', { content: 'Unique unicorn xyz99' }, db)
|
|
185
|
-
|
|
186
|
-
const result = (await callTool('search_entries', { query: 'xyz99', limit: 5 }, db)) as {
|
|
187
|
-
entries: unknown[]
|
|
188
|
-
count: number
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
expect(result.count).toBeGreaterThan(0)
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
it('should return empty for non-matching query', async () => {
|
|
195
|
-
const result = (await callTool(
|
|
196
|
-
'search_entries',
|
|
197
|
-
{ query: 'nonexistent_term_abcxyz', limit: 5 },
|
|
198
|
-
db
|
|
199
|
-
)) as { entries: unknown[]; count: number }
|
|
200
|
-
|
|
201
|
-
expect(result.count).toBe(0)
|
|
202
|
-
})
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
describe('callTool - search_by_date_range', () => {
|
|
206
|
-
it('should search by date range', async () => {
|
|
207
|
-
const today = new Date()
|
|
208
|
-
const tomorrow = new Date(today)
|
|
209
|
-
tomorrow.setDate(tomorrow.getDate() + 1)
|
|
210
|
-
const todayStr = today.toISOString().split('T')[0]!
|
|
211
|
-
const tomorrowStr = tomorrow.toISOString().split('T')[0]!
|
|
212
|
-
|
|
213
|
-
// Ensure an entry exists today
|
|
214
|
-
await callTool('create_entry', { content: 'Date range test entry' }, db)
|
|
215
|
-
|
|
216
|
-
const result = (await callTool(
|
|
217
|
-
'search_by_date_range',
|
|
218
|
-
{ start_date: todayStr, end_date: tomorrowStr },
|
|
219
|
-
db
|
|
220
|
-
)) as { entries: unknown[]; count: number }
|
|
221
|
-
|
|
222
|
-
expect(result.count).toBeGreaterThan(0)
|
|
223
|
-
})
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
// ========================================================================
|
|
227
|
-
// callTool - analytics tools
|
|
228
|
-
// ========================================================================
|
|
229
|
-
|
|
230
|
-
describe('callTool - get_statistics', () => {
|
|
231
|
-
it('should return statistics', async () => {
|
|
232
|
-
const result = (await callTool('get_statistics', {}, db)) as {
|
|
233
|
-
groupBy: string
|
|
234
|
-
totalEntries: number
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
expect(result.totalEntries).toBeGreaterThan(0)
|
|
238
|
-
expect(result.groupBy).toBe('week')
|
|
239
|
-
})
|
|
240
|
-
|
|
241
|
-
it('should accept group_by parameter', async () => {
|
|
242
|
-
const result = (await callTool('get_statistics', { group_by: 'day' }, db)) as {
|
|
243
|
-
groupBy: string
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
expect(result.groupBy).toBe('day')
|
|
247
|
-
})
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
// ========================================================================
|
|
251
|
-
// callTool - relationship tools
|
|
252
|
-
// ========================================================================
|
|
253
|
-
|
|
254
|
-
describe('callTool - link_entries', () => {
|
|
255
|
-
it('should link two entries', async () => {
|
|
256
|
-
const e1 = (await callTool('create_entry', { content: 'Link source' }, db)) as {
|
|
257
|
-
entry: { id: number }
|
|
258
|
-
}
|
|
259
|
-
const e2 = (await callTool('create_entry', { content: 'Link target' }, db)) as {
|
|
260
|
-
entry: { id: number }
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const result = (await callTool(
|
|
264
|
-
'link_entries',
|
|
265
|
-
{
|
|
266
|
-
from_entry_id: e1.entry.id,
|
|
267
|
-
to_entry_id: e2.entry.id,
|
|
268
|
-
relationship_type: 'references',
|
|
269
|
-
description: 'Test link',
|
|
270
|
-
},
|
|
271
|
-
db
|
|
272
|
-
)) as { success: boolean; relationship: { relationshipType: string } }
|
|
273
|
-
|
|
274
|
-
expect(result.success).toBe(true)
|
|
275
|
-
expect(result.relationship.relationshipType).toBe('references')
|
|
276
|
-
})
|
|
277
|
-
|
|
278
|
-
it('should return failure for nonexistent entry', async () => {
|
|
279
|
-
const result = (await callTool(
|
|
280
|
-
'link_entries',
|
|
281
|
-
{
|
|
282
|
-
from_entry_id: 99999,
|
|
283
|
-
to_entry_id: 99998,
|
|
284
|
-
relationship_type: 'references',
|
|
285
|
-
},
|
|
286
|
-
db
|
|
287
|
-
)) as { success: boolean; message?: string }
|
|
288
|
-
|
|
289
|
-
expect(result.success).toBe(false)
|
|
290
|
-
})
|
|
291
|
-
})
|
|
292
|
-
|
|
293
|
-
// ========================================================================
|
|
294
|
-
// callTool - admin tools
|
|
295
|
-
// ========================================================================
|
|
296
|
-
|
|
297
|
-
describe('callTool - update_entry', () => {
|
|
298
|
-
it('should update entry content', async () => {
|
|
299
|
-
const created = (await callTool(
|
|
300
|
-
'create_entry',
|
|
301
|
-
{ content: 'Original content' },
|
|
302
|
-
db
|
|
303
|
-
)) as { entry: { id: number } }
|
|
304
|
-
|
|
305
|
-
const result = (await callTool(
|
|
306
|
-
'update_entry',
|
|
307
|
-
{ entry_id: created.entry.id, content: 'Updated content' },
|
|
308
|
-
db
|
|
309
|
-
)) as { success: boolean; entry: { content: string } }
|
|
310
|
-
|
|
311
|
-
expect(result.success).toBe(true)
|
|
312
|
-
expect(result.entry.content).toBe('Updated content')
|
|
313
|
-
})
|
|
314
|
-
})
|
|
315
|
-
|
|
316
|
-
describe('callTool - delete_entry', () => {
|
|
317
|
-
it('should soft delete an entry', async () => {
|
|
318
|
-
const created = (await callTool('create_entry', { content: 'To be deleted' }, db)) as {
|
|
319
|
-
entry: { id: number }
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
const result = (await callTool('delete_entry', { entry_id: created.entry.id }, db)) as {
|
|
323
|
-
success: boolean
|
|
324
|
-
entryId: number
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
expect(result.success).toBe(true)
|
|
328
|
-
expect(result.entryId).toBe(created.entry.id)
|
|
329
|
-
})
|
|
330
|
-
|
|
331
|
-
it('should return error for nonexistent entry', async () => {
|
|
332
|
-
const result = (await callTool('delete_entry', { entry_id: 99999 }, db)) as {
|
|
333
|
-
success: boolean
|
|
334
|
-
error: string
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
expect(result.success).toBe(false)
|
|
338
|
-
expect(result.error).toContain('not found')
|
|
339
|
-
})
|
|
340
|
-
})
|
|
341
|
-
|
|
342
|
-
// ========================================================================
|
|
343
|
-
// callTool - tag tools
|
|
344
|
-
// ========================================================================
|
|
345
|
-
|
|
346
|
-
describe('callTool - list_tags', () => {
|
|
347
|
-
it('should list tags with usage counts', async () => {
|
|
348
|
-
const result = (await callTool('list_tags', {}, db)) as {
|
|
349
|
-
tags: { name: string; count: number }[]
|
|
350
|
-
count: number
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
expect(result.tags).toBeDefined()
|
|
354
|
-
expect(result.count).toBeGreaterThan(0)
|
|
355
|
-
})
|
|
356
|
-
})
|
|
357
|
-
|
|
358
|
-
describe('callTool - merge_tags', () => {
|
|
359
|
-
it('should merge tags', async () => {
|
|
360
|
-
await callTool('create_entry', { content: 'Merge tag source', tags: ['merge-src'] }, db)
|
|
361
|
-
|
|
362
|
-
const result = (await callTool(
|
|
363
|
-
'merge_tags',
|
|
364
|
-
{ source_tag: 'merge-src', target_tag: 'merge-tgt' },
|
|
365
|
-
db
|
|
366
|
-
)) as { success: boolean; message: string }
|
|
367
|
-
|
|
368
|
-
expect(result.success).toBe(true)
|
|
369
|
-
expect(result.message).toContain('Merged')
|
|
370
|
-
})
|
|
371
|
-
})
|
|
372
|
-
|
|
373
|
-
// ========================================================================
|
|
374
|
-
// callTool - export tools
|
|
375
|
-
// ========================================================================
|
|
376
|
-
|
|
377
|
-
describe('callTool - export_entries', () => {
|
|
378
|
-
it('should export as JSON', async () => {
|
|
379
|
-
const result = (await callTool('export_entries', { format: 'json' }, db)) as {
|
|
380
|
-
format: string
|
|
381
|
-
entries: unknown[]
|
|
382
|
-
count: number
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
expect(result.format).toBe('json')
|
|
386
|
-
expect(result.entries.length).toBeGreaterThan(0)
|
|
387
|
-
expect(result.count).toBe(result.entries.length)
|
|
388
|
-
})
|
|
389
|
-
|
|
390
|
-
it('should export as markdown', async () => {
|
|
391
|
-
const result = (await callTool('export_entries', { format: 'markdown' }, db)) as {
|
|
392
|
-
format: string
|
|
393
|
-
content: string
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
expect(result.format).toBe('markdown')
|
|
397
|
-
expect(result.content.length).toBeGreaterThan(0)
|
|
398
|
-
})
|
|
399
|
-
})
|
|
400
|
-
|
|
401
|
-
// ========================================================================
|
|
402
|
-
// callTool - backup tools
|
|
403
|
-
// ========================================================================
|
|
404
|
-
|
|
405
|
-
describe('callTool - backup_journal', () => {
|
|
406
|
-
it('should create a backup', async () => {
|
|
407
|
-
const result = (await callTool('backup_journal', { name: 'test-tool-backup' }, db)) as {
|
|
408
|
-
success: boolean
|
|
409
|
-
filename: string
|
|
410
|
-
path: string
|
|
411
|
-
sizeBytes: number
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
expect(result.success).toBe(true)
|
|
415
|
-
expect(result.filename).toContain('test-tool-backup')
|
|
416
|
-
|
|
417
|
-
// Cleanup backup file
|
|
418
|
-
try {
|
|
419
|
-
const fs = require('node:fs')
|
|
420
|
-
if (fs.existsSync(result.path)) {
|
|
421
|
-
fs.unlinkSync(result.path)
|
|
422
|
-
}
|
|
423
|
-
} catch {
|
|
424
|
-
// Ignore cleanup
|
|
425
|
-
}
|
|
426
|
-
})
|
|
427
|
-
})
|
|
428
|
-
|
|
429
|
-
describe('callTool - list_backups', () => {
|
|
430
|
-
it('should list backups', async () => {
|
|
431
|
-
const result = (await callTool('list_backups', {}, db)) as {
|
|
432
|
-
backups: unknown[]
|
|
433
|
-
total: number
|
|
434
|
-
backupsDirectory: string
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
expect(result.backups).toBeDefined()
|
|
438
|
-
expect(typeof result.total).toBe('number')
|
|
439
|
-
expect(result.backupsDirectory).toBeDefined()
|
|
440
|
-
})
|
|
441
|
-
})
|
|
442
|
-
|
|
443
|
-
// ========================================================================
|
|
444
|
-
// callTool - unknown tool
|
|
445
|
-
// ========================================================================
|
|
446
|
-
|
|
447
|
-
describe('callTool - error handling', () => {
|
|
448
|
-
it('should throw for unknown tool', async () => {
|
|
449
|
-
await expect(callTool('nonexistent_tool', {}, db)).rejects.toThrow('Unknown tool')
|
|
450
|
-
})
|
|
451
|
-
})
|
|
452
|
-
|
|
453
|
-
// ========================================================================
|
|
454
|
-
// callTool - visualize_relationships
|
|
455
|
-
// ========================================================================
|
|
456
|
-
|
|
457
|
-
describe('callTool - visualize_relationships', () => {
|
|
458
|
-
it('should generate mermaid diagram', async () => {
|
|
459
|
-
const e1 = (await callTool('create_entry', { content: 'Viz entry A' }, db)) as {
|
|
460
|
-
entry: { id: number }
|
|
461
|
-
}
|
|
462
|
-
const e2 = (await callTool('create_entry', { content: 'Viz entry B' }, db)) as {
|
|
463
|
-
entry: { id: number }
|
|
464
|
-
}
|
|
465
|
-
await callTool(
|
|
466
|
-
'link_entries',
|
|
467
|
-
{
|
|
468
|
-
from_entry_id: e1.entry.id,
|
|
469
|
-
to_entry_id: e2.entry.id,
|
|
470
|
-
relationship_type: 'implements',
|
|
471
|
-
},
|
|
472
|
-
db
|
|
473
|
-
)
|
|
474
|
-
|
|
475
|
-
const result = (await callTool(
|
|
476
|
-
'visualize_relationships',
|
|
477
|
-
{ entry_id: e1.entry.id },
|
|
478
|
-
db
|
|
479
|
-
)) as { mermaid: string | null; entry_count: number }
|
|
480
|
-
|
|
481
|
-
expect(result.entry_count).toBeGreaterThan(0)
|
|
482
|
-
})
|
|
483
|
-
})
|
|
484
|
-
|
|
485
|
-
// ========================================================================
|
|
486
|
-
// callTool - cross project insights
|
|
487
|
-
// ========================================================================
|
|
488
|
-
|
|
489
|
-
describe('callTool - get_cross_project_insights', () => {
|
|
490
|
-
it('should return insights structure', async () => {
|
|
491
|
-
// Need project entries for insights
|
|
492
|
-
await callTool('create_entry', { content: 'Insight entry 1', project_number: 100 }, db)
|
|
493
|
-
await callTool('create_entry', { content: 'Insight entry 2', project_number: 100 }, db)
|
|
494
|
-
await callTool('create_entry', { content: 'Insight entry 3', project_number: 100 }, db)
|
|
495
|
-
|
|
496
|
-
const result = (await callTool(
|
|
497
|
-
'get_cross_project_insights',
|
|
498
|
-
{ min_entries: 1 },
|
|
499
|
-
db
|
|
500
|
-
)) as {
|
|
501
|
-
project_count: number
|
|
502
|
-
total_entries: number
|
|
503
|
-
projects: unknown[]
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
expect(result.project_count).toBeGreaterThan(0)
|
|
507
|
-
expect(result.total_entries).toBeGreaterThan(0)
|
|
508
|
-
})
|
|
509
|
-
})
|
|
510
|
-
})
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool Output Schemas Invariant Test
|
|
3
|
-
*
|
|
4
|
-
* Structural enforcement: verifies every tool has an outputSchema,
|
|
5
|
-
* error responses pass outputSchema validation, and ErrorFieldsMixin
|
|
6
|
-
* is properly wired.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { describe, it, expect } from 'vitest'
|
|
10
|
-
import { getTools } from '../../src/handlers/tools/index.js'
|
|
11
|
-
import { DatabaseAdapterFactory } from '../../src/database/adapter-factory.js'
|
|
12
|
-
import { ErrorFieldsMixin } from '../../src/handlers/tools/error-fields-mixin.js'
|
|
13
|
-
import path from 'node:path'
|
|
14
|
-
import os from 'node:os'
|
|
15
|
-
import fs from 'node:fs'
|
|
16
|
-
import type { z } from 'zod'
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Tools that intentionally omit outputSchema.
|
|
20
|
-
* mj_execute_code: bare {} JSON Schema crashes clients that process structuredContent.
|
|
21
|
-
*/
|
|
22
|
-
const OUTPUT_SCHEMA_EXCLUSIONS = new Set(['mj_execute_code'])
|
|
23
|
-
|
|
24
|
-
describe('Tool Output Schemas Invariant', () => {
|
|
25
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mj-invariant-'))
|
|
26
|
-
const dbPath = path.join(tmpDir, 'test-schemas.db')
|
|
27
|
-
|
|
28
|
-
let tools: ReturnType<typeof getTools>
|
|
29
|
-
|
|
30
|
-
it('should load all tools', async () => {
|
|
31
|
-
const db = await DatabaseAdapterFactory.create(dbPath)
|
|
32
|
-
await db.initialize()
|
|
33
|
-
tools = getTools(db, null)
|
|
34
|
-
expect(tools.length).toBeGreaterThan(0)
|
|
35
|
-
db.close()
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('every tool (except known exclusions) must have an outputSchema', () => {
|
|
39
|
-
const missing = tools.filter(
|
|
40
|
-
(t) => t.outputSchema === undefined && !OUTPUT_SCHEMA_EXCLUSIONS.has(t.name)
|
|
41
|
-
)
|
|
42
|
-
expect(
|
|
43
|
-
missing.length,
|
|
44
|
-
`Tools missing outputSchema: ${missing.map((t) => t.name).join(', ')}`
|
|
45
|
-
).toBe(0)
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
it('error response must pass outputSchema (tools with only ErrorFieldsMixin required fields)', () => {
|
|
49
|
-
const errorResponse = {
|
|
50
|
-
success: false,
|
|
51
|
-
error: 'Test error',
|
|
52
|
-
code: 'INTERNAL_ERROR',
|
|
53
|
-
category: 'internal',
|
|
54
|
-
recoverable: false,
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Track tools that fail and WHY — differentiate between mixin issues
|
|
58
|
-
// (real bugs) and tools with extra required fields (acceptable).
|
|
59
|
-
const mixinFailures: string[] = []
|
|
60
|
-
|
|
61
|
-
for (const tool of tools) {
|
|
62
|
-
if (!tool.outputSchema || OUTPUT_SCHEMA_EXCLUSIONS.has(tool.name)) continue
|
|
63
|
-
const schema = tool.outputSchema as z.ZodType
|
|
64
|
-
const result = schema.safeParse(errorResponse)
|
|
65
|
-
if (!result.success) {
|
|
66
|
-
// Check if every issue path is OUTSIDE ErrorFieldsMixin shape
|
|
67
|
-
const mixinKeys = new Set([
|
|
68
|
-
'success',
|
|
69
|
-
'error',
|
|
70
|
-
'code',
|
|
71
|
-
'category',
|
|
72
|
-
'recoverable',
|
|
73
|
-
'suggestion',
|
|
74
|
-
])
|
|
75
|
-
const hasMixinFailure = result.error.issues.some(
|
|
76
|
-
(issue) => issue.path.length === 1 && mixinKeys.has(String(issue.path[0]))
|
|
77
|
-
)
|
|
78
|
-
if (hasMixinFailure) {
|
|
79
|
-
mixinFailures.push(tool.name)
|
|
80
|
-
}
|
|
81
|
-
// else: tool has extra required fields beyond ErrorFieldsMixin — acceptable
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
expect(
|
|
86
|
-
mixinFailures.length,
|
|
87
|
-
`ErrorFieldsMixin fields rejected by outputSchema: ${mixinFailures.join(', ')}`
|
|
88
|
-
).toBe(0)
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
it('ErrorFieldsMixin fields must be present in every outputSchema', () => {
|
|
92
|
-
const mixinKeys = Object.keys(ErrorFieldsMixin.shape)
|
|
93
|
-
|
|
94
|
-
for (const tool of tools) {
|
|
95
|
-
if (!tool.outputSchema) continue
|
|
96
|
-
const schema = tool.outputSchema as z.ZodObject<Record<string, z.ZodType>>
|
|
97
|
-
if (typeof schema.shape !== 'object') continue
|
|
98
|
-
|
|
99
|
-
for (const key of mixinKeys) {
|
|
100
|
-
expect(
|
|
101
|
-
key in schema.shape,
|
|
102
|
-
`Tool "${tool.name}" outputSchema missing ErrorFieldsMixin field: ${key}`
|
|
103
|
-
).toBe(true)
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
// Cleanup
|
|
109
|
-
it('cleanup', () => {
|
|
110
|
-
try {
|
|
111
|
-
fs.rmSync(tmpDir, { recursive: true })
|
|
112
|
-
} catch {
|
|
113
|
-
// Best-effort cleanup
|
|
114
|
-
}
|
|
115
|
-
})
|
|
116
|
-
})
|