recall-mcp-v3 3.7.4 → 3.9.0

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.
Files changed (70) hide show
  1. package/dist/__tests__/api-get-token.test.d.ts +18 -0
  2. package/dist/__tests__/api-get-token.test.d.ts.map +1 -0
  3. package/dist/__tests__/api-get-token.test.js +195 -0
  4. package/dist/__tests__/api-get-token.test.js.map +1 -0
  5. package/dist/__tests__/repo-override-save-log.test.d.ts +11 -0
  6. package/dist/__tests__/repo-override-save-log.test.d.ts.map +1 -0
  7. package/dist/__tests__/repo-override-save-log.test.js +352 -0
  8. package/dist/__tests__/repo-override-save-log.test.js.map +1 -0
  9. package/dist/api.d.ts +6 -1
  10. package/dist/api.d.ts.map +1 -1
  11. package/dist/api.js +49 -5
  12. package/dist/api.js.map +1 -1
  13. package/dist/auth/__tests__/auth-store.test.d.ts +6 -0
  14. package/dist/auth/__tests__/auth-store.test.d.ts.map +1 -0
  15. package/dist/auth/__tests__/auth-store.test.js +161 -0
  16. package/dist/auth/__tests__/auth-store.test.js.map +1 -0
  17. package/dist/auth/__tests__/device-client.test.d.ts +10 -0
  18. package/dist/auth/__tests__/device-client.test.d.ts.map +1 -0
  19. package/dist/auth/__tests__/device-client.test.js +327 -0
  20. package/dist/auth/__tests__/device-client.test.js.map +1 -0
  21. package/dist/auth/__tests__/preflight.test.d.ts +2 -0
  22. package/dist/auth/__tests__/preflight.test.d.ts.map +1 -0
  23. package/dist/auth/__tests__/preflight.test.js +37 -0
  24. package/dist/auth/__tests__/preflight.test.js.map +1 -0
  25. package/dist/auth/__tests__/run-auth.test.d.ts +11 -0
  26. package/dist/auth/__tests__/run-auth.test.d.ts.map +1 -0
  27. package/dist/auth/__tests__/run-auth.test.js +387 -0
  28. package/dist/auth/__tests__/run-auth.test.js.map +1 -0
  29. package/dist/auth/__tests__/tool-detection.test.d.ts +10 -0
  30. package/dist/auth/__tests__/tool-detection.test.d.ts.map +1 -0
  31. package/dist/auth/__tests__/tool-detection.test.js +122 -0
  32. package/dist/auth/__tests__/tool-detection.test.js.map +1 -0
  33. package/dist/auth/__tests__/tool-patching.test.d.ts +13 -0
  34. package/dist/auth/__tests__/tool-patching.test.d.ts.map +1 -0
  35. package/dist/auth/__tests__/tool-patching.test.js +385 -0
  36. package/dist/auth/__tests__/tool-patching.test.js.map +1 -0
  37. package/dist/auth/auth-store.d.ts +61 -0
  38. package/dist/auth/auth-store.d.ts.map +1 -0
  39. package/dist/auth/auth-store.js +158 -0
  40. package/dist/auth/auth-store.js.map +1 -0
  41. package/dist/auth/device-client.d.ts +85 -0
  42. package/dist/auth/device-client.d.ts.map +1 -0
  43. package/dist/auth/device-client.js +269 -0
  44. package/dist/auth/device-client.js.map +1 -0
  45. package/dist/auth/preflight.d.ts +10 -0
  46. package/dist/auth/preflight.d.ts.map +1 -0
  47. package/dist/auth/preflight.js +35 -0
  48. package/dist/auth/preflight.js.map +1 -0
  49. package/dist/auth/run-auth.d.ts +56 -0
  50. package/dist/auth/run-auth.d.ts.map +1 -0
  51. package/dist/auth/run-auth.js +222 -0
  52. package/dist/auth/run-auth.js.map +1 -0
  53. package/dist/auth/tool-detection.d.ts +47 -0
  54. package/dist/auth/tool-detection.d.ts.map +1 -0
  55. package/dist/auth/tool-detection.js +99 -0
  56. package/dist/auth/tool-detection.js.map +1 -0
  57. package/dist/auth/tool-patching.d.ts +85 -0
  58. package/dist/auth/tool-patching.d.ts.map +1 -0
  59. package/dist/auth/tool-patching.js +353 -0
  60. package/dist/auth/tool-patching.js.map +1 -0
  61. package/dist/cli.d.ts.map +1 -1
  62. package/dist/cli.js +30 -0
  63. package/dist/cli.js.map +1 -1
  64. package/dist/index.js +8 -0
  65. package/dist/index.js.map +1 -1
  66. package/dist/tools.d.ts +2 -0
  67. package/dist/tools.d.ts.map +1 -1
  68. package/dist/tools.js +27 -2
  69. package/dist/tools.js.map +1 -1
  70. package/package.json +1 -1
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Tests for the `getToken()` resolution in api.ts.
3
+ *
4
+ * Exercises:
5
+ * - Auth store wins over env var when both are set.
6
+ * - Env var used as fallback when auth store absent.
7
+ * - Corrupt auth store logs once + falls through to env (does not throw).
8
+ * - Missing both paths throws with an actionable error.
9
+ * - Result is memoized: subsequent calls don't re-read the filesystem.
10
+ * - "No token found" is also memoized so we don't hammer stderr on retries.
11
+ *
12
+ * `getToken` itself is not exported, but every request-making function calls
13
+ * it before issuing a fetch. We use `saveSession`'s code path by mocking the
14
+ * network layer — any call that reaches `fetch` has already resolved the
15
+ * token. The `__resetTokenCache` export is the test seam.
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=api-get-token.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-get-token.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/api-get-token.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Tests for the `getToken()` resolution in api.ts.
3
+ *
4
+ * Exercises:
5
+ * - Auth store wins over env var when both are set.
6
+ * - Env var used as fallback when auth store absent.
7
+ * - Corrupt auth store logs once + falls through to env (does not throw).
8
+ * - Missing both paths throws with an actionable error.
9
+ * - Result is memoized: subsequent calls don't re-read the filesystem.
10
+ * - "No token found" is also memoized so we don't hammer stderr on retries.
11
+ *
12
+ * `getToken` itself is not exported, but every request-making function calls
13
+ * it before issuing a fetch. We use `saveSession`'s code path by mocking the
14
+ * network layer — any call that reaches `fetch` has already resolved the
15
+ * token. The `__resetTokenCache` export is the test seam.
16
+ */
17
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
18
+ import * as fs from 'node:fs';
19
+ import * as os from 'node:os';
20
+ import * as path from 'node:path';
21
+ import { __resetTokenCache, getTokenSource, RecallApiError } from '../api.js';
22
+ import { writeAuthStore } from '../auth/auth-store.js';
23
+ // ---------------------------------------------------------------------------
24
+ // Fixture: the encryption layer and /v1/keys/team endpoint are mocked so we
25
+ // can isolate the token-resolution behavior from everything downstream.
26
+ // ---------------------------------------------------------------------------
27
+ vi.mock('../crypto.js', () => ({
28
+ encrypt: vi.fn().mockReturnValue('encrypted'),
29
+ decrypt: vi.fn().mockReturnValue('decrypted'),
30
+ isEncrypted: vi.fn().mockReturnValue(false),
31
+ safeDecrypt: vi.fn().mockReturnValue(''),
32
+ normalizeToString: vi.fn((s) => s),
33
+ }));
34
+ // ---------------------------------------------------------------------------
35
+ // readAuthStoreSync resolves its path via process.env at call time, so each
36
+ // test points RECALL_AUTH_DIR at its own tmp dir and resets the cache.
37
+ // ---------------------------------------------------------------------------
38
+ let tmp;
39
+ let originalEnv;
40
+ beforeEach(() => {
41
+ tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'recall-gettoken-'));
42
+ originalEnv = {
43
+ token: process.env.RECALL_API_TOKEN,
44
+ authDir: process.env.RECALL_AUTH_DIR,
45
+ };
46
+ // Start each test with a clean slate.
47
+ delete process.env.RECALL_API_TOKEN;
48
+ process.env.RECALL_AUTH_DIR = path.join(tmp, 'recall');
49
+ __resetTokenCache();
50
+ vi.restoreAllMocks();
51
+ });
52
+ afterEach(() => {
53
+ if (originalEnv.token !== undefined) {
54
+ process.env.RECALL_API_TOKEN = originalEnv.token;
55
+ }
56
+ else {
57
+ delete process.env.RECALL_API_TOKEN;
58
+ }
59
+ if (originalEnv.authDir !== undefined) {
60
+ process.env.RECALL_AUTH_DIR = originalEnv.authDir;
61
+ }
62
+ else {
63
+ delete process.env.RECALL_AUTH_DIR;
64
+ }
65
+ fs.rmSync(tmp, { recursive: true, force: true });
66
+ __resetTokenCache();
67
+ });
68
+ async function writeStore(token) {
69
+ await writeAuthStore({
70
+ token,
71
+ issued_at: '2026-04-23T00:00:00.000Z',
72
+ api_base: 'https://api-v3.recall.team',
73
+ client_version: '3.9.0',
74
+ }, process.env);
75
+ }
76
+ // Helper to force a call through getToken + observe the token it attached
77
+ // to the request. We shim global fetch so no real network call happens.
78
+ async function captureTokenViaFetch() {
79
+ const fetchSpy = vi
80
+ .spyOn(globalThis, 'fetch')
81
+ .mockImplementation(() => Promise.resolve(new Response(JSON.stringify({
82
+ hasAccess: true,
83
+ encryptionKey: 'k',
84
+ keyVersion: 1,
85
+ teamId: 't',
86
+ teamName: 'tt',
87
+ teamSlug: 'ts',
88
+ tier: 'free',
89
+ }), { status: 200, headers: { 'Content-Type': 'application/json' } })));
90
+ const { getTeamKey, clearKeyCache } = await import('../api.js');
91
+ clearKeyCache();
92
+ try {
93
+ await getTeamKey();
94
+ }
95
+ catch {
96
+ // If getToken throws NO_TOKEN the fetch was never called — that's valid
97
+ // in the "no token found" test which asserts by catching the error.
98
+ }
99
+ const call = fetchSpy.mock.calls[0];
100
+ if (!call)
101
+ return null;
102
+ const init = call[1];
103
+ const auth = init?.headers?.['Authorization'];
104
+ return auth?.replace(/^Bearer\s+/, '') ?? null;
105
+ }
106
+ // ---------------------------------------------------------------------------
107
+ // Tests
108
+ // ---------------------------------------------------------------------------
109
+ describe('getToken: auth store precedence', () => {
110
+ it('prefers the auth store over RECALL_API_TOKEN when both are set', async () => {
111
+ await writeStore('rcl_from_store');
112
+ process.env.RECALL_API_TOKEN = 'rcl_from_env';
113
+ const tokenUsed = await captureTokenViaFetch();
114
+ expect(tokenUsed).toBe('rcl_from_store');
115
+ expect(getTokenSource()).toBe('auth_store');
116
+ });
117
+ it('falls back to RECALL_API_TOKEN when the auth store is absent', async () => {
118
+ process.env.RECALL_API_TOKEN = 'rcl_from_env_only';
119
+ const tokenUsed = await captureTokenViaFetch();
120
+ expect(tokenUsed).toBe('rcl_from_env_only');
121
+ expect(getTokenSource()).toBe('env');
122
+ });
123
+ it('uses the auth store even when the env var is empty string', async () => {
124
+ await writeStore('rcl_store_only');
125
+ process.env.RECALL_API_TOKEN = '';
126
+ const tokenUsed = await captureTokenViaFetch();
127
+ expect(tokenUsed).toBe('rcl_store_only');
128
+ expect(getTokenSource()).toBe('auth_store');
129
+ });
130
+ });
131
+ describe('getToken: error handling', () => {
132
+ it('throws NO_TOKEN when neither store nor env is present', async () => {
133
+ const { getTeamKey, clearKeyCache } = await import('../api.js');
134
+ clearKeyCache();
135
+ await expect(getTeamKey()).rejects.toMatchObject({
136
+ name: 'RecallApiError',
137
+ code: 'NO_TOKEN',
138
+ status: 401,
139
+ });
140
+ });
141
+ it('the NO_TOKEN error message suggests both `auth` and the env var', async () => {
142
+ const { getTeamKey, clearKeyCache } = await import('../api.js');
143
+ clearKeyCache();
144
+ await expect(getTeamKey()).rejects.toThrow(/recall-mcp-v3 auth/);
145
+ await expect(getTeamKey()).rejects.toThrow(/RECALL_API_TOKEN/);
146
+ });
147
+ it('falls through to env on a corrupt auth store and logs once', async () => {
148
+ const dir = path.join(tmp, 'recall');
149
+ fs.mkdirSync(dir, { recursive: true });
150
+ fs.writeFileSync(path.join(dir, 'auth.json'), 'not valid json {{{');
151
+ process.env.RECALL_API_TOKEN = 'rcl_env_rescue';
152
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
153
+ const tokenUsed = await captureTokenViaFetch();
154
+ expect(tokenUsed).toBe('rcl_env_rescue');
155
+ expect(getTokenSource()).toBe('env');
156
+ expect(consoleSpy).toHaveBeenCalledTimes(1);
157
+ expect(consoleSpy.mock.calls[0][0]).toMatch(/auth store/i);
158
+ });
159
+ it('corrupt store + no env throws NO_TOKEN but still only logs the corruption once', async () => {
160
+ const dir = path.join(tmp, 'recall');
161
+ fs.mkdirSync(dir, { recursive: true });
162
+ fs.writeFileSync(path.join(dir, 'auth.json'), '{corrupt');
163
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
164
+ const { getTeamKey, clearKeyCache } = await import('../api.js');
165
+ clearKeyCache();
166
+ await expect(getTeamKey()).rejects.toBeInstanceOf(RecallApiError);
167
+ // Second call should NOT re-log: the "no token" outcome is memoized.
168
+ await expect(getTeamKey()).rejects.toBeInstanceOf(RecallApiError);
169
+ expect(consoleSpy).toHaveBeenCalledTimes(1);
170
+ });
171
+ });
172
+ describe('getToken: memoization', () => {
173
+ it('does not re-read the auth store on subsequent calls', async () => {
174
+ // Observation: delete the auth store after the first call. If the token
175
+ // cache is working, the second call still returns the first token; if
176
+ // the second call re-read the file, it would fall through to env (unset)
177
+ // and throw NO_TOKEN.
178
+ await writeStore('rcl_memo_test');
179
+ const first = await captureTokenViaFetch();
180
+ expect(first).toBe('rcl_memo_test');
181
+ fs.rmSync(path.join(tmp, 'recall'), { recursive: true, force: true });
182
+ const second = await captureTokenViaFetch();
183
+ expect(second).toBe('rcl_memo_test');
184
+ });
185
+ it('__resetTokenCache forces a fresh read (test seam works)', async () => {
186
+ await writeStore('rcl_first');
187
+ expect(await captureTokenViaFetch()).toBe('rcl_first');
188
+ await writeStore('rcl_second');
189
+ // Without reset, the old token is memoized.
190
+ expect(await captureTokenViaFetch()).toBe('rcl_first');
191
+ __resetTokenCache();
192
+ expect(await captureTokenViaFetch()).toBe('rcl_second');
193
+ });
194
+ });
195
+ //# sourceMappingURL=api-get-token.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-get-token.test.js","sourceRoot":"","sources":["../../src/__tests__/api-get-token.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Tests for explicit `repo` param override on saveSession and logDecision.
3
+ *
4
+ * When a developer's git remote (e.g., raydawg88/stoodio-v2) doesn't match
5
+ * the enrolled Recall repo name (e.g., defendersoftheinternet/stoodio-v2),
6
+ * the explicit `repo` param lets the caller specify the correct name.
7
+ *
8
+ * Mirrors the existing test patterns in get-context-repo-resolution.test.ts.
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=repo-override-save-log.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-override-save-log.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/repo-override-save-log.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,352 @@
1
+ /**
2
+ * Tests for explicit `repo` param override on saveSession and logDecision.
3
+ *
4
+ * When a developer's git remote (e.g., raydawg88/stoodio-v2) doesn't match
5
+ * the enrolled Recall repo name (e.g., defendersoftheinternet/stoodio-v2),
6
+ * the explicit `repo` param lets the caller specify the correct name.
7
+ *
8
+ * Mirrors the existing test patterns in get-context-repo-resolution.test.ts.
9
+ */
10
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
11
+ // Configurable mocks
12
+ const mockExecSync = vi.fn();
13
+ // Mock api module
14
+ vi.mock('../api.js', async (importOriginal) => {
15
+ const actual = await importOriginal();
16
+ return {
17
+ ...actual,
18
+ resolveRepo: vi.fn(),
19
+ resolveRepoFromGraph: vi.fn().mockResolvedValue(null),
20
+ fetchTeamGraph: vi.fn().mockResolvedValue(null),
21
+ getTeamKey: vi.fn().mockResolvedValue('mock-key'),
22
+ getCachedTier: vi.fn().mockReturnValue('team'),
23
+ listRepos: vi.fn().mockResolvedValue([]),
24
+ saveSessionAsync: vi.fn().mockResolvedValue({ id: 'sess_test123' }),
25
+ logDecision: vi.fn().mockResolvedValue({ id: 'dec_test123' }),
26
+ };
27
+ });
28
+ vi.mock('../transcript-finder.js', () => ({
29
+ findCurrentTranscript: vi.fn().mockReturnValue(null),
30
+ readTranscriptFile: vi.fn().mockReturnValue(null),
31
+ }));
32
+ vi.mock('../preprocessor.js', () => ({
33
+ preprocessTranscript: vi.fn().mockResolvedValue({
34
+ content: 'test transcript',
35
+ stats: { originalSize: 100, processedSize: 50, messagesExtracted: 5, errorsFound: 0, toolCallsLogged: 2 },
36
+ }),
37
+ }));
38
+ // Mock child_process — delegates to configurable mockExecSync
39
+ vi.mock('child_process', () => ({
40
+ execSync: (...args) => mockExecSync(...args),
41
+ }));
42
+ // Mock fs
43
+ vi.mock('fs', async (importOriginal) => {
44
+ const actual = await importOriginal();
45
+ return {
46
+ ...actual,
47
+ readdirSync: vi.fn().mockReturnValue([]),
48
+ existsSync: vi.fn().mockReturnValue(false),
49
+ };
50
+ });
51
+ import * as api from '../api.js';
52
+ import { saveSession, logDecision } from '../tools.js';
53
+ // Helper: set up resolveRepoFromGraph to return a valid resolved repo
54
+ function mockResolvedRepo() {
55
+ vi.mocked(api.resolveRepoFromGraph).mockResolvedValue({
56
+ repoId: 'repo-123',
57
+ teamId: 'team-456',
58
+ teamSlug: 'myteam',
59
+ encryptionKey: 'mock-key',
60
+ tier: 'pro',
61
+ });
62
+ }
63
+ describe('saveSession with explicit repo param', () => {
64
+ beforeEach(() => {
65
+ vi.clearAllMocks();
66
+ // Default: not in a git repo
67
+ mockExecSync.mockImplementation(() => {
68
+ throw new Error('fatal: not a git repository');
69
+ });
70
+ });
71
+ // =========================================================================
72
+ // Happy path: explicit repo resolves correctly
73
+ // =========================================================================
74
+ describe('valid repo param', () => {
75
+ it('should save session using the specified repo, skipping filesystem detection', async () => {
76
+ mockResolvedRepo();
77
+ const result = await saveSession({
78
+ repo: 'defendersoftheinternet/stoodio-v2',
79
+ summary: 'Wired contact form',
80
+ });
81
+ expect(result.isError).toBe(false);
82
+ // Should NOT try to read git config
83
+ expect(mockExecSync).not.toHaveBeenCalled();
84
+ // Should resolve with the explicit repo name
85
+ expect(api.resolveRepoFromGraph).toHaveBeenCalledWith('defendersoftheinternet/stoodio-v2');
86
+ });
87
+ it('should NOT call listRepos when repo param is provided', async () => {
88
+ mockResolvedRepo();
89
+ await saveSession({
90
+ repo: 'defendersoftheinternet/stoodio-v2',
91
+ summary: 'Test session',
92
+ });
93
+ expect(api.listRepos).not.toHaveBeenCalled();
94
+ });
95
+ it('should trim whitespace from repo param', async () => {
96
+ mockResolvedRepo();
97
+ await saveSession({
98
+ repo: ' defendersoftheinternet/stoodio-v2 ',
99
+ summary: 'Test session',
100
+ });
101
+ expect(api.resolveRepoFromGraph).toHaveBeenCalledWith('defendersoftheinternet/stoodio-v2');
102
+ });
103
+ it('should take priority over projectPath when both are provided', async () => {
104
+ mockResolvedRepo();
105
+ await saveSession({
106
+ repo: 'defendersoftheinternet/stoodio-v2',
107
+ projectPath: '/some/other/project',
108
+ summary: 'Test session',
109
+ });
110
+ // repo param wins — filesystem detection never called
111
+ expect(mockExecSync).not.toHaveBeenCalled();
112
+ expect(api.resolveRepoFromGraph).toHaveBeenCalledWith('defendersoftheinternet/stoodio-v2');
113
+ });
114
+ });
115
+ // =========================================================================
116
+ // Invalid format
117
+ // =========================================================================
118
+ describe('invalid repo format', () => {
119
+ it('should reject repo without slash (no owner/repo format)', async () => {
120
+ const result = await saveSession({
121
+ repo: 'just-a-name',
122
+ summary: 'Test session',
123
+ });
124
+ expect(result.isError).toBe(true);
125
+ expect(result.content[0].text).toContain('Invalid repo format');
126
+ expect(result.content[0].text).toContain('owner/repo');
127
+ });
128
+ });
129
+ // =========================================================================
130
+ // Empty/whitespace repo falls through to filesystem
131
+ // =========================================================================
132
+ describe('empty repo param', () => {
133
+ it('should fall through to filesystem when repo is empty string', async () => {
134
+ vi.mocked(api.listRepos).mockResolvedValue(['stoodiohq/recall-v3']);
135
+ const result = await saveSession({ repo: '', summary: 'Test' });
136
+ // Should hit the filesystem path (which fails in our mock) then list repos
137
+ expect(result.isError).toBe(true);
138
+ expect(result.content[0].text).toContain('stoodiohq/recall-v3');
139
+ expect(api.resolveRepoFromGraph).not.toHaveBeenCalled();
140
+ });
141
+ it('should fall through to filesystem when repo is whitespace only', async () => {
142
+ vi.mocked(api.listRepos).mockResolvedValue(['stoodiohq/recall-v3']);
143
+ const result = await saveSession({ repo: ' ', summary: 'Test' });
144
+ expect(result.isError).toBe(true);
145
+ expect(result.content[0].text).toContain('stoodiohq/recall-v3');
146
+ expect(api.resolveRepoFromGraph).not.toHaveBeenCalled();
147
+ });
148
+ });
149
+ // =========================================================================
150
+ // Error handling: REPO_NOT_ENROLLED
151
+ // =========================================================================
152
+ describe('repo not enrolled', () => {
153
+ it('should return NOT_ENROLLED with available repos when repo not found', async () => {
154
+ vi.mocked(api.resolveRepoFromGraph).mockResolvedValue(null);
155
+ vi.mocked(api.resolveRepo).mockRejectedValue(new api.RecallApiError('Repo not enrolled', 'REPO_NOT_ENROLLED', 404));
156
+ vi.mocked(api.listRepos).mockResolvedValue([
157
+ 'stoodiohq/recall-v3',
158
+ 'raydawg88/scratch-golf-site',
159
+ ]);
160
+ const result = await saveSession({
161
+ repo: 'raydawg88/nonexistent-repo',
162
+ summary: 'Test',
163
+ });
164
+ expect(result.isError).toBe(true);
165
+ expect(result.content[0].text).toContain('raydawg88/nonexistent-repo');
166
+ expect(result.content[0].text).toContain('stoodiohq/recall-v3');
167
+ });
168
+ it('should return skip-all message when repo not found and no repos configured', async () => {
169
+ vi.mocked(api.resolveRepoFromGraph).mockResolvedValue(null);
170
+ vi.mocked(api.resolveRepo).mockRejectedValue(new api.RecallApiError('Repo not enrolled', 'REPO_NOT_ENROLLED', 404));
171
+ vi.mocked(api.listRepos).mockResolvedValue([]);
172
+ const result = await saveSession({
173
+ repo: 'raydawg88/nonexistent-repo',
174
+ summary: 'Test',
175
+ });
176
+ expect(result.isError).toBe(true);
177
+ expect(result.content[0].text.toLowerCase()).toMatch(/skip.*all.*recall.*tools/i);
178
+ });
179
+ });
180
+ // =========================================================================
181
+ // Error handling: auth
182
+ // =========================================================================
183
+ describe('auth errors', () => {
184
+ it('should handle auth errors on repo param path', async () => {
185
+ vi.mocked(api.resolveRepoFromGraph).mockRejectedValue(new api.RecallApiError('Unauthorized', 'UNAUTHORIZED', 401));
186
+ const result = await saveSession({
187
+ repo: 'raydawg88/my-project',
188
+ summary: 'Test',
189
+ });
190
+ expect(result.isError).toBe(true);
191
+ expect(result.content[0].text).toContain('Authentication failed');
192
+ });
193
+ });
194
+ // =========================================================================
195
+ // Backward compatibility: no repo param still works via filesystem
196
+ // =========================================================================
197
+ describe('backward compatibility (no repo param)', () => {
198
+ it('should still resolve from git remote when no repo param', async () => {
199
+ mockExecSync.mockImplementation((cmd) => {
200
+ if (typeof cmd === 'string' && cmd.includes('remote.origin.url')) {
201
+ return 'git@github.com:stoodiohq/recall-v3.git\n';
202
+ }
203
+ if (typeof cmd === 'string' && cmd.includes('rev-parse --abbrev-ref')) {
204
+ return 'main\n';
205
+ }
206
+ return '';
207
+ });
208
+ mockResolvedRepo();
209
+ const result = await saveSession({ summary: 'Test session' });
210
+ expect(result.isError).toBe(false);
211
+ // Should call git to detect the repo
212
+ expect(mockExecSync).toHaveBeenCalled();
213
+ expect(api.resolveRepoFromGraph).toHaveBeenCalledWith('stoodiohq/recall-v3');
214
+ });
215
+ });
216
+ });
217
+ describe('logDecision with explicit repo param', () => {
218
+ beforeEach(() => {
219
+ vi.clearAllMocks();
220
+ // Default: not in a git repo
221
+ mockExecSync.mockImplementation(() => {
222
+ throw new Error('fatal: not a git repository');
223
+ });
224
+ });
225
+ // =========================================================================
226
+ // Happy path: explicit repo resolves correctly
227
+ // =========================================================================
228
+ describe('valid repo param', () => {
229
+ it('should log decision using the specified repo, skipping filesystem detection', async () => {
230
+ mockResolvedRepo();
231
+ const result = await logDecision({
232
+ repo: 'defendersoftheinternet/stoodio-v2',
233
+ decision: 'Use Cloudflare Worker for contact form',
234
+ reasoning: 'Site is on Cloudflare Pages, simplest path',
235
+ });
236
+ expect(result.isError).toBe(false);
237
+ expect(result.content[0].text).toContain('Decision logged successfully');
238
+ // Should NOT try to read git config
239
+ expect(mockExecSync).not.toHaveBeenCalled();
240
+ expect(api.resolveRepoFromGraph).toHaveBeenCalledWith('defendersoftheinternet/stoodio-v2');
241
+ });
242
+ it('should trim whitespace from repo param', async () => {
243
+ mockResolvedRepo();
244
+ await logDecision({
245
+ repo: ' defendersoftheinternet/stoodio-v2 ',
246
+ decision: 'Test',
247
+ reasoning: 'Test',
248
+ });
249
+ expect(api.resolveRepoFromGraph).toHaveBeenCalledWith('defendersoftheinternet/stoodio-v2');
250
+ });
251
+ it('should take priority over projectPath when both are provided', async () => {
252
+ mockResolvedRepo();
253
+ await logDecision({
254
+ repo: 'defendersoftheinternet/stoodio-v2',
255
+ projectPath: '/some/other/project',
256
+ decision: 'Test',
257
+ reasoning: 'Test',
258
+ });
259
+ expect(mockExecSync).not.toHaveBeenCalled();
260
+ expect(api.resolveRepoFromGraph).toHaveBeenCalledWith('defendersoftheinternet/stoodio-v2');
261
+ });
262
+ });
263
+ // =========================================================================
264
+ // Invalid format
265
+ // =========================================================================
266
+ describe('invalid repo format', () => {
267
+ it('should reject repo without slash', async () => {
268
+ const result = await logDecision({
269
+ repo: 'just-a-name',
270
+ decision: 'Test',
271
+ reasoning: 'Test',
272
+ });
273
+ expect(result.isError).toBe(true);
274
+ expect(result.content[0].text).toContain('Invalid repo format');
275
+ expect(result.content[0].text).toContain('owner/repo');
276
+ });
277
+ });
278
+ // =========================================================================
279
+ // Empty repo falls through to filesystem
280
+ // =========================================================================
281
+ describe('empty repo param', () => {
282
+ it('should fall through to filesystem when repo is empty string', async () => {
283
+ const result = await logDecision({
284
+ repo: '',
285
+ decision: 'Test',
286
+ reasoning: 'Test',
287
+ });
288
+ // No git repo in mock, so it should error
289
+ expect(result.isError).toBe(true);
290
+ expect(result.content[0].text).toContain('Could not determine repository');
291
+ });
292
+ });
293
+ // =========================================================================
294
+ // Error handling: REPO_NOT_ENROLLED
295
+ // =========================================================================
296
+ describe('repo not enrolled', () => {
297
+ it('should return NOT_ENROLLED with available repos', async () => {
298
+ vi.mocked(api.resolveRepoFromGraph).mockResolvedValue(null);
299
+ vi.mocked(api.resolveRepo).mockRejectedValue(new api.RecallApiError('Repo not enrolled', 'REPO_NOT_ENROLLED', 404));
300
+ vi.mocked(api.listRepos).mockResolvedValue([
301
+ 'stoodiohq/recall-v3',
302
+ ]);
303
+ const result = await logDecision({
304
+ repo: 'raydawg88/nonexistent-repo',
305
+ decision: 'Test',
306
+ reasoning: 'Test',
307
+ });
308
+ expect(result.isError).toBe(true);
309
+ expect(result.content[0].text).toContain('raydawg88/nonexistent-repo');
310
+ });
311
+ });
312
+ // =========================================================================
313
+ // Auth errors
314
+ // =========================================================================
315
+ describe('auth errors', () => {
316
+ it('should handle auth errors', async () => {
317
+ vi.mocked(api.resolveRepoFromGraph).mockRejectedValue(new api.RecallApiError('Unauthorized', 'UNAUTHORIZED', 401));
318
+ const result = await logDecision({
319
+ repo: 'raydawg88/my-project',
320
+ decision: 'Test',
321
+ reasoning: 'Test',
322
+ });
323
+ expect(result.isError).toBe(true);
324
+ expect(result.content[0].text).toContain('Authentication failed');
325
+ });
326
+ });
327
+ // =========================================================================
328
+ // Backward compatibility
329
+ // =========================================================================
330
+ describe('backward compatibility (no repo param)', () => {
331
+ it('should still resolve from git remote when no repo param', async () => {
332
+ mockExecSync.mockImplementation((cmd) => {
333
+ if (typeof cmd === 'string' && cmd.includes('remote.origin.url')) {
334
+ return 'git@github.com:stoodiohq/recall-v3.git\n';
335
+ }
336
+ if (typeof cmd === 'string' && cmd.includes('rev-parse --abbrev-ref')) {
337
+ return 'main\n';
338
+ }
339
+ return '';
340
+ });
341
+ mockResolvedRepo();
342
+ const result = await logDecision({
343
+ decision: 'Use Workers',
344
+ reasoning: 'Cloudflare stack',
345
+ });
346
+ expect(result.isError).toBe(false);
347
+ expect(mockExecSync).toHaveBeenCalled();
348
+ expect(api.resolveRepoFromGraph).toHaveBeenCalledWith('stoodiohq/recall-v3');
349
+ });
350
+ });
351
+ });
352
+ //# sourceMappingURL=repo-override-save-log.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-override-save-log.test.js","sourceRoot":"","sources":["../../src/__tests__/repo-override-save-log.test.ts"],"names":[],"mappings":"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"}
package/dist/api.d.ts CHANGED
@@ -2,7 +2,8 @@
2
2
  * Recall API Client
3
3
  *
4
4
  * HTTP client for the Recall v3 API with encryption support.
5
- * - Reads token from RECALL_API_TOKEN environment variable
5
+ * - Reads token from the local auth store (written by `recall-mcp-v3 auth`);
6
+ * falls back to RECALL_API_TOKEN env var for legacy installs.
6
7
  * - Fetches team encryption key from API
7
8
  * - Encrypts content before sending, decrypts after receiving
8
9
  */
@@ -45,6 +46,10 @@ declare class RecallApiError extends Error {
45
46
  status: number;
46
47
  constructor(message: string, code: string, status: number);
47
48
  }
49
+ /** Test-only hook so suites can reset the cached token between runs. */
50
+ export declare function __resetTokenCache(): void;
51
+ /** Exposed for debugging / heartbeat telemetry. */
52
+ export declare function getTokenSource(): 'auth_store' | 'env' | null;
48
53
  /**
49
54
  * Fetch the team encryption key from API.
50
55
  * Caches the key in memory for the duration of the process.