grov 0.5.2 → 0.5.3

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 (48) hide show
  1. package/README.md +19 -1
  2. package/dist/cli.js +8 -0
  3. package/dist/lib/api-client.d.ts +18 -1
  4. package/dist/lib/api-client.js +57 -0
  5. package/dist/lib/llm-extractor.d.ts +14 -38
  6. package/dist/lib/llm-extractor.js +380 -406
  7. package/dist/lib/store/convenience.d.ts +40 -0
  8. package/dist/lib/store/convenience.js +104 -0
  9. package/dist/lib/store/database.d.ts +22 -0
  10. package/dist/lib/store/database.js +375 -0
  11. package/dist/lib/store/drift.d.ts +9 -0
  12. package/dist/lib/store/drift.js +89 -0
  13. package/dist/lib/store/index.d.ts +7 -0
  14. package/dist/lib/store/index.js +13 -0
  15. package/dist/lib/store/sessions.d.ts +32 -0
  16. package/dist/lib/store/sessions.js +240 -0
  17. package/dist/lib/store/steps.d.ts +40 -0
  18. package/dist/lib/store/steps.js +161 -0
  19. package/dist/lib/store/tasks.d.ts +33 -0
  20. package/dist/lib/store/tasks.js +133 -0
  21. package/dist/lib/store/types.d.ts +167 -0
  22. package/dist/lib/store/types.js +2 -0
  23. package/dist/lib/store.d.ts +1 -436
  24. package/dist/lib/store.js +2 -1478
  25. package/dist/proxy/cache.d.ts +36 -0
  26. package/dist/proxy/cache.js +51 -0
  27. package/dist/proxy/config.d.ts +1 -0
  28. package/dist/proxy/config.js +2 -0
  29. package/dist/proxy/extended-cache.d.ts +10 -0
  30. package/dist/proxy/extended-cache.js +155 -0
  31. package/dist/proxy/handlers/preprocess.d.ts +20 -0
  32. package/dist/proxy/handlers/preprocess.js +169 -0
  33. package/dist/proxy/injection/delta-tracking.d.ts +11 -0
  34. package/dist/proxy/injection/delta-tracking.js +93 -0
  35. package/dist/proxy/injection/injectors.d.ts +7 -0
  36. package/dist/proxy/injection/injectors.js +139 -0
  37. package/dist/proxy/request-processor.d.ts +18 -4
  38. package/dist/proxy/request-processor.js +151 -30
  39. package/dist/proxy/response-processor.js +93 -45
  40. package/dist/proxy/server.d.ts +0 -1
  41. package/dist/proxy/server.js +342 -566
  42. package/dist/proxy/types.d.ts +13 -0
  43. package/dist/proxy/types.js +2 -0
  44. package/dist/proxy/utils/extractors.d.ts +18 -0
  45. package/dist/proxy/utils/extractors.js +109 -0
  46. package/dist/proxy/utils/logging.d.ts +18 -0
  47. package/dist/proxy/utils/logging.js +42 -0
  48. package/package.json +5 -2
@@ -0,0 +1,167 @@
1
+ export type TaskStatus = 'complete' | 'question' | 'partial' | 'abandoned';
2
+ export type TriggerReason = 'complete' | 'threshold' | 'abandoned';
3
+ export interface Task {
4
+ id: string;
5
+ project_path: string;
6
+ user?: string;
7
+ original_query: string;
8
+ goal?: string;
9
+ reasoning_trace: string[];
10
+ files_touched: string[];
11
+ decisions: Array<{
12
+ choice: string;
13
+ reason: string;
14
+ }>;
15
+ constraints: string[];
16
+ status: TaskStatus;
17
+ trigger_reason?: TriggerReason;
18
+ linked_commit?: string;
19
+ parent_task_id?: string;
20
+ turn_number?: number;
21
+ tags: string[];
22
+ created_at: string;
23
+ synced_at?: string | null;
24
+ sync_error?: string | null;
25
+ }
26
+ export interface CreateTaskInput {
27
+ project_path: string;
28
+ user?: string;
29
+ original_query: string;
30
+ goal?: string;
31
+ reasoning_trace?: string[];
32
+ files_touched?: string[];
33
+ decisions?: Array<{
34
+ choice: string;
35
+ reason: string;
36
+ }>;
37
+ constraints?: string[];
38
+ status: TaskStatus;
39
+ trigger_reason?: TriggerReason;
40
+ linked_commit?: string;
41
+ parent_task_id?: string;
42
+ turn_number?: number;
43
+ tags?: string[];
44
+ }
45
+ export type SessionStatus = 'active' | 'completed' | 'abandoned';
46
+ export type SessionMode = 'normal' | 'drifted' | 'forced';
47
+ export type TaskType = 'main' | 'subtask' | 'parallel';
48
+ export interface RecoveryPlan {
49
+ steps: Array<{
50
+ file?: string;
51
+ action: string;
52
+ }>;
53
+ }
54
+ export interface DriftEvent {
55
+ timestamp: string;
56
+ score: number;
57
+ level: string;
58
+ prompt_summary: string;
59
+ }
60
+ interface SessionStateBase {
61
+ session_id: string;
62
+ user_id?: string;
63
+ project_path: string;
64
+ original_goal?: string;
65
+ expected_scope: string[];
66
+ constraints: string[];
67
+ keywords: string[];
68
+ escalation_count: number;
69
+ last_checked_at: number;
70
+ start_time: string;
71
+ last_update: string;
72
+ status: SessionStatus;
73
+ }
74
+ interface HookFields {
75
+ success_criteria?: string[];
76
+ last_drift_score?: number;
77
+ pending_recovery_plan?: RecoveryPlan;
78
+ drift_history?: DriftEvent[];
79
+ actions_taken?: string[];
80
+ files_explored?: string[];
81
+ current_intent?: string;
82
+ drift_warnings?: string[];
83
+ }
84
+ interface ProxyFields {
85
+ token_count?: number;
86
+ session_mode?: SessionMode;
87
+ waiting_for_recovery?: boolean;
88
+ last_clear_at?: number;
89
+ completed_at?: string;
90
+ parent_session_id?: string;
91
+ task_type?: TaskType;
92
+ pending_correction?: string;
93
+ pending_forced_recovery?: string;
94
+ pending_clear_summary?: string;
95
+ cached_injection?: string;
96
+ final_response?: string;
97
+ }
98
+ export interface SessionState extends SessionStateBase, HookFields, ProxyFields {
99
+ }
100
+ export interface CreateSessionStateInput {
101
+ session_id: string;
102
+ user_id?: string;
103
+ project_path: string;
104
+ original_goal?: string;
105
+ expected_scope?: string[];
106
+ constraints?: string[];
107
+ keywords?: string[];
108
+ success_criteria?: string[];
109
+ parent_session_id?: string;
110
+ task_type?: TaskType;
111
+ }
112
+ export type StepActionType = 'edit' | 'write' | 'bash' | 'read' | 'glob' | 'grep' | 'task' | 'other';
113
+ export type DriftType = 'none' | 'minor' | 'major' | 'critical';
114
+ export type CorrectionLevel = 'nudge' | 'correct' | 'intervene' | 'halt';
115
+ export interface StepRecord {
116
+ id: string;
117
+ session_id: string;
118
+ action_type: StepActionType;
119
+ files: string[];
120
+ folders: string[];
121
+ command?: string;
122
+ reasoning?: string;
123
+ drift_score?: number;
124
+ drift_type?: DriftType;
125
+ is_key_decision: boolean;
126
+ is_validated: boolean;
127
+ correction_given?: string;
128
+ correction_level?: CorrectionLevel;
129
+ keywords: string[];
130
+ timestamp: number;
131
+ }
132
+ export interface CreateStepInput {
133
+ session_id: string;
134
+ action_type: StepActionType;
135
+ files?: string[];
136
+ folders?: string[];
137
+ command?: string;
138
+ reasoning?: string;
139
+ drift_score?: number;
140
+ drift_type?: DriftType;
141
+ is_key_decision?: boolean;
142
+ is_validated?: boolean;
143
+ correction_given?: string;
144
+ correction_level?: CorrectionLevel;
145
+ keywords?: string[];
146
+ }
147
+ export interface DriftLogEntry {
148
+ id: string;
149
+ session_id: string;
150
+ timestamp: number;
151
+ action_type?: string;
152
+ files: string[];
153
+ drift_score: number;
154
+ drift_reason?: string;
155
+ correction_given?: string;
156
+ recovery_plan?: Record<string, unknown>;
157
+ }
158
+ export interface CreateDriftLogInput {
159
+ session_id: string;
160
+ action_type?: string;
161
+ files?: string[];
162
+ drift_score: number;
163
+ drift_reason?: string;
164
+ correction_given?: string;
165
+ recovery_plan?: Record<string, unknown>;
166
+ }
167
+ export {};
@@ -0,0 +1,2 @@
1
+ // Store types and interfaces
2
+ export {};
@@ -1,436 +1 @@
1
- import Database from 'better-sqlite3';
2
- import type { ClaudeAction } from './session-parser.js';
3
- export type TaskStatus = 'complete' | 'question' | 'partial' | 'abandoned';
4
- export type TriggerReason = 'complete' | 'threshold' | 'abandoned';
5
- export interface Task {
6
- id: string;
7
- project_path: string;
8
- user?: string;
9
- original_query: string;
10
- goal?: string;
11
- reasoning_trace: string[];
12
- files_touched: string[];
13
- decisions: Array<{
14
- choice: string;
15
- reason: string;
16
- }>;
17
- constraints: string[];
18
- status: TaskStatus;
19
- trigger_reason?: TriggerReason;
20
- linked_commit?: string;
21
- parent_task_id?: string;
22
- turn_number?: number;
23
- tags: string[];
24
- created_at: string;
25
- synced_at?: string | null;
26
- sync_error?: string | null;
27
- }
28
- export interface CreateTaskInput {
29
- project_path: string;
30
- user?: string;
31
- original_query: string;
32
- goal?: string;
33
- reasoning_trace?: string[];
34
- files_touched?: string[];
35
- decisions?: Array<{
36
- choice: string;
37
- reason: string;
38
- }>;
39
- constraints?: string[];
40
- status: TaskStatus;
41
- trigger_reason?: TriggerReason;
42
- linked_commit?: string;
43
- parent_task_id?: string;
44
- turn_number?: number;
45
- tags?: string[];
46
- }
47
- export type SessionStatus = 'active' | 'completed' | 'abandoned';
48
- export type SessionMode = 'normal' | 'drifted' | 'forced';
49
- export type TaskType = 'main' | 'subtask' | 'parallel';
50
- export interface RecoveryPlan {
51
- steps: Array<{
52
- file?: string;
53
- action: string;
54
- }>;
55
- }
56
- export interface DriftEvent {
57
- timestamp: string;
58
- score: number;
59
- level: string;
60
- prompt_summary: string;
61
- }
62
- interface SessionStateBase {
63
- session_id: string;
64
- user_id?: string;
65
- project_path: string;
66
- original_goal?: string;
67
- expected_scope: string[];
68
- constraints: string[];
69
- keywords: string[];
70
- escalation_count: number;
71
- last_checked_at: number;
72
- start_time: string;
73
- last_update: string;
74
- status: SessionStatus;
75
- }
76
- interface HookFields {
77
- success_criteria?: string[];
78
- last_drift_score?: number;
79
- pending_recovery_plan?: RecoveryPlan;
80
- drift_history?: DriftEvent[];
81
- actions_taken?: string[];
82
- files_explored?: string[];
83
- current_intent?: string;
84
- drift_warnings?: string[];
85
- }
86
- interface ProxyFields {
87
- token_count?: number;
88
- session_mode?: SessionMode;
89
- waiting_for_recovery?: boolean;
90
- last_clear_at?: number;
91
- completed_at?: string;
92
- parent_session_id?: string;
93
- task_type?: TaskType;
94
- pending_correction?: string;
95
- pending_forced_recovery?: string;
96
- pending_clear_summary?: string;
97
- cached_injection?: string;
98
- final_response?: string;
99
- }
100
- export interface SessionState extends SessionStateBase, HookFields, ProxyFields {
101
- }
102
- export interface CreateSessionStateInput {
103
- session_id: string;
104
- user_id?: string;
105
- project_path: string;
106
- original_goal?: string;
107
- expected_scope?: string[];
108
- constraints?: string[];
109
- keywords?: string[];
110
- success_criteria?: string[];
111
- parent_session_id?: string;
112
- task_type?: TaskType;
113
- }
114
- export type StepActionType = 'edit' | 'write' | 'bash' | 'read' | 'glob' | 'grep' | 'task' | 'other';
115
- export type DriftType = 'none' | 'minor' | 'major' | 'critical';
116
- export type CorrectionLevel = 'nudge' | 'correct' | 'intervene' | 'halt';
117
- export interface StepRecord {
118
- id: string;
119
- session_id: string;
120
- action_type: StepActionType;
121
- files: string[];
122
- folders: string[];
123
- command?: string;
124
- reasoning?: string;
125
- drift_score?: number;
126
- drift_type?: DriftType;
127
- is_key_decision: boolean;
128
- is_validated: boolean;
129
- correction_given?: string;
130
- correction_level?: CorrectionLevel;
131
- keywords: string[];
132
- timestamp: number;
133
- }
134
- export interface CreateStepInput {
135
- session_id: string;
136
- action_type: StepActionType;
137
- files?: string[];
138
- folders?: string[];
139
- command?: string;
140
- reasoning?: string;
141
- drift_score?: number;
142
- drift_type?: DriftType;
143
- is_key_decision?: boolean;
144
- is_validated?: boolean;
145
- correction_given?: string;
146
- correction_level?: CorrectionLevel;
147
- keywords?: string[];
148
- }
149
- export interface DriftLogEntry {
150
- id: string;
151
- session_id: string;
152
- timestamp: number;
153
- action_type?: string;
154
- files: string[];
155
- drift_score: number;
156
- drift_reason?: string;
157
- correction_given?: string;
158
- recovery_plan?: Record<string, unknown>;
159
- }
160
- export interface CreateDriftLogInput {
161
- session_id: string;
162
- action_type?: string;
163
- files?: string[];
164
- drift_score: number;
165
- drift_reason?: string;
166
- correction_given?: string;
167
- recovery_plan?: Record<string, unknown>;
168
- }
169
- export type ChangeType = 'read' | 'write' | 'edit' | 'create' | 'delete';
170
- export interface FileReasoning {
171
- id: string;
172
- task_id?: string;
173
- file_path: string;
174
- anchor?: string;
175
- line_start?: number;
176
- line_end?: number;
177
- code_hash?: string;
178
- change_type?: ChangeType;
179
- reasoning: string;
180
- created_at: string;
181
- }
182
- export interface CreateFileReasoningInput {
183
- task_id?: string;
184
- file_path: string;
185
- anchor?: string;
186
- line_start?: number;
187
- line_end?: number;
188
- code_hash?: string;
189
- change_type?: ChangeType;
190
- reasoning: string;
191
- }
192
- /**
193
- * Initialize the database connection and create tables
194
- */
195
- export declare function initDatabase(): Database.Database;
196
- /**
197
- * Close the database connection
198
- */
199
- export declare function closeDatabase(): void;
200
- /**
201
- * Create a new task
202
- */
203
- export declare function createTask(input: CreateTaskInput): Task;
204
- /**
205
- * Get tasks for a project
206
- */
207
- export declare function getTasksForProject(projectPath: string, options?: {
208
- status?: TaskStatus;
209
- limit?: number;
210
- }): Task[];
211
- export declare function getTasksByFiles(projectPath: string, files: string[], options?: {
212
- status?: TaskStatus;
213
- limit?: number;
214
- }): Task[];
215
- /**
216
- * Get a task by ID
217
- */
218
- export declare function getTaskById(id: string): Task | null;
219
- /**
220
- * Update a task's status
221
- */
222
- export declare function updateTaskStatus(id: string, status: TaskStatus): void;
223
- /**
224
- * Get task count for a project
225
- */
226
- export declare function getTaskCount(projectPath: string): number;
227
- /**
228
- * Get unsynced tasks for a project (synced_at is NULL)
229
- */
230
- export declare function getUnsyncedTasks(projectPath: string, limit?: number): Task[];
231
- /**
232
- * Mark a task as synced and clear any previous sync error
233
- */
234
- export declare function markTaskSynced(id: string): void;
235
- /**
236
- * Record a sync error for a task
237
- */
238
- export declare function setTaskSyncError(id: string, error: string): void;
239
- /**
240
- * Create a new session state.
241
- * FIXED: Uses INSERT OR IGNORE to handle race conditions safely.
242
- */
243
- export declare function createSessionState(input: CreateSessionStateInput): SessionState;
244
- /**
245
- * Get a session state by ID
246
- */
247
- export declare function getSessionState(sessionId: string): SessionState | null;
248
- /**
249
- * Update a session state.
250
- * SECURITY: Uses transaction for atomic updates to prevent race conditions.
251
- */
252
- export declare function updateSessionState(sessionId: string, updates: Partial<Omit<SessionState, 'session_id' | 'start_time'>>): void;
253
- /**
254
- * Delete a session state
255
- */
256
- export declare function deleteSessionState(sessionId: string): void;
257
- /**
258
- * Get active sessions for a project
259
- */
260
- export declare function getActiveSessionsForProject(projectPath: string): SessionState[];
261
- /**
262
- * Get child sessions (subtasks and parallel tasks) for a parent session
263
- */
264
- export declare function getChildSessions(parentSessionId: string): SessionState[];
265
- /**
266
- * Get active session for a specific user in a project
267
- */
268
- export declare function getActiveSessionForUser(projectPath: string, userId?: string): SessionState | null;
269
- /**
270
- * Get all active sessions (for proxy-status command)
271
- */
272
- export declare function getActiveSessionsForStatus(): SessionState[];
273
- /**
274
- * Update session drift metrics after a prompt check
275
- */
276
- export declare function updateSessionDrift(sessionId: string, driftScore: number, correctionLevel: CorrectionLevel | null, promptSummary: string, recoveryPlan?: RecoveryPlan): void;
277
- /**
278
- * Check if a session should be flagged for review
279
- * Returns true if: status=drifted OR warnings>=3 OR avg_score<6
280
- */
281
- export declare function shouldFlagForReview(sessionId: string): boolean;
282
- /**
283
- * Get drift summary for a session (used by capture)
284
- */
285
- export declare function getDriftSummary(sessionId: string): {
286
- totalEvents: number;
287
- resolved: boolean;
288
- finalScore: number | null;
289
- hadHalt: boolean;
290
- };
291
- /**
292
- * Create a new file reasoning entry
293
- */
294
- export declare function createFileReasoning(input: CreateFileReasoningInput): FileReasoning;
295
- /**
296
- * Get file reasoning entries for a task
297
- */
298
- export declare function getFileReasoningForTask(taskId: string): FileReasoning[];
299
- /**
300
- * Get file reasoning entries by file path
301
- */
302
- export declare function getFileReasoningByPath(filePath: string, limit?: number): FileReasoning[];
303
- /**
304
- * Get file reasoning entries matching a pattern (for files in a project).
305
- * SECURITY: Uses escaped LIKE patterns to prevent injection.
306
- */
307
- export declare function getFileReasoningByPathPattern(pathPattern: string, limit?: number): FileReasoning[];
308
- /**
309
- * Get the database path
310
- */
311
- export declare function getDatabasePath(): string;
312
- /**
313
- * Create a new step record (proxy version)
314
- */
315
- export declare function createStep(input: CreateStepInput): StepRecord;
316
- /**
317
- * Get steps for a session
318
- */
319
- export declare function getStepsForSession(sessionId: string, limit?: number): StepRecord[];
320
- /**
321
- * Get recent steps for a session (most recent N)
322
- */
323
- export declare function getRecentSteps(sessionId: string, count?: number): StepRecord[];
324
- /**
325
- * Get validated steps only (for summary generation)
326
- */
327
- export declare function getValidatedSteps(sessionId: string): StepRecord[];
328
- /**
329
- * Get key decision steps for a session (is_key_decision = 1)
330
- * Used for user message injection - important decisions with reasoning
331
- */
332
- export declare function getKeyDecisions(sessionId: string, limit?: number): StepRecord[];
333
- /**
334
- * Get edited files for a session (action_type IN ('edit', 'write'))
335
- * Used for user message injection - prevent re-work
336
- */
337
- export declare function getEditedFiles(sessionId: string): string[];
338
- /**
339
- * Delete steps for a session
340
- */
341
- export declare function deleteStepsForSession(sessionId: string): void;
342
- /**
343
- * Update reasoning for recent steps that don't have reasoning yet
344
- * Called at end_turn to backfill reasoning from Claude's text response
345
- */
346
- export declare function updateRecentStepsReasoning(sessionId: string, reasoning: string, limit?: number): number;
347
- /**
348
- * Get relevant steps (key decisions and write/edit actions) - proxy version
349
- * Reference: plan_proxy_local.md Section 2.2
350
- */
351
- export declare function getRelevantStepsSimple(sessionId: string, limit?: number): StepRecord[];
352
- /**
353
- * Save a Claude action as a step (hook version - uses ClaudeAction)
354
- */
355
- export declare function saveStep(sessionId: string, action: ClaudeAction, driftScore: number, isKeyDecision?: boolean, keywords?: string[]): void;
356
- /**
357
- * Update last_checked_at timestamp for a session
358
- */
359
- export declare function updateLastChecked(sessionId: string, timestamp: number): void;
360
- /**
361
- * Get steps that touched specific files
362
- */
363
- export declare function getStepsByFiles(sessionId: string, files: string[], limit?: number): StepRecord[];
364
- /**
365
- * Get steps that touched specific folders
366
- */
367
- export declare function getStepsByFolders(sessionId: string, folders: string[], limit?: number): StepRecord[];
368
- /**
369
- * Get steps matching keywords
370
- */
371
- export declare function getStepsByKeywords(sessionId: string, keywords: string[], limit?: number): StepRecord[];
372
- /**
373
- * Get key decision steps
374
- */
375
- export declare function getKeyDecisionSteps(sessionId: string, limit?: number): StepRecord[];
376
- /**
377
- * Get steps reasoning by file path (for proxy team memory injection)
378
- * Searches across sessions, returns file-level reasoning from steps table
379
- * @param excludeSessionId - Optional session ID to exclude (for filtering current session)
380
- */
381
- export declare function getStepsReasoningByPath(filePath: string, limit?: number, excludeSessionId?: string): Array<{
382
- file_path: string;
383
- reasoning: string;
384
- anchor?: string;
385
- }>;
386
- /**
387
- * Combined retrieval: runs all 4 queries and deduplicates (hook version)
388
- * Priority: key decisions > files > folders > keywords
389
- */
390
- export declare function getRelevantSteps(sessionId: string, currentFiles: string[], currentFolders: string[], keywords: string[], limit?: number): StepRecord[];
391
- /**
392
- * Log a drift event (for rejected actions)
393
- */
394
- export declare function logDriftEvent(input: CreateDriftLogInput): DriftLogEntry;
395
- /**
396
- * Get drift log for a session
397
- */
398
- export declare function getDriftLog(sessionId: string, limit?: number): DriftLogEntry[];
399
- /**
400
- * Update token count for a session
401
- */
402
- export declare function updateTokenCount(sessionId: string, tokenCount: number): void;
403
- /**
404
- * Update session mode
405
- */
406
- export declare function updateSessionMode(sessionId: string, mode: SessionMode): void;
407
- /**
408
- * Mark session as waiting for recovery
409
- */
410
- export declare function markWaitingForRecovery(sessionId: string, waiting: boolean): void;
411
- /**
412
- * Increment escalation count
413
- */
414
- export declare function incrementEscalation(sessionId: string): void;
415
- /**
416
- * Update last clear timestamp and reset token count
417
- */
418
- export declare function markCleared(sessionId: string): void;
419
- /**
420
- * Mark session as completed (instead of deleting)
421
- * Session will be cleaned up after 1 hour
422
- */
423
- export declare function markSessionCompleted(sessionId: string): void;
424
- /**
425
- * Cleanup sessions completed more than 24 hours ago
426
- * Also deletes associated steps and drift_log entries
427
- * Skips sessions that have active children (RESTRICT approach)
428
- * Returns number of sessions cleaned up
429
- */
430
- export declare function cleanupOldCompletedSessions(maxAgeMs?: number): number;
431
- /**
432
- * Get completed session for project (for new_task detection)
433
- * Returns most recent completed session if exists
434
- */
435
- export declare function getCompletedSessionForProject(projectPath: string): SessionState | null;
436
- export {};
1
+ export * from './store/index.js';