@code4bug/jarvis-agent 1.3.2 → 1.3.3
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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
3
|
* 危险命令交互式确认组件
|
|
4
4
|
*
|
|
@@ -7,21 +7,18 @@ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
|
7
7
|
* 2. 持久授权(写入 ~/.jarvis/.permissions.json)
|
|
8
8
|
* 3. 取消执行
|
|
9
9
|
*/
|
|
10
|
-
import
|
|
10
|
+
import { useState } from 'react';
|
|
11
11
|
import { Box, Text, useInput, useStdout } from 'ink';
|
|
12
12
|
const OPTIONS = [
|
|
13
13
|
{ key: 'once', label: '临时执行(仅本次会话)', color: 'yellow' },
|
|
14
14
|
{ key: 'always', label: '持久授权(写入 ~/.jarvis/.permissions.json)', color: 'green' },
|
|
15
15
|
{ key: 'cancel', label: '取消执行', color: 'red' },
|
|
16
16
|
];
|
|
17
|
-
// 圆角边框字符
|
|
18
|
-
const BORDER = { tl: '╭', tr: '╮', bl: '╰', br: '╯', h: '─', v: '│' };
|
|
19
17
|
export default function DangerConfirm({ command, reason, ruleName, onSelect }) {
|
|
20
18
|
const [selectedIndex, setSelectedIndex] = useState(2); // 默认选中「取消」,最安全
|
|
21
19
|
const { stdout } = useStdout();
|
|
22
|
-
const cols = Math.min(stdout?.columns ?? 80,
|
|
23
|
-
|
|
24
|
-
const innerWidth = cols - 4;
|
|
20
|
+
const cols = Math.min(stdout?.columns ?? 80, 84);
|
|
21
|
+
const contentWidth = Math.max(32, cols - 8);
|
|
25
22
|
useInput((_input, key) => {
|
|
26
23
|
if (key.upArrow) {
|
|
27
24
|
setSelectedIndex((prev) => (prev > 0 ? prev - 1 : OPTIONS.length - 1));
|
|
@@ -36,15 +33,14 @@ export default function DangerConfirm({ command, reason, ruleName, onSelect }) {
|
|
|
36
33
|
onSelect('cancel');
|
|
37
34
|
}
|
|
38
35
|
});
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}), _jsx(Text, { color: "yellow", children: bottomBorder })] }));
|
|
36
|
+
const section = (label, value) => (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "gray", children: label }), _jsx(Box, { width: contentWidth, marginTop: 0, children: value })] }));
|
|
37
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 1, paddingX: 1, children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { backgroundColor: "yellow", color: "black", bold: true, children: ' 安全围栏 ' }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { bold: true, color: "white", children: "\u68C0\u6D4B\u5230\u9AD8\u98CE\u9669\u547D\u4EE4" }), _jsx(Text, { color: "gray", children: "\u8BF7\u786E\u8BA4\u662F\u5426\u7EE7\u7EED\u6267\u884C" })] })] }), section('命令', _jsx(Text, { color: "white", bold: true, wrap: "truncate-end", children: command })), section('规则', _jsx(Text, { color: "cyan", children: ruleName })), section('原因', _jsx(Text, { color: "red", children: reason })), _jsx(Box, { marginTop: 2, children: _jsx(Text, { color: "gray", dimColor: true, children: "\u4F7F\u7528 \u2191\u2193 \u9009\u62E9\uFF0CEnter \u786E\u8BA4\uFF0CESC \u53D6\u6D88" }) }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: OPTIONS.map((opt, i) => {
|
|
38
|
+
const isSelected = i === selectedIndex;
|
|
39
|
+
const prefix = isSelected ? '›' : ' ';
|
|
40
|
+
const textColor = isSelected ? 'black' : opt.color;
|
|
41
|
+
const backgroundColor = isSelected
|
|
42
|
+
? (opt.color === 'yellow' ? 'yellow' : opt.color === 'green' ? 'green' : 'red')
|
|
43
|
+
: undefined;
|
|
44
|
+
return (_jsx(Box, { marginTop: i === 0 ? 0 : 1, children: _jsx(Text, { color: textColor, backgroundColor: backgroundColor, bold: isSelected, children: ` ${prefix} ${opt.label} ` }) }, opt.key));
|
|
45
|
+
}) })] }));
|
|
50
46
|
}
|
|
@@ -2,6 +2,16 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { Box, Text } from 'ink';
|
|
4
4
|
import { PROJECT_NAME, getContextTokenLimit, getModelName, isThinkingModeToggleEnabled } from '../config/constants.js';
|
|
5
|
+
import { getToolStatsText } from '../tools/index.js';
|
|
6
|
+
function truncateText(text, maxChars) {
|
|
7
|
+
if (maxChars <= 0)
|
|
8
|
+
return '';
|
|
9
|
+
if (text.length <= maxChars)
|
|
10
|
+
return text;
|
|
11
|
+
if (maxChars === 1)
|
|
12
|
+
return '…';
|
|
13
|
+
return `${text.slice(0, maxChars - 1)}…`;
|
|
14
|
+
}
|
|
5
15
|
/** 生成 token 用量进度条 */
|
|
6
16
|
function tokenProgressBar(used, limit, barWidth) {
|
|
7
17
|
const ratio = Math.min(used / limit, 1);
|
|
@@ -15,7 +25,8 @@ function StatusBar({ width, totalTokens, activeAgents = 0 }) {
|
|
|
15
25
|
const modelName = getModelName();
|
|
16
26
|
const contextTokenLimit = getContextTokenLimit();
|
|
17
27
|
const thinkingModeToggleEnabled = isThinkingModeToggleEnabled();
|
|
18
|
-
const
|
|
28
|
+
const toolStats = getToolStatsText();
|
|
29
|
+
const rawLeft = ` ${modelName} │ ${PROJECT_NAME} │ ${toolStats}`;
|
|
19
30
|
// 右侧:智能体数量(有后台 Agent 时显示)+ token 进度条 + 思考模式切换(可选)
|
|
20
31
|
const agentPart = activeAgents > 0 ? `⬡ ${activeAgents} agent${activeAgents > 1 ? 's' : ''} │ ` : '';
|
|
21
32
|
const tokenLabel = `${totalTokens}/${contextTokenLimit}`;
|
|
@@ -24,6 +35,8 @@ function StatusBar({ width, totalTokens, activeAgents = 0 }) {
|
|
|
24
35
|
const effortPart = thinkingModeToggleEnabled ? ' │ ● medium · /effort' : '';
|
|
25
36
|
// 右侧完整文本长度(用于计算间距)
|
|
26
37
|
const rightLen = agentPart.length + tokenLabel.length + 1 + barWidth + effortPart.length + 1;
|
|
38
|
+
const leftMaxWidth = Math.max(width - rightLen - 1, 1);
|
|
39
|
+
const left = truncateText(rawLeft, leftMaxWidth);
|
|
27
40
|
const gap = Math.max(width - left.length - rightLen, 1);
|
|
28
41
|
return (_jsxs(Box, { children: [_jsx(Text, { color: "gray", children: left }), _jsx(Text, { children: ' '.repeat(gap) }), activeAgents > 0 && _jsx(Text, { color: "cyan", children: agentPart }), _jsxs(Text, { color: "gray", children: [tokenLabel, " "] }), _jsx(Text, { color: color, children: bar }), thinkingModeToggleEnabled && _jsx(Text, { color: "gray", children: effortPart }), _jsx(Text, { children: " " })] }));
|
|
29
42
|
}
|
package/dist/skills/index.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import { exec } from 'child_process';
|
|
13
13
|
import fs from 'fs';
|
|
14
14
|
import path from 'path';
|
|
15
|
-
import { scanExternalSkills
|
|
15
|
+
import { scanExternalSkills } from './loader.js';
|
|
16
16
|
import { allTools as builtinTools } from '../tools/index.js';
|
|
17
17
|
// ===== 缓存 =====
|
|
18
18
|
let _skillCache = null;
|
|
@@ -210,7 +210,6 @@ export function loadExternalSkills() {
|
|
|
210
210
|
if (_skillCache)
|
|
211
211
|
return _skillCache;
|
|
212
212
|
_skillCache = scanExternalSkills();
|
|
213
|
-
console.log(`[skills] 已加载 ${_skillCache.length} 个外部 skill (${getExternalSkillsDir()})`);
|
|
214
213
|
return _skillCache;
|
|
215
214
|
}
|
|
216
215
|
/** 获取合并后的所有工具:内置 tools + 外部 skills */
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -22,3 +22,5 @@ export declare function findTool(name: string): Tool | undefined;
|
|
|
22
22
|
export declare function getAllTools(): Tool[];
|
|
23
23
|
/** 按名称查找工具(内置 + 外部 skills) */
|
|
24
24
|
export declare function findToolMerged(name: string): Tool | undefined;
|
|
25
|
+
/** 获取状态栏用的工具统计摘要 */
|
|
26
|
+
export declare function getToolStatsText(): string;
|
package/dist/tools/index.js
CHANGED
|
@@ -27,6 +27,7 @@ export function findTool(name) {
|
|
|
27
27
|
}
|
|
28
28
|
// ===== 合并工具(内置 + 外部 Skills)=====
|
|
29
29
|
import { getMergedTools, findMergedTool } from '../skills/index.js';
|
|
30
|
+
import { listSkills } from '../skills/index.js';
|
|
30
31
|
/** 获取所有工具(内置 + 外部 skills),供 QueryEngine 使用 */
|
|
31
32
|
export function getAllTools() {
|
|
32
33
|
return getMergedTools();
|
|
@@ -35,3 +36,7 @@ export function getAllTools() {
|
|
|
35
36
|
export function findToolMerged(name) {
|
|
36
37
|
return findMergedTool(name);
|
|
37
38
|
}
|
|
39
|
+
/** 获取状态栏用的工具统计摘要 */
|
|
40
|
+
export function getToolStatsText() {
|
|
41
|
+
return `skills(${allTools.length}/${listSkills().length})`;
|
|
42
|
+
}
|