thatgfsj-code 0.4.1 → 0.5.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.
package/dist/tui/repl.js CHANGED
@@ -87,50 +87,64 @@ export class REPL {
87
87
  let fullResponse = '';
88
88
  let hasStartedOutput = false;
89
89
  try {
90
- const stream = this.app.getAgent().run(this.app.session.getMessages());
90
+ const stream = this.app.streamResponse();
91
91
  for await (const chunk of stream) {
92
92
  this.output.stopThinking();
93
- const parts = chunk.split('\n');
94
- for (const part of parts) {
95
- // Tool message: @@TOOL@@{json}
96
- if (part.startsWith('@@TOOL@@')) {
97
- try {
98
- const data = JSON.parse(part.slice(8));
99
- if (data.action === 'call') {
100
- if (hasStartedOutput) {
101
- this.output.endAssistant();
102
- hasStartedOutput = false;
93
+ // Check for structured tool messages
94
+ if (chunk.includes('@@TOOL@@')) {
95
+ const parts = chunk.split('\n');
96
+ for (const part of parts) {
97
+ if (part.startsWith('@@TOOL@@')) {
98
+ try {
99
+ const data = JSON.parse(part.slice(8));
100
+ if (data.action === 'call') {
101
+ if (hasStartedOutput) {
102
+ this.output.endAssistant();
103
+ hasStartedOutput = false;
104
+ }
105
+ this.output.printToolCall(data.name, data.args || '');
106
+ this.output.startExecuting(data.name);
107
+ }
108
+ else if (data.action === 'result') {
109
+ this.output.stopThinking();
110
+ this.output.printToolResult(data.output || data.error || '', !!data.error);
111
+ this.output.printToolEnd();
103
112
  }
104
- this.output.printToolCall(data.name, data.args || '');
105
- // Show executing state
106
- this.output.startExecuting(data.name);
107
113
  }
108
- else if (data.action === 'result') {
109
- this.output.stopThinking();
110
- this.output.printToolResult(data.output || data.error || '', !!data.error);
111
- this.output.printToolEnd();
114
+ catch {
115
+ // If parse fails, treat as regular text
116
+ if (part) {
117
+ if (!hasStartedOutput) {
118
+ this.output.beginAssistant();
119
+ hasStartedOutput = true;
120
+ }
121
+ this.output.writeChunk(part);
122
+ }
112
123
  }
113
124
  }
114
- catch {
125
+ else if (part) {
126
+ // Regular text between tool messages
127
+ if (!hasStartedOutput) {
128
+ this.output.beginAssistant();
129
+ hasStartedOutput = true;
130
+ }
115
131
  this.output.writeChunk(part + '\n');
116
132
  }
117
- continue;
118
133
  }
119
- // Regular text
120
- if (part) {
121
- if (!hasStartedOutput) {
122
- this.output.beginAssistant();
123
- hasStartedOutput = true;
124
- }
125
- this.output.writeChunk(part + '\n');
134
+ }
135
+ else {
136
+ // Pure text chunk - just output it
137
+ if (!hasStartedOutput) {
138
+ this.output.beginAssistant();
139
+ hasStartedOutput = true;
126
140
  }
141
+ this.output.writeChunk(chunk);
127
142
  }
128
143
  fullResponse += chunk;
129
144
  }
130
145
  if (hasStartedOutput) {
131
146
  this.output.endAssistant();
132
147
  }
133
- // Don't save empty responses
134
148
  if (fullResponse.trim()) {
135
149
  this.app.session.addMessage('assistant', fullResponse);
136
150
  this.app.session.truncate();
@@ -1 +1 @@
1
- {"version":3,"file":"repl.js","sourceRoot":"","sources":["../../src/tui/repl.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"repl.js","sourceRoot":"","sources":["../../src/tui/repl.ts"],"names":[],"mappings":"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"}
@@ -13,7 +13,7 @@ export class WelcomeScreen {
13
13
  if (hasApiKey)
14
14
  return;
15
15
  console.log();
16
- console.log(chalk.cyan.bold(' ⚡ Thatgfsj Code') + chalk.gray(' v0.4.1'));
16
+ console.log(chalk.cyan.bold(' ⚡ Thatgfsj Code') + chalk.gray(' v0.5.0'));
17
17
  console.log(chalk.gray(' AI Coding Assistant'));
18
18
  console.log(line);
19
19
  console.log();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thatgfsj-code",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "Thatgfsj Code - AI Coding Assistant",
5
5
  "main": "dist/cmd/index.js",
6
6
  "type": "module",
package/src/app/index.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * App - Core application singleton
3
- * Assembles all services: config, LLM, session, tools, hooks, prompts
4
- * Replaces the scattered initialization in old src/index.ts
3
+ * Simplified: directly uses LLMService (which has built-in agent loop)
5
4
  */
6
5
 
7
6
  import { ConfigManager } from '../config/index.js';
@@ -10,8 +9,7 @@ import { SessionManager } from '../session/index.js';
10
9
  import { ToolRegistry } from '../tools/index.js';
11
10
  import { HookManager } from '../hooks/index.js';
12
11
  import { SystemPromptBuilder } from '../prompts/index.js';
13
- import { Agent } from './agent.js';
14
- import type { ChatMessage } from '../types.js';
12
+ import type { ChatMessage, ChatResponse } from '../types.js';
15
13
 
16
14
  export class App {
17
15
  config: ConfigManager;
@@ -20,7 +18,6 @@ export class App {
20
18
  tools: ToolRegistry;
21
19
  hooks: HookManager;
22
20
  prompts: SystemPromptBuilder;
23
- private agent: Agent;
24
21
 
25
22
  private constructor(
26
23
  config: ConfigManager,
@@ -29,7 +26,6 @@ export class App {
29
26
  tools: ToolRegistry,
30
27
  hooks: HookManager,
31
28
  prompts: SystemPromptBuilder,
32
- agent: Agent,
33
29
  ) {
34
30
  this.config = config;
35
31
  this.llm = llm;
@@ -37,18 +33,12 @@ export class App {
37
33
  this.tools = tools;
38
34
  this.hooks = hooks;
39
35
  this.prompts = prompts;
40
- this.agent = agent;
41
36
  }
42
37
 
43
- /**
44
- * Create and initialize the App
45
- */
46
38
  static async create(): Promise<App> {
47
- // Load config
48
39
  const config = await ConfigManager.load();
49
40
  const aiConfig = config.getAIConfig();
50
41
 
51
- // Create services
52
42
  const llm = LLMService.fromConfig(aiConfig);
53
43
  const session = new SessionManager();
54
44
  const tools = new ToolRegistry();
@@ -59,13 +49,24 @@ export class App {
59
49
  permissionMode: 'ask',
60
50
  });
61
51
 
62
- // Create agent
63
- const agent = new Agent(llm, tools, { hooks, maxIterations: 10 });
52
+ // Register tools with LLM service
53
+ llm.registerTools(tools.list());
64
54
 
65
55
  // Set up system prompt
66
56
  session.addMessage('system', prompts.build());
67
57
 
68
- return new App(config, llm, session, tools, hooks, prompts, agent);
58
+ return new App(config, llm, session, tools, hooks, prompts);
59
+ }
60
+
61
+ /**
62
+ * Stream a response for the current session messages.
63
+ * The LLMService handles the full agent loop internally.
64
+ */
65
+ async *streamResponse(messages?: ChatMessage[]): AsyncGenerator<string, void> {
66
+ const msgs = messages || this.session.getMessages();
67
+ for await (const chunk of this.llm.chatStream(msgs)) {
68
+ yield chunk;
69
+ }
69
70
  }
70
71
 
71
72
  /**
@@ -75,27 +76,21 @@ export class App {
75
76
  this.session.addMessage('user', prompt);
76
77
 
77
78
  let fullResponse = '';
78
- for await (const chunk of this.agent.run(this.session.getMessages())) {
79
- process.stdout.write(chunk);
80
- fullResponse += chunk;
79
+ try {
80
+ for await (const chunk of this.streamResponse()) {
81
+ process.stdout.write(chunk);
82
+ fullResponse += chunk;
83
+ }
84
+ } catch (err) {
85
+ // Re-throw after saving partial response
86
+ if (fullResponse) {
87
+ this.session.addMessage('assistant', fullResponse);
88
+ }
89
+ throw err;
81
90
  }
82
91
 
83
- console.log(); // newline
92
+ console.log();
84
93
  this.session.addMessage('assistant', fullResponse);
85
94
  return fullResponse;
86
95
  }
87
-
88
- /**
89
- * Get the agent for streaming control
90
- */
91
- getAgent(): Agent {
92
- return this.agent;
93
- }
94
-
95
- /**
96
- * Get current config
97
- */
98
- getConfig(): ConfigManager {
99
- return this.config;
100
- }
101
96
  }
package/src/cmd/index.ts CHANGED
@@ -40,7 +40,7 @@ process.on('unhandledRejection', (reason) => {
40
40
  program
41
41
  .name('gfcode')
42
42
  .description('🤖 Thatgfsj Code - AI Coding Assistant')
43
- .version('0.4.1')
43
+ .version('0.5.0')
44
44
  .argument('[prompt]', 'Task to execute (omit to start interactive mode)')
45
45
  .option('-m, --model <model>', 'Specify model')
46
46
  .option('-i, --interactive', 'Force interactive mode')
@@ -82,32 +82,36 @@ program
82
82
  let hasStarted = false;
83
83
 
84
84
  try {
85
- const stream = app.getAgent().run(app.session.getMessages());
85
+ const stream = app.streamResponse();
86
86
  for await (const chunk of stream) {
87
87
  out.stopThinking();
88
88
 
89
- const parts = chunk.split('\n');
90
- for (const part of parts) {
91
- if (part.startsWith('@@TOOL@@')) {
92
- try {
93
- const data = JSON.parse(part.slice(8));
94
- if (data.action === 'call') {
95
- if (hasStarted) { out.endAssistant(); hasStarted = false; }
96
- out.printToolCall(data.name, data.args || '');
97
- out.startExecuting(data.name);
98
- } else if (data.action === 'result') {
99
- out.stopThinking();
100
- out.printToolResult(data.output || data.error || '', !!data.error);
101
- out.printToolEnd();
102
- }
103
- } catch {}
104
- continue;
105
- }
106
- if (part) {
107
- if (!hasStarted) { out.beginAssistant(); hasStarted = true; }
108
- out.writeChunk(part + '\n');
89
+ if (chunk.includes('@@TOOL@@')) {
90
+ const parts = chunk.split('\n');
91
+ for (const part of parts) {
92
+ if (part.startsWith('@@TOOL@@')) {
93
+ try {
94
+ const data = JSON.parse(part.slice(8));
95
+ if (data.action === 'call') {
96
+ if (hasStarted) { out.endAssistant(); hasStarted = false; }
97
+ out.printToolCall(data.name, data.args || '');
98
+ out.startExecuting(data.name);
99
+ } else if (data.action === 'result') {
100
+ out.stopThinking();
101
+ out.printToolResult(data.output || data.error || '', !!data.error);
102
+ out.printToolEnd();
103
+ }
104
+ } catch {}
105
+ } else if (part) {
106
+ if (!hasStarted) { out.beginAssistant(); hasStarted = true; }
107
+ out.writeChunk(part + '\n');
108
+ }
109
109
  }
110
+ } else {
111
+ if (!hasStarted) { out.beginAssistant(); hasStarted = true; }
112
+ out.writeChunk(chunk);
110
113
  }
114
+
111
115
  fullResponse += chunk;
112
116
  }
113
117
  if (hasStarted) out.endAssistant();
package/src/llm/index.ts CHANGED
@@ -91,7 +91,6 @@ export class LLMService {
91
91
  let fullContent = '';
92
92
  let detectedToolCalls: ToolCall[] | undefined;
93
93
 
94
- // Stream the response, passing tools so the API knows about them
95
94
  const stream = this.provider.chatStream(currentMessages, options, hasTools ? toolsArray : undefined);
96
95
 
97
96
  for await (const chunk of stream) {
package/src/tui/output.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
- * REPL Output - Beautiful terminal UI
2
+ * REPL Output - Clean terminal UI
3
+ * Inspired by opencode: simple indentation for streaming, clean boundaries
3
4
  */
4
5
 
5
6
  import chalk from 'chalk';
@@ -7,14 +8,12 @@ import ora, { Ora } from 'ora';
7
8
 
8
9
  export class REPLOutput {
9
10
  private spinner: Ora | null = null;
10
- private inAssistantBlock = false;
11
- private currentLineHasContent = false;
12
11
 
13
12
  // ── Banner ──────────────────────────────────────────────
14
13
 
15
14
  printBanner(): void {
16
15
  console.log();
17
- console.log(chalk.cyan.bold(' ⚡ Thatgfsj Code') + chalk.gray(' v0.4.1'));
16
+ console.log(chalk.cyan.bold(' ⚡ Thatgfsj Code') + chalk.gray(' v0.5.0'));
18
17
  console.log(chalk.gray(' AI Coding Assistant'));
19
18
  console.log(chalk.gray(' ' + '─'.repeat(52)));
20
19
  console.log();
@@ -30,54 +29,54 @@ export class REPLOutput {
30
29
 
31
30
  printUserInput(input: string): void {
32
31
  console.log();
33
- console.log(chalk.gray(' ┌─ ') + chalk.bold('You'));
32
+ console.log(chalk.bold(' You'));
33
+ console.log(chalk.gray(' ' + '─'.repeat(40)));
34
34
  for (const line of input.split('\n')) {
35
- console.log(chalk.gray(' ') + line);
35
+ console.log(' ' + line);
36
36
  }
37
- console.log(chalk.gray(' └─'));
37
+ console.log();
38
38
  }
39
39
 
40
40
  // ── Assistant Streaming ─────────────────────────────────
41
41
 
42
+ /**
43
+ * Begin assistant response - just print the header
44
+ */
42
45
  beginAssistant(): void {
43
- if (this.inAssistantBlock) return;
44
- this.inAssistantBlock = true;
45
- this.currentLineHasContent = false;
46
- console.log();
47
- process.stdout.write(chalk.cyan(' ┌─ ') + chalk.bold('AI') + '\n' + chalk.cyan(' │ '));
46
+ console.log(chalk.bold(' AI'));
47
+ console.log(chalk.gray(' ' + '─'.repeat(40)));
48
48
  }
49
49
 
50
+ /**
51
+ * Write streaming chunk - output as-is with indent.
52
+ * The chunk already contains proper newlines from the AI.
53
+ */
50
54
  writeChunk(chunk: string): void {
51
- if (!this.inAssistantBlock) this.beginAssistant();
52
-
53
- for (const char of chunk) {
54
- if (char === '\n') {
55
- process.stdout.write('\n' + chalk.cyan(' │ '));
56
- this.currentLineHasContent = false;
57
- } else {
58
- process.stdout.write(char);
59
- this.currentLineHasContent = true;
55
+ // Indent each line by 2 spaces
56
+ const lines = chunk.split('\n');
57
+ for (let i = 0; i < lines.length; i++) {
58
+ if (lines[i]) {
59
+ process.stdout.write(' ' + lines[i]);
60
+ }
61
+ if (i < lines.length - 1) {
62
+ process.stdout.write('\n');
60
63
  }
61
64
  }
62
65
  }
63
66
 
67
+ /**
68
+ * End assistant response
69
+ */
64
70
  endAssistant(): void {
65
- if (!this.inAssistantBlock) return;
66
- if (this.currentLineHasContent) {
67
- process.stdout.write('\n');
68
- }
69
- process.stdout.write(chalk.cyan(' └─') + '\n\n');
70
- this.inAssistantBlock = false;
71
- this.currentLineHasContent = false;
71
+ process.stdout.write('\n');
72
+ console.log();
72
73
  }
73
74
 
74
75
  // ── Tool Calls ──────────────────────────────────────────
75
76
 
76
77
  printToolCall(name: string, args: string): void {
77
- if (this.inAssistantBlock) this.endAssistant();
78
-
79
78
  console.log();
80
- console.log(chalk.yellow(' ⚙ ') + chalk.bold(name) + chalk.gray(' ─────────────────────────'));
79
+ console.log(chalk.yellow(' ⚙ ') + chalk.bold(name));
81
80
 
82
81
  if (args) {
83
82
  try {
@@ -85,15 +84,15 @@ export class REPLOutput {
85
84
  for (const [key, val] of Object.entries(obj)) {
86
85
  let display: string;
87
86
  if (typeof val === 'string') {
88
- display = val.length > 120 ? val.slice(0, 120) + '...' : val;
87
+ display = val.length > 100 ? val.slice(0, 100) + '...' : val;
89
88
  } else {
90
89
  display = JSON.stringify(val);
91
- if (display.length > 120) display = display.slice(0, 120) + '...';
90
+ if (display.length > 100) display = display.slice(0, 100) + '...';
92
91
  }
93
- console.log(chalk.gray(' ' + key + ': ') + chalk.white(display));
92
+ console.log(chalk.gray(' ' + key + ': ') + display);
94
93
  }
95
94
  } catch {
96
- const display = args.length > 150 ? args.slice(0, 150) + '...' : args;
95
+ const display = args.length > 120 ? args.slice(0, 120) + '...' : args;
97
96
  console.log(chalk.gray(' ') + display);
98
97
  }
99
98
  }
@@ -103,7 +102,7 @@ export class REPLOutput {
103
102
  if (!output) return;
104
103
 
105
104
  const lines = output.split('\n');
106
- const maxLines = 25;
105
+ const maxLines = 20;
107
106
  const display = lines.slice(0, maxLines);
108
107
 
109
108
  for (const line of display) {
@@ -120,7 +119,7 @@ export class REPLOutput {
120
119
  }
121
120
 
122
121
  printToolEnd(): void {
123
- console.log(chalk.yellow(' ────────────────────────────────────'));
122
+ console.log();
124
123
  }
125
124
 
126
125
  // ── Thinking ────────────────────────────────────────────
@@ -167,11 +166,11 @@ export class REPLOutput {
167
166
 
168
167
  error(msg: string): void {
169
168
  console.log();
170
- console.log(chalk.red(' ┌─ Error'));
169
+ console.log(chalk.red(' Error'));
170
+ console.log(chalk.red(' ' + '─'.repeat(40)));
171
171
  for (const line of msg.split('\n')) {
172
- console.log(chalk.red(' ') + line);
172
+ console.log(chalk.red(' ') + line);
173
173
  }
174
- console.log(chalk.red(' └─'));
175
174
  console.log();
176
175
  }
177
176
 
@@ -202,9 +201,9 @@ export class REPLOutput {
202
201
  section(title: string, items: Array<{ label: string; value: string }>): void {
203
202
  console.log();
204
203
  console.log(chalk.bold(' ' + title));
205
- this.divider();
204
+ console.log(chalk.gray(' ' + '─'.repeat(40)));
206
205
  for (const item of items) {
207
- console.log(' ' + chalk.gray(item.label.padEnd(14)) + chalk.white(item.value));
206
+ console.log(' ' + chalk.gray(item.label.padEnd(14)) + item.value);
208
207
  }
209
208
  console.log();
210
209
  }
@@ -214,7 +213,7 @@ export class REPLOutput {
214
213
  printHelp(): void {
215
214
  console.log();
216
215
  console.log(chalk.bold(' Commands'));
217
- this.divider();
216
+ console.log(chalk.gray(' ' + '─'.repeat(40)));
218
217
  const cmds: [string, string][] = [
219
218
  ['help', 'Show this help'],
220
219
  ['tools', 'List available tools'],
@@ -227,7 +226,7 @@ export class REPLOutput {
227
226
  }
228
227
  console.log();
229
228
  console.log(chalk.bold(' Keyboard'));
230
- this.divider();
229
+ console.log(chalk.gray(' ' + '─'.repeat(40)));
231
230
  console.log(' ' + chalk.cyan('↑ / ↓'.padEnd(14)) + chalk.gray('Browse command history'));
232
231
  console.log(' ' + chalk.cyan('Tab'.padEnd(14)) + chalk.gray('Auto-complete'));
233
232
  console.log(' ' + chalk.cyan('Ctrl+C'.padEnd(14)) + chalk.gray('Exit'));
package/src/tui/repl.ts CHANGED
@@ -106,44 +106,56 @@ export class REPL {
106
106
  let hasStartedOutput = false;
107
107
 
108
108
  try {
109
- const stream = this.app.getAgent().run(this.app.session.getMessages());
109
+ const stream = this.app.streamResponse();
110
110
 
111
111
  for await (const chunk of stream) {
112
112
  this.output.stopThinking();
113
113
 
114
- const parts = chunk.split('\n');
115
- for (const part of parts) {
116
- // Tool message: @@TOOL@@{json}
117
- if (part.startsWith('@@TOOL@@')) {
118
- try {
119
- const data = JSON.parse(part.slice(8));
120
- if (data.action === 'call') {
121
- if (hasStartedOutput) {
122
- this.output.endAssistant();
123
- hasStartedOutput = false;
114
+ // Check for structured tool messages
115
+ if (chunk.includes('@@TOOL@@')) {
116
+ const parts = chunk.split('\n');
117
+ for (const part of parts) {
118
+ if (part.startsWith('@@TOOL@@')) {
119
+ try {
120
+ const data = JSON.parse(part.slice(8));
121
+ if (data.action === 'call') {
122
+ if (hasStartedOutput) {
123
+ this.output.endAssistant();
124
+ hasStartedOutput = false;
125
+ }
126
+ this.output.printToolCall(data.name, data.args || '');
127
+ this.output.startExecuting(data.name);
128
+ } else if (data.action === 'result') {
129
+ this.output.stopThinking();
130
+ this.output.printToolResult(data.output || data.error || '', !!data.error);
131
+ this.output.printToolEnd();
124
132
  }
125
- this.output.printToolCall(data.name, data.args || '');
126
- // Show executing state
127
- this.output.startExecuting(data.name);
128
- } else if (data.action === 'result') {
129
- this.output.stopThinking();
130
- this.output.printToolResult(data.output || data.error || '', !!data.error);
131
- this.output.printToolEnd();
133
+ } catch {
134
+ // If parse fails, treat as regular text
135
+ if (part) {
136
+ if (!hasStartedOutput) {
137
+ this.output.beginAssistant();
138
+ hasStartedOutput = true;
139
+ }
140
+ this.output.writeChunk(part);
141
+ }
142
+ }
143
+ } else if (part) {
144
+ // Regular text between tool messages
145
+ if (!hasStartedOutput) {
146
+ this.output.beginAssistant();
147
+ hasStartedOutput = true;
132
148
  }
133
- } catch {
134
149
  this.output.writeChunk(part + '\n');
135
150
  }
136
- continue;
137
151
  }
138
-
139
- // Regular text
140
- if (part) {
141
- if (!hasStartedOutput) {
142
- this.output.beginAssistant();
143
- hasStartedOutput = true;
144
- }
145
- this.output.writeChunk(part + '\n');
152
+ } else {
153
+ // Pure text chunk - just output it
154
+ if (!hasStartedOutput) {
155
+ this.output.beginAssistant();
156
+ hasStartedOutput = true;
146
157
  }
158
+ this.output.writeChunk(chunk);
147
159
  }
148
160
 
149
161
  fullResponse += chunk;
@@ -153,7 +165,6 @@ export class REPL {
153
165
  this.output.endAssistant();
154
166
  }
155
167
 
156
- // Don't save empty responses
157
168
  if (fullResponse.trim()) {
158
169
  this.app.session.addMessage('assistant', fullResponse);
159
170
  this.app.session.truncate();
@@ -18,7 +18,7 @@ export class WelcomeScreen {
18
18
  if (hasApiKey) return;
19
19
 
20
20
  console.log();
21
- console.log(chalk.cyan.bold(' ⚡ Thatgfsj Code') + chalk.gray(' v0.4.1'));
21
+ console.log(chalk.cyan.bold(' ⚡ Thatgfsj Code') + chalk.gray(' v0.5.0'));
22
22
  console.log(chalk.gray(' AI Coding Assistant'));
23
23
  console.log(line);
24
24
  console.log();