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.
- package/dist/cli/agents/registry.d.ts +17 -0
- package/dist/cli/agents/registry.js +132 -0
- package/dist/cli/commands/agents.d.ts +1 -0
- package/dist/cli/commands/agents.js +48 -0
- package/dist/cli/commands/disable.d.ts +1 -0
- package/dist/cli/commands/disable.js +179 -0
- package/dist/cli/commands/doctor.d.ts +1 -0
- package/dist/cli/commands/doctor.js +157 -0
- package/dist/{commands → cli/commands}/drift-test.js +39 -26
- package/dist/cli/commands/init.d.ts +1 -0
- package/dist/cli/commands/init.js +90 -0
- package/dist/{commands → cli/commands}/login.js +19 -18
- package/dist/{commands → cli/commands}/logout.js +1 -1
- package/dist/{commands → cli/commands}/proxy-status.js +1 -1
- package/dist/cli/commands/setup.d.ts +6 -0
- package/dist/cli/commands/setup.js +309 -0
- package/dist/{commands → cli/commands}/status.js +1 -1
- package/dist/{commands → cli/commands}/sync.d.ts +1 -0
- package/dist/{commands → cli/commands}/sync.js +59 -4
- package/dist/{commands → cli/commands}/uninstall.js +2 -2
- package/dist/cli/index.js +270 -0
- package/dist/{lib → core/cloud}/cloud-sync.d.ts +3 -3
- package/dist/{lib → core/cloud}/cloud-sync.js +10 -10
- package/dist/{lib → core/extraction}/correction-builder-proxy.d.ts +1 -1
- package/dist/{lib → core/extraction}/correction-builder-proxy.js +0 -4
- package/dist/{lib → core/extraction}/drift-checker-proxy.d.ts +13 -9
- package/dist/core/extraction/drift-checker-proxy.js +510 -0
- package/dist/{lib → core/extraction}/llm-extractor.d.ts +8 -38
- package/dist/{lib → core/extraction}/llm-extractor.js +132 -220
- package/dist/{lib → core}/store/sessions.js +3 -19
- package/dist/core/store/store.d.ts +1 -0
- package/dist/{lib → core/store}/store.js +1 -1
- package/dist/{lib → core}/store/types.d.ts +0 -4
- package/dist/integrations/mcp/cache.d.ts +27 -0
- package/dist/integrations/mcp/cache.js +106 -0
- package/dist/integrations/mcp/capture/antigravity-parser.d.ts +26 -0
- package/dist/integrations/mcp/capture/antigravity-parser.js +272 -0
- package/dist/integrations/mcp/capture/antigravity-scanner.d.ts +24 -0
- package/dist/integrations/mcp/capture/antigravity-scanner.js +153 -0
- package/dist/integrations/mcp/capture/antigravity-sync-tracker.d.ts +29 -0
- package/dist/integrations/mcp/capture/antigravity-sync-tracker.js +115 -0
- package/dist/integrations/mcp/capture/cli-extractor.d.ts +18 -0
- package/dist/integrations/mcp/capture/cli-extractor.js +258 -0
- package/dist/integrations/mcp/capture/cli-synced.d.ts +4 -0
- package/dist/integrations/mcp/capture/cli-synced.js +62 -0
- package/dist/integrations/mcp/capture/cli-transform.d.ts +30 -0
- package/dist/integrations/mcp/capture/cli-transform.js +62 -0
- package/dist/integrations/mcp/capture/cli-watcher.d.ts +31 -0
- package/dist/integrations/mcp/capture/cli-watcher.js +106 -0
- package/dist/integrations/mcp/capture/hook-handler.d.ts +2 -0
- package/dist/integrations/mcp/capture/hook-handler.js +157 -0
- package/dist/integrations/mcp/capture/sqlite-reader.d.ts +35 -0
- package/dist/integrations/mcp/capture/sqlite-reader.js +388 -0
- package/dist/integrations/mcp/capture/sync-tracker.d.ts +16 -0
- package/dist/integrations/mcp/capture/sync-tracker.js +102 -0
- package/dist/integrations/mcp/clients/cursor/rules-installer.d.ts +19 -0
- package/dist/integrations/mcp/clients/cursor/rules-installer.js +123 -0
- package/dist/integrations/mcp/index.d.ts +1 -0
- package/dist/integrations/mcp/index.js +94 -0
- package/dist/integrations/mcp/logger.d.ts +8 -0
- package/dist/integrations/mcp/logger.js +50 -0
- package/dist/integrations/mcp/server.d.ts +5 -0
- package/dist/integrations/mcp/server.js +58 -0
- package/dist/integrations/mcp/tools/expand.d.ts +1 -0
- package/dist/integrations/mcp/tools/expand.js +53 -0
- package/dist/integrations/mcp/tools/preview.d.ts +1 -0
- package/dist/integrations/mcp/tools/preview.js +64 -0
- package/dist/integrations/proxy/agents/base.d.ts +43 -0
- package/dist/integrations/proxy/agents/base.js +13 -0
- package/dist/{proxy/utils → integrations/proxy/agents/claude}/extractors.d.ts +4 -8
- package/dist/{proxy/utils → integrations/proxy/agents/claude}/extractors.js +4 -33
- package/dist/{proxy → integrations/proxy/agents/claude}/forwarder.d.ts +1 -1
- package/dist/{proxy → integrations/proxy/agents/claude}/forwarder.js +22 -6
- package/dist/integrations/proxy/agents/claude/index.d.ts +43 -0
- package/dist/integrations/proxy/agents/claude/index.js +386 -0
- package/dist/{proxy/action-parser.d.ts → integrations/proxy/agents/claude/parser.d.ts} +1 -1
- package/dist/integrations/proxy/agents/codex/extractors.d.ts +6 -0
- package/dist/integrations/proxy/agents/codex/extractors.js +49 -0
- package/dist/integrations/proxy/agents/codex/forwarder.d.ts +9 -0
- package/dist/integrations/proxy/agents/codex/forwarder.js +125 -0
- package/dist/integrations/proxy/agents/codex/index.d.ts +44 -0
- package/dist/integrations/proxy/agents/codex/index.js +371 -0
- package/dist/integrations/proxy/agents/codex/parser.d.ts +11 -0
- package/dist/integrations/proxy/agents/codex/parser.js +104 -0
- package/dist/integrations/proxy/agents/codex/patch.d.ts +12 -0
- package/dist/integrations/proxy/agents/codex/patch.js +40 -0
- package/dist/integrations/proxy/agents/codex/settings.d.ts +18 -0
- package/dist/integrations/proxy/agents/codex/settings.js +73 -0
- package/dist/integrations/proxy/agents/codex/types.d.ts +59 -0
- package/dist/integrations/proxy/agents/codex/types.js +2 -0
- package/dist/integrations/proxy/agents/index.d.ts +11 -0
- package/dist/integrations/proxy/agents/index.js +25 -0
- package/dist/integrations/proxy/agents/types.d.ts +77 -0
- package/dist/integrations/proxy/agents/types.js +2 -0
- package/dist/{proxy → integrations/proxy/cache}/extended-cache.js +2 -6
- package/dist/{proxy → integrations/proxy}/config.js +1 -1
- package/dist/{proxy → integrations/proxy}/handlers/preprocess.d.ts +3 -3
- package/dist/integrations/proxy/handlers/preprocess.js +194 -0
- package/dist/integrations/proxy/index.js +20 -0
- package/dist/integrations/proxy/injection/memory-injection.d.ts +56 -0
- package/dist/integrations/proxy/injection/memory-injection.js +252 -0
- package/dist/integrations/proxy/orchestrator.d.ts +30 -0
- package/dist/integrations/proxy/orchestrator.js +954 -0
- package/dist/integrations/proxy/request-processor.d.ts +14 -0
- package/dist/integrations/proxy/request-processor.js +68 -0
- package/dist/{proxy → integrations/proxy}/response-processor.d.ts +4 -3
- package/dist/{proxy → integrations/proxy}/response-processor.js +51 -43
- package/dist/{proxy → integrations/proxy}/server.d.ts +0 -1
- package/dist/integrations/proxy/server.js +146 -0
- package/dist/{proxy → integrations/proxy}/types.d.ts +4 -0
- package/dist/{proxy → integrations/proxy}/utils/logging.d.ts +1 -0
- package/dist/{proxy → integrations/proxy}/utils/logging.js +5 -0
- package/package.json +31 -10
- package/postinstall.js +62 -6
- package/dist/cli.js +0 -149
- package/dist/commands/capture.d.ts +0 -6
- package/dist/commands/capture.js +0 -324
- package/dist/commands/disable.d.ts +0 -1
- package/dist/commands/disable.js +0 -14
- package/dist/commands/doctor.d.ts +0 -1
- package/dist/commands/doctor.js +0 -89
- package/dist/commands/init.d.ts +0 -1
- package/dist/commands/init.js +0 -52
- package/dist/commands/inject.d.ts +0 -5
- package/dist/commands/inject.js +0 -88
- package/dist/commands/prompt-inject.d.ts +0 -4
- package/dist/commands/prompt-inject.js +0 -451
- package/dist/commands/unregister.d.ts +0 -1
- package/dist/commands/unregister.js +0 -28
- package/dist/lib/anchor-extractor.d.ts +0 -30
- package/dist/lib/anchor-extractor.js +0 -296
- package/dist/lib/correction-builder.d.ts +0 -10
- package/dist/lib/correction-builder.js +0 -226
- package/dist/lib/drift-checker-proxy.js +0 -373
- package/dist/lib/drift-checker.d.ts +0 -66
- package/dist/lib/drift-checker.js +0 -341
- package/dist/lib/hooks.d.ts +0 -38
- package/dist/lib/hooks.js +0 -291
- package/dist/lib/jsonl-parser.d.ts +0 -87
- package/dist/lib/jsonl-parser.js +0 -281
- package/dist/lib/session-parser.d.ts +0 -44
- package/dist/lib/session-parser.js +0 -256
- package/dist/lib/store.d.ts +0 -1
- package/dist/proxy/cache.d.ts +0 -32
- package/dist/proxy/cache.js +0 -47
- package/dist/proxy/handlers/preprocess.js +0 -186
- package/dist/proxy/index.js +0 -30
- package/dist/proxy/injection/delta-tracking.d.ts +0 -11
- package/dist/proxy/injection/delta-tracking.js +0 -94
- package/dist/proxy/injection/injectors.d.ts +0 -7
- package/dist/proxy/injection/injectors.js +0 -139
- package/dist/proxy/request-processor.d.ts +0 -27
- package/dist/proxy/request-processor.js +0 -233
- package/dist/proxy/server.js +0 -1289
- /package/dist/{commands → cli/commands}/drift-test.d.ts +0 -0
- /package/dist/{commands → cli/commands}/login.d.ts +0 -0
- /package/dist/{commands → cli/commands}/logout.d.ts +0 -0
- /package/dist/{commands → cli/commands}/proxy-status.d.ts +0 -0
- /package/dist/{commands → cli/commands}/status.d.ts +0 -0
- /package/dist/{commands → cli/commands}/uninstall.d.ts +0 -0
- /package/dist/{cli.d.ts → cli/index.d.ts} +0 -0
- /package/dist/{lib → core/cloud}/api-client.d.ts +0 -0
- /package/dist/{lib → core/cloud}/api-client.js +0 -0
- /package/dist/{lib → core/cloud}/credentials.d.ts +0 -0
- /package/dist/{lib → core/cloud}/credentials.js +0 -0
- /package/dist/{lib → core}/store/convenience.d.ts +0 -0
- /package/dist/{lib → core}/store/convenience.js +0 -0
- /package/dist/{lib → core}/store/database.d.ts +0 -0
- /package/dist/{lib → core}/store/database.js +0 -0
- /package/dist/{lib → core}/store/drift.d.ts +0 -0
- /package/dist/{lib → core}/store/drift.js +0 -0
- /package/dist/{lib → core}/store/index.d.ts +0 -0
- /package/dist/{lib → core}/store/index.js +0 -0
- /package/dist/{lib → core}/store/sessions.d.ts +0 -0
- /package/dist/{lib → core}/store/steps.d.ts +0 -0
- /package/dist/{lib → core}/store/steps.js +0 -0
- /package/dist/{lib → core}/store/tasks.d.ts +0 -0
- /package/dist/{lib → core}/store/tasks.js +0 -0
- /package/dist/{lib → core}/store/types.js +0 -0
- /package/dist/{proxy/action-parser.js → integrations/proxy/agents/claude/parser.js} +0 -0
- /package/dist/{lib → integrations/proxy/agents/claude}/settings.d.ts +0 -0
- /package/dist/{lib → integrations/proxy/agents/claude}/settings.js +0 -0
- /package/dist/{proxy → integrations/proxy/cache}/extended-cache.d.ts +0 -0
- /package/dist/{proxy → integrations/proxy}/config.d.ts +0 -0
- /package/dist/{proxy → integrations/proxy}/index.d.ts +0 -0
- /package/dist/{proxy → integrations/proxy}/types.js +0 -0
- /package/dist/{lib → utils}/debug.d.ts +0 -0
- /package/dist/{lib → utils}/debug.js +0 -0
- /package/dist/{lib → utils}/utils.d.ts +0 -0
- /package/dist/{lib → utils}/utils.js +0 -0
|
@@ -1,174 +1,50 @@
|
|
|
1
1
|
// LLM-based extraction using Anthropic Claude Haiku for drift detection
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
let anthropicClient = null;
|
|
15
|
-
/**
|
|
16
|
-
* Initialize the Anthropic client
|
|
17
|
-
*/
|
|
18
|
-
function getAnthropicClient() {
|
|
19
|
-
if (!anthropicClient) {
|
|
20
|
-
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
21
|
-
if (!apiKey) {
|
|
22
|
-
throw new Error('ANTHROPIC_API_KEY environment variable is required for drift detection');
|
|
23
|
-
}
|
|
24
|
-
anthropicClient = new Anthropic({ apiKey });
|
|
25
|
-
}
|
|
26
|
-
return anthropicClient;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Extract intent from first user prompt using Haiku
|
|
30
|
-
* Called once at session start to populate session_states
|
|
31
|
-
* Falls back to basic extraction if API unavailable (for hook compatibility)
|
|
32
|
-
*/
|
|
33
|
-
export async function extractIntent(firstPrompt) {
|
|
34
|
-
// Check availability first - allows hook to work without API key
|
|
35
|
-
if (!isIntentExtractionAvailable()) {
|
|
36
|
-
return createFallbackIntent(firstPrompt);
|
|
37
|
-
}
|
|
2
|
+
import { debugLLM } from '../../utils/debug.js';
|
|
3
|
+
import { forwardToAnthropic } from '../../integrations/proxy/agents/claude/forwarder.js';
|
|
4
|
+
import { buildSafeHeaders } from '../../integrations/proxy/config.js';
|
|
5
|
+
import { isDebugMode } from '../../integrations/proxy/utils/logging.js';
|
|
6
|
+
// Haiku model constant
|
|
7
|
+
// Model list: https://docs.anthropic.com/en/docs/about-claude/models
|
|
8
|
+
const HAIKU_MODEL = 'claude-haiku-4-5-20251001';
|
|
9
|
+
async function callHaiku(maxTokens, prompt, headers, context = 'unknown') {
|
|
10
|
+
if (isDebugMode())
|
|
11
|
+
console.log(`[HAIKU] ${context} started`);
|
|
12
|
+
// Use same header filtering as proxy forward - includes all Claude Code headers
|
|
13
|
+
const safeHeaders = buildSafeHeaders(headers);
|
|
38
14
|
try {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
USER REQUEST:
|
|
43
|
-
${firstPrompt.substring(0, 2000)}
|
|
44
|
-
|
|
45
|
-
Extract as JSON:
|
|
46
|
-
{
|
|
47
|
-
"goal": "A single, high-density sentence describing the technical intent. RULES: 1. No bullet points, no newlines. 2. Must include the main Technology Name (e.g. 'Prometheus', 'React', 'AWS') if inferred. 3. If the user provided a list, synthesize it into one summary statement. Example: 'Implement Prometheus metrics collection with counter and gauge primitives' instead of 'Add metrics: - counters - gauges'.",
|
|
48
|
-
"expected_scope": ["list", "of", "files/folders", "likely", "to", "be", "modified"],
|
|
49
|
-
"constraints": ["EXPLICIT restrictions from the user - see examples below"],
|
|
50
|
-
"success_criteria": ["How to know when the task is complete"],
|
|
51
|
-
"keywords": ["relevant", "technical", "terms"]
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
═══════════════════════════════════════════════════════════════
|
|
55
|
-
CONSTRAINTS EXTRACTION - BE VERY THOROUGH
|
|
56
|
-
═══════════════════════════════════════════════════════════════
|
|
57
|
-
|
|
58
|
-
Look for NEGATIVE constraints (things NOT to do):
|
|
59
|
-
- "NU modifica" / "DON'T modify" / "NEVER change" / "don't touch"
|
|
60
|
-
- "NU rula" / "DON'T run" / "NO commands" / "don't execute"
|
|
61
|
-
- "fără X" / "without X" / "except X" / "not including"
|
|
62
|
-
- "nu scrie cod" / "don't write code" / "just plan"
|
|
63
|
-
|
|
64
|
-
Look for POSITIVE constraints (things MUST do / ONLY do):
|
|
65
|
-
- "ONLY modify X" / "DOAR în X" / "only in folder Y"
|
|
66
|
-
- "must use Y" / "trebuie să folosești Y"
|
|
67
|
-
- "keep it simple" / "no external dependencies"
|
|
68
|
-
- "use TypeScript" / "must be async"
|
|
69
|
-
|
|
70
|
-
EXAMPLES:
|
|
71
|
-
Input: "Fix bug in auth. NU modifica nimic in afara de sandbox/, NU rula comenzi."
|
|
72
|
-
Output constraints: ["DO NOT modify files outside sandbox/", "DO NOT run commands"]
|
|
73
|
-
|
|
74
|
-
Input: "Add feature X. Only use standard library, keep backward compatible."
|
|
75
|
-
Output constraints: ["ONLY use standard library", "Keep backward compatible"]
|
|
76
|
-
|
|
77
|
-
Input: "Analyze code and create plan. Nu scrie cod inca, doar planifica."
|
|
78
|
-
Output constraints: ["DO NOT write code yet", "Only create plan/analysis"]
|
|
79
|
-
|
|
80
|
-
For expected_scope:
|
|
81
|
-
- Include file patterns (e.g., "src/auth/", "*.test.ts", "sandbox/")
|
|
82
|
-
- Include component/module names mentioned
|
|
83
|
-
- Be conservative - only include clearly relevant areas
|
|
84
|
-
|
|
85
|
-
RESPONSE RULES:
|
|
86
|
-
- English only (translate Romanian/other languages to English)
|
|
87
|
-
- No emojis
|
|
88
|
-
- Valid JSON only
|
|
89
|
-
- If no constraints found, return empty array []`;
|
|
90
|
-
const response = await client.messages.create({
|
|
91
|
-
model: 'claude-haiku-4-5-20251001',
|
|
92
|
-
max_tokens: 500,
|
|
15
|
+
const result = await forwardToAnthropic({
|
|
16
|
+
model: HAIKU_MODEL,
|
|
17
|
+
max_tokens: maxTokens,
|
|
93
18
|
messages: [{ role: 'user', content: prompt }],
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
if (
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
const jsonMatch = content.text.match(/\{[\s\S]*\}/);
|
|
101
|
-
if (!jsonMatch) {
|
|
102
|
-
return createFallbackIntent(firstPrompt);
|
|
103
|
-
}
|
|
104
|
-
const parsed = JSON.parse(jsonMatch[0]);
|
|
105
|
-
return {
|
|
106
|
-
goal: typeof parsed.goal === 'string' ? parsed.goal : '', // Don't fallback to prompt
|
|
107
|
-
expected_scope: Array.isArray(parsed.expected_scope)
|
|
108
|
-
? parsed.expected_scope.filter((s) => typeof s === 'string')
|
|
109
|
-
: [],
|
|
110
|
-
constraints: Array.isArray(parsed.constraints)
|
|
111
|
-
? parsed.constraints.filter((c) => typeof c === 'string')
|
|
112
|
-
: [],
|
|
113
|
-
success_criteria: Array.isArray(parsed.success_criteria)
|
|
114
|
-
? parsed.success_criteria.filter((s) => typeof s === 'string')
|
|
115
|
-
: [],
|
|
116
|
-
keywords: Array.isArray(parsed.keywords)
|
|
117
|
-
? parsed.keywords.filter((k) => typeof k === 'string')
|
|
118
|
-
: [],
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
return createFallbackIntent(firstPrompt);
|
|
19
|
+
}, safeHeaders);
|
|
20
|
+
// Check for error response
|
|
21
|
+
if (result.statusCode >= 400) {
|
|
22
|
+
const errorBody = result.body;
|
|
23
|
+
throw new Error(errorBody.error?.message || `HTTP ${result.statusCode}`);
|
|
123
24
|
}
|
|
25
|
+
// Parse response
|
|
26
|
+
const body = result.body;
|
|
27
|
+
const text = body.content?.[0]?.type === 'text' ? body.content[0].text || '' : '';
|
|
28
|
+
if (isDebugMode())
|
|
29
|
+
console.log(`[HAIKU] ${context} success`);
|
|
30
|
+
return { text, success: true };
|
|
124
31
|
}
|
|
125
|
-
catch {
|
|
126
|
-
//
|
|
127
|
-
|
|
32
|
+
catch (err) {
|
|
33
|
+
// Always log errors
|
|
34
|
+
console.error(`[HAIKU] ${context} error:`, err.message);
|
|
35
|
+
return { text: '', success: false };
|
|
128
36
|
}
|
|
129
37
|
}
|
|
130
|
-
/**
|
|
131
|
-
* Fallback intent extraction without LLM
|
|
132
|
-
*/
|
|
133
|
-
function createFallbackIntent(prompt) {
|
|
134
|
-
// Basic keyword extraction
|
|
135
|
-
const words = prompt.toLowerCase().split(/\s+/);
|
|
136
|
-
const techKeywords = words.filter(w => w.length > 3 &&
|
|
137
|
-
/^[a-z]+$/.test(w) &&
|
|
138
|
-
!['this', 'that', 'with', 'from', 'have', 'will', 'would', 'could', 'should'].includes(w));
|
|
139
|
-
// Extract file patterns
|
|
140
|
-
const filePatterns = prompt.match(/[\w\/.-]+\.(ts|js|tsx|jsx|py|go|rs|java|css|html|md)/g) || [];
|
|
141
|
-
return {
|
|
142
|
-
goal: '', // Empty - don't copy user prompt as goal; goal should be synthesized only
|
|
143
|
-
expected_scope: [...new Set(filePatterns)].slice(0, 5),
|
|
144
|
-
constraints: [],
|
|
145
|
-
success_criteria: [],
|
|
146
|
-
keywords: [...new Set(techKeywords)].slice(0, 10),
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Check if intent extraction is available
|
|
151
|
-
*/
|
|
152
|
-
export function isIntentExtractionAvailable() {
|
|
153
|
-
return !!(process.env.ANTHROPIC_API_KEY || process.env.GROV_API_KEY);
|
|
154
|
-
}
|
|
155
38
|
// ============================================
|
|
156
39
|
// SESSION SUMMARY FOR CLEAR OPERATION
|
|
157
40
|
// Reference: plan_proxy_local.md Section 2.3, 4.5
|
|
158
41
|
// ============================================
|
|
159
|
-
/**
|
|
160
|
-
* Check if session summary generation is available
|
|
161
|
-
*/
|
|
162
|
-
export function isSummaryAvailable() {
|
|
163
|
-
return !!(process.env.ANTHROPIC_API_KEY || process.env.GROV_API_KEY);
|
|
164
|
-
}
|
|
165
42
|
/**
|
|
166
43
|
* Generate session summary for CLEAR operation
|
|
167
44
|
* Reference: plan_proxy_local.md Section 2.3, 4.5
|
|
168
45
|
*/
|
|
169
|
-
export async function generateSessionSummary(sessionState, steps, maxTokens = 800 // Default 800, CLEAR mode uses 15000
|
|
170
|
-
) {
|
|
171
|
-
const client = getAnthropicClient();
|
|
46
|
+
export async function generateSessionSummary(sessionState, steps, maxTokens = 800, // Default 800, CLEAR mode uses 15000
|
|
47
|
+
headers) {
|
|
172
48
|
// For larger summaries, include more steps
|
|
173
49
|
const stepLimit = maxTokens > 5000 ? 50 : 20;
|
|
174
50
|
const wordLimit = Math.min(Math.floor(maxTokens / 2), 10000); // ~2 tokens per word
|
|
@@ -193,8 +69,6 @@ export async function generateSessionSummary(sessionState, steps, maxTokens = 80
|
|
|
193
69
|
|
|
194
70
|
ORIGINAL GOAL: ${sessionState.original_goal || 'Not specified'}
|
|
195
71
|
|
|
196
|
-
EXPECTED SCOPE: ${sessionState.expected_scope.join(', ') || 'Not specified'}
|
|
197
|
-
|
|
198
72
|
CONSTRAINTS: ${sessionState.constraints.join(', ') || 'None'}
|
|
199
73
|
|
|
200
74
|
ACTIONS TAKEN:
|
|
@@ -210,18 +84,13 @@ Create a summary with these sections (keep total under ${wordLimit} words):
|
|
|
210
84
|
${maxTokens > 5000 ? '7. IMPORTANT CONTEXT: (any critical information that must not be lost)' : ''}
|
|
211
85
|
|
|
212
86
|
Format as plain text, not JSON.`;
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
max_tokens: maxTokens,
|
|
216
|
-
messages: [{ role: 'user', content: prompt }],
|
|
217
|
-
});
|
|
218
|
-
const content = response.content?.[0];
|
|
219
|
-
if (!content || content.type !== 'text') {
|
|
87
|
+
const haikuResult = await callHaiku(maxTokens, prompt, headers, 'generateSessionSummary');
|
|
88
|
+
if (!haikuResult.success || !haikuResult.text) {
|
|
220
89
|
return createFallbackSummary(sessionState, steps);
|
|
221
90
|
}
|
|
222
91
|
return `PREVIOUS SESSION CONTEXT (auto-generated after context limit):
|
|
223
92
|
|
|
224
|
-
${
|
|
93
|
+
${haikuResult.text}`;
|
|
225
94
|
}
|
|
226
95
|
/**
|
|
227
96
|
* Create fallback summary without LLM
|
|
@@ -239,12 +108,6 @@ ${files.slice(0, 10).map(f => `- ${f}`).join('\n') || '- None recorded'}
|
|
|
239
108
|
|
|
240
109
|
Please continue from where you left off.`;
|
|
241
110
|
}
|
|
242
|
-
/**
|
|
243
|
-
* Check if task analysis is available
|
|
244
|
-
*/
|
|
245
|
-
export function isTaskAnalysisAvailable() {
|
|
246
|
-
return !!(process.env.ANTHROPIC_API_KEY || process.env.GROV_API_KEY);
|
|
247
|
-
}
|
|
248
111
|
/**
|
|
249
112
|
* Format conversation messages for prompt
|
|
250
113
|
*/
|
|
@@ -280,8 +143,7 @@ function formatToolCalls(steps) {
|
|
|
280
143
|
* Called after each main model response to orchestrate sessions
|
|
281
144
|
* Also compresses reasoning for steps if assistantResponse > 1000 chars
|
|
282
145
|
*/
|
|
283
|
-
export async function analyzeTaskContext(currentSession, latestUserMessage, recentSteps, assistantResponse, conversationHistory) {
|
|
284
|
-
const client = getAnthropicClient();
|
|
146
|
+
export async function analyzeTaskContext(currentSession, latestUserMessage, recentSteps, assistantResponse, conversationHistory, headers) {
|
|
285
147
|
// Check if we need to compress reasoning
|
|
286
148
|
const needsCompression = assistantResponse.length > 1000;
|
|
287
149
|
const compressionInstruction = needsCompression
|
|
@@ -309,10 +171,13 @@ ${toolCallsText}
|
|
|
309
171
|
<output>
|
|
310
172
|
Return a JSON object with these fields:
|
|
311
173
|
- task_type: one of "information", "planning", or "implementation"
|
|
312
|
-
- action: one of "continue", "task_complete", "new_task", or "subtask_complete"
|
|
174
|
+
- action: one of "continue", "task_complete", "new_task", "subtask", "parallel_task", or "subtask_complete"
|
|
313
175
|
- task_id: existing session_id "${currentSession?.session_id || 'NEW'}" or "NEW" for new task
|
|
314
176
|
- current_goal: "SYNTHESIZE a concise goal (max 150 chars). RULES: 1. If original_goal is empty, SYNTHESIZE from user messages. 2. DO NOT copy the user's request verbatim - summarize it. 3. Start with Technology/Component name. 4. One sentence, no newlines. Example: 'TypeScript Logger with level filtering and JSON output' NOT 'Create a structured logger in /home/... with debug, info...'"
|
|
315
177
|
- reasoning: brief explanation of why you made this decision${compressionInstruction}
|
|
178
|
+
|
|
179
|
+
CONDITIONAL FIELD (only include when action is "new_task", "subtask", or "parallel_task"):
|
|
180
|
+
- constraints: array of explicit restrictions from user (see step_4_extract_constraints). If no restrictions found, use empty array [].
|
|
316
181
|
</output>
|
|
317
182
|
|
|
318
183
|
<step_1_identify_task_type>
|
|
@@ -471,6 +336,57 @@ Reason: The new task was requested AND completed. Use task_complete so it gets s
|
|
|
471
336
|
The key insight: task_complete saves the memory. If you return new_task, the work won't be saved until a FUTURE completion. If Claude already finished the work, use task_complete.
|
|
472
337
|
</step_3_detect_new_task>
|
|
473
338
|
|
|
339
|
+
<step_4_extract_constraints>
|
|
340
|
+
ONLY perform this step if action is "new_task", "subtask", or "parallel_task".
|
|
341
|
+
If action is "continue" or "task_complete", skip this and set constraints to empty array [].
|
|
342
|
+
|
|
343
|
+
WHAT IS A CONSTRAINT?
|
|
344
|
+
A constraint is an EXPLICIT restriction the user stated about HOW to do the task.
|
|
345
|
+
It is NOT the task itself - it is a LIMIT on how the task should be done.
|
|
346
|
+
|
|
347
|
+
TWO TYPES:
|
|
348
|
+
|
|
349
|
+
1. NEGATIVE CONSTRAINTS - Things Claude must NOT do:
|
|
350
|
+
Pattern: "don't", "do not", "never", "no", "without", "except", "avoid"
|
|
351
|
+
|
|
352
|
+
Examples:
|
|
353
|
+
- "Don't modify files outside src/" becomes "DO NOT modify files outside src/"
|
|
354
|
+
- "No external dependencies" becomes "DO NOT add external dependencies"
|
|
355
|
+
- "Just plan, don't code yet" becomes "DO NOT write code"
|
|
356
|
+
|
|
357
|
+
2. POSITIVE CONSTRAINTS - Things Claude MUST do or ONLY do:
|
|
358
|
+
Pattern: "only", "must", "always", "keep", "use only"
|
|
359
|
+
|
|
360
|
+
Examples:
|
|
361
|
+
- "Only modify the auth module" becomes "ONLY modify auth module"
|
|
362
|
+
- "Must use TypeScript" becomes "MUST use TypeScript"
|
|
363
|
+
- "Keep backward compatible" becomes "MUST keep backward compatible"
|
|
364
|
+
|
|
365
|
+
WHAT IS NOT A CONSTRAINT:
|
|
366
|
+
- The task itself: "Fix the bug" is the goal, not a constraint
|
|
367
|
+
- General preferences: "Make it fast" is too vague, not an explicit restriction
|
|
368
|
+
- Questions: "Should I use Redis?" is not a restriction
|
|
369
|
+
|
|
370
|
+
OUTPUT FORMAT:
|
|
371
|
+
- Start each constraint with "DO NOT", "ONLY", or "MUST"
|
|
372
|
+
- Be specific and actionable
|
|
373
|
+
- If no constraints found, return empty array []
|
|
374
|
+
|
|
375
|
+
EXAMPLES:
|
|
376
|
+
|
|
377
|
+
User message: "Fix the auth bug. Don't touch the database code."
|
|
378
|
+
constraints: ["DO NOT modify database code"]
|
|
379
|
+
|
|
380
|
+
User message: "Add caching. Only use Redis, must be async."
|
|
381
|
+
constraints: ["ONLY use Redis", "MUST be async"]
|
|
382
|
+
|
|
383
|
+
User message: "Explain how auth works"
|
|
384
|
+
constraints: []
|
|
385
|
+
|
|
386
|
+
User message: "Implement feature X"
|
|
387
|
+
constraints: []
|
|
388
|
+
</step_4_extract_constraints>
|
|
389
|
+
|
|
474
390
|
<important_notes>
|
|
475
391
|
Do not rely on specific keywords in any language. The same intent can be expressed many different ways across languages and phrasings. Always understand the intent from the full context.
|
|
476
392
|
|
|
@@ -490,12 +406,21 @@ RESPONSE RULES:
|
|
|
490
406
|
- No markdown formatting, no emojis
|
|
491
407
|
</important_notes>`;
|
|
492
408
|
debugLLM('analyzeTaskContext', `Calling Haiku for task analysis (needsCompression=${needsCompression})`);
|
|
493
|
-
const
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
409
|
+
const haikuResult = await callHaiku(needsCompression ? 800 : 400, prompt, headers, 'analyzeTaskContext');
|
|
410
|
+
if (!haikuResult.success) {
|
|
411
|
+
// Fallback on error
|
|
412
|
+
const fallbackGoal = currentSession?.original_goal || '';
|
|
413
|
+
return {
|
|
414
|
+
task_type: 'implementation',
|
|
415
|
+
action: currentSession ? 'continue' : 'new_task',
|
|
416
|
+
task_id: currentSession?.session_id || 'NEW',
|
|
417
|
+
current_goal: fallbackGoal,
|
|
418
|
+
reasoning: 'Fallback due to Haiku error',
|
|
419
|
+
step_reasoning: assistantResponse.substring(0, 1000),
|
|
420
|
+
constraints: [],
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
const text = haikuResult.text;
|
|
499
424
|
try {
|
|
500
425
|
// Try to parse JSON from response (may have extra text)
|
|
501
426
|
const jsonMatch = text.match(/\{[\s\S]*\}/);
|
|
@@ -511,7 +436,16 @@ RESPONSE RULES:
|
|
|
511
436
|
if (!needsCompression && assistantResponse.length > 0) {
|
|
512
437
|
analysis.step_reasoning = assistantResponse.substring(0, 1000);
|
|
513
438
|
}
|
|
514
|
-
|
|
439
|
+
// Parse constraints (only for new_task/subtask/parallel_task actions)
|
|
440
|
+
if (analysis.constraints) {
|
|
441
|
+
analysis.constraints = Array.isArray(analysis.constraints)
|
|
442
|
+
? analysis.constraints.filter((c) => typeof c === 'string')
|
|
443
|
+
: [];
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
analysis.constraints = [];
|
|
447
|
+
}
|
|
448
|
+
debugLLM('analyzeTaskContext', `Result: task_type=${analysis.task_type}, action=${analysis.action}, goal="${analysis.current_goal?.substring(0, 50) || 'N/A'}" constraints=${analysis.constraints.length} reasoning="${analysis.reasoning?.substring(0, 150) || 'none'}"`);
|
|
515
449
|
return analysis;
|
|
516
450
|
}
|
|
517
451
|
catch (parseError) {
|
|
@@ -528,15 +462,10 @@ RESPONSE RULES:
|
|
|
528
462
|
current_goal: fallbackGoal,
|
|
529
463
|
reasoning: 'Fallback due to parse error',
|
|
530
464
|
step_reasoning: assistantResponse.substring(0, 1000),
|
|
465
|
+
constraints: [],
|
|
531
466
|
};
|
|
532
467
|
}
|
|
533
468
|
}
|
|
534
|
-
/**
|
|
535
|
-
* Check if reasoning extraction is available
|
|
536
|
-
*/
|
|
537
|
-
export function isReasoningExtractionAvailable() {
|
|
538
|
-
return !!process.env.ANTHROPIC_API_KEY || !!process.env.GROV_API_KEY;
|
|
539
|
-
}
|
|
540
469
|
/**
|
|
541
470
|
* Extract reasoning trace and decisions from steps
|
|
542
471
|
* Called at task_complete to populate team memory with rich context
|
|
@@ -544,8 +473,7 @@ export function isReasoningExtractionAvailable() {
|
|
|
544
473
|
* @param formattedSteps - Pre-formatted XML string with grouped steps and actions
|
|
545
474
|
* @param originalGoal - The original task goal
|
|
546
475
|
*/
|
|
547
|
-
export async function extractReasoningAndDecisions(formattedSteps, originalGoal) {
|
|
548
|
-
const client = getAnthropicClient();
|
|
476
|
+
export async function extractReasoningAndDecisions(formattedSteps, originalGoal, headers) {
|
|
549
477
|
if (formattedSteps.length < 50) {
|
|
550
478
|
return { system_name: null, summary: null, reasoning_trace: [], decisions: [] };
|
|
551
479
|
}
|
|
@@ -900,16 +828,14 @@ Before responding, verify:
|
|
|
900
828
|
|
|
901
829
|
Return ONLY valid JSON, no markdown code blocks, no explanation.`;
|
|
902
830
|
debugLLM('extractReasoningAndDecisions', `Analyzing formatted steps, ${formattedSteps.length} chars`);
|
|
831
|
+
const haikuResult = await callHaiku(1500, prompt, headers, 'extractReasoningAndDecisions');
|
|
832
|
+
if (!haikuResult.success) {
|
|
833
|
+
return { system_name: null, summary: null, reasoning_trace: [], decisions: [] };
|
|
834
|
+
}
|
|
903
835
|
try {
|
|
904
|
-
const
|
|
905
|
-
model: 'claude-haiku-4-5-20251001',
|
|
906
|
-
max_tokens: 1500,
|
|
907
|
-
messages: [{ role: 'user', content: prompt }],
|
|
908
|
-
});
|
|
909
|
-
const text = response.content[0].type === 'text' ? response.content[0].text : '';
|
|
836
|
+
const text = haikuResult.text;
|
|
910
837
|
const jsonMatch = text.match(/\{[\s\S]*\}/);
|
|
911
838
|
if (!jsonMatch) {
|
|
912
|
-
console.error('[LLM-EXTRACTOR] No JSON in response');
|
|
913
839
|
return { system_name: null, summary: null, reasoning_trace: [], decisions: [] };
|
|
914
840
|
}
|
|
915
841
|
// Try to parse JSON, with repair attempts for common Haiku formatting issues
|
|
@@ -938,13 +864,11 @@ Return ONLY valid JSON, no markdown code blocks, no explanation.`;
|
|
|
938
864
|
const extractedSystemName = systemMatch ? systemMatch[1] : undefined;
|
|
939
865
|
result = { system_name: extractedSystemName, knowledge_pairs: pairs, decisions: [] };
|
|
940
866
|
}
|
|
941
|
-
catch
|
|
942
|
-
console.error('[LLM-EXTRACTOR] JSON parse failed');
|
|
867
|
+
catch {
|
|
943
868
|
throw parseError;
|
|
944
869
|
}
|
|
945
870
|
}
|
|
946
871
|
else {
|
|
947
|
-
console.error('[LLM-EXTRACTOR] JSON parse failed');
|
|
948
872
|
throw parseError;
|
|
949
873
|
}
|
|
950
874
|
}
|
|
@@ -984,12 +908,6 @@ Return ONLY valid JSON, no markdown code blocks, no explanation.`;
|
|
|
984
908
|
return { system_name: null, summary: null, reasoning_trace: [], decisions: [] };
|
|
985
909
|
}
|
|
986
910
|
}
|
|
987
|
-
/**
|
|
988
|
-
* Check if shouldUpdateMemory is available
|
|
989
|
-
*/
|
|
990
|
-
export function isShouldUpdateAvailable() {
|
|
991
|
-
return !!process.env.ANTHROPIC_API_KEY || !!process.env.GROV_API_KEY;
|
|
992
|
-
}
|
|
993
911
|
/**
|
|
994
912
|
* Decide if a memory should be updated based on new session data
|
|
995
913
|
* Called when a match is found before sync
|
|
@@ -1447,25 +1365,21 @@ Input: task_type=information, query="Ok I understand now", files_touched=[]
|
|
|
1447
1365
|
Output: {"should_update": false, "reason": "User acknowledged explanation but did not confirm any change", "superseded_mapping": [], "condensed_old_reasoning": null, "evolution_summary": null}
|
|
1448
1366
|
</examples>`;
|
|
1449
1367
|
}
|
|
1450
|
-
export async function shouldUpdateMemory(existingMemory, newData, sessionContext) {
|
|
1451
|
-
const client = getAnthropicClient();
|
|
1368
|
+
export async function shouldUpdateMemory(existingMemory, newData, sessionContext, headers) {
|
|
1452
1369
|
// Check if evolution_steps consolidation is needed
|
|
1453
1370
|
const evolutionCount = existingMemory.evolution_steps?.length || 0;
|
|
1454
1371
|
const needsConsolidation = evolutionCount > 10;
|
|
1455
1372
|
// Build the prompt with all context
|
|
1456
1373
|
const prompt = buildShouldUpdatePrompt(existingMemory, newData, sessionContext, needsConsolidation, evolutionCount);
|
|
1457
1374
|
debugLLM('shouldUpdateMemory', `Analyzing memory update (needsConsolidation=${needsConsolidation})`);
|
|
1375
|
+
const haikuResult = await callHaiku(needsConsolidation ? 1500 : 800, prompt, headers, 'shouldUpdateMemory');
|
|
1376
|
+
if (!haikuResult.success) {
|
|
1377
|
+
return createFallbackResult(sessionContext);
|
|
1378
|
+
}
|
|
1458
1379
|
try {
|
|
1459
|
-
const
|
|
1460
|
-
model: 'claude-haiku-4-5-20251001',
|
|
1461
|
-
max_tokens: needsConsolidation ? 1500 : 800,
|
|
1462
|
-
messages: [{ role: 'user', content: prompt }],
|
|
1463
|
-
});
|
|
1464
|
-
const text = response.content[0].type === 'text' ? response.content[0].text : '';
|
|
1465
|
-
// Try to parse JSON from response
|
|
1380
|
+
const text = haikuResult.text;
|
|
1466
1381
|
const jsonMatch = text.match(/\{[\s\S]*\}/);
|
|
1467
1382
|
if (!jsonMatch) {
|
|
1468
|
-
console.error('[HAIKU] No JSON in response');
|
|
1469
1383
|
return createFallbackResult(sessionContext);
|
|
1470
1384
|
}
|
|
1471
1385
|
// Parse and validate response
|
|
@@ -1473,8 +1387,7 @@ export async function shouldUpdateMemory(existingMemory, newData, sessionContext
|
|
|
1473
1387
|
try {
|
|
1474
1388
|
result = JSON.parse(jsonMatch[0]);
|
|
1475
1389
|
}
|
|
1476
|
-
catch
|
|
1477
|
-
console.error('[HAIKU] JSON parse failed');
|
|
1390
|
+
catch {
|
|
1478
1391
|
return createFallbackResult(sessionContext);
|
|
1479
1392
|
}
|
|
1480
1393
|
// Ensure required fields have defaults
|
|
@@ -1487,8 +1400,7 @@ export async function shouldUpdateMemory(existingMemory, newData, sessionContext
|
|
|
1487
1400
|
debugLLM('shouldUpdateMemory', `Result: should_update=${result.should_update}, reason="${result.reason.substring(0, 50)}"`);
|
|
1488
1401
|
return result;
|
|
1489
1402
|
}
|
|
1490
|
-
catch
|
|
1491
|
-
console.error('[HAIKU] Error:', String(error));
|
|
1403
|
+
catch {
|
|
1492
1404
|
return createFallbackResult(sessionContext);
|
|
1493
1405
|
}
|
|
1494
1406
|
}
|
|
@@ -11,9 +11,7 @@ function rowToSessionState(row) {
|
|
|
11
11
|
project_path: row.project_path,
|
|
12
12
|
original_goal: row.original_goal,
|
|
13
13
|
raw_user_prompt: row.raw_user_prompt,
|
|
14
|
-
expected_scope: safeJsonParse(row.expected_scope, []),
|
|
15
14
|
constraints: safeJsonParse(row.constraints, []),
|
|
16
|
-
keywords: safeJsonParse(row.keywords, []),
|
|
17
15
|
escalation_count: row.escalation_count || 0,
|
|
18
16
|
last_checked_at: row.last_checked_at || 0,
|
|
19
17
|
start_time: row.start_time,
|
|
@@ -47,8 +45,6 @@ function rowToSessionState(row) {
|
|
|
47
45
|
* Uses INSERT OR IGNORE to handle race conditions safely.
|
|
48
46
|
*/
|
|
49
47
|
export function createSessionState(input) {
|
|
50
|
-
// DEBUG: Commented out for cleaner terminal - uncomment when debugging
|
|
51
|
-
// console.log(`[DEBUG-DB] createSessionState called with raw_user_prompt="${input.raw_user_prompt?.substring(0, 50)}"`);
|
|
52
48
|
const database = getDb();
|
|
53
49
|
const now = new Date().toISOString();
|
|
54
50
|
const sessionState = {
|
|
@@ -58,9 +54,7 @@ export function createSessionState(input) {
|
|
|
58
54
|
project_path: input.project_path,
|
|
59
55
|
original_goal: input.original_goal,
|
|
60
56
|
raw_user_prompt: input.raw_user_prompt,
|
|
61
|
-
expected_scope: input.expected_scope || [],
|
|
62
57
|
constraints: input.constraints || [],
|
|
63
|
-
keywords: input.keywords || [],
|
|
64
58
|
escalation_count: 0,
|
|
65
59
|
last_checked_at: 0,
|
|
66
60
|
start_time: now,
|
|
@@ -87,18 +81,16 @@ export function createSessionState(input) {
|
|
|
87
81
|
const stmt = database.prepare(`
|
|
88
82
|
INSERT OR IGNORE INTO session_states (
|
|
89
83
|
session_id, user_id, project_path, original_goal, raw_user_prompt,
|
|
90
|
-
|
|
84
|
+
constraints,
|
|
91
85
|
token_count, escalation_count, session_mode,
|
|
92
86
|
waiting_for_recovery, last_checked_at, last_clear_at,
|
|
93
87
|
start_time, last_update, status,
|
|
94
88
|
parent_session_id, task_type,
|
|
95
89
|
success_criteria, last_drift_score, pending_recovery_plan, drift_history,
|
|
96
90
|
completed_at
|
|
97
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
|
91
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
98
92
|
`);
|
|
99
|
-
stmt.run(sessionState.session_id, sessionState.user_id || null, sessionState.project_path, sessionState.original_goal || null, sessionState.raw_user_prompt || null, JSON.stringify(sessionState.
|
|
100
|
-
// DEBUG: Commented out for cleaner terminal - uncomment when debugging
|
|
101
|
-
// console.log(`[DEBUG-DB] INSERT done. sessionState.raw_user_prompt="${sessionState.raw_user_prompt?.substring(0, 50)}"`);
|
|
93
|
+
stmt.run(sessionState.session_id, sessionState.user_id || null, sessionState.project_path, sessionState.original_goal || null, sessionState.raw_user_prompt || null, JSON.stringify(sessionState.constraints), sessionState.token_count, sessionState.escalation_count, sessionState.session_mode, sessionState.waiting_for_recovery ? 1 : 0, sessionState.last_checked_at, sessionState.last_clear_at || null, sessionState.start_time, sessionState.last_update, sessionState.status, sessionState.parent_session_id || null, sessionState.task_type, JSON.stringify(sessionState.success_criteria || []), sessionState.last_drift_score || null, sessionState.pending_recovery_plan ? JSON.stringify(sessionState.pending_recovery_plan) : null, JSON.stringify(sessionState.drift_history || []), sessionState.completed_at || null);
|
|
102
94
|
return sessionState;
|
|
103
95
|
}
|
|
104
96
|
/**
|
|
@@ -130,18 +122,10 @@ export function updateSessionState(sessionId, updates) {
|
|
|
130
122
|
setClauses.push('original_goal = ?');
|
|
131
123
|
params.push(updates.original_goal || null);
|
|
132
124
|
}
|
|
133
|
-
if (updates.expected_scope !== undefined) {
|
|
134
|
-
setClauses.push('expected_scope = ?');
|
|
135
|
-
params.push(JSON.stringify(updates.expected_scope));
|
|
136
|
-
}
|
|
137
125
|
if (updates.constraints !== undefined) {
|
|
138
126
|
setClauses.push('constraints = ?');
|
|
139
127
|
params.push(JSON.stringify(updates.constraints));
|
|
140
128
|
}
|
|
141
|
-
if (updates.keywords !== undefined) {
|
|
142
|
-
setClauses.push('keywords = ?');
|
|
143
|
-
params.push(JSON.stringify(updates.keywords));
|
|
144
|
-
}
|
|
145
129
|
if (updates.token_count !== undefined) {
|
|
146
130
|
setClauses.push('token_count = ?');
|
|
147
131
|
params.push(updates.token_count);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './index.js';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Re-export from modular store for backward compatibility
|
|
2
|
-
export * from './
|
|
2
|
+
export * from './index.js';
|
|
@@ -72,9 +72,7 @@ interface SessionStateBase {
|
|
|
72
72
|
project_path: string;
|
|
73
73
|
original_goal?: string;
|
|
74
74
|
raw_user_prompt?: string;
|
|
75
|
-
expected_scope: string[];
|
|
76
75
|
constraints: string[];
|
|
77
|
-
keywords: string[];
|
|
78
76
|
escalation_count: number;
|
|
79
77
|
last_checked_at: number;
|
|
80
78
|
start_time: string;
|
|
@@ -113,9 +111,7 @@ export interface CreateSessionStateInput {
|
|
|
113
111
|
project_path: string;
|
|
114
112
|
original_goal?: string;
|
|
115
113
|
raw_user_prompt?: string;
|
|
116
|
-
expected_scope?: string[];
|
|
117
114
|
constraints?: string[];
|
|
118
|
-
keywords?: string[];
|
|
119
115
|
success_criteria?: string[];
|
|
120
116
|
parent_session_id?: string;
|
|
121
117
|
task_type?: TaskType;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Memory } from '@grov/shared';
|
|
2
|
+
/**
|
|
3
|
+
* Get current project path
|
|
4
|
+
* Used as cache key and for API filtering
|
|
5
|
+
*
|
|
6
|
+
* Cursor sets WORKSPACE_FOLDER_PATHS env var with the open workspace path.
|
|
7
|
+
* We extract just the folder name to match how proxy stores project_path.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getProjectPath(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Store memories from preview call
|
|
12
|
+
* Indexes by 8-char ID prefix for fast lookup
|
|
13
|
+
*/
|
|
14
|
+
export declare function setPreviewCache(memories: Memory[]): void;
|
|
15
|
+
/**
|
|
16
|
+
* Get memory by 8-char ID
|
|
17
|
+
* Handles both 8-char and full UUID (extracts first 8 chars)
|
|
18
|
+
*/
|
|
19
|
+
export declare function getMemoryById(id: string): Memory | null;
|
|
20
|
+
/**
|
|
21
|
+
* Get list of cached IDs (for error messages)
|
|
22
|
+
*/
|
|
23
|
+
export declare function getCachedIds(): string[];
|
|
24
|
+
/**
|
|
25
|
+
* Clear preview cache (e.g., when project changes)
|
|
26
|
+
*/
|
|
27
|
+
export declare function clearPreviewCache(): void;
|