@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.
Files changed (65) hide show
  1. package/README.md +1 -1
  2. package/dist/agents/jarvis.md +1 -1
  3. package/dist/commands/init.js +4 -4
  4. package/dist/components/AnimatedStatusText.d.ts +10 -0
  5. package/dist/components/AnimatedStatusText.js +17 -0
  6. package/dist/components/ComposerPane.d.ts +25 -0
  7. package/dist/components/ComposerPane.js +10 -0
  8. package/dist/components/FooterPane.d.ts +9 -0
  9. package/dist/components/FooterPane.js +22 -0
  10. package/dist/components/InputTextView.d.ts +11 -0
  11. package/dist/components/InputTextView.js +44 -0
  12. package/dist/components/MarkdownText.d.ts +4 -0
  13. package/dist/components/MarkdownText.js +10 -3
  14. package/dist/components/MessageItem.js +4 -1
  15. package/dist/components/MessageList.d.ts +9 -0
  16. package/dist/components/MessageList.js +8 -0
  17. package/dist/components/MessageViewport.d.ts +21 -0
  18. package/dist/components/MessageViewport.js +11 -0
  19. package/dist/components/MultilineInput.js +62 -344
  20. package/dist/components/StatusBar.js +9 -6
  21. package/dist/components/StreamingDraft.d.ts +11 -0
  22. package/dist/components/StreamingDraft.js +14 -0
  23. package/dist/components/WelcomeHeader.js +4 -2
  24. package/dist/components/inputEditing.d.ts +20 -0
  25. package/dist/components/inputEditing.js +48 -0
  26. package/dist/components/setup/SetupConfirmStep.d.ts +8 -0
  27. package/dist/components/setup/SetupConfirmStep.js +12 -0
  28. package/dist/components/setup/SetupDoneStep.d.ts +7 -0
  29. package/dist/components/setup/SetupDoneStep.js +5 -0
  30. package/dist/components/setup/SetupFormStep.d.ts +11 -0
  31. package/dist/components/setup/SetupFormStep.js +44 -0
  32. package/dist/components/setup/SetupHeader.d.ts +9 -0
  33. package/dist/components/setup/SetupHeader.js +25 -0
  34. package/dist/components/setup/SetupProviderStep.d.ts +6 -0
  35. package/dist/components/setup/SetupProviderStep.js +20 -0
  36. package/dist/components/setup/SetupWelcomeStep.d.ts +5 -0
  37. package/dist/components/setup/SetupWelcomeStep.js +5 -0
  38. package/dist/config/bootstrap.d.ts +38 -0
  39. package/dist/config/bootstrap.js +155 -0
  40. package/dist/config/constants.d.ts +7 -6
  41. package/dist/config/constants.js +29 -16
  42. package/dist/config/loader.d.ts +2 -0
  43. package/dist/config/loader.js +4 -0
  44. package/dist/core/hint.js +3 -3
  45. package/dist/core/query.js +3 -2
  46. package/dist/hooks/useMultilineInputStream.d.ts +17 -0
  47. package/dist/hooks/useMultilineInputStream.js +141 -0
  48. package/dist/hooks/useTerminalCursorSync.d.ts +8 -0
  49. package/dist/hooks/useTerminalCursorSync.js +44 -0
  50. package/dist/hooks/useTerminalSize.d.ts +7 -0
  51. package/dist/hooks/useTerminalSize.js +21 -0
  52. package/dist/index.js +2 -2
  53. package/dist/screens/AppBootstrap.d.ts +1 -0
  54. package/dist/screens/AppBootstrap.js +14 -0
  55. package/dist/screens/repl.js +39 -28
  56. package/dist/screens/setup/SetupWizard.d.ts +7 -0
  57. package/dist/screens/setup/SetupWizard.js +198 -0
  58. package/dist/services/api/llm.js +5 -3
  59. package/dist/skills/index.js +10 -3
  60. package/dist/terminal/cursor.d.ts +6 -0
  61. package/dist/terminal/cursor.js +21 -0
  62. package/dist/tools/createSkill.js +59 -1
  63. package/dist/tools/readFile.js +28 -3
  64. package/dist/tools/writeFile.js +63 -2
  65. package/package.json +1 -1
package/README.md CHANGED
@@ -139,7 +139,7 @@ jarvis --version
139
139
  | 工具名 | 说明 |
140
140
  | --- | --- |
141
141
  | `read_file` | 读取文件 |
142
- | `write_file` | 写入文件 |
142
+ | `write_file` | 写入文件,支持整文件覆盖或局部修改 |
143
143
  | `run_command` | 执行命令 |
144
144
  | `list_directory` | 列出目录内容 |
145
145
  | `search_files` | 搜索文件内容 |
@@ -58,7 +58,7 @@ vibe: 你的全能助手,有问必答,随时待命。
58
58
  - 自动化脚本编写
59
59
 
60
60
  ### 信息检索与知识问答
61
- - 利用联网搜索工具(tavily_search)获取实时信息,包括新闻、天气、热点事件等
61
+ - 利用联网搜索工具(web_search)获取实时信息,包括新闻、天气、热点事件等
62
62
  - 回答各领域知识问题:科技、历史、地理、文化、商业等
63
63
  - 信息汇总、对比分析、趋势解读
64
64
 
@@ -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 { APP_NAME, APP_VERSION } from '../config/constants.js';
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(`> 由 ${APP_NAME} /init 自动生成`);
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(`> 由 ${APP_NAME} /init 自动生成`);
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(`${APP_NAME} ${APP_VERSION} - 项目初始化`);
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 rendered = useMemo(() => renderMarkdown(text), [text]);
164
- return (_jsx(Text, { wrap: "wrap", color: color, children: rendered }));
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: [_jsx(Text, { color: dotColor, children: dot }), _jsx(Box, { marginLeft: 2, flexDirection: "column", children: _jsx(MarkdownText, { text: msg.content, color: "gray" }) }), _jsx(MessageStats, { msg: msg, show: showDetails })] }));
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);