@stan-chen/simple-cli 0.2.3 → 0.2.4

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 (136) hide show
  1. package/README.md +62 -63
  2. package/dist/anyllm.py +62 -0
  3. package/dist/builtins.d.ts +726 -0
  4. package/dist/builtins.js +481 -0
  5. package/dist/cli.d.ts +0 -4
  6. package/dist/cli.js +34 -493
  7. package/dist/engine.d.ts +33 -0
  8. package/dist/engine.js +138 -0
  9. package/dist/learnings.d.ts +15 -0
  10. package/dist/learnings.js +54 -0
  11. package/dist/llm.d.ts +18 -0
  12. package/dist/llm.js +66 -0
  13. package/dist/mcp.d.ts +132 -0
  14. package/dist/mcp.js +43 -0
  15. package/dist/skills.d.ts +5 -16
  16. package/dist/skills.js +91 -253
  17. package/dist/tui.d.ts +1 -0
  18. package/dist/tui.js +10 -0
  19. package/package.json +10 -6
  20. package/dist/claw/jit.d.ts +0 -5
  21. package/dist/claw/jit.js +0 -138
  22. package/dist/claw/management.d.ts +0 -3
  23. package/dist/claw/management.js +0 -107
  24. package/dist/commands/add.d.ts +0 -9
  25. package/dist/commands/add.js +0 -50
  26. package/dist/commands/git/commit.d.ts +0 -12
  27. package/dist/commands/git/commit.js +0 -98
  28. package/dist/commands/git/status.d.ts +0 -6
  29. package/dist/commands/git/status.js +0 -42
  30. package/dist/commands/index.d.ts +0 -16
  31. package/dist/commands/index.js +0 -377
  32. package/dist/commands/mcp/status.d.ts +0 -6
  33. package/dist/commands/mcp/status.js +0 -31
  34. package/dist/commands/swarm.d.ts +0 -36
  35. package/dist/commands/swarm.js +0 -236
  36. package/dist/commands.d.ts +0 -32
  37. package/dist/commands.js +0 -427
  38. package/dist/context.d.ts +0 -116
  39. package/dist/context.js +0 -337
  40. package/dist/index.d.ts +0 -6
  41. package/dist/index.js +0 -109
  42. package/dist/lib/agent.d.ts +0 -99
  43. package/dist/lib/agent.js +0 -313
  44. package/dist/lib/editor.d.ts +0 -74
  45. package/dist/lib/editor.js +0 -441
  46. package/dist/lib/git.d.ts +0 -164
  47. package/dist/lib/git.js +0 -356
  48. package/dist/lib/shim.d.ts +0 -4
  49. package/dist/lib/shim.js +0 -30
  50. package/dist/lib/ui.d.ts +0 -159
  51. package/dist/lib/ui.js +0 -277
  52. package/dist/mcp/client.d.ts +0 -22
  53. package/dist/mcp/client.js +0 -81
  54. package/dist/mcp/manager.d.ts +0 -186
  55. package/dist/mcp/manager.js +0 -446
  56. package/dist/prompts/provider.d.ts +0 -22
  57. package/dist/prompts/provider.js +0 -79
  58. package/dist/providers/index.d.ts +0 -31
  59. package/dist/providers/index.js +0 -93
  60. package/dist/providers/multi.d.ts +0 -12
  61. package/dist/providers/multi.js +0 -28
  62. package/dist/registry.d.ts +0 -29
  63. package/dist/registry.js +0 -443
  64. package/dist/repoMap.d.ts +0 -5
  65. package/dist/repoMap.js +0 -79
  66. package/dist/router.d.ts +0 -41
  67. package/dist/router.js +0 -118
  68. package/dist/swarm/coordinator.d.ts +0 -86
  69. package/dist/swarm/coordinator.js +0 -257
  70. package/dist/swarm/index.d.ts +0 -28
  71. package/dist/swarm/index.js +0 -29
  72. package/dist/swarm/task.d.ts +0 -104
  73. package/dist/swarm/task.js +0 -221
  74. package/dist/swarm/types.d.ts +0 -132
  75. package/dist/swarm/types.js +0 -37
  76. package/dist/swarm/worker.d.ts +0 -109
  77. package/dist/swarm/worker.js +0 -369
  78. package/dist/tools/analyzeFile.d.ts +0 -16
  79. package/dist/tools/analyzeFile.js +0 -43
  80. package/dist/tools/analyze_file.d.ts +0 -16
  81. package/dist/tools/analyze_file.js +0 -43
  82. package/dist/tools/clawBrain.d.ts +0 -23
  83. package/dist/tools/clawBrain.js +0 -136
  84. package/dist/tools/claw_brain.d.ts +0 -23
  85. package/dist/tools/claw_brain.js +0 -139
  86. package/dist/tools/deleteFile.d.ts +0 -19
  87. package/dist/tools/deleteFile.js +0 -36
  88. package/dist/tools/delete_file.d.ts +0 -19
  89. package/dist/tools/delete_file.js +0 -36
  90. package/dist/tools/fileOps.d.ts +0 -22
  91. package/dist/tools/fileOps.js +0 -43
  92. package/dist/tools/file_ops.d.ts +0 -22
  93. package/dist/tools/file_ops.js +0 -43
  94. package/dist/tools/git.d.ts +0 -40
  95. package/dist/tools/git.js +0 -236
  96. package/dist/tools/glob.d.ts +0 -34
  97. package/dist/tools/glob.js +0 -165
  98. package/dist/tools/grep.d.ts +0 -53
  99. package/dist/tools/grep.js +0 -296
  100. package/dist/tools/linter.d.ts +0 -35
  101. package/dist/tools/linter.js +0 -407
  102. package/dist/tools/listDir.d.ts +0 -29
  103. package/dist/tools/listDir.js +0 -50
  104. package/dist/tools/list_dir.d.ts +0 -29
  105. package/dist/tools/list_dir.js +0 -50
  106. package/dist/tools/memory.d.ts +0 -34
  107. package/dist/tools/memory.js +0 -215
  108. package/dist/tools/organizer.d.ts +0 -1
  109. package/dist/tools/organizer.js +0 -65
  110. package/dist/tools/readFiles.d.ts +0 -25
  111. package/dist/tools/readFiles.js +0 -31
  112. package/dist/tools/read_files.d.ts +0 -25
  113. package/dist/tools/read_files.js +0 -31
  114. package/dist/tools/reloadTools.d.ts +0 -11
  115. package/dist/tools/reloadTools.js +0 -22
  116. package/dist/tools/reload_tools.d.ts +0 -11
  117. package/dist/tools/reload_tools.js +0 -22
  118. package/dist/tools/runCommand.d.ts +0 -32
  119. package/dist/tools/runCommand.js +0 -79
  120. package/dist/tools/run_command.d.ts +0 -32
  121. package/dist/tools/run_command.js +0 -103
  122. package/dist/tools/scheduler.d.ts +0 -25
  123. package/dist/tools/scheduler.js +0 -65
  124. package/dist/tools/scraper.d.ts +0 -31
  125. package/dist/tools/scraper.js +0 -211
  126. package/dist/tools/writeFiles.d.ts +0 -63
  127. package/dist/tools/writeFiles.js +0 -87
  128. package/dist/tools/write_files.d.ts +0 -84
  129. package/dist/tools/write_files.js +0 -91
  130. package/dist/tools/write_to_file.d.ts +0 -15
  131. package/dist/tools/write_to_file.js +0 -21
  132. package/dist/ui/server.d.ts +0 -5
  133. package/dist/ui/server.js +0 -74
  134. package/dist/watcher.d.ts +0 -35
  135. package/dist/watcher.js +0 -164
  136. /package/{docs/assets → assets}/logo.jpeg +0 -0
package/dist/context.js DELETED
@@ -1,337 +0,0 @@
1
- /**
2
- * Context Manager - Manages conversation context and file state
3
- * Based on Aider's coder.py and GeminiCLI's context management
4
- * Uses gpt-tokenizer for accurate token counting (with fallback)
5
- */
6
- import { readFile } from 'fs/promises';
7
- import { existsSync, readFileSync } from 'fs';
8
- import { relative, resolve } from 'path';
9
- import { generateRepoMap } from './repoMap.js';
10
- import { getActiveSkill } from './skills.js';
11
- import { loadAllTools, getToolDefinitions } from './registry.js';
12
- import { getPromptProvider } from './prompts/provider.js';
13
- // Cached tokenizer (typed as any to handle missing module)
14
- let tokenEncoder = null;
15
- let tokenizerLoaded = false;
16
- /**
17
- * Load tokenizer lazily (handles case where gpt-tokenizer not installed)
18
- */
19
- async function loadTokenizer() {
20
- if (tokenizerLoaded)
21
- return;
22
- tokenizerLoaded = true;
23
- try {
24
- const mod = await import('gpt-tokenizer');
25
- tokenEncoder = mod.encode;
26
- }
27
- catch {
28
- // gpt-tokenizer not installed, will use fallback
29
- }
30
- }
31
- /**
32
- * Count tokens using gpt-tokenizer (accurate for GPT models)
33
- * Falls back to rough estimation if not available
34
- */
35
- async function countTokensAsync(text) {
36
- await loadTokenizer();
37
- if (tokenEncoder) {
38
- try {
39
- return tokenEncoder(text).length;
40
- }
41
- catch {
42
- // Fall through to estimation
43
- }
44
- }
45
- // Fallback: ~4 chars per token (rough but reasonable)
46
- return Math.ceil(text.length / 4);
47
- }
48
- /**
49
- * Synchronous token count (uses cached encoder or estimation)
50
- */
51
- function countTokens(text) {
52
- if (tokenEncoder) {
53
- try {
54
- return tokenEncoder(text).length;
55
- }
56
- catch {
57
- // Fall through
58
- }
59
- }
60
- return Math.ceil(text.length / 4);
61
- }
62
- /**
63
- * ContextManager class
64
- * Manages the conversation context, file state, and system prompts
65
- */
66
- export class ContextManager {
67
- cwd;
68
- activeFiles = new Set();
69
- readOnlyFiles = new Set();
70
- history = [];
71
- skill;
72
- tools = new Map();
73
- repoMapCache = '';
74
- repoMapTimestamp = 0;
75
- constructor(cwd) {
76
- this.cwd = cwd || process.cwd();
77
- this.skill = getActiveSkill();
78
- }
79
- /**
80
- * Initialize the context manager
81
- */
82
- async initialize() {
83
- // Load tools
84
- this.tools = await loadAllTools();
85
- // Generate initial repo map
86
- await this.refreshRepoMap();
87
- }
88
- /**
89
- * Add a file to active context
90
- */
91
- addFile(path, readOnly = false) {
92
- const fullPath = resolve(this.cwd, path);
93
- if (!existsSync(fullPath)) {
94
- return false;
95
- }
96
- if (readOnly) {
97
- this.readOnlyFiles.add(fullPath);
98
- this.activeFiles.delete(fullPath);
99
- }
100
- else {
101
- this.activeFiles.add(fullPath);
102
- this.readOnlyFiles.delete(fullPath);
103
- }
104
- return true;
105
- }
106
- /**
107
- * Remove a file from context
108
- */
109
- removeFile(path) {
110
- const fullPath = resolve(this.cwd, path);
111
- const wasActive = this.activeFiles.delete(fullPath);
112
- const wasReadOnly = this.readOnlyFiles.delete(fullPath);
113
- return wasActive || wasReadOnly;
114
- }
115
- /**
116
- * Add a message to history
117
- */
118
- addMessage(role, content) {
119
- this.history.push({
120
- role,
121
- content,
122
- timestamp: Date.now(),
123
- });
124
- }
125
- /**
126
- * Clear conversation history
127
- */
128
- clearHistory() {
129
- this.history = [];
130
- }
131
- /**
132
- * Get all files in context
133
- */
134
- getFiles() {
135
- return {
136
- active: Array.from(this.activeFiles).map(f => relative(this.cwd, f)),
137
- readOnly: Array.from(this.readOnlyFiles).map(f => relative(this.cwd, f)),
138
- };
139
- }
140
- /**
141
- * Read all files in context
142
- */
143
- async getFileContents() {
144
- const contents = new Map();
145
- for (const file of [...this.activeFiles, ...this.readOnlyFiles]) {
146
- try {
147
- const content = await readFile(file, 'utf-8');
148
- const relPath = relative(this.cwd, file);
149
- contents.set(relPath, content);
150
- }
151
- catch {
152
- // Skip files that can't be read
153
- }
154
- }
155
- return contents;
156
- }
157
- /**
158
- * Set the active skill
159
- */
160
- setSkill(skill) {
161
- this.skill = skill;
162
- }
163
- /**
164
- * Get the current skill
165
- */
166
- getSkill() {
167
- return this.skill;
168
- }
169
- /**
170
- * Refresh the repository map
171
- */
172
- async refreshRepoMap() {
173
- const now = Date.now();
174
- // Cache for 30 seconds
175
- if (this.repoMapCache && now - this.repoMapTimestamp < 30000) {
176
- return this.repoMapCache;
177
- }
178
- this.repoMapCache = await generateRepoMap(this.cwd);
179
- this.repoMapTimestamp = now;
180
- return this.repoMapCache;
181
- }
182
- /**
183
- * Build the system prompt
184
- */
185
- async buildSystemPrompt() {
186
- const provider = getPromptProvider();
187
- const systemPrompt = await provider.getSystemPrompt({
188
- cwd: this.cwd,
189
- skillPrompt: this.skill.systemPrompt
190
- });
191
- const parts = [systemPrompt];
192
- // Tool definitions
193
- const toolDefs = getToolDefinitions(this.tools);
194
- parts.push('\n## Available Tools\n' + toolDefs);
195
- // Active files
196
- const files = this.getFiles();
197
- if (files.active.length > 0 || files.readOnly.length > 0) {
198
- parts.push('\n## Context Files');
199
- if (files.active.length > 0) {
200
- parts.push('\nEditable files:');
201
- parts.push(files.active.map(f => `- ${f}`).join('\n'));
202
- }
203
- if (files.readOnly.length > 0) {
204
- parts.push('\nRead-only files:');
205
- parts.push(files.readOnly.map(f => `- ${f}`).join('\n'));
206
- }
207
- }
208
- // Repository map (condensed)
209
- const repoMap = await this.refreshRepoMap();
210
- if (repoMap) {
211
- const condensed = repoMap.split('\n').slice(0, 50).join('\n');
212
- parts.push('\n## Repository Structure\n' + condensed);
213
- if (repoMap.split('\n').length > 50) {
214
- parts.push('... (truncated)');
215
- }
216
- }
217
- // CLAW MODE: Inject JIT Agent Persona
218
- const agentFile = resolve(this.cwd, '.simple', 'workdir', 'AGENT.md');
219
- if ((process.argv.includes('--claw') || process.argv.includes('-claw')) && existsSync(agentFile)) {
220
- try {
221
- const agentPersona = readFileSync(agentFile, 'utf-8');
222
- parts.push('\n\n' + agentPersona);
223
- }
224
- catch { /* ignore read errors */ }
225
- }
226
- return parts.join('\n');
227
- }
228
- /**
229
- * Build messages for LLM
230
- */
231
- async buildMessages(userMessage) {
232
- const messages = [];
233
- // System prompt
234
- const systemPrompt = await this.buildSystemPrompt();
235
- messages.push({ role: 'system', content: systemPrompt });
236
- // File contents as context
237
- const fileContents = await this.getFileContents();
238
- if (fileContents.size > 0) {
239
- let fileContext = '## File Contents\n\n';
240
- for (const [path, content] of fileContents) {
241
- const truncated = content.length > 10000
242
- ? content.slice(0, 10000) + '\n... (truncated)'
243
- : content;
244
- fileContext += `### ${path}\n\`\`\`\n${truncated}\n\`\`\`\n\n`;
245
- }
246
- messages.push({ role: 'user', content: fileContext });
247
- messages.push({ role: 'assistant', content: 'I have read the files. How can I help?' });
248
- }
249
- // Conversation history
250
- for (const msg of this.history) {
251
- messages.push({ role: msg.role, content: msg.content });
252
- }
253
- // Current message with format reminder for JSON mode
254
- const formatReminder = '\n\nCRITICAL: Respond with ONLY a JSON object. NO conversational text. No markdown wrappers. Use this format: {"thought": "...", "tool": "tool_name", "args": {...}}';
255
- messages.push({ role: 'user', content: userMessage + formatReminder });
256
- return messages;
257
- }
258
- /**
259
- * Estimate token count using accurate tokenizer
260
- */
261
- async estimateTokenCount() {
262
- // Ensure tokenizer is loaded
263
- await loadTokenizer();
264
- let total = 0;
265
- // System prompt
266
- const systemPrompt = await this.buildSystemPrompt();
267
- total += countTokens(systemPrompt);
268
- // File contents
269
- const fileContents = await this.getFileContents();
270
- for (const content of fileContents.values()) {
271
- total += countTokens(content);
272
- }
273
- // History
274
- for (const msg of this.history) {
275
- total += countTokens(msg.content);
276
- }
277
- // Add overhead for message formatting (~4 tokens per message)
278
- total += (this.history.length + 2) * 4;
279
- return total;
280
- }
281
- /**
282
- * Get current state
283
- */
284
- getState() {
285
- return {
286
- cwd: this.cwd,
287
- activeFiles: this.activeFiles,
288
- readOnlyFiles: this.readOnlyFiles,
289
- history: this.history,
290
- skill: this.skill,
291
- tokenEstimate: 0, // Calculated async
292
- };
293
- }
294
- /**
295
- * Restore state
296
- */
297
- restoreState(state) {
298
- if (state.cwd)
299
- this.cwd = state.cwd;
300
- if (state.activeFiles)
301
- this.activeFiles = state.activeFiles;
302
- if (state.readOnlyFiles)
303
- this.readOnlyFiles = state.readOnlyFiles;
304
- if (state.history)
305
- this.history = state.history;
306
- if (state.skill)
307
- this.skill = state.skill;
308
- }
309
- /**
310
- * Get conversation history
311
- */
312
- getHistory() {
313
- return [...this.history];
314
- }
315
- /**
316
- * Get tools
317
- */
318
- getTools() {
319
- return this.tools;
320
- }
321
- /**
322
- * Get working directory
323
- */
324
- getCwd() {
325
- return this.cwd;
326
- }
327
- }
328
- // Create a global context manager instance
329
- let globalContext = null;
330
- export function getContextManager(cwd) {
331
- if (!globalContext) {
332
- globalContext = new ContextManager(cwd);
333
- }
334
- return globalContext;
335
- }
336
- // Export token counting utility for use elsewhere
337
- export { countTokens };
package/dist/index.d.ts DELETED
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Simple-CLI Orchestrator - Core loop: Observe -> Plan -> Verify -> Act -> Reflect
4
- * Must remain under 150 lines. Supports MoE routing with --moe flag.
5
- */
6
- import 'dotenv/config';
package/dist/index.js DELETED
@@ -1,109 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Simple-CLI Orchestrator - Core loop: Observe -> Plan -> Verify -> Act -> Reflect
4
- * Must remain under 150 lines. Supports MoE routing with --moe flag.
5
- */
6
- import 'dotenv/config';
7
- import * as readline from 'readline';
8
- import { generateRepoMap } from './repoMap.js';
9
- import { loadTools } from './registry.js';
10
- import { createProvider } from './providers/index.js';
11
- import { createMultiProvider } from './providers/multi.js';
12
- import { routeTask, loadTierConfig, formatRoutingDecision } from './router.js';
13
- import { getPromptProvider } from './prompts/provider.js';
14
- const YOLO_MODE = process.argv.includes('--yolo');
15
- const MOE_MODE = process.argv.includes('--moe');
16
- let tools;
17
- let history = [];
18
- const buildPrompt = async () => {
19
- const repoMap = await generateRepoMap();
20
- const toolDefs = Array.from(tools.values()).map(t => `- ${t.name}: ${t.description}`).join('\n');
21
- const provider = getPromptProvider();
22
- const systemPrompt = await provider.getSystemPrompt({ cwd: process.cwd() });
23
- return `${systemPrompt}
24
- ## Context\n${repoMap}
25
- ## Tools\n${toolDefs}
26
- ## Format: <thought>reasoning</thought> then {"tool": "name", "args": {}} or {"tool": "none", "message": "..."}`;
27
- };
28
- import { jsonrepair } from 'jsonrepair';
29
- const parseResponse = (r) => {
30
- const thought = r.match(/<thought>([\s\S]*?)<\/thought>/)?.[1]?.trim() || '';
31
- const jsonMatch = r.match(/\{[\s\S]*"tool"[\s\S]*\}/);
32
- let action = { tool: 'none', message: 'No action', args: {} };
33
- if (jsonMatch) {
34
- try {
35
- const repaired = jsonrepair(jsonMatch[0]);
36
- action = JSON.parse(repaired);
37
- }
38
- catch { /* use default */ }
39
- }
40
- return { thought, action };
41
- };
42
- const confirm = async (tool, args) => {
43
- if (YOLO_MODE)
44
- return true;
45
- const t = tools.get(tool);
46
- if (!t || t.permission === 'read')
47
- return !!t;
48
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
49
- return new Promise(res => {
50
- rl.question(`[CONFIRM] ${tool}(${JSON.stringify(args)})? (y/n) `, a => { rl.close(); res(a.toLowerCase() === 'y'); });
51
- });
52
- };
53
- const execTool = async (name, args) => {
54
- const t = tools.get(name);
55
- if (!t)
56
- return `Error: Tool "${name}" not found`;
57
- try {
58
- const r = await t.execute(args);
59
- return typeof r === 'string' ? r : JSON.stringify(r, null, 2);
60
- }
61
- catch (e) {
62
- return `Error: ${e instanceof Error ? e.message : e}`;
63
- }
64
- };
65
- const main = async () => {
66
- console.log(`Simple-CLI v0.1.0 ${MOE_MODE ? '[MoE]' : ''} ${YOLO_MODE ? '[YOLO]' : '[Safe]'}`);
67
- tools = await loadTools();
68
- const systemPrompt = await buildPrompt();
69
- const tierConfigs = MOE_MODE ? loadTierConfig() : null;
70
- const multiProvider = tierConfigs ? createMultiProvider(tierConfigs) : null;
71
- const singleProvider = !MOE_MODE ? createProvider() : null;
72
- const generate = async (input) => {
73
- if (MOE_MODE && multiProvider && tierConfigs) {
74
- const routing = await routeTask(input, (p) => multiProvider.generateWithTier(1, p, [{ role: 'user', content: input }]));
75
- console.log(formatRoutingDecision(routing, tierConfigs));
76
- return multiProvider.generateWithTier(routing.tier, systemPrompt, history);
77
- }
78
- return singleProvider.generateResponse(systemPrompt, history);
79
- };
80
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
81
- const prompt = () => {
82
- rl.question('\n> ', async (input) => {
83
- if (input.toLowerCase() === 'exit') {
84
- rl.close();
85
- return;
86
- }
87
- history.push({ role: 'user', content: input });
88
- const response = await generate(input);
89
- const { thought, action } = parseResponse(response);
90
- console.log(`\n[Thought] ${thought}`);
91
- if (action.tool !== 'none') {
92
- if (await confirm(action.tool, action.args || {})) {
93
- const result = await execTool(action.tool, action.args || {});
94
- console.log(`[Result] ${result}`);
95
- history.push({ role: 'assistant', content: response }, { role: 'user', content: `Tool result: ${result}` });
96
- }
97
- else
98
- console.log('[Skipped]');
99
- }
100
- else {
101
- console.log(`[Response] ${action.message}`);
102
- history.push({ role: 'assistant', content: response });
103
- }
104
- prompt();
105
- });
106
- };
107
- prompt();
108
- };
109
- main().catch(console.error);
@@ -1,99 +0,0 @@
1
- /**
2
- * Agent Core - Main agent loop with reflection and retry
3
- * Implements Aider-style reasoning and error recovery
4
- */
5
- import { Message } from '../context.js';
6
- import { EditBlock, EditResult } from './editor.js';
7
- import { GitManager } from './git.js';
8
- import type { TypeLLMResponse } from '@stan-chen/typellm';
9
- export interface AgentConfig {
10
- maxReflections: number;
11
- autoLint: boolean;
12
- autoTest: boolean;
13
- autoCommit: boolean;
14
- testCommand?: string;
15
- lintCommand?: string;
16
- }
17
- export interface ToolCall {
18
- tool: string;
19
- args: Record<string, unknown>;
20
- }
21
- export interface AgentResponse {
22
- thought?: string;
23
- action: ToolCall | {
24
- tool: 'none';
25
- message: string;
26
- };
27
- editBlocks?: EditBlock[];
28
- }
29
- export interface ReflectionContext {
30
- attempt: number;
31
- previousError: string;
32
- previousResponse: string;
33
- failedEdits: EditResult[];
34
- }
35
- /**
36
- * Parse LLM response into structured format
37
- */
38
- export declare function parseResponse(response: TypeLLMResponse | string): AgentResponse;
39
- /**
40
- * Build reflection prompt for retry
41
- */
42
- export declare function buildReflectionPrompt(context: ReflectionContext): string;
43
- /**
44
- * Build lint error prompt
45
- */
46
- export declare function buildLintErrorPrompt(file: string, errors: string): string;
47
- /**
48
- * Build test failure prompt
49
- */
50
- export declare function buildTestFailurePrompt(output: string): string;
51
- /**
52
- * Agent class - Main orchestration logic
53
- */
54
- export declare class Agent {
55
- private config;
56
- private git;
57
- private generateFn;
58
- private executeTool;
59
- private lintFn?;
60
- private testFn?;
61
- constructor(options: {
62
- config: AgentConfig;
63
- git: GitManager;
64
- generateFn: (messages: Message[]) => Promise<TypeLLMResponse>;
65
- executeTool: (name: string, args: Record<string, unknown>) => Promise<unknown>;
66
- lintFn?: (file: string) => Promise<{
67
- passed: boolean;
68
- output: string;
69
- }>;
70
- testFn?: () => Promise<{
71
- passed: boolean;
72
- output: string;
73
- }>;
74
- });
75
- /**
76
- * Process a user message with reflection loop
77
- */
78
- process(userMessage: string, history: Message[], systemPrompt: string): Promise<{
79
- response: AgentResponse;
80
- editResults: EditResult[];
81
- lintResults: Array<{
82
- file: string;
83
- passed: boolean;
84
- output: string;
85
- }>;
86
- testResult?: {
87
- passed: boolean;
88
- output: string;
89
- };
90
- commitResult?: {
91
- hash: string;
92
- message: string;
93
- };
94
- }>;
95
- }
96
- /**
97
- * Summarize conversation history to reduce tokens
98
- */
99
- export declare function summarizeHistory(history: Message[], generateFn: (messages: Message[]) => Promise<TypeLLMResponse>, maxMessages?: number): Promise<Message[]>;