thatgfsj-code 0.7.0 → 0.7.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 (75) hide show
  1. package/dist/app/index.d.ts.map +1 -1
  2. package/dist/app/index.js +5 -0
  3. package/dist/app/index.js.map +1 -1
  4. package/dist/cmd/index.d.ts +0 -5
  5. package/dist/cmd/index.d.ts.map +1 -1
  6. package/dist/cmd/index.js +36 -56
  7. package/dist/cmd/index.js.map +1 -1
  8. package/dist/session/index.d.ts +5 -21
  9. package/dist/session/index.d.ts.map +1 -1
  10. package/dist/session/index.js +26 -22
  11. package/dist/session/index.js.map +1 -1
  12. package/dist/tools/nwt.d.ts +5 -0
  13. package/dist/tools/nwt.d.ts.map +1 -1
  14. package/dist/tools/nwt.js +68 -0
  15. package/dist/tools/nwt.js.map +1 -1
  16. package/dist/tui/app.js +1 -1
  17. package/dist/tui/app.js.map +1 -1
  18. package/dist/tui/components/ChatList.d.ts +1 -1
  19. package/dist/tui/components/ChatList.d.ts.map +1 -1
  20. package/dist/tui/components/ChatList.js +5 -3
  21. package/dist/tui/components/ChatList.js.map +1 -1
  22. package/dist/tui/components/ChatMessage.d.ts +1 -1
  23. package/dist/tui/components/ChatMessage.d.ts.map +1 -1
  24. package/dist/tui/components/ChatMessage.js +4 -2
  25. package/dist/tui/components/ChatMessage.js.map +1 -1
  26. package/dist/tui/components/Header.d.ts +1 -1
  27. package/dist/tui/components/Header.d.ts.map +1 -1
  28. package/dist/tui/components/Header.js +5 -3
  29. package/dist/tui/components/Header.js.map +1 -1
  30. package/dist/tui/components/StatusBar.d.ts +1 -1
  31. package/dist/tui/components/StatusBar.d.ts.map +1 -1
  32. package/dist/tui/components/StatusBar.js +4 -2
  33. package/dist/tui/components/StatusBar.js.map +1 -1
  34. package/dist/tui/components/Thinking.d.ts +2 -1
  35. package/dist/tui/components/Thinking.d.ts.map +1 -1
  36. package/dist/tui/components/Thinking.js +5 -1
  37. package/dist/tui/components/Thinking.js.map +1 -1
  38. package/dist/tui/components/UserInput.d.ts +1 -1
  39. package/dist/tui/components/UserInput.d.ts.map +1 -1
  40. package/dist/tui/components/UserInput.js +5 -22
  41. package/dist/tui/components/UserInput.js.map +1 -1
  42. package/package.json +1 -1
  43. package/src/app/index.ts +6 -0
  44. package/src/cmd/index.tsx +38 -51
  45. package/src/session/index.ts +28 -22
  46. package/src/tools/nwt.ts +68 -0
  47. package/src/tui/app.tsx +1 -1
  48. package/src/tui/components/ChatList.tsx +4 -4
  49. package/src/tui/components/ChatMessage.tsx +2 -2
  50. package/src/tui/components/Header.tsx +3 -3
  51. package/src/tui/components/StatusBar.tsx +2 -2
  52. package/src/tui/components/Thinking.tsx +7 -1
  53. package/src/tui/components/UserInput.tsx +8 -24
  54. package/dist/app/agent.d.ts +0 -31
  55. package/dist/app/agent.d.ts.map +0 -1
  56. package/dist/app/agent.js +0 -106
  57. package/dist/app/agent.js.map +0 -1
  58. package/dist/tui/input.d.ts +0 -13
  59. package/dist/tui/input.d.ts.map +0 -1
  60. package/dist/tui/input.js +0 -47
  61. package/dist/tui/input.js.map +0 -1
  62. package/dist/tui/output.d.ts +0 -44
  63. package/dist/tui/output.d.ts.map +0 -1
  64. package/dist/tui/output.js +0 -202
  65. package/dist/tui/output.js.map +0 -1
  66. package/dist/tui/repl.d.ts +0 -15
  67. package/dist/tui/repl.d.ts.map +0 -1
  68. package/dist/tui/repl.js +0 -162
  69. package/dist/tui/repl.js.map +0 -1
  70. package/install.bat +0 -63
  71. package/install.ps1 +0 -217
  72. package/install.sh +0 -113
  73. package/src/tui/input.ts +0 -53
  74. package/src/tui/output.ts +0 -235
  75. package/src/tui/repl.ts +0 -181
package/src/tools/nwt.ts CHANGED
@@ -107,6 +107,9 @@ export class NwtTool implements Tool {
107
107
  if (!existsSync(eventsDir)) mkdirSync(eventsDir, { recursive: true });
108
108
  if (!existsSync(archiveDir)) mkdirSync(archiveDir, { recursive: true });
109
109
 
110
+ // Auto-archive events older than 30 days on every init
111
+ this.autoArchiveIfNeeded(cwd);
112
+
110
113
  // Write metadata
111
114
  const meta = {
112
115
  version: '1.0.0',
@@ -340,6 +343,71 @@ export class NwtTool implements Tool {
340
343
  };
341
344
  }
342
345
 
346
+ // ── Auto Archive ──────────────────────────────────────
347
+
348
+ /**
349
+ * Auto-archive events older than 30 days.
350
+ * Runs silently on init - no output unless something was archived.
351
+ */
352
+ private autoArchiveIfNeeded(cwd: string): void {
353
+ try {
354
+ const nwtDir = join(cwd, NWT_DIR);
355
+ const eventsDir = join(nwtDir, EVENTS_DIR);
356
+ const archiveDir = join(nwtDir, ARCHIVE_DIR);
357
+
358
+ if (!existsSync(eventsDir)) return;
359
+
360
+ const files = readdirSync(eventsDir).filter(f => f.endsWith('.json'));
361
+ if (files.length === 0) return;
362
+
363
+ const cutoff = new Date();
364
+ cutoff.setDate(cutoff.getDate() - ARCHIVE_AFTER_DAYS);
365
+
366
+ const toArchive: string[] = [];
367
+ const toKeep: string[] = [];
368
+
369
+ for (const file of files) {
370
+ try {
371
+ const event = JSON.parse(readFileSync(join(eventsDir, file), 'utf-8'));
372
+ const eventDate = new Date(event.timestamp);
373
+ if (eventDate < cutoff) {
374
+ toArchive.push(file);
375
+ } else {
376
+ toKeep.push(file);
377
+ }
378
+ } catch {
379
+ toKeep.push(file);
380
+ }
381
+ }
382
+
383
+ if (toArchive.length === 0) return;
384
+
385
+ // Create monthly archive file
386
+ const archiveName = `archive-${new Date().toISOString().split('T')[0]}.json`;
387
+ const archiveEvents = toArchive.map(f => {
388
+ return JSON.parse(readFileSync(join(eventsDir, f), 'utf-8'));
389
+ });
390
+
391
+ if (!existsSync(archiveDir)) mkdirSync(archiveDir, { recursive: true });
392
+
393
+ // Append to existing archive or create new
394
+ const archivePath = join(archiveDir, archiveName);
395
+ let existing: any[] = [];
396
+ if (existsSync(archivePath)) {
397
+ try { existing = JSON.parse(readFileSync(archivePath, 'utf-8')); } catch {}
398
+ }
399
+ existing.push(...archiveEvents);
400
+ writeFileSync(archivePath, JSON.stringify(existing, null, 2));
401
+
402
+ // Remove archived files from events dir
403
+ for (const file of toArchive) {
404
+ try { renameSync(join(eventsDir, file), join(archiveDir, file)); } catch {}
405
+ }
406
+ } catch {
407
+ // Silent fail - don't break init
408
+ }
409
+ }
410
+
343
411
  // ── Helpers ───────────────────────────────────────────
344
412
 
345
413
  private loadEvents(cwd: string): TimelineEvent[] {
package/src/tui/app.tsx CHANGED
@@ -53,7 +53,7 @@ export function TuiApp({ app }: Props) {
53
53
  streamingToolCalls={streamingToolCalls}
54
54
  width={terminalWidth - 4}
55
55
  />
56
- {isThinking && <Thinking />}
56
+ <Thinking active={isThinking} />
57
57
  <UserInput onSubmit={onSubmit} disabled={isThinking} />
58
58
  <StatusBar messageCount={allMessages.length} skills={activeSkills} />
59
59
  </Box>
@@ -1,5 +1,5 @@
1
1
  /** @jsxImportSource react */
2
- import React from 'react';
2
+ import React, { memo } from 'react';
3
3
  import { Box } from 'ink';
4
4
  import { ChatMessage, type MessageData } from './ChatMessage.js';
5
5
  import type { ToolCallData } from './ToolCall.js';
@@ -11,9 +11,9 @@ interface Props {
11
11
  width?: number;
12
12
  }
13
13
 
14
- export function ChatList({ messages, streaming, streamingToolCalls, width }: Props) {
14
+ export const ChatList = memo(function ChatList({ messages, streaming, streamingToolCalls, width }: Props) {
15
15
  return (
16
- <Box flexDirection="column" flexGrow={1}>
16
+ <Box flexDirection="column">
17
17
  {messages.map((msg, i) => (
18
18
  <ChatMessage key={i} message={msg} width={width} />
19
19
  ))}
@@ -29,4 +29,4 @@ export function ChatList({ messages, streaming, streamingToolCalls, width }: Pro
29
29
  )}
30
30
  </Box>
31
31
  );
32
- }
32
+ });
@@ -44,11 +44,11 @@ function AssistantMessage({ content, toolCalls, width }: { content: string; tool
44
44
  );
45
45
  }
46
46
 
47
- export function ChatMessage({ message, width }: Props) {
47
+ export const ChatMessage = React.memo(function ChatMessage({ message, width }: Props) {
48
48
  if (message.role === 'user') {
49
49
  return <UserMessage content={message.content} width={width} />;
50
50
  }
51
51
  return <AssistantMessage content={message.content} toolCalls={message.toolCalls} width={width} />;
52
- }
52
+ });
53
53
 
54
54
  export type { MessageData };
@@ -7,14 +7,14 @@ interface Props {
7
7
  model: string;
8
8
  }
9
9
 
10
- export function Header({ provider, model }: Props) {
10
+ export const Header = React.memo(function Header({ provider, model }: Props) {
11
11
  return (
12
12
  <Box flexDirection="column" marginBottom={0}>
13
13
  <Box justifyContent="space-between" width="100%">
14
14
  <Box>
15
15
  <Text color="#06B6D4" bold> ⚡ </Text>
16
16
  <Text color="#22D3EE" bold>THATGFSJ CODE</Text>
17
- <Text dimColor> v0.7.0</Text>
17
+ <Text dimColor> v0.7.2</Text>
18
18
  </Box>
19
19
  <Box>
20
20
  <Text color="#06B6D4" bold> {provider} </Text>
@@ -25,4 +25,4 @@ export function Header({ provider, model }: Props) {
25
25
  <Text color="#374151">{'─'.repeat(80)}</Text>
26
26
  </Box>
27
27
  );
28
- }
28
+ });
@@ -7,7 +7,7 @@ interface Props {
7
7
  skills: string[];
8
8
  }
9
9
 
10
- export function StatusBar({ messageCount, skills }: Props) {
10
+ export const StatusBar = React.memo(function StatusBar({ messageCount, skills }: Props) {
11
11
  const activeSkills = skills.slice(0, 3).join(', ');
12
12
  const moreSkills = skills.length > 3 ? ` +${skills.length - 3}` : '';
13
13
 
@@ -27,4 +27,4 @@ export function StatusBar({ messageCount, skills }: Props) {
27
27
  </Box>
28
28
  </Box>
29
29
  );
30
- }
30
+ });
@@ -4,10 +4,16 @@ import { Box, Text } from 'ink';
4
4
  import Spinner from 'ink-spinner';
5
5
 
6
6
  interface Props {
7
+ active?: boolean;
7
8
  message?: string;
8
9
  }
9
10
 
10
- export function Thinking({ message = 'Thinking' }: Props) {
11
+ export function Thinking({ active = true, message = 'Thinking' }: Props) {
12
+ if (!active) {
13
+ // Keep layout stable - render empty space
14
+ return <Box paddingY={0}><Text> </Text></Box>;
15
+ }
16
+
11
17
  return (
12
18
  <Box paddingLeft={1}>
13
19
  <Text color="#06B6D4">
@@ -1,5 +1,5 @@
1
1
  /** @jsxImportSource react */
2
- import React, { useState } from 'react';
2
+ import React, { useState, memo } from 'react';
3
3
  import { Box, Text, useInput, useApp } from 'ink';
4
4
 
5
5
  interface Props {
@@ -7,9 +7,8 @@ interface Props {
7
7
  disabled?: boolean;
8
8
  }
9
9
 
10
- export function UserInput({ onSubmit, disabled }: Props) {
10
+ export const UserInput = memo(function UserInput({ onSubmit, disabled }: Props) {
11
11
  const [value, setValue] = useState('');
12
- const [cursorPos, setCursorPos] = useState(0);
13
12
  const [history, setHistory] = useState<string[]>([]);
14
13
  const [historyIdx, setHistoryIdx] = useState(-1);
15
14
  const { exit } = useApp();
@@ -20,15 +19,11 @@ export function UserInput({ onSubmit, disabled }: Props) {
20
19
  if (key.return) {
21
20
  const trimmed = value.trim();
22
21
  if (trimmed) {
23
- if (trimmed === 'exit' || trimmed === 'quit') {
24
- exit();
25
- return;
26
- }
22
+ if (trimmed === 'exit' || trimmed === 'quit') { exit(); return; }
27
23
  setHistory(prev => [...prev, trimmed]);
28
24
  setHistoryIdx(-1);
29
25
  onSubmit(trimmed);
30
26
  setValue('');
31
- setCursorPos(0);
32
27
  }
33
28
  return;
34
29
  }
@@ -37,39 +32,28 @@ export function UserInput({ onSubmit, disabled }: Props) {
37
32
  const newIdx = historyIdx === -1 ? history.length - 1 : Math.max(0, historyIdx - 1);
38
33
  setHistoryIdx(newIdx);
39
34
  setValue(history[newIdx]);
40
- setCursorPos(history[newIdx].length);
41
35
  return;
42
36
  }
43
37
 
44
38
  if (key.downArrow && historyIdx >= 0) {
45
39
  const newIdx = historyIdx + 1;
46
40
  if (newIdx >= history.length) {
47
- setHistoryIdx(-1);
48
- setValue('');
49
- setCursorPos(0);
41
+ setHistoryIdx(-1); setValue('');
50
42
  } else {
51
- setHistoryIdx(newIdx);
52
- setValue(history[newIdx]);
53
- setCursorPos(history[newIdx].length);
43
+ setHistoryIdx(newIdx); setValue(history[newIdx]);
54
44
  }
55
45
  return;
56
46
  }
57
47
 
58
48
  if (key.backspace || key.delete) {
59
- if (cursorPos > 0) {
60
- setValue(v => v.slice(0, cursorPos - 1) + v.slice(cursorPos));
61
- setCursorPos(p => p - 1);
62
- }
49
+ setValue(v => v.slice(0, -1));
63
50
  return;
64
51
  }
65
52
 
66
- if (key.leftArrow) { setCursorPos(p => Math.max(0, p - 1)); return; }
67
- if (key.rightArrow) { setCursorPos(p => Math.min(value.length, p + 1)); return; }
68
53
  if (key.ctrl && input === 'c') { exit(); return; }
69
54
 
70
55
  if (input && !key.ctrl && !key.meta) {
71
- setValue(v => v.slice(0, cursorPos) + input + v.slice(cursorPos));
72
- setCursorPos(p => p + input.length);
56
+ setValue(v => v + input);
73
57
  }
74
58
  });
75
59
 
@@ -80,4 +64,4 @@ export function UserInput({ onSubmit, disabled }: Props) {
80
64
  {!disabled && <Text color="#06B6D4">█</Text>}
81
65
  </Box>
82
66
  );
83
- }
67
+ });
@@ -1,31 +0,0 @@
1
- /**
2
- * Agent Loop - Core agent logic with streaming and tool execution
3
- * Extracted from old src/core/ai-engine.ts
4
- *
5
- * The agent loop: while(true) { stream response → check tool calls → execute → repeat }
6
- */
7
- import type { ChatMessage, ChatResponse } from '../types.js';
8
- import type { HookManager } from '../hooks/index.js';
9
- import { LLMService } from '../llm/index.js';
10
- import { ToolRegistry } from '../tools/index.js';
11
- export interface AgentConfig {
12
- maxIterations?: number;
13
- hooks?: HookManager;
14
- }
15
- export declare class Agent {
16
- private llm;
17
- private registry;
18
- private hooks?;
19
- private maxIterations;
20
- constructor(llm: LLMService, registry: ToolRegistry, config?: AgentConfig);
21
- /**
22
- * Run agent loop with streaming output
23
- * Returns the final response
24
- */
25
- run(messages: ChatMessage[]): AsyncGenerator<string, ChatResponse>;
26
- /**
27
- * Non-streaming chat (convenience method)
28
- */
29
- chat(messages: ChatMessage[]): Promise<ChatResponse>;
30
- }
31
- //# sourceMappingURL=agent.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/app/agent.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,WAAW,WAAW;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,qBAAa,KAAK;IAChB,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,KAAK,CAAC,CAAc;IAC5B,OAAO,CAAC,aAAa,CAAS;gBAElB,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,GAAE,WAAgB;IAU7E;;;OAGG;IACI,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,YAAY,CAAC;IA0FzE;;OAEG;IACG,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;CAO3D"}
package/dist/app/agent.js DELETED
@@ -1,106 +0,0 @@
1
- /**
2
- * Agent Loop - Core agent logic with streaming and tool execution
3
- * Extracted from old src/core/ai-engine.ts
4
- *
5
- * The agent loop: while(true) { stream response → check tool calls → execute → repeat }
6
- */
7
- import chalk from 'chalk';
8
- export class Agent {
9
- llm;
10
- registry;
11
- hooks;
12
- maxIterations;
13
- constructor(llm, registry, config = {}) {
14
- this.llm = llm;
15
- this.registry = registry;
16
- this.hooks = config.hooks;
17
- this.maxIterations = config.maxIterations ?? 10;
18
- // Register tools with LLM service
19
- this.llm.registerTools(registry.list());
20
- }
21
- /**
22
- * Run agent loop with streaming output
23
- * Returns the final response
24
- */
25
- async *run(messages) {
26
- let currentMessages = [...messages];
27
- let iterations = 0;
28
- while (iterations < this.maxIterations) {
29
- iterations++;
30
- // Hook: beforeAgentLoop
31
- if (this.hooks) {
32
- await this.hooks.emit('beforeAgentLoop', { messages: currentMessages, iteration: iterations });
33
- }
34
- // Stream the response
35
- let fullContent = '';
36
- for await (const chunk of this.llm.chatStream(currentMessages, { maxIterations: 1 })) {
37
- fullContent += chunk;
38
- yield chunk;
39
- }
40
- // Get the full response to check for tool calls
41
- const response = {
42
- content: fullContent,
43
- role: 'assistant',
44
- };
45
- // Check if the response contains tool calls
46
- // For now, we rely on the LLM service to handle tool calls internally
47
- // If the LLM service returned tool_calls, we need to process them
48
- if (response.tool_calls && response.tool_calls.length > 0) {
49
- currentMessages.push({
50
- role: 'assistant',
51
- content: response.content,
52
- tool_calls: response.tool_calls,
53
- });
54
- for (const toolCall of response.tool_calls) {
55
- // Hook: beforeToolCall
56
- if (this.hooks) {
57
- await this.hooks.emit('beforeToolCall', {
58
- toolName: toolCall.function.name,
59
- toolParams: JSON.parse(toolCall.function.arguments || '{}'),
60
- toolCallId: toolCall.id,
61
- });
62
- }
63
- const result = await this.registry.execute(toolCall.function.name, JSON.parse(toolCall.function.arguments || '{}'));
64
- // Hook: afterToolCall
65
- if (this.hooks) {
66
- await this.hooks.emit('afterToolCall', {
67
- toolName: toolCall.function.name,
68
- toolParams: JSON.parse(toolCall.function.arguments || '{}'),
69
- toolResult: result,
70
- toolCallId: toolCall.id,
71
- });
72
- }
73
- currentMessages.push({
74
- role: 'tool',
75
- content: result.success ? (result.output || JSON.stringify(result.data)) : (result.error || 'Tool failed'),
76
- tool_call_id: toolCall.id,
77
- name: toolCall.function.name,
78
- });
79
- yield `\n${chalk.gray(`[tool: ${toolCall.function.name}]`)}`;
80
- }
81
- continue; // Next iteration
82
- }
83
- // No tool calls - done
84
- if (response.content) {
85
- currentMessages.push({ role: 'assistant', content: response.content });
86
- }
87
- // Hook: afterAgentLoop
88
- if (this.hooks) {
89
- await this.hooks.emit('afterAgentLoop', { messages: currentMessages, iteration: iterations });
90
- }
91
- return response;
92
- }
93
- return { content: '[Agent loop exceeded maximum iterations]', role: 'assistant' };
94
- }
95
- /**
96
- * Non-streaming chat (convenience method)
97
- */
98
- async chat(messages) {
99
- let fullContent = '';
100
- for await (const chunk of this.run(messages)) {
101
- fullContent += chunk;
102
- }
103
- return { content: fullContent, role: 'assistant' };
104
- }
105
- }
106
- //# sourceMappingURL=agent.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/app/agent.ts"],"names":[],"mappings":"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"}
@@ -1,13 +0,0 @@
1
- /**
2
- * REPL Input Handler
3
- */
4
- export declare class REPLInput {
5
- private rl;
6
- private history;
7
- private historyIndex;
8
- constructor();
9
- prompt(prefix?: string): Promise<string>;
10
- close(): void;
11
- private completer;
12
- }
13
- //# sourceMappingURL=input.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/tui/input.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,qBAAa,SAAS;IACpB,OAAO,CAAC,EAAE,CAAqB;IAC/B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,YAAY,CAAc;;IAyB5B,MAAM,CAAC,MAAM,GAAE,MAAyB,GAAG,OAAO,CAAC,MAAM,CAAC;IAQhE,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,SAAS;CAKlB"}
package/dist/tui/input.js DELETED
@@ -1,47 +0,0 @@
1
- /**
2
- * REPL Input Handler
3
- */
4
- import readline from 'readline';
5
- import chalk from 'chalk';
6
- export class REPLInput {
7
- rl;
8
- history = [];
9
- historyIndex = -1;
10
- constructor() {
11
- this.rl = readline.createInterface({
12
- input: process.stdin,
13
- output: process.stdout,
14
- completer: this.completer.bind(this),
15
- historySize: 100,
16
- tabSize: 4,
17
- });
18
- this.rl.on('SIGINT', () => {
19
- process.stdout.write(chalk.gray('\n Goodbye! 👋\n'));
20
- process.exit(0);
21
- });
22
- this.rl.on('line', (line) => {
23
- if (line.trim()) {
24
- this.history.push(line);
25
- if (this.history.length > 100)
26
- this.history.shift();
27
- }
28
- this.historyIndex = this.history.length;
29
- });
30
- }
31
- async prompt(prefix = chalk.cyan('❯ ')) {
32
- return new Promise((resolve) => {
33
- this.rl.question(prefix, (answer) => {
34
- resolve(answer);
35
- });
36
- });
37
- }
38
- close() {
39
- this.rl.close();
40
- }
41
- completer(line) {
42
- const commands = ['exit', 'quit', 'clear', 'help', 'tools', 'model'];
43
- const hits = commands.filter(c => c.startsWith(line.toLowerCase()));
44
- return [hits.length ? hits : [], line];
45
- }
46
- }
47
- //# sourceMappingURL=input.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"input.js","sourceRoot":"","sources":["../../src/tui/input.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,OAAO,SAAS;IACZ,EAAE,CAAqB;IACvB,OAAO,GAAa,EAAE,CAAC;IACvB,YAAY,GAAW,CAAC,CAAC,CAAC;IAElC;QACE,IAAI,CAAC,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;YACjC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;YACpC,WAAW,EAAE,GAAG;YAChB,OAAO,EAAE,CAAC;SACX,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;YACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAC1B,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBAChB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACxB,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG;oBAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACtD,CAAC;YACD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QAC1C,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAiB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;gBAClC,OAAO,CAAC,MAAM,CAAC,CAAC;YAClB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;IAEO,SAAS,CAAC,IAAY;QAC5B,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QACpE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;CACF"}
@@ -1,44 +0,0 @@
1
- /**
2
- * REPL Output - Clean terminal UI
3
- * Inspired by opencode: simple indentation for streaming, clean boundaries
4
- */
5
- export declare class REPLOutput {
6
- private spinner;
7
- printBanner(): void;
8
- getPrompt(): string;
9
- printUserInput(input: string): void;
10
- /**
11
- * Begin assistant response - just print the header
12
- */
13
- beginAssistant(): void;
14
- /**
15
- * Write streaming chunk - output as-is with indent.
16
- * The chunk already contains proper newlines from the AI.
17
- */
18
- writeChunk(chunk: string): void;
19
- /**
20
- * End assistant response
21
- */
22
- endAssistant(): void;
23
- printToolCall(name: string, args: string): void;
24
- printToolResult(output: string, isError?: boolean): void;
25
- printToolEnd(): void;
26
- startThinking(): void;
27
- startExecuting(toolName: string): void;
28
- stopThinking(): void;
29
- stopThinkingFail(msg: string): void;
30
- info(msg: string): void;
31
- success(msg: string): void;
32
- error(msg: string): void;
33
- warning(msg: string): void;
34
- dim(msg: string): void;
35
- divider(): void;
36
- spacer(): void;
37
- clear(): void;
38
- section(title: string, items: Array<{
39
- label: string;
40
- value: string;
41
- }>): void;
42
- printHelp(): void;
43
- }
44
- //# sourceMappingURL=output.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/tui/output.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAoB;IAInC,WAAW,IAAI,IAAI;IAUnB,SAAS,IAAI,MAAM;IAMnB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAYnC;;OAEG;IACH,cAAc,IAAI,IAAI;IAKtB;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAa/B;;OAEG;IACH,YAAY,IAAI,IAAI;IAOpB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAwB/C,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,IAAI;IAoBtD,YAAY,IAAI,IAAI;IAMpB,aAAa,IAAI,IAAI;IAQrB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQtC,YAAY,IAAI,IAAI;IAOpB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IASnC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIvB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI1B,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAUxB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAMtB,OAAO,IAAI,IAAI;IAIf,MAAM,IAAI,IAAI;IAId,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI;IAY5E,SAAS,IAAI,IAAI;CAsBlB"}