@code4bug/jarvis-agent 1.1.8 → 1.3.1
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 +1 -1
- package/dist/agents/jarvis.md +1 -1
- package/dist/commands/init.js +4 -4
- package/dist/components/AnimatedStatusText.d.ts +10 -0
- package/dist/components/AnimatedStatusText.js +17 -0
- package/dist/components/ComposerPane.d.ts +25 -0
- package/dist/components/ComposerPane.js +10 -0
- package/dist/components/FooterPane.d.ts +9 -0
- package/dist/components/FooterPane.js +22 -0
- package/dist/components/InputTextView.d.ts +11 -0
- package/dist/components/InputTextView.js +44 -0
- package/dist/components/MarkdownText.d.ts +4 -0
- package/dist/components/MarkdownText.js +10 -3
- package/dist/components/MessageItem.js +4 -1
- package/dist/components/MessageList.d.ts +9 -0
- package/dist/components/MessageList.js +8 -0
- package/dist/components/MessageViewport.d.ts +21 -0
- package/dist/components/MessageViewport.js +11 -0
- package/dist/components/MultilineInput.js +62 -344
- package/dist/components/StatusBar.js +9 -6
- package/dist/components/StreamingDraft.d.ts +11 -0
- package/dist/components/StreamingDraft.js +14 -0
- package/dist/components/WelcomeHeader.js +4 -2
- package/dist/components/inputEditing.d.ts +20 -0
- package/dist/components/inputEditing.js +48 -0
- package/dist/components/setup/SetupConfirmStep.d.ts +8 -0
- package/dist/components/setup/SetupConfirmStep.js +12 -0
- package/dist/components/setup/SetupDoneStep.d.ts +7 -0
- package/dist/components/setup/SetupDoneStep.js +5 -0
- package/dist/components/setup/SetupFormStep.d.ts +11 -0
- package/dist/components/setup/SetupFormStep.js +44 -0
- package/dist/components/setup/SetupHeader.d.ts +9 -0
- package/dist/components/setup/SetupHeader.js +25 -0
- package/dist/components/setup/SetupProviderStep.d.ts +6 -0
- package/dist/components/setup/SetupProviderStep.js +20 -0
- package/dist/components/setup/SetupWelcomeStep.d.ts +5 -0
- package/dist/components/setup/SetupWelcomeStep.js +5 -0
- package/dist/config/bootstrap.d.ts +38 -0
- package/dist/config/bootstrap.js +155 -0
- package/dist/config/constants.d.ts +7 -6
- package/dist/config/constants.js +29 -16
- package/dist/config/loader.d.ts +2 -0
- package/dist/config/loader.js +4 -0
- package/dist/core/hint.js +3 -3
- package/dist/core/query.js +3 -2
- package/dist/hooks/useMultilineInputStream.d.ts +17 -0
- package/dist/hooks/useMultilineInputStream.js +141 -0
- package/dist/hooks/useTerminalCursorSync.d.ts +8 -0
- package/dist/hooks/useTerminalCursorSync.js +44 -0
- package/dist/hooks/useTerminalSize.d.ts +7 -0
- package/dist/hooks/useTerminalSize.js +21 -0
- package/dist/index.js +2 -2
- package/dist/screens/AppBootstrap.d.ts +1 -0
- package/dist/screens/AppBootstrap.js +14 -0
- package/dist/screens/repl.js +39 -28
- package/dist/screens/setup/SetupWizard.d.ts +7 -0
- package/dist/screens/setup/SetupWizard.js +198 -0
- package/dist/services/api/llm.js +5 -3
- package/dist/skills/index.js +10 -3
- package/dist/terminal/cursor.d.ts +6 -0
- package/dist/terminal/cursor.js +21 -0
- package/dist/tools/createSkill.js +59 -1
- package/dist/tools/readFile.js +28 -3
- package/dist/tools/writeFile.js +63 -2
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/agents/jarvis.md
CHANGED
package/dist/commands/init.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import fs from 'fs';
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import { execSync } from 'child_process';
|
|
10
|
-
import {
|
|
10
|
+
import { APP_VERSION, getAppName } from '../config/constants.js';
|
|
11
11
|
import { LLMServiceImpl, getDefaultConfig } from '../services/api/llm.js';
|
|
12
12
|
import { allTools } from '../tools/index.js';
|
|
13
13
|
import { loadAllAgents } from '../agents/index.js';
|
|
@@ -358,7 +358,7 @@ function renderJarvisMd(input) {
|
|
|
358
358
|
md.push(`- ${line}`);
|
|
359
359
|
}
|
|
360
360
|
md.push('');
|
|
361
|
-
md.push(`> 由 ${
|
|
361
|
+
md.push(`> 由 ${getAppName()} /init 自动生成`);
|
|
362
362
|
md.push('');
|
|
363
363
|
return md.join('\n');
|
|
364
364
|
}
|
|
@@ -508,7 +508,7 @@ function generateBasicJarvisMd(input) {
|
|
|
508
508
|
md.push('');
|
|
509
509
|
md.push('- 本文件为自动生成结果;若需更准确的业务背景,请补充 README 或项目文档。');
|
|
510
510
|
md.push('');
|
|
511
|
-
md.push(`> 由 ${
|
|
511
|
+
md.push(`> 由 ${getAppName()} /init 自动生成`);
|
|
512
512
|
md.push('');
|
|
513
513
|
return md.join('\n');
|
|
514
514
|
}
|
|
@@ -522,7 +522,7 @@ export async function executeInit() {
|
|
|
522
522
|
const dirTree = scanDirectoryTree(cwd);
|
|
523
523
|
// ===== 构建终端显示文本 =====
|
|
524
524
|
const display = [];
|
|
525
|
-
display.push(`${
|
|
525
|
+
display.push(`${getAppName()} ${APP_VERSION} - 项目初始化`);
|
|
526
526
|
display.push('');
|
|
527
527
|
// 项目基本信息
|
|
528
528
|
display.push('[ 项目信息 ]');
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface AnimatedStatusTextProps {
|
|
3
|
+
label: string;
|
|
4
|
+
color?: string;
|
|
5
|
+
dotColor?: string;
|
|
6
|
+
intervalMs?: number;
|
|
7
|
+
}
|
|
8
|
+
declare function AnimatedStatusText({ label, color, dotColor, intervalMs, }: AnimatedStatusTextProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
declare const _default: React.MemoExoticComponent<typeof AnimatedStatusText>;
|
|
10
|
+
export default _default;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React, { useEffect, useState } from 'react';
|
|
3
|
+
import { Text } from 'ink';
|
|
4
|
+
const FRAMES = [' ', '. ', '.. ', '...'];
|
|
5
|
+
function AnimatedStatusText({ label, color = 'gray', dotColor = 'yellow', intervalMs = 600, }) {
|
|
6
|
+
const [frameIndex, setFrameIndex] = useState(0);
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const timer = setInterval(() => {
|
|
9
|
+
setFrameIndex((prev) => (prev + 1) % FRAMES.length);
|
|
10
|
+
}, intervalMs);
|
|
11
|
+
return () => {
|
|
12
|
+
clearInterval(timer);
|
|
13
|
+
};
|
|
14
|
+
}, [intervalMs]);
|
|
15
|
+
return (_jsxs(Text, { color: color, children: [_jsx(Text, { color: dotColor, children: "\u25CF" }), ' ', label, FRAMES[frameIndex]] }));
|
|
16
|
+
}
|
|
17
|
+
export default React.memo(AnimatedStatusText);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SlashCommand } from '../commands/index.js';
|
|
3
|
+
interface ComposerPaneProps {
|
|
4
|
+
width: number;
|
|
5
|
+
countdown: number | null;
|
|
6
|
+
isProcessing: boolean;
|
|
7
|
+
input: string;
|
|
8
|
+
placeholder: string;
|
|
9
|
+
windowFocused: boolean;
|
|
10
|
+
slashMenuVisible: boolean;
|
|
11
|
+
slashMenuItems: SlashCommand[];
|
|
12
|
+
slashMenuIndex: number;
|
|
13
|
+
onInputChange: (value: string) => void;
|
|
14
|
+
onSubmit: (value: string) => Promise<void>;
|
|
15
|
+
onUpArrow: () => void;
|
|
16
|
+
onDownArrow: () => void;
|
|
17
|
+
onSlashMenuUp: () => void;
|
|
18
|
+
onSlashMenuDown: () => void;
|
|
19
|
+
onSlashMenuSelect: () => void;
|
|
20
|
+
onSlashMenuClose: () => void;
|
|
21
|
+
onTabFillPlaceholder: () => void;
|
|
22
|
+
}
|
|
23
|
+
declare function ComposerPane({ width, countdown, isProcessing, input, placeholder, windowFocused, slashMenuVisible, slashMenuItems, slashMenuIndex, onInputChange, onSubmit, onUpArrow, onDownArrow, onSlashMenuUp, onSlashMenuDown, onSlashMenuSelect, onSlashMenuClose, onTabFillPlaceholder, }: ComposerPaneProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
declare const _default: React.MemoExoticComponent<typeof ComposerPane>;
|
|
25
|
+
export default _default;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
|
+
import Spinner from 'ink-spinner';
|
|
5
|
+
import MultilineInput from './MultilineInput.js';
|
|
6
|
+
import SlashCommandMenu from './SlashCommandMenu.js';
|
|
7
|
+
function ComposerPane({ width, countdown, isProcessing, input, placeholder, windowFocused, slashMenuVisible, slashMenuItems, slashMenuIndex, onInputChange, onSubmit, onUpArrow, onDownArrow, onSlashMenuUp, onSlashMenuDown, onSlashMenuSelect, onSlashMenuClose, onTabFillPlaceholder, }) {
|
|
8
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(Text, { color: "gray", children: '─'.repeat(Math.max(width - 2, 1)) }), slashMenuVisible && !isProcessing && (_jsx(SlashCommandMenu, { commands: slashMenuItems, selectedIndex: slashMenuIndex })), _jsx(Box, { children: countdown !== null ? (_jsxs(Box, { children: [_jsx(Text, { color: "gray", dimColor: true, children: "\u276F " }), _jsx(Text, { color: "yellow", children: "Press " }), _jsx(Text, { color: "yellow", bold: true, children: "Ctrl+C" }), _jsx(Text, { color: "yellow", children: " again to exit " }), _jsxs(Text, { color: "gray", dimColor: true, children: ["(", countdown, "s)"] })] })) : isProcessing ? (_jsxs(Box, { children: [_jsx(Text, { color: "cyan", bold: true, children: "\u276F " }), _jsx(Text, { color: "yellow", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { color: "gray", italic: true, children: " processing..." })] })) : (_jsxs(Box, { children: [_jsx(Text, { color: "cyan", bold: true, children: "\u276F " }), _jsx(MultilineInput, { value: input, onChange: onInputChange, onSubmit: onSubmit, onUpArrow: onUpArrow, onDownArrow: onDownArrow, placeholder: placeholder, isActive: !isProcessing, showCursor: windowFocused && !isProcessing, slashMenuActive: slashMenuVisible, onSlashMenuUp: onSlashMenuUp, onSlashMenuDown: onSlashMenuDown, onSlashMenuSelect: onSlashMenuSelect, onSlashMenuClose: onSlashMenuClose, onTabFillPlaceholder: onTabFillPlaceholder })] })) })] }));
|
|
9
|
+
}
|
|
10
|
+
export default React.memo(ComposerPane);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface FooterPaneProps {
|
|
3
|
+
width: number;
|
|
4
|
+
tokenCountRef: React.MutableRefObject<number>;
|
|
5
|
+
activeAgents: number;
|
|
6
|
+
}
|
|
7
|
+
declare function FooterPane({ width, tokenCountRef, activeAgents }: FooterPaneProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
declare const _default: React.MemoExoticComponent<typeof FooterPane>;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React, { useEffect, useState } from 'react';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
|
+
import StatusBar from './StatusBar.js';
|
|
5
|
+
const TOKEN_REFRESH_INTERVAL = 100;
|
|
6
|
+
function FooterPane({ width, tokenCountRef, activeAgents }) {
|
|
7
|
+
const [displayTokens, setDisplayTokens] = useState(() => tokenCountRef.current);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
setDisplayTokens(tokenCountRef.current);
|
|
10
|
+
const timer = setInterval(() => {
|
|
11
|
+
setDisplayTokens((prev) => {
|
|
12
|
+
const next = tokenCountRef.current;
|
|
13
|
+
return prev === next ? prev : next;
|
|
14
|
+
});
|
|
15
|
+
}, TOKEN_REFRESH_INTERVAL);
|
|
16
|
+
return () => {
|
|
17
|
+
clearInterval(timer);
|
|
18
|
+
};
|
|
19
|
+
}, [tokenCountRef]);
|
|
20
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(Text, { color: "gray", children: '─'.repeat(Math.max(width - 2, 1)) }), _jsx(StatusBar, { width: width - 2, totalTokens: displayTokens, activeAgents: activeAgents })] }));
|
|
21
|
+
}
|
|
22
|
+
export default React.memo(FooterPane);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface InputTextViewProps {
|
|
3
|
+
value: string;
|
|
4
|
+
cursor: number;
|
|
5
|
+
placeholder: string;
|
|
6
|
+
showCursor: boolean;
|
|
7
|
+
onResetPastedChunks?: () => void;
|
|
8
|
+
}
|
|
9
|
+
declare function InputTextView({ value, cursor, placeholder, showCursor, onResetPastedChunks, }: InputTextViewProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
declare const _default: React.MemoExoticComponent<typeof InputTextView>;
|
|
11
|
+
export default _default;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
|
+
import { getCursorRowCol, PASTE_PLACEHOLDER_RE } from './inputEditing.js';
|
|
5
|
+
function renderWithPlaceholders(text, keyPrefix) {
|
|
6
|
+
const parts = [];
|
|
7
|
+
let lastIndex = 0;
|
|
8
|
+
const re = new RegExp(PASTE_PLACEHOLDER_RE.source, 'g');
|
|
9
|
+
let m;
|
|
10
|
+
while ((m = re.exec(text)) !== null) {
|
|
11
|
+
if (m.index > lastIndex) {
|
|
12
|
+
parts.push(_jsx(Text, { children: text.slice(lastIndex, m.index) }, `${keyPrefix}-t-${lastIndex}`));
|
|
13
|
+
}
|
|
14
|
+
parts.push(_jsx(Text, { color: "cyan", dimColor: true, children: m[0] }, `${keyPrefix}-p-${m.index}`));
|
|
15
|
+
lastIndex = m.index + m[0].length;
|
|
16
|
+
}
|
|
17
|
+
if (lastIndex < text.length) {
|
|
18
|
+
parts.push(_jsx(Text, { children: text.slice(lastIndex) }, `${keyPrefix}-t-${lastIndex}`));
|
|
19
|
+
}
|
|
20
|
+
return parts;
|
|
21
|
+
}
|
|
22
|
+
function InputTextView({ value, cursor, placeholder, showCursor, onResetPastedChunks, }) {
|
|
23
|
+
const isEmpty = value.length === 0;
|
|
24
|
+
if (isEmpty) {
|
|
25
|
+
onResetPastedChunks?.();
|
|
26
|
+
if (showCursor && placeholder.length > 0) {
|
|
27
|
+
return (_jsxs(Box, { children: [_jsx(Text, { inverse: true, color: "white", children: placeholder[0] }), _jsx(Text, { color: "gray", children: placeholder.slice(1) }), _jsx(Text, { color: "gray", dimColor: true, children: " [Tab]" })] }));
|
|
28
|
+
}
|
|
29
|
+
return (_jsxs(Box, { children: [showCursor && _jsx(Text, { inverse: true, children: " " }), _jsx(Text, { color: "gray", children: placeholder })] }));
|
|
30
|
+
}
|
|
31
|
+
const lines = value.split('\n');
|
|
32
|
+
const { row: cursorRow, col: cursorCol } = getCursorRowCol(value, cursor);
|
|
33
|
+
return (_jsx(Box, { flexDirection: "column", children: lines.map((line, i) => {
|
|
34
|
+
if (!showCursor || i !== cursorRow) {
|
|
35
|
+
const parts = renderWithPlaceholders(line, `l${i}`);
|
|
36
|
+
return _jsx(Box, { children: parts.length > 0 ? parts : _jsx(Text, { children: " " }) }, i);
|
|
37
|
+
}
|
|
38
|
+
const before = line.slice(0, cursorCol);
|
|
39
|
+
const cursorChar = line[cursorCol] ?? ' ';
|
|
40
|
+
const after = line.slice(cursorCol + 1);
|
|
41
|
+
return (_jsxs(Box, { children: [renderWithPlaceholders(before, `b${i}`), _jsx(Text, { inverse: true, children: cursorChar }), renderWithPlaceholders(after, `a${i}`)] }, i));
|
|
42
|
+
}) }));
|
|
43
|
+
}
|
|
44
|
+
export default React.memo(InputTextView);
|
|
@@ -3,6 +3,10 @@ import React from 'react';
|
|
|
3
3
|
* Markdown 终端渲染组件
|
|
4
4
|
* 支持表格(动态列宽+自动换行)、代码块(深色背景+边框)、加粗、列表等
|
|
5
5
|
* 对流式不完整文本做容错补全
|
|
6
|
+
*
|
|
7
|
+
* 渲染策略:将 ANSI 字符串按 \n 拆行,每行用独立 <Text> 渲染。
|
|
8
|
+
* 直接将含 \n 的 ANSI 字符串塞入单个 <Text> 会导致 ink 布局引擎
|
|
9
|
+
* 与 ANSI 转义序列冲突,出现光标错位和输出错乱。
|
|
6
10
|
*/
|
|
7
11
|
declare function MarkdownText({ text, color }: {
|
|
8
12
|
text: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import React, { useMemo } from 'react';
|
|
3
|
-
import { Text } from 'ink';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
4
|
import { Marked } from 'marked';
|
|
5
5
|
// @ts-ignore — marked-terminal 无内置类型声明
|
|
6
6
|
import { markedTerminal } from 'marked-terminal';
|
|
@@ -158,9 +158,16 @@ function renderMarkdown(text) {
|
|
|
158
158
|
* Markdown 终端渲染组件
|
|
159
159
|
* 支持表格(动态列宽+自动换行)、代码块(深色背景+边框)、加粗、列表等
|
|
160
160
|
* 对流式不完整文本做容错补全
|
|
161
|
+
*
|
|
162
|
+
* 渲染策略:将 ANSI 字符串按 \n 拆行,每行用独立 <Text> 渲染。
|
|
163
|
+
* 直接将含 \n 的 ANSI 字符串塞入单个 <Text> 会导致 ink 布局引擎
|
|
164
|
+
* 与 ANSI 转义序列冲突,出现光标错位和输出错乱。
|
|
161
165
|
*/
|
|
162
166
|
function MarkdownText({ text, color }) {
|
|
163
|
-
const
|
|
164
|
-
|
|
167
|
+
const lines = useMemo(() => {
|
|
168
|
+
const rendered = renderMarkdown(text);
|
|
169
|
+
return rendered.split('\n');
|
|
170
|
+
}, [text]);
|
|
171
|
+
return (_jsx(Box, { flexDirection: "column", children: lines.map((line, i) => (_jsx(Text, { wrap: "wrap", color: color, children: line }, i))) }));
|
|
165
172
|
}
|
|
166
173
|
export default React.memo(MarkdownText);
|
|
@@ -79,8 +79,11 @@ function MessageItem({ msg, showDetails = false }) {
|
|
|
79
79
|
// 有 subAgentId 时:标题行 + 内容分两行,避免内容粘连
|
|
80
80
|
_jsxs(_Fragment, { children: [_jsxs(Box, { children: [_jsxs(Text, { color: dotColor, children: [dot, " "] }), _jsxs(Text, { color: "blue", dimColor: true, children: [msg.subAgentId, " \u203A "] })] }), _jsx(Box, { marginLeft: 2, flexDirection: "column", children: _jsx(MarkdownText, { text: msg.content }) })] })) : (_jsxs(Box, { flexDirection: "row", alignItems: "flex-start", children: [_jsxs(Text, { color: dotColor, children: [dot, " "] }), _jsx(Box, { flexDirection: "column", flexShrink: 1, children: _jsx(MarkdownText, { text: msg.content }) })] })), _jsx(MessageStats, { msg: msg, show: showDetails })] }));
|
|
81
81
|
}
|
|
82
|
+
if (msg.type === 'system' && msg.content) {
|
|
83
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { flexDirection: "row", alignItems: "flex-start", children: [_jsxs(Text, { color: dotColor, children: [dot, " "] }), _jsx(Box, { flexDirection: "column", flexShrink: 1, children: _jsx(MarkdownText, { text: msg.content, color: "gray" }) })] }), _jsx(MessageStats, { msg: msg, show: showDetails })] }));
|
|
84
|
+
}
|
|
82
85
|
if (msg.status !== 'pending' && msg.content) {
|
|
83
|
-
return (_jsxs(Box, { flexDirection: "column", children: [
|
|
86
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { flexDirection: "row", alignItems: "flex-start", children: [_jsxs(Text, { color: dotColor, children: [dot, " "] }), _jsx(Box, { flexDirection: "column", flexShrink: 1, children: _jsx(MarkdownText, { text: msg.content, color: "gray" }) })] }), _jsx(MessageStats, { msg: msg, show: showDetails })] }));
|
|
84
87
|
}
|
|
85
88
|
return null;
|
|
86
89
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Message } from '../types/index.js';
|
|
3
|
+
interface MessageListProps {
|
|
4
|
+
messages: Message[];
|
|
5
|
+
showDetails: boolean;
|
|
6
|
+
}
|
|
7
|
+
declare function MessageList({ messages, showDetails }: MessageListProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
declare const _default: React.MemoExoticComponent<typeof MessageList>;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Box } from 'ink';
|
|
4
|
+
import MessageItem from './MessageItem.js';
|
|
5
|
+
function MessageList({ messages, showDetails }) {
|
|
6
|
+
return (_jsx(Box, { flexDirection: "column", children: messages.map((msg) => (_jsx(MessageItem, { msg: msg, showDetails: showDetails }, msg.id))) }));
|
|
7
|
+
}
|
|
8
|
+
export default React.memo(MessageList);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ConfirmChoice } from './DangerConfirm.js';
|
|
3
|
+
import { LoopState, Message } from '../types/index.js';
|
|
4
|
+
import { DangerConfirmResult } from '../core/query.js';
|
|
5
|
+
interface DangerConfirmState {
|
|
6
|
+
command: string;
|
|
7
|
+
reason: string;
|
|
8
|
+
ruleName: string;
|
|
9
|
+
resolve: (choice: DangerConfirmResult) => void;
|
|
10
|
+
}
|
|
11
|
+
interface MessageViewportProps {
|
|
12
|
+
messages: Message[];
|
|
13
|
+
streamText: string;
|
|
14
|
+
showDetails: boolean;
|
|
15
|
+
dangerConfirm: DangerConfirmState | null;
|
|
16
|
+
loopState: LoopState | null;
|
|
17
|
+
onResolveDangerConfirm: (choice: ConfirmChoice) => void;
|
|
18
|
+
}
|
|
19
|
+
declare function MessageViewport({ messages, streamText, showDetails, dangerConfirm, loopState, onResolveDangerConfirm, }: MessageViewportProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
declare const _default: React.MemoExoticComponent<typeof MessageViewport>;
|
|
21
|
+
export default _default;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
|
+
import Spinner from 'ink-spinner';
|
|
5
|
+
import DangerConfirm from './DangerConfirm.js';
|
|
6
|
+
import MessageList from './MessageList.js';
|
|
7
|
+
import StreamingDraft from './StreamingDraft.js';
|
|
8
|
+
function MessageViewport({ messages, streamText, showDetails, dangerConfirm, loopState, onResolveDangerConfirm, }) {
|
|
9
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(MessageList, { messages: messages, showDetails: showDetails }), streamText && _jsx(StreamingDraft, { text: streamText }), dangerConfirm && (_jsx(DangerConfirm, { command: dangerConfirm.command, reason: dangerConfirm.reason, ruleName: dangerConfirm.ruleName, onSelect: onResolveDangerConfirm })), loopState?.isRunning && (_jsxs(Box, { children: [_jsx(Text, { color: "yellow", children: _jsx(Spinner, { type: "dots" }) }), _jsxs(Text, { color: "gray", children: [" iteration ", loopState.iteration, "/", loopState.maxIterations] })] }))] }));
|
|
10
|
+
}
|
|
11
|
+
export default React.memo(MessageViewport);
|