thatgfsj-code 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/cmd/index.js +1 -1
  2. package/dist/config/index.d.ts +5 -1
  3. package/dist/config/index.d.ts.map +1 -1
  4. package/dist/config/index.js +22 -4
  5. package/dist/config/index.js.map +1 -1
  6. package/dist/config/providers.d.ts +5 -10
  7. package/dist/config/providers.d.ts.map +1 -1
  8. package/dist/config/providers.js +152 -78
  9. package/dist/config/providers.js.map +1 -1
  10. package/dist/config/types.d.ts +1 -1
  11. package/dist/config/types.d.ts.map +1 -1
  12. package/dist/llm/anthropic.d.ts +34 -3
  13. package/dist/llm/anthropic.d.ts.map +1 -1
  14. package/dist/llm/anthropic.js +83 -35
  15. package/dist/llm/anthropic.js.map +1 -1
  16. package/dist/llm/gemini.d.ts +14 -1
  17. package/dist/llm/gemini.d.ts.map +1 -1
  18. package/dist/llm/gemini.js +56 -23
  19. package/dist/llm/gemini.js.map +1 -1
  20. package/dist/llm/index.d.ts +9 -8
  21. package/dist/llm/index.d.ts.map +1 -1
  22. package/dist/llm/index.js +75 -80
  23. package/dist/llm/index.js.map +1 -1
  24. package/dist/llm/openai.d.ts +30 -3
  25. package/dist/llm/openai.d.ts.map +1 -1
  26. package/dist/llm/openai.js +45 -28
  27. package/dist/llm/openai.js.map +1 -1
  28. package/dist/tui/output.js +1 -1
  29. package/dist/tui/welcome.d.ts +5 -1
  30. package/dist/tui/welcome.d.ts.map +1 -1
  31. package/dist/tui/welcome.js +75 -29
  32. package/dist/tui/welcome.js.map +1 -1
  33. package/package.json +1 -1
  34. package/src/cmd/index.ts +1 -1
  35. package/src/config/index.ts +21 -4
  36. package/src/config/providers.ts +153 -79
  37. package/src/config/types.ts +11 -5
  38. package/src/llm/anthropic.ts +90 -39
  39. package/src/llm/gemini.ts +65 -30
  40. package/src/llm/index.ts +77 -87
  41. package/src/llm/openai.ts +46 -34
  42. package/src/tui/output.ts +1 -1
  43. package/src/tui/welcome.ts +86 -32
package/dist/llm/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * LLM Service - Factory for creating providers
3
- * Replaces the monolithic AIEngine with a clean provider abstraction
3
+ * Supports all providers + custom relay stations (中转站)
4
4
  */
5
5
  import chalk from 'chalk';
6
6
  import { PROVIDERS } from '../config/providers.js';
@@ -10,8 +10,10 @@ import { GeminiProvider } from './gemini.js';
10
10
  export class LLMService {
11
11
  provider;
12
12
  tools = new Map();
13
- constructor(provider) {
13
+ apiKey;
14
+ constructor(provider, apiKey) {
14
15
  this.provider = provider;
16
+ this.apiKey = apiKey;
15
17
  }
16
18
  /**
17
19
  * Create LLMService from AIConfig
@@ -38,7 +40,7 @@ export class LLMService {
38
40
  default:
39
41
  provider = new OpenAIProvider(providerCfg);
40
42
  }
41
- return new LLMService(provider);
43
+ return new LLMService(provider, providerCfg.apiKey);
42
44
  }
43
45
  /**
44
46
  * Register tools for function calling
@@ -54,12 +56,18 @@ export class LLMService {
54
56
  getProviderName() {
55
57
  return this.provider.name;
56
58
  }
59
+ /**
60
+ * Check if API key is available
61
+ */
62
+ hasApiKey() {
63
+ return !!this.apiKey;
64
+ }
57
65
  /**
58
66
  * Non-streaming chat
59
67
  */
60
68
  async chat(messages, options) {
61
69
  if (!this.hasApiKey()) {
62
- return this.getMockResponse(messages);
70
+ throw new Error(this.getNoKeyMessage());
63
71
  }
64
72
  return this.provider.chat(messages, options);
65
73
  }
@@ -68,104 +76,91 @@ export class LLMService {
68
76
  */
69
77
  async *chatStream(messages, options) {
70
78
  if (!this.hasApiKey()) {
71
- const mock = this.getMockResponse(messages);
72
- for (const char of mock.content) {
73
- await new Promise(r => setTimeout(r, 10));
74
- yield char;
75
- }
76
- return mock;
79
+ throw new Error(this.getNoKeyMessage());
77
80
  }
78
81
  const maxIterations = options?.maxIterations ?? 10;
79
82
  let currentMessages = [...messages];
80
83
  let iterations = 0;
81
84
  while (iterations < maxIterations) {
82
85
  iterations++;
83
- // Get tools in provider format
84
- const toolsArray = [...this.tools.values()];
85
- const providerTools = toolsArray.length > 0 ? this.provider.buildTools(toolsArray) : [];
86
86
  // Stream the response
87
87
  let fullContent = '';
88
- const streamOptions = { ...options };
89
- // Add tools to the request if available
90
- if (providerTools.length > 0) {
91
- // We need to pass tools differently depending on provider
92
- // For now, inject into messages context
93
- }
94
- for await (const chunk of this.provider.chatStream(currentMessages, streamOptions)) {
88
+ for await (const chunk of this.provider.chatStream(currentMessages, options)) {
95
89
  fullContent += chunk;
96
90
  yield chunk;
97
91
  }
98
- // Check for tool calls in the response
99
- const response = await this.provider.chat(currentMessages, { ...streamOptions, stream: false });
100
- const toolCalls = response.tool_calls;
101
- if (toolCalls && toolCalls.length > 0) {
102
- // Append assistant message with tool calls
103
- currentMessages.push({
104
- role: 'assistant',
105
- content: fullContent,
106
- tool_calls: toolCalls,
107
- });
108
- // Execute each tool
109
- for (const toolCall of toolCalls) {
110
- const tool = this.tools.get(toolCall.function.name);
111
- if (!tool) {
92
+ // Check for tool calls by making a non-streaming request
93
+ // (streaming tool calls are complex, so we check after stream completes)
94
+ const toolsArray = [...this.tools.values()];
95
+ if (toolsArray.length > 0 && iterations < maxIterations) {
96
+ try {
97
+ const response = await this.provider.chat(currentMessages, options);
98
+ const toolCalls = response.tool_calls;
99
+ if (toolCalls && toolCalls.length > 0) {
112
100
  currentMessages.push({
113
- role: 'tool',
114
- content: `Tool "${toolCall.function.name}" not found`,
115
- tool_call_id: toolCall.id,
116
- name: toolCall.function.name,
101
+ role: 'assistant',
102
+ content: response.content || fullContent,
103
+ tool_calls: toolCalls,
117
104
  });
105
+ for (const toolCall of toolCalls) {
106
+ const tool = this.tools.get(toolCall.function.name);
107
+ if (!tool) {
108
+ currentMessages.push({
109
+ role: 'tool',
110
+ content: `Tool "${toolCall.function.name}" not found`,
111
+ tool_call_id: toolCall.id,
112
+ name: toolCall.function.name,
113
+ });
114
+ continue;
115
+ }
116
+ try {
117
+ const params = JSON.parse(toolCall.function.arguments || '{}');
118
+ const result = await tool.execute(params);
119
+ currentMessages.push({
120
+ role: 'tool',
121
+ content: result.success ? (result.output || JSON.stringify(result.data)) : (result.error || 'Tool failed'),
122
+ tool_call_id: toolCall.id,
123
+ name: toolCall.function.name,
124
+ });
125
+ yield `\n${chalk.gray(`[tool: ${toolCall.function.name}]`)}`;
126
+ }
127
+ catch (error) {
128
+ currentMessages.push({
129
+ role: 'tool',
130
+ content: `Tool execution error: ${error.message}`,
131
+ tool_call_id: toolCall.id,
132
+ name: toolCall.function.name,
133
+ });
134
+ }
135
+ }
118
136
  continue;
119
137
  }
120
- try {
121
- const params = JSON.parse(toolCall.function.arguments || '{}');
122
- const result = await tool.execute(params);
123
- currentMessages.push({
124
- role: 'tool',
125
- content: result.success ? (result.output || JSON.stringify(result.data)) : (result.error || 'Tool failed'),
126
- tool_call_id: toolCall.id,
127
- name: toolCall.function.name,
128
- });
129
- yield `\n${chalk.gray(`[tool: ${toolCall.function.name}]`)}`;
130
- }
131
- catch (error) {
132
- currentMessages.push({
133
- role: 'tool',
134
- content: `Tool execution error: ${error.message}`,
135
- tool_call_id: toolCall.id,
136
- name: toolCall.function.name,
137
- });
138
- }
139
138
  }
140
- continue; // Loop back for next iteration
139
+ catch {
140
+ // If the non-streaming check fails, just return the streamed content
141
+ }
141
142
  }
142
- // No tool calls - we're done
143
- return response;
143
+ return { content: fullContent, role: 'assistant' };
144
144
  }
145
145
  return { content: '[Agent loop exceeded maximum iterations]', role: 'assistant' };
146
146
  }
147
147
  /**
148
- * Check if API key is available
149
- */
150
- hasApiKey() {
151
- return !!this.provider.config?.apiKey;
152
- }
153
- /**
154
- * Mock response when no API key is set
148
+ * Error message when no API key is configured
155
149
  */
156
- getMockResponse(messages) {
157
- const last = messages[messages.length - 1]?.content || '';
158
- let content;
159
- if (/^(hi|hello|hey)/i.test(last)) {
160
- content = 'Hi there! How can I help you today?';
161
- }
162
- else if (last.toLowerCase().includes('who are you')) {
163
- content = 'I am Thatgfsj Code, an AI coding assistant.';
164
- }
165
- else {
166
- content = `I understand you said: "${last.slice(0, 50)}..."\n\nThis is a demo response. Configure an API key for full AI capabilities.\nRun: gfcode init`;
167
- }
168
- return { content, role: 'assistant' };
150
+ getNoKeyMessage() {
151
+ return [
152
+ '❌ 未配置 API Key,无法调用 AI。',
153
+ '',
154
+ '请先运行以下命令配置:',
155
+ ' gfcode init',
156
+ '',
157
+ '或手动设置环境变量:',
158
+ ' export SILICONFLOW_API_KEY="sk-..." # 硅基流动',
159
+ ' export OPENAI_API_KEY="sk-..." # OpenAI',
160
+ ' export DEEPSEEK_API_KEY="sk-..." # DeepSeek',
161
+ ' export KIMI_API_KEY="sk-..." # Kimi',
162
+ ' export ANTHROPIC_API_KEY="sk-ant-..." # Claude',
163
+ ].join('\n');
169
164
  }
170
165
  }
171
166
  export { OpenAIProvider } from './openai.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"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"}
@@ -1,17 +1,44 @@
1
1
  /**
2
2
  * OpenAI-compatible Provider
3
- * Works with: OpenAI, SiliconFlow, MiniMax (OpenAI mode), DeepSeek, Kimi, ERNIE, Ollama
3
+ * Works with: OpenAI, SiliconFlow, DeepSeek, Kimi, Zhipu, MiniMax, Baichuan, Stepfun, Doubao, Ollama, ERNIE
4
+ * Also works with any OpenAI-compatible relay station (中转站)
5
+ *
6
+ * API: POST {baseUrl}/chat/completions
7
+ * Auth: Authorization: Bearer {apiKey}
8
+ * Streaming: SSE with "data: {...}" lines, ends with "data: [DONE]"
4
9
  */
5
10
  import type { ChatMessage, ChatResponse, ChatOptions } from '../types.js';
6
11
  import type { Tool } from '../tools/types.js';
7
12
  import type { LLMProvider, ProviderConfig } from './provider.js';
8
13
  export declare class OpenAIProvider implements LLMProvider {
9
14
  readonly name = "openai";
10
- private config;
15
+ protected config: ProviderConfig;
11
16
  constructor(config: ProviderConfig);
12
17
  buildTools(tools: Tool[]): any[];
13
18
  chat(messages: ChatMessage[], options?: ChatOptions): Promise<ChatResponse>;
14
19
  chatStream(messages: ChatMessage[], options?: ChatOptions): AsyncGenerator<string, ChatResponse>;
15
- private buildRequest;
20
+ /**
21
+ * Build the request body for OpenAI-compatible API
22
+ */
23
+ protected buildRequest(messages: ChatMessage[], stream: boolean, options?: ChatOptions): {
24
+ stream_options?: {
25
+ include_usage: boolean;
26
+ } | undefined;
27
+ model: string;
28
+ messages: {
29
+ tool_calls?: import("../types.js").ToolCall[] | undefined;
30
+ tool_call_id?: string | undefined;
31
+ name?: string | undefined;
32
+ role: import("../types.js").Role;
33
+ content: string;
34
+ }[];
35
+ temperature: number;
36
+ max_tokens: number;
37
+ stream: boolean;
38
+ };
39
+ /**
40
+ * Execute the HTTP request
41
+ */
42
+ protected doRequest(body: any): Promise<Response>;
16
43
  }
17
44
  //# sourceMappingURL=openai.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/llm/openai.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEjE,qBAAa,cAAe,YAAW,WAAW;IAChD,QAAQ,CAAC,IAAI,YAAY;IACzB,OAAO,CAAC,MAAM,CAAiB;gBAEnB,MAAM,EAAE,cAAc;IAIlC,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,GAAG,EAAE;IAiB1B,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IA4B1E,UAAU,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,cAAc,CAAC,MAAM,EAAE,YAAY,CAAC;IAsDvG,OAAO,CAAC,YAAY;CAerB"}
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/llm/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEjE,qBAAa,cAAe,YAAW,WAAW;IAChD,QAAQ,CAAC,IAAI,YAAY;IACzB,SAAS,CAAC,MAAM,EAAE,cAAc,CAAC;gBAErB,MAAM,EAAE,cAAc;IAIlC,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,GAAG,EAAE;IAiB1B,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAkB1E,UAAU,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,cAAc,CAAC,MAAM,EAAE,YAAY,CAAC;IAoDvG;;OAEG;IACH,SAAS,CAAC,YAAY,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,WAAW;;;;;;;;;;;;;;;;IAiBtF;;OAEG;cACa,SAAS,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;CAWxD"}
@@ -1,6 +1,11 @@
1
1
  /**
2
2
  * OpenAI-compatible Provider
3
- * Works with: OpenAI, SiliconFlow, MiniMax (OpenAI mode), DeepSeek, Kimi, ERNIE, Ollama
3
+ * Works with: OpenAI, SiliconFlow, DeepSeek, Kimi, Zhipu, MiniMax, Baichuan, Stepfun, Doubao, Ollama, ERNIE
4
+ * Also works with any OpenAI-compatible relay station (中转站)
5
+ *
6
+ * API: POST {baseUrl}/chat/completions
7
+ * Auth: Authorization: Bearer {apiKey}
8
+ * Streaming: SSE with "data: {...}" lines, ends with "data: [DONE]"
4
9
  */
5
10
  export class OpenAIProvider {
6
11
  name = 'openai';
@@ -24,40 +29,26 @@ export class OpenAIProvider {
24
29
  }
25
30
  async chat(messages, options) {
26
31
  const body = this.buildRequest(messages, false, options);
27
- const response = await fetch(`${this.config.baseUrl}/chat/completions`, {
28
- method: 'POST',
29
- headers: {
30
- 'Content-Type': 'application/json',
31
- 'Authorization': `Bearer ${this.config.apiKey}`,
32
- },
33
- body: JSON.stringify(body),
34
- });
35
- if (!response.ok) {
36
- const text = await response.text().catch(() => '');
37
- throw new Error(`OpenAI API error ${response.status}: ${text}`);
38
- }
32
+ const response = await this.doRequest(body);
39
33
  const data = await response.json();
40
34
  const choice = data.choices?.[0];
41
35
  return {
42
36
  content: choice?.message?.content || '',
43
37
  role: 'assistant',
44
- usage: data.usage,
38
+ usage: data.usage ? {
39
+ prompt_tokens: data.usage.prompt_tokens || 0,
40
+ completion_tokens: data.usage.completion_tokens || 0,
41
+ total_tokens: data.usage.total_tokens || 0,
42
+ } : undefined,
45
43
  tool_calls: choice?.message?.tool_calls,
46
44
  };
47
45
  }
48
46
  async *chatStream(messages, options) {
49
47
  const body = this.buildRequest(messages, true, options);
50
- const response = await fetch(`${this.config.baseUrl}/chat/completions`, {
51
- method: 'POST',
52
- headers: {
53
- 'Content-Type': 'application/json',
54
- 'Authorization': `Bearer ${this.config.apiKey}`,
55
- },
56
- body: JSON.stringify(body),
57
- });
48
+ const response = await this.doRequest(body);
58
49
  if (!response.ok || !response.body) {
59
50
  const text = await response.text().catch(() => '');
60
- throw new Error(`OpenAI API error ${response.status}: ${text}`);
51
+ throw new Error(`API error ${response.status}: ${text}`);
61
52
  }
62
53
  const reader = response.body.getReader();
63
54
  const decoder = new TextDecoder();
@@ -73,14 +64,22 @@ export class OpenAIProvider {
73
64
  buffer = lines.pop() || '';
74
65
  for (const line of lines) {
75
66
  const trimmed = line.trim();
76
- if (!trimmed || !trimmed.startsWith('data: ') || trimmed === 'data: [DONE]')
67
+ if (!trimmed)
68
+ continue;
69
+ if (trimmed === 'data: [DONE]')
70
+ continue;
71
+ if (!trimmed.startsWith('data: '))
77
72
  continue;
78
73
  try {
79
74
  const data = JSON.parse(trimmed.slice(6));
80
- const content = data.choices?.[0]?.delta?.content;
81
- if (content) {
82
- fullContent += content;
83
- yield content;
75
+ const delta = data.choices?.[0]?.delta;
76
+ if (delta?.content) {
77
+ fullContent += delta.content;
78
+ yield delta.content;
79
+ }
80
+ // Handle tool calls in streaming
81
+ if (delta?.tool_calls) {
82
+ // Store tool calls for final response
84
83
  }
85
84
  }
86
85
  catch {
@@ -94,6 +93,9 @@ export class OpenAIProvider {
94
93
  }
95
94
  return { content: fullContent, role: 'assistant' };
96
95
  }
96
+ /**
97
+ * Build the request body for OpenAI-compatible API
98
+ */
97
99
  buildRequest(messages, stream, options) {
98
100
  return {
99
101
  model: this.config.model,
@@ -107,7 +109,22 @@ export class OpenAIProvider {
107
109
  temperature: options?.temperature ?? this.config.temperature,
108
110
  max_tokens: options?.maxTokens ?? this.config.maxTokens,
109
111
  stream,
112
+ ...(stream && { stream_options: { include_usage: true } }),
110
113
  };
111
114
  }
115
+ /**
116
+ * Execute the HTTP request
117
+ */
118
+ async doRequest(body) {
119
+ const url = `${this.config.baseUrl}/chat/completions`;
120
+ return fetch(url, {
121
+ method: 'POST',
122
+ headers: {
123
+ 'Content-Type': 'application/json',
124
+ 'Authorization': `Bearer ${this.config.apiKey}`,
125
+ },
126
+ body: JSON.stringify(body),
127
+ });
128
+ }
112
129
  }
113
130
  //# sourceMappingURL=openai.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/llm/openai.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/llm/openai.ts"],"names":[],"mappings":"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"}
@@ -47,7 +47,7 @@ export class REPLOutput {
47
47
  printBanner() {
48
48
  console.log(chalk.cyan(`
49
49
  ╔═══════════════════════════════════════╗
50
- ║ 🤖 Thatgfsj Code v0.3.0 ║
50
+ ║ 🤖 Thatgfsj Code v0.4.0 ║
51
51
  ║ AI Coding Assistant ║
52
52
  ╚═══════════════════════════════════════╝
53
53
  `));
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Welcome / Setup Wizard
3
- * Migrated and simplified from old src/repl/welcome.ts
3
+ * Supports all providers + custom relay stations (中转站)
4
4
  */
5
5
  export declare class WelcomeScreen {
6
6
  /**
@@ -11,5 +11,9 @@ export declare class WelcomeScreen {
11
11
  * Interactive setup wizard
12
12
  */
13
13
  static interactiveSetup(): Promise<void>;
14
+ /**
15
+ * Save config to file
16
+ */
17
+ private static saveConfig;
14
18
  }
15
19
  //# sourceMappingURL=welcome.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"welcome.d.ts","sourceRoot":"","sources":["../../src/tui/welcome.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,qBAAa,aAAa;IACxB;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAarC;;OAEG;WACU,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;CAmE/C"}
1
+ {"version":3,"file":"welcome.d.ts","sourceRoot":"","sources":["../../src/tui/welcome.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,qBAAa,aAAa;IACxB;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAarC;;OAEG;WACU,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IA0F9C;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;CA4B1B"}
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * Welcome / Setup Wizard
3
- * Migrated and simplified from old src/repl/welcome.ts
3
+ * Supports all providers + custom relay stations (中转站)
4
4
  */
5
5
  import chalk from 'chalk';
6
6
  import readline from 'readline';
7
7
  import { existsSync, mkdirSync, writeFileSync } from 'fs';
8
8
  import { join } from 'path';
9
9
  import { homedir } from 'os';
10
- import { PROVIDERS, getModelsForProvider, listProviders } from '../config/providers.js';
10
+ import { getModelsForProvider, listProviders, isCustomProvider } from '../config/providers.js';
11
11
  export class WelcomeScreen {
12
12
  /**
13
13
  * Show welcome if no API key is configured
@@ -20,7 +20,7 @@ export class WelcomeScreen {
20
20
  console.log(chalk.cyan('|') + chalk.yellow(' 快速开始指南').padEnd(w) + chalk.cyan('|'));
21
21
  console.log(chalk.cyan('|') + ' '.repeat(w) + chalk.cyan('|'));
22
22
  console.log(chalk.cyan('|') + chalk.gray(' 运行 gfcode init 配置你的 API Key').padEnd(w) + chalk.cyan('|'));
23
- console.log(chalk.cyan('|') + chalk.gray(' 或设置环境变量: OPENAI_API_KEY, SILICONFLOW_API_KEY ').padEnd(w) + chalk.cyan('|'));
23
+ console.log(chalk.cyan('|') + chalk.gray(' 支持: OpenAI / Claude / DeepSeek / Kimi / 智谱 / 中转站').padEnd(w) + chalk.cyan('|'));
24
24
  console.log(chalk.cyan('+') + '-'.repeat(w) + '+');
25
25
  console.log();
26
26
  }
@@ -40,47 +40,93 @@ export class WelcomeScreen {
40
40
  console.log(chalk.white(' 步骤 1/3: 选择 AI 提供商\n'));
41
41
  const providers = listProviders();
42
42
  providers.forEach((p, i) => {
43
- console.log(chalk.green(` ${i + 1}. ${p.name}`));
43
+ const num = (i + 1).toString().padStart(2);
44
+ console.log(chalk.green(` ${num}. ${p.name}`));
44
45
  });
45
46
  console.log();
46
47
  const choice = await question(chalk.green(' 请选择 (1-' + providers.length + '): '));
47
48
  const selected = providers[parseInt(choice) - 1] || providers[0];
48
49
  const providerName = selected.key;
49
- // Step 2: Enter API Key
50
- console.log(chalk.white('\n 步骤 2/3: 输入 API Key\n'));
51
- console.log(chalk.gray(` 获取地址: ${PROVIDERS[providerName].baseUrl.replace('/v1', '').replace('/v1beta', '')}`));
50
+ // Step 2: Enter API Key (and base URL for custom providers)
51
+ console.log(chalk.white('\n 步骤 2/3: 配置连接信息\n'));
52
+ let baseUrl;
53
+ if (isCustomProvider(providerName)) {
54
+ // Custom provider needs base URL
55
+ console.log(chalk.yellow(' 自定义 Provider (中转站) 模式'));
56
+ console.log(chalk.gray(' 支持 OpenAI 兼容 或 Anthropic 兼容 的中转站'));
57
+ console.log();
58
+ baseUrl = await question(chalk.green(' 请输入中转站 Base URL: '));
59
+ if (!baseUrl) {
60
+ console.log(chalk.red(' ❌ 中转站必须提供 Base URL'));
61
+ rl.close();
62
+ return;
63
+ }
64
+ // Remove trailing slash
65
+ baseUrl = baseUrl.replace(/\/+$/, '');
66
+ // Remove /v1 suffix if present (we'll add it in the provider)
67
+ // Actually keep it as-is since the user knows their endpoint
68
+ }
52
69
  const apiKey = await question(chalk.green(' 请输入 API Key: '));
53
70
  // Step 3: Choose model
54
71
  console.log(chalk.white('\n 步骤 3/3: 选择模型\n'));
55
- const models = getModelsForProvider(providerName);
56
- models.forEach((m, i) => {
57
- console.log(chalk.green(` ${i + 1}. ${m.name}`) + chalk.gray(` - ${m.desc}`));
58
- });
59
- console.log();
60
- const modelChoice = await question(chalk.green(' 请选择模型 (1-' + models.length + '): '));
61
- const selectedModel = models[parseInt(modelChoice) - 1] || models[0];
62
- // Save config
63
- const configDir = join(homedir(), '.thatgfsj');
64
- const configPath = join(configDir, 'config.json');
65
- if (!existsSync(configDir)) {
66
- mkdirSync(configDir, { recursive: true });
72
+ if (isCustomProvider(providerName)) {
73
+ // Custom provider: let user type model name
74
+ console.log(chalk.gray(' 输入中转站支持的模型名称'));
75
+ console.log(chalk.gray(' 例如: gpt-4o-mini, claude-sonnet-4-20250514, deepseek-chat'));
76
+ const model = await question(chalk.green(' 模型名称: '));
77
+ if (!model) {
78
+ console.log(chalk.red(' ❌ 必须指定模型'));
79
+ rl.close();
80
+ return;
81
+ }
82
+ // Save config
83
+ this.saveConfig(providerName, model, apiKey, baseUrl);
84
+ }
85
+ else {
86
+ // Standard provider: show model list
87
+ const models = getModelsForProvider(providerName);
88
+ models.forEach((m, i) => {
89
+ const num = (i + 1).toString().padStart(2);
90
+ console.log(chalk.green(` ${num}. ${m.name}`) + chalk.gray(` - ${m.desc}`));
91
+ });
92
+ console.log();
93
+ const modelChoice = await question(chalk.green(' 请选择模型 (1-' + models.length + '): '));
94
+ const selectedModel = models[parseInt(modelChoice) - 1] || models[0];
95
+ this.saveConfig(providerName, selectedModel.id, apiKey, baseUrl);
67
96
  }
68
- writeFileSync(configPath, JSON.stringify({
69
- provider: providerName,
70
- model: selectedModel.id,
71
- apiKey,
72
- temperature: 0.7,
73
- maxTokens: 4096,
74
- }, null, 2));
75
97
  console.log(chalk.green('\n ✅ 配置已保存!'));
76
- console.log(chalk.gray(` 提供商: ${providerName}`));
77
- console.log(chalk.gray(` 模型: ${selectedModel.name}`));
78
- console.log(chalk.gray(` 配置文件: ${configPath}`));
98
+ console.log(chalk.gray(` 配置文件: ${join(homedir(), '.thatgfsj', 'config.json')}`));
79
99
  console.log(chalk.cyan('\n 运行 gfcode 开始使用\n'));
80
100
  }
81
101
  finally {
82
102
  rl.close();
83
103
  }
84
104
  }
105
+ /**
106
+ * Save config to file
107
+ */
108
+ static saveConfig(provider, model, apiKey, baseUrl) {
109
+ const configDir = join(homedir(), '.thatgfsj');
110
+ const configPath = join(configDir, 'config.json');
111
+ if (!existsSync(configDir)) {
112
+ mkdirSync(configDir, { recursive: true });
113
+ }
114
+ const config = {
115
+ provider,
116
+ model,
117
+ apiKey,
118
+ temperature: 0.7,
119
+ maxTokens: 4096,
120
+ };
121
+ if (baseUrl) {
122
+ config.baseUrl = baseUrl;
123
+ }
124
+ writeFileSync(configPath, JSON.stringify(config, null, 2));
125
+ console.log(chalk.gray(` 提供商: ${provider}`));
126
+ console.log(chalk.gray(` 模型: ${model}`));
127
+ if (baseUrl) {
128
+ console.log(chalk.gray(` Base URL: ${baseUrl}`));
129
+ }
130
+ }
85
131
  }
86
132
  //# sourceMappingURL=welcome.js.map