grov 0.5.11 → 0.6.13

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 (190) hide show
  1. package/dist/cli/agents/registry.d.ts +17 -0
  2. package/dist/cli/agents/registry.js +132 -0
  3. package/dist/cli/commands/agents.d.ts +1 -0
  4. package/dist/cli/commands/agents.js +48 -0
  5. package/dist/cli/commands/disable.d.ts +1 -0
  6. package/dist/cli/commands/disable.js +179 -0
  7. package/dist/cli/commands/doctor.d.ts +1 -0
  8. package/dist/cli/commands/doctor.js +157 -0
  9. package/dist/{commands → cli/commands}/drift-test.js +39 -26
  10. package/dist/cli/commands/init.d.ts +1 -0
  11. package/dist/cli/commands/init.js +90 -0
  12. package/dist/{commands → cli/commands}/login.js +19 -18
  13. package/dist/{commands → cli/commands}/logout.js +1 -1
  14. package/dist/{commands → cli/commands}/proxy-status.js +1 -1
  15. package/dist/cli/commands/setup.d.ts +6 -0
  16. package/dist/cli/commands/setup.js +309 -0
  17. package/dist/{commands → cli/commands}/status.js +1 -1
  18. package/dist/{commands → cli/commands}/sync.d.ts +1 -0
  19. package/dist/{commands → cli/commands}/sync.js +59 -4
  20. package/dist/{commands → cli/commands}/uninstall.js +2 -2
  21. package/dist/cli/index.js +270 -0
  22. package/dist/{lib → core/cloud}/cloud-sync.d.ts +3 -3
  23. package/dist/{lib → core/cloud}/cloud-sync.js +10 -10
  24. package/dist/{lib → core/extraction}/correction-builder-proxy.d.ts +1 -1
  25. package/dist/{lib → core/extraction}/correction-builder-proxy.js +0 -4
  26. package/dist/{lib → core/extraction}/drift-checker-proxy.d.ts +13 -9
  27. package/dist/core/extraction/drift-checker-proxy.js +510 -0
  28. package/dist/{lib → core/extraction}/llm-extractor.d.ts +8 -38
  29. package/dist/{lib → core/extraction}/llm-extractor.js +132 -220
  30. package/dist/{lib → core}/store/sessions.js +3 -19
  31. package/dist/core/store/store.d.ts +1 -0
  32. package/dist/{lib → core/store}/store.js +1 -1
  33. package/dist/{lib → core}/store/types.d.ts +0 -4
  34. package/dist/integrations/mcp/cache.d.ts +27 -0
  35. package/dist/integrations/mcp/cache.js +106 -0
  36. package/dist/integrations/mcp/capture/antigravity-parser.d.ts +26 -0
  37. package/dist/integrations/mcp/capture/antigravity-parser.js +272 -0
  38. package/dist/integrations/mcp/capture/antigravity-scanner.d.ts +24 -0
  39. package/dist/integrations/mcp/capture/antigravity-scanner.js +153 -0
  40. package/dist/integrations/mcp/capture/antigravity-sync-tracker.d.ts +29 -0
  41. package/dist/integrations/mcp/capture/antigravity-sync-tracker.js +115 -0
  42. package/dist/integrations/mcp/capture/cli-extractor.d.ts +18 -0
  43. package/dist/integrations/mcp/capture/cli-extractor.js +258 -0
  44. package/dist/integrations/mcp/capture/cli-synced.d.ts +4 -0
  45. package/dist/integrations/mcp/capture/cli-synced.js +62 -0
  46. package/dist/integrations/mcp/capture/cli-transform.d.ts +30 -0
  47. package/dist/integrations/mcp/capture/cli-transform.js +62 -0
  48. package/dist/integrations/mcp/capture/cli-watcher.d.ts +31 -0
  49. package/dist/integrations/mcp/capture/cli-watcher.js +106 -0
  50. package/dist/integrations/mcp/capture/hook-handler.d.ts +2 -0
  51. package/dist/integrations/mcp/capture/hook-handler.js +157 -0
  52. package/dist/integrations/mcp/capture/sqlite-reader.d.ts +35 -0
  53. package/dist/integrations/mcp/capture/sqlite-reader.js +388 -0
  54. package/dist/integrations/mcp/capture/sync-tracker.d.ts +16 -0
  55. package/dist/integrations/mcp/capture/sync-tracker.js +102 -0
  56. package/dist/integrations/mcp/clients/cursor/rules-installer.d.ts +19 -0
  57. package/dist/integrations/mcp/clients/cursor/rules-installer.js +123 -0
  58. package/dist/integrations/mcp/index.d.ts +1 -0
  59. package/dist/integrations/mcp/index.js +94 -0
  60. package/dist/integrations/mcp/logger.d.ts +8 -0
  61. package/dist/integrations/mcp/logger.js +50 -0
  62. package/dist/integrations/mcp/server.d.ts +5 -0
  63. package/dist/integrations/mcp/server.js +58 -0
  64. package/dist/integrations/mcp/tools/expand.d.ts +1 -0
  65. package/dist/integrations/mcp/tools/expand.js +53 -0
  66. package/dist/integrations/mcp/tools/preview.d.ts +1 -0
  67. package/dist/integrations/mcp/tools/preview.js +64 -0
  68. package/dist/integrations/proxy/agents/base.d.ts +43 -0
  69. package/dist/integrations/proxy/agents/base.js +13 -0
  70. package/dist/{proxy/utils → integrations/proxy/agents/claude}/extractors.d.ts +4 -8
  71. package/dist/{proxy/utils → integrations/proxy/agents/claude}/extractors.js +4 -33
  72. package/dist/{proxy → integrations/proxy/agents/claude}/forwarder.d.ts +1 -1
  73. package/dist/{proxy → integrations/proxy/agents/claude}/forwarder.js +22 -6
  74. package/dist/integrations/proxy/agents/claude/index.d.ts +43 -0
  75. package/dist/integrations/proxy/agents/claude/index.js +386 -0
  76. package/dist/{proxy/action-parser.d.ts → integrations/proxy/agents/claude/parser.d.ts} +1 -1
  77. package/dist/integrations/proxy/agents/codex/extractors.d.ts +6 -0
  78. package/dist/integrations/proxy/agents/codex/extractors.js +49 -0
  79. package/dist/integrations/proxy/agents/codex/forwarder.d.ts +9 -0
  80. package/dist/integrations/proxy/agents/codex/forwarder.js +125 -0
  81. package/dist/integrations/proxy/agents/codex/index.d.ts +44 -0
  82. package/dist/integrations/proxy/agents/codex/index.js +371 -0
  83. package/dist/integrations/proxy/agents/codex/parser.d.ts +11 -0
  84. package/dist/integrations/proxy/agents/codex/parser.js +104 -0
  85. package/dist/integrations/proxy/agents/codex/patch.d.ts +12 -0
  86. package/dist/integrations/proxy/agents/codex/patch.js +40 -0
  87. package/dist/integrations/proxy/agents/codex/settings.d.ts +18 -0
  88. package/dist/integrations/proxy/agents/codex/settings.js +73 -0
  89. package/dist/integrations/proxy/agents/codex/types.d.ts +59 -0
  90. package/dist/integrations/proxy/agents/codex/types.js +2 -0
  91. package/dist/integrations/proxy/agents/index.d.ts +11 -0
  92. package/dist/integrations/proxy/agents/index.js +25 -0
  93. package/dist/integrations/proxy/agents/types.d.ts +77 -0
  94. package/dist/integrations/proxy/agents/types.js +2 -0
  95. package/dist/{proxy → integrations/proxy/cache}/extended-cache.js +2 -6
  96. package/dist/{proxy → integrations/proxy}/config.js +1 -1
  97. package/dist/{proxy → integrations/proxy}/handlers/preprocess.d.ts +3 -3
  98. package/dist/integrations/proxy/handlers/preprocess.js +194 -0
  99. package/dist/integrations/proxy/index.js +20 -0
  100. package/dist/integrations/proxy/injection/memory-injection.d.ts +56 -0
  101. package/dist/integrations/proxy/injection/memory-injection.js +252 -0
  102. package/dist/integrations/proxy/orchestrator.d.ts +30 -0
  103. package/dist/integrations/proxy/orchestrator.js +954 -0
  104. package/dist/integrations/proxy/request-processor.d.ts +14 -0
  105. package/dist/integrations/proxy/request-processor.js +68 -0
  106. package/dist/{proxy → integrations/proxy}/response-processor.d.ts +4 -3
  107. package/dist/{proxy → integrations/proxy}/response-processor.js +51 -43
  108. package/dist/{proxy → integrations/proxy}/server.d.ts +0 -1
  109. package/dist/integrations/proxy/server.js +146 -0
  110. package/dist/{proxy → integrations/proxy}/types.d.ts +4 -0
  111. package/dist/{proxy → integrations/proxy}/utils/logging.d.ts +1 -0
  112. package/dist/{proxy → integrations/proxy}/utils/logging.js +5 -0
  113. package/package.json +31 -10
  114. package/postinstall.js +62 -6
  115. package/dist/cli.js +0 -149
  116. package/dist/commands/capture.d.ts +0 -6
  117. package/dist/commands/capture.js +0 -324
  118. package/dist/commands/disable.d.ts +0 -1
  119. package/dist/commands/disable.js +0 -14
  120. package/dist/commands/doctor.d.ts +0 -1
  121. package/dist/commands/doctor.js +0 -89
  122. package/dist/commands/init.d.ts +0 -1
  123. package/dist/commands/init.js +0 -52
  124. package/dist/commands/inject.d.ts +0 -5
  125. package/dist/commands/inject.js +0 -88
  126. package/dist/commands/prompt-inject.d.ts +0 -4
  127. package/dist/commands/prompt-inject.js +0 -451
  128. package/dist/commands/unregister.d.ts +0 -1
  129. package/dist/commands/unregister.js +0 -28
  130. package/dist/lib/anchor-extractor.d.ts +0 -30
  131. package/dist/lib/anchor-extractor.js +0 -296
  132. package/dist/lib/correction-builder.d.ts +0 -10
  133. package/dist/lib/correction-builder.js +0 -226
  134. package/dist/lib/drift-checker-proxy.js +0 -373
  135. package/dist/lib/drift-checker.d.ts +0 -66
  136. package/dist/lib/drift-checker.js +0 -341
  137. package/dist/lib/hooks.d.ts +0 -38
  138. package/dist/lib/hooks.js +0 -291
  139. package/dist/lib/jsonl-parser.d.ts +0 -87
  140. package/dist/lib/jsonl-parser.js +0 -281
  141. package/dist/lib/session-parser.d.ts +0 -44
  142. package/dist/lib/session-parser.js +0 -256
  143. package/dist/lib/store.d.ts +0 -1
  144. package/dist/proxy/cache.d.ts +0 -32
  145. package/dist/proxy/cache.js +0 -47
  146. package/dist/proxy/handlers/preprocess.js +0 -186
  147. package/dist/proxy/index.js +0 -30
  148. package/dist/proxy/injection/delta-tracking.d.ts +0 -11
  149. package/dist/proxy/injection/delta-tracking.js +0 -94
  150. package/dist/proxy/injection/injectors.d.ts +0 -7
  151. package/dist/proxy/injection/injectors.js +0 -139
  152. package/dist/proxy/request-processor.d.ts +0 -27
  153. package/dist/proxy/request-processor.js +0 -233
  154. package/dist/proxy/server.js +0 -1289
  155. /package/dist/{commands → cli/commands}/drift-test.d.ts +0 -0
  156. /package/dist/{commands → cli/commands}/login.d.ts +0 -0
  157. /package/dist/{commands → cli/commands}/logout.d.ts +0 -0
  158. /package/dist/{commands → cli/commands}/proxy-status.d.ts +0 -0
  159. /package/dist/{commands → cli/commands}/status.d.ts +0 -0
  160. /package/dist/{commands → cli/commands}/uninstall.d.ts +0 -0
  161. /package/dist/{cli.d.ts → cli/index.d.ts} +0 -0
  162. /package/dist/{lib → core/cloud}/api-client.d.ts +0 -0
  163. /package/dist/{lib → core/cloud}/api-client.js +0 -0
  164. /package/dist/{lib → core/cloud}/credentials.d.ts +0 -0
  165. /package/dist/{lib → core/cloud}/credentials.js +0 -0
  166. /package/dist/{lib → core}/store/convenience.d.ts +0 -0
  167. /package/dist/{lib → core}/store/convenience.js +0 -0
  168. /package/dist/{lib → core}/store/database.d.ts +0 -0
  169. /package/dist/{lib → core}/store/database.js +0 -0
  170. /package/dist/{lib → core}/store/drift.d.ts +0 -0
  171. /package/dist/{lib → core}/store/drift.js +0 -0
  172. /package/dist/{lib → core}/store/index.d.ts +0 -0
  173. /package/dist/{lib → core}/store/index.js +0 -0
  174. /package/dist/{lib → core}/store/sessions.d.ts +0 -0
  175. /package/dist/{lib → core}/store/steps.d.ts +0 -0
  176. /package/dist/{lib → core}/store/steps.js +0 -0
  177. /package/dist/{lib → core}/store/tasks.d.ts +0 -0
  178. /package/dist/{lib → core}/store/tasks.js +0 -0
  179. /package/dist/{lib → core}/store/types.js +0 -0
  180. /package/dist/{proxy/action-parser.js → integrations/proxy/agents/claude/parser.js} +0 -0
  181. /package/dist/{lib → integrations/proxy/agents/claude}/settings.d.ts +0 -0
  182. /package/dist/{lib → integrations/proxy/agents/claude}/settings.js +0 -0
  183. /package/dist/{proxy → integrations/proxy/cache}/extended-cache.d.ts +0 -0
  184. /package/dist/{proxy → integrations/proxy}/config.d.ts +0 -0
  185. /package/dist/{proxy → integrations/proxy}/index.d.ts +0 -0
  186. /package/dist/{proxy → integrations/proxy}/types.js +0 -0
  187. /package/dist/{lib → utils}/debug.d.ts +0 -0
  188. /package/dist/{lib → utils}/debug.js +0 -0
  189. /package/dist/{lib → utils}/utils.d.ts +0 -0
  190. /package/dist/{lib → utils}/utils.js +0 -0
@@ -0,0 +1,17 @@
1
+ export type AgentType = 'cli' | 'ide';
2
+ export interface CliAgent {
3
+ id: string;
4
+ name: string;
5
+ description: string;
6
+ type: AgentType;
7
+ command: string;
8
+ requirements: string[];
9
+ configPath: string;
10
+ isConfigured: () => boolean;
11
+ }
12
+ export declare function getAllCliAgents(): CliAgent[];
13
+ export declare function getCliAgentsByType(type: AgentType): CliAgent[];
14
+ export declare function getCliAgentById(id: string): CliAgent | undefined;
15
+ export declare function isAnyAgentConfigured(): boolean;
16
+ export declare function getConfiguredAgents(): CliAgent[];
17
+ export declare function getFirstConfiguredAgent(): CliAgent | null;
@@ -0,0 +1,132 @@
1
+ // Centralized agent registry for CLI operations
2
+ // Add new agents here - all CLI commands will see them
3
+ import { existsSync, readFileSync } from 'fs';
4
+ import { homedir } from 'os';
5
+ import { join } from 'path';
6
+ import { parse } from 'smol-toml';
7
+ const CLAUDE_SETTINGS_PATH = join(homedir(), '.claude', 'settings.json');
8
+ const CODEX_CONFIG_PATH = join(homedir(), '.codex', 'config.toml');
9
+ const CURSOR_MCP_PATH = join(homedir(), '.cursor', 'mcp.json');
10
+ const ZED_SETTINGS_PATH = join(homedir(), '.config', 'zed', 'settings.json');
11
+ const ANTIGRAVITY_MCP_PATH = join(homedir(), '.gemini', 'antigravity', 'mcp_config.json');
12
+ const AGENTS = [
13
+ {
14
+ id: 'claude',
15
+ name: 'Claude Code',
16
+ description: "Anthropic's coding agent",
17
+ type: 'cli',
18
+ command: 'claude',
19
+ requirements: ['Claude Code CLI (npm i -g @anthropic-ai/claude-code)'],
20
+ configPath: CLAUDE_SETTINGS_PATH,
21
+ isConfigured: () => {
22
+ if (!existsSync(CLAUDE_SETTINGS_PATH))
23
+ return false;
24
+ try {
25
+ const settings = JSON.parse(readFileSync(CLAUDE_SETTINGS_PATH, 'utf-8'));
26
+ return settings.env?.ANTHROPIC_BASE_URL === 'http://127.0.0.1:8080';
27
+ }
28
+ catch {
29
+ return false;
30
+ }
31
+ },
32
+ },
33
+ {
34
+ id: 'codex',
35
+ name: 'Codex',
36
+ description: "OpenAI's CLI agent",
37
+ type: 'cli',
38
+ command: 'codex',
39
+ requirements: ['OPENAI_API_KEY environment variable', 'Codex CLI (npm i -g @openai/codex)'],
40
+ configPath: CODEX_CONFIG_PATH,
41
+ isConfigured: () => {
42
+ if (!existsSync(CODEX_CONFIG_PATH))
43
+ return false;
44
+ try {
45
+ const content = readFileSync(CODEX_CONFIG_PATH, 'utf-8');
46
+ const config = parse(content);
47
+ return config.model_provider === 'grov' && !!config.model_providers?.grov;
48
+ }
49
+ catch {
50
+ return false;
51
+ }
52
+ },
53
+ },
54
+ {
55
+ id: 'cursor',
56
+ name: 'Cursor',
57
+ description: 'Cursor IDE',
58
+ type: 'ide',
59
+ command: 'cursor',
60
+ requirements: ['Cursor IDE installed'],
61
+ configPath: CURSOR_MCP_PATH,
62
+ isConfigured: () => {
63
+ if (!existsSync(CURSOR_MCP_PATH))
64
+ return false;
65
+ try {
66
+ const config = JSON.parse(readFileSync(CURSOR_MCP_PATH, 'utf-8'));
67
+ return !!config.mcpServers?.grov;
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ },
73
+ },
74
+ {
75
+ id: 'zed',
76
+ name: 'Zed',
77
+ description: 'Zed Editor',
78
+ type: 'ide',
79
+ command: 'zed',
80
+ requirements: ['Zed Editor installed'],
81
+ configPath: ZED_SETTINGS_PATH,
82
+ isConfigured: () => {
83
+ if (!existsSync(ZED_SETTINGS_PATH))
84
+ return false;
85
+ try {
86
+ const config = JSON.parse(readFileSync(ZED_SETTINGS_PATH, 'utf-8'));
87
+ return !!config.context_servers?.grov;
88
+ }
89
+ catch {
90
+ return false;
91
+ }
92
+ },
93
+ },
94
+ {
95
+ id: 'antigravity',
96
+ name: 'Antigravity',
97
+ description: 'Google Antigravity IDE',
98
+ type: 'ide',
99
+ command: 'antigravity',
100
+ requirements: ['Antigravity IDE installed'],
101
+ configPath: ANTIGRAVITY_MCP_PATH,
102
+ isConfigured: () => {
103
+ if (!existsSync(ANTIGRAVITY_MCP_PATH))
104
+ return false;
105
+ try {
106
+ const config = JSON.parse(readFileSync(ANTIGRAVITY_MCP_PATH, 'utf-8'));
107
+ return !!config.mcpServers?.grov;
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ },
113
+ },
114
+ ];
115
+ export function getAllCliAgents() {
116
+ return AGENTS;
117
+ }
118
+ export function getCliAgentsByType(type) {
119
+ return AGENTS.filter(a => a.type === type);
120
+ }
121
+ export function getCliAgentById(id) {
122
+ return AGENTS.find(a => a.id === id);
123
+ }
124
+ export function isAnyAgentConfigured() {
125
+ return AGENTS.some(a => a.isConfigured());
126
+ }
127
+ export function getConfiguredAgents() {
128
+ return AGENTS.filter(a => a.isConfigured());
129
+ }
130
+ export function getFirstConfiguredAgent() {
131
+ return AGENTS.find(a => a.isConfigured()) ?? null;
132
+ }
@@ -0,0 +1 @@
1
+ export declare function agents(): void;
@@ -0,0 +1,48 @@
1
+ // grov agents - List supported agents and setup instructions
2
+ import { getCliAgentsByType } from '../agents/registry.js';
3
+ const green = '\x1b[32m';
4
+ const dim = '\x1b[90m';
5
+ const cyan = '\x1b[36m';
6
+ const reset = '\x1b[0m';
7
+ export function agents() {
8
+ const cliAgents = getCliAgentsByType('cli');
9
+ const ideAgents = getCliAgentsByType('ide');
10
+ console.log('\nSupported Agents');
11
+ console.log('================\n');
12
+ console.log('CLI AGENTS (require proxy running)');
13
+ console.log('──────────────────────────────────');
14
+ for (const agent of cliAgents) {
15
+ printAgent(agent);
16
+ }
17
+ console.log('IDE AGENTS (native integration, no proxy)');
18
+ console.log('─────────────────────────────────────────');
19
+ for (const agent of ideAgents) {
20
+ printAgent(agent);
21
+ }
22
+ console.log('Quick Start');
23
+ console.log('───────────\n');
24
+ console.log(`${cyan}CLI AGENTS${reset} (Claude Code, Codex):`);
25
+ console.log(' 1. grov init <agent>');
26
+ console.log(' 2. grov proxy (keep running)');
27
+ console.log(' 3. Use agent in another terminal\n');
28
+ console.log(`${cyan}IDE AGENTS${reset} (Cursor, Zed):`);
29
+ console.log(' 1. grov init <agent>');
30
+ console.log(' 2. Restart your IDE');
31
+ console.log(' 3. Use normally - grov runs automatically\n');
32
+ console.log(`Troubleshooting: ${cyan}grov doctor <agent>${reset} for detailed checks\n`);
33
+ }
34
+ function printAgent(agent) {
35
+ const configured = agent.isConfigured();
36
+ const statusIcon = configured ? `${green}●${reset}` : `${dim}○${reset}`;
37
+ const statusText = configured ? `${green}Configured${reset}` : `${dim}Not configured${reset}`;
38
+ console.log(`${statusIcon} ${agent.name} - ${agent.description}`);
39
+ console.log(` Status: ${statusText}`);
40
+ if (!configured) {
41
+ console.log(` Setup: grov init ${agent.id}`);
42
+ console.log(' Requires:');
43
+ for (const req of agent.requirements) {
44
+ console.log(` • ${req}`);
45
+ }
46
+ }
47
+ console.log('');
48
+ }
@@ -0,0 +1 @@
1
+ export declare function disable(agentName?: 'claude' | 'codex' | 'cursor' | 'antigravity' | 'zed'): Promise<void>;
@@ -0,0 +1,179 @@
1
+ // grov disable - Remove proxy/MCP configuration
2
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { homedir } from 'os';
5
+ import { getAgentByName } from '../../integrations/proxy/agents/index.js';
6
+ import { removeProjectRulesPointer } from '../../integrations/mcp/clients/cursor/rules-installer.js';
7
+ export async function disable(agentName = 'claude') {
8
+ // Cursor: MCP-based disable
9
+ if (agentName === 'cursor') {
10
+ console.log('Disabling grov for Cursor...\n');
11
+ // 1. Remove MCP registration (global)
12
+ const mcpResult = removeCursorMcp();
13
+ // 2. Remove stop hook (global)
14
+ const hooksResult = removeCursorHooks();
15
+ // 3. Remove project rules pointer (keeps .grov/)
16
+ const projectDir = process.cwd();
17
+ const pointerRemoved = removeProjectRulesPointer(projectDir);
18
+ if (mcpResult) {
19
+ console.log(' - MCP server unregistered');
20
+ }
21
+ else {
22
+ console.log(' = MCP server was not registered');
23
+ }
24
+ if (hooksResult) {
25
+ console.log(' - Stop hook removed');
26
+ }
27
+ else {
28
+ console.log(' = Stop hook was not configured');
29
+ }
30
+ if (pointerRemoved) {
31
+ console.log(' - Removed .cursor/rules/90_grov.mdc');
32
+ }
33
+ else {
34
+ console.log(' = .cursor/rules/90_grov.mdc was not present');
35
+ }
36
+ console.log('\n.grov/ folder preserved (contains your rules).');
37
+ console.log('Restart Cursor to apply changes.');
38
+ return;
39
+ }
40
+ // Antigravity: MCP-based disable
41
+ if (agentName === 'antigravity') {
42
+ console.log('Disabling grov for Antigravity...\n');
43
+ const mcpResult = removeAntigravityMcp();
44
+ if (mcpResult) {
45
+ console.log(' - MCP server unregistered');
46
+ }
47
+ else {
48
+ console.log(' = MCP server was not registered');
49
+ }
50
+ console.log('\nRestart Antigravity to apply changes.');
51
+ return;
52
+ }
53
+ // Zed: MCP-based disable
54
+ if (agentName === 'zed') {
55
+ console.log('Disabling grov for Zed...\n');
56
+ const mcpResult = removeZedMcp();
57
+ if (mcpResult) {
58
+ console.log(' - Context server unregistered');
59
+ }
60
+ else {
61
+ console.log(' = Context server was not registered');
62
+ }
63
+ console.log('\nRestart Zed to apply changes.');
64
+ return;
65
+ }
66
+ // Claude/Codex: proxy-based disable
67
+ const agent = getAgentByName(agentName);
68
+ if (!agent) {
69
+ console.error(`Unknown agent: ${agentName}`);
70
+ console.error('Supported agents: claude, codex, cursor');
71
+ process.exit(1);
72
+ }
73
+ const settings = agent.getSettings();
74
+ const result = settings.setProxyEnabled(false);
75
+ if (result.action === 'removed') {
76
+ console.log(`Grov disabled for ${agentName}.`);
77
+ console.log(' - Proxy configuration removed');
78
+ }
79
+ else {
80
+ console.log(`Grov was not configured for ${agentName}.`);
81
+ }
82
+ console.log(`\nConfig file: ${settings.getConfigPath()}`);
83
+ const targetName = agentName === 'claude' ? 'Anthropic' : 'OpenAI';
84
+ console.log(`\n${agentName} will now connect directly to ${targetName}.`);
85
+ }
86
+ /**
87
+ * Remove grov MCP from ~/.cursor/mcp.json
88
+ */
89
+ function removeCursorMcp() {
90
+ const mcpPath = join(homedir(), '.cursor', 'mcp.json');
91
+ if (!existsSync(mcpPath)) {
92
+ return false;
93
+ }
94
+ try {
95
+ const content = readFileSync(mcpPath, 'utf-8');
96
+ const config = JSON.parse(content);
97
+ if (!config.mcpServers?.grov) {
98
+ return false;
99
+ }
100
+ delete config.mcpServers.grov;
101
+ writeFileSync(mcpPath, JSON.stringify(config, null, 2));
102
+ return true;
103
+ }
104
+ catch {
105
+ return false;
106
+ }
107
+ }
108
+ /**
109
+ * Remove grov hook from ~/.cursor/hooks.json
110
+ */
111
+ function removeCursorHooks() {
112
+ const hooksPath = join(homedir(), '.cursor', 'hooks.json');
113
+ if (!existsSync(hooksPath)) {
114
+ return false;
115
+ }
116
+ try {
117
+ const content = readFileSync(hooksPath, 'utf-8');
118
+ const config = JSON.parse(content);
119
+ if (!config.hooks?.stop) {
120
+ return false;
121
+ }
122
+ const originalLength = config.hooks.stop.length;
123
+ config.hooks.stop = config.hooks.stop.filter((h) => !h.command?.includes('grov capture-hook'));
124
+ if (config.hooks.stop.length === originalLength) {
125
+ return false;
126
+ }
127
+ writeFileSync(hooksPath, JSON.stringify(config, null, 2));
128
+ return true;
129
+ }
130
+ catch {
131
+ return false;
132
+ }
133
+ }
134
+ /**
135
+ * Remove grov MCP from ~/.gemini/antigravity/mcp_config.json
136
+ */
137
+ function removeAntigravityMcp() {
138
+ const mcpConfigPath = join(homedir(), '.gemini', 'antigravity', 'mcp_config.json');
139
+ if (!existsSync(mcpConfigPath)) {
140
+ return false;
141
+ }
142
+ try {
143
+ const content = readFileSync(mcpConfigPath, 'utf-8');
144
+ const config = JSON.parse(content);
145
+ if (!config.mcpServers?.grov) {
146
+ return false;
147
+ }
148
+ delete config.mcpServers.grov;
149
+ writeFileSync(mcpConfigPath, JSON.stringify(config, null, 2));
150
+ return true;
151
+ }
152
+ catch {
153
+ return false;
154
+ }
155
+ }
156
+ /**
157
+ * Remove grov from ~/.config/zed/settings.json context_servers
158
+ */
159
+ function removeZedMcp() {
160
+ const settingsPath = join(homedir(), '.config', 'zed', 'settings.json');
161
+ if (!existsSync(settingsPath)) {
162
+ return false;
163
+ }
164
+ try {
165
+ const content = readFileSync(settingsPath, 'utf-8');
166
+ // Remove comments for parsing
167
+ const cleanContent = content.replace(/^\s*\/\/.*$/gm, '');
168
+ const config = JSON.parse(cleanContent);
169
+ if (!config.context_servers?.grov) {
170
+ return false;
171
+ }
172
+ delete config.context_servers.grov;
173
+ writeFileSync(settingsPath, JSON.stringify(config, null, 2));
174
+ return true;
175
+ }
176
+ catch {
177
+ return false;
178
+ }
179
+ }
@@ -0,0 +1 @@
1
+ export declare function doctor(agent?: string): Promise<void>;
@@ -0,0 +1,157 @@
1
+ // grov doctor - Check setup and diagnose issues
2
+ import { existsSync } from 'fs';
3
+ import { homedir } from 'os';
4
+ import { join } from 'path';
5
+ import { request } from 'undici';
6
+ import { readCredentials, getSyncStatus } from '../../core/cloud/credentials.js';
7
+ import { initDatabase } from '../../core/store/database.js';
8
+ import { getAllCliAgents, getCliAgentById } from '../agents/registry.js';
9
+ const DB_PATH = join(homedir(), '.grov', 'memory.db');
10
+ export async function doctor(agent) {
11
+ console.log('\nGrov Doctor');
12
+ console.log('===========\n');
13
+ if (!agent) {
14
+ await runGeneralChecks();
15
+ console.log('\n--- Agent Status ---\n');
16
+ for (const a of getAllCliAgents()) {
17
+ const configured = a.isConfigured();
18
+ const icon = configured ? '\x1b[32m●\x1b[0m' : '\x1b[90m○\x1b[0m';
19
+ const status = configured ? 'Configured' : 'Not configured';
20
+ console.log(`${icon} ${a.name}: ${status}`);
21
+ if (!configured) {
22
+ console.log(` \x1b[90m→ grov init ${a.id}\x1b[0m`);
23
+ }
24
+ }
25
+ console.log('\n\x1b[90mRun grov doctor <agent> for detailed checks\x1b[0m');
26
+ }
27
+ else if (agent === 'claude') {
28
+ await runClaudeChecks();
29
+ }
30
+ else if (agent === 'codex') {
31
+ await runCodexChecks();
32
+ }
33
+ else if (agent === 'cursor') {
34
+ await runCursorChecks();
35
+ }
36
+ else if (agent === 'antigravity') {
37
+ await runAntigravityChecks();
38
+ }
39
+ else if (agent === 'zed') {
40
+ await runZedChecks();
41
+ }
42
+ else {
43
+ console.log(`Unknown agent: ${agent}`);
44
+ console.log('Supported: claude, codex, cursor, antigravity, zed');
45
+ }
46
+ console.log('');
47
+ }
48
+ async function runGeneralChecks() {
49
+ const proxyRunning = await checkProxy();
50
+ printCheck('Proxy', proxyRunning, 'Running on port 8080', 'Not running', 'grov proxy');
51
+ const creds = readCredentials();
52
+ printCheck('Login', !!creds, creds ? `Logged in as ${creds.email}` : 'Not logged in', 'Not logged in', 'grov login');
53
+ const syncStatus = getSyncStatus();
54
+ const syncOk = syncStatus?.enabled && syncStatus?.teamId;
55
+ const syncMsg = syncOk
56
+ ? `Team ${syncStatus.teamId.substring(0, 8)}...`
57
+ : syncStatus?.teamId ? 'Disabled' : 'No team';
58
+ printCheck('Cloud Sync', !!syncOk, syncMsg, syncMsg, 'grov sync --enable --team <id>');
59
+ const dbStats = checkDatabase();
60
+ const dbOk = dbStats.tasks > 0 || dbStats.sessions > 0;
61
+ const dbMsg = `${dbStats.tasks} tasks, ${dbStats.unsynced} unsynced, ${dbStats.sessions} active`;
62
+ printCheck('Local Database', dbOk, dbMsg, 'Empty', 'Use Claude/Codex with proxy, or Cursor with MCP');
63
+ }
64
+ async function runClaudeChecks() {
65
+ console.log('Claude Code Checks\n');
66
+ const proxyRunning = await checkProxy();
67
+ printCheck('Proxy', proxyRunning, 'Running on port 8080', 'Not running', 'grov proxy');
68
+ const agent = getCliAgentById('claude');
69
+ if (agent) {
70
+ printCheck('ANTHROPIC_BASE_URL', agent.isConfigured(), 'Configured for proxy', 'Not configured', 'grov init claude');
71
+ printCheck('Settings file', existsSync(agent.configPath), agent.configPath, 'Not found', 'Run claude once to create settings');
72
+ }
73
+ }
74
+ async function runCodexChecks() {
75
+ console.log('Codex CLI Checks\n');
76
+ const proxyRunning = await checkProxy();
77
+ printCheck('Proxy', proxyRunning, 'Running on port 8080', 'Not running', 'grov proxy');
78
+ const agent = getCliAgentById('codex');
79
+ if (agent) {
80
+ printCheck('model_provider', agent.isConfigured(), 'Set to grov', 'Not configured', 'grov init codex');
81
+ printCheck('Config file', existsSync(agent.configPath), agent.configPath, 'Not found', 'Run codex once to create config');
82
+ }
83
+ const apiKey = process.env.OPENAI_API_KEY;
84
+ const hasApiKey = !!(apiKey && apiKey.length > 10);
85
+ const shell = process.env.SHELL?.includes('zsh') ? '~/.zshrc' : '~/.bashrc';
86
+ const apiKeyFix = process.platform === 'win32'
87
+ ? 'setx OPENAI_API_KEY "sk-..." (permanent)'
88
+ : `Add to ${shell}: export OPENAI_API_KEY=sk-...`;
89
+ printCheck('OPENAI_API_KEY', hasApiKey, 'Set', 'NOT SET - Codex will not work', apiKeyFix);
90
+ }
91
+ async function checkProxy() {
92
+ try {
93
+ const res = await request('http://127.0.0.1:8080/health', {
94
+ headersTimeout: 2000,
95
+ bodyTimeout: 2000
96
+ });
97
+ return res.statusCode === 200;
98
+ }
99
+ catch {
100
+ return false;
101
+ }
102
+ }
103
+ async function runCursorChecks() {
104
+ console.log('Cursor Checks\n');
105
+ const agent = getCliAgentById('cursor');
106
+ if (agent) {
107
+ printCheck('MCP Server', agent.isConfigured(), 'Registered in ~/.cursor/mcp.json', 'Not registered', 'grov init cursor');
108
+ }
109
+ const projectDir = process.cwd();
110
+ const hasGrovRules = existsSync(join(projectDir, '.grov', 'rules.mdc'));
111
+ printCheck('Project Rules', hasGrovRules, '.grov/rules.mdc exists', 'Not found', 'grov init cursor');
112
+ const hasPointer = existsSync(join(projectDir, '.cursor', 'rules', '90_grov.mdc'));
113
+ printCheck('Cursor Pointer', hasPointer, '.cursor/rules/90_grov.mdc exists', 'Not found', 'grov init cursor');
114
+ const cursorDir = join(homedir(), '.cursor');
115
+ printCheck('Cursor Installed', existsSync(cursorDir), '~/.cursor exists', 'Not found', 'Install Cursor IDE');
116
+ }
117
+ function checkDatabase() {
118
+ if (!existsSync(DB_PATH)) {
119
+ return { tasks: 0, unsynced: 0, sessions: 0 };
120
+ }
121
+ try {
122
+ const db = initDatabase();
123
+ const tasks = db.prepare('SELECT COUNT(*) as c FROM tasks').get().c;
124
+ const unsynced = db.prepare('SELECT COUNT(*) as c FROM tasks WHERE synced_at IS NULL').get().c;
125
+ const sessions = db.prepare("SELECT COUNT(*) as c FROM session_states WHERE status = 'active'").get().c;
126
+ return { tasks, unsynced, sessions };
127
+ }
128
+ catch {
129
+ return { tasks: 0, unsynced: 0, sessions: 0 };
130
+ }
131
+ }
132
+ function printCheck(name, ok, successMsg, failMsg, fix) {
133
+ const icon = ok ? '\x1b[32m✓\x1b[0m' : '\x1b[31m✗\x1b[0m';
134
+ const msg = ok ? successMsg : failMsg;
135
+ console.log(`${icon} ${name}: ${msg}`);
136
+ if (!ok) {
137
+ console.log(` \x1b[90m→ ${fix}\x1b[0m`);
138
+ }
139
+ }
140
+ async function runAntigravityChecks() {
141
+ console.log('Antigravity Checks\n');
142
+ const agent = getCliAgentById('antigravity');
143
+ if (agent) {
144
+ printCheck('MCP Server', agent.isConfigured(), 'Registered in ~/.gemini/antigravity/mcp_config.json', 'Not registered', 'grov init antigravity');
145
+ }
146
+ const antigravityDir = join(homedir(), '.gemini', 'antigravity');
147
+ printCheck('Antigravity Installed', existsSync(antigravityDir), '~/.gemini/antigravity exists', 'Not found', 'Install Antigravity IDE');
148
+ }
149
+ async function runZedChecks() {
150
+ console.log('Zed Checks\n');
151
+ const agent = getCliAgentById('zed');
152
+ if (agent) {
153
+ printCheck('Context Server', agent.isConfigured(), 'Registered in ~/.config/zed/settings.json', 'Not registered', 'grov init zed');
154
+ }
155
+ const zedConfigDir = join(homedir(), '.config', 'zed');
156
+ printCheck('Zed Installed', existsSync(zedConfigDir), '~/.config/zed exists', 'Not found', 'Install Zed Editor');
157
+ }
@@ -4,37 +4,57 @@
4
4
  // NOTE: This command creates mock STEPS from the prompt for testing.
5
5
  // In real usage, steps are tracked by the proxy from Claude's actions.
6
6
  import 'dotenv/config';
7
- import { getSessionState, createSessionState } from '../lib/store.js';
8
- import { extractIntent } from '../lib/llm-extractor.js';
9
- import { checkDrift, checkDriftBasic, isDriftCheckAvailable, scoreToCorrectionLevel } from '../lib/drift-checker-proxy.js';
10
- import { buildCorrection, formatCorrectionForInjection } from '../lib/correction-builder-proxy.js';
7
+ import { getSessionState, createSessionState } from '../../core/store/store.js';
8
+ import { analyzeTaskContext } from '../../core/extraction/llm-extractor.js';
9
+ import { checkDrift, scoreToCorrectionLevel } from '../../core/extraction/drift-checker-proxy.js';
10
+ import { buildCorrection, formatCorrectionForInjection } from '../../core/extraction/correction-builder-proxy.js';
11
+ // CLI uses env var for auth (not proxy headers)
12
+ // Creates mock headers matching what Claude Code would send
13
+ function getCliHeaders() {
14
+ const apiKey = process.env.ANTHROPIC_API_KEY || process.env.GROV_API_KEY;
15
+ if (!apiKey)
16
+ return null;
17
+ return {
18
+ 'x-api-key': apiKey,
19
+ 'anthropic-version': '2023-06-01',
20
+ 'content-type': 'application/json',
21
+ };
22
+ }
11
23
  export async function driftTest(prompt, options) {
12
24
  console.log('=== GROV DRIFT TEST ===\n');
13
- // Check API availability
14
- const llmAvailable = isDriftCheckAvailable();
15
- console.log(`Anthropic API: ${llmAvailable ? 'AVAILABLE' : 'NOT AVAILABLE (using fallback)'}`);
25
+ // Get headers from env (CLI mode)
26
+ const headers = getCliHeaders();
27
+ console.log(`Anthropic API: ${headers ? 'AVAILABLE' : 'NOT AVAILABLE (using fallback)'}`);
16
28
  console.log('');
29
+ if (!headers) {
30
+ console.log('Set ANTHROPIC_API_KEY or GROV_API_KEY to enable LLM drift checking.');
31
+ return;
32
+ }
17
33
  // Get or create session state
18
34
  let sessionState = options.session ? getSessionState(options.session) : null;
19
35
  // If no session, create a test one with provided or extracted goal
20
36
  if (!sessionState) {
21
37
  console.log('No session provided, creating test session...');
22
38
  const goalText = options.goal || prompt;
23
- const intent = await extractIntent(goalText);
24
- console.log('\n--- Extracted Intent ---');
25
- console.log(`Goal: ${intent.goal}`);
26
- console.log(`Scope: ${intent.expected_scope.join(', ') || 'none'}`);
27
- console.log(`Constraints: ${intent.constraints.join(', ') || 'none'}`);
28
- console.log(`Keywords: ${intent.keywords.join(', ')}`);
39
+ // Use analyzeTaskContext with mock context to extract goal and constraints
40
+ const mockConversation = [{ role: 'user', content: goalText }];
41
+ const taskAnalysis = await analyzeTaskContext(null, // no existing session
42
+ goalText, // latest user message
43
+ [], // no recent steps
44
+ '', // no assistant response yet
45
+ mockConversation, // conversation history
46
+ headers);
47
+ console.log('\n--- Task Analysis ---');
48
+ console.log(`Goal: ${taskAnalysis.current_goal}`);
49
+ console.log(`Action: ${taskAnalysis.action}`);
50
+ console.log(`Constraints: ${(taskAnalysis.constraints || []).join(', ') || 'none'}`);
29
51
  console.log('');
30
52
  // Create temporary session state
31
53
  sessionState = createSessionState({
32
54
  session_id: options.session || 'test-session-' + Date.now(),
33
55
  project_path: process.cwd(),
34
- original_goal: intent.goal,
35
- expected_scope: intent.expected_scope,
36
- constraints: intent.constraints,
37
- keywords: intent.keywords,
56
+ original_goal: taskAnalysis.current_goal,
57
+ constraints: taskAnalysis.constraints || [],
38
58
  task_type: 'main',
39
59
  });
40
60
  }
@@ -88,15 +108,8 @@ export async function driftTest(prompt, options) {
88
108
  console.log('');
89
109
  // Run drift check
90
110
  console.log('--- Running Drift Check ---');
91
- let result;
92
- if (llmAvailable) {
93
- console.log('Using LLM-based detection...');
94
- result = await checkDrift(driftInput);
95
- }
96
- else {
97
- console.log('Using basic (fallback) detection...');
98
- result = checkDriftBasic(driftInput);
99
- }
111
+ console.log('Using LLM-based detection...');
112
+ const result = await checkDrift(driftInput, headers);
100
113
  console.log('');
101
114
  console.log('--- Drift Check Result ---');
102
115
  console.log(`Score: ${result.score}/10`);
@@ -0,0 +1 @@
1
+ export declare function init(agentName?: 'claude' | 'codex' | 'cursor' | 'antigravity' | 'zed'): Promise<void>;