thatgfsj-code 0.3.0 → 0.3.1

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 (262) hide show
  1. package/CHANGELOG.md +229 -0
  2. package/DEVELOPMENT.md +286 -0
  3. package/README.md +144 -79
  4. package/dist/agent/core.d.ts +56 -0
  5. package/dist/agent/core.d.ts.map +1 -0
  6. package/dist/agent/core.js +142 -0
  7. package/dist/agent/core.js.map +1 -0
  8. package/dist/agent/index.d.ts +8 -0
  9. package/dist/agent/index.d.ts.map +1 -0
  10. package/dist/agent/index.js +8 -0
  11. package/dist/agent/index.js.map +1 -0
  12. package/dist/agent/intent.d.ts +36 -0
  13. package/dist/agent/intent.d.ts.map +1 -0
  14. package/dist/agent/intent.js +146 -0
  15. package/dist/agent/intent.js.map +1 -0
  16. package/dist/agent/streaming.d.ts +50 -0
  17. package/dist/agent/streaming.d.ts.map +1 -0
  18. package/dist/agent/streaming.js +110 -0
  19. package/dist/agent/streaming.js.map +1 -0
  20. package/dist/core/ai-engine.d.ts +76 -0
  21. package/dist/core/ai-engine.d.ts.map +1 -0
  22. package/dist/core/ai-engine.js +394 -0
  23. package/dist/core/ai-engine.js.map +1 -0
  24. package/dist/core/cli.d.ts +21 -0
  25. package/dist/core/cli.d.ts.map +1 -0
  26. package/dist/core/cli.js +143 -0
  27. package/dist/core/cli.js.map +1 -0
  28. package/dist/core/config.d.ts +55 -0
  29. package/dist/core/config.d.ts.map +1 -0
  30. package/dist/core/config.js +162 -0
  31. package/dist/core/config.js.map +1 -0
  32. package/dist/core/context-compactor.d.ts +54 -0
  33. package/dist/core/context-compactor.d.ts.map +1 -0
  34. package/dist/core/context-compactor.js +197 -0
  35. package/dist/core/context-compactor.js.map +1 -0
  36. package/dist/core/hooks.d.ts +75 -0
  37. package/dist/core/hooks.d.ts.map +1 -0
  38. package/dist/core/hooks.js +146 -0
  39. package/dist/core/hooks.js.map +1 -0
  40. package/dist/core/permissions.d.ts +52 -0
  41. package/dist/core/permissions.d.ts.map +1 -0
  42. package/dist/core/permissions.js +237 -0
  43. package/dist/core/permissions.js.map +1 -0
  44. package/dist/core/session.d.ts +54 -0
  45. package/dist/core/session.d.ts.map +1 -0
  46. package/dist/core/session.js +147 -0
  47. package/dist/core/session.js.map +1 -0
  48. package/dist/core/skills.d.ts +60 -0
  49. package/dist/core/skills.d.ts.map +1 -0
  50. package/dist/core/skills.js +175 -0
  51. package/dist/core/skills.js.map +1 -0
  52. package/dist/core/state.d.ts +60 -0
  53. package/dist/core/state.d.ts.map +1 -0
  54. package/dist/core/state.js +106 -0
  55. package/dist/core/state.js.map +1 -0
  56. package/dist/core/subagent.d.ts +68 -0
  57. package/dist/core/subagent.d.ts.map +1 -0
  58. package/dist/core/subagent.js +142 -0
  59. package/dist/core/subagent.js.map +1 -0
  60. package/dist/core/system-prompt.d.ts +40 -0
  61. package/dist/core/system-prompt.d.ts.map +1 -0
  62. package/dist/core/system-prompt.js +138 -0
  63. package/dist/core/system-prompt.js.map +1 -0
  64. package/dist/core/tool-registry.d.ts +53 -0
  65. package/dist/core/tool-registry.d.ts.map +1 -0
  66. package/dist/core/tool-registry.js +138 -0
  67. package/dist/core/tool-registry.js.map +1 -0
  68. package/dist/core/types.d.ts +206 -0
  69. package/dist/core/types.d.ts.map +1 -0
  70. package/dist/core/types.js +127 -0
  71. package/dist/core/types.js.map +1 -0
  72. package/dist/index.d.ts +7 -0
  73. package/dist/{cmd/index.d.ts.map → index.d.ts.map} +1 -1
  74. package/dist/index.js +472 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/mcp/client.d.ts +1 -1
  77. package/dist/mcp/client.d.ts.map +1 -1
  78. package/dist/repl/index.d.ts +8 -0
  79. package/dist/repl/index.d.ts.map +1 -0
  80. package/dist/repl/index.js +8 -0
  81. package/dist/repl/index.js.map +1 -0
  82. package/dist/repl/input.d.ts +69 -0
  83. package/dist/repl/input.d.ts.map +1 -0
  84. package/dist/repl/input.js +139 -0
  85. package/dist/repl/input.js.map +1 -0
  86. package/dist/repl/loop.d.ts +184 -0
  87. package/dist/repl/loop.d.ts.map +1 -0
  88. package/dist/repl/loop.js +932 -0
  89. package/dist/repl/loop.js.map +1 -0
  90. package/dist/repl/output.d.ts +105 -0
  91. package/dist/repl/output.d.ts.map +1 -0
  92. package/dist/repl/output.js +199 -0
  93. package/dist/repl/output.js.map +1 -0
  94. package/dist/repl/welcome.d.ts +68 -0
  95. package/dist/repl/welcome.d.ts.map +1 -0
  96. package/dist/repl/welcome.js +254 -0
  97. package/dist/repl/welcome.js.map +1 -0
  98. package/dist/tools/file.d.ts +1 -1
  99. package/dist/tools/file.d.ts.map +1 -1
  100. package/dist/tools/git.d.ts +1 -1
  101. package/dist/tools/git.d.ts.map +1 -1
  102. package/dist/tools/index.d.ts +15 -35
  103. package/dist/tools/index.d.ts.map +1 -1
  104. package/dist/tools/index.js +31 -80
  105. package/dist/tools/index.js.map +1 -1
  106. package/dist/tools/search.d.ts +1 -1
  107. package/dist/tools/search.d.ts.map +1 -1
  108. package/dist/tools/shell.d.ts +11 -4
  109. package/dist/tools/shell.d.ts.map +1 -1
  110. package/dist/tools/shell.js +78 -42
  111. package/dist/tools/shell.js.map +1 -1
  112. package/dist/utils/diff-preview.d.ts +42 -0
  113. package/dist/utils/diff-preview.d.ts.map +1 -0
  114. package/dist/utils/diff-preview.js +174 -0
  115. package/dist/utils/diff-preview.js.map +1 -0
  116. package/dist/utils/index.d.ts +8 -0
  117. package/dist/utils/index.d.ts.map +1 -0
  118. package/dist/utils/index.js +8 -0
  119. package/dist/utils/index.js.map +1 -0
  120. package/dist/utils/memory.d.ts +81 -0
  121. package/dist/utils/memory.d.ts.map +1 -0
  122. package/dist/utils/memory.js +186 -0
  123. package/dist/utils/memory.js.map +1 -0
  124. package/dist/utils/project-context.d.ts +62 -0
  125. package/dist/utils/project-context.d.ts.map +1 -0
  126. package/dist/utils/project-context.js +197 -0
  127. package/dist/utils/project-context.js.map +1 -0
  128. package/docs/API_KEY_GUIDE.md +6 -0
  129. package/docs/FAQ.md +25 -3
  130. package/package.json +41 -9
  131. package/ROADMAP.md +0 -61
  132. package/dist/app/agent.d.ts +0 -31
  133. package/dist/app/agent.d.ts.map +0 -1
  134. package/dist/app/agent.js +0 -106
  135. package/dist/app/agent.js.map +0 -1
  136. package/dist/app/index.d.ts +0 -39
  137. package/dist/app/index.d.ts.map +0 -1
  138. package/dist/app/index.js +0 -80
  139. package/dist/app/index.js.map +0 -1
  140. package/dist/cmd/index.d.ts +0 -12
  141. package/dist/cmd/index.js +0 -85
  142. package/dist/cmd/index.js.map +0 -1
  143. package/dist/config/index.d.ts +0 -39
  144. package/dist/config/index.d.ts.map +0 -1
  145. package/dist/config/index.js +0 -110
  146. package/dist/config/index.js.map +0 -1
  147. package/dist/config/providers.d.ts +0 -23
  148. package/dist/config/providers.d.ts.map +0 -1
  149. package/dist/config/providers.js +0 -152
  150. package/dist/config/providers.js.map +0 -1
  151. package/dist/config/types.d.ts +0 -33
  152. package/dist/config/types.d.ts.map +0 -1
  153. package/dist/config/types.js +0 -5
  154. package/dist/config/types.js.map +0 -1
  155. package/dist/hooks/index.d.ts +0 -31
  156. package/dist/hooks/index.d.ts.map +0 -1
  157. package/dist/hooks/index.js +0 -71
  158. package/dist/hooks/index.js.map +0 -1
  159. package/dist/llm/anthropic.d.ts +0 -17
  160. package/dist/llm/anthropic.d.ts.map +0 -1
  161. package/dist/llm/anthropic.js +0 -126
  162. package/dist/llm/anthropic.js.map +0 -1
  163. package/dist/llm/gemini.d.ts +0 -16
  164. package/dist/llm/gemini.d.ts.map +0 -1
  165. package/dist/llm/gemini.js +0 -107
  166. package/dist/llm/gemini.js.map +0 -1
  167. package/dist/llm/index.d.ts +0 -48
  168. package/dist/llm/index.d.ts.map +0 -1
  169. package/dist/llm/index.js +0 -174
  170. package/dist/llm/index.js.map +0 -1
  171. package/dist/llm/openai.d.ts +0 -17
  172. package/dist/llm/openai.d.ts.map +0 -1
  173. package/dist/llm/openai.js +0 -113
  174. package/dist/llm/openai.js.map +0 -1
  175. package/dist/llm/provider.d.ts +0 -33
  176. package/dist/llm/provider.d.ts.map +0 -1
  177. package/dist/llm/provider.js +0 -6
  178. package/dist/llm/provider.js.map +0 -1
  179. package/dist/prompts/index.d.ts +0 -27
  180. package/dist/prompts/index.d.ts.map +0 -1
  181. package/dist/prompts/index.js +0 -102
  182. package/dist/prompts/index.js.map +0 -1
  183. package/dist/session/compactor.d.ts +0 -48
  184. package/dist/session/compactor.d.ts.map +0 -1
  185. package/dist/session/compactor.js +0 -77
  186. package/dist/session/compactor.js.map +0 -1
  187. package/dist/session/index.d.ts +0 -48
  188. package/dist/session/index.d.ts.map +0 -1
  189. package/dist/session/index.js +0 -69
  190. package/dist/session/index.js.map +0 -1
  191. package/dist/session/message.d.ts +0 -26
  192. package/dist/session/message.d.ts.map +0 -1
  193. package/dist/session/message.js +0 -34
  194. package/dist/session/message.js.map +0 -1
  195. package/dist/tools/types.d.ts +0 -68
  196. package/dist/tools/types.d.ts.map +0 -1
  197. package/dist/tools/types.js +0 -57
  198. package/dist/tools/types.js.map +0 -1
  199. package/dist/tui/index.d.ts +0 -8
  200. package/dist/tui/index.d.ts.map +0 -1
  201. package/dist/tui/index.js +0 -8
  202. package/dist/tui/index.js.map +0 -1
  203. package/dist/tui/input.d.ts +0 -14
  204. package/dist/tui/input.d.ts.map +0 -1
  205. package/dist/tui/input.js +0 -50
  206. package/dist/tui/input.js.map +0 -1
  207. package/dist/tui/output.d.ts +0 -20
  208. package/dist/tui/output.d.ts.map +0 -1
  209. package/dist/tui/output.js +0 -70
  210. package/dist/tui/output.js.map +0 -1
  211. package/dist/tui/repl.d.ts +0 -25
  212. package/dist/tui/repl.d.ts.map +0 -1
  213. package/dist/tui/repl.js +0 -114
  214. package/dist/tui/repl.js.map +0 -1
  215. package/dist/tui/welcome.d.ts +0 -15
  216. package/dist/tui/welcome.d.ts.map +0 -1
  217. package/dist/tui/welcome.js +0 -86
  218. package/dist/tui/welcome.js.map +0 -1
  219. package/dist/types.d.ts +0 -38
  220. package/dist/types.d.ts.map +0 -1
  221. package/dist/types.js +0 -6
  222. package/dist/types.js.map +0 -1
  223. package/dist/utils/diff.d.ts +0 -22
  224. package/dist/utils/diff.d.ts.map +0 -1
  225. package/dist/utils/diff.js +0 -60
  226. package/dist/utils/diff.js.map +0 -1
  227. package/dist/utils/project.d.ts +0 -32
  228. package/dist/utils/project.d.ts.map +0 -1
  229. package/dist/utils/project.js +0 -89
  230. package/dist/utils/project.js.map +0 -1
  231. package/src/app/agent.ts +0 -140
  232. package/src/app/index.ts +0 -101
  233. package/src/cmd/index.ts +0 -96
  234. package/src/config/index.ts +0 -130
  235. package/src/config/providers.ts +0 -160
  236. package/src/config/types.ts +0 -46
  237. package/src/hooks/index.ts +0 -111
  238. package/src/llm/anthropic.ts +0 -146
  239. package/src/llm/gemini.ts +0 -127
  240. package/src/llm/index.ts +0 -209
  241. package/src/llm/openai.ts +0 -132
  242. package/src/llm/provider.ts +0 -38
  243. package/src/mcp/client.ts +0 -330
  244. package/src/prompts/index.ts +0 -123
  245. package/src/session/compactor.ts +0 -103
  246. package/src/session/index.ts +0 -81
  247. package/src/session/message.ts +0 -42
  248. package/src/tools/file.ts +0 -117
  249. package/src/tools/git.ts +0 -132
  250. package/src/tools/index.ts +0 -108
  251. package/src/tools/search.ts +0 -263
  252. package/src/tools/shell.ts +0 -136
  253. package/src/tools/types.ts +0 -122
  254. package/src/tui/index.ts +0 -8
  255. package/src/tui/input.ts +0 -56
  256. package/src/tui/output.ts +0 -83
  257. package/src/tui/repl.ts +0 -131
  258. package/src/tui/welcome.ts +0 -101
  259. package/src/types.ts +0 -42
  260. package/src/utils/diff.ts +0 -71
  261. package/src/utils/project.ts +0 -99
  262. package/tsconfig.json +0 -19
@@ -1,136 +0,0 @@
1
- /**
2
- * Shell Tool - Execute shell commands with security checks
3
- * Migrated from old src/tools/shell.ts (permission logic inlined)
4
- */
5
-
6
- import type { Tool, ToolResult, ToolContext } from './types.js';
7
- import { exec } from 'child_process';
8
- import { promisify } from 'util';
9
-
10
- const execAsync = promisify(exec);
11
-
12
- // Dangerous command patterns - blocked immediately
13
- const DANGEROUS_PATTERNS = [
14
- /^rm\s+-rf\s+\//i,
15
- /^del\s+\/f\s+\/s\s+\/q/i,
16
- /^format\s+[a-z]:/i,
17
- /^mkfs/i,
18
- /^dd\s+if=/i,
19
- /^shred/i,
20
- /^cat\s+\/dev\/null\s*>/i,
21
- />\s*\/dev\/sda/i,
22
- /^rm\s+-rf\s+\$HOME/i,
23
- /^rm\s+-rf\s+%USERPROFILE%/i,
24
- /^curl\s+.*\|.*sh/i,
25
- /^wget\s+.*\|.*sh/i,
26
- /^eval\s+/i,
27
- /base64\s+-d\s+.*\|/i,
28
- ];
29
-
30
- // Commands that need user confirmation
31
- const CONFIRM_REQUIRED = [
32
- 'rm -rf',
33
- 'rmdir',
34
- 'del /s /q',
35
- 'format',
36
- 'mkfs',
37
- 'dd',
38
- 'shutdown',
39
- 'reboot',
40
- 'pkill',
41
- 'killall',
42
- 'git push --force',
43
- 'git push -f',
44
- ];
45
-
46
- export class ShellTool implements Tool {
47
- name = 'shell';
48
- description = 'Execute shell commands and scripts. Some commands require user confirmation.';
49
-
50
- inputSchema = {
51
- type: 'object' as const,
52
- properties: {
53
- command: { type: 'string', description: 'Shell command to execute' },
54
- cwd: { type: 'string', description: 'Working directory' },
55
- timeout: { type: 'number', description: 'Timeout in seconds', default: 30 },
56
- },
57
- required: ['command'],
58
- };
59
-
60
- metadata = {
61
- permissions: ['execute', 'write', 'network'] as ('read' | 'write' | 'execute' | 'network')[],
62
- tags: ['shell', 'system', 'dangerous'],
63
- maxDuration: 120000,
64
- version: '1.0.0',
65
- };
66
-
67
- parameters = [
68
- { name: 'command', type: 'string', description: 'Shell command to execute', required: true },
69
- { name: 'cwd', type: 'string', description: 'Working directory', required: false },
70
- { name: 'timeout', type: 'number', description: 'Timeout in seconds', required: false },
71
- ];
72
-
73
- /**
74
- * Check if command matches dangerous patterns
75
- */
76
- private isDangerous(command: string): boolean {
77
- return DANGEROUS_PATTERNS.some(pattern => pattern.test(command.trim()));
78
- }
79
-
80
- /**
81
- * Check if command needs user confirmation
82
- */
83
- private needsConfirmation(command: string): boolean {
84
- const lower = command.toLowerCase();
85
- return CONFIRM_REQUIRED.some(cmd => lower.includes(cmd.toLowerCase()));
86
- }
87
-
88
- async execute(params: Record<string, any>, ctx?: ToolContext): Promise<ToolResult> {
89
- const { command, cwd, timeout = 30 } = params;
90
-
91
- if (!command || typeof command !== 'string') {
92
- return { success: false, error: 'Command is required and must be a string' };
93
- }
94
-
95
- const trimmed = command.trim();
96
-
97
- // Block dangerous commands
98
- if (this.isDangerous(trimmed)) {
99
- return { success: false, error: `Blocked: dangerous command "${trimmed.substring(0, 50)}..."` };
100
- }
101
-
102
- if (trimmed.length > 10000) {
103
- return { success: false, error: 'Command too long (max 10000 characters)' };
104
- }
105
-
106
- // Ask for confirmation on risky commands
107
- if (ctx?.confirmAction && this.needsConfirmation(trimmed)) {
108
- const confirmed = await ctx.confirmAction(
109
- `⚠️ Confirm command:\n ${command}\n\n[y] Yes [n] No`
110
- );
111
- if (!confirmed) {
112
- return { success: false, error: 'Command cancelled by user' };
113
- }
114
- }
115
-
116
- try {
117
- const options: any = {
118
- timeout: timeout * 1000,
119
- maxBuffer: 10 * 1024 * 1024, // 10MB
120
- };
121
- if (cwd) options.cwd = cwd;
122
-
123
- const { stdout, stderr } = await execAsync(command, options);
124
- const stdoutStr = stdout?.toString() || '';
125
- const stderrStr = stderr?.toString() || '';
126
- const output = stdoutStr + (stderrStr ? `\n[stderr]: ${stderrStr}` : '');
127
-
128
- return { success: true, output: output.trim() || '(command executed successfully with no output)' };
129
- } catch (error: any) {
130
- if (error.killed) {
131
- return { success: false, error: 'Command timed out' };
132
- }
133
- return { success: false, error: error.message || 'Command execution failed' };
134
- }
135
- }
136
- }
@@ -1,122 +0,0 @@
1
- /**
2
- * Tool interface definitions
3
- * Extracted from old src/core/types.ts
4
- */
5
-
6
- // ==================== Tool Parameter & Schema ====================
7
-
8
- export interface ToolParameter {
9
- name: string;
10
- type: string;
11
- description: string;
12
- required: boolean;
13
- default?: any;
14
- enum?: string[];
15
- }
16
-
17
- export interface ToolInputSchema {
18
- type: 'object';
19
- properties: Record<string, {
20
- type: string;
21
- description: string;
22
- default?: any;
23
- enum?: string[];
24
- }>;
25
- required?: string[];
26
- }
27
-
28
- export interface ToolMetadata {
29
- permissions?: ('read' | 'write' | 'execute' | 'network')[];
30
- maxDuration?: number;
31
- tags?: string[];
32
- version?: string;
33
- deprecated?: string;
34
- }
35
-
36
- // ==================== Tool Interface ====================
37
-
38
- export interface ToolContext {
39
- sessionId?: string;
40
- workingDirectory?: string;
41
- confirmAction?: (msg: string) => Promise<boolean>;
42
- signal?: AbortSignal;
43
- toolCallId?: string;
44
- }
45
-
46
- export interface ToolResult {
47
- success: boolean;
48
- output?: string;
49
- error?: string;
50
- data?: any;
51
- }
52
-
53
- export interface Tool {
54
- name: string;
55
- description: string;
56
- parameters: ToolParameter[];
57
- inputSchema?: ToolInputSchema;
58
- metadata?: ToolMetadata;
59
- execute(params: Record<string, any>, ctx?: ToolContext): Promise<ToolResult>;
60
- }
61
-
62
- // ==================== Tool Builder ====================
63
-
64
- export class ToolBuilder {
65
- private _name = '';
66
- private _description = '';
67
- private _parameters: ToolParameter[] = [];
68
- private _inputSchema: ToolInputSchema = { type: 'object', properties: {} };
69
- private _metadata: ToolMetadata = {};
70
- private _fn?: (params: Record<string, any>, ctx: ToolContext) => Promise<ToolResult>;
71
-
72
- name(n: string): this { this._name = n; return this; }
73
- description(d: string): this { this._description = d; return this; }
74
-
75
- param(p: ToolParameter): this {
76
- this._parameters.push(p);
77
- this._inputSchema.properties[p.name] = {
78
- type: p.type,
79
- description: p.description,
80
- default: p.default,
81
- enum: p.enum,
82
- };
83
- return this;
84
- }
85
-
86
- stringParam(name: string, description: string, required = true, defaultVal?: string): this {
87
- return this.param({ name, type: 'string', description, required, default: defaultVal });
88
- }
89
-
90
- booleanParam(name: string, description: string, required = false, defaultVal?: boolean): this {
91
- return this.param({ name, type: 'boolean', description, required, default: defaultVal });
92
- }
93
-
94
- permissions(...perms: ('read' | 'write' | 'execute' | 'network')[]): this {
95
- this._metadata.permissions = perms;
96
- return this;
97
- }
98
-
99
- tags(...t: string[]): this {
100
- this._metadata.tags = t;
101
- return this;
102
- }
103
-
104
- handle(fn: (params: Record<string, any>, ctx: ToolContext) => Promise<ToolResult>): this {
105
- this._fn = fn;
106
- return this;
107
- }
108
-
109
- build(): Tool {
110
- if (!this._name || !this._fn) {
111
- throw new Error('Tool name and handler are required');
112
- }
113
- return {
114
- name: this._name,
115
- description: this._description,
116
- parameters: this._parameters,
117
- inputSchema: this._inputSchema,
118
- metadata: this._metadata,
119
- execute: this._fn,
120
- };
121
- }
122
- }
package/src/tui/index.ts DELETED
@@ -1,8 +0,0 @@
1
- /**
2
- * TUI Module - Terminal User Interface
3
- */
4
-
5
- export { REPL } from './repl.js';
6
- export { REPLInput } from './input.js';
7
- export { REPLOutput } from './output.js';
8
- export { WelcomeScreen } from './welcome.js';
package/src/tui/input.ts DELETED
@@ -1,56 +0,0 @@
1
- /**
2
- * REPL Input Handler
3
- * Migrated from old src/repl/input.ts
4
- */
5
-
6
- import readline from 'readline';
7
- import chalk from 'chalk';
8
-
9
- export class REPLInput {
10
- private rl: readline.Interface;
11
- private history: string[] = [];
12
- private historyIndex: number = -1;
13
-
14
- constructor() {
15
- this.rl = readline.createInterface({
16
- input: process.stdin,
17
- output: process.stdout,
18
- completer: this.completer.bind(this),
19
- historySize: 100,
20
- tabSize: 4,
21
- });
22
-
23
- // Handle Ctrl+C
24
- this.rl.on('SIGINT', () => {
25
- process.stdout.write(chalk.gray('\n\n👋 Exiting...\n'));
26
- process.exit(0);
27
- });
28
-
29
- // Track history
30
- this.rl.on('line', (line) => {
31
- if (line.trim()) {
32
- this.history.push(line);
33
- if (this.history.length > 100) this.history.shift();
34
- }
35
- this.historyIndex = this.history.length;
36
- });
37
- }
38
-
39
- async prompt(prefix: string = chalk.green('\n> ')): Promise<string> {
40
- return new Promise((resolve) => {
41
- this.rl.question(prefix, (answer) => {
42
- resolve(answer);
43
- });
44
- });
45
- }
46
-
47
- close(): void {
48
- this.rl.close();
49
- }
50
-
51
- private completer(line: string): [string[], string] {
52
- const commands = ['exit', 'quit', 'clear', 'help', 'tools', 'model'];
53
- const hits = commands.filter(c => c.startsWith(line.toLowerCase()));
54
- return [hits.length ? hits : [], line];
55
- }
56
- }
package/src/tui/output.ts DELETED
@@ -1,83 +0,0 @@
1
- /**
2
- * REPL Output Handler
3
- * Migrated from old src/repl/output.ts
4
- */
5
-
6
- import chalk from 'chalk';
7
- import ora, { Ora } from 'ora';
8
-
9
- export class REPLOutput {
10
- private spinner: Ora | null = null;
11
-
12
- printError(error: string): void {
13
- console.error(chalk.red(`\n❌ Error: ${error}`));
14
- }
15
-
16
- printWarning(warning: string): void {
17
- console.warn(chalk.yellow(`\n⚠️ ${warning}`));
18
- }
19
-
20
- printSuccess(message: string): void {
21
- console.log(chalk.green(`\n✅ ${message}`));
22
- }
23
-
24
- printInfo(message: string): void {
25
- console.log(chalk.gray(message));
26
- }
27
-
28
- printDivider(char = '─', length = 40): void {
29
- console.log(chalk.gray(char.repeat(length)));
30
- }
31
-
32
- printHeader(text: string): void {
33
- this.printDivider();
34
- console.log(chalk.cyan(text));
35
- this.printDivider();
36
- }
37
-
38
- startSpinner(text: string): void {
39
- this.spinner = ora({ text, color: 'cyan', spinner: 'dots' }).start();
40
- }
41
-
42
- stopSpinner(): void {
43
- if (this.spinner) {
44
- this.spinner.stop();
45
- this.spinner = null;
46
- }
47
- }
48
-
49
- stopSpinnerFail(text?: string): void {
50
- if (this.spinner) {
51
- this.spinner.fail(text || this.spinner.text);
52
- this.spinner = null;
53
- }
54
- }
55
-
56
- clear(): void {
57
- console.clear();
58
- }
59
-
60
- printBanner(): void {
61
- console.log(chalk.cyan(`
62
- ╔═══════════════════════════════════════╗
63
- ║ 🤖 Thatgfsj Code v0.3.0 ║
64
- ║ AI Coding Assistant ║
65
- ╚═══════════════════════════════════════╝
66
- `));
67
- }
68
-
69
- printHelp(): void {
70
- console.log(`
71
- ${chalk.cyan('Commands:')}
72
- ${chalk.gray('exit, Ctrl+C')} - Exit
73
- ${chalk.gray('clear')} - Clear screen
74
- ${chalk.gray('help')} - Show this help
75
- ${chalk.gray('tools')} - List available tools
76
- ${chalk.gray('model')} - Show current model
77
-
78
- ${chalk.cyan('Tips:')}
79
- • Use ${chalk.gray('↑/↓')} for command history
80
- • Use ${chalk.gray('Tab')} for auto-complete
81
- `);
82
- }
83
- }
package/src/tui/repl.ts DELETED
@@ -1,131 +0,0 @@
1
- /**
2
- * REPL - Main interactive loop
3
- * Migrated from old src/repl/loop.ts + src/index.ts interactive mode
4
- */
5
-
6
- import chalk from 'chalk';
7
- import { REPLInput } from './input.js';
8
- import { REPLOutput } from './output.js';
9
- import { App } from '../app/index.js';
10
- import { ProjectContext } from '../utils/project.js';
11
-
12
- export class REPL {
13
- private input: REPLInput;
14
- private output: REPLOutput;
15
- private app: App;
16
- private running = false;
17
-
18
- constructor(app: App) {
19
- this.input = new REPLInput();
20
- this.output = new REPLOutput();
21
- this.app = app;
22
- }
23
-
24
- /**
25
- * Start the REPL
26
- */
27
- async start(): Promise<void> {
28
- this.running = true;
29
-
30
- // Show banner
31
- this.output.clear();
32
- this.output.printBanner();
33
- this.output.printInfo('Type "help" for available commands\n');
34
- this.output.printDivider();
35
-
36
- // Show project context
37
- console.log(chalk.gray(ProjectContext.getSummary()));
38
- this.output.printDivider();
39
- console.log();
40
-
41
- // Main loop
42
- while (this.running) {
43
- try {
44
- const userInput = await this.input.prompt();
45
-
46
- if (!userInput.trim()) continue;
47
-
48
- // Handle commands
49
- const handled = await this.handleCommand(userInput.trim());
50
- if (handled) continue;
51
-
52
- // Process with AI
53
- await this.processInput(userInput.trim());
54
- } catch (error: any) {
55
- if (error.message === 'SIGINT') continue;
56
- this.output.printError(error.message);
57
- }
58
- }
59
- }
60
-
61
- /**
62
- * Handle built-in commands
63
- */
64
- private async handleCommand(input: string): Promise<boolean> {
65
- const cmd = input.toLowerCase();
66
-
67
- switch (cmd) {
68
- case 'exit':
69
- case 'quit':
70
- this.output.printInfo('\n👋 Goodbye!');
71
- this.running = false;
72
- this.input.close();
73
- return true;
74
-
75
- case 'clear':
76
- this.output.clear();
77
- this.output.printBanner();
78
- return true;
79
-
80
- case 'help':
81
- this.output.printHelp();
82
- return true;
83
-
84
- case 'tools':
85
- this.output.printHeader('🔧 Available Tools');
86
- for (const tool of this.app.tools.list()) {
87
- this.output.printInfo(` ${tool.name} - ${tool.description}`);
88
- }
89
- console.log();
90
- return true;
91
-
92
- case 'model':
93
- this.output.printHeader('🤖 Current Model');
94
- const cfg = this.app.config.get();
95
- this.output.printInfo(` Provider: ${cfg.provider}`);
96
- this.output.printInfo(` Model: ${cfg.model}`);
97
- this.output.printInfo(` Base URL: ${cfg.baseUrl || 'default'}`);
98
- console.log();
99
- return true;
100
-
101
- default:
102
- return false;
103
- }
104
- }
105
-
106
- /**
107
- * Process user input with AI
108
- */
109
- private async processInput(input: string): Promise<void> {
110
- this.app.session.addMessage('user', input);
111
-
112
- this.output.startSpinner('Thinking...');
113
- let fullResponse = '';
114
-
115
- try {
116
- const stream = this.app.getAgent().run(this.app.session.getMessages());
117
- for await (const chunk of stream) {
118
- this.output.stopSpinner();
119
- process.stdout.write(chunk);
120
- fullResponse += chunk;
121
- }
122
-
123
- console.log(); // newline
124
-
125
- this.app.session.addMessage('assistant', fullResponse);
126
- this.app.session.truncate();
127
- } catch (error: any) {
128
- this.output.stopSpinnerFail(chalk.red(`Error: ${error.message}`));
129
- }
130
- }
131
- }
@@ -1,101 +0,0 @@
1
- /**
2
- * Welcome / Setup Wizard
3
- * Migrated and simplified from old src/repl/welcome.ts
4
- */
5
-
6
- import chalk from 'chalk';
7
- import readline from 'readline';
8
- import { existsSync, mkdirSync, writeFileSync } from 'fs';
9
- import { join } from 'path';
10
- import { homedir } from 'os';
11
- import { PROVIDERS, getModelsForProvider, listProviders } from '../config/providers.js';
12
- import type { ProviderName } from '../config/types.js';
13
-
14
- export class WelcomeScreen {
15
- /**
16
- * Show welcome if no API key is configured
17
- */
18
- static show(hasApiKey: boolean): void {
19
- if (hasApiKey) return;
20
-
21
- const w = 62;
22
- console.log(chalk.cyan('+') + chalk.white.bold(' Thatgfsj Code ') + chalk.cyan('-'.repeat(w - 16)) + '+');
23
- console.log(chalk.cyan('|') + chalk.yellow(' 快速开始指南').padEnd(w) + chalk.cyan('|'));
24
- console.log(chalk.cyan('|') + ' '.repeat(w) + chalk.cyan('|'));
25
- console.log(chalk.cyan('|') + chalk.gray(' 运行 gfcode init 配置你的 API Key').padEnd(w) + chalk.cyan('|'));
26
- console.log(chalk.cyan('|') + chalk.gray(' 或设置环境变量: OPENAI_API_KEY, SILICONFLOW_API_KEY 等').padEnd(w) + chalk.cyan('|'));
27
- console.log(chalk.cyan('+') + '-'.repeat(w) + '+');
28
- console.log();
29
- }
30
-
31
- /**
32
- * Interactive setup wizard
33
- */
34
- static async interactiveSetup(): Promise<void> {
35
- console.clear();
36
- console.log(chalk.cyan('\n 🤖 Thatgfsj Code 配置向导\n'));
37
-
38
- const rl = readline.createInterface({
39
- input: process.stdin,
40
- output: process.stdout,
41
- });
42
-
43
- const question = (prompt: string): Promise<string> =>
44
- new Promise(resolve => rl.question(prompt, answer => resolve(answer.trim())));
45
-
46
- try {
47
- // Step 1: Choose provider
48
- console.log(chalk.white(' 步骤 1/3: 选择 AI 提供商\n'));
49
- const providers = listProviders();
50
- providers.forEach((p, i) => {
51
- console.log(chalk.green(` ${i + 1}. ${p.name}`));
52
- });
53
- console.log();
54
-
55
- const choice = await question(chalk.green(' 请选择 (1-' + providers.length + '): '));
56
- const selected = providers[parseInt(choice) - 1] || providers[0];
57
- const providerName = selected.key;
58
-
59
- // Step 2: Enter API Key
60
- console.log(chalk.white('\n 步骤 2/3: 输入 API Key\n'));
61
- console.log(chalk.gray(` 获取地址: ${PROVIDERS[providerName].baseUrl.replace('/v1', '').replace('/v1beta', '')}`));
62
- const apiKey = await question(chalk.green(' 请输入 API Key: '));
63
-
64
- // Step 3: Choose model
65
- console.log(chalk.white('\n 步骤 3/3: 选择模型\n'));
66
- const models = getModelsForProvider(providerName);
67
- models.forEach((m, i) => {
68
- console.log(chalk.green(` ${i + 1}. ${m.name}`) + chalk.gray(` - ${m.desc}`));
69
- });
70
- console.log();
71
-
72
- const modelChoice = await question(chalk.green(' 请选择模型 (1-' + models.length + '): '));
73
- const selectedModel = models[parseInt(modelChoice) - 1] || models[0];
74
-
75
- // Save config
76
- const configDir = join(homedir(), '.thatgfsj');
77
- const configPath = join(configDir, 'config.json');
78
-
79
- if (!existsSync(configDir)) {
80
- mkdirSync(configDir, { recursive: true });
81
- }
82
-
83
- writeFileSync(configPath, JSON.stringify({
84
- provider: providerName,
85
- model: selectedModel.id,
86
- apiKey,
87
- temperature: 0.7,
88
- maxTokens: 4096,
89
- }, null, 2));
90
-
91
- console.log(chalk.green('\n ✅ 配置已保存!'));
92
- console.log(chalk.gray(` 提供商: ${providerName}`));
93
- console.log(chalk.gray(` 模型: ${selectedModel.name}`));
94
- console.log(chalk.gray(` 配置文件: ${configPath}`));
95
- console.log(chalk.cyan('\n 运行 gfcode 开始使用\n'));
96
-
97
- } finally {
98
- rl.close();
99
- }
100
- }
101
- }
package/src/types.ts DELETED
@@ -1,42 +0,0 @@
1
- /**
2
- * Global shared types for Thatgfsj Code
3
- * Only the most fundamental types used across modules
4
- */
5
-
6
- export type Role = 'system' | 'user' | 'assistant' | 'tool';
7
-
8
- export interface ChatMessage {
9
- role: Role;
10
- content: string;
11
- name?: string;
12
- tool_calls?: ToolCall[];
13
- tool_call_id?: string;
14
- reasoning_content?: string;
15
- }
16
-
17
- export interface ToolCall {
18
- id: string;
19
- type: 'function';
20
- function: {
21
- name: string;
22
- arguments: string;
23
- };
24
- }
25
-
26
- export interface ChatResponse {
27
- content: string;
28
- role: 'assistant';
29
- usage?: {
30
- prompt_tokens: number;
31
- completion_tokens: number;
32
- total_tokens: number;
33
- };
34
- tool_calls?: ToolCall[];
35
- reasoning_content?: string;
36
- }
37
-
38
- export interface ChatOptions {
39
- temperature?: number;
40
- maxTokens?: number;
41
- stream?: boolean;
42
- }