@stackmemoryai/stackmemory 0.2.7 → 0.2.8
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 +25 -8
- package/dist/scripts/cancel-duplicate-tasks.js +2 -1
- package/dist/scripts/cancel-duplicate-tasks.js.map +1 -1
- package/dist/scripts/list-linear-tasks.js +3 -4
- package/dist/scripts/list-linear-tasks.js.map +1 -1
- package/dist/scripts/merge-linear-duplicates-safe.js +4 -2
- package/dist/scripts/merge-linear-duplicates-safe.js.map +1 -1
- package/dist/scripts/show-linear-summary.js +4 -1
- package/dist/scripts/show-linear-summary.js.map +1 -1
- package/dist/scripts/status.js +6 -2
- package/dist/scripts/status.js.map +1 -1
- package/dist/src/cli/auto-detect.js.map +1 -1
- package/dist/src/cli/claude-sm.js.map +1 -1
- package/dist/src/cli/commands/config.d.ts +6 -0
- package/dist/src/cli/commands/config.d.ts.map +1 -0
- package/dist/src/cli/commands/config.js +224 -0
- package/dist/src/cli/commands/config.js.map +1 -0
- package/dist/src/cli/commands/linear.d.ts.map +1 -1
- package/dist/src/cli/commands/linear.js +123 -47
- package/dist/src/cli/commands/linear.js.map +1 -1
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +48 -1
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/core/config/config-manager.d.ts +95 -0
- package/dist/src/core/config/config-manager.d.ts.map +1 -0
- package/dist/src/core/config/config-manager.js +359 -0
- package/dist/src/core/config/config-manager.js.map +1 -0
- package/dist/src/core/config/types.d.ts +72 -0
- package/dist/src/core/config/types.d.ts.map +1 -0
- package/dist/src/core/config/types.js +127 -0
- package/dist/src/core/config/types.js.map +1 -0
- package/dist/src/core/context/compaction-handler.d.ts +119 -0
- package/dist/src/core/context/compaction-handler.d.ts.map +1 -0
- package/dist/src/core/context/compaction-handler.js +306 -0
- package/dist/src/core/context/compaction-handler.js.map +1 -0
- package/dist/src/core/context/model-aware-compaction.d.ts +101 -0
- package/dist/src/core/context/model-aware-compaction.d.ts.map +1 -0
- package/dist/src/core/context/model-aware-compaction.js +616 -0
- package/dist/src/core/context/model-aware-compaction.js.map +1 -0
- package/dist/src/core/query/query-parser.d.ts +104 -0
- package/dist/src/core/query/query-parser.d.ts.map +1 -0
- package/dist/src/core/query/query-parser.js +347 -0
- package/dist/src/core/query/query-parser.js.map +1 -0
- package/dist/src/core/retrieval/index.d.ts +8 -0
- package/dist/src/core/retrieval/index.d.ts.map +1 -0
- package/dist/src/core/retrieval/index.js +8 -0
- package/dist/src/core/retrieval/index.js.map +1 -0
- package/dist/src/core/retrieval/llm-context-retrieval.d.ts +71 -0
- package/dist/src/core/retrieval/llm-context-retrieval.d.ts.map +1 -0
- package/dist/src/core/retrieval/llm-context-retrieval.js +545 -0
- package/dist/src/core/retrieval/llm-context-retrieval.js.map +1 -0
- package/dist/src/core/retrieval/summary-generator.d.ts +63 -0
- package/dist/src/core/retrieval/summary-generator.d.ts.map +1 -0
- package/dist/src/core/retrieval/summary-generator.js +622 -0
- package/dist/src/core/retrieval/summary-generator.js.map +1 -0
- package/dist/src/core/retrieval/types.d.ts +257 -0
- package/dist/src/core/retrieval/types.d.ts.map +1 -0
- package/dist/src/core/retrieval/types.js +18 -0
- package/dist/src/core/retrieval/types.js.map +1 -0
- package/dist/src/core/trace/trace-detector.d.ts +108 -0
- package/dist/src/core/trace/trace-detector.d.ts.map +1 -0
- package/dist/src/core/trace/trace-detector.demo.d.ts +5 -0
- package/dist/src/core/trace/trace-detector.demo.d.ts.map +1 -0
- package/dist/src/core/trace/trace-detector.demo.js +145 -0
- package/dist/src/core/trace/trace-detector.demo.js.map +1 -0
- package/dist/src/core/trace/trace-detector.js +425 -0
- package/dist/src/core/trace/trace-detector.js.map +1 -0
- package/dist/src/core/trace/trace-store.d.ts +60 -0
- package/dist/src/core/trace/trace-store.d.ts.map +1 -0
- package/dist/src/core/trace/trace-store.js +323 -0
- package/dist/src/core/trace/trace-store.js.map +1 -0
- package/dist/src/core/trace/types.d.ts +81 -0
- package/dist/src/core/trace/types.d.ts.map +1 -0
- package/dist/src/core/trace/types.js +70 -0
- package/dist/src/core/trace/types.js.map +1 -0
- package/dist/src/integrations/linear/sync-manager.d.ts +76 -0
- package/dist/src/integrations/linear/sync-manager.d.ts.map +1 -0
- package/dist/src/integrations/linear/sync-manager.js +223 -0
- package/dist/src/integrations/linear/sync-manager.js.map +1 -0
- package/dist/src/integrations/mcp/server.d.ts +8 -0
- package/dist/src/integrations/mcp/server.d.ts.map +1 -1
- package/dist/src/integrations/mcp/server.js +368 -16
- package/dist/src/integrations/mcp/server.js.map +1 -1
- package/dist/src/integrations/mcp/trace-test.d.ts +5 -0
- package/dist/src/integrations/mcp/trace-test.d.ts.map +1 -0
- package/dist/src/integrations/mcp/trace-test.js +54 -0
- package/dist/src/integrations/mcp/trace-test.js.map +1 -0
- package/dist/src/services/config-service.d.ts +1 -1
- package/dist/src/services/config-service.d.ts.map +1 -1
- package/dist/src/services/config-service.js.map +1 -1
- package/dist/src/types/task.d.ts +11 -1
- package/dist/src/types/task.d.ts.map +1 -1
- package/dist/src/utils/logger.d.ts +4 -4
- package/dist/src/utils/logger.d.ts.map +1 -1
- package/dist/src/utils/logger.js.map +1 -1
- package/package.json +9 -8
- package/dist/attention-scoring/src/attention-tracker.d.ts +0 -79
- package/dist/attention-scoring/src/attention-tracker.d.ts.map +0 -1
- package/dist/attention-scoring/src/attention-tracker.js +0 -488
- package/dist/attention-scoring/src/attention-tracker.js.map +0 -1
- package/dist/attention-scoring/src/mcp-integration.d.ts +0 -56
- package/dist/attention-scoring/src/mcp-integration.d.ts.map +0 -1
- package/dist/attention-scoring/src/mcp-integration.js +0 -369
- package/dist/attention-scoring/src/mcp-integration.js.map +0 -1
- package/dist/index.js +0 -382
- package/dist/p2p-sync/src/p2p-sync.d.ts +0 -81
- package/dist/p2p-sync/src/p2p-sync.d.ts.map +0 -1
- package/dist/p2p-sync/src/p2p-sync.js +0 -457
- package/dist/p2p-sync/src/p2p-sync.js.map +0 -1
- package/dist/p2p-sync/src/team-context-sync.d.ts +0 -99
- package/dist/p2p-sync/src/team-context-sync.d.ts.map +0 -1
- package/dist/p2p-sync/src/team-context-sync.js +0 -491
- package/dist/p2p-sync/src/team-context-sync.js.map +0 -1
- package/dist/scripts/merge-linear-duplicates.d.ts +0 -7
- package/dist/scripts/merge-linear-duplicates.d.ts.map +0 -1
- package/dist/scripts/merge-linear-duplicates.js +0 -126
- package/dist/scripts/merge-linear-duplicates.js.map +0 -1
- package/dist/src/analytics/api/analytics-api.d.ts +0 -24
- package/dist/src/analytics/api/analytics-api.d.ts.map +0 -1
- package/dist/src/analytics/api/analytics-api.js +0 -279
- package/dist/src/analytics/api/analytics-api.js.map +0 -1
- package/dist/src/analytics/core/analytics-service.d.ts +0 -23
- package/dist/src/analytics/core/analytics-service.d.ts.map +0 -1
- package/dist/src/analytics/core/analytics-service.js +0 -160
- package/dist/src/analytics/core/analytics-service.js.map +0 -1
- package/dist/src/analytics/index.d.ts +0 -12
- package/dist/src/analytics/index.d.ts.map +0 -1
- package/dist/src/analytics/index.js +0 -11
- package/dist/src/analytics/index.js.map +0 -1
- package/dist/src/analytics/queries/metrics-queries.d.ts +0 -11
- package/dist/src/analytics/queries/metrics-queries.d.ts.map +0 -1
- package/dist/src/analytics/queries/metrics-queries.js +0 -179
- package/dist/src/analytics/queries/metrics-queries.js.map +0 -1
- package/dist/src/analytics/types/metrics.d.ts +0 -60
- package/dist/src/analytics/types/metrics.d.ts.map +0 -1
- package/dist/src/analytics/types/metrics.js +0 -2
- package/dist/src/analytics/types/metrics.js.map +0 -1
- package/dist/src/beads/beads-task-store.d.ts +0 -117
- package/dist/src/beads/beads-task-store.d.ts.map +0 -1
- package/dist/src/beads/beads-task-store.js +0 -318
- package/dist/src/beads/beads-task-store.js.map +0 -1
- package/dist/src/beads/task-aware-context.d.ts +0 -103
- package/dist/src/beads/task-aware-context.d.ts.map +0 -1
- package/dist/src/beads/task-aware-context.js +0 -395
- package/dist/src/beads/task-aware-context.js.map +0 -1
- package/dist/src/beads-task-store.d.ts +0 -117
- package/dist/src/beads-task-store.d.ts.map +0 -1
- package/dist/src/beads-task-store.js +0 -318
- package/dist/src/beads-task-store.js.map +0 -1
- package/dist/src/cli/__tests__/index.test.d.ts +0 -5
- package/dist/src/cli/__tests__/index.test.d.ts.map +0 -1
- package/dist/src/cli/__tests__/index.test.js +0 -726
- package/dist/src/cli/__tests__/index.test.js.map +0 -1
- package/dist/src/cli/analytics-viewer.d.ts +0 -3
- package/dist/src/cli/analytics-viewer.d.ts.map +0 -1
- package/dist/src/cli/analytics-viewer.js +0 -89
- package/dist/src/cli/analytics-viewer.js.map +0 -1
- package/dist/src/cli/cli.d.ts +0 -7
- package/dist/src/cli/cli.d.ts.map +0 -1
- package/dist/src/cli/cli.js +0 -704
- package/dist/src/cli/cli.js.map +0 -1
- package/dist/src/cli/project-commands.d.ts +0 -8
- package/dist/src/cli/project-commands.d.ts.map +0 -1
- package/dist/src/cli/project-commands.js +0 -212
- package/dist/src/cli/project-commands.js.map +0 -1
- package/dist/src/cli.d.ts +0 -7
- package/dist/src/cli.d.ts.map +0 -1
- package/dist/src/cli.js +0 -73
- package/dist/src/cli.js.map +0 -1
- package/dist/src/core/context/__tests__/frame-manager.test.d.ts +0 -5
- package/dist/src/core/context/__tests__/frame-manager.test.d.ts.map +0 -1
- package/dist/src/core/context/__tests__/frame-manager.test.js +0 -892
- package/dist/src/core/context/__tests__/frame-manager.test.js.map +0 -1
- package/dist/src/core/error-handler.d.ts +0 -46
- package/dist/src/core/error-handler.d.ts.map +0 -1
- package/dist/src/core/error-handler.js +0 -212
- package/dist/src/core/error-handler.js.map +0 -1
- package/dist/src/core/errors/__tests__/error-handling.test.d.ts +0 -5
- package/dist/src/core/errors/__tests__/error-handling.test.d.ts.map +0 -1
- package/dist/src/core/errors/__tests__/error-handling.test.js +0 -239
- package/dist/src/core/errors/__tests__/error-handling.test.js.map +0 -1
- package/dist/src/core/frame-manager.d.ts +0 -106
- package/dist/src/core/frame-manager.d.ts.map +0 -1
- package/dist/src/core/frame-manager.js +0 -387
- package/dist/src/core/frame-manager.js.map +0 -1
- package/dist/src/core/logger.d.ts +0 -24
- package/dist/src/core/logger.d.ts.map +0 -1
- package/dist/src/core/logger.js +0 -121
- package/dist/src/core/logger.js.map +0 -1
- package/dist/src/core/logger.test.d.ts +0 -2
- package/dist/src/core/logger.test.d.ts.map +0 -1
- package/dist/src/core/logger.test.js +0 -31
- package/dist/src/core/logger.test.js.map +0 -1
- package/dist/src/core/progress-tracker.d.ts +0 -95
- package/dist/src/core/progress-tracker.d.ts.map +0 -1
- package/dist/src/core/progress-tracker.js +0 -178
- package/dist/src/core/progress-tracker.js.map +0 -1
- package/dist/src/core/project-manager.d.ts +0 -130
- package/dist/src/core/project-manager.d.ts.map +0 -1
- package/dist/src/core/project-manager.js +0 -582
- package/dist/src/core/project-manager.js.map +0 -1
- package/dist/src/core/update-checker.d.ts +0 -38
- package/dist/src/core/update-checker.d.ts.map +0 -1
- package/dist/src/core/update-checker.js +0 -156
- package/dist/src/core/update-checker.js.map +0 -1
- package/dist/src/error-handler.d.ts +0 -42
- package/dist/src/error-handler.d.ts.map +0 -1
- package/dist/src/error-handler.js +0 -155
- package/dist/src/error-handler.js.map +0 -1
- package/dist/src/features/tasks/__tests__/pebbles-task-store.test.d.ts +0 -5
- package/dist/src/features/tasks/__tests__/pebbles-task-store.test.d.ts.map +0 -1
- package/dist/src/features/tasks/__tests__/pebbles-task-store.test.js +0 -712
- package/dist/src/features/tasks/__tests__/pebbles-task-store.test.js.map +0 -1
- package/dist/src/frame-manager.d.ts +0 -106
- package/dist/src/frame-manager.d.ts.map +0 -1
- package/dist/src/frame-manager.js +0 -361
- package/dist/src/frame-manager.js.map +0 -1
- package/dist/src/integrations/browser-mcp.d.ts +0 -94
- package/dist/src/integrations/browser-mcp.d.ts.map +0 -1
- package/dist/src/integrations/browser-mcp.js +0 -431
- package/dist/src/integrations/browser-mcp.js.map +0 -1
- package/dist/src/integrations/linear/__tests__/auth.test.d.ts +0 -5
- package/dist/src/integrations/linear/__tests__/auth.test.d.ts.map +0 -1
- package/dist/src/integrations/linear/__tests__/auth.test.js +0 -517
- package/dist/src/integrations/linear/__tests__/auth.test.js.map +0 -1
- package/dist/src/integrations/linear/__tests__/sync-service.test.d.ts +0 -5
- package/dist/src/integrations/linear/__tests__/sync-service.test.d.ts.map +0 -1
- package/dist/src/integrations/linear/__tests__/sync-service.test.js +0 -700
- package/dist/src/integrations/linear/__tests__/sync-service.test.js.map +0 -1
- package/dist/src/integrations/linear-auth.d.ts +0 -99
- package/dist/src/integrations/linear-auth.d.ts.map +0 -1
- package/dist/src/integrations/linear-auth.js +0 -319
- package/dist/src/integrations/linear-auth.js.map +0 -1
- package/dist/src/integrations/linear-auto-sync.d.ts +0 -77
- package/dist/src/integrations/linear-auto-sync.d.ts.map +0 -1
- package/dist/src/integrations/linear-auto-sync.js +0 -268
- package/dist/src/integrations/linear-auto-sync.js.map +0 -1
- package/dist/src/integrations/linear-client.d.ts +0 -86
- package/dist/src/integrations/linear-client.d.ts.map +0 -1
- package/dist/src/integrations/linear-client.js +0 -277
- package/dist/src/integrations/linear-client.js.map +0 -1
- package/dist/src/integrations/linear-config.d.ts +0 -51
- package/dist/src/integrations/linear-config.d.ts.map +0 -1
- package/dist/src/integrations/linear-config.js +0 -103
- package/dist/src/integrations/linear-config.js.map +0 -1
- package/dist/src/integrations/linear-sync.d.ts +0 -97
- package/dist/src/integrations/linear-sync.d.ts.map +0 -1
- package/dist/src/integrations/linear-sync.js +0 -391
- package/dist/src/integrations/linear-sync.js.map +0 -1
- package/dist/src/integrations/mcp/__tests__/server.test.d.ts +0 -5
- package/dist/src/integrations/mcp/__tests__/server.test.d.ts.map +0 -1
- package/dist/src/integrations/mcp/__tests__/server.test.js +0 -790
- package/dist/src/integrations/mcp/__tests__/server.test.js.map +0 -1
- package/dist/src/logger.d.ts +0 -24
- package/dist/src/logger.d.ts.map +0 -1
- package/dist/src/logger.js +0 -120
- package/dist/src/logger.js.map +0 -1
- package/dist/src/mcp/mcp-server.d.ts +0 -40
- package/dist/src/mcp/mcp-server.d.ts.map +0 -1
- package/dist/src/mcp/mcp-server.js +0 -828
- package/dist/src/mcp/mcp-server.js.map +0 -1
- package/dist/src/mcp-server.d.ts +0 -32
- package/dist/src/mcp-server.d.ts.map +0 -1
- package/dist/src/mcp-server.js +0 -441
- package/dist/src/mcp-server.js.map +0 -1
- package/dist/src/pebbles/pebbles-task-store.d.ts +0 -117
- package/dist/src/pebbles/pebbles-task-store.d.ts.map +0 -1
- package/dist/src/pebbles/pebbles-task-store.js +0 -335
- package/dist/src/pebbles/pebbles-task-store.js.map +0 -1
- package/dist/src/pebbles/task-aware-context.d.ts +0 -103
- package/dist/src/pebbles/task-aware-context.d.ts.map +0 -1
- package/dist/src/pebbles/task-aware-context.js +0 -412
- package/dist/src/pebbles/task-aware-context.js.map +0 -1
- package/dist/src/railway/index.d.ts +0 -7
- package/dist/src/railway/index.d.ts.map +0 -1
- package/dist/src/railway/index.js +0 -401
- package/dist/src/railway/index.js.map +0 -1
- package/dist/src/runway/auth/auth-middleware.d.ts +0 -66
- package/dist/src/runway/auth/auth-middleware.d.ts.map +0 -1
- package/dist/src/runway/auth/auth-middleware.js +0 -337
- package/dist/src/runway/auth/auth-middleware.js.map +0 -1
- package/dist/src/runway/server/runway-mcp-server.d.ts +0 -46
- package/dist/src/runway/server/runway-mcp-server.d.ts.map +0 -1
- package/dist/src/runway/server/runway-mcp-server.js +0 -601
- package/dist/src/runway/server/runway-mcp-server.js.map +0 -1
- package/dist/src/runway.bak/auth/auth-middleware.d.ts +0 -66
- package/dist/src/runway.bak/auth/auth-middleware.d.ts.map +0 -1
- package/dist/src/runway.bak/auth/auth-middleware.js +0 -337
- package/dist/src/runway.bak/auth/auth-middleware.js.map +0 -1
- package/dist/src/runway.bak/server/runway-mcp-server.d.ts +0 -46
- package/dist/src/runway.bak/server/runway-mcp-server.d.ts.map +0 -1
- package/dist/src/runway.bak/server/runway-mcp-server.js +0 -601
- package/dist/src/runway.bak/server/runway-mcp-server.js.map +0 -1
- package/dist/src/task-aware-context.d.ts +0 -103
- package/dist/src/task-aware-context.d.ts.map +0 -1
- package/dist/src/task-aware-context.js +0 -395
- package/dist/src/task-aware-context.js.map +0 -1
|
@@ -1,726 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for StackMemory CLI Commands
|
|
3
|
-
*/
|
|
4
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
5
|
-
import { program } from 'commander';
|
|
6
|
-
import { join } from 'path';
|
|
7
|
-
import { mkdtempSync, rmSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
8
|
-
import { tmpdir } from 'os';
|
|
9
|
-
// Mock dependencies
|
|
10
|
-
vi.mock('../core/monitoring/logger', () => ({
|
|
11
|
-
logger: {
|
|
12
|
-
info: vi.fn(),
|
|
13
|
-
error: vi.fn(),
|
|
14
|
-
debug: vi.fn(),
|
|
15
|
-
warn: vi.fn()
|
|
16
|
-
}
|
|
17
|
-
}));
|
|
18
|
-
vi.mock('better-sqlite3', () => ({
|
|
19
|
-
default: vi.fn().mockImplementation(() => ({
|
|
20
|
-
exec: vi.fn(),
|
|
21
|
-
prepare: vi.fn(() => ({
|
|
22
|
-
run: vi.fn(),
|
|
23
|
-
get: vi.fn(),
|
|
24
|
-
all: vi.fn(() => [])
|
|
25
|
-
})),
|
|
26
|
-
close: vi.fn()
|
|
27
|
-
}))
|
|
28
|
-
}));
|
|
29
|
-
vi.mock('../core/context/frame-manager', () => ({
|
|
30
|
-
FrameManager: vi.fn().mockImplementation(() => ({
|
|
31
|
-
createFrame: vi.fn(() => 'frame-123'),
|
|
32
|
-
getActiveFramePath: vi.fn(() => []),
|
|
33
|
-
getStackDepth: vi.fn(() => 0),
|
|
34
|
-
getHotStackContext: vi.fn(() => [])
|
|
35
|
-
}))
|
|
36
|
-
}));
|
|
37
|
-
vi.mock('../features/tasks/pebbles-task-store.js', () => ({
|
|
38
|
-
PebblesTaskStore: vi.fn().mockImplementation(() => ({
|
|
39
|
-
createTask: vi.fn(() => 'task-123'),
|
|
40
|
-
getActiveTasks: vi.fn(() => []),
|
|
41
|
-
getMetrics: vi.fn(() => ({
|
|
42
|
-
total_tasks: 0,
|
|
43
|
-
completion_rate: 0,
|
|
44
|
-
blocked_tasks: 0
|
|
45
|
-
}))
|
|
46
|
-
}))
|
|
47
|
-
}));
|
|
48
|
-
vi.mock('../integrations/linear/auth', () => ({
|
|
49
|
-
LinearAuthManager: vi.fn().mockImplementation(() => ({
|
|
50
|
-
isConfigured: vi.fn(() => false),
|
|
51
|
-
loadConfig: vi.fn(),
|
|
52
|
-
loadTokens: vi.fn()
|
|
53
|
-
})),
|
|
54
|
-
LinearOAuthSetup: vi.fn().mockImplementation(() => ({
|
|
55
|
-
setupInteractive: vi.fn(),
|
|
56
|
-
completeAuth: vi.fn(),
|
|
57
|
-
testConnection: vi.fn()
|
|
58
|
-
}))
|
|
59
|
-
}));
|
|
60
|
-
vi.mock('../integrations/linear/sync', () => ({
|
|
61
|
-
LinearSyncEngine: vi.fn().mockImplementation(() => ({
|
|
62
|
-
sync: vi.fn(() => ({
|
|
63
|
-
success: true,
|
|
64
|
-
synced: { toLinear: 1, fromLinear: 2, updated: 0 },
|
|
65
|
-
conflicts: [],
|
|
66
|
-
errors: []
|
|
67
|
-
}))
|
|
68
|
-
})),
|
|
69
|
-
DEFAULT_SYNC_CONFIG: {
|
|
70
|
-
enabled: true,
|
|
71
|
-
direction: 'bidirectional'
|
|
72
|
-
}
|
|
73
|
-
}));
|
|
74
|
-
vi.mock('../core/utils/update-checker', () => ({
|
|
75
|
-
UpdateChecker: {
|
|
76
|
-
checkForUpdates: vi.fn(),
|
|
77
|
-
forceCheck: vi.fn()
|
|
78
|
-
}
|
|
79
|
-
}));
|
|
80
|
-
vi.mock('../core/monitoring/progress-tracker', () => ({
|
|
81
|
-
ProgressTracker: vi.fn().mockImplementation(() => ({
|
|
82
|
-
getSummary: vi.fn(() => 'Progress summary'),
|
|
83
|
-
updateLinearStatus: vi.fn()
|
|
84
|
-
}))
|
|
85
|
-
}));
|
|
86
|
-
// Mock child_process for git operations
|
|
87
|
-
vi.mock('child_process', () => ({
|
|
88
|
-
execSync: vi.fn(() => Buffer.from('mock git output'))
|
|
89
|
-
}));
|
|
90
|
-
// Mock the command registration functions
|
|
91
|
-
vi.mock('./commands/projects', () => ({
|
|
92
|
-
registerProjectCommands: vi.fn()
|
|
93
|
-
}));
|
|
94
|
-
vi.mock('./commands/linear', () => ({
|
|
95
|
-
registerLinearCommands: vi.fn()
|
|
96
|
-
}));
|
|
97
|
-
vi.mock('./commands/linear-test', () => ({
|
|
98
|
-
registerLinearTestCommand: vi.fn()
|
|
99
|
-
}));
|
|
100
|
-
vi.mock('./commands/session', () => ({
|
|
101
|
-
createSessionCommands: vi.fn()
|
|
102
|
-
}));
|
|
103
|
-
vi.mock('./commands/worktree', () => ({
|
|
104
|
-
registerWorktreeCommands: vi.fn()
|
|
105
|
-
}));
|
|
106
|
-
vi.mock('./commands/onboard', () => ({
|
|
107
|
-
registerOnboardingCommand: vi.fn()
|
|
108
|
-
}));
|
|
109
|
-
vi.mock('./commands/webhook', () => ({
|
|
110
|
-
webhookCommand: vi.fn(() => ({ name: 'webhook' }))
|
|
111
|
-
}));
|
|
112
|
-
vi.mock('../core/projects/project-manager.js', () => ({
|
|
113
|
-
ProjectManager: {
|
|
114
|
-
getInstance: vi.fn(() => ({
|
|
115
|
-
detectProject: vi.fn()
|
|
116
|
-
}))
|
|
117
|
-
}
|
|
118
|
-
}));
|
|
119
|
-
vi.mock('../core/session/index.js', () => ({
|
|
120
|
-
sessionManager: {
|
|
121
|
-
initialize: vi.fn(),
|
|
122
|
-
getOrCreateSession: vi.fn(() => ({
|
|
123
|
-
sessionId: 'test-session-123',
|
|
124
|
-
projectId: 'test-project',
|
|
125
|
-
state: 'active',
|
|
126
|
-
startedAt: Date.now() - 600000, // 10 minutes ago
|
|
127
|
-
branch: 'main'
|
|
128
|
-
})),
|
|
129
|
-
listSessions: vi.fn(() => [])
|
|
130
|
-
},
|
|
131
|
-
FrameQueryMode: {
|
|
132
|
-
CURRENT_SESSION: 'current_session',
|
|
133
|
-
ALL_ACTIVE: 'all_active',
|
|
134
|
-
PROJECT_ACTIVE: 'project_active',
|
|
135
|
-
HISTORICAL: 'historical'
|
|
136
|
-
}
|
|
137
|
-
}));
|
|
138
|
-
describe('CLI Commands', () => {
|
|
139
|
-
let tempDir;
|
|
140
|
-
let originalCwd;
|
|
141
|
-
let originalArgv;
|
|
142
|
-
let consoleSpy;
|
|
143
|
-
beforeEach(() => {
|
|
144
|
-
// Setup temp directory
|
|
145
|
-
tempDir = mkdtempSync(join(tmpdir(), 'stackmemory-cli-test-'));
|
|
146
|
-
originalCwd = process.cwd();
|
|
147
|
-
originalArgv = [...process.argv];
|
|
148
|
-
// Mock process.cwd() to return our temp directory
|
|
149
|
-
vi.spyOn(process, 'cwd').mockReturnValue(tempDir);
|
|
150
|
-
// Mock console methods
|
|
151
|
-
consoleSpy = {
|
|
152
|
-
log: vi.spyOn(console, 'log').mockImplementation(() => { }),
|
|
153
|
-
error: vi.spyOn(console, 'error').mockImplementation(() => { }),
|
|
154
|
-
};
|
|
155
|
-
// Mock process.exit to prevent tests from exiting
|
|
156
|
-
vi.spyOn(process, 'exit').mockImplementation(() => {
|
|
157
|
-
throw new Error('process.exit() called');
|
|
158
|
-
});
|
|
159
|
-
// Clear commander program
|
|
160
|
-
program.commands.length = 0;
|
|
161
|
-
program.options.length = 0;
|
|
162
|
-
});
|
|
163
|
-
afterEach(() => {
|
|
164
|
-
// Restore original state
|
|
165
|
-
vi.spyOn(process, 'cwd').mockRestore();
|
|
166
|
-
process.argv = originalArgv;
|
|
167
|
-
consoleSpy.log.mockRestore();
|
|
168
|
-
consoleSpy.error.mockRestore();
|
|
169
|
-
vi.spyOn(process, 'exit').mockRestore();
|
|
170
|
-
// Cleanup temp directory
|
|
171
|
-
if (tempDir) {
|
|
172
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
173
|
-
}
|
|
174
|
-
vi.clearAllMocks();
|
|
175
|
-
});
|
|
176
|
-
describe('init command', () => {
|
|
177
|
-
beforeEach(async () => {
|
|
178
|
-
// Dynamically import to get fresh instance
|
|
179
|
-
delete require.cache[require.resolve('../index.js')];
|
|
180
|
-
await import('../index.js');
|
|
181
|
-
});
|
|
182
|
-
it('should initialize StackMemory in current directory', async () => {
|
|
183
|
-
process.argv = ['node', 'stackmemory', 'init'];
|
|
184
|
-
try {
|
|
185
|
-
await program.parseAsync();
|
|
186
|
-
}
|
|
187
|
-
catch (error) {
|
|
188
|
-
// Expect process.exit to be called
|
|
189
|
-
expect(error.message).toBe('process.exit() called');
|
|
190
|
-
}
|
|
191
|
-
const stackmemoryDir = join(tempDir, '.stackmemory');
|
|
192
|
-
expect(existsSync(stackmemoryDir)).toBe(true);
|
|
193
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('✅ StackMemory initialized in', tempDir);
|
|
194
|
-
});
|
|
195
|
-
it('should handle initialization errors', async () => {
|
|
196
|
-
// Mock FrameManager to throw error
|
|
197
|
-
const { FrameManager } = await import('../core/context/frame-manager');
|
|
198
|
-
FrameManager.mockImplementationOnce(() => {
|
|
199
|
-
throw new Error('Database error');
|
|
200
|
-
});
|
|
201
|
-
process.argv = ['node', 'stackmemory', 'init'];
|
|
202
|
-
try {
|
|
203
|
-
await program.parseAsync();
|
|
204
|
-
}
|
|
205
|
-
catch (error) {
|
|
206
|
-
expect(error.message).toBe('process.exit() called');
|
|
207
|
-
}
|
|
208
|
-
expect(consoleSpy.error).toHaveBeenCalledWith('❌ Initialization failed:', 'Database error');
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
describe('status command', () => {
|
|
212
|
-
beforeEach(async () => {
|
|
213
|
-
// Create a test database file
|
|
214
|
-
const dbDir = join(tempDir, '.stackmemory');
|
|
215
|
-
mkdirSync(dbDir, { recursive: true });
|
|
216
|
-
writeFileSync(join(dbDir, 'context.db'), '');
|
|
217
|
-
delete require.cache[require.resolve('../index.js')];
|
|
218
|
-
await import('../index.js');
|
|
219
|
-
});
|
|
220
|
-
it('should show status when StackMemory is initialized', async () => {
|
|
221
|
-
process.argv = ['node', 'stackmemory', 'status'];
|
|
222
|
-
await program.parseAsync();
|
|
223
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('📊 StackMemory Status:');
|
|
224
|
-
});
|
|
225
|
-
it('should show error when StackMemory is not initialized', async () => {
|
|
226
|
-
// Remove the database file
|
|
227
|
-
rmSync(join(tempDir, '.stackmemory'), { recursive: true });
|
|
228
|
-
process.argv = ['node', 'stackmemory', 'status'];
|
|
229
|
-
await program.parseAsync();
|
|
230
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('❌ StackMemory not initialized. Run "stackmemory init" first.');
|
|
231
|
-
});
|
|
232
|
-
it('should handle --all option', async () => {
|
|
233
|
-
process.argv = ['node', 'stackmemory', 'status', '--all'];
|
|
234
|
-
await program.parseAsync();
|
|
235
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('📊 StackMemory Status:');
|
|
236
|
-
});
|
|
237
|
-
it('should handle --project option', async () => {
|
|
238
|
-
process.argv = ['node', 'stackmemory', 'status', '--project'];
|
|
239
|
-
await program.parseAsync();
|
|
240
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('📊 StackMemory Status:');
|
|
241
|
-
});
|
|
242
|
-
it('should handle --session option', async () => {
|
|
243
|
-
process.argv = ['node', 'stackmemory', 'status', '--session', 'test-session-id'];
|
|
244
|
-
await program.parseAsync();
|
|
245
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('📊 StackMemory Status:');
|
|
246
|
-
});
|
|
247
|
-
it('should handle status check errors', async () => {
|
|
248
|
-
// Mock FrameManager to throw error
|
|
249
|
-
const { FrameManager } = await import('../core/context/frame-manager');
|
|
250
|
-
FrameManager.mockImplementationOnce(() => {
|
|
251
|
-
throw new Error('Status error');
|
|
252
|
-
});
|
|
253
|
-
process.argv = ['node', 'stackmemory', 'status'];
|
|
254
|
-
try {
|
|
255
|
-
await program.parseAsync();
|
|
256
|
-
}
|
|
257
|
-
catch (error) {
|
|
258
|
-
expect(error.message).toBe('process.exit() called');
|
|
259
|
-
}
|
|
260
|
-
expect(consoleSpy.error).toHaveBeenCalledWith('❌ Status check failed:', 'Status error');
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
describe('Linear commands', () => {
|
|
264
|
-
beforeEach(async () => {
|
|
265
|
-
delete require.cache[require.resolve('../index.js')];
|
|
266
|
-
await import('../index.js');
|
|
267
|
-
});
|
|
268
|
-
describe('linear setup', () => {
|
|
269
|
-
it('should setup Linear OAuth integration', async () => {
|
|
270
|
-
const { LinearOAuthSetup } = await import('../integrations/linear/auth');
|
|
271
|
-
const mockSetup = LinearOAuthSetup;
|
|
272
|
-
mockSetup.mockImplementation(() => ({
|
|
273
|
-
setupInteractive: vi.fn().mockResolvedValue({
|
|
274
|
-
authUrl: 'https://linear.app/oauth/authorize?client_id=test',
|
|
275
|
-
instructions: [
|
|
276
|
-
'Step 1: Visit the authorization URL',
|
|
277
|
-
'Step 2: Complete authorization'
|
|
278
|
-
]
|
|
279
|
-
})
|
|
280
|
-
}));
|
|
281
|
-
process.argv = ['node', 'stackmemory', 'linear', 'setup'];
|
|
282
|
-
await program.parseAsync();
|
|
283
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('🔗 Linear OAuth Setup\n');
|
|
284
|
-
});
|
|
285
|
-
it('should handle setup errors', async () => {
|
|
286
|
-
const { LinearOAuthSetup } = await import('../integrations/linear/auth');
|
|
287
|
-
const mockSetup = LinearOAuthSetup;
|
|
288
|
-
mockSetup.mockImplementation(() => ({
|
|
289
|
-
setupInteractive: vi.fn().mockRejectedValue(new Error('Setup failed'))
|
|
290
|
-
}));
|
|
291
|
-
process.argv = ['node', 'stackmemory', 'linear', 'setup'];
|
|
292
|
-
try {
|
|
293
|
-
await program.parseAsync();
|
|
294
|
-
}
|
|
295
|
-
catch (error) {
|
|
296
|
-
expect(error.message).toBe('process.exit() called');
|
|
297
|
-
}
|
|
298
|
-
expect(consoleSpy.error).toHaveBeenCalledWith('❌ Setup failed:', 'Setup failed');
|
|
299
|
-
});
|
|
300
|
-
});
|
|
301
|
-
describe('linear authorize', () => {
|
|
302
|
-
it('should complete Linear authorization', async () => {
|
|
303
|
-
const { LinearOAuthSetup } = await import('../integrations/linear/auth');
|
|
304
|
-
const mockSetup = LinearOAuthSetup;
|
|
305
|
-
mockSetup.mockImplementation(() => ({
|
|
306
|
-
completeAuth: vi.fn().mockResolvedValue(true),
|
|
307
|
-
testConnection: vi.fn().mockResolvedValue(true)
|
|
308
|
-
}));
|
|
309
|
-
process.argv = ['node', 'stackmemory', 'linear', 'authorize', 'auth-code-123'];
|
|
310
|
-
await program.parseAsync();
|
|
311
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('✅ Linear integration authorized successfully!');
|
|
312
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('✅ Linear connection test passed!');
|
|
313
|
-
});
|
|
314
|
-
it('should handle authorization failure', async () => {
|
|
315
|
-
const { LinearOAuthSetup } = await import('../integrations/linear/auth');
|
|
316
|
-
const mockSetup = LinearOAuthSetup;
|
|
317
|
-
mockSetup.mockImplementation(() => ({
|
|
318
|
-
completeAuth: vi.fn().mockResolvedValue(false)
|
|
319
|
-
}));
|
|
320
|
-
process.argv = ['node', 'stackmemory', 'linear', 'authorize', 'invalid-code'];
|
|
321
|
-
try {
|
|
322
|
-
await program.parseAsync();
|
|
323
|
-
}
|
|
324
|
-
catch (error) {
|
|
325
|
-
expect(error.message).toBe('process.exit() called');
|
|
326
|
-
}
|
|
327
|
-
expect(consoleSpy.error).toHaveBeenCalledWith('❌ Authorization failed. Please try again.');
|
|
328
|
-
});
|
|
329
|
-
it('should handle connection test failure after successful auth', async () => {
|
|
330
|
-
const { LinearOAuthSetup } = await import('../integrations/linear/auth');
|
|
331
|
-
const mockSetup = LinearOAuthSetup;
|
|
332
|
-
mockSetup.mockImplementation(() => ({
|
|
333
|
-
completeAuth: vi.fn().mockResolvedValue(true),
|
|
334
|
-
testConnection: vi.fn().mockResolvedValue(false)
|
|
335
|
-
}));
|
|
336
|
-
process.argv = ['node', 'stackmemory', 'linear', 'authorize', 'auth-code-123'];
|
|
337
|
-
await program.parseAsync();
|
|
338
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('✅ Linear integration authorized successfully!');
|
|
339
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('⚠️ Linear connection test failed. Check your configuration.');
|
|
340
|
-
});
|
|
341
|
-
});
|
|
342
|
-
describe('linear status', () => {
|
|
343
|
-
it('should show status when not configured', async () => {
|
|
344
|
-
process.argv = ['node', 'stackmemory', 'linear', 'status'];
|
|
345
|
-
await program.parseAsync();
|
|
346
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('📊 Linear Integration Status:');
|
|
347
|
-
expect(consoleSpy.log).toHaveBeenCalledWith(' Configured: ❌');
|
|
348
|
-
});
|
|
349
|
-
it('should show detailed status when configured', async () => {
|
|
350
|
-
const { LinearAuthManager } = await import('../integrations/linear/auth');
|
|
351
|
-
const mockAuthManager = LinearAuthManager;
|
|
352
|
-
mockAuthManager.mockImplementation(() => ({
|
|
353
|
-
isConfigured: vi.fn(() => true),
|
|
354
|
-
loadConfig: vi.fn(() => ({
|
|
355
|
-
clientId: 'test-client-id'
|
|
356
|
-
})),
|
|
357
|
-
loadTokens: vi.fn(() => ({
|
|
358
|
-
accessToken: 'test-token',
|
|
359
|
-
expiresAt: Date.now() + 3600000
|
|
360
|
-
}))
|
|
361
|
-
}));
|
|
362
|
-
const { LinearOAuthSetup } = await import('../integrations/linear/auth');
|
|
363
|
-
const mockSetup = LinearOAuthSetup;
|
|
364
|
-
mockSetup.mockImplementation(() => ({
|
|
365
|
-
testConnection: vi.fn().mockResolvedValue(true)
|
|
366
|
-
}));
|
|
367
|
-
process.argv = ['node', 'stackmemory', 'linear', 'status'];
|
|
368
|
-
await program.parseAsync();
|
|
369
|
-
expect(consoleSpy.log).toHaveBeenCalledWith(' Configured: ✅');
|
|
370
|
-
expect(consoleSpy.log).toHaveBeenCalledWith(' Connection: ✅ OK');
|
|
371
|
-
});
|
|
372
|
-
});
|
|
373
|
-
describe('linear sync', () => {
|
|
374
|
-
beforeEach(() => {
|
|
375
|
-
// Create database directory for sync commands
|
|
376
|
-
const dbDir = join(tempDir, '.stackmemory');
|
|
377
|
-
mkdirSync(dbDir, { recursive: true });
|
|
378
|
-
writeFileSync(join(dbDir, 'context.db'), '');
|
|
379
|
-
});
|
|
380
|
-
it('should sync with Linear when configured', async () => {
|
|
381
|
-
const { LinearAuthManager } = await import('../integrations/linear/auth');
|
|
382
|
-
const mockAuthManager = LinearAuthManager;
|
|
383
|
-
mockAuthManager.mockImplementation(() => ({
|
|
384
|
-
isConfigured: vi.fn(() => true)
|
|
385
|
-
}));
|
|
386
|
-
process.argv = ['node', 'stackmemory', 'linear', 'sync'];
|
|
387
|
-
await program.parseAsync();
|
|
388
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('🔄 Starting bidirectional sync with Linear...');
|
|
389
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('✅ Sync completed successfully!');
|
|
390
|
-
});
|
|
391
|
-
it('should handle sync with custom direction', async () => {
|
|
392
|
-
const { LinearAuthManager } = await import('../integrations/linear/auth');
|
|
393
|
-
const mockAuthManager = LinearAuthManager;
|
|
394
|
-
mockAuthManager.mockImplementation(() => ({
|
|
395
|
-
isConfigured: vi.fn(() => true)
|
|
396
|
-
}));
|
|
397
|
-
process.argv = ['node', 'stackmemory', 'linear', 'sync', '--direction', 'to_linear'];
|
|
398
|
-
await program.parseAsync();
|
|
399
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('🔄 Starting to_linear sync with Linear...');
|
|
400
|
-
});
|
|
401
|
-
it('should handle sync errors', async () => {
|
|
402
|
-
const { LinearAuthManager } = await import('../integrations/linear/auth');
|
|
403
|
-
const mockAuthManager = LinearAuthManager;
|
|
404
|
-
mockAuthManager.mockImplementation(() => ({
|
|
405
|
-
isConfigured: vi.fn(() => true)
|
|
406
|
-
}));
|
|
407
|
-
const { LinearSyncEngine } = await import('../integrations/linear/sync');
|
|
408
|
-
const mockSyncEngine = LinearSyncEngine;
|
|
409
|
-
mockSyncEngine.mockImplementation(() => ({
|
|
410
|
-
sync: vi.fn().mockResolvedValue({
|
|
411
|
-
success: false,
|
|
412
|
-
errors: ['Sync error occurred']
|
|
413
|
-
})
|
|
414
|
-
}));
|
|
415
|
-
process.argv = ['node', 'stackmemory', 'linear', 'sync'];
|
|
416
|
-
await program.parseAsync();
|
|
417
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('❌ Sync failed');
|
|
418
|
-
});
|
|
419
|
-
it('should show warning when not configured', async () => {
|
|
420
|
-
process.argv = ['node', 'stackmemory', 'linear', 'sync'];
|
|
421
|
-
await program.parseAsync();
|
|
422
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('❌ Linear not configured. Set LINEAR_API_KEY environment variable or run "stackmemory linear setup" first.');
|
|
423
|
-
});
|
|
424
|
-
it('should show warning when not initialized', async () => {
|
|
425
|
-
rmSync(join(tempDir, '.stackmemory'), { recursive: true });
|
|
426
|
-
process.argv = ['node', 'stackmemory', 'linear', 'sync'];
|
|
427
|
-
await program.parseAsync();
|
|
428
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('❌ StackMemory not initialized. Run "stackmemory init" first.');
|
|
429
|
-
});
|
|
430
|
-
});
|
|
431
|
-
});
|
|
432
|
-
describe('context:test command', () => {
|
|
433
|
-
beforeEach(() => {
|
|
434
|
-
// Create database directory for context commands
|
|
435
|
-
const dbDir = join(tempDir, '.stackmemory');
|
|
436
|
-
mkdirSync(dbDir, { recursive: true });
|
|
437
|
-
writeFileSync(join(dbDir, 'context.db'), '');
|
|
438
|
-
});
|
|
439
|
-
it('should create test context frames', async () => {
|
|
440
|
-
delete require.cache[require.resolve('../index.js')];
|
|
441
|
-
await import('../index.js');
|
|
442
|
-
const { FrameManager } = await import('../core/context/frame-manager');
|
|
443
|
-
const mockFrameManager = FrameManager;
|
|
444
|
-
let frameCallCount = 0;
|
|
445
|
-
mockFrameManager.mockImplementation(() => ({
|
|
446
|
-
createFrame: vi.fn(() => `frame-${++frameCallCount}`),
|
|
447
|
-
addEvent: vi.fn(),
|
|
448
|
-
closeFrame: vi.fn(),
|
|
449
|
-
getStackDepth: vi.fn(() => frameCallCount),
|
|
450
|
-
getActiveFramePath: vi.fn(() => [])
|
|
451
|
-
}));
|
|
452
|
-
process.argv = ['node', 'stackmemory', 'context:test'];
|
|
453
|
-
await program.parseAsync();
|
|
454
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('📝 Creating test context frames...');
|
|
455
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('✅ Test frames created!');
|
|
456
|
-
});
|
|
457
|
-
it('should handle context test errors', async () => {
|
|
458
|
-
delete require.cache[require.resolve('../index.js')];
|
|
459
|
-
await import('../index.js');
|
|
460
|
-
const { FrameManager } = await import('../core/context/frame-manager');
|
|
461
|
-
const mockFrameManager = FrameManager;
|
|
462
|
-
mockFrameManager.mockImplementation(() => {
|
|
463
|
-
throw new Error('Context test error');
|
|
464
|
-
});
|
|
465
|
-
process.argv = ['node', 'stackmemory', 'context:test'];
|
|
466
|
-
try {
|
|
467
|
-
await program.parseAsync();
|
|
468
|
-
}
|
|
469
|
-
catch (error) {
|
|
470
|
-
expect(error.message).toBe('process.exit() called');
|
|
471
|
-
}
|
|
472
|
-
expect(consoleSpy.error).toHaveBeenCalledWith('❌ Test failed:', 'Context test error');
|
|
473
|
-
});
|
|
474
|
-
it('should show warning when not initialized', async () => {
|
|
475
|
-
rmSync(join(tempDir, '.stackmemory'), { recursive: true });
|
|
476
|
-
delete require.cache[require.resolve('../index.js')];
|
|
477
|
-
await import('../index.js');
|
|
478
|
-
process.argv = ['node', 'stackmemory', 'context:test'];
|
|
479
|
-
await program.parseAsync();
|
|
480
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('❌ StackMemory not initialized. Run "stackmemory init" first.');
|
|
481
|
-
});
|
|
482
|
-
});
|
|
483
|
-
describe('update-check command', () => {
|
|
484
|
-
beforeEach(async () => {
|
|
485
|
-
delete require.cache[require.resolve('../index.js')];
|
|
486
|
-
await import('../index.js');
|
|
487
|
-
});
|
|
488
|
-
it('should check for updates', async () => {
|
|
489
|
-
const { UpdateChecker } = await import('../core/utils/update-checker');
|
|
490
|
-
UpdateChecker.forceCheck = vi.fn().mockResolvedValue(undefined);
|
|
491
|
-
process.argv = ['node', 'stackmemory', 'update-check'];
|
|
492
|
-
await program.parseAsync();
|
|
493
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('🔍 Checking for updates...');
|
|
494
|
-
expect(UpdateChecker.forceCheck).toHaveBeenCalled();
|
|
495
|
-
});
|
|
496
|
-
it('should handle update check errors', async () => {
|
|
497
|
-
const { UpdateChecker } = await import('../core/utils/update-checker');
|
|
498
|
-
UpdateChecker.forceCheck = vi.fn().mockRejectedValue(new Error('Update check failed'));
|
|
499
|
-
process.argv = ['node', 'stackmemory', 'update-check'];
|
|
500
|
-
try {
|
|
501
|
-
await program.parseAsync();
|
|
502
|
-
}
|
|
503
|
-
catch (error) {
|
|
504
|
-
expect(error.message).toBe('process.exit() called');
|
|
505
|
-
}
|
|
506
|
-
expect(consoleSpy.error).toHaveBeenCalledWith('❌ Update check failed:', 'Update check failed');
|
|
507
|
-
});
|
|
508
|
-
});
|
|
509
|
-
describe('progress command', () => {
|
|
510
|
-
beforeEach(() => {
|
|
511
|
-
const dbDir = join(tempDir, '.stackmemory');
|
|
512
|
-
mkdirSync(dbDir, { recursive: true });
|
|
513
|
-
writeFileSync(join(dbDir, 'context.db'), '');
|
|
514
|
-
});
|
|
515
|
-
it('should show progress summary', async () => {
|
|
516
|
-
delete require.cache[require.resolve('../index.js')];
|
|
517
|
-
await import('../index.js');
|
|
518
|
-
process.argv = ['node', 'stackmemory', 'progress'];
|
|
519
|
-
await program.parseAsync();
|
|
520
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('Progress summary');
|
|
521
|
-
});
|
|
522
|
-
it('should handle progress errors', async () => {
|
|
523
|
-
delete require.cache[require.resolve('../index.js')];
|
|
524
|
-
await import('../index.js');
|
|
525
|
-
const { ProgressTracker } = await import('../core/monitoring/progress-tracker');
|
|
526
|
-
const mockProgressTracker = ProgressTracker;
|
|
527
|
-
mockProgressTracker.mockImplementation(() => ({
|
|
528
|
-
getSummary: vi.fn(() => {
|
|
529
|
-
throw new Error('Progress error');
|
|
530
|
-
})
|
|
531
|
-
}));
|
|
532
|
-
process.argv = ['node', 'stackmemory', 'progress'];
|
|
533
|
-
try {
|
|
534
|
-
await program.parseAsync();
|
|
535
|
-
}
|
|
536
|
-
catch (error) {
|
|
537
|
-
expect(error.message).toBe('process.exit() called');
|
|
538
|
-
}
|
|
539
|
-
expect(consoleSpy.error).toHaveBeenCalledWith('❌ Failed to show progress:', 'Progress error');
|
|
540
|
-
});
|
|
541
|
-
it('should show warning when not initialized', async () => {
|
|
542
|
-
rmSync(join(tempDir, '.stackmemory'), { recursive: true });
|
|
543
|
-
delete require.cache[require.resolve('../index.js')];
|
|
544
|
-
await import('../index.js');
|
|
545
|
-
process.argv = ['node', 'stackmemory', 'progress'];
|
|
546
|
-
await program.parseAsync();
|
|
547
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('❌ StackMemory not initialized. Run "stackmemory init" first.');
|
|
548
|
-
});
|
|
549
|
-
});
|
|
550
|
-
describe('mcp-server command', () => {
|
|
551
|
-
beforeEach(async () => {
|
|
552
|
-
delete require.cache[require.resolve('../index.js')];
|
|
553
|
-
});
|
|
554
|
-
it('should start MCP server with default options', async () => {
|
|
555
|
-
// Mock the MCP server module
|
|
556
|
-
vi.doMock('../integrations/mcp/server.js', () => ({
|
|
557
|
-
runMCPServer: vi.fn().mockResolvedValue(undefined)
|
|
558
|
-
}));
|
|
559
|
-
await import('../index.js');
|
|
560
|
-
process.argv = ['node', 'stackmemory', 'mcp-server'];
|
|
561
|
-
await program.parseAsync();
|
|
562
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('🚀 Starting StackMemory MCP Server...');
|
|
563
|
-
expect(process.env.PROJECT_ROOT).toBe(tempDir);
|
|
564
|
-
});
|
|
565
|
-
it('should start MCP server with custom project path', async () => {
|
|
566
|
-
const customPath = '/custom/project/path';
|
|
567
|
-
vi.doMock('../integrations/mcp/server.js', () => ({
|
|
568
|
-
runMCPServer: vi.fn().mockResolvedValue(undefined)
|
|
569
|
-
}));
|
|
570
|
-
await import('../index.js');
|
|
571
|
-
process.argv = ['node', 'stackmemory', 'mcp-server', '--project', customPath];
|
|
572
|
-
await program.parseAsync();
|
|
573
|
-
expect(consoleSpy.log).toHaveBeenCalledWith(` Project: ${customPath}`);
|
|
574
|
-
expect(process.env.PROJECT_ROOT).toBe(customPath);
|
|
575
|
-
});
|
|
576
|
-
it('should handle MCP server errors', async () => {
|
|
577
|
-
vi.doMock('../integrations/mcp/server.js', () => ({
|
|
578
|
-
runMCPServer: vi.fn().mockRejectedValue(new Error('MCP server error'))
|
|
579
|
-
}));
|
|
580
|
-
await import('../index.js');
|
|
581
|
-
process.argv = ['node', 'stackmemory', 'mcp-server'];
|
|
582
|
-
try {
|
|
583
|
-
await program.parseAsync();
|
|
584
|
-
}
|
|
585
|
-
catch (error) {
|
|
586
|
-
expect(error.message).toBe('process.exit() called');
|
|
587
|
-
}
|
|
588
|
-
expect(consoleSpy.error).toHaveBeenCalledWith('❌ MCP server failed:', 'MCP server error');
|
|
589
|
-
});
|
|
590
|
-
});
|
|
591
|
-
describe('Command registration', () => {
|
|
592
|
-
it('should register all command modules', async () => {
|
|
593
|
-
const registerProjectCommands = (await import('./commands/projects')).registerProjectCommands;
|
|
594
|
-
const registerLinearCommands = (await import('./commands/linear')).registerLinearCommands;
|
|
595
|
-
const registerLinearTestCommand = (await import('./commands/linear-test')).registerLinearTestCommand;
|
|
596
|
-
const createSessionCommands = (await import('./commands/session')).createSessionCommands;
|
|
597
|
-
const registerWorktreeCommands = (await import('./commands/worktree')).registerWorktreeCommands;
|
|
598
|
-
const registerOnboardingCommand = (await import('./commands/onboard')).registerOnboardingCommand;
|
|
599
|
-
const webhookCommand = (await import('./commands/webhook')).webhookCommand;
|
|
600
|
-
delete require.cache[require.resolve('../index.js')];
|
|
601
|
-
await import('../index.js');
|
|
602
|
-
expect(registerProjectCommands).toHaveBeenCalledWith(expect.any(Object));
|
|
603
|
-
expect(registerLinearCommands).toHaveBeenCalledWith(expect.any(Object));
|
|
604
|
-
expect(registerLinearTestCommand).toHaveBeenCalledWith(expect.any(Object));
|
|
605
|
-
expect(createSessionCommands).toHaveBeenCalledWith(expect.any(Object));
|
|
606
|
-
expect(registerWorktreeCommands).toHaveBeenCalledWith(expect.any(Object));
|
|
607
|
-
expect(registerOnboardingCommand).toHaveBeenCalledWith(expect.any(Object));
|
|
608
|
-
expect(webhookCommand).toHaveBeenCalled();
|
|
609
|
-
});
|
|
610
|
-
});
|
|
611
|
-
describe('Error handling and edge cases', () => {
|
|
612
|
-
beforeEach(async () => {
|
|
613
|
-
delete require.cache[require.resolve('../index.js')];
|
|
614
|
-
await import('../index.js');
|
|
615
|
-
});
|
|
616
|
-
it('should handle missing command arguments gracefully', async () => {
|
|
617
|
-
process.argv = ['node', 'stackmemory'];
|
|
618
|
-
await program.parseAsync();
|
|
619
|
-
// Should not throw error and should show help
|
|
620
|
-
expect(consoleSpy.error).not.toHaveBeenCalled();
|
|
621
|
-
});
|
|
622
|
-
it('should handle unknown commands gracefully', async () => {
|
|
623
|
-
process.argv = ['node', 'stackmemory', 'unknown-command'];
|
|
624
|
-
try {
|
|
625
|
-
await program.parseAsync();
|
|
626
|
-
}
|
|
627
|
-
catch (error) {
|
|
628
|
-
// Commander will handle unknown commands
|
|
629
|
-
expect(error.name).toBe('CommanderError');
|
|
630
|
-
}
|
|
631
|
-
});
|
|
632
|
-
it('should handle interrupted operations gracefully', async () => {
|
|
633
|
-
const { FrameManager } = await import('../core/context/frame-manager');
|
|
634
|
-
const mockFrameManager = FrameManager;
|
|
635
|
-
// Simulate an interruption during initialization
|
|
636
|
-
mockFrameManager.mockImplementation(() => {
|
|
637
|
-
const error = new Error('Operation interrupted');
|
|
638
|
-
error.code = 'EINT';
|
|
639
|
-
throw error;
|
|
640
|
-
});
|
|
641
|
-
const dbDir = join(tempDir, '.stackmemory');
|
|
642
|
-
mkdirSync(dbDir, { recursive: true });
|
|
643
|
-
writeFileSync(join(dbDir, 'context.db'), '');
|
|
644
|
-
process.argv = ['node', 'stackmemory', 'status'];
|
|
645
|
-
try {
|
|
646
|
-
await program.parseAsync();
|
|
647
|
-
}
|
|
648
|
-
catch (error) {
|
|
649
|
-
expect(error.message).toBe('process.exit() called');
|
|
650
|
-
}
|
|
651
|
-
});
|
|
652
|
-
it('should validate command options properly', async () => {
|
|
653
|
-
process.argv = ['node', 'stackmemory', 'linear', 'sync', '--direction', 'invalid-direction'];
|
|
654
|
-
const dbDir = join(tempDir, '.stackmemory');
|
|
655
|
-
mkdirSync(dbDir, { recursive: true });
|
|
656
|
-
writeFileSync(join(dbDir, 'context.db'), '');
|
|
657
|
-
// Should handle invalid option values gracefully
|
|
658
|
-
await program.parseAsync();
|
|
659
|
-
});
|
|
660
|
-
it('should handle environment variable issues', async () => {
|
|
661
|
-
// Test with missing environment variables
|
|
662
|
-
delete process.env.HOME;
|
|
663
|
-
delete process.env.USER;
|
|
664
|
-
const dbDir = join(tempDir, '.stackmemory');
|
|
665
|
-
mkdirSync(dbDir, { recursive: true });
|
|
666
|
-
writeFileSync(join(dbDir, 'context.db'), '');
|
|
667
|
-
process.argv = ['node', 'stackmemory', 'status'];
|
|
668
|
-
// Should still work despite missing env vars
|
|
669
|
-
await program.parseAsync();
|
|
670
|
-
expect(consoleSpy.log).toHaveBeenCalledWith('📊 StackMemory Status:');
|
|
671
|
-
});
|
|
672
|
-
});
|
|
673
|
-
describe('Integration with external services', () => {
|
|
674
|
-
beforeEach(() => {
|
|
675
|
-
const dbDir = join(tempDir, '.stackmemory');
|
|
676
|
-
mkdirSync(dbDir, { recursive: true });
|
|
677
|
-
writeFileSync(join(dbDir, 'context.db'), '');
|
|
678
|
-
});
|
|
679
|
-
it('should handle network failures in Linear integration', async () => {
|
|
680
|
-
delete require.cache[require.resolve('../index.js')];
|
|
681
|
-
await import('../index.js');
|
|
682
|
-
const { LinearSyncEngine } = await import('../integrations/linear/sync');
|
|
683
|
-
const mockSyncEngine = LinearSyncEngine;
|
|
684
|
-
mockSyncEngine.mockImplementation(() => ({
|
|
685
|
-
sync: vi.fn().mockRejectedValue(new Error('Network timeout'))
|
|
686
|
-
}));
|
|
687
|
-
const { LinearAuthManager } = await import('../integrations/linear/auth');
|
|
688
|
-
const mockAuthManager = LinearAuthManager;
|
|
689
|
-
mockAuthManager.mockImplementation(() => ({
|
|
690
|
-
isConfigured: vi.fn(() => true)
|
|
691
|
-
}));
|
|
692
|
-
process.argv = ['node', 'stackmemory', 'linear', 'sync'];
|
|
693
|
-
try {
|
|
694
|
-
await program.parseAsync();
|
|
695
|
-
}
|
|
696
|
-
catch (error) {
|
|
697
|
-
expect(error.message).toBe('process.exit() called');
|
|
698
|
-
}
|
|
699
|
-
expect(consoleSpy.error).toHaveBeenCalledWith('❌ Sync failed:', 'Network timeout');
|
|
700
|
-
});
|
|
701
|
-
it('should handle file system permission issues', async () => {
|
|
702
|
-
delete require.cache[require.resolve('../index.js')];
|
|
703
|
-
await import('../index.js');
|
|
704
|
-
// Mock fs operations to throw permission errors
|
|
705
|
-
const originalWriteFileSync = require('fs').writeFileSync;
|
|
706
|
-
require('fs').writeFileSync = vi.fn(() => {
|
|
707
|
-
const error = new Error('Permission denied');
|
|
708
|
-
error.code = 'EACCES';
|
|
709
|
-
throw error;
|
|
710
|
-
});
|
|
711
|
-
try {
|
|
712
|
-
process.argv = ['node', 'stackmemory', 'init'];
|
|
713
|
-
try {
|
|
714
|
-
await program.parseAsync();
|
|
715
|
-
}
|
|
716
|
-
catch (error) {
|
|
717
|
-
expect(error.message).toBe('process.exit() called');
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
finally {
|
|
721
|
-
require('fs').writeFileSync = originalWriteFileSync;
|
|
722
|
-
}
|
|
723
|
-
});
|
|
724
|
-
});
|
|
725
|
-
});
|
|
726
|
-
//# sourceMappingURL=index.test.js.map
|