@recall_v3/mcp-server 0.1.0 → 3.0.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.
@@ -1,14 +1,21 @@
1
1
  /**
2
- * Recall Configuration Management
2
+ * Recall v3 Configuration Management
3
3
  *
4
- * Manages the local config file at ~/.recall/config.json.
4
+ * Manages the local config file at ~/.config/recall/config.json.
5
+ * This is intentionally SEPARATE from v2's ~/.recall/ directory.
5
6
  * Handles secure storage of API tokens and team keys.
6
7
  */
7
8
  import type { RecallConfig } from '@recall_v3/shared';
8
9
  /**
9
- * Get the path to the Recall config directory
10
+ * Get the path to the Recall v3 config directory
11
+ * Uses ~/.config/recall/ (XDG-compliant, separate from v2)
10
12
  */
11
13
  export declare function getConfigDir(): string;
14
+ /**
15
+ * Get the path to the legacy v2 config directory
16
+ * (used only for migration checking)
17
+ */
18
+ export declare function getLegacyConfigDir(): string;
12
19
  /**
13
20
  * Get the path to the config file
14
21
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAQtD;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAwCD;;;GAGG;AACH,wBAAgB,UAAU,IAAI,YAAY,CAwBzC;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAe9D;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAQtC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,GAAG,IAAI,CAS3C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAG/C;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAErD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGxD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAI5D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAEpG;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAErD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,IAAI,CAQhC;AAED;;;GAGG;AACH,MAAM,WAAW,cAAe,SAAQ,YAAY;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,CAOlD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AActD;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAqGD;;;GAGG;AACH,wBAAgB,UAAU,IAAI,YAAY,CA2BzC;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAe9D;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAQtC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,GAAG,IAAI,CAS3C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAG/C;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAErD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGxD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAI5D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAEpG;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAErD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,IAAI,CAQhC;AAED;;;GAGG;AACH,MAAM,WAAW,cAAe,SAAQ,YAAY;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,CAOlD"}
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  /**
3
- * Recall Configuration Management
3
+ * Recall v3 Configuration Management
4
4
  *
5
- * Manages the local config file at ~/.recall/config.json.
5
+ * Manages the local config file at ~/.config/recall/config.json.
6
+ * This is intentionally SEPARATE from v2's ~/.recall/ directory.
6
7
  * Handles secure storage of API tokens and team keys.
7
8
  */
8
9
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
@@ -40,6 +41,7 @@ var __importStar = (this && this.__importStar) || (function () {
40
41
  })();
41
42
  Object.defineProperty(exports, "__esModule", { value: true });
42
43
  exports.getConfigDir = getConfigDir;
44
+ exports.getLegacyConfigDir = getLegacyConfigDir;
43
45
  exports.getConfigPath = getConfigPath;
44
46
  exports.loadConfig = loadConfig;
45
47
  exports.saveConfig = saveConfig;
@@ -63,11 +65,23 @@ const os = __importStar(require("node:os"));
63
65
  const CONFIG_VERSION = 1;
64
66
  // Default API base URL (v3)
65
67
  const DEFAULT_API_BASE_URL = 'https://api-v3.recall.team';
68
+ // v3 uses ~/.config/recall/ (XDG-compliant, separate from v2's ~/.recall/)
69
+ const V3_CONFIG_DIR = path.join(os.homedir(), '.config', 'recall');
70
+ // v2 used ~/.recall/ - we check this for migration
71
+ const V2_CONFIG_DIR = path.join(os.homedir(), '.recall');
66
72
  /**
67
- * Get the path to the Recall config directory
73
+ * Get the path to the Recall v3 config directory
74
+ * Uses ~/.config/recall/ (XDG-compliant, separate from v2)
68
75
  */
69
76
  function getConfigDir() {
70
- return path.join(os.homedir(), '.recall');
77
+ return V3_CONFIG_DIR;
78
+ }
79
+ /**
80
+ * Get the path to the legacy v2 config directory
81
+ * (used only for migration checking)
82
+ */
83
+ function getLegacyConfigDir() {
84
+ return V2_CONFIG_DIR;
71
85
  }
72
86
  /**
73
87
  * Get the path to the config file
@@ -108,11 +122,64 @@ function migrateConfig(config) {
108
122
  migrated.version = CONFIG_VERSION;
109
123
  return migrated;
110
124
  }
125
+ /**
126
+ * Check if a config file at a given path is a v3 config
127
+ * v3 configs have teamKeys and a version field (v2 didn't)
128
+ */
129
+ function isV3Config(config) {
130
+ // v3 configs always have version field
131
+ return typeof config.version === 'number' && config.version >= 1;
132
+ }
133
+ /**
134
+ * Migrate v3 config from old v2 location (~/.recall/) to new v3 location (~/.config/recall/)
135
+ * This only migrates if:
136
+ * 1. No config exists at new v3 location
137
+ * 2. A v3 config exists at old v2 location (has version field)
138
+ *
139
+ * v2 configs (without version field) are left alone - they belong to v2
140
+ */
141
+ function migrateFromV2Location() {
142
+ const v3ConfigPath = getConfigPath();
143
+ const v2ConfigPath = path.join(getLegacyConfigDir(), 'config.json');
144
+ // If v3 config already exists at new location, nothing to migrate
145
+ if (fs.existsSync(v3ConfigPath)) {
146
+ return;
147
+ }
148
+ // If no config exists at old v2 location, nothing to migrate
149
+ if (!fs.existsSync(v2ConfigPath)) {
150
+ return;
151
+ }
152
+ try {
153
+ const raw = fs.readFileSync(v2ConfigPath, 'utf-8');
154
+ const parsed = JSON.parse(raw);
155
+ // Only migrate if it's a v3 config (has version field)
156
+ // v2 configs don't have version field and belong to v2
157
+ if (!isV3Config(parsed)) {
158
+ return;
159
+ }
160
+ // This is a v3 config in the old location - migrate it
161
+ console.log(`[Recall v3] Migrating config from ~/.recall/ to ~/.config/recall/`);
162
+ // Ensure new directory exists
163
+ ensureConfigDir();
164
+ // Copy config to new location
165
+ fs.writeFileSync(v3ConfigPath, JSON.stringify(parsed, null, 2), { mode: 0o600 });
166
+ // Remove config from old location (but leave other v2 artifacts)
167
+ // Note: We only remove config.json, not the whole directory
168
+ fs.unlinkSync(v2ConfigPath);
169
+ console.log(`[Recall v3] Migration complete. v3 config is now at ~/.config/recall/config.json`);
170
+ }
171
+ catch (error) {
172
+ // Migration failed - not critical, user can manually migrate
173
+ console.warn(`[Recall v3] Could not migrate config from ~/.recall/ (non-critical)`);
174
+ }
175
+ }
111
176
  /**
112
177
  * Load configuration from disk
113
178
  * Returns a default config if the file doesn't exist
114
179
  */
115
180
  function loadConfig() {
181
+ // First, try to migrate from old v2 location if needed
182
+ migrateFromV2Location();
116
183
  const configPath = getConfigPath();
117
184
  if (!fs.existsSync(configPath)) {
118
185
  return createDefaultConfig();
@@ -53,4 +53,14 @@ export declare function decryptContent(encrypted: string, keyBase64: string): st
53
53
  * Encrypt content and return as JSON string
54
54
  */
55
55
  export declare function encryptContent(plaintext: string, keyBase64: string): string;
56
+ /**
57
+ * Encrypt content and return in Recall format: RECALL_ENCRYPTED:v1:iv:tag:ciphertext
58
+ * This is the format expected by the v3 API.
59
+ */
60
+ export declare function encryptForApi(plaintext: string, keyBase64: string): string;
61
+ /**
62
+ * Decrypt content in Recall format: RECALL_ENCRYPTED:v1:iv:tag:ciphertext
63
+ * This is the format returned by the v3 API.
64
+ */
65
+ export declare function decryptFromApi(encrypted: string, keyBase64: string): string;
56
66
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAO1D;;GAEG;AACH,wBAAgB,UAAU,IAAI,UAAU,CAEvC;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAGpC;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,gBAAgB,CA+B9E;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CA0C5E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAWxE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAEpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CA8BtD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAY3E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAG3E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAO1D;;GAEG;AACH,wBAAgB,UAAU,IAAI,UAAU,CAEvC;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAGpC;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,gBAAgB,CA+B9E;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CA0C5E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAWxE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAEpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CA8BtD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAY3E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAG3E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAG1E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAkB3E"}
@@ -48,6 +48,8 @@ exports.serializeEncrypted = serializeEncrypted;
48
48
  exports.isEncryptedString = isEncryptedString;
49
49
  exports.decryptContent = decryptContent;
50
50
  exports.encryptContent = encryptContent;
51
+ exports.encryptForApi = encryptForApi;
52
+ exports.decryptFromApi = decryptFromApi;
51
53
  const crypto = __importStar(require("node:crypto"));
52
54
  // AES-256-GCM constants
53
55
  const ALGORITHM = 'aes-256-gcm';
@@ -222,3 +224,30 @@ function encryptContent(plaintext, keyBase64) {
222
224
  const payload = encrypt(plaintext, keyBase64);
223
225
  return JSON.stringify(payload);
224
226
  }
227
+ /**
228
+ * Encrypt content and return in Recall format: RECALL_ENCRYPTED:v1:iv:tag:ciphertext
229
+ * This is the format expected by the v3 API.
230
+ */
231
+ function encryptForApi(plaintext, keyBase64) {
232
+ const payload = encrypt(plaintext, keyBase64);
233
+ return `RECALL_ENCRYPTED:v1:${payload.iv}:${payload.tag}:${payload.ciphertext}`;
234
+ }
235
+ /**
236
+ * Decrypt content in Recall format: RECALL_ENCRYPTED:v1:iv:tag:ciphertext
237
+ * This is the format returned by the v3 API.
238
+ */
239
+ function decryptFromApi(encrypted, keyBase64) {
240
+ if (!encrypted.startsWith('RECALL_ENCRYPTED:')) {
241
+ throw new Error('Invalid encrypted format: must start with RECALL_ENCRYPTED:');
242
+ }
243
+ const parts = encrypted.split(':');
244
+ if (parts.length !== 5) {
245
+ throw new Error('Invalid encrypted format: expected RECALL_ENCRYPTED:v1:iv:tag:ciphertext');
246
+ }
247
+ const [, version, iv, tag, ciphertext] = parts;
248
+ if (version !== 'v1') {
249
+ throw new Error(`Unsupported encryption version: ${version}`);
250
+ }
251
+ const payload = { iv, tag, ciphertext };
252
+ return decrypt(payload, keyBase64);
253
+ }
package/dist/index.js CHANGED
@@ -16,8 +16,8 @@ const index_js_2 = require("./tools/index.js");
16
16
  // Tool definitions
17
17
  const TOOLS = [
18
18
  {
19
- name: 'recall_get_context',
20
- description: "Get team brain (context.md) for the current repository. This is the distilled current state - loads automatically at every session start. Use recall_get_history for the full encyclopedia.",
19
+ name: 'recall3_get_context',
20
+ description: "Get team brain (context.md) for the current repository. This is the distilled current state - loads automatically at every session start. Use recall3_get_history for the full encyclopedia.",
21
21
  inputSchema: {
22
22
  type: 'object',
23
23
  properties: {
@@ -29,8 +29,8 @@ const TOOLS = [
29
29
  },
30
30
  },
31
31
  {
32
- name: 'recall_get_history',
33
- description: "Get detailed session history (context.md + recent sessions). This includes more context than recall_get_context but uses more tokens.",
32
+ name: 'recall3_get_history',
33
+ description: "Get detailed session history (context.md + recent sessions). This includes more context than recall3_get_context but uses more tokens.",
34
34
  inputSchema: {
35
35
  type: 'object',
36
36
  properties: {
@@ -43,7 +43,7 @@ const TOOLS = [
43
43
  },
44
44
  },
45
45
  {
46
- name: 'recall_get_transcripts',
46
+ name: 'recall3_get_transcripts',
47
47
  description: "Get full session transcripts (context.md + history.md). WARNING: This can be very large and use many tokens. Only use when you need complete historical details.",
48
48
  inputSchema: {
49
49
  type: 'object',
@@ -57,7 +57,7 @@ const TOOLS = [
57
57
  },
58
58
  },
59
59
  {
60
- name: 'recall_save_session',
60
+ name: 'recall3_save_session',
61
61
  description: "Save a summary of what was accomplished in this coding session. This updates the team memory files.",
62
62
  inputSchema: {
63
63
  type: 'object',
@@ -101,7 +101,7 @@ const TOOLS = [
101
101
  },
102
102
  },
103
103
  {
104
- name: 'recall_log_decision',
104
+ name: 'recall3_log_decision',
105
105
  description: "Log an important decision made during coding. Quick way to capture why something was done.",
106
106
  inputSchema: {
107
107
  type: 'object',
@@ -143,19 +143,19 @@ class RecallMCPServer {
143
143
  try {
144
144
  let result;
145
145
  switch (name) {
146
- case 'recall_get_context':
146
+ case 'recall3_get_context':
147
147
  result = await (0, index_js_2.getContext)(args);
148
148
  break;
149
- case 'recall_get_history':
149
+ case 'recall3_get_history':
150
150
  result = await (0, index_js_2.getHistory)(args);
151
151
  break;
152
- case 'recall_get_transcripts':
152
+ case 'recall3_get_transcripts':
153
153
  result = await (0, index_js_2.getTranscripts)(args);
154
154
  break;
155
- case 'recall_save_session':
155
+ case 'recall3_save_session':
156
156
  result = await (0, index_js_2.saveSession)(args);
157
157
  break;
158
- case 'recall_log_decision':
158
+ case 'recall3_log_decision':
159
159
  result = await (0, index_js_2.logDecision)(args);
160
160
  break;
161
161
  default:
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * getContext Tool Implementation
3
3
  *
4
- * Fetches the team brain (context.md) for the current repository.
4
+ * Fetches the team brain (context) for the current repository from Recall v3 API.
5
5
  * This is the distilled current state - loaded at every session start.
6
6
  */
7
7
  import { type ToolResponse } from './types.js';
@@ -12,7 +12,7 @@ export interface GetContextArgs {
12
12
  * Execute the getContext tool
13
13
  *
14
14
  * @param args - Tool arguments (projectPath is optional)
15
- * @returns MCP tool response with context.md content
15
+ * @returns MCP tool response with context content
16
16
  */
17
17
  export declare function getContext(args: GetContextArgs): Promise<ToolResponse>;
18
18
  //# sourceMappingURL=getContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getContext.d.ts","sourceRoot":"","sources":["../../src/tools/getContext.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAqD,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAGlG,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAkF5E"}
1
+ {"version":3,"file":"getContext.d.ts","sourceRoot":"","sources":["../../src/tools/getContext.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAqD,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAGlG,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA2FD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CA2E5E"}
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * getContext Tool Implementation
4
4
  *
5
- * Fetches the team brain (context.md) for the current repository.
5
+ * Fetches the team brain (context) for the current repository from Recall v3 API.
6
6
  * This is the distilled current state - loaded at every session start.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -12,11 +12,62 @@ const index_js_1 = require("../config/index.js");
12
12
  const index_js_2 = require("../crypto/index.js");
13
13
  const types_js_1 = require("./types.js");
14
14
  const utils_js_1 = require("./utils.js");
15
+ /**
16
+ * Build context markdown from sessions
17
+ */
18
+ function buildContextFromSessions(sessions, teamKey, repoName) {
19
+ const parts = [];
20
+ parts.push(`# Team Memory - ${repoName}`);
21
+ parts.push('');
22
+ parts.push(`Last updated: ${new Date().toISOString().split('T')[0]}`);
23
+ parts.push('');
24
+ if (sessions.length === 0) {
25
+ parts.push('No sessions recorded yet. Use `recall save` to save your first session.');
26
+ return parts.join('\n');
27
+ }
28
+ parts.push('## Recent Sessions');
29
+ parts.push('');
30
+ // Show last 10 sessions for context
31
+ const recentSessions = sessions.slice(0, 10);
32
+ for (const session of recentSessions) {
33
+ const date = session.started_at.split('T')[0];
34
+ const developer = session.user.github_username || session.user.name || 'Unknown';
35
+ parts.push(`### ${date} - ${developer}`);
36
+ parts.push('');
37
+ // Use TLDR summary for quick context
38
+ if (session.tldr_summary) {
39
+ parts.push(session.tldr_summary);
40
+ parts.push('');
41
+ }
42
+ // Try to decrypt and include full content if available
43
+ if (session.encrypted_content && session.encrypted_content.startsWith('RECALL_ENCRYPTED:')) {
44
+ try {
45
+ const decrypted = (0, index_js_2.decryptFromApi)(session.encrypted_content, teamKey);
46
+ parts.push(decrypted);
47
+ parts.push('');
48
+ }
49
+ catch (error) {
50
+ // If decryption fails, just use the TLDR
51
+ if (!session.tldr_summary) {
52
+ parts.push('(Session content encrypted)');
53
+ parts.push('');
54
+ }
55
+ }
56
+ }
57
+ parts.push('---');
58
+ parts.push('');
59
+ }
60
+ if (sessions.length > 10) {
61
+ parts.push(`*${sessions.length - 10} more sessions available. Use recall_get_history for full history.*`);
62
+ parts.push('');
63
+ }
64
+ return parts.join('\n');
65
+ }
15
66
  /**
16
67
  * Execute the getContext tool
17
68
  *
18
69
  * @param args - Tool arguments (projectPath is optional)
19
- * @returns MCP tool response with context.md content
70
+ * @returns MCP tool response with context content
20
71
  */
21
72
  async function getContext(args) {
22
73
  try {
@@ -48,25 +99,11 @@ async function getContext(args) {
48
99
  (0, index_js_1.setTeamKey)(teamId, teamKey);
49
100
  }
50
101
  // Fetch context from API
51
- const response = await client.getContext(repoId);
52
- // The contextMd comes encrypted from the API, decrypt it
53
- let contextMd;
54
- try {
55
- // Check if content is encrypted
56
- if (response.contextMd.startsWith('{') || response.contextMd.includes(':')) {
57
- contextMd = (0, index_js_2.decryptContent)(response.contextMd, teamKey);
58
- }
59
- else {
60
- // Already plaintext (shouldn't happen, but handle gracefully)
61
- contextMd = response.contextMd;
62
- }
63
- }
64
- catch (decryptError) {
65
- // If decryption fails, it might already be plaintext
66
- contextMd = response.contextMd;
67
- }
102
+ const response = await client.getContextV3(repoId);
103
+ // Build context markdown from sessions
104
+ const contextMd = buildContextFromSessions(response.sessions, teamKey, repoInfo.fullName);
68
105
  // Format output with metadata
69
- const header = `Reading from: ${projectPath}/.recall`;
106
+ const header = `# Team Memory (Recall)\n\nThe following is your team's shared context for this repository.\nUse this to understand what has been built, why decisions were made,\nand what mistakes to avoid.\n\n---`;
70
107
  return (0, types_js_1.formattedResponse)(header, contextMd);
71
108
  }
72
109
  catch (error) {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * getHistory Tool Implementation
3
3
  *
4
- * Fetches context.md + recent session history for the repository.
4
+ * Fetches context + recent session history for the repository from Recall v3 API.
5
5
  * This provides more detail than getContext but uses more tokens.
6
6
  */
7
7
  import { type ToolResponse } from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"getHistory.d.ts","sourceRoot":"","sources":["../../src/tools/getHistory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAqD,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAGlG,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CA8F5E"}
1
+ {"version":3,"file":"getHistory.d.ts","sourceRoot":"","sources":["../../src/tools/getHistory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAqD,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAGlG,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAmJD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CA2E5E"}
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * getHistory Tool Implementation
4
4
  *
5
- * Fetches context.md + recent session history for the repository.
5
+ * Fetches context + recent session history for the repository from Recall v3 API.
6
6
  * This provides more detail than getContext but uses more tokens.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -12,6 +12,90 @@ const index_js_1 = require("../config/index.js");
12
12
  const index_js_2 = require("../crypto/index.js");
13
13
  const types_js_1 = require("./types.js");
14
14
  const utils_js_1 = require("./utils.js");
15
+ /**
16
+ * Build history markdown from API response
17
+ */
18
+ function buildHistoryMarkdown(response, teamKey, repoName) {
19
+ const parts = [];
20
+ parts.push(`# Team Memory History - ${repoName}`);
21
+ parts.push('');
22
+ parts.push(`Generated: ${new Date().toISOString()}`);
23
+ parts.push('');
24
+ // Decisions section
25
+ if (response.decisions.length > 0) {
26
+ parts.push('## Key Decisions');
27
+ parts.push('');
28
+ for (const decision of response.decisions) {
29
+ const date = decision.created_at.split('T')[0];
30
+ const author = decision.user.github_username || decision.user.name || 'Unknown';
31
+ parts.push(`### ${date} - ${author}`);
32
+ parts.push('');
33
+ parts.push(`**${decision.title}**`);
34
+ parts.push('');
35
+ // Try to decrypt full content
36
+ if (decision.encrypted_content && decision.encrypted_content.startsWith('RECALL_ENCRYPTED:')) {
37
+ try {
38
+ const decrypted = (0, index_js_2.decryptFromApi)(decision.encrypted_content, teamKey);
39
+ parts.push(decrypted);
40
+ }
41
+ catch {
42
+ // Use title only
43
+ }
44
+ }
45
+ parts.push('');
46
+ }
47
+ parts.push('---');
48
+ parts.push('');
49
+ }
50
+ // Mistakes section
51
+ if (response.mistakes.length > 0) {
52
+ parts.push('## Mistakes & Gotchas');
53
+ parts.push('');
54
+ parts.push('*Things the team learned the hard way - avoid repeating these.*');
55
+ parts.push('');
56
+ for (const mistake of response.mistakes) {
57
+ const date = mistake.created_at.split('T')[0];
58
+ const author = mistake.user.github_username || mistake.user.name || 'Unknown';
59
+ parts.push(`- **${mistake.title}** (${date}, ${author})`);
60
+ }
61
+ parts.push('');
62
+ parts.push('---');
63
+ parts.push('');
64
+ }
65
+ // Sessions section
66
+ parts.push('## Session History');
67
+ parts.push('');
68
+ if (response.sessions.length === 0) {
69
+ parts.push('No sessions recorded yet.');
70
+ }
71
+ else {
72
+ for (const session of response.sessions) {
73
+ const date = session.started_at.split('T')[0];
74
+ const developer = session.user.github_username || session.user.name || 'Unknown';
75
+ parts.push(`### ${date} - ${developer}`);
76
+ parts.push('');
77
+ // TLDR summary
78
+ if (session.tldr_summary) {
79
+ parts.push(`**Summary:** ${session.tldr_summary}`);
80
+ parts.push('');
81
+ }
82
+ // Full content if available
83
+ if (session.encrypted_content && session.encrypted_content.startsWith('RECALL_ENCRYPTED:')) {
84
+ try {
85
+ const decrypted = (0, index_js_2.decryptFromApi)(session.encrypted_content, teamKey);
86
+ parts.push(decrypted);
87
+ }
88
+ catch {
89
+ // Use TLDR only
90
+ }
91
+ }
92
+ parts.push('');
93
+ parts.push('---');
94
+ parts.push('');
95
+ }
96
+ }
97
+ return parts.join('\n');
98
+ }
15
99
  /**
16
100
  * Execute the getHistory tool
17
101
  *
@@ -48,36 +132,15 @@ async function getHistory(args) {
48
132
  (0, index_js_1.setTeamKey)(teamId, teamKey);
49
133
  }
50
134
  // Fetch history from API
51
- const response = await client.getHistory(repoId);
52
- // Decrypt content
53
- let contextMd;
54
- let historyMd;
55
- try {
56
- // Decrypt context
57
- if (response.contextMd.startsWith('{') || response.contextMd.includes(':')) {
58
- contextMd = (0, index_js_2.decryptContent)(response.contextMd, teamKey);
59
- }
60
- else {
61
- contextMd = response.contextMd;
62
- }
63
- // Decrypt history
64
- if (response.historyMd.startsWith('{') || response.historyMd.includes(':')) {
65
- historyMd = (0, index_js_2.decryptContent)(response.historyMd, teamKey);
66
- }
67
- else {
68
- historyMd = response.historyMd;
69
- }
70
- }
71
- catch (decryptError) {
72
- // If decryption fails, use as-is
73
- contextMd = response.contextMd;
74
- historyMd = response.historyMd;
75
- }
76
- // Combine context and history
77
- const combinedContent = `# Recall Context\n\n${contextMd}\n\n---\n\n# Session History\n\n${historyMd}`;
135
+ const response = await client.getHistoryV3(repoId);
136
+ // Build history markdown
137
+ const historyMd = buildHistoryMarkdown(response, teamKey, repoInfo.fullName);
78
138
  // Format output with metadata
79
- const header = `Reading history from: ${projectPath}/.recall (${response.sessionCount} sessions)`;
80
- return (0, types_js_1.formattedResponse)(header, combinedContent);
139
+ const sessionCount = response.sessions.length;
140
+ const decisionCount = response.decisions.length;
141
+ const mistakeCount = response.mistakes.length;
142
+ const header = `# Team Memory (Recall)\n\nRepository: ${repoInfo.fullName}\nSessions: ${sessionCount} | Decisions: ${decisionCount} | Mistakes: ${mistakeCount}\n\n---`;
143
+ return (0, types_js_1.formattedResponse)(header, historyMd);
81
144
  }
82
145
  catch (error) {
83
146
  if (error instanceof client_js_1.AuthenticationError) {
@@ -108,7 +108,7 @@ async function getTranscripts(args) {
108
108
  transcriptsMd,
109
109
  ].join('\n');
110
110
  // Format output
111
- const header = `Reading full transcripts from: ${projectPath}/.recall`;
111
+ const header = `Full session transcripts for: ${repoInfo.fullName}`;
112
112
  return (0, types_js_1.formattedResponse)(header, combinedContent);
113
113
  }
114
114
  catch (error) {
@@ -2,11 +2,16 @@
2
2
  * saveSession Tool Implementation
3
3
  *
4
4
  * Saves a summary of what was accomplished in this coding session.
5
- * Updates the team memory files via the Recall API.
5
+ * Encrypts content with team key and sends to Recall v3 API.
6
6
  */
7
7
  import { type ToolResponse } from './types.js';
8
8
  export interface SaveSessionArgs {
9
- summary: string;
9
+ /** Pre-written summary (if transcript not provided) */
10
+ summary?: string;
11
+ /** Raw conversation transcript - will be summarized by AI */
12
+ transcript?: string;
13
+ /** Git repository path (defaults to cwd if not provided) */
14
+ projectPath?: string;
10
15
  decisions?: Array<{
11
16
  what: string;
12
17
  why: string;
@@ -19,7 +24,7 @@ export interface SaveSessionArgs {
19
24
  /**
20
25
  * Execute the saveSession tool
21
26
  *
22
- * @param args - Tool arguments with session summary and metadata
27
+ * @param args - Tool arguments with session summary/transcript and metadata
23
28
  * @returns MCP tool response with save confirmation
24
29
  */
25
30
  export declare function saveSession(args: SaveSessionArgs): Promise<ToolResponse>;
@@ -1 +1 @@
1
- {"version":3,"file":"saveSession.d.ts","sourceRoot":"","sources":["../../src/tools/saveSession.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAkC,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/E,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,KAAK,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;KACb,CAAC,CAAC;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CA8H9E"}
1
+ {"version":3,"file":"saveSession.d.ts","sourceRoot":"","sources":["../../src/tools/saveSession.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAkC,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/E,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,KAAK,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;KACb,CAAC,CAAC;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA4JD;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CAwM9E"}