galaxy-code 0.1.5 → 0.1.7
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/README.md +149 -600
- package/dist/cli.bundle.js +588 -0
- package/package.json +14 -12
- package/dist/app.d.ts +0 -7
- package/dist/app.js +0 -597
- package/dist/auto-updater.d.ts +0 -21
- package/dist/auto-updater.js +0 -144
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +0 -159
- package/dist/connections/claude.d.ts +0 -71
- package/dist/connections/claude.js +0 -303
- package/dist/connections/gemini.d.ts +0 -40
- package/dist/connections/gemini.js +0 -232
- package/dist/connections/index.d.ts +0 -11
- package/dist/connections/index.js +0 -11
- package/dist/connections/ollama.d.ts +0 -37
- package/dist/connections/ollama.js +0 -73
- package/dist/connections/types.d.ts +0 -22
- package/dist/connections/types.js +0 -7
- package/dist/env.d.ts +0 -1
- package/dist/env.js +0 -29
- package/dist/node_modules/@workspace/agent-core/connections/claude.d.ts +0 -72
- package/dist/node_modules/@workspace/agent-core/connections/claude.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/connections/claude.js +0 -270
- package/dist/node_modules/@workspace/agent-core/connections/claude.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/connections/gemini.d.ts +0 -41
- package/dist/node_modules/@workspace/agent-core/connections/gemini.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/connections/gemini.js +0 -203
- package/dist/node_modules/@workspace/agent-core/connections/gemini.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/connections/index.d.ts +0 -12
- package/dist/node_modules/@workspace/agent-core/connections/index.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/connections/index.js +0 -12
- package/dist/node_modules/@workspace/agent-core/connections/index.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/connections/ollama.d.ts +0 -38
- package/dist/node_modules/@workspace/agent-core/connections/ollama.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/connections/ollama.js +0 -64
- package/dist/node_modules/@workspace/agent-core/connections/ollama.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/connections/types.d.ts +0 -23
- package/dist/node_modules/@workspace/agent-core/connections/types.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/connections/types.js +0 -8
- package/dist/node_modules/@workspace/agent-core/connections/types.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/index.d.ts +0 -13
- package/dist/node_modules/@workspace/agent-core/index.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/index.js +0 -22
- package/dist/node_modules/@workspace/agent-core/index.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/package.json +0 -53
- package/dist/node_modules/@workspace/agent-core/prompts/ba-it-analyzer.d.ts +0 -2
- package/dist/node_modules/@workspace/agent-core/prompts/ba-it-analyzer.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/prompts/ba-it-analyzer.js +0 -144
- package/dist/node_modules/@workspace/agent-core/prompts/ba-it-analyzer.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/prompts/index.d.ts +0 -12
- package/dist/node_modules/@workspace/agent-core/prompts/index.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/prompts/index.js +0 -12
- package/dist/node_modules/@workspace/agent-core/prompts/index.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/prompts/orchestrator.d.ts +0 -9
- package/dist/node_modules/@workspace/agent-core/prompts/orchestrator.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/prompts/orchestrator.js +0 -89
- package/dist/node_modules/@workspace/agent-core/prompts/orchestrator.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/prompts/planning-agent.d.ts +0 -9
- package/dist/node_modules/@workspace/agent-core/prompts/planning-agent.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/prompts/planning-agent.js +0 -196
- package/dist/node_modules/@workspace/agent-core/prompts/planning-agent.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/prompts/universal-agent.d.ts +0 -8
- package/dist/node_modules/@workspace/agent-core/prompts/universal-agent.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/prompts/universal-agent.js +0 -112
- package/dist/node_modules/@workspace/agent-core/prompts/universal-agent.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/providers/agent-selector.d.ts +0 -30
- package/dist/node_modules/@workspace/agent-core/providers/agent-selector.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/providers/agent-selector.js +0 -76
- package/dist/node_modules/@workspace/agent-core/providers/agent-selector.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/providers/claude-agent.d.ts +0 -30
- package/dist/node_modules/@workspace/agent-core/providers/claude-agent.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/providers/claude-agent.js +0 -107
- package/dist/node_modules/@workspace/agent-core/providers/claude-agent.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/providers/gemini-agent.d.ts +0 -37
- package/dist/node_modules/@workspace/agent-core/providers/gemini-agent.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/providers/gemini-agent.js +0 -144
- package/dist/node_modules/@workspace/agent-core/providers/gemini-agent.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/providers/index.d.ts +0 -13
- package/dist/node_modules/@workspace/agent-core/providers/index.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/providers/index.js +0 -13
- package/dist/node_modules/@workspace/agent-core/providers/index.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/providers/ollama-agent.d.ts +0 -54
- package/dist/node_modules/@workspace/agent-core/providers/ollama-agent.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/providers/ollama-agent.js +0 -247
- package/dist/node_modules/@workspace/agent-core/providers/ollama-agent.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/providers/orchestrator.d.ts +0 -17
- package/dist/node_modules/@workspace/agent-core/providers/orchestrator.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/providers/orchestrator.js +0 -62
- package/dist/node_modules/@workspace/agent-core/providers/orchestrator.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/ba-it-analyzer.d.ts +0 -67
- package/dist/node_modules/@workspace/agent-core/tools/ba-it-analyzer.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/ba-it-analyzer.js +0 -81
- package/dist/node_modules/@workspace/agent-core/tools/ba-it-analyzer.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/code-generate-agent.d.ts +0 -52
- package/dist/node_modules/@workspace/agent-core/tools/code-generate-agent.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/code-generate-agent.js +0 -150
- package/dist/node_modules/@workspace/agent-core/tools/code-generate-agent.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/command-runner.d.ts +0 -15
- package/dist/node_modules/@workspace/agent-core/tools/command-runner.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/command-runner.js +0 -121
- package/dist/node_modules/@workspace/agent-core/tools/command-runner.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/document-parser.d.ts +0 -12
- package/dist/node_modules/@workspace/agent-core/tools/document-parser.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/document-parser.js +0 -84
- package/dist/node_modules/@workspace/agent-core/tools/document-parser.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/file-operations.d.ts +0 -18
- package/dist/node_modules/@workspace/agent-core/tools/file-operations.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/file-operations.js +0 -126
- package/dist/node_modules/@workspace/agent-core/tools/file-operations.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/galaxy-ui-integration.d.ts +0 -95
- package/dist/node_modules/@workspace/agent-core/tools/galaxy-ui-integration.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/galaxy-ui-integration.js +0 -245
- package/dist/node_modules/@workspace/agent-core/tools/galaxy-ui-integration.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/git-operations.d.ts +0 -12
- package/dist/node_modules/@workspace/agent-core/tools/git-operations.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/git-operations.js +0 -115
- package/dist/node_modules/@workspace/agent-core/tools/git-operations.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/index.d.ts +0 -11
- package/dist/node_modules/@workspace/agent-core/tools/index.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/index.js +0 -11
- package/dist/node_modules/@workspace/agent-core/tools/index.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/planning-agent.d.ts +0 -30
- package/dist/node_modules/@workspace/agent-core/tools/planning-agent.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/planning-agent.js +0 -125
- package/dist/node_modules/@workspace/agent-core/tools/planning-agent.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/progress-reporter.d.ts +0 -20
- package/dist/node_modules/@workspace/agent-core/tools/progress-reporter.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/progress-reporter.js +0 -46
- package/dist/node_modules/@workspace/agent-core/tools/progress-reporter.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/registry.d.ts +0 -22
- package/dist/node_modules/@workspace/agent-core/tools/registry.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/registry.js +0 -651
- package/dist/node_modules/@workspace/agent-core/tools/registry.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/tool-event-emitter.d.ts +0 -25
- package/dist/node_modules/@workspace/agent-core/tools/tool-event-emitter.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/tool-event-emitter.js +0 -26
- package/dist/node_modules/@workspace/agent-core/tools/tool-event-emitter.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/types.d.ts +0 -32
- package/dist/node_modules/@workspace/agent-core/tools/types.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/tools/types.js +0 -2
- package/dist/node_modules/@workspace/agent-core/tools/types.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/types.d.ts +0 -40
- package/dist/node_modules/@workspace/agent-core/types.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/types.js +0 -9
- package/dist/node_modules/@workspace/agent-core/types.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/utils/config-manager.d.ts +0 -103
- package/dist/node_modules/@workspace/agent-core/utils/config-manager.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/utils/config-manager.js +0 -307
- package/dist/node_modules/@workspace/agent-core/utils/config-manager.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/utils/devtools.d.ts +0 -22
- package/dist/node_modules/@workspace/agent-core/utils/devtools.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/utils/devtools.js +0 -62
- package/dist/node_modules/@workspace/agent-core/utils/devtools.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/utils/message-formatters.d.ts +0 -33
- package/dist/node_modules/@workspace/agent-core/utils/message-formatters.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/utils/message-formatters.js +0 -591
- package/dist/node_modules/@workspace/agent-core/utils/message-formatters.js.map +0 -1
- package/dist/node_modules/@workspace/agent-core/utils/progress-tracker.d.ts +0 -60
- package/dist/node_modules/@workspace/agent-core/utils/progress-tracker.d.ts.map +0 -1
- package/dist/node_modules/@workspace/agent-core/utils/progress-tracker.js +0 -204
- package/dist/node_modules/@workspace/agent-core/utils/progress-tracker.js.map +0 -1
- package/dist/prompts/ba-it-analyzer.d.ts +0 -1
- package/dist/prompts/ba-it-analyzer.js +0 -143
- package/dist/prompts/index.d.ts +0 -11
- package/dist/prompts/index.js +0 -11
- package/dist/prompts/orchestrator.d.ts +0 -8
- package/dist/prompts/orchestrator.js +0 -88
- package/dist/prompts/planning-agent.d.ts +0 -8
- package/dist/prompts/planning-agent.js +0 -195
- package/dist/prompts/universal-agent.d.ts +0 -7
- package/dist/prompts/universal-agent.js +0 -111
- package/dist/providers/agent-selector.d.ts +0 -29
- package/dist/providers/agent-selector.js +0 -84
- package/dist/providers/claude-agent.d.ts +0 -29
- package/dist/providers/claude-agent.js +0 -121
- package/dist/providers/gemini-agent.d.ts +0 -36
- package/dist/providers/gemini-agent.js +0 -168
- package/dist/providers/index.d.ts +0 -12
- package/dist/providers/index.js +0 -12
- package/dist/providers/ollama-agent.d.ts +0 -53
- package/dist/providers/ollama-agent.js +0 -276
- package/dist/providers/orchestrator.d.ts +0 -16
- package/dist/providers/orchestrator.js +0 -76
- package/dist/tools/ba-it-analyzer.d.ts +0 -66
- package/dist/tools/ba-it-analyzer.js +0 -90
- package/dist/tools/code-generate-agent.d.ts +0 -51
- package/dist/tools/code-generate-agent.js +0 -159
- package/dist/tools/command-runner.d.ts +0 -14
- package/dist/tools/command-runner.js +0 -120
- package/dist/tools/document-parser.d.ts +0 -11
- package/dist/tools/document-parser.js +0 -83
- package/dist/tools/file-operations.d.ts +0 -17
- package/dist/tools/file-operations.js +0 -127
- package/dist/tools/galaxy-ui-integration.d.ts +0 -94
- package/dist/tools/galaxy-ui-integration.js +0 -244
- package/dist/tools/git-operations.d.ts +0 -11
- package/dist/tools/git-operations.js +0 -114
- package/dist/tools/index.d.ts +0 -10
- package/dist/tools/index.js +0 -10
- package/dist/tools/planning-agent.d.ts +0 -29
- package/dist/tools/planning-agent.js +0 -134
- package/dist/tools/progress-reporter.d.ts +0 -19
- package/dist/tools/progress-reporter.js +0 -52
- package/dist/tools/registry.d.ts +0 -21
- package/dist/tools/registry.js +0 -695
- package/dist/tools/tool-event-emitter.d.ts +0 -24
- package/dist/tools/tool-event-emitter.js +0 -25
- package/dist/tools/types.d.ts +0 -31
- package/dist/tools/types.js +0 -1
- package/dist/types.d.ts +0 -39
- package/dist/types.js +0 -8
- package/dist/update-checker.d.ts +0 -22
- package/dist/update-checker.js +0 -85
- package/dist/utils/config-manager.d.ts +0 -102
- package/dist/utils/config-manager.js +0 -326
- package/dist/utils/devtools.d.ts +0 -21
- package/dist/utils/devtools.js +0 -61
- package/dist/utils/message-formatters.d.ts +0 -32
- package/dist/utils/message-formatters.js +0 -590
- package/dist/utils/progress-tracker.d.ts +0 -59
- package/dist/utils/progress-tracker.js +0 -213
package/dist/utils/devtools.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Bùi Trọng Hiếu
|
|
3
|
-
* @email kevinbui210191@gmail.com
|
|
4
|
-
* @create 2024-10-13
|
|
5
|
-
* @modify 2024-10-13
|
|
6
|
-
* @desc React DevTools integration for development
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* Initialize React DevTools connection for debugging
|
|
10
|
-
* Only runs in development mode
|
|
11
|
-
*
|
|
12
|
-
* Note: react-devtools-core requires browser globals that don't exist in Node.js
|
|
13
|
-
* This may not work reliably in terminal environments
|
|
14
|
-
*/
|
|
15
|
-
export async function initDevTools() {
|
|
16
|
-
if (process.env['NODE_ENV'] !== 'development') {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
try {
|
|
20
|
-
// Polyfill browser globals for react-devtools-core
|
|
21
|
-
if (typeof globalThis.self === 'undefined') {
|
|
22
|
-
// @ts-ignore - Adding browser global to Node.js
|
|
23
|
-
globalThis.self = globalThis;
|
|
24
|
-
}
|
|
25
|
-
if (typeof globalThis.window === 'undefined') {
|
|
26
|
-
// @ts-ignore - Adding browser global to Node.js
|
|
27
|
-
globalThis.window = globalThis;
|
|
28
|
-
}
|
|
29
|
-
// Dynamic import to avoid bundling in production
|
|
30
|
-
// @ts-expect-error - react-devtools-core doesn't have type definitions
|
|
31
|
-
const devTools = await import('react-devtools-core');
|
|
32
|
-
const { connectToDevTools } = devTools;
|
|
33
|
-
connectToDevTools({
|
|
34
|
-
host: 'localhost',
|
|
35
|
-
port: 8097,
|
|
36
|
-
useHttps: false,
|
|
37
|
-
retryDelay: 1000,
|
|
38
|
-
});
|
|
39
|
-
console.log('✅ React DevTools: Đã kết nối tới localhost:8097');
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
// Silently ignore DevTools errors - it's optional
|
|
43
|
-
// Users can still use the app without DevTools
|
|
44
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
45
|
-
if (message.includes('Cannot find module')) {
|
|
46
|
-
console.log('💡 DevTools không khả dụng (chưa cài đặt react-devtools-core)');
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
console.log('💡 DevTools không khả dụng (không hỗ trợ trong môi trường này)');
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Display component for DevTools status
|
|
55
|
-
*/
|
|
56
|
-
export function DevToolsStatus({ connected }) {
|
|
57
|
-
if (process.env['NODE_ENV'] !== 'development') {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
return connected ? '🔧 DevTools Đã Kết Nối' : '⚠️ DevTools Chưa Kết Nối';
|
|
61
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Bùi Trọng Hiếu
|
|
3
|
-
* @email kevinbui210191@gmail.com
|
|
4
|
-
* @create 2025-01-10
|
|
5
|
-
* @desc Message formatters for rich tool output display
|
|
6
|
-
*/
|
|
7
|
-
import React from 'react';
|
|
8
|
-
import type { ToolExecutionInfo } from '../connections/types.js';
|
|
9
|
-
export interface FormattedMessage {
|
|
10
|
-
type: 'plain' | 'todos' | 'diff' | 'code';
|
|
11
|
-
content: React.ReactNode;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Parse tool result to detect format type
|
|
15
|
-
*/
|
|
16
|
-
export declare function detectMessageType(content: string, toolName?: string): FormattedMessage['type'];
|
|
17
|
-
/**
|
|
18
|
-
* Format todo list output from plan_task
|
|
19
|
-
*/
|
|
20
|
-
export declare function formatTodos(content: string): React.ReactNode;
|
|
21
|
-
/**
|
|
22
|
-
* Format git-style diff output for file operations
|
|
23
|
-
*/
|
|
24
|
-
export declare function formatDiff(content: string, filePath?: string): React.ReactNode;
|
|
25
|
-
/**
|
|
26
|
-
* Format code blocks
|
|
27
|
-
*/
|
|
28
|
-
export declare function formatCode(content: string): React.ReactNode;
|
|
29
|
-
/**
|
|
30
|
-
* Main formatter dispatcher
|
|
31
|
-
*/
|
|
32
|
-
export declare function formatMessage(content: string | object | any[], toolName?: string, toolInfo?: ToolExecutionInfo): React.ReactNode;
|
|
@@ -1,590 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Bùi Trọng Hiếu
|
|
3
|
-
* @email kevinbui210191@gmail.com
|
|
4
|
-
* @create 2025-01-10
|
|
5
|
-
* @desc Message formatters for rich tool output display
|
|
6
|
-
*/
|
|
7
|
-
import React from 'react';
|
|
8
|
-
import { Box, Text } from 'ink';
|
|
9
|
-
/**
|
|
10
|
-
* Get terminal width with fallback
|
|
11
|
-
*/
|
|
12
|
-
const getTerminalWidth = () => {
|
|
13
|
-
const width = process.stdout?.columns;
|
|
14
|
-
return typeof width === 'number' && Number.isFinite(width) ? width : 80;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Truncate long lines to fit terminal width
|
|
18
|
-
*/
|
|
19
|
-
const truncateLine = (line, maxWidth) => {
|
|
20
|
-
if (line.length <= maxWidth)
|
|
21
|
-
return line;
|
|
22
|
-
return line.slice(0, maxWidth - 3) + '...';
|
|
23
|
-
};
|
|
24
|
-
/**
|
|
25
|
-
* Parse tool result to detect format type
|
|
26
|
-
*/
|
|
27
|
-
export function detectMessageType(content, toolName) {
|
|
28
|
-
// Plan task outputs todos
|
|
29
|
-
if (toolName === 'plan_task') {
|
|
30
|
-
return 'todos';
|
|
31
|
-
}
|
|
32
|
-
// File operations show diffs
|
|
33
|
-
if (toolName === 'file_write' || toolName === 'code_generate') {
|
|
34
|
-
// Check if content has diff markers
|
|
35
|
-
if (content.includes('---') ||
|
|
36
|
-
content.includes('+++') ||
|
|
37
|
-
content.includes('@@')) {
|
|
38
|
-
return 'diff';
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
// Code blocks
|
|
42
|
-
if (content.includes('```')) {
|
|
43
|
-
return 'code';
|
|
44
|
-
}
|
|
45
|
-
return 'plain';
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Generate simple diff between two texts
|
|
49
|
-
*/
|
|
50
|
-
function generateDiff(oldText, newText) {
|
|
51
|
-
const oldLines = oldText.split('\n');
|
|
52
|
-
const newLines = newText.split('\n');
|
|
53
|
-
const diffLines = [];
|
|
54
|
-
let oldIdx = 0;
|
|
55
|
-
let newIdx = 0;
|
|
56
|
-
// Simple line-by-line comparison
|
|
57
|
-
while (oldIdx < oldLines.length || newIdx < newLines.length) {
|
|
58
|
-
const oldLine = oldLines[oldIdx];
|
|
59
|
-
const newLine = newLines[newIdx];
|
|
60
|
-
if (oldLine === newLine) {
|
|
61
|
-
// Context line
|
|
62
|
-
diffLines.push({
|
|
63
|
-
type: 'context',
|
|
64
|
-
oldLineNum: oldIdx + 1,
|
|
65
|
-
newLineNum: newIdx + 1,
|
|
66
|
-
content: oldLine || '',
|
|
67
|
-
});
|
|
68
|
-
oldIdx++;
|
|
69
|
-
newIdx++;
|
|
70
|
-
}
|
|
71
|
-
else if (oldIdx < oldLines.length && oldLine !== undefined && !newLines.includes(oldLine)) {
|
|
72
|
-
// Line removed
|
|
73
|
-
diffLines.push({
|
|
74
|
-
type: 'remove',
|
|
75
|
-
oldLineNum: oldIdx + 1,
|
|
76
|
-
content: oldLine || '',
|
|
77
|
-
});
|
|
78
|
-
oldIdx++;
|
|
79
|
-
}
|
|
80
|
-
else if (newIdx < newLines.length && newLine !== undefined && !oldLines.includes(newLine)) {
|
|
81
|
-
// Line added
|
|
82
|
-
diffLines.push({
|
|
83
|
-
type: 'add',
|
|
84
|
-
newLineNum: newIdx + 1,
|
|
85
|
-
content: newLine || '',
|
|
86
|
-
});
|
|
87
|
-
newIdx++;
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
// Lines differ but exist in both - treat as remove + add
|
|
91
|
-
if (oldIdx < oldLines.length) {
|
|
92
|
-
diffLines.push({
|
|
93
|
-
type: 'remove',
|
|
94
|
-
oldLineNum: oldIdx + 1,
|
|
95
|
-
content: oldLine || '',
|
|
96
|
-
});
|
|
97
|
-
oldIdx++;
|
|
98
|
-
}
|
|
99
|
-
if (newIdx < newLines.length) {
|
|
100
|
-
diffLines.push({
|
|
101
|
-
type: 'add',
|
|
102
|
-
newLineNum: newIdx + 1,
|
|
103
|
-
content: newLine || '',
|
|
104
|
-
});
|
|
105
|
-
newIdx++;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return diffLines;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Compress diff by grouping context lines
|
|
113
|
-
*/
|
|
114
|
-
function compressDiff(diffLines, contextLines = 2) {
|
|
115
|
-
const compressed = [];
|
|
116
|
-
let i = 0;
|
|
117
|
-
while (i < diffLines.length) {
|
|
118
|
-
const line = diffLines[i];
|
|
119
|
-
if (line && line.type !== 'context') {
|
|
120
|
-
// Add changed line
|
|
121
|
-
compressed.push(line);
|
|
122
|
-
i++;
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
// Look for runs of context lines
|
|
126
|
-
const contextStart = i;
|
|
127
|
-
let contextEnd = i;
|
|
128
|
-
while (contextEnd < diffLines.length &&
|
|
129
|
-
diffLines[contextEnd]?.type === 'context') {
|
|
130
|
-
contextEnd++;
|
|
131
|
-
}
|
|
132
|
-
const contextLength = contextEnd - contextStart;
|
|
133
|
-
if (contextLength <= contextLines * 2) {
|
|
134
|
-
// Keep all context if small
|
|
135
|
-
for (let j = contextStart; j < contextEnd; j++) {
|
|
136
|
-
if (diffLines[j])
|
|
137
|
-
compressed.push(diffLines[j]);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
// Keep only beginning and end context
|
|
142
|
-
for (let j = contextStart; j < contextStart + contextLines; j++) {
|
|
143
|
-
if (diffLines[j])
|
|
144
|
-
compressed.push(diffLines[j]);
|
|
145
|
-
}
|
|
146
|
-
// Add placeholder for skipped lines
|
|
147
|
-
const skipped = contextLength - contextLines * 2;
|
|
148
|
-
compressed.push({
|
|
149
|
-
type: 'context',
|
|
150
|
-
content: `... ${skipped} unchanged lines ...`,
|
|
151
|
-
});
|
|
152
|
-
for (let j = contextEnd - contextLines; j < contextEnd; j++) {
|
|
153
|
-
if (diffLines[j])
|
|
154
|
-
compressed.push(diffLines[j]);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
i = contextEnd;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return compressed;
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Format todo list output from plan_task
|
|
164
|
-
*/
|
|
165
|
-
export function formatTodos(content) {
|
|
166
|
-
try {
|
|
167
|
-
// Try to parse as JSON first (if plan_task returns structured data)
|
|
168
|
-
const data = JSON.parse(content);
|
|
169
|
-
if (data.tasks && Array.isArray(data.tasks)) {
|
|
170
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
171
|
-
React.createElement(Text, { bold: true, color: "cyan" }, "\uD83D\uDCCB Todos"),
|
|
172
|
-
data.tasks.map((task, idx) => (React.createElement(Box, { key: idx, marginLeft: 2 },
|
|
173
|
-
React.createElement(Text, { color: task.completed ? 'green' : 'gray' },
|
|
174
|
-
task.completed ? '☒' : '☐',
|
|
175
|
-
' ',
|
|
176
|
-
task.content || task.title || task.description))))));
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
catch {
|
|
180
|
-
// Not JSON, parse as plain text todo list
|
|
181
|
-
const lines = content.split('\n');
|
|
182
|
-
const todoLines = [];
|
|
183
|
-
for (const line of lines) {
|
|
184
|
-
const trimmed = line.trim();
|
|
185
|
-
// Match patterns like: "☒ Task name" or "- [x] Task name" or "✓ Task name"
|
|
186
|
-
if (trimmed.match(/^[☒✓✅-]\s*\[x\]\s*/i)) {
|
|
187
|
-
todoLines.push({
|
|
188
|
-
completed: true,
|
|
189
|
-
text: trimmed.replace(/^[☒✓✅-]\s*\[x\]\s*/i, ''),
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
else if (trimmed.match(/^[☐-]\s*\[\s*\]\s*/)) {
|
|
193
|
-
todoLines.push({
|
|
194
|
-
completed: false,
|
|
195
|
-
text: trimmed.replace(/^[☐-]\s*\[\s*\]\s*/, ''),
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
else if (trimmed.match(/^[-*•]\s+/)) {
|
|
199
|
-
todoLines.push({
|
|
200
|
-
completed: false,
|
|
201
|
-
text: trimmed.replace(/^[-*•]\s+/, ''),
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
if (todoLines.length > 0) {
|
|
206
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
207
|
-
React.createElement(Text, { bold: true, color: "cyan" }, "\uD83D\uDCCB Todos"),
|
|
208
|
-
todoLines.map((todo, idx) => (React.createElement(Box, { key: idx, marginLeft: 2 },
|
|
209
|
-
React.createElement(Text, { color: todo.completed ? 'green' : 'gray' },
|
|
210
|
-
todo.completed ? '☒' : '☐',
|
|
211
|
-
" ",
|
|
212
|
-
todo.text))))));
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
// Fallback to plain text
|
|
216
|
-
return React.createElement(Text, null, content);
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Format git-style diff output for file operations
|
|
220
|
-
*/
|
|
221
|
-
export function formatDiff(content, filePath) {
|
|
222
|
-
const lines = content.split('\n');
|
|
223
|
-
const diffLines = [];
|
|
224
|
-
let lineNumber = 1;
|
|
225
|
-
for (let i = 0; i < lines.length; i++) {
|
|
226
|
-
const line = lines[i] || '';
|
|
227
|
-
// File header
|
|
228
|
-
if (line.startsWith('---') || line.startsWith('+++')) {
|
|
229
|
-
diffLines.push(React.createElement(Box, { key: i },
|
|
230
|
-
React.createElement(Text, { bold: true, color: "cyan" }, line)));
|
|
231
|
-
continue;
|
|
232
|
-
}
|
|
233
|
-
// Hunk header (e.g., @@ -1,4 +1,6 @@)
|
|
234
|
-
if (line.startsWith('@@')) {
|
|
235
|
-
diffLines.push(React.createElement(Box, { key: i },
|
|
236
|
-
React.createElement(Text, { bold: true, color: "magenta" }, line)));
|
|
237
|
-
continue;
|
|
238
|
-
}
|
|
239
|
-
// Deleted line
|
|
240
|
-
if (line.startsWith('-')) {
|
|
241
|
-
diffLines.push(React.createElement(Box, { key: i },
|
|
242
|
-
React.createElement(Text, { dimColor: true }, String(lineNumber).padStart(4, ' ')),
|
|
243
|
-
React.createElement(Text, { color: "red" }, ` ${line}`)));
|
|
244
|
-
lineNumber++;
|
|
245
|
-
continue;
|
|
246
|
-
}
|
|
247
|
-
// Added line
|
|
248
|
-
if (line.startsWith('+')) {
|
|
249
|
-
diffLines.push(React.createElement(Box, { key: i },
|
|
250
|
-
React.createElement(Text, { dimColor: true }, String(lineNumber).padStart(4, ' ')),
|
|
251
|
-
React.createElement(Text, { color: "green" }, ` ${line}`)));
|
|
252
|
-
lineNumber++;
|
|
253
|
-
continue;
|
|
254
|
-
}
|
|
255
|
-
// Context line (unchanged)
|
|
256
|
-
diffLines.push(React.createElement(Box, { key: i },
|
|
257
|
-
React.createElement(Text, { dimColor: true }, String(lineNumber).padStart(4, ' ')),
|
|
258
|
-
React.createElement(Text, null, ` ${line}`)));
|
|
259
|
-
lineNumber++;
|
|
260
|
-
}
|
|
261
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
262
|
-
filePath && React.createElement(Text, { bold: true, color: "yellow" }, `📝 ${filePath}`),
|
|
263
|
-
diffLines));
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Format code blocks
|
|
267
|
-
*/
|
|
268
|
-
export function formatCode(content) {
|
|
269
|
-
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
|
|
270
|
-
const parts = [];
|
|
271
|
-
let lastIndex = 0;
|
|
272
|
-
let match;
|
|
273
|
-
let idx = 0;
|
|
274
|
-
while ((match = codeBlockRegex.exec(content)) !== null) {
|
|
275
|
-
// Text before code block
|
|
276
|
-
if (match.index > lastIndex) {
|
|
277
|
-
parts.push(React.createElement(Text, { key: `text-${idx}` }, content.slice(lastIndex, match.index)));
|
|
278
|
-
}
|
|
279
|
-
// Code block
|
|
280
|
-
const language = match[1] || 'text';
|
|
281
|
-
const code = match[2];
|
|
282
|
-
parts.push(React.createElement(Box, { key: `code-${idx}`, flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1 },
|
|
283
|
-
React.createElement(Text, { dimColor: true }, language),
|
|
284
|
-
React.createElement(Text, { color: "cyan" }, code)));
|
|
285
|
-
lastIndex = match.index + match[0].length;
|
|
286
|
-
idx++;
|
|
287
|
-
}
|
|
288
|
-
// Remaining text
|
|
289
|
-
if (lastIndex < content.length) {
|
|
290
|
-
parts.push(React.createElement(Text, { key: `text-${idx}` }, content.slice(lastIndex)));
|
|
291
|
-
}
|
|
292
|
-
return React.createElement(Box, { flexDirection: "column" }, parts);
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* Format file tree output
|
|
296
|
-
* Pattern: 📁 LIST DIRECTORY (path)
|
|
297
|
-
* ↳ Listed X items.
|
|
298
|
-
*/
|
|
299
|
-
const formatFileTree = (content, toolInfo) => {
|
|
300
|
-
let itemCount = 0;
|
|
301
|
-
let directory = 'current directory';
|
|
302
|
-
// Get directory from toolInfo args
|
|
303
|
-
if (toolInfo?.args?.path) {
|
|
304
|
-
directory = toolInfo?.args.path;
|
|
305
|
-
}
|
|
306
|
-
// Count items from tree output
|
|
307
|
-
if (content) {
|
|
308
|
-
const lines = content.split('\n').filter(line => {
|
|
309
|
-
const trimmed = line.trim();
|
|
310
|
-
return trimmed && !trimmed.startsWith('Failed');
|
|
311
|
-
});
|
|
312
|
-
itemCount = lines.length;
|
|
313
|
-
}
|
|
314
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
315
|
-
React.createElement(Text, { bold: true, color: "cyan" },
|
|
316
|
-
"\uD83D\uDCC1 LIST DIRECTORY ",
|
|
317
|
-
React.createElement(Text, { color: "gray" },
|
|
318
|
-
"(",
|
|
319
|
-
directory,
|
|
320
|
-
")")),
|
|
321
|
-
React.createElement(Box, { marginLeft: 1 },
|
|
322
|
-
React.createElement(Text, { color: "green" },
|
|
323
|
-
"\u21B3 Listed ",
|
|
324
|
-
itemCount,
|
|
325
|
-
" items."))));
|
|
326
|
-
};
|
|
327
|
-
/**
|
|
328
|
-
* Format file read output
|
|
329
|
-
* Pattern: 📄 READ (filename)
|
|
330
|
-
* ↳ Read X lines.
|
|
331
|
-
*/
|
|
332
|
-
const formatFileRead = (content, toolInfo) => {
|
|
333
|
-
let lineCount = 0;
|
|
334
|
-
let fileName = 'file';
|
|
335
|
-
// Get file name from toolInfo args
|
|
336
|
-
if (toolInfo?.args?.path) {
|
|
337
|
-
const parts = toolInfo.args.path.split('/');
|
|
338
|
-
fileName = parts[parts.length - 1] || toolInfo.args.path;
|
|
339
|
-
}
|
|
340
|
-
// Count lines from content
|
|
341
|
-
if (content) {
|
|
342
|
-
lineCount = content.split('\n').length;
|
|
343
|
-
}
|
|
344
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
345
|
-
React.createElement(Text, { bold: true, color: "cyan" },
|
|
346
|
-
"\uD83D\uDCC4 READ ",
|
|
347
|
-
React.createElement(Text, { color: "gray" },
|
|
348
|
-
"(",
|
|
349
|
-
fileName,
|
|
350
|
-
")")),
|
|
351
|
-
React.createElement(Box, { marginLeft: 1 },
|
|
352
|
-
React.createElement(Text, { color: "green" },
|
|
353
|
-
"\u21B3 Read ",
|
|
354
|
-
lineCount,
|
|
355
|
-
" lines."))));
|
|
356
|
-
};
|
|
357
|
-
/**
|
|
358
|
-
* Format file write output with diff view
|
|
359
|
-
* Handles both new file creation and file updates
|
|
360
|
-
*/
|
|
361
|
-
const formatFileWrite = (content, toolInfo) => {
|
|
362
|
-
let fileName = 'file';
|
|
363
|
-
let writeResult = null;
|
|
364
|
-
// Try to parse FileWriteResult from content
|
|
365
|
-
try {
|
|
366
|
-
writeResult = JSON.parse(content);
|
|
367
|
-
}
|
|
368
|
-
catch {
|
|
369
|
-
// Fallback: treat as new file with content from args
|
|
370
|
-
if (toolInfo?.args?.content) {
|
|
371
|
-
writeResult = {
|
|
372
|
-
isNewFile: true,
|
|
373
|
-
newContent: toolInfo.args.content,
|
|
374
|
-
linesAdded: toolInfo.args.content.split('\n').length,
|
|
375
|
-
linesRemoved: 0,
|
|
376
|
-
path: toolInfo.args.path,
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
if (!writeResult) {
|
|
381
|
-
return React.createElement(Text, { wrap: "wrap" }, content);
|
|
382
|
-
}
|
|
383
|
-
// Get file name
|
|
384
|
-
if (writeResult.path) {
|
|
385
|
-
const parts = writeResult.path.split('/');
|
|
386
|
-
fileName = parts[parts.length - 1] || writeResult.path;
|
|
387
|
-
}
|
|
388
|
-
const { isNewFile, oldContent, newContent, linesAdded, linesRemoved } = writeResult;
|
|
389
|
-
// Header and status
|
|
390
|
-
const statusText = isNewFile
|
|
391
|
-
? `Succeeded. File created. (+${linesAdded} added)`
|
|
392
|
-
: `Succeeded. File edited. (+${linesAdded} added, -${linesRemoved} removed)`;
|
|
393
|
-
// Calculate max content width (terminal width - border - padding - line numbers)
|
|
394
|
-
const terminalWidth = getTerminalWidth();
|
|
395
|
-
const maxContentWidth = terminalWidth - 15; // Reserve space for borders, padding, line numbers
|
|
396
|
-
if (isNewFile) {
|
|
397
|
-
// New file: show only first 10 lines
|
|
398
|
-
const diffLines = [];
|
|
399
|
-
const contentLines = newContent.split('\n');
|
|
400
|
-
const MAX_DISPLAY_LINES = 10;
|
|
401
|
-
// Chỉ hiển thị 10 dòng đầu nếu file có nhiều hơn 10 dòng
|
|
402
|
-
const linesToShow = contentLines.length > MAX_DISPLAY_LINES
|
|
403
|
-
? contentLines.slice(0, MAX_DISPLAY_LINES)
|
|
404
|
-
: contentLines;
|
|
405
|
-
linesToShow.forEach((line, idx) => {
|
|
406
|
-
const truncated = truncateLine(line, maxContentWidth);
|
|
407
|
-
diffLines.push(React.createElement(Box, { key: idx },
|
|
408
|
-
React.createElement(Text, { dimColor: true }, String(idx + 1).padStart(4, ' ')),
|
|
409
|
-
React.createElement(Text, { color: "green" }, ` + ${truncated}`)));
|
|
410
|
-
});
|
|
411
|
-
// Thêm dòng "..." nếu có nhiều hơn 10 dòng
|
|
412
|
-
if (contentLines.length > MAX_DISPLAY_LINES) {
|
|
413
|
-
diffLines.push(React.createElement(Box, { key: "truncated" },
|
|
414
|
-
React.createElement(Text, { dimColor: true },
|
|
415
|
-
"... (",
|
|
416
|
-
contentLines.length - MAX_DISPLAY_LINES,
|
|
417
|
-
" more lines)")));
|
|
418
|
-
}
|
|
419
|
-
return (React.createElement(Box, { flexDirection: "column", width: terminalWidth - 2 },
|
|
420
|
-
React.createElement(Text, { bold: true, color: "cyan" },
|
|
421
|
-
"\uD83D\uDCDD APPLY PATCH ",
|
|
422
|
-
React.createElement(Text, { color: "gray" },
|
|
423
|
-
"(",
|
|
424
|
-
fileName,
|
|
425
|
-
")")),
|
|
426
|
-
React.createElement(Box, { marginLeft: 1, marginBottom: 1 },
|
|
427
|
-
React.createElement(Text, { color: "green" },
|
|
428
|
-
"\u21B3 ",
|
|
429
|
-
statusText)),
|
|
430
|
-
React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, paddingY: 0, width: terminalWidth - 4 }, diffLines)));
|
|
431
|
-
}
|
|
432
|
-
else {
|
|
433
|
-
// File edited: show full diff
|
|
434
|
-
const diffLines = generateDiff(oldContent || '', newContent);
|
|
435
|
-
const compressedDiff = compressDiff(diffLines, 2);
|
|
436
|
-
const diffElements = [];
|
|
437
|
-
compressedDiff.forEach((line, idx) => {
|
|
438
|
-
if (line.content.startsWith('...') &&
|
|
439
|
-
line.content.includes('unchanged')) {
|
|
440
|
-
// Placeholder for skipped lines
|
|
441
|
-
diffElements.push(React.createElement(Box, { key: idx },
|
|
442
|
-
React.createElement(Text, { dimColor: true }, line.content)));
|
|
443
|
-
}
|
|
444
|
-
else if (line.type === 'add') {
|
|
445
|
-
const truncated = truncateLine(line.content, maxContentWidth);
|
|
446
|
-
diffElements.push(React.createElement(Box, { key: idx },
|
|
447
|
-
React.createElement(Text, { dimColor: true }, ' '.padStart(4, ' ')),
|
|
448
|
-
React.createElement(Text, { dimColor: true }, "|"),
|
|
449
|
-
React.createElement(Text, { dimColor: true }, String(line.newLineNum).padStart(4, ' ')),
|
|
450
|
-
React.createElement(Text, { color: "green" }, ` + ${truncated}`)));
|
|
451
|
-
}
|
|
452
|
-
else if (line.type === 'remove') {
|
|
453
|
-
const truncated = truncateLine(line.content, maxContentWidth);
|
|
454
|
-
diffElements.push(React.createElement(Box, { key: idx },
|
|
455
|
-
React.createElement(Text, { dimColor: true }, String(line.oldLineNum).padStart(4, ' ')),
|
|
456
|
-
React.createElement(Text, { dimColor: true }, "|"),
|
|
457
|
-
React.createElement(Text, { dimColor: true }, ' '.padStart(4, ' ')),
|
|
458
|
-
React.createElement(Text, { color: "red" }, ` - ${truncated}`)));
|
|
459
|
-
}
|
|
460
|
-
else {
|
|
461
|
-
// Context line
|
|
462
|
-
const truncated = truncateLine(line.content, maxContentWidth);
|
|
463
|
-
diffElements.push(React.createElement(Box, { key: idx },
|
|
464
|
-
React.createElement(Text, { dimColor: true }, String(line.oldLineNum).padStart(4, ' ')),
|
|
465
|
-
React.createElement(Text, { dimColor: true }, "|"),
|
|
466
|
-
React.createElement(Text, { dimColor: true }, String(line.newLineNum).padStart(4, ' ')),
|
|
467
|
-
React.createElement(Text, null, ` ${truncated}`)));
|
|
468
|
-
}
|
|
469
|
-
});
|
|
470
|
-
// Add truncation notice if diff is too long
|
|
471
|
-
if (diffElements.length > 30) {
|
|
472
|
-
diffElements.splice(30);
|
|
473
|
-
diffElements.push(React.createElement(Box, { key: "truncated" },
|
|
474
|
-
React.createElement(Text, { dimColor: true }, "... (diff truncated for display)")));
|
|
475
|
-
}
|
|
476
|
-
return (React.createElement(Box, { flexDirection: "column", width: terminalWidth - 2 },
|
|
477
|
-
React.createElement(Text, { bold: true, color: "cyan" },
|
|
478
|
-
"\uD83D\uDCDD APPLY PATCH ",
|
|
479
|
-
React.createElement(Text, { color: "gray" },
|
|
480
|
-
"(",
|
|
481
|
-
fileName,
|
|
482
|
-
")")),
|
|
483
|
-
React.createElement(Box, { marginLeft: 1, marginBottom: 1 },
|
|
484
|
-
React.createElement(Text, { color: "green" },
|
|
485
|
-
"\u21B3 ",
|
|
486
|
-
statusText)),
|
|
487
|
-
React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, paddingY: 0, width: terminalWidth - 4 }, diffElements)));
|
|
488
|
-
}
|
|
489
|
-
};
|
|
490
|
-
/**
|
|
491
|
-
* Format command execution output
|
|
492
|
-
* Pattern: ⚡ EXECUTE (command)
|
|
493
|
-
* ↳ ✓ Success. Output: X lines. (hoặc ✗ Failed)
|
|
494
|
-
*/
|
|
495
|
-
const formatCommandRun = (content, toolInfo) => {
|
|
496
|
-
let isSuccess = true;
|
|
497
|
-
let outputLines = 0;
|
|
498
|
-
let command = 'command';
|
|
499
|
-
// Get command from toolInfo args
|
|
500
|
-
if (toolInfo?.args?.command) {
|
|
501
|
-
command = toolInfo.args.command;
|
|
502
|
-
}
|
|
503
|
-
// Parse content to determine success/failure
|
|
504
|
-
if (content) {
|
|
505
|
-
// Format: stdout:\n...\n\nstderr:\n...
|
|
506
|
-
const stdoutMatch = content.match(/stdout:\n([\s\S]*?)\n\nstderr:/);
|
|
507
|
-
const stderrMatch = content.match(/stderr:\n([\s\S]*)/);
|
|
508
|
-
if (stdoutMatch && stdoutMatch[1]) {
|
|
509
|
-
const lines = stdoutMatch[1].split('\n').filter(line => line.trim());
|
|
510
|
-
outputLines = lines.length;
|
|
511
|
-
}
|
|
512
|
-
// Check if there's meaningful error content in stderr
|
|
513
|
-
if (stderrMatch && stderrMatch[1]) {
|
|
514
|
-
const stderrContent = stderrMatch[1].trim();
|
|
515
|
-
// Some commands output warnings to stderr but still succeed
|
|
516
|
-
// Only mark as failed if there's actual error content
|
|
517
|
-
if (stderrContent && stderrContent.toLowerCase().includes('error')) {
|
|
518
|
-
isSuccess = false;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
// Check for common error indicators
|
|
522
|
-
if (content.toLowerCase().includes('command not found') ||
|
|
523
|
-
content.toLowerCase().includes('no such file') ||
|
|
524
|
-
content.toLowerCase().includes('permission denied')) {
|
|
525
|
-
isSuccess = false;
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
const statusIcon = isSuccess ? '✓' : '✗';
|
|
529
|
-
const statusText = isSuccess ? 'Success' : 'Failed';
|
|
530
|
-
const statusColor = isSuccess ? 'green' : 'red';
|
|
531
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
532
|
-
React.createElement(Text, { bold: true, color: "cyan" },
|
|
533
|
-
"\u26A1 EXECUTE ",
|
|
534
|
-
React.createElement(Text, { color: "gray" },
|
|
535
|
-
"(",
|
|
536
|
-
command,
|
|
537
|
-
")")),
|
|
538
|
-
React.createElement(Box, { marginLeft: 1 },
|
|
539
|
-
React.createElement(Text, { color: statusColor },
|
|
540
|
-
"\u21B3 ",
|
|
541
|
-
statusIcon,
|
|
542
|
-
" ",
|
|
543
|
-
statusText,
|
|
544
|
-
". Output: ",
|
|
545
|
-
outputLines,
|
|
546
|
-
" lines."))));
|
|
547
|
-
};
|
|
548
|
-
/**
|
|
549
|
-
* Normalize tool name by removing "galaxy:" prefix if present
|
|
550
|
-
*/
|
|
551
|
-
const normalizeToolName = (toolName) => {
|
|
552
|
-
if (!toolName)
|
|
553
|
-
return '';
|
|
554
|
-
return toolName.replace(/^galaxy:/, '');
|
|
555
|
-
};
|
|
556
|
-
/**
|
|
557
|
-
* Main formatter dispatcher
|
|
558
|
-
*/
|
|
559
|
-
export function formatMessage(content, toolName, toolInfo) {
|
|
560
|
-
// Normalize tool name
|
|
561
|
-
const normalizedToolName = normalizeToolName(toolName);
|
|
562
|
-
// Convert to string if needed
|
|
563
|
-
const contentStr = typeof content === 'string' ? content : JSON.stringify(content, null, 2);
|
|
564
|
-
// Match tool-specific formatters
|
|
565
|
-
switch (normalizedToolName) {
|
|
566
|
-
case 'file_tree':
|
|
567
|
-
return formatFileTree(contentStr, toolInfo);
|
|
568
|
-
case 'file_read':
|
|
569
|
-
return formatFileRead(contentStr, toolInfo);
|
|
570
|
-
case 'file_write':
|
|
571
|
-
return formatFileWrite(contentStr, toolInfo);
|
|
572
|
-
case 'command_run':
|
|
573
|
-
return formatCommandRun(contentStr, toolInfo);
|
|
574
|
-
case 'plan_task':
|
|
575
|
-
// Plan is already displayed in planning list, don't show tool result
|
|
576
|
-
return null;
|
|
577
|
-
case 'progress_reporter':
|
|
578
|
-
// Progress updates are shown in planning list status, don't show tool result
|
|
579
|
-
return null;
|
|
580
|
-
case 'todos':
|
|
581
|
-
return formatTodos(contentStr);
|
|
582
|
-
case 'diff':
|
|
583
|
-
return formatDiff(contentStr, toolName);
|
|
584
|
-
case 'code':
|
|
585
|
-
return formatCode(contentStr);
|
|
586
|
-
default:
|
|
587
|
-
// Full content display with word wrap
|
|
588
|
-
return React.createElement(Text, { wrap: "wrap" }, contentStr);
|
|
589
|
-
}
|
|
590
|
-
}
|