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,157 +0,0 @@
1
- /**
2
- * Tool Registry - Manages available tools with context support
3
- * S02: Enhanced with inputSchema generation and permission metadata
4
- */
5
-
6
- import { Tool, ToolResult, ToolContext, ToolInputSchema } from './types.js';
7
-
8
- export class ToolRegistry {
9
- private tools: Map<string, Tool> = new Map();
10
- private context: ToolContext = {};
11
-
12
- constructor() {
13
- this.registerDefaultTools();
14
- }
15
-
16
- setContext(ctx: Partial<ToolContext>) {
17
- this.context = { ...this.context, ...ctx };
18
- }
19
-
20
- getContext(): ToolContext {
21
- return this.context;
22
- }
23
-
24
- register(tool: Tool): void {
25
- if (this.tools.has(tool.name)) {
26
- console.warn(`Tool ${tool.name} already exists, overwriting...`);
27
- }
28
- this.tools.set(tool.name, tool);
29
- }
30
-
31
- unregister(name: string): boolean {
32
- return this.tools.delete(name);
33
- }
34
-
35
- get(name: string): Tool | undefined {
36
- return this.tools.get(name);
37
- }
38
-
39
- list(): string[] {
40
- return Array.from(this.tools.keys());
41
- }
42
-
43
- /**
44
- * S02: Get tools formatted for AI API
45
- * Uses inputSchema if available, otherwise builds from parameters
46
- */
47
- getToolsForAPI() {
48
- return Array.from(this.tools.values()).map(tool => ({
49
- type: 'function' as const,
50
- function: {
51
- name: tool.name,
52
- description: tool.description,
53
- parameters: tool.inputSchema || this.buildInputSchema(tool)
54
- }
55
- }));
56
- }
57
-
58
- /**
59
- * S02: Build JSON Schema from legacy parameters array
60
- */
61
- private buildInputSchema(tool: Tool): ToolInputSchema {
62
- return {
63
- type: 'object',
64
- properties: tool.parameters.reduce((acc, p) => {
65
- acc[p.name] = {
66
- type: p.type === 'string' ? 'string'
67
- : p.type === 'number' ? 'number'
68
- : p.type === 'boolean' ? 'boolean'
69
- : 'string',
70
- description: p.description
71
- };
72
- return acc;
73
- }, {} as Record<string, { type: string; description: string }>),
74
- required: tool.parameters.filter(p => p.required).map(p => p.name)
75
- };
76
- }
77
-
78
- /**
79
- * S02: List all tools with their metadata
80
- */
81
- listAll() {
82
- return Array.from(this.tools.values()).map(t => ({
83
- name: t.name,
84
- description: t.description,
85
- permissions: t.metadata?.permissions,
86
- tags: t.metadata?.tags,
87
- deprecated: t.metadata?.deprecated
88
- }));
89
- }
90
-
91
- async execute(name: string, params: Record<string, any>): Promise<ToolResult> {
92
- const tool = this.tools.get(name);
93
-
94
- if (!tool) {
95
- return { success: false, error: `Tool "${name}" not found` };
96
- }
97
-
98
- // S02: Validate params against inputSchema
99
- const validationError = this.validateParams(tool, params);
100
- if (validationError) {
101
- return { success: false, error: validationError };
102
- }
103
-
104
- try {
105
- return await tool.execute(params, this.context);
106
- } catch (error: any) {
107
- return { success: false, error: error.message };
108
- }
109
- }
110
-
111
- /**
112
- * S02: Validate params against tool's inputSchema
113
- */
114
- private validateParams(tool: Tool, params: Record<string, any>): string | null {
115
- const schema = tool.inputSchema || this.buildInputSchema(tool);
116
-
117
- // Check required
118
- if (schema.required) {
119
- for (const req of schema.required) {
120
- if (params[req] === undefined || params[req] === null) {
121
- return `Missing required parameter: ${req}`;
122
- }
123
- }
124
- }
125
-
126
- // Check types
127
- for (const [key, value] of Object.entries(params)) {
128
- const prop = schema.properties[key];
129
- if (prop && value !== undefined) {
130
- const expectedType = prop.type;
131
- const actualType = typeof value;
132
- // Type coercion for string/number
133
- if (expectedType === 'number' && actualType === 'string' && !isNaN(Number(value))) {
134
- // Auto-coerce strings to numbers — ok
135
- } else if (actualType !== expectedType) {
136
- return `Invalid type for ${key}: expected ${expectedType}, got ${actualType}`;
137
- }
138
- }
139
- }
140
-
141
- return null;
142
- }
143
-
144
- async executeAll(tools: Array<{ name: string; params: Record<string, any> }>): Promise<ToolResult[]> {
145
- const results: ToolResult[] = [];
146
- for (const { name, params } of tools) {
147
- const result = await this.execute(name, params);
148
- results.push(result);
149
- if (!result.success) break;
150
- }
151
- return results;
152
- }
153
-
154
- private registerDefaultTools(): void {
155
- // Tools registered externally via AIEngine
156
- }
157
- }
package/src/core/types.ts DELETED
@@ -1,280 +0,0 @@
1
- /**
2
- * Type definitions for Thatgfsj Code
3
- * S02: Enhanced Tool interface with Builder pattern, inputSchema, and metadata
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 AIResponse {
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 AIConfig {
39
- model: string;
40
- apiKey?: string;
41
- temperature?: number;
42
- maxTokens?: number;
43
- baseUrl?: string;
44
- provider?: 'minimax' | 'openai' | 'siliconflow' | 'anthropic' | 'ollama' | 'custom' | 'gemini' | 'kimi' | 'deepseek' | 'ernie';
45
- }
46
-
47
- // ==================== S02: Enhanced Tool Interface ====================
48
-
49
- /**
50
- * Tool parameter with type support
51
- */
52
- export interface ToolParameter {
53
- name: string;
54
- type: string;
55
- description: string;
56
- required: boolean;
57
- default?: any;
58
- enum?: string[];
59
- }
60
-
61
- /**
62
- * S02: Input Schema — JSON Schema style tool input definition
63
- * Claude Code uses this for structured tool parameter validation
64
- */
65
- export interface ToolInputSchema {
66
- type: 'object';
67
- properties: Record<string, {
68
- type: string;
69
- description: string;
70
- default?: any;
71
- enum?: string[];
72
- }>;
73
- required?: string[];
74
- }
75
-
76
- /**
77
- * S02: Tool metadata — extra info beyond name/description
78
- */
79
- export interface ToolMetadata {
80
- /** Permission category: read, write, execute, network */
81
- permissions?: ('read' | 'write' | 'execute' | 'network')[];
82
- /** Max execution time in ms */
83
- maxDuration?: number;
84
- /** Tags for categorization */
85
- tags?: string[];
86
- /** Version */
87
- version?: string;
88
- /** Deprecation notice */
89
- deprecated?: string;
90
- }
91
-
92
- /**
93
- * S02: Tool interface with inputSchema + metadata
94
- * Both 'parameters' (legacy) and 'inputSchema' (new) are supported
95
- */
96
- export interface Tool {
97
- name: string;
98
- description: string;
99
- /** Legacy parameter list (still used by existing tools) */
100
- parameters: ToolParameter[];
101
- /** S02: JSON Schema for tool input (computed from parameters) */
102
- inputSchema?: ToolInputSchema;
103
- /** S02: Metadata for permissions, tags, etc. */
104
- metadata?: ToolMetadata;
105
- execute(params: Record<string, any>, ctx?: ToolContext): Promise<ToolResult>;
106
- }
107
-
108
- /**
109
- * S02: Enriched execution context
110
- */
111
- export interface ToolContext {
112
- sessionId?: string;
113
- workingDirectory?: string;
114
- confirmAction?: (msg: string) => Promise<boolean>;
115
- signal?: AbortSignal;
116
- toolCallId?: string;
117
- }
118
-
119
- // Legacy alias
120
- export { ToolParameter as ToolParam };
121
-
122
- /**
123
- * S02: Tool Builder — fluent API to construct tools
124
- */
125
- export class ToolBuilder {
126
- private _name = '';
127
- private _description = '';
128
- private _parameters: ToolParameter[] = [];
129
- private _inputSchema: ToolInputSchema = { type: 'object', properties: {} };
130
- private _metadata: ToolMetadata = {};
131
- private _fn?: (params: Record<string, any>, ctx: ToolContext) => Promise<ToolResult>;
132
-
133
- name(n: string): this { this._name = n; return this; }
134
- description(d: string): this { this._description = d; return this; }
135
-
136
- param(p: ToolParameter): this {
137
- this._parameters.push(p);
138
- this._inputSchema.properties[p.name] = {
139
- type: p.type,
140
- description: p.description,
141
- default: p.default,
142
- enum: p.enum
143
- };
144
- return this;
145
- }
146
-
147
- stringParam(name: string, description: string, required = true, defaultVal?: string): this {
148
- return this.param({ name, type: 'string', description, required, default: defaultVal });
149
- }
150
-
151
- numberParam(name: string, description: string, required = true, defaultVal?: number): this {
152
- return this.param({ name, type: 'number', description, required, default: defaultVal });
153
- }
154
-
155
- booleanParam(name: string, description: string, required: boolean = false, defaultVal?: boolean): this {
156
- return this.param({ name, type: 'boolean', description, required, default: defaultVal });
157
- }
158
-
159
- required(...names: string[]): this {
160
- this._inputSchema.required = names;
161
- return this;
162
- }
163
-
164
- meta(m: ToolMetadata): this {
165
- this._metadata = { ...this._metadata, ...m };
166
- return this;
167
- }
168
-
169
- permissions(...perms: ('read' | 'write' | 'execute' | 'network')[]): this {
170
- this._metadata.permissions = perms;
171
- return this;
172
- }
173
-
174
- tags(...t: string[]): this {
175
- this._metadata.tags = t;
176
- return this;
177
- }
178
-
179
- handle(fn: (params: Record<string, any>, ctx: ToolContext) => Promise<ToolResult>): this {
180
- this._fn = fn;
181
- return this;
182
- }
183
-
184
- build(): Tool {
185
- if (!this._name || !this._fn) {
186
- throw new Error('Tool name and handler are required');
187
- }
188
- return {
189
- name: this._name,
190
- description: this._description,
191
- parameters: this._parameters,
192
- inputSchema: this._inputSchema,
193
- metadata: this._metadata,
194
- execute: this._fn
195
- };
196
- }
197
- }
198
-
199
- // ==================== Tool Registry Enhancement ====================
200
-
201
- export interface ToolResult {
202
- success: boolean;
203
- output?: string;
204
- error?: string;
205
- data?: any;
206
- }
207
-
208
- export interface Session {
209
- id: string;
210
- messages: ChatMessage[];
211
- createdAt: Date;
212
- lastActiveAt: Date;
213
- }
214
-
215
- export interface Config {
216
- model: string;
217
- apiKey: string;
218
- temperature: number;
219
- maxTokens: number;
220
- provider?: 'minimax' | 'openai' | 'siliconflow' | 'anthropic' | 'ollama' | 'custom' | 'gemini' | 'kimi' | 'deepseek' | 'ernie';
221
- baseUrl?: string;
222
- }
223
-
224
- // Provider configurations
225
- export const PROVIDERS = {
226
- minimax: {
227
- name: 'MiniMax',
228
- baseUrl: 'https://api.minimax.io/anthropic/v1',
229
- defaultModel: 'MiniMax-M2.5',
230
- envKeys: ['MINIMAX_API_KEY', 'OPENAI_API_KEY']
231
- },
232
- siliconflow: {
233
- name: 'SiliconFlow (硅基流动)',
234
- baseUrl: 'https://api.siliconflow.cn/v1',
235
- defaultModel: 'Qwen/Qwen2.5-7B-Instruct',
236
- envKeys: ['SILICONFLOW_API_KEY', 'OPENAI_API_KEY']
237
- },
238
- openai: {
239
- name: 'OpenAI',
240
- baseUrl: 'https://api.openai.com/v1',
241
- defaultModel: 'gpt-4o-mini',
242
- envKeys: ['OPENAI_API_KEY']
243
- },
244
- anthropic: {
245
- name: 'Anthropic',
246
- baseUrl: 'https://api.anthropic.com/v1',
247
- defaultModel: 'claude-3-haiku-20240307',
248
- envKeys: ['ANTHROPIC_API_KEY']
249
- },
250
- ollama: {
251
- name: 'Ollama (Local)',
252
- baseUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',
253
- defaultModel: 'llama2',
254
- envKeys: []
255
- },
256
- gemini: {
257
- name: 'Google Gemini',
258
- baseUrl: 'https://generativelanguage.googleapis.com/v1beta',
259
- defaultModel: 'gemini-1.5-flash',
260
- envKeys: ['GEMINI_API_KEY']
261
- },
262
- kimi: {
263
- name: 'Kimi (Moonshot AI)',
264
- baseUrl: 'https://api.moonshot.cn/v1',
265
- defaultModel: 'moonshot-v1-8k',
266
- envKeys: ['KIMI_API_KEY', 'MOONSHOT_API_KEY']
267
- },
268
- deepseek: {
269
- name: 'DeepSeek',
270
- baseUrl: 'https://api.deepseek.com/v1',
271
- defaultModel: 'deepseek-chat',
272
- envKeys: ['DEEPSEEK_API_KEY']
273
- },
274
- ernie: {
275
- name: 'Baidu ERNIE (文心一言)',
276
- baseUrl: 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1',
277
- defaultModel: 'ernie-4.0-8k',
278
- envKeys: ['ERNIE_API_KEY', 'BAIDU_API_KEY']
279
- }
280
- } as const;