thatgfsj-code 0.2.1 → 0.2.2

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 (64) hide show
  1. package/CHANGELOG.md +131 -0
  2. package/DEVELOPMENT.md +286 -0
  3. package/README.md +131 -30
  4. package/dist/core/ai-engine.d.ts +17 -0
  5. package/dist/core/ai-engine.d.ts.map +1 -1
  6. package/dist/core/ai-engine.js +23 -7
  7. package/dist/core/ai-engine.js.map +1 -1
  8. package/dist/index.js +18 -27
  9. package/dist/index.js.map +1 -1
  10. package/dist/repl/input.d.ts +8 -0
  11. package/dist/repl/input.d.ts.map +1 -1
  12. package/dist/repl/input.js +12 -0
  13. package/dist/repl/input.js.map +1 -1
  14. package/dist/repl/loop.d.ts +56 -0
  15. package/dist/repl/loop.d.ts.map +1 -1
  16. package/dist/repl/loop.js +333 -4
  17. package/dist/repl/loop.js.map +1 -1
  18. package/dist/repl/output.d.ts.map +1 -1
  19. package/dist/repl/output.js +3 -1
  20. package/dist/repl/output.js.map +1 -1
  21. package/dist/repl/welcome.js +1 -1
  22. package/dist/repl/welcome.js.map +1 -1
  23. package/docs/API_KEY_GUIDE.md +6 -0
  24. package/docs/FAQ.md +25 -3
  25. package/package.json +35 -3
  26. package/.patches/0001-fix-repl-replace-readline-with-inquirer-input-for-ke.patch +0 -279
  27. package/.patches/0002-fix-repl-stream-AI-output-directly-to-stdout-so-term.patch +0 -564
  28. package/.patches/0003-fix-session-break-the-hallucination-loop-in-assistan.patch +0 -194
  29. package/.patches/0004-chore-release-bump-version-to-0.2.1.patch +0 -24
  30. package/ROADMAP.md +0 -107
  31. package/src/agent/core.ts +0 -179
  32. package/src/agent/index.ts +0 -8
  33. package/src/agent/intent.ts +0 -181
  34. package/src/agent/streaming.ts +0 -132
  35. package/src/core/ai-engine.ts +0 -437
  36. package/src/core/cli.ts +0 -171
  37. package/src/core/config.ts +0 -147
  38. package/src/core/context-compactor.ts +0 -245
  39. package/src/core/hooks.ts +0 -196
  40. package/src/core/permissions.ts +0 -308
  41. package/src/core/session.ts +0 -165
  42. package/src/core/skills.ts +0 -208
  43. package/src/core/state.ts +0 -120
  44. package/src/core/subagent.ts +0 -195
  45. package/src/core/system-prompt.ts +0 -163
  46. package/src/core/tool-registry.ts +0 -157
  47. package/src/core/types.ts +0 -280
  48. package/src/index.ts +0 -544
  49. package/src/mcp/client.ts +0 -330
  50. package/src/repl/index.ts +0 -8
  51. package/src/repl/input.ts +0 -139
  52. package/src/repl/loop.ts +0 -280
  53. package/src/repl/output.ts +0 -222
  54. package/src/repl/welcome.ts +0 -296
  55. package/src/tools/file.ts +0 -117
  56. package/src/tools/git.ts +0 -132
  57. package/src/tools/index.ts +0 -48
  58. package/src/tools/search.ts +0 -263
  59. package/src/tools/shell.ts +0 -181
  60. package/src/utils/diff-preview.ts +0 -202
  61. package/src/utils/index.ts +0 -8
  62. package/src/utils/memory.ts +0 -223
  63. package/src/utils/project-context.ts +0 -207
  64. package/tsconfig.json +0 -19
@@ -1,194 +0,0 @@
1
- From 85a3542565751fa08120fa6189454788ee643ad7 Mon Sep 17 00:00:00 2001
2
- From: Thatgfsj <thatgfsj@users.noreply.github.com>
3
- Date: Mon, 6 Jul 2026 02:33:48 +0800
4
- Subject: [PATCH 3/4] =?UTF-8?q?fix(session):=20break=20the=20'[=E5=B7=B2?=
5
- =?UTF-8?q?=E4=B8=AD=E6=96=AD]'=20hallucination=20loop=20in=20assistant=20?=
6
- =?UTF-8?q?history?=
7
- MIME-Version: 1.0
8
- Content-Type: text/plain; charset=UTF-8
9
- Content-Transfer-Encoding: 8bit
10
-
11
- When a tool/shell call retry produced literal text '[已中断' in the
12
- assistant output, that string was added back into the session history
13
- and re-fed to the LLM next turn. The LLM then interpreted the literal
14
- as 'I was interrupted', rewrote the same paragraph, and the cycle
15
- repeated indefinitely.
16
-
17
- SessionManager.addMessage now drops messages whose content matches the
18
- pollution patterns (literal [已中断/已中断 marker, isolated think blocks,
19
- etc.), and getMessages() collapses adjacent identical assistant
20
- messages. REPLLoop surfaces a warning when a message was dropped so the
21
- user knows to rephrase.
22
-
23
- Closes the 'AI keeps saying interrupted' bug reported by the user.
24
- ---
25
- src/core/session.ts | 102 +++++++++++++++++++++++++++++++++++++++-----
26
- 1 file changed, 92 insertions(+), 10 deletions(-)
27
-
28
- diff --git a/src/core/session.ts b/src/core/session.ts
29
- index cfd53d9..fd5804b 100644
30
- --- a/src/core/session.ts
31
- +++ b/src/core/session.ts
32
- @@ -1,13 +1,51 @@
33
- /**
34
- * Session Manager - Manages conversation history
35
- + *
36
- + * F4 (anti-[已中断]):
37
- + * - addMessage 拦截含"已中断" / 链形 think 块等污染字符串
38
- + * (之前 AI 在失败重试时会把这些字面写进 history 造成病毒循环)
39
- + * - sanitize() 在 lastMessages 输出到 LLM 前再做一次去噪
40
- */
41
-
42
- import { ChatMessage, Session } from './types.js';
43
-
44
- +/**
45
- + * Patterns that indicate the message is polluted by a previous broken
46
- + * tool/stream retry loop. These should never be re-sent to the LLM.
47
- + */
48
- +const POLLUTION_PATTERNS: RegExp[] = [
49
- + /\[已中断/, // literally "[已中断" - sentinel from bad run
50
- + /\u5df2\u4e2d\u65ad/, // 已中断 (escaped form)
51
- + /^\s*\[已中断\s*$/m, // line that is exactly [已中断
52
- + /^<think>[\s\S]*?<\/think>\s*$/m, // entire message that is just a think block
53
- + /\u{1F6AB}/u, // ⛔ emoji sometimes used as interrupt marker
54
- +];
55
- +
56
- +function looksPolluted(content: string): boolean {
57
- + if (!content) return false;
58
- + // Strip obvious thinking fences and check the *remaining* core content.
59
- + const stripped = content
60
- + .replace(/<think>[\s\S]*?<\/think>/g, '')
61
- + .replace(/<\/?think>/g, '')
62
- + .trim();
63
- +
64
- + for (const p of POLLUTION_PATTERNS) {
65
- + if (p.test(content)) return true;
66
- + }
67
- +
68
- + // A message whose entire stripped form is shorter than 6 chars AND
69
- + // contains an interruption-related token is also suspect.
70
- + if (stripped.length < 6 && /(中断|interrupted|cancelled|已取消)/i.test(stripped)) {
71
- + return true;
72
- + }
73
- + return false;
74
- +}
75
- +
76
- export class SessionManager {
77
- private messages: ChatMessage[] = [];
78
- private sessionId: string;
79
- private createdAt: Date;
80
- + private droppedCount = 0;
81
-
82
- constructor() {
83
- this.sessionId = this.generateId();
84
- @@ -15,25 +53,72 @@ export class SessionManager {
85
- }
86
-
87
- /**
88
- - * Add a message to the session
89
- + * Add a message to the session.
90
- + * Returns true if accepted, false if dropped because it looked polluted.
91
- */
92
- - addMessage(role: ChatMessage['role'], content: string): void {
93
- + addMessage(role: ChatMessage['role'], content: string): boolean {
94
- + if (role !== 'system' && looksPolluted(content)) {
95
- + this.droppedCount++;
96
- + // Keep a 1-line internal note so the user can see *something* happened,
97
- + // but the original polluted text does NOT go to the LLM context.
98
- + this.messages.push({
99
- + role: 'user',
100
- + content: '[system: dropped a polluted prior message containing "已中断" markers. Continue with the original task.]',
101
- + name: 'system'
102
- + });
103
- + return false;
104
- + }
105
- +
106
- this.messages.push({
107
- role,
108
- content,
109
- name: role === 'user' ? 'user' : undefined
110
- });
111
- + return true;
112
- }
113
-
114
- /**
115
- - * Get all messages
116
- + * Add a message WITHOUT any sanitization (for trusted callers, e.g. system prompt)
117
- + */
118
- + addMessageRaw(role: ChatMessage['role'], content: string): void {
119
- + this.messages.push({ role, content });
120
- + }
121
- +
122
- + /**
123
- + * How many polluted messages have we filtered out? Useful for debugging
124
- + * the "AI keeps saying interrupted" loop.
125
- + */
126
- + getDroppedCount(): number {
127
- + return this.droppedCount;
128
- + }
129
- +
130
- + /**
131
- + * Return messages ready to send to the LLM. We additionally dedupe
132
- + * adjacent identical assistant messages (a recovery hack against the
133
- + * "AI repeats the same paragraph each turn" loop).
134
- */
135
- getMessages(): ChatMessage[] {
136
- - return [...this.messages];
137
- + const out: ChatMessage[] = [];
138
- + for (let i = 0; i < this.messages.length; i++) {
139
- + const m = this.messages[i];
140
- + const prev = out[out.length - 1];
141
- + if (
142
- + prev &&
143
- + m.role === 'assistant' &&
144
- + prev.role === 'assistant' &&
145
- + m.content.length > 0 &&
146
- + m.content === prev.content
147
- + ) {
148
- + // collapse identical neighbour
149
- + continue;
150
- + }
151
- + out.push(m);
152
- + }
153
- + return out;
154
- }
155
-
156
- /**
157
- - * Get message count
158
- + * Get message count (raw, includes internal notes)
159
- */
160
- getMessageCount(): number {
161
- return this.messages.length;
162
- @@ -44,6 +129,7 @@ export class SessionManager {
163
- */
164
- clear(): void {
165
- this.messages = [];
166
- + this.droppedCount = 0;
167
- }
168
-
169
- /**
170
- @@ -63,10 +149,9 @@ export class SessionManager {
171
- */
172
- truncate(maxMessages: number = 20): void {
173
- if (this.messages.length > maxMessages) {
174
- - // Keep system message if exists
175
- const systemMsg = this.messages.find(m => m.role === 'system');
176
- const otherMsgs = this.messages.filter(m => m.role !== 'system');
177
- -
178
- +
179
- this.messages = [
180
- ...(systemMsg ? [systemMsg] : []),
181
- ...otherMsgs.slice(-(maxMessages - 1))
182
- @@ -74,9 +159,6 @@ export class SessionManager {
183
- }
184
- }
185
-
186
- - /**
187
- - * Generate unique session ID
188
- - */
189
- private generateId(): string {
190
- return `session_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
191
- }
192
- --
193
- 2.45.2.windows.1
194
-
@@ -1,24 +0,0 @@
1
- From 84b72cd73990da198d3fd7a72b5f53ec0dee40f6 Mon Sep 17 00:00:00 2001
2
- From: Thatgfsj <thatgfsj@users.noreply.github.com>
3
- Date: Mon, 6 Jul 2026 02:33:52 +0800
4
- Subject: [PATCH 4/4] chore(release): bump version to 0.2.1
5
-
6
- ---
7
- package.json | 2 +-
8
- 1 file changed, 1 insertion(+), 1 deletion(-)
9
-
10
- diff --git a/package.json b/package.json
11
- index be6bc8d..b09a74a 100644
12
- --- a/package.json
13
- +++ b/package.json
14
- @@ -1,6 +1,6 @@
15
- {
16
- "name": "thatgfsj-code",
17
- - "version": "0.2.0",
18
- + "version": "0.2.1",
19
- "description": "Thatgfsj Code - Your AI Coding Assistant",
20
- "main": "dist/index.js",
21
- "type": "module",
22
- --
23
- 2.45.2.windows.1
24
-
package/ROADMAP.md DELETED
@@ -1,107 +0,0 @@
1
- # Thatgfsj Code - Development Roadmap
2
-
3
- ## ✅ 全部阶段已完成
4
-
5
- ---
6
-
7
- ## 阶段总结
8
-
9
- ### ✅ 第一阶段: REPL 优化
10
- - [x] 彩色 UI (Banner, 分隔线)
11
- - [x] 命令提示符
12
- - [x] Ctrl+C 中断
13
- - [x] 内置命令 (exit, clear, context, help, tools)
14
- - [x] 项目信息显示
15
- - [x] 流式 Spinner
16
- - [x] 多行输入检测
17
- - [x] 历史记录
18
-
19
- ### ✅ 第二阶段: 工具框架
20
- - [x] Git 工具 (status, log, diff, commit, branch, checkout, pull, push)
21
- - [x] 代码搜索工具 (grep, find, tree, files)
22
-
23
- ### ✅ 第三阶段: LLM 集成
24
- - [x] 意图识别 (chat/code/command/query/complex)
25
- - [x] 任务拆解
26
- - [x] Streaming 输出
27
- - [x] Ollama 本地模型支持
28
-
29
- ### ✅ 第四阶段: 安全 + UX
30
- - [x] Diff 预览
31
- - [x] 项目感知 (自动读取 package.json, .gitignore)
32
- - [x] 记忆机制 (会话修改历史)
33
- - [x] 危险命令确认
34
-
35
- ---
36
-
37
- ## 最终文件结构
38
-
39
- ```
40
- src/
41
- ├── index.ts # CLI 入口
42
- ├── repl/ # 交互式 REPL
43
- │ ├── input.ts
44
- │ ├── output.ts
45
- │ └── loop.ts
46
- ├── agent/ # Agent 核心
47
- │ ├── core.ts
48
- │ ├── intent.ts
49
- │ └── streaming.ts
50
- ├── tools/ # 工具
51
- │ ├── file.ts
52
- │ ├── shell.ts
53
- │ ├── git.ts
54
- │ ├── search.ts
55
- │ └── index.ts
56
- ├── utils/ # 工具函数
57
- │ ├── diff-preview.ts
58
- │ ├── project-context.ts
59
- │ └── memory.ts
60
- └── core/ # 核心模块
61
- ├── ai-engine.ts
62
- ├── config.ts
63
- ├── session.ts
64
- ├── tool-registry.ts
65
- └── types.ts
66
- ```
67
-
68
- ---
69
-
70
- ## 使用方法
71
-
72
- ```bash
73
- # 交互模式
74
- gfcode
75
-
76
- # 单命令
77
- gfcode "创建文件 hello.js"
78
-
79
- # 指定模型
80
- gfcode -m Pro/moonshotai/Kimi-K2.5 "你的任务"
81
-
82
- # 使用 Ollama
83
- $env:PROVIDER="ollama"
84
- $env:MODEL="llama2"
85
- gfcode "你好"
86
- ```
87
-
88
- ---
89
-
90
- ## 可用工具
91
-
92
- | 工具 | 功能 |
93
- |------|------|
94
- | `file` | 读取/写入/删除文件 |
95
- | `shell` | 执行 Shell 命令 |
96
- | `git` | Git 操作 |
97
- | `search` | 代码搜索 |
98
-
99
- ## 可用提供商
100
-
101
- | Provider | 说明 |
102
- |----------|------|
103
- | siliconflow | 硅基流动 (默认) |
104
- | minimax | MiniMax |
105
- | openai | OpenAI |
106
- | anthropic | Anthropic |
107
- | ollama | 本地模型 |
package/src/agent/core.ts DELETED
@@ -1,179 +0,0 @@
1
- /**
2
- * Agent Module
3
- * Core agent logic with intent recognition, task planning, and streaming
4
- */
5
-
6
- import { AIEngine } from '../core/ai-engine.js';
7
- import { SessionManager } from '../core/session.js';
8
- import { IntentRecognizer, Intent, SubTask } from './intent.js';
9
- import { StreamingOutput } from './streaming.js';
10
- import chalk from 'chalk';
11
-
12
- export interface AgentConfig {
13
- maxIterations?: number;
14
- streaming?: boolean;
15
- verbose?: boolean;
16
- }
17
-
18
- export class Agent {
19
- private ai: AIEngine;
20
- private session: SessionManager;
21
- private intentRecognizer: IntentRecognizer;
22
- private config: AgentConfig;
23
- private streaming: StreamingOutput;
24
-
25
- constructor(ai: AIEngine, session: SessionManager, config?: AgentConfig) {
26
- this.ai = ai;
27
- this.session = session;
28
- this.intentRecognizer = new IntentRecognizer(ai);
29
- this.config = {
30
- maxIterations: 5,
31
- streaming: false,
32
- verbose: false,
33
- ...config
34
- };
35
- this.streaming = new StreamingOutput();
36
- }
37
-
38
- /**
39
- * Process user input through the agent
40
- */
41
- async process(input: string): Promise<string> {
42
- // Step 1: Recognize intent
43
- const intent = await this.intentRecognizer.recognize(input);
44
-
45
- if (this.config.verbose) {
46
- console.log(chalk.gray(`\n📍 Intent: ${intent.type} (${intent.confidence}) - ${intent.reason}`));
47
- }
48
-
49
- // Step 2: Handle complex tasks
50
- if (intent.type === 'complex') {
51
- return await this.handleComplexTask(input, intent);
52
- }
53
-
54
- // Step 3: Route to appropriate handler
55
- switch (intent.type) {
56
- case 'command':
57
- return await this.handleCommand(input);
58
- case 'query':
59
- return await this.handleQuery(input);
60
- case 'code':
61
- case 'chat':
62
- default:
63
- return await this.handleGeneral(input);
64
- }
65
- }
66
-
67
- /**
68
- * Handle complex multi-step tasks
69
- */
70
- private async handleComplexTask(input: string, intent: Intent): Promise<string> {
71
- const subtasks = await this.intentRecognizer.breakIntoSubtasks(input);
72
-
73
- if (this.config.verbose) {
74
- console.log(chalk.cyan(`\n📋 Breaking into ${subtasks.length} subtasks:`));
75
- subtasks.forEach((task, i) => {
76
- console.log(chalk.gray(` ${i + 1}. ${task.description} [${task.action}]`));
77
- });
78
- }
79
-
80
- let results: string[] = [];
81
-
82
- for (let i = 0; i < subtasks.length; i++) {
83
- const task = subtasks[i];
84
- console.log(chalk.cyan(`\n[${i + 1}/${subtasks.length}] ${task.description}...`));
85
-
86
- const result = await this.process(task.description);
87
- results.push(result);
88
- }
89
-
90
- return results.join('\n\n');
91
- }
92
-
93
- /**
94
- * Handle command intent
95
- */
96
- private async handleCommand(input: string): Promise<string> {
97
- // Extract command from input
98
- const command = input
99
- .replace(/^(run|execute|exec)\s+/i, '')
100
- .trim();
101
-
102
- // Add to session and get response
103
- this.session.addMessage('user', input);
104
-
105
- const response = await this.ai.chat(this.session.getMessages(), this.config.maxIterations);
106
-
107
- this.session.addMessage('assistant', response.content);
108
-
109
- return response.content;
110
- }
111
-
112
- /**
113
- * Handle query intent
114
- */
115
- private async handleQuery(input: string): Promise<string> {
116
- this.session.addMessage('user', input);
117
-
118
- const response = await this.ai.chat(this.session.getMessages(), this.config.maxIterations);
119
-
120
- this.session.addMessage('assistant', response.content);
121
-
122
- return response.content;
123
- }
124
-
125
- /**
126
- * Handle general/code/chat intents
127
- */
128
- private async handleGeneral(input: string): Promise<string> {
129
- this.session.addMessage('user', input);
130
-
131
- const response = await this.ai.chat(this.session.getMessages(), this.config.maxIterations);
132
-
133
- this.session.addMessage('assistant', response.content);
134
-
135
- return response.content;
136
- }
137
-
138
- /**
139
- * Process with streaming output
140
- */
141
- async processStream(input: string, onChunk: (chunk: string) => void): Promise<string> {
142
- const wasStreaming = this.config.streaming;
143
- this.config.streaming = true;
144
-
145
- this.streaming.start({ onChunk });
146
-
147
- try {
148
- const result = await this.process(input);
149
- this.streaming.end();
150
- return result;
151
- } catch (error) {
152
- this.streaming.stop();
153
- throw error;
154
- } finally {
155
- this.config.streaming = wasStreaming;
156
- }
157
- }
158
-
159
- /**
160
- * Get session
161
- */
162
- getSession(): SessionManager {
163
- return this.session;
164
- }
165
-
166
- /**
167
- * Clear session
168
- */
169
- clearSession(): void {
170
- this.session.clear();
171
- }
172
-
173
- /**
174
- * Interrupt ongoing operation
175
- */
176
- interrupt(): void {
177
- this.streaming.stop();
178
- }
179
- }
@@ -1,8 +0,0 @@
1
- /**
2
- * Agent Module
3
- * Core agent logic with intent recognition and task planning
4
- */
5
-
6
- export { Agent, type AgentConfig } from './core.js';
7
- export { IntentRecognizer, type Intent, type SubTask } from './intent.js';
8
- export { StreamingOutput } from './streaming.js';
@@ -1,181 +0,0 @@
1
- /**
2
- * Intent Recognition
3
- * Identifies user intent: chat, code, command, or query
4
- */
5
-
6
- export interface Intent {
7
- type: 'chat' | 'code' | 'command' | 'query' | 'complex';
8
- confidence: number;
9
- reason?: string;
10
- subTasks?: SubTask[];
11
- }
12
-
13
- export interface SubTask {
14
- description: string;
15
- action: string;
16
- target?: string;
17
- }
18
-
19
- /**
20
- * Intent Recognition Prompt
21
- */
22
- const INTENT_PROMPT = `Analyze the user message and identify their intent.
23
-
24
- Intent types:
25
- - "chat": General conversation, questions, small talk
26
- - "code": Write, edit, refactor code
27
- - "command": Execute shell commands, git operations
28
- - "query": Search files, find information, read code
29
- - "complex": Multiple actions needed - break into subtasks
30
-
31
- Respond with JSON:
32
- {
33
- "type": "chat|code|command|query|complex",
34
- "confidence": 0.0-1.0,
35
- "reason": "brief explanation",
36
- "subTasks": [{"description": "...", "action": "...", "target": "..."}] // only for complex
37
- }
38
-
39
- User message:`;
40
-
41
- export class IntentRecognizer {
42
- private ai: any;
43
-
44
- constructor(aiEngine: any) {
45
- this.ai = aiEngine;
46
- }
47
-
48
- /**
49
- * Recognize intent from user message
50
- */
51
- async recognize(message: string): Promise<Intent> {
52
- // Fast path: simple keyword matching for common patterns
53
- const fastIntent = this.fastRecognize(message);
54
- if (fastIntent.confidence > 0.8) {
55
- return fastIntent;
56
- }
57
-
58
- // Use AI for complex cases
59
- return await this.aiRecognize(message);
60
- }
61
-
62
- /**
63
- * Fast keyword-based recognition
64
- */
65
- private fastRecognize(message: string): Intent {
66
- const lower = message.toLowerCase().trim();
67
- const words = lower.split(/\s+/);
68
-
69
- // Command patterns
70
- const commandPatterns = [
71
- /^run\s+/, /^execute\s+/, /^exec\s+/,
72
- /^npm\s+/, /^node\s+/, /^git\s+/,
73
- /^pip\s+/, /^python\s+/, /^cargo\s+/,
74
- /^make\s+/, /^docker\s+/, /^curl\s+/,
75
- ];
76
-
77
- for (const pattern of commandPatterns) {
78
- if (pattern.test(lower)) {
79
- return { type: 'command', confidence: 0.9, reason: 'Command pattern detected' };
80
- }
81
- }
82
-
83
- // Code patterns
84
- const codePatterns = [
85
- /^write\s+/, /^create\s+.*file/i,
86
- /^edit\s+/, /^modify\s+/, /^change\s+/,
87
- /^refactor/i, /^implement/i,
88
- /^add\s+.*function/i, /^add\s+.*class/i,
89
- /\{[\s\S]*\}/, // Contains code block
90
- /function\s+\w+\s*\(/,
91
- /const\s+\w+\s*=/,
92
- /let\s+\w+\s*=/,
93
- /class\s+\w+/,
94
- ];
95
-
96
- for (const pattern of codePatterns) {
97
- if (pattern.test(message)) {
98
- return { type: 'code', confidence: 0.85, reason: 'Code pattern detected' };
99
- }
100
- }
101
-
102
- // Query patterns
103
- const queryPatterns = [
104
- /^find\s+/, /^search\s+/, /^grep\s+/,
105
- /^show\s+.*files/i, /^list\s+.*files/i,
106
- /^what\s+is\s+/, /^how\s+does\s+/,
107
- /^explain\s+/, /^what's\s+in\s+/,
108
- /^read\s+/, /^look\s+at\s+/,
109
- ];
110
-
111
- for (const pattern of queryPatterns) {
112
- if (pattern.test(lower)) {
113
- return { type: 'query', confidence: 0.85, reason: 'Query pattern detected' };
114
- }
115
- }
116
-
117
- // Complex task patterns (multiple actions)
118
- const complexPatterns = [
119
- /refactor.*and.*test/i,
120
- /create.*and.*setup/i,
121
- /build.*and.*deploy/i,
122
- /fix.*and.*verify/i,
123
- /migrate.*to/i,
124
- /rewrite.*from/i,
125
- ];
126
-
127
- for (const pattern of complexPatterns) {
128
- if (pattern.test(lower)) {
129
- return { type: 'complex', confidence: 0.8, reason: 'Multiple actions detected' };
130
- }
131
- }
132
-
133
- // Default to chat
134
- return { type: 'chat', confidence: 0.6, reason: 'Default intent' };
135
- }
136
-
137
- /**
138
- * AI-powered recognition for ambiguous cases
139
- */
140
- private async aiRecognize(message: string): Promise<Intent> {
141
- // For now, use fast recognition as fallback
142
- // TODO: Implement AI-based recognition for complex cases
143
- return this.fastRecognize(message);
144
- }
145
-
146
- /**
147
- * Break complex task into subtasks
148
- */
149
- async breakIntoSubtasks(message: string): Promise<SubTask[]> {
150
- const lower = message.toLowerCase();
151
-
152
- // Simple rule-based decomposition
153
- const tasks: SubTask[] = [];
154
-
155
- // "refactor X and add tests"
156
- if (lower.includes('refactor') && lower.includes('test')) {
157
- tasks.push({ description: 'Refactor code', action: 'code', target: 'refactor' });
158
- tasks.push({ description: 'Add tests', action: 'code', target: 'test' });
159
- }
160
-
161
- // "create X and setup Y"
162
- if (lower.includes('create') && lower.includes('setup')) {
163
- tasks.push({ description: 'Create component', action: 'code', target: 'create' });
164
- tasks.push({ description: 'Setup configuration', action: 'command', target: 'setup' });
165
- }
166
-
167
- // "fix X and verify"
168
- if (lower.includes('fix') && (lower.includes('verify') || lower.includes('test'))) {
169
- tasks.push({ description: 'Fix issue', action: 'code', target: 'fix' });
170
- tasks.push({ description: 'Verify fix', action: 'command', target: 'test' });
171
- }
172
-
173
- // If no decomposition rules matched, treat as single task
174
- if (tasks.length === 0) {
175
- const intent = this.fastRecognize(message);
176
- tasks.push({ description: message, action: intent.type, target: message });
177
- }
178
-
179
- return tasks;
180
- }
181
- }