claude-code-workflow 6.2.7 → 6.3.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 (208) hide show
  1. package/.claude/CLAUDE.md +16 -1
  2. package/.claude/workflows/cli-templates/protocols/analysis-protocol.md +11 -4
  3. package/.claude/workflows/cli-templates/protocols/write-protocol.md +10 -75
  4. package/.claude/workflows/cli-tools-usage.md +14 -24
  5. package/.codex/AGENTS.md +51 -1
  6. package/.codex/prompts/compact.md +378 -0
  7. package/.gemini/GEMINI.md +57 -20
  8. package/ccw/dist/cli.d.ts.map +1 -1
  9. package/ccw/dist/cli.js +21 -8
  10. package/ccw/dist/cli.js.map +1 -1
  11. package/ccw/dist/commands/cli.d.ts +2 -0
  12. package/ccw/dist/commands/cli.d.ts.map +1 -1
  13. package/ccw/dist/commands/cli.js +129 -8
  14. package/ccw/dist/commands/cli.js.map +1 -1
  15. package/ccw/dist/commands/hook.d.ts.map +1 -1
  16. package/ccw/dist/commands/hook.js +3 -2
  17. package/ccw/dist/commands/hook.js.map +1 -1
  18. package/ccw/dist/config/litellm-api-config-manager.d.ts +180 -0
  19. package/ccw/dist/config/litellm-api-config-manager.d.ts.map +1 -0
  20. package/ccw/dist/config/litellm-api-config-manager.js +770 -0
  21. package/ccw/dist/config/litellm-api-config-manager.js.map +1 -0
  22. package/ccw/dist/config/provider-models.d.ts +73 -0
  23. package/ccw/dist/config/provider-models.d.ts.map +1 -0
  24. package/ccw/dist/config/provider-models.js +172 -0
  25. package/ccw/dist/config/provider-models.js.map +1 -0
  26. package/ccw/dist/core/cache-manager.d.ts.map +1 -1
  27. package/ccw/dist/core/cache-manager.js +3 -5
  28. package/ccw/dist/core/cache-manager.js.map +1 -1
  29. package/ccw/dist/core/dashboard-generator.d.ts.map +1 -1
  30. package/ccw/dist/core/dashboard-generator.js +3 -1
  31. package/ccw/dist/core/dashboard-generator.js.map +1 -1
  32. package/ccw/dist/core/routes/cli-routes.d.ts.map +1 -1
  33. package/ccw/dist/core/routes/cli-routes.js +169 -0
  34. package/ccw/dist/core/routes/cli-routes.js.map +1 -1
  35. package/ccw/dist/core/routes/codexlens-routes.d.ts.map +1 -1
  36. package/ccw/dist/core/routes/codexlens-routes.js +234 -18
  37. package/ccw/dist/core/routes/codexlens-routes.js.map +1 -1
  38. package/ccw/dist/core/routes/hooks-routes.d.ts.map +1 -1
  39. package/ccw/dist/core/routes/hooks-routes.js +30 -32
  40. package/ccw/dist/core/routes/hooks-routes.js.map +1 -1
  41. package/ccw/dist/core/routes/litellm-api-routes.d.ts +21 -0
  42. package/ccw/dist/core/routes/litellm-api-routes.d.ts.map +1 -0
  43. package/ccw/dist/core/routes/litellm-api-routes.js +780 -0
  44. package/ccw/dist/core/routes/litellm-api-routes.js.map +1 -0
  45. package/ccw/dist/core/routes/litellm-routes.d.ts +20 -0
  46. package/ccw/dist/core/routes/litellm-routes.d.ts.map +1 -0
  47. package/ccw/dist/core/routes/litellm-routes.js +85 -0
  48. package/ccw/dist/core/routes/litellm-routes.js.map +1 -0
  49. package/ccw/dist/core/routes/mcp-routes.js +2 -2
  50. package/ccw/dist/core/routes/mcp-routes.js.map +1 -1
  51. package/ccw/dist/core/routes/status-routes.d.ts.map +1 -1
  52. package/ccw/dist/core/routes/status-routes.js +39 -0
  53. package/ccw/dist/core/routes/status-routes.js.map +1 -1
  54. package/ccw/dist/core/routes/system-routes.js +1 -1
  55. package/ccw/dist/core/routes/system-routes.js.map +1 -1
  56. package/ccw/dist/core/server.d.ts.map +1 -1
  57. package/ccw/dist/core/server.js +15 -1
  58. package/ccw/dist/core/server.js.map +1 -1
  59. package/ccw/dist/mcp-server/index.js +1 -1
  60. package/ccw/dist/mcp-server/index.js.map +1 -1
  61. package/ccw/dist/tools/claude-cli-tools.d.ts +82 -0
  62. package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -0
  63. package/ccw/dist/tools/claude-cli-tools.js +216 -0
  64. package/ccw/dist/tools/claude-cli-tools.js.map +1 -0
  65. package/ccw/dist/tools/cli-executor.d.ts.map +1 -1
  66. package/ccw/dist/tools/cli-executor.js +76 -14
  67. package/ccw/dist/tools/cli-executor.js.map +1 -1
  68. package/ccw/dist/tools/codex-lens.d.ts +9 -2
  69. package/ccw/dist/tools/codex-lens.d.ts.map +1 -1
  70. package/ccw/dist/tools/codex-lens.js +114 -9
  71. package/ccw/dist/tools/codex-lens.js.map +1 -1
  72. package/ccw/dist/tools/context-cache-store.d.ts +136 -0
  73. package/ccw/dist/tools/context-cache-store.d.ts.map +1 -0
  74. package/ccw/dist/tools/context-cache-store.js +256 -0
  75. package/ccw/dist/tools/context-cache-store.js.map +1 -0
  76. package/ccw/dist/tools/context-cache.d.ts +56 -0
  77. package/ccw/dist/tools/context-cache.d.ts.map +1 -0
  78. package/ccw/dist/tools/context-cache.js +294 -0
  79. package/ccw/dist/tools/context-cache.js.map +1 -0
  80. package/ccw/dist/tools/core-memory.d.ts.map +1 -1
  81. package/ccw/dist/tools/core-memory.js +33 -19
  82. package/ccw/dist/tools/core-memory.js.map +1 -1
  83. package/ccw/dist/tools/index.d.ts.map +1 -1
  84. package/ccw/dist/tools/index.js +2 -0
  85. package/ccw/dist/tools/index.js.map +1 -1
  86. package/ccw/dist/tools/litellm-client.d.ts +85 -0
  87. package/ccw/dist/tools/litellm-client.d.ts.map +1 -0
  88. package/ccw/dist/tools/litellm-client.js +188 -0
  89. package/ccw/dist/tools/litellm-client.js.map +1 -0
  90. package/ccw/dist/tools/litellm-executor.d.ts +34 -0
  91. package/ccw/dist/tools/litellm-executor.d.ts.map +1 -0
  92. package/ccw/dist/tools/litellm-executor.js +192 -0
  93. package/ccw/dist/tools/litellm-executor.js.map +1 -0
  94. package/ccw/dist/tools/pattern-parser.d.ts +55 -0
  95. package/ccw/dist/tools/pattern-parser.d.ts.map +1 -0
  96. package/ccw/dist/tools/pattern-parser.js +237 -0
  97. package/ccw/dist/tools/pattern-parser.js.map +1 -0
  98. package/ccw/dist/tools/smart-search.d.ts +1 -0
  99. package/ccw/dist/tools/smart-search.d.ts.map +1 -1
  100. package/ccw/dist/tools/smart-search.js +117 -41
  101. package/ccw/dist/tools/smart-search.js.map +1 -1
  102. package/ccw/dist/types/litellm-api-config.d.ts +294 -0
  103. package/ccw/dist/types/litellm-api-config.d.ts.map +1 -0
  104. package/ccw/dist/types/litellm-api-config.js +8 -0
  105. package/ccw/dist/types/litellm-api-config.js.map +1 -0
  106. package/ccw/src/cli.ts +258 -244
  107. package/ccw/src/commands/cli.ts +153 -9
  108. package/ccw/src/commands/hook.ts +3 -2
  109. package/ccw/src/config/.litellm-api-config-manager.ts.2025-12-23T11-57-43-727Z.bak +441 -0
  110. package/ccw/src/config/litellm-api-config-manager.ts +1012 -0
  111. package/ccw/src/config/provider-models.ts +222 -0
  112. package/ccw/src/core/cache-manager.ts +292 -294
  113. package/ccw/src/core/dashboard-generator.ts +3 -1
  114. package/ccw/src/core/routes/cli-routes.ts +192 -0
  115. package/ccw/src/core/routes/codexlens-routes.ts +241 -19
  116. package/ccw/src/core/routes/hooks-routes.ts +399 -405
  117. package/ccw/src/core/routes/litellm-api-routes.ts +930 -0
  118. package/ccw/src/core/routes/litellm-routes.ts +107 -0
  119. package/ccw/src/core/routes/mcp-routes.ts +1271 -1271
  120. package/ccw/src/core/routes/status-routes.ts +51 -0
  121. package/ccw/src/core/routes/system-routes.ts +1 -1
  122. package/ccw/src/core/server.ts +15 -1
  123. package/ccw/src/mcp-server/index.ts +1 -1
  124. package/ccw/src/templates/dashboard-css/12-cli-legacy.css +44 -0
  125. package/ccw/src/templates/dashboard-css/31-api-settings.css +2265 -0
  126. package/ccw/src/templates/dashboard-js/components/cli-history.js +15 -8
  127. package/ccw/src/templates/dashboard-js/components/cli-status.js +323 -9
  128. package/ccw/src/templates/dashboard-js/components/navigation.js +329 -313
  129. package/ccw/src/templates/dashboard-js/i18n.js +583 -1
  130. package/ccw/src/templates/dashboard-js/views/api-settings.js +3362 -0
  131. package/ccw/src/templates/dashboard-js/views/cli-manager.js +199 -24
  132. package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +1265 -27
  133. package/ccw/src/templates/dashboard.html +840 -831
  134. package/ccw/src/tools/claude-cli-tools.ts +300 -0
  135. package/ccw/src/tools/cli-executor.ts +83 -14
  136. package/ccw/src/tools/codex-lens.ts +146 -9
  137. package/ccw/src/tools/context-cache-store.ts +368 -0
  138. package/ccw/src/tools/context-cache.ts +393 -0
  139. package/ccw/src/tools/core-memory.ts +33 -19
  140. package/ccw/src/tools/index.ts +2 -0
  141. package/ccw/src/tools/litellm-client.ts +246 -0
  142. package/ccw/src/tools/litellm-executor.ts +241 -0
  143. package/ccw/src/tools/pattern-parser.ts +329 -0
  144. package/ccw/src/tools/smart-search.ts +142 -41
  145. package/ccw/src/types/litellm-api-config.ts +402 -0
  146. package/ccw-litellm/README.md +180 -0
  147. package/ccw-litellm/pyproject.toml +35 -0
  148. package/ccw-litellm/src/ccw_litellm/__init__.py +47 -0
  149. package/ccw-litellm/src/ccw_litellm/__pycache__/__init__.cpython-313.pyc +0 -0
  150. package/ccw-litellm/src/ccw_litellm/__pycache__/cli.cpython-313.pyc +0 -0
  151. package/ccw-litellm/src/ccw_litellm/cli.py +108 -0
  152. package/ccw-litellm/src/ccw_litellm/clients/__init__.py +12 -0
  153. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/__init__.cpython-313.pyc +0 -0
  154. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_embedder.cpython-313.pyc +0 -0
  155. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_llm.cpython-313.pyc +0 -0
  156. package/ccw-litellm/src/ccw_litellm/clients/litellm_embedder.py +251 -0
  157. package/ccw-litellm/src/ccw_litellm/clients/litellm_llm.py +165 -0
  158. package/ccw-litellm/src/ccw_litellm/config/__init__.py +22 -0
  159. package/ccw-litellm/src/ccw_litellm/config/__pycache__/__init__.cpython-313.pyc +0 -0
  160. package/ccw-litellm/src/ccw_litellm/config/__pycache__/loader.cpython-313.pyc +0 -0
  161. package/ccw-litellm/src/ccw_litellm/config/__pycache__/models.cpython-313.pyc +0 -0
  162. package/ccw-litellm/src/ccw_litellm/config/loader.py +316 -0
  163. package/ccw-litellm/src/ccw_litellm/config/models.py +130 -0
  164. package/ccw-litellm/src/ccw_litellm/interfaces/__init__.py +14 -0
  165. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/__init__.cpython-313.pyc +0 -0
  166. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/embedder.cpython-313.pyc +0 -0
  167. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/llm.cpython-313.pyc +0 -0
  168. package/ccw-litellm/src/ccw_litellm/interfaces/embedder.py +52 -0
  169. package/ccw-litellm/src/ccw_litellm/interfaces/llm.py +45 -0
  170. package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
  171. package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
  172. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
  173. package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
  174. package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-313.pyc +0 -0
  175. package/codex-lens/src/codexlens/cli/commands.py +378 -23
  176. package/codex-lens/src/codexlens/cli/embedding_manager.py +660 -56
  177. package/codex-lens/src/codexlens/cli/model_manager.py +31 -18
  178. package/codex-lens/src/codexlens/cli/output.py +12 -1
  179. package/codex-lens/src/codexlens/config.py +93 -0
  180. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
  181. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
  182. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
  183. package/codex-lens/src/codexlens/search/chain_search.py +6 -2
  184. package/codex-lens/src/codexlens/search/hybrid_search.py +44 -21
  185. package/codex-lens/src/codexlens/search/ranking.py +1 -1
  186. package/codex-lens/src/codexlens/semantic/__init__.py +42 -0
  187. package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-313.pyc +0 -0
  188. package/codex-lens/src/codexlens/semantic/__pycache__/base.cpython-313.pyc +0 -0
  189. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
  190. package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-313.pyc +0 -0
  191. package/codex-lens/src/codexlens/semantic/__pycache__/factory.cpython-313.pyc +0 -0
  192. package/codex-lens/src/codexlens/semantic/__pycache__/gpu_support.cpython-313.pyc +0 -0
  193. package/codex-lens/src/codexlens/semantic/__pycache__/litellm_embedder.cpython-313.pyc +0 -0
  194. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
  195. package/codex-lens/src/codexlens/semantic/base.py +61 -0
  196. package/codex-lens/src/codexlens/semantic/chunker.py +43 -20
  197. package/codex-lens/src/codexlens/semantic/embedder.py +60 -13
  198. package/codex-lens/src/codexlens/semantic/factory.py +98 -0
  199. package/codex-lens/src/codexlens/semantic/gpu_support.py +225 -3
  200. package/codex-lens/src/codexlens/semantic/litellm_embedder.py +144 -0
  201. package/codex-lens/src/codexlens/semantic/rotational_embedder.py +434 -0
  202. package/codex-lens/src/codexlens/semantic/vector_store.py +33 -8
  203. package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-313.pyc +0 -0
  204. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_004_dual_fts.cpython-313.pyc +0 -0
  205. package/codex-lens/src/codexlens/storage/path_mapper.py +27 -1
  206. package/package.json +15 -5
  207. package/.codex/prompts.zip +0 -0
  208. package/ccw/package.json +0 -65
@@ -0,0 +1,393 @@
1
+ /**
2
+ * Context Cache MCP Tool
3
+ * Pack files by @patterns, cache in memory, paginated read by session ID
4
+ *
5
+ * Operations:
6
+ * - pack: Parse @patterns and cache file contents
7
+ * - read: Paginated read from cache by session ID
8
+ * - status: Get cache/session status
9
+ * - release: Release session cache
10
+ * - cleanup: Cleanup expired caches
11
+ */
12
+
13
+ import { z } from 'zod';
14
+ import type { ToolSchema, ToolResult } from '../types/tool.js';
15
+ import { parseAndPack } from './pattern-parser.js';
16
+ import {
17
+ getContextCacheStore,
18
+ type CacheMetadata,
19
+ type PagedReadResult,
20
+ type CacheStatus,
21
+ type SessionStatus,
22
+ } from './context-cache-store.js';
23
+
24
+ // Zod schema for parameter validation
25
+ const OperationEnum = z.enum(['pack', 'read', 'status', 'release', 'cleanup']);
26
+
27
+ const ParamsSchema = z.object({
28
+ operation: OperationEnum,
29
+ // Pack parameters
30
+ patterns: z.array(z.string()).optional(),
31
+ content: z.string().optional(), // Direct text content to cache
32
+ session_id: z.string().optional(),
33
+ cwd: z.string().optional(),
34
+ include_dirs: z.array(z.string()).optional(),
35
+ ttl: z.number().optional(),
36
+ include_metadata: z.boolean().optional().default(true),
37
+ max_file_size: z.number().optional(),
38
+ // Read parameters
39
+ offset: z.number().optional().default(0),
40
+ limit: z.number().optional().default(65536), // 64KB default
41
+ });
42
+
43
+ type Params = z.infer<typeof ParamsSchema>;
44
+
45
+ // Result types
46
+ interface PackResult {
47
+ operation: 'pack';
48
+ session_id: string;
49
+ files_packed: number;
50
+ files_skipped: number;
51
+ total_bytes: number;
52
+ patterns_matched: number;
53
+ patterns_failed: number;
54
+ expires_at: string;
55
+ errors?: string[];
56
+ }
57
+
58
+ interface ReadResult {
59
+ operation: 'read';
60
+ session_id: string;
61
+ content: string;
62
+ offset: number;
63
+ limit: number;
64
+ total_bytes: number;
65
+ has_more: boolean;
66
+ next_offset: number | null;
67
+ }
68
+
69
+ interface StatusResult {
70
+ operation: 'status';
71
+ session_id?: string;
72
+ session?: SessionStatus;
73
+ cache?: CacheStatus;
74
+ }
75
+
76
+ interface ReleaseResult {
77
+ operation: 'release';
78
+ session_id: string;
79
+ released: boolean;
80
+ freed_bytes: number;
81
+ }
82
+
83
+ interface CleanupResult {
84
+ operation: 'cleanup';
85
+ removed: number;
86
+ remaining: number;
87
+ }
88
+
89
+ type OperationResult = PackResult | ReadResult | StatusResult | ReleaseResult | CleanupResult;
90
+
91
+ /**
92
+ * Generate session ID if not provided
93
+ */
94
+ function generateSessionId(): string {
95
+ return `ctx-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
96
+ }
97
+
98
+ /**
99
+ * Operation: pack
100
+ * Parse @patterns and/or cache text content directly
101
+ */
102
+ async function executePack(params: Params): Promise<PackResult> {
103
+ const {
104
+ patterns,
105
+ content,
106
+ session_id,
107
+ cwd,
108
+ include_dirs,
109
+ ttl,
110
+ include_metadata,
111
+ max_file_size,
112
+ } = params;
113
+
114
+ // Require at least patterns or content
115
+ if ((!patterns || patterns.length === 0) && !content) {
116
+ throw new Error('Either "patterns" or "content" is required for pack operation');
117
+ }
118
+
119
+ const sessionId = session_id || generateSessionId();
120
+ const store = getContextCacheStore();
121
+
122
+ let finalContent = '';
123
+ let filesPacked = 0;
124
+ let filesSkipped = 0;
125
+ let totalBytes = 0;
126
+ let patternsMatched = 0;
127
+ let patternsFailed = 0;
128
+ let errors: string[] = [];
129
+ let files: string[] = [];
130
+ let parsedPatterns: string[] = [];
131
+
132
+ // Pack files from patterns if provided
133
+ if (patterns && patterns.length > 0) {
134
+ const result = await parseAndPack(patterns, {
135
+ cwd: cwd || process.cwd(),
136
+ includeDirs: include_dirs,
137
+ includeMetadata: include_metadata,
138
+ maxFileSize: max_file_size,
139
+ });
140
+
141
+ finalContent = result.content;
142
+ filesPacked = result.packedFiles.length;
143
+ filesSkipped = result.skippedFiles.length;
144
+ totalBytes = result.totalBytes;
145
+ patternsMatched = result.parseResult.stats.matched_patterns;
146
+ patternsFailed = result.parseResult.stats.total_patterns - patternsMatched;
147
+ errors = result.parseResult.errors;
148
+ files = result.packedFiles;
149
+ parsedPatterns = result.parseResult.patterns;
150
+ }
151
+
152
+ // Append direct content if provided
153
+ if (content) {
154
+ if (finalContent) {
155
+ finalContent += '\n\n=== ADDITIONAL CONTENT ===\n' + content;
156
+ } else {
157
+ finalContent = content;
158
+ }
159
+ totalBytes += Buffer.byteLength(content, 'utf-8');
160
+ }
161
+
162
+ // Store in cache
163
+ const metadata: CacheMetadata = {
164
+ files,
165
+ patterns: parsedPatterns,
166
+ total_bytes: totalBytes,
167
+ file_count: filesPacked,
168
+ };
169
+
170
+ const entry = store.set(sessionId, finalContent, metadata, ttl);
171
+ const expiresAt = new Date(entry.created_at + entry.ttl).toISOString();
172
+
173
+ return {
174
+ operation: 'pack',
175
+ session_id: sessionId,
176
+ files_packed: filesPacked,
177
+ files_skipped: filesSkipped,
178
+ total_bytes: totalBytes,
179
+ patterns_matched: patternsMatched,
180
+ patterns_failed: patternsFailed,
181
+ expires_at: expiresAt,
182
+ errors: errors.length > 0 ? errors : undefined,
183
+ };
184
+ }
185
+
186
+ /**
187
+ * Operation: read
188
+ * Paginated read from cache
189
+ */
190
+ function executeRead(params: Params): ReadResult {
191
+ const { session_id, offset, limit } = params;
192
+
193
+ if (!session_id) {
194
+ throw new Error('Parameter "session_id" is required for read operation');
195
+ }
196
+
197
+ const store = getContextCacheStore();
198
+ const result = store.read(session_id, offset, limit);
199
+
200
+ if (!result) {
201
+ throw new Error(`Session "${session_id}" not found or expired`);
202
+ }
203
+
204
+ return {
205
+ operation: 'read',
206
+ session_id,
207
+ content: result.content,
208
+ offset: result.offset,
209
+ limit: result.limit,
210
+ total_bytes: result.total_bytes,
211
+ has_more: result.has_more,
212
+ next_offset: result.next_offset,
213
+ };
214
+ }
215
+
216
+ /**
217
+ * Operation: status
218
+ * Get session or overall cache status
219
+ */
220
+ function executeStatus(params: Params): StatusResult {
221
+ const { session_id } = params;
222
+ const store = getContextCacheStore();
223
+
224
+ if (session_id) {
225
+ // Session-specific status
226
+ const sessionStatus = store.getSessionStatus(session_id);
227
+ return {
228
+ operation: 'status',
229
+ session_id,
230
+ session: sessionStatus,
231
+ };
232
+ }
233
+
234
+ // Overall cache status
235
+ const cacheStatus = store.getStatus();
236
+ return {
237
+ operation: 'status',
238
+ cache: cacheStatus,
239
+ };
240
+ }
241
+
242
+ /**
243
+ * Operation: release
244
+ * Release session cache
245
+ */
246
+ function executeRelease(params: Params): ReleaseResult {
247
+ const { session_id } = params;
248
+
249
+ if (!session_id) {
250
+ throw new Error('Parameter "session_id" is required for release operation');
251
+ }
252
+
253
+ const store = getContextCacheStore();
254
+ const result = store.release(session_id);
255
+
256
+ return {
257
+ operation: 'release',
258
+ session_id,
259
+ released: result.released,
260
+ freed_bytes: result.freed_bytes,
261
+ };
262
+ }
263
+
264
+ /**
265
+ * Operation: cleanup
266
+ * Cleanup expired caches
267
+ */
268
+ function executeCleanup(): CleanupResult {
269
+ const store = getContextCacheStore();
270
+ const result = store.cleanupExpired();
271
+ const status = store.getStatus();
272
+
273
+ return {
274
+ operation: 'cleanup',
275
+ removed: result.removed,
276
+ remaining: status.entries,
277
+ };
278
+ }
279
+
280
+ /**
281
+ * Route to operation handler
282
+ */
283
+ async function execute(params: Params): Promise<OperationResult> {
284
+ const { operation } = params;
285
+
286
+ switch (operation) {
287
+ case 'pack':
288
+ return executePack(params);
289
+ case 'read':
290
+ return executeRead(params);
291
+ case 'status':
292
+ return executeStatus(params);
293
+ case 'release':
294
+ return executeRelease(params);
295
+ case 'cleanup':
296
+ return executeCleanup();
297
+ default:
298
+ throw new Error(
299
+ `Unknown operation: ${operation}. Valid operations: pack, read, status, release, cleanup`
300
+ );
301
+ }
302
+ }
303
+
304
+ // MCP Tool Schema
305
+ export const schema: ToolSchema = {
306
+ name: 'context_cache',
307
+ description: `Context file cache with @pattern and text content support, paginated reading.
308
+
309
+ Usage:
310
+ context_cache(operation="pack", patterns=["@src/**/*.ts"], session_id="...")
311
+ context_cache(operation="pack", content="text to cache", session_id="...")
312
+ context_cache(operation="pack", patterns=["@src/**/*.ts"], content="extra text")
313
+ context_cache(operation="read", session_id="...", offset=0, limit=65536)
314
+ context_cache(operation="status", session_id="...")
315
+ context_cache(operation="release", session_id="...")
316
+ context_cache(operation="cleanup")
317
+
318
+ Pattern syntax:
319
+ @src/**/*.ts - All TypeScript files in src
320
+ @CLAUDE.md - Specific file
321
+ @../shared/**/* - Sibling directory (needs include_dirs)`,
322
+ inputSchema: {
323
+ type: 'object',
324
+ properties: {
325
+ operation: {
326
+ type: 'string',
327
+ enum: ['pack', 'read', 'status', 'release', 'cleanup'],
328
+ description: 'Operation to perform',
329
+ },
330
+ patterns: {
331
+ type: 'array',
332
+ items: { type: 'string' },
333
+ description: '@patterns to pack (e.g., ["@src/**/*.ts"]). Either patterns or content required for pack.',
334
+ },
335
+ content: {
336
+ type: 'string',
337
+ description: 'Direct text content to cache. Either patterns or content required for pack.',
338
+ },
339
+ session_id: {
340
+ type: 'string',
341
+ description: 'Cache session ID. Auto-generated for pack if not provided.',
342
+ },
343
+ cwd: {
344
+ type: 'string',
345
+ description: 'Working directory for pattern resolution (default: process.cwd())',
346
+ },
347
+ include_dirs: {
348
+ type: 'array',
349
+ items: { type: 'string' },
350
+ description: 'Additional directories to include for pattern matching',
351
+ },
352
+ ttl: {
353
+ type: 'number',
354
+ description: 'Cache TTL in milliseconds (default: 1800000 = 30min)',
355
+ },
356
+ include_metadata: {
357
+ type: 'boolean',
358
+ description: 'Include file metadata headers in packed content (default: true)',
359
+ },
360
+ max_file_size: {
361
+ type: 'number',
362
+ description: 'Max file size in bytes to include (default: 1MB). Larger files are skipped.',
363
+ },
364
+ offset: {
365
+ type: 'number',
366
+ description: 'Byte offset for paginated read (default: 0)',
367
+ },
368
+ limit: {
369
+ type: 'number',
370
+ description: 'Max bytes to read (default: 65536 = 64KB)',
371
+ },
372
+ },
373
+ required: ['operation'],
374
+ },
375
+ };
376
+
377
+ // Handler function
378
+ export async function handler(
379
+ params: Record<string, unknown>
380
+ ): Promise<ToolResult<OperationResult>> {
381
+ const parsed = ParamsSchema.safeParse(params);
382
+
383
+ if (!parsed.success) {
384
+ return { success: false, error: `Invalid params: ${parsed.error.message}` };
385
+ }
386
+
387
+ try {
388
+ const result = await execute(parsed.data);
389
+ return { success: true, result };
390
+ } catch (error) {
391
+ return { success: false, error: (error as Error).message };
392
+ }
393
+ }
@@ -16,6 +16,8 @@ const OperationEnum = z.enum(['list', 'import', 'export', 'summary', 'embed', 's
16
16
 
17
17
  const ParamsSchema = z.object({
18
18
  operation: OperationEnum,
19
+ // Path parameter - highest priority for project resolution
20
+ path: z.string().optional(),
19
21
  text: z.string().optional(),
20
22
  id: z.string().optional(),
21
23
  tool: z.enum(['gemini', 'qwen']).optional().default('gemini'),
@@ -106,17 +108,21 @@ interface EmbedStatusResult {
106
108
  type OperationResult = ListResult | ImportResult | ExportResult | SummaryResult | EmbedResult | SearchResult | EmbedStatusResult;
107
109
 
108
110
  /**
109
- * Get project path from current working directory
111
+ * Get project path - uses explicit path if provided, otherwise falls back to current working directory
112
+ * Priority: path parameter > getProjectRoot()
110
113
  */
111
- function getProjectPath(): string {
114
+ function getProjectPath(explicitPath?: string): string {
115
+ if (explicitPath) {
116
+ return explicitPath;
117
+ }
112
118
  return getProjectRoot();
113
119
  }
114
120
 
115
121
  /**
116
- * Get database path for current project
122
+ * Get database path for project
117
123
  */
118
- function getDatabasePath(): string {
119
- const projectPath = getProjectPath();
124
+ function getDatabasePath(explicitPath?: string): string {
125
+ const projectPath = getProjectPath(explicitPath);
120
126
  const paths = StoragePaths.project(projectPath);
121
127
  return join(paths.root, 'core-memory', 'core_memory.db');
122
128
  }
@@ -129,8 +135,8 @@ const PREVIEW_MAX_LENGTH = 100;
129
135
  * List all memories with compact output
130
136
  */
131
137
  function executeList(params: Params): ListResult {
132
- const { limit } = params;
133
- const store = getCoreMemoryStore(getProjectPath());
138
+ const { limit, path } = params;
139
+ const store = getCoreMemoryStore(getProjectPath(path));
134
140
  const memories = store.getMemories({ limit }) as CoreMemory[];
135
141
 
136
142
  // Convert to compact format with truncated preview
@@ -160,13 +166,13 @@ function executeList(params: Params): ListResult {
160
166
  * Import text as a new memory
161
167
  */
162
168
  function executeImport(params: Params): ImportResult {
163
- const { text } = params;
169
+ const { text, path } = params;
164
170
 
165
171
  if (!text || text.trim() === '') {
166
172
  throw new Error('Parameter "text" is required for import operation');
167
173
  }
168
174
 
169
- const store = getCoreMemoryStore(getProjectPath());
175
+ const store = getCoreMemoryStore(getProjectPath(path));
170
176
  const memory = store.upsertMemory({
171
177
  content: text.trim(),
172
178
  });
@@ -184,14 +190,14 @@ function executeImport(params: Params): ImportResult {
184
190
  * Searches current project first, then all projects if not found
185
191
  */
186
192
  function executeExport(params: Params): ExportResult {
187
- const { id } = params;
193
+ const { id, path } = params;
188
194
 
189
195
  if (!id) {
190
196
  throw new Error('Parameter "id" is required for export operation');
191
197
  }
192
198
 
193
- // Try current project first
194
- const store = getCoreMemoryStore(getProjectPath());
199
+ // Try current project first (or explicit path if provided)
200
+ const store = getCoreMemoryStore(getProjectPath(path));
195
201
  let memory = store.getMemory(id);
196
202
 
197
203
  // If not found, search across all projects
@@ -218,13 +224,13 @@ function executeExport(params: Params): ExportResult {
218
224
  * Generate AI summary for a memory
219
225
  */
220
226
  async function executeSummary(params: Params): Promise<SummaryResult> {
221
- const { id, tool = 'gemini' } = params;
227
+ const { id, tool = 'gemini', path } = params;
222
228
 
223
229
  if (!id) {
224
230
  throw new Error('Parameter "id" is required for summary operation');
225
231
  }
226
232
 
227
- const store = getCoreMemoryStore(getProjectPath());
233
+ const store = getCoreMemoryStore(getProjectPath(path));
228
234
  const memory = store.getMemory(id);
229
235
 
230
236
  if (!memory) {
@@ -245,8 +251,8 @@ async function executeSummary(params: Params): Promise<SummaryResult> {
245
251
  * Generate embeddings for memory chunks
246
252
  */
247
253
  async function executeEmbed(params: Params): Promise<EmbedResult> {
248
- const { source_id, batch_size = 8, force = false } = params;
249
- const dbPath = getDatabasePath();
254
+ const { source_id, batch_size = 8, force = false, path } = params;
255
+ const dbPath = getDatabasePath(path);
250
256
 
251
257
  const result = await MemoryEmbedder.generateEmbeddings(dbPath, {
252
258
  sourceId: source_id,
@@ -272,13 +278,13 @@ async function executeEmbed(params: Params): Promise<EmbedResult> {
272
278
  * Search memory chunks using semantic search
273
279
  */
274
280
  async function executeSearch(params: Params): Promise<SearchResult> {
275
- const { query, top_k = 10, min_score = 0.3, source_type } = params;
281
+ const { query, top_k = 10, min_score = 0.3, source_type, path } = params;
276
282
 
277
283
  if (!query) {
278
284
  throw new Error('Parameter "query" is required for search operation');
279
285
  }
280
286
 
281
- const dbPath = getDatabasePath();
287
+ const dbPath = getDatabasePath(path);
282
288
 
283
289
  const result = await MemoryEmbedder.searchMemories(dbPath, query, {
284
290
  topK: top_k,
@@ -309,7 +315,8 @@ async function executeSearch(params: Params): Promise<SearchResult> {
309
315
  * Get embedding status statistics
310
316
  */
311
317
  async function executeEmbedStatus(params: Params): Promise<EmbedStatusResult> {
312
- const dbPath = getDatabasePath();
318
+ const { path } = params;
319
+ const dbPath = getDatabasePath(path);
313
320
 
314
321
  const result = await MemoryEmbedder.getEmbeddingStatus(dbPath);
315
322
 
@@ -368,6 +375,9 @@ Usage:
368
375
  core_memory(operation="search", query="authentication") # Search memories semantically
369
376
  core_memory(operation="embed_status") # Check embedding status
370
377
 
378
+ Path parameter (highest priority):
379
+ core_memory(operation="list", path="/path/to/project") # Use specific project path
380
+
371
381
  Memory IDs use format: CMEM-YYYYMMDD-HHMMSS`,
372
382
  inputSchema: {
373
383
  type: 'object',
@@ -377,6 +387,10 @@ Memory IDs use format: CMEM-YYYYMMDD-HHMMSS`,
377
387
  enum: ['list', 'import', 'export', 'summary', 'embed', 'search', 'embed_status'],
378
388
  description: 'Operation to perform',
379
389
  },
390
+ path: {
391
+ type: 'string',
392
+ description: 'Project path (highest priority - overrides auto-detected project root)',
393
+ },
380
394
  text: {
381
395
  type: 'string',
382
396
  description: 'Text content to import (required for import operation)',
@@ -22,6 +22,7 @@ import { executeInitWithProgress } from './smart-search.js';
22
22
  // codex_lens removed - functionality integrated into smart_search
23
23
  import * as readFileMod from './read-file.js';
24
24
  import * as coreMemoryMod from './core-memory.js';
25
+ import * as contextCacheMod from './context-cache.js';
25
26
  import type { ProgressInfo } from './codex-lens.js';
26
27
 
27
28
  // Import legacy JS tools
@@ -357,6 +358,7 @@ registerTool(toLegacyTool(smartSearchMod));
357
358
  // codex_lens removed - functionality integrated into smart_search
358
359
  registerTool(toLegacyTool(readFileMod));
359
360
  registerTool(toLegacyTool(coreMemoryMod));
361
+ registerTool(toLegacyTool(contextCacheMod));
360
362
 
361
363
  // Register legacy JS tools
362
364
  registerTool(uiGeneratePreviewTool);