@code4bug/jarvis-agent 1.3.4 → 1.3.5

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.
@@ -91,6 +91,7 @@ vibe: 你的全能助手,有问必答,随时待命。
91
91
  - 涉及代码时,代码必须可直接运行,无语法错误
92
92
  - 多方案时先推荐最优解,再列备选
93
93
  - 根据问题类型灵活调整输出格式:代码用代码块、信息用结构化列表、分析用表格等
94
+ - 用户消息里的文件名、路径、命令、参数、扩展名必须逐字保留,不得擅自纠错或改写;若目标不存在,先检查目录或搜索再判断
94
95
 
95
96
  ### 沟通风格
96
97
  - 默认中文回答,代码注释优先中文
@@ -1,11 +1,13 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import React, { useMemo } from 'react';
3
- import { Box, Text } from 'ink';
3
+ import { Box, Text, useStdout } from 'ink';
4
4
  import { Marked } from 'marked';
5
5
  // @ts-ignore — marked-terminal 无内置类型声明
6
6
  import { markedTerminal } from 'marked-terminal';
7
7
  // @ts-ignore
8
8
  import Table from 'cli-table3';
9
+ // @ts-ignore — wrap-ansi 无显式类型声明
10
+ import wrapAnsi from 'wrap-ansi';
9
11
  // ===== ANSI 颜色常量 =====
10
12
  const RESET = '\x1b[0m';
11
13
  const BG_CODE = '\x1b[48;5;236m'; // 深灰背景
@@ -154,6 +156,29 @@ function renderMarkdown(text) {
154
156
  return text;
155
157
  }
156
158
  }
159
+ function wrapRenderedLine(line, width) {
160
+ if (!line)
161
+ return [''];
162
+ const safeWidth = Math.max(width, 12);
163
+ const plainLine = stripAnsi(line);
164
+ const listPrefixMatch = plainLine.match(/^(\s*(?:[*+-]|\d+\.)\s+)/);
165
+ if (!listPrefixMatch) {
166
+ return wrapAnsi(line, safeWidth, {
167
+ hard: true,
168
+ trim: false,
169
+ wordWrap: false,
170
+ }).split('\n');
171
+ }
172
+ const prefix = listPrefixMatch[1];
173
+ const content = line.slice(prefix.length);
174
+ const contentWidth = Math.max(safeWidth - prefix.length, 8);
175
+ const wrappedContent = wrapAnsi(content, contentWidth, {
176
+ hard: true,
177
+ trim: false,
178
+ wordWrap: false,
179
+ }).split('\n');
180
+ return wrappedContent.map((segment, index) => (`${index === 0 ? prefix : ' '.repeat(prefix.length)}${segment}`));
181
+ }
157
182
  /**
158
183
  * Markdown 终端渲染组件
159
184
  * 支持表格(动态列宽+自动换行)、代码块(深色背景+边框)、加粗、列表等
@@ -164,10 +189,14 @@ function renderMarkdown(text) {
164
189
  * 与 ANSI 转义序列冲突,出现光标错位和输出错乱。
165
190
  */
166
191
  function MarkdownText({ text, color }) {
192
+ const { stdout } = useStdout();
167
193
  const lines = useMemo(() => {
168
194
  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))) }));
195
+ const availableWidth = Math.max(Math.min(stdout?.columns ?? 80, 100) - 6, 20);
196
+ return rendered
197
+ .split('\n')
198
+ .flatMap((line) => wrapRenderedLine(line, availableWidth));
199
+ }, [text, stdout]);
200
+ return (_jsx(Box, { flexDirection: "column", children: lines.map((line, i) => (_jsx(Text, { color: color, children: line || ' ' }, i))) }));
172
201
  }
173
202
  export default React.memo(MarkdownText);
@@ -186,6 +186,9 @@ export class LLMServiceImpl {
186
186
  '\n\n[安全围栏] 系统已内置安全围栏(Safeguard),会自动拦截危险命令并弹出交互式确认菜单。' +
187
187
  '当你需要执行任何命令时,直接调用 Bash 工具即可,不要自行判断命令是否危险,不要用文字询问用户"是否确认执行"。' +
188
188
  '安全围栏会自动处理拦截和用户确认流程。' +
189
+ '\n\n[文件与命令保真] 用户消息中出现的文件名、目录名、路径、命令、参数、扩展名,必须按原文逐字使用,不得自行纠错、改写、补全或翻译。' +
190
+ '即使你怀疑用户有拼写错误,也必须先按原文检查;若原文目标不存在,再基于目录扫描结果给出候选项。' +
191
+ '尤其不要把相似文件名擅自改成你认为“更正确”的拼写。' +
189
192
  '\n\n[文件修改约束] 修改已有文件时,先读取目标文件,再优先使用局部修改方式。' +
190
193
  '如果只改少量内容,优先使用 write_file 的 replace 模式;需要结构化补丁时使用 diff 模式;只有新建文件或确实需要大范围重写时才使用 overwrite。';
191
194
  // 追加系统环境信息,帮助 LLM 感知用户运行环境
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code4bug/jarvis-agent",
3
- "version": "1.3.4",
3
+ "version": "1.3.5",
4
4
  "description": "基于 React + TypeScript + Ink 构建的命令行智能体交互界面",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",