codegrunt 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +351 -0
  2. package/dist/cli/at-resolver.d.ts +10 -0
  3. package/dist/cli/at-resolver.js +138 -0
  4. package/dist/cli/at-resolver.js.map +1 -0
  5. package/dist/cli/banner.d.ts +1 -0
  6. package/dist/cli/banner.js +111 -0
  7. package/dist/cli/banner.js.map +1 -0
  8. package/dist/cli/commands.d.ts +25 -0
  9. package/dist/cli/commands.js +799 -0
  10. package/dist/cli/commands.js.map +1 -0
  11. package/dist/cli/index.d.ts +2 -0
  12. package/dist/cli/index.js +142 -0
  13. package/dist/cli/index.js.map +1 -0
  14. package/dist/cli/input.d.ts +14 -0
  15. package/dist/cli/input.js +742 -0
  16. package/dist/cli/input.js.map +1 -0
  17. package/dist/cli/repl.d.ts +2 -0
  18. package/dist/cli/repl.js +217 -0
  19. package/dist/cli/repl.js.map +1 -0
  20. package/dist/cli/setup.d.ts +7 -0
  21. package/dist/cli/setup.js +82 -0
  22. package/dist/cli/setup.js.map +1 -0
  23. package/dist/cli/skills.d.ts +28 -0
  24. package/dist/cli/skills.js +299 -0
  25. package/dist/cli/skills.js.map +1 -0
  26. package/dist/cli/update.d.ts +7 -0
  27. package/dist/cli/update.js +135 -0
  28. package/dist/cli/update.js.map +1 -0
  29. package/dist/config.d.ts +19 -0
  30. package/dist/config.js +93 -0
  31. package/dist/config.js.map +1 -0
  32. package/dist/core/agent/loop.d.ts +17 -0
  33. package/dist/core/agent/loop.js +353 -0
  34. package/dist/core/agent/loop.js.map +1 -0
  35. package/dist/core/context/manager.d.ts +26 -0
  36. package/dist/core/context/manager.js +98 -0
  37. package/dist/core/context/manager.js.map +1 -0
  38. package/dist/core/context/project-guide.d.ts +1 -0
  39. package/dist/core/context/project-guide.js +17 -0
  40. package/dist/core/context/project-guide.js.map +1 -0
  41. package/dist/core/tools/edit_file.d.ts +2 -0
  42. package/dist/core/tools/edit_file.js +54 -0
  43. package/dist/core/tools/edit_file.js.map +1 -0
  44. package/dist/core/tools/execute_shell.d.ts +2 -0
  45. package/dist/core/tools/execute_shell.js +67 -0
  46. package/dist/core/tools/execute_shell.js.map +1 -0
  47. package/dist/core/tools/executor.d.ts +3 -0
  48. package/dist/core/tools/executor.js +86 -0
  49. package/dist/core/tools/executor.js.map +1 -0
  50. package/dist/core/tools/list_directory.d.ts +2 -0
  51. package/dist/core/tools/list_directory.js +74 -0
  52. package/dist/core/tools/list_directory.js.map +1 -0
  53. package/dist/core/tools/read_file.d.ts +2 -0
  54. package/dist/core/tools/read_file.js +40 -0
  55. package/dist/core/tools/read_file.js.map +1 -0
  56. package/dist/core/tools/registry.d.ts +4 -0
  57. package/dist/core/tools/registry.js +24 -0
  58. package/dist/core/tools/registry.js.map +1 -0
  59. package/dist/core/tools/search_files.d.ts +2 -0
  60. package/dist/core/tools/search_files.js +88 -0
  61. package/dist/core/tools/search_files.js.map +1 -0
  62. package/dist/core/tools/write_file.d.ts +2 -0
  63. package/dist/core/tools/write_file.js +43 -0
  64. package/dist/core/tools/write_file.js.map +1 -0
  65. package/dist/providers/deepseek/client.d.ts +8 -0
  66. package/dist/providers/deepseek/client.js +27 -0
  67. package/dist/providers/deepseek/client.js.map +1 -0
  68. package/dist/providers/deepseek/provider.d.ts +8 -0
  69. package/dist/providers/deepseek/provider.js +165 -0
  70. package/dist/providers/deepseek/provider.js.map +1 -0
  71. package/dist/types.d.ts +111 -0
  72. package/dist/types.js +3 -0
  73. package/dist/types.js.map +1 -0
  74. package/dist/utils/billing.d.ts +40 -0
  75. package/dist/utils/billing.js +165 -0
  76. package/dist/utils/billing.js.map +1 -0
  77. package/dist/utils/confirm.d.ts +3 -0
  78. package/dist/utils/confirm.js +242 -0
  79. package/dist/utils/confirm.js.map +1 -0
  80. package/dist/utils/display.d.ts +10 -0
  81. package/dist/utils/display.js +121 -0
  82. package/dist/utils/display.js.map +1 -0
  83. package/dist/utils/interrupt.d.ts +5 -0
  84. package/dist/utils/interrupt.js +13 -0
  85. package/dist/utils/interrupt.js.map +1 -0
  86. package/dist/utils/markdown.d.ts +18 -0
  87. package/dist/utils/markdown.js +223 -0
  88. package/dist/utils/markdown.js.map +1 -0
  89. package/package.json +42 -0
@@ -0,0 +1,353 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { ContextManager } from '../context/manager.js';
4
+ import { loadProjectGuide } from '../context/project-guide.js';
5
+ import { getToolDefinitions } from '../tools/registry.js';
6
+ import { executeTool, resetYesAll } from '../tools/executor.js';
7
+ import { printToolCall, printToolResult, printAssistantHeader, printThinkingCollapsed } from '../../utils/display.js';
8
+ import { MarkdownRenderer } from '../../utils/markdown.js';
9
+ import { isReasonerModel, CHAT_CONTEXT_BUDGET } from '../../config.js';
10
+ const MAX_ITERATIONS = 30;
11
+ // ── Cumulative usage tracking ──────────────────────────────────────────────
12
+ const sessionUsage = { inputTokens: 0, outputTokens: 0, cacheHitTokens: 0, cacheMissTokens: 0 };
13
+ export function addUsage(u) {
14
+ sessionUsage.inputTokens += u.inputTokens;
15
+ sessionUsage.outputTokens += u.outputTokens;
16
+ sessionUsage.cacheHitTokens += u.cacheHitTokens;
17
+ sessionUsage.cacheMissTokens += u.cacheMissTokens;
18
+ }
19
+ export function getSessionUsage() {
20
+ return { ...sessionUsage };
21
+ }
22
+ export function resetSessionUsage() {
23
+ sessionUsage.inputTokens = 0;
24
+ sessionUsage.outputTokens = 0;
25
+ sessionUsage.cacheHitTokens = 0;
26
+ sessionUsage.cacheMissTokens = 0;
27
+ }
28
+ // Detect the system language from environment variables / locale.
29
+ // Returns 'zh' for Chinese systems, otherwise 'en'.
30
+ function detectSystemLanguage() {
31
+ const locale = process.env.LC_ALL
32
+ || process.env.LC_MESSAGES
33
+ || process.env.LANG
34
+ || '';
35
+ if (locale.toLowerCase().startsWith('zh'))
36
+ return 'zh';
37
+ // Also check Windows system locale
38
+ if (process.platform === 'win32') {
39
+ try {
40
+ const resolved = Intl.DateTimeFormat().resolvedOptions().locale;
41
+ if (resolved.toLowerCase().startsWith('zh'))
42
+ return 'zh';
43
+ }
44
+ catch { /* ignore */ }
45
+ }
46
+ return 'en';
47
+ }
48
+ // Read-type tools: acquiring information without side effects.
49
+ // Used by the anti-hallucination check to detect whether the model has
50
+ // grounded itself in project context before making changes.
51
+ const READ_TOOL_NAMES = new Set(['read_file', 'search_files', 'list_directory']);
52
+ const WRITE_TOOL_NAMES = new Set(['write_file', 'edit_file']);
53
+ // System prompt is kept stable (no dynamic content) to maximise prompt cache hits.
54
+ // For reasoner (R1) models: system prompt is injected into the first user message
55
+ // because R1 API converts system messages internally anyway.
56
+ // DeepSeek-optimized: explicit tool-calling patterns, structured thinking, and
57
+ // clear formatting rules that work well with DeepSeek's instruction-following style.
58
+ function buildSystemPrompt(guide, language) {
59
+ const langInstruction = language === 'zh'
60
+ ? `## Language
61
+ - The user's system language is Chinese (zh). You MUST respond in Chinese (Simplified Chinese, 简体中文) at all times.
62
+ - All explanations, summaries, and conversation with the user should be in Chinese.
63
+ - Code and technical identifiers (variable names, file paths, commands) remain in their original language.`
64
+ : `## Language
65
+ - Respond in English only.`;
66
+ const base = `You are CodeGrunt, an expert AI coding assistant running in the terminal. You are powered by DeepSeek, optimized for software engineering tasks.
67
+
68
+ You have access to tools that let you read files, write files, edit files, run shell commands, list directories, and search code. Use them to complete the user's task.
69
+
70
+ ${langInstruction}
71
+
72
+ ## Core Guidelines
73
+ - Read files before editing them to understand the current content
74
+ - Prefer edit_file over write_file for modifying existing files
75
+ - Run tests after making changes to verify correctness
76
+ - When a task is complete, summarize what you did concisely
77
+
78
+ ## Tool Usage Best Practices
79
+ - Chain tool calls when possible: read search results, then read relevant files, then make edits
80
+ - For search_files: use specific, unique patterns to narrow results
81
+ - For execute_shell: combine commands with && when possible; avoid interactive commands
82
+ - For edit_file: old_string must match exactly including whitespace — copy from read_file output
83
+ - For list_directory: start shallow (depth 1-2) then drill deeper as needed
84
+ - Large tool outputs are truncated — use search or targeted reads when outputs are cut off
85
+
86
+ ## Code Quality
87
+ - Follow existing code conventions in the project
88
+ - Write idiomatic code for the language/framework being used
89
+ - Add minimal, targeted comments for non-obvious logic only
90
+ - Handle errors gracefully in production code
91
+
92
+ ## Anti-Hallucination Rules
93
+ - NEVER invent APIs, functions, types, imports, or dependencies that don't exist in the project. Before using any library or internal API, you MUST read its definition file or find existing usage in the codebase via search_files.
94
+ - When generating new code, you MUST first find and read at least one existing file that demonstrates the pattern, style, and conventions you plan to follow. Copy-adapt is safer than inventing.
95
+ - Every code change must be traceable to something you actually READ during this session — not your training data. If you haven't read a relevant file yet, read it before writing.
96
+ - If you're unsure whether a function/type/import path exists, use search_files or read_file to verify BEFORE writing code that depends on it.
97
+ - For any non-trivial edit, add a brief comment in the code referencing the file(s) that informed your change (e.g., "// Ref: src/utils/billing.ts L23-45" or "// Following pattern from src/cli/commands.ts").`;
98
+ return guide ? base + guide : base;
99
+ }
100
+ function buildFirstUserPrefix(cwd, model, systemPrompt) {
101
+ const parts = [];
102
+ parts.push(`[cwd: ${cwd}]`);
103
+ // For reasoner models: embed system prompt in the first user message
104
+ if (isReasonerModel(model) && systemPrompt) {
105
+ parts.push(`\n[System Instructions]\n${systemPrompt}`);
106
+ }
107
+ return parts.join('\n') + '\n\n';
108
+ }
109
+ export async function runAgentLoop(options) {
110
+ const { task, cwd, config, provider, onText, onToolCall, onToolResult, signal } = options;
111
+ const model = config.model;
112
+ const context = options.context ?? new ContextManager(CHAT_CONTEXT_BUDGET);
113
+ const toolDefs = getToolDefinitions();
114
+ const guide = options.systemPromptOverride ? null : await loadProjectGuide(cwd);
115
+ const lang = detectSystemLanguage();
116
+ // When a skill provides a system prompt override, use it instead of the
117
+ // default coding-assistant identity. This lets skills define completely
118
+ // different roles (e.g. "You are a BaZi fortune-telling master").
119
+ const systemPrompt = options.systemPromptOverride
120
+ ? options.systemPromptOverride
121
+ : (guide ? buildSystemPrompt(guide, lang) : buildSystemPrompt(null, lang));
122
+ const isReasoner = isReasonerModel(model);
123
+ // Only push system prompt once per session (keeps it stable for cache hits).
124
+ // Reasoner models skip system role — prompt goes into first user message.
125
+ if (context.getMessages().length === 0) {
126
+ if (!isReasoner) {
127
+ context.push({ role: 'system', content: systemPrompt });
128
+ }
129
+ }
130
+ // Reset per-turn state
131
+ resetYesAll();
132
+ let hasReadThisTurn = false;
133
+ // Warned-this-turn flag: only inject the anti-hallucination reminder once per
134
+ // turn to avoid spamming context with repeated warnings.
135
+ let warnedBlindWrite = false;
136
+ // Prepend cwd (and system prompt for reasoner) to the first message of each turn
137
+ const isFirstTurn = context.getMessages().length <= (isReasoner ? 0 : 1);
138
+ const userContent = isFirstTurn
139
+ ? buildFirstUserPrefix(cwd, model, isReasoner ? systemPrompt : undefined) + task
140
+ : task;
141
+ context.push({ role: 'user', content: userContent });
142
+ for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {
143
+ if (signal?.aborted)
144
+ break;
145
+ let assistantText = '';
146
+ let reasoningText = '';
147
+ const toolCallAccumulator = new Map();
148
+ let finishReason = null;
149
+ let outputTokens = 0;
150
+ let thinkingStartTime = null;
151
+ // Animated spinner: "⠋ Thinking… (3s · ↑ 42 tokens · iter 2/30)"
152
+ const startTime = Date.now();
153
+ const thinkingSpinner = ora({
154
+ text: chalk.gray('Thinking…'),
155
+ color: 'gray',
156
+ stream: process.stdout,
157
+ });
158
+ const updateThinkingText = () => {
159
+ const elapsed = Math.floor((Date.now() - startTime) / 1000);
160
+ const iterInfo = iteration > 0 ? ` · iter ${iteration + 1}/${MAX_ITERATIONS}` : '';
161
+ thinkingSpinner.text = chalk.gray(`Thinking… (${elapsed}s · ↑ ${outputTokens} tokens${iterInfo} Esc to cancel)`);
162
+ };
163
+ const showThinking = () => {
164
+ if (!thinkingSpinner.isSpinning) {
165
+ thinkingSpinner.start();
166
+ updateThinkingText();
167
+ // Tick every second so the elapsed time updates even between chunks
168
+ const ticker = setInterval(() => {
169
+ if (thinkingSpinner.isSpinning)
170
+ updateThinkingText();
171
+ else
172
+ clearInterval(ticker);
173
+ }, 1000);
174
+ }
175
+ else {
176
+ updateThinkingText();
177
+ }
178
+ };
179
+ const hideThinking = () => {
180
+ if (thinkingSpinner.isSpinning) {
181
+ thinkingSpinner.stop();
182
+ }
183
+ };
184
+ const stream = provider.stream(context.getMessages(), {
185
+ model: config.model,
186
+ maxTokens: config.maxTokens,
187
+ // Reasoner models do not support temperature — omit it
188
+ temperature: isReasoner ? undefined : config.temperature,
189
+ reasoningEffort: isReasoner ? config.reasoningEffort : undefined,
190
+ topP: config.topP,
191
+ frequencyPenalty: config.frequencyPenalty,
192
+ presencePenalty: config.presencePenalty,
193
+ tools: toolDefs,
194
+ signal,
195
+ });
196
+ const md = new MarkdownRenderer();
197
+ // Start spinner immediately so user sees instant feedback while waiting
198
+ // for the first streaming chunk (important for reasoner models which may
199
+ // take 30-60 seconds to emit their first reasoning delta).
200
+ showThinking();
201
+ try {
202
+ for await (const chunk of stream) {
203
+ if (signal?.aborted)
204
+ break;
205
+ if (chunk.type === 'text_delta') {
206
+ hideThinking();
207
+ if (!assistantText) {
208
+ // Print assistant header before first text chunk
209
+ printAssistantHeader();
210
+ }
211
+ assistantText += chunk.text;
212
+ outputTokens += Math.ceil(chunk.text.length / 4);
213
+ onText?.(chunk.text);
214
+ const formatted = md.feed(chunk.text);
215
+ if (formatted)
216
+ process.stdout.write(formatted);
217
+ }
218
+ else if (chunk.type === 'reasoning_delta') {
219
+ if (thinkingStartTime === null)
220
+ thinkingStartTime = Date.now();
221
+ reasoningText += chunk.text;
222
+ outputTokens += Math.ceil(chunk.text.length / 4);
223
+ showThinking();
224
+ }
225
+ else if (chunk.type === 'tool_call_delta') {
226
+ const existing = toolCallAccumulator.get(chunk.index) ?? { id: '', name: '', arguments: '' };
227
+ if (chunk.id)
228
+ existing.id = chunk.id;
229
+ if (chunk.name)
230
+ existing.name = chunk.name;
231
+ existing.arguments += chunk.arguments_delta;
232
+ toolCallAccumulator.set(chunk.index, existing);
233
+ }
234
+ else if (chunk.type === 'finish') {
235
+ hideThinking();
236
+ finishReason = chunk.finish_reason;
237
+ }
238
+ }
239
+ if (signal?.aborted)
240
+ break;
241
+ }
242
+ finally {
243
+ // Always stop the spinner, even on abort/error.
244
+ // Without this, the ora timer keeps writing to stdout and corrupts
245
+ // subsequent terminal output (e.g. the next readMultilineInput panel).
246
+ hideThinking();
247
+ }
248
+ // Flush any remaining markdown buffer
249
+ const flushOut = md.flush();
250
+ if (flushOut)
251
+ process.stdout.write(flushOut);
252
+ // Show collapsed reasoning block after stream completes
253
+ if (reasoningText && thinkingStartTime !== null) {
254
+ const elapsed = Date.now() - thinkingStartTime;
255
+ printThinkingCollapsed(reasoningText, elapsed);
256
+ }
257
+ // Warn if response was truncated due to token limit (especially common with
258
+ // reasoner models whose chain-of-thought consumes most of maxTokens budget).
259
+ if (finishReason === 'length') {
260
+ process.stdout.write('\n');
261
+ if (lang === 'zh') {
262
+ process.stdout.write(chalk.yellow('⚠ 响应被截断(已达 token 上限)。请用 /config maxtokens <数值> 调高上限后重试(建议 32768 或更高)。\n'));
263
+ }
264
+ else {
265
+ process.stdout.write(chalk.yellow('⚠ Response truncated (token limit reached). Increase with /config maxtokens <value> (try 32768 or higher).\n'));
266
+ }
267
+ }
268
+ if (finishReason === 'stop' || (finishReason === 'length' && toolCallAccumulator.size === 0)) {
269
+ if (assistantText) {
270
+ context.push({
271
+ role: 'assistant',
272
+ content: assistantText,
273
+ ...(reasoningText ? { reasoning_content: reasoningText } : {}),
274
+ });
275
+ process.stdout.write('\n');
276
+ }
277
+ break;
278
+ }
279
+ if (finishReason === 'tool_calls') {
280
+ if (assistantText)
281
+ process.stdout.write('\n');
282
+ const toolCalls = Array.from(toolCallAccumulator.entries())
283
+ .sort(([a], [b]) => a - b)
284
+ .map(([, tc]) => ({
285
+ id: tc.id,
286
+ type: 'function',
287
+ function: { name: tc.name, arguments: tc.arguments },
288
+ }));
289
+ context.push({
290
+ role: 'assistant',
291
+ content: null,
292
+ tool_calls: toolCalls,
293
+ ...(reasoningText ? { reasoning_content: reasoningText } : {}),
294
+ });
295
+ // ── Anti-hallucination: detect "blind write" pattern ─────────────────
296
+ // If the model issues write/edit without any read/search/list in the
297
+ // same batch and hasn't read anything this turn, inject a one-time
298
+ // reminder. This catches the most common hallucination vector: jumping
299
+ // straight to generating code without grounding in the codebase.
300
+ const hasWriteInBatch = toolCalls.some(tc => WRITE_TOOL_NAMES.has(tc.function.name));
301
+ const hasReadInBatch = toolCalls.some(tc => READ_TOOL_NAMES.has(tc.function.name));
302
+ if (hasWriteInBatch && !hasReadInBatch && !hasReadThisTurn && !warnedBlindWrite) {
303
+ warnedBlindWrite = true;
304
+ const warning = lang === 'zh'
305
+ ? '⚠️ 检测到直接写入操作:你尚未读取任何项目文件就尝试编辑代码。这极大增加了凭空编造不存在的 API/类型/模式的风险。建议在写入之前先用 read_file 或 search_files 了解现有代码风格和可用的接口。'
306
+ : '⚠️ Blind write detected: you are attempting to edit code without having read any project files first. This greatly increases the risk of inventing non-existent APIs, types, or patterns. Consider using read_file or search_files to ground yourself before writing.';
307
+ context.push({ role: 'user', content: warning });
308
+ }
309
+ for (const tc of toolCalls) {
310
+ let parsedArgs = {};
311
+ try {
312
+ parsedArgs = JSON.parse(tc.function.arguments);
313
+ }
314
+ catch {
315
+ // leave empty
316
+ }
317
+ // Track reads so subsequent writes in the same turn are considered grounded
318
+ if (READ_TOOL_NAMES.has(tc.function.name)) {
319
+ hasReadThisTurn = true;
320
+ }
321
+ onToolCall?.(tc.function.name, parsedArgs);
322
+ printToolCall(tc.function.name, parsedArgs);
323
+ const toolSpinner = ora({
324
+ text: chalk.gray(`Running ${tc.function.name}…`),
325
+ color: 'cyan',
326
+ stream: process.stdout,
327
+ }).start();
328
+ // Stop spinner before executing so confirmation UIs (edit_file, write_file)
329
+ // can take over stdout/raw-mode without the spinner corrupting their output.
330
+ toolSpinner.stop();
331
+ const result = await executeTool(tc.function.name, tc.function.arguments, cwd);
332
+ onToolResult?.(tc.function.name, result);
333
+ printToolResult(tc.function.name, result);
334
+ context.push({
335
+ role: 'tool',
336
+ tool_call_id: tc.id,
337
+ content: result.success ? result.output : (result.error ?? result.output),
338
+ });
339
+ if (result.userRejected) {
340
+ return;
341
+ }
342
+ }
343
+ // continue loop — model will process tool results
344
+ }
345
+ else {
346
+ // length or unknown finish reason — stop
347
+ if (assistantText)
348
+ process.stdout.write('\n');
349
+ break;
350
+ }
351
+ }
352
+ }
353
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../../src/core/agent/loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { Message } from '../../types.js';
2
+ export declare class ContextManager {
3
+ private messages;
4
+ private tokenBudget;
5
+ /**
6
+ * @param tokenBudget Maximum estimated tokens for stored messages.
7
+ * For DeepSeek-V4 (128K context), default ~90K leaves room for output.
8
+ * For R1 reasoner (1M context), can go much higher.
9
+ */
10
+ constructor(tokenBudget?: number);
11
+ push(message: Message): void;
12
+ getMessages(): Message[];
13
+ clear(): void;
14
+ /** Replace messages wholesale (used for cache-warm restart) */
15
+ setMessages(msgs: Message[]): void;
16
+ estimatedTokenCount(): number;
17
+ /** Adjust the token budget dynamically (e.g. when switching models) */
18
+ setTokenBudget(budget: number): void;
19
+ private estimateTokens;
20
+ private trim;
21
+ /**
22
+ * Remove the oldest message group from the conversation, preserving
23
+ * assistant(tool_calls) ↔ tool message pairing required by the LLM API.
24
+ */
25
+ private removeOldestGroup;
26
+ }
@@ -0,0 +1,98 @@
1
+ const CHARS_PER_TOKEN = 4;
2
+ export class ContextManager {
3
+ messages = [];
4
+ tokenBudget;
5
+ /**
6
+ * @param tokenBudget Maximum estimated tokens for stored messages.
7
+ * For DeepSeek-V4 (128K context), default ~90K leaves room for output.
8
+ * For R1 reasoner (1M context), can go much higher.
9
+ */
10
+ constructor(tokenBudget = 90_000) {
11
+ this.tokenBudget = tokenBudget;
12
+ }
13
+ push(message) {
14
+ this.messages.push(message);
15
+ this.trim();
16
+ }
17
+ getMessages() {
18
+ return this.messages;
19
+ }
20
+ clear() {
21
+ this.messages = [];
22
+ }
23
+ /** Replace messages wholesale (used for cache-warm restart) */
24
+ setMessages(msgs) {
25
+ this.messages = msgs;
26
+ this.trim();
27
+ }
28
+ estimatedTokenCount() {
29
+ return this.estimateTokens();
30
+ }
31
+ /** Adjust the token budget dynamically (e.g. when switching models) */
32
+ setTokenBudget(budget) {
33
+ this.tokenBudget = budget;
34
+ this.trim();
35
+ }
36
+ estimateTokens() {
37
+ let total = 0;
38
+ for (const msg of this.messages) {
39
+ if ('content' in msg && msg.content) {
40
+ total += Math.ceil(String(msg.content).length / CHARS_PER_TOKEN);
41
+ }
42
+ // Account for reasoning_content in token count
43
+ if ('reasoning_content' in msg && msg.reasoning_content) {
44
+ total += Math.ceil(String(msg.reasoning_content).length / CHARS_PER_TOKEN);
45
+ }
46
+ // Tool calls consume tokens
47
+ if ('tool_calls' in msg && msg.tool_calls) {
48
+ for (const tc of msg.tool_calls) {
49
+ total += Math.ceil(tc.function.name.length / CHARS_PER_TOKEN);
50
+ total += Math.ceil(tc.function.arguments.length / CHARS_PER_TOKEN);
51
+ }
52
+ }
53
+ }
54
+ return total;
55
+ }
56
+ trim() {
57
+ const hasSystem = this.messages[0]?.role === 'system';
58
+ const startIdx = hasSystem ? 1 : 0;
59
+ // Keep system + at least the last 4 messages (user/assistant/tool pairs)
60
+ const minMessages = hasSystem ? 5 : 4;
61
+ while (this.estimateTokens() > this.tokenBudget && this.messages.length > minMessages) {
62
+ this.removeOldestGroup(startIdx);
63
+ }
64
+ }
65
+ /**
66
+ * Remove the oldest message group from the conversation, preserving
67
+ * assistant(tool_calls) ↔ tool message pairing required by the LLM API.
68
+ */
69
+ removeOldestGroup(startIdx) {
70
+ const msg = this.messages[startIdx];
71
+ if (msg && msg.role === 'assistant' && 'tool_calls' in msg && msg.tool_calls) {
72
+ // This is an assistant message with tool calls — must remove it
73
+ // together with all subsequent tool response messages.
74
+ let removeCount = 1;
75
+ while (startIdx + removeCount < this.messages.length &&
76
+ this.messages[startIdx + removeCount].role === 'tool') {
77
+ removeCount++;
78
+ }
79
+ this.messages.splice(startIdx, removeCount);
80
+ }
81
+ else if (msg && msg.role === 'tool') {
82
+ // Standalone tool message without preceding assistant(tool_calls) —
83
+ // this can happen if the assistant was already removed. Skip it
84
+ // to avoid breaking the stream, and also skip any contiguous tool messages.
85
+ let removeCount = 1;
86
+ while (startIdx + removeCount < this.messages.length &&
87
+ this.messages[startIdx + removeCount].role === 'tool') {
88
+ removeCount++;
89
+ }
90
+ this.messages.splice(startIdx, removeCount);
91
+ }
92
+ else {
93
+ // Plain message (user, assistant without tool_calls, system) — safe to remove
94
+ this.messages.splice(startIdx, 1);
95
+ }
96
+ }
97
+ }
98
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/core/context/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function loadProjectGuide(cwd: string): Promise<string | null>;
@@ -0,0 +1,17 @@
1
+ import { readFile } from 'fs/promises';
2
+ import { join } from 'path';
3
+ // Priority order: CODEGRUNT.md > CLAUDE.md
4
+ const GUIDE_FILES = ['CODEGRUNT.md', 'CLAUDE.md'];
5
+ export async function loadProjectGuide(cwd) {
6
+ for (const filename of GUIDE_FILES) {
7
+ try {
8
+ const content = await readFile(join(cwd, filename), 'utf-8');
9
+ return `\n\n---\n# Project Guide (${filename})\n\n${content.trim()}`;
10
+ }
11
+ catch {
12
+ // not found, try next
13
+ }
14
+ }
15
+ return null;
16
+ }
17
+ //# sourceMappingURL=project-guide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-guide.js","sourceRoot":"","sources":["../../../src/core/context/project-guide.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,2CAA2C;AAC3C,MAAM,WAAW,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,GAAW;IAChD,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;YAC7D,OAAO,6BAA6B,QAAQ,QAAQ,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QACvE,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../../types.js';
2
+ export declare const editFileTool: Tool;
@@ -0,0 +1,54 @@
1
+ import { readFile, writeFile } from 'fs/promises';
2
+ import { resolve } from 'path';
3
+ import { printDiff } from '../../utils/display.js';
4
+ export const editFileTool = {
5
+ definition: {
6
+ type: 'function',
7
+ function: {
8
+ name: 'edit_file',
9
+ description: 'Replace an exact string in a file with new content. The old_string must match exactly (including whitespace). Fails clearly if old_string is not found.',
10
+ parameters: {
11
+ type: 'object',
12
+ properties: {
13
+ path: {
14
+ type: 'string',
15
+ description: 'The path to the file to edit',
16
+ },
17
+ old_string: {
18
+ type: 'string',
19
+ description: 'The exact string to find and replace',
20
+ },
21
+ new_string: {
22
+ type: 'string',
23
+ description: 'The string to replace it with',
24
+ },
25
+ },
26
+ required: ['path', 'old_string', 'new_string'],
27
+ },
28
+ },
29
+ },
30
+ async execute(args) {
31
+ const filePath = resolve(args.path);
32
+ const oldString = args.old_string;
33
+ const newString = args.new_string;
34
+ try {
35
+ const content = await readFile(filePath, 'utf-8');
36
+ if (!content.includes(oldString)) {
37
+ return {
38
+ success: false,
39
+ output: '',
40
+ error: `old_string not found in ${filePath}. The string must match exactly including whitespace and indentation.`,
41
+ };
42
+ }
43
+ const updated = content.replace(oldString, newString);
44
+ await writeFile(filePath, updated, 'utf-8');
45
+ printDiff(filePath, content, updated);
46
+ return { success: true, output: `Edited ${filePath}` };
47
+ }
48
+ catch (err) {
49
+ const message = err instanceof Error ? err.message : String(err);
50
+ return { success: false, output: '', error: `Failed to edit ${filePath}: ${message}` };
51
+ }
52
+ },
53
+ };
54
+ //# sourceMappingURL=edit_file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit_file.js","sourceRoot":"","sources":["../../../src/core/tools/edit_file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,MAAM,CAAC,MAAM,YAAY,GAAS;IAChC,UAAU,EAAE;QACV,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE;YACR,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,yJAAyJ;YACtK,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,IAAI,EAAE;wBACJ,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,8BAA8B;qBAC5C;oBACD,UAAU,EAAE;wBACV,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,sCAAsC;qBACpD;oBACD,UAAU,EAAE;wBACV,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,+BAA+B;qBAC7C;iBACF;gBACD,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,YAAY,CAAC;aAC/C;SACF;KACF;IAED,KAAK,CAAC,OAAO,CAAC,IAAI;QAChB,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,IAAc,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,UAAoB,CAAC;QAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,UAAoB,CAAC;QAE5C,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAElD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBACjC,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,EAAE;oBACV,KAAK,EAAE,2BAA2B,QAAQ,uEAAuE;iBAClH,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YACtD,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAC5C,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YACtC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,QAAQ,EAAE,EAAE,CAAC;QACzD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,kBAAkB,QAAQ,KAAK,OAAO,EAAE,EAAE,CAAC;QACzF,CAAC;IACH,CAAC;CACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../../types.js';
2
+ export declare const executeShellTool: Tool;