xx-ai-cli 0.1.0
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/LICENSE +21 -0
- package/README.md +328 -0
- package/dist/commands/agent.d.ts +12 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +311 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/ask.d.ts +7 -0
- package/dist/commands/ask.d.ts.map +1 -0
- package/dist/commands/ask.js +52 -0
- package/dist/commands/ask.js.map +1 -0
- package/dist/commands/chat.d.ts +9 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +129 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/cmd.d.ts +6 -0
- package/dist/commands/cmd.d.ts.map +1 -0
- package/dist/commands/cmd.js +52 -0
- package/dist/commands/cmd.js.map +1 -0
- package/dist/commands/code.d.ts +8 -0
- package/dist/commands/code.d.ts.map +1 -0
- package/dist/commands/code.js +75 -0
- package/dist/commands/code.js.map +1 -0
- package/dist/commands/file.d.ts +7 -0
- package/dist/commands/file.d.ts.map +1 -0
- package/dist/commands/file.js +66 -0
- package/dist/commands/file.js.map +1 -0
- package/dist/commands/history.d.ts +5 -0
- package/dist/commands/history.d.ts.map +1 -0
- package/dist/commands/history.js +159 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +144 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install.d.ts +24 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +328 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/model.d.ts +6 -0
- package/dist/commands/model.d.ts.map +1 -0
- package/dist/commands/model.js +128 -0
- package/dist/commands/model.js.map +1 -0
- package/dist/commands/pkg.d.ts +12 -0
- package/dist/commands/pkg.d.ts.map +1 -0
- package/dist/commands/pkg.js +132 -0
- package/dist/commands/pkg.js.map +1 -0
- package/dist/commands/run.d.ts +9 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +185 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/core/agentTask.d.ts +20 -0
- package/dist/core/agentTask.d.ts.map +1 -0
- package/dist/core/agentTask.js +81 -0
- package/dist/core/agentTask.js.map +1 -0
- package/dist/core/config.d.ts +41 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +153 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/executor.d.ts +20 -0
- package/dist/core/executor.d.ts.map +1 -0
- package/dist/core/executor.js +68 -0
- package/dist/core/executor.js.map +1 -0
- package/dist/core/files.d.ts +24 -0
- package/dist/core/files.d.ts.map +1 -0
- package/dist/core/files.js +95 -0
- package/dist/core/files.js.map +1 -0
- package/dist/core/github.d.ts +32 -0
- package/dist/core/github.d.ts.map +1 -0
- package/dist/core/github.js +82 -0
- package/dist/core/github.js.map +1 -0
- package/dist/core/prompt.d.ts +9 -0
- package/dist/core/prompt.d.ts.map +1 -0
- package/dist/core/prompt.js +44 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/router.d.ts +16 -0
- package/dist/core/router.d.ts.map +1 -0
- package/dist/core/router.js +182 -0
- package/dist/core/router.js.map +1 -0
- package/dist/core/search.d.ts +14 -0
- package/dist/core/search.d.ts.map +1 -0
- package/dist/core/search.js +179 -0
- package/dist/core/search.js.map +1 -0
- package/dist/core/session.d.ts +38 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +172 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/stream.d.ts +15 -0
- package/dist/core/stream.d.ts.map +1 -0
- package/dist/core/stream.js +102 -0
- package/dist/core/stream.js.map +1 -0
- package/dist/core/tools.d.ts +343 -0
- package/dist/core/tools.d.ts.map +1 -0
- package/dist/core/tools.js +293 -0
- package/dist/core/tools.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +372 -0
- package/dist/index.js.map +1 -0
- package/dist/ui/renderer.d.ts +17 -0
- package/dist/ui/renderer.d.ts.map +1 -0
- package/dist/ui/renderer.js +69 -0
- package/dist/ui/renderer.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { config, PROVIDER_LABELS } from '../core/config.js';
|
|
3
|
+
import { theme } from '../ui/renderer.js';
|
|
4
|
+
// ─── 意图识别规则 ─────────────────────────────────────────────
|
|
5
|
+
const INTENT_RULES = [
|
|
6
|
+
{
|
|
7
|
+
intent: 'search',
|
|
8
|
+
score: 0.9,
|
|
9
|
+
patterns: [
|
|
10
|
+
/搜索|查一下|查找|找找|最新|新闻|实时/,
|
|
11
|
+
/search|google|look up|find out|latest|news/i,
|
|
12
|
+
/^搜.{0,20}(吗|啊|呢|?|\?)?$/, // 去掉"查"开头的宽泛匹配
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
intent: 'pkg_install',
|
|
17
|
+
score: 0.95,
|
|
18
|
+
patterns: [
|
|
19
|
+
/安装\s*(npm|包|库|插件|模块|package)/,
|
|
20
|
+
/npm install|pip install|brew install/i,
|
|
21
|
+
/install\s+[\w@/-]+/i,
|
|
22
|
+
/帮我装|帮我安装/,
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
intent: 'shell',
|
|
27
|
+
score: 0.93, // 调高,避免被 search 抢走
|
|
28
|
+
patterns: [
|
|
29
|
+
/命令|shell|terminal|终端|如何用命令/,
|
|
30
|
+
/怎么.*命令|用什么命令|command/i,
|
|
31
|
+
/find|grep|chmod|mkdir|rm |ls |ps |kill|port|端口|进程|查看.*占用|被.*占用/,
|
|
32
|
+
/帮我.*命令|给.*命令/,
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
intent: 'code_gen',
|
|
37
|
+
score: 0.88,
|
|
38
|
+
patterns: [
|
|
39
|
+
/写.*代码|生成.*代码|实现.*函数|写.*函数|写.*类|写.*脚本/,
|
|
40
|
+
/write.*code|generate.*code|implement|create.*function/i,
|
|
41
|
+
/帮我写|帮我实现|帮我生成/,
|
|
42
|
+
/用.*写.*[((]|typescript|python|java|golang|rust|go\s+写/i,
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
intent: 'code_explain',
|
|
47
|
+
score: 0.88,
|
|
48
|
+
patterns: [
|
|
49
|
+
/解释.*代码|解释.*这段|这段代码|代码.*什么意思|什么作用/,
|
|
50
|
+
/explain.*code|what does.*code|how does/i,
|
|
51
|
+
/看看这段|分析这段/,
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
intent: 'code_review',
|
|
56
|
+
score: 0.88,
|
|
57
|
+
patterns: [
|
|
58
|
+
/review|代码审查|code review|审查代码|检查代码|有没有.*问题|bug/i,
|
|
59
|
+
/帮我.*看看.*代码|优化.*代码|改进.*代码/,
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
intent: 'file',
|
|
64
|
+
score: 0.92,
|
|
65
|
+
patterns: [
|
|
66
|
+
/\.(ts|tsx|js|jsx|py|go|java|rs|cpp|c|json|yaml|yml|md|txt|sh|env)\b/,
|
|
67
|
+
/文件|file|读取|打开.*文件/,
|
|
68
|
+
/分析.*文件|看.*文件/,
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
intent: 'agent',
|
|
73
|
+
score: 0.85,
|
|
74
|
+
patterns: [
|
|
75
|
+
/帮我完成|自动|一步步|帮我.*然后.*帮我|多个步骤/,
|
|
76
|
+
/复杂任务|多步|agent|自动化/,
|
|
77
|
+
/先.*再.*然后|并且.*同时/,
|
|
78
|
+
/项目.*创建|创建.*项目|初始化.*项目/,
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
];
|
|
82
|
+
// ─── 关键词提取 ───────────────────────────────────────────────
|
|
83
|
+
function extractArgs(input, intent) {
|
|
84
|
+
const args = {};
|
|
85
|
+
// 提取文件路径
|
|
86
|
+
const fileMatch = input.match(/\.\/[\w/.-]+|\/[\w/.-]+\.\w+/);
|
|
87
|
+
if (fileMatch)
|
|
88
|
+
args.filePath = fileMatch[0];
|
|
89
|
+
// 提取包名(npm install xxx)
|
|
90
|
+
const pkgMatch = input.match(/(?:安装|install)\s+([\w@/-]+(?:@[\w.^~-]+)?)/i);
|
|
91
|
+
if (pkgMatch)
|
|
92
|
+
args.packageName = pkgMatch[1];
|
|
93
|
+
// 提取搜索关键词(去掉指令词)
|
|
94
|
+
if (intent === 'search') {
|
|
95
|
+
args.query = input
|
|
96
|
+
.replace(/^(搜索|查一下|查找|帮我搜索|search|look up)/i, '')
|
|
97
|
+
.trim();
|
|
98
|
+
}
|
|
99
|
+
return args;
|
|
100
|
+
}
|
|
101
|
+
// ─── 识别意图 ─────────────────────────────────────────────────
|
|
102
|
+
// 高优先意图:一旦命中任意一条 pattern,就覆盖 file 意图
|
|
103
|
+
const CODE_INTENTS = new Set(['code_explain', 'code_gen', 'code_review']);
|
|
104
|
+
export function detectIntent(input) {
|
|
105
|
+
const scores = {};
|
|
106
|
+
for (const rule of INTENT_RULES) {
|
|
107
|
+
const matchCount = rule.patterns.filter((p) => p.test(input)).length;
|
|
108
|
+
if (matchCount > 0) {
|
|
109
|
+
scores[rule.intent] = rule.score * (matchCount / rule.patterns.length + 0.5);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// 合并规则:代码类意图 + file 同时命中时,代码意图优先
|
|
113
|
+
if (scores['file'] !== undefined) {
|
|
114
|
+
for (const ci of CODE_INTENTS) {
|
|
115
|
+
if (scores[ci] !== undefined) {
|
|
116
|
+
delete scores['file'];
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
let bestIntent = 'chat';
|
|
122
|
+
let bestScore = 0;
|
|
123
|
+
for (const [intent, score] of Object.entries(scores)) {
|
|
124
|
+
if (score > bestScore) {
|
|
125
|
+
bestScore = score;
|
|
126
|
+
bestIntent = intent;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
intent: bestIntent,
|
|
131
|
+
confidence: Math.min(bestScore, 1),
|
|
132
|
+
extractedArgs: extractArgs(input, bestIntent),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// ─── 意图标签 ─────────────────────────────────────────────────
|
|
136
|
+
export const INTENT_LABELS = {
|
|
137
|
+
search: '🔍 联网搜索',
|
|
138
|
+
code_gen: '💻 代码生成',
|
|
139
|
+
code_explain: '📖 代码解释',
|
|
140
|
+
code_review: '🔬 Code Review',
|
|
141
|
+
file: '📄 文件分析',
|
|
142
|
+
shell: '🔧 命令建议',
|
|
143
|
+
pkg_install: '📦 安装包',
|
|
144
|
+
agent: '🤖 Agent 任务',
|
|
145
|
+
chat: '💬 对话',
|
|
146
|
+
};
|
|
147
|
+
// ─── 自动选择最优模型 ─────────────────────────────────────────
|
|
148
|
+
// 不同任务对应最优模型(按优先级排列)
|
|
149
|
+
const MODEL_PREFERENCE = {
|
|
150
|
+
code_gen: ['deepseek', 'qwen', 'glm', 'moonshot', 'doubao'],
|
|
151
|
+
code_explain: ['deepseek', 'qwen', 'glm', 'moonshot', 'doubao'],
|
|
152
|
+
code_review: ['deepseek', 'qwen', 'glm', 'moonshot', 'doubao'],
|
|
153
|
+
file: ['moonshot', 'qwen', 'deepseek', 'glm', 'doubao'],
|
|
154
|
+
agent: ['deepseek', 'qwen', 'moonshot', 'glm', 'doubao'],
|
|
155
|
+
search: ['glm', 'qwen', 'deepseek', 'moonshot', 'doubao'],
|
|
156
|
+
shell: ['deepseek', 'glm', 'qwen', 'moonshot', 'doubao'],
|
|
157
|
+
pkg_install: ['deepseek', 'glm', 'qwen', 'moonshot', 'doubao'],
|
|
158
|
+
chat: ['glm', 'qwen', 'deepseek', 'moonshot', 'doubao'],
|
|
159
|
+
};
|
|
160
|
+
export function selectBestModel(intent) {
|
|
161
|
+
const providers = config.get('providers');
|
|
162
|
+
const preference = MODEL_PREFERENCE[intent];
|
|
163
|
+
// 从偏好列表中找第一个已配置 API Key 的模型
|
|
164
|
+
for (const p of preference) {
|
|
165
|
+
if (providers[p]?.apiKey)
|
|
166
|
+
return p;
|
|
167
|
+
}
|
|
168
|
+
// 都没配置,返回默认
|
|
169
|
+
return config.get('defaultProvider');
|
|
170
|
+
}
|
|
171
|
+
// ─── 打印路由决策 ─────────────────────────────────────────────
|
|
172
|
+
export function printRouteDecision(input, intentResult, selectedModel) {
|
|
173
|
+
const { intent, confidence } = intentResult;
|
|
174
|
+
const label = INTENT_LABELS[intent];
|
|
175
|
+
const modelLabel = PROVIDER_LABELS[selectedModel];
|
|
176
|
+
const confPct = (confidence * 100).toFixed(0);
|
|
177
|
+
console.log(`\n${theme.dim('┌─ 智能路由')} ${chalk.bold(label)} ` +
|
|
178
|
+
`${chalk.dim(`(置信度 ${confPct}%)`)} ` +
|
|
179
|
+
`${chalk.dim('→')} ${chalk.green(modelLabel)}`);
|
|
180
|
+
console.log(theme.dim('└─────────────────────────────────────'));
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/core/router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface SearchResult {
|
|
2
|
+
title: string;
|
|
3
|
+
url: string;
|
|
4
|
+
snippet: string;
|
|
5
|
+
}
|
|
6
|
+
export interface SearchResponse {
|
|
7
|
+
query: string;
|
|
8
|
+
results: SearchResult[];
|
|
9
|
+
provider: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function webSearch(query: string, maxResults?: number): Promise<SearchResponse>;
|
|
12
|
+
/** 将搜索结果格式化为供 AI 读取的文本 */
|
|
13
|
+
export declare function formatSearchResults(resp: SearchResponse): string;
|
|
14
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/core/search.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA2KD,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CA0B3F;AAED,0BAA0B;AAC1B,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAMhE"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { config } from './config.js';
|
|
2
|
+
// ─── DuckDuckGo HTML 搜索(无需 API Key,需要网络可访问)───────
|
|
3
|
+
async function searchDuckDuckGo(query, maxResults) {
|
|
4
|
+
const controller = new AbortController();
|
|
5
|
+
const timeout = setTimeout(() => controller.abort(), 8000); // 8 秒超时
|
|
6
|
+
try {
|
|
7
|
+
// 先用 Instant Answer API 试一下
|
|
8
|
+
const iaUrl = `https://api.duckduckgo.com/?q=${encodeURIComponent(query)}&format=json&no_html=1&skip_disambig=1`;
|
|
9
|
+
const iaRes = await fetch(iaUrl, {
|
|
10
|
+
signal: controller.signal,
|
|
11
|
+
headers: { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36' },
|
|
12
|
+
});
|
|
13
|
+
clearTimeout(timeout);
|
|
14
|
+
if (iaRes.ok) {
|
|
15
|
+
const data = (await iaRes.json());
|
|
16
|
+
const results = [];
|
|
17
|
+
if (data.Abstract && data.AbstractURL) {
|
|
18
|
+
results.push({ title: data.AbstractSource ?? query, url: data.AbstractURL, snippet: data.Abstract });
|
|
19
|
+
}
|
|
20
|
+
for (const r of data.Results ?? []) {
|
|
21
|
+
if (r.Text && r.FirstURL && results.length < maxResults) {
|
|
22
|
+
results.push({ title: r.Text.split(' - ')[0] ?? r.Text, url: r.FirstURL, snippet: r.Text });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
for (const t of data.RelatedTopics ?? []) {
|
|
26
|
+
if (t.Text && t.FirstURL && results.length < maxResults) {
|
|
27
|
+
results.push({ title: t.Name ?? t.Text.split(' - ')[0], url: t.FirstURL, snippet: t.Text });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (results.length > 0)
|
|
31
|
+
return results.slice(0, maxResults);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
clearTimeout(timeout);
|
|
36
|
+
// 网络不通,直接返回提示,不再尝试 HTML 搜索
|
|
37
|
+
return [{
|
|
38
|
+
title: '搜索不可用',
|
|
39
|
+
url: '',
|
|
40
|
+
snippet: `[搜索不可用] DuckDuckGo 无法访问(网络受限或未配置代理)。` +
|
|
41
|
+
`请改用 xxcli search-config set serper --key <API_KEY> 配置搜索引擎,` +
|
|
42
|
+
`或直接使用 xxcli install ${query.split(' ')[0]} 命令尝试安装。`,
|
|
43
|
+
}];
|
|
44
|
+
}
|
|
45
|
+
// Instant Answer 无结果时,改用 DDG HTML 搜索
|
|
46
|
+
try {
|
|
47
|
+
const htmlController = new AbortController();
|
|
48
|
+
const htmlTimeout = setTimeout(() => htmlController.abort(), 8000);
|
|
49
|
+
const htmlUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
|
|
50
|
+
const htmlRes = await fetch(htmlUrl, {
|
|
51
|
+
signal: htmlController.signal,
|
|
52
|
+
headers: {
|
|
53
|
+
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
54
|
+
'Accept': 'text/html',
|
|
55
|
+
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
clearTimeout(htmlTimeout);
|
|
59
|
+
if (!htmlRes.ok)
|
|
60
|
+
throw new Error(`HTTP ${htmlRes.status}`);
|
|
61
|
+
const html = await htmlRes.text();
|
|
62
|
+
const results = [];
|
|
63
|
+
const resultBlocks = html.match(/<a class="result__a"[^>]+href="([^"]+)"[^>]*>([^<]+)<\/a>[\s\S]*?<a class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g) ?? [];
|
|
64
|
+
for (const block of resultBlocks) {
|
|
65
|
+
if (results.length >= maxResults)
|
|
66
|
+
break;
|
|
67
|
+
const urlMatch = block.match(/href="([^"]+)"/);
|
|
68
|
+
const titleMatch = block.match(/<a class="result__a"[^>]+>([^<]+)<\/a>/);
|
|
69
|
+
const snippetMatch = block.match(/<a class="result__snippet"[^>]*>([\s\S]*?)<\/a>/);
|
|
70
|
+
if (urlMatch && titleMatch) {
|
|
71
|
+
const url = urlMatch[1].startsWith('//') ? `https:${urlMatch[1]}` : urlMatch[1];
|
|
72
|
+
const snippet = snippetMatch ? snippetMatch[1].replace(/<[^>]+>/g, '').trim() : '';
|
|
73
|
+
results.push({ title: titleMatch[1].trim(), url, snippet: snippet.slice(0, 300) });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (results.length > 0)
|
|
77
|
+
return results.slice(0, maxResults);
|
|
78
|
+
}
|
|
79
|
+
catch { /* HTML 搜索也失败,走兜底 */ }
|
|
80
|
+
// 最终兜底
|
|
81
|
+
return [{
|
|
82
|
+
title: '搜索无结果',
|
|
83
|
+
url: `https://duckduckgo.com/?q=${encodeURIComponent(query)}`,
|
|
84
|
+
snippet: `搜索 "${query}" 无结果。建议配置 Serper 或 Tavily 获得更好的搜索效果:xxcli search-config set serper --key <API_KEY>`,
|
|
85
|
+
}];
|
|
86
|
+
}
|
|
87
|
+
// ─── Serper(Google Search API,需要 API Key)────────────────
|
|
88
|
+
async function searchSerper(query, apiKey, maxResults) {
|
|
89
|
+
const res = await fetch('https://google.serper.dev/search', {
|
|
90
|
+
method: 'POST',
|
|
91
|
+
headers: {
|
|
92
|
+
'Content-Type': 'application/json',
|
|
93
|
+
'X-API-KEY': apiKey,
|
|
94
|
+
},
|
|
95
|
+
body: JSON.stringify({ q: query, num: maxResults, gl: 'cn', hl: 'zh-cn' }),
|
|
96
|
+
});
|
|
97
|
+
if (!res.ok)
|
|
98
|
+
throw new Error(`Serper 请求失败 [${res.status}]`);
|
|
99
|
+
const data = (await res.json());
|
|
100
|
+
const results = [];
|
|
101
|
+
if (data.answerBox) {
|
|
102
|
+
results.push({
|
|
103
|
+
title: data.answerBox.title,
|
|
104
|
+
url: data.answerBox.link,
|
|
105
|
+
snippet: data.answerBox.snippet,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
for (const item of data.organic ?? []) {
|
|
109
|
+
if (results.length >= maxResults)
|
|
110
|
+
break;
|
|
111
|
+
results.push({ title: item.title, url: item.link, snippet: item.snippet });
|
|
112
|
+
}
|
|
113
|
+
return results;
|
|
114
|
+
}
|
|
115
|
+
// ─── Tavily(AI-optimized search,需要 API Key)───────────────
|
|
116
|
+
async function searchTavily(query, apiKey, maxResults) {
|
|
117
|
+
const res = await fetch('https://api.tavily.com/search', {
|
|
118
|
+
method: 'POST',
|
|
119
|
+
headers: { 'Content-Type': 'application/json' },
|
|
120
|
+
body: JSON.stringify({
|
|
121
|
+
api_key: apiKey,
|
|
122
|
+
query,
|
|
123
|
+
max_results: maxResults,
|
|
124
|
+
include_answer: true,
|
|
125
|
+
search_depth: 'basic',
|
|
126
|
+
}),
|
|
127
|
+
});
|
|
128
|
+
if (!res.ok)
|
|
129
|
+
throw new Error(`Tavily 请求失败 [${res.status}]`);
|
|
130
|
+
const data = (await res.json());
|
|
131
|
+
const results = [];
|
|
132
|
+
if (data.answer) {
|
|
133
|
+
results.push({ title: '综合答案', url: '', snippet: data.answer });
|
|
134
|
+
}
|
|
135
|
+
for (const item of data.results ?? []) {
|
|
136
|
+
if (results.length >= maxResults)
|
|
137
|
+
break;
|
|
138
|
+
results.push({ title: item.title, url: item.url, snippet: item.content.slice(0, 300) });
|
|
139
|
+
}
|
|
140
|
+
return results;
|
|
141
|
+
}
|
|
142
|
+
// ─── 主搜索入口 ───────────────────────────────────────────────
|
|
143
|
+
export async function webSearch(query, maxResults) {
|
|
144
|
+
const searchCfg = config.get('search');
|
|
145
|
+
const limit = maxResults ?? searchCfg.maxResults;
|
|
146
|
+
const provider = searchCfg.provider;
|
|
147
|
+
let results = [];
|
|
148
|
+
try {
|
|
149
|
+
if (provider === 'serper' && searchCfg.apiKey) {
|
|
150
|
+
results = await searchSerper(query, searchCfg.apiKey, limit);
|
|
151
|
+
}
|
|
152
|
+
else if (provider === 'tavily' && searchCfg.apiKey) {
|
|
153
|
+
results = await searchTavily(query, searchCfg.apiKey, limit);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
// 默认 DuckDuckGo,无需 key
|
|
157
|
+
results = await searchDuckDuckGo(query, limit);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
// 降级到 DuckDuckGo
|
|
162
|
+
if (provider !== 'duckduckgo') {
|
|
163
|
+
results = await searchDuckDuckGo(query, limit);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
throw err;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return { query, results, provider };
|
|
170
|
+
}
|
|
171
|
+
/** 将搜索结果格式化为供 AI 读取的文本 */
|
|
172
|
+
export function formatSearchResults(resp) {
|
|
173
|
+
if (!resp.results.length)
|
|
174
|
+
return `搜索 "${resp.query}" 无结果`;
|
|
175
|
+
return resp.results
|
|
176
|
+
.map((r, i) => `[${i + 1}] ${r.title}\n${r.url ? `URL: ${r.url}\n` : ''}${r.snippet}`)
|
|
177
|
+
.join('\n\n');
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/core/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAcrC,oDAAoD;AACpD,KAAK,UAAU,gBAAgB,CAAC,KAAa,EAAE,UAAkB;IAC/D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ;IAEpE,IAAI,CAAC;QACH,4BAA4B;QAC5B,MAAM,KAAK,GAAG,iCAAiC,kBAAkB,CAAC,KAAK,CAAC,wCAAwC,CAAC;QACjH,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE;YAC/B,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,OAAO,EAAE,EAAE,YAAY,EAAE,oEAAoE,EAAE;SAChG,CAAC,CAAC;QACH,YAAY,CAAC,OAAO,CAAC,CAAC;QAEtB,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAM/B,CAAC;YAEF,MAAM,OAAO,GAAmB,EAAE,CAAC;YACnC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,cAAc,IAAI,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YACvG,CAAC;YACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;gBACnC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;oBACxD,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC9F,CAAC;YACH,CAAC;YACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,IAAI,EAAE,EAAE,CAAC;gBACzC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;oBACxD,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC9F,CAAC;YACH,CAAC;YACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,YAAY,CAAC,OAAO,CAAC,CAAC;QACtB,2BAA2B;QAC3B,OAAO,CAAC;gBACN,KAAK,EAAE,OAAO;gBACd,GAAG,EAAE,EAAE;gBACP,OAAO,EAAE,sCAAsC;oBAC7C,4DAA4D;oBAC5D,uBAAuB,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU;aACvD,CAAC,CAAC;IACL,CAAC;IAED,qCAAqC;IACrC,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,IAAI,eAAe,EAAE,CAAC;QAC7C,MAAM,WAAW,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC;QAEnE,MAAM,OAAO,GAAG,uCAAuC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QACnF,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE;YACnC,MAAM,EAAE,cAAc,CAAC,MAAM;YAC7B,OAAO,EAAE;gBACP,YAAY,EAAE,uHAAuH;gBACrI,QAAQ,EAAE,WAAW;gBACrB,iBAAiB,EAAE,yBAAyB;aAC7C;SACF,CAAC,CAAC;QACH,YAAY,CAAC,WAAW,CAAC,CAAC;QAE1B,IAAI,CAAC,OAAO,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAE3D,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QAClC,MAAM,OAAO,GAAmB,EAAE,CAAC;QACnC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,mHAAmH,CAAC,IAAI,EAAE,CAAC;QAE3J,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;YACjC,IAAI,OAAO,CAAC,MAAM,IAAI,UAAU;gBAAE,MAAM;YACxC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAC/C,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;YACzE,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;YAEpF,IAAI,QAAQ,IAAI,UAAU,EAAE,CAAC;gBAC3B,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAChF,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnF,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YACrF,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAEhC,OAAO;IACP,OAAO,CAAC;YACN,KAAK,EAAE,OAAO;YACd,GAAG,EAAE,6BAA6B,kBAAkB,CAAC,KAAK,CAAC,EAAE;YAC7D,OAAO,EAAE,OAAO,KAAK,qFAAqF;SAC3G,CAAC,CAAC;AACL,CAAC;AAED,2DAA2D;AAC3D,KAAK,UAAU,YAAY,CAAC,KAAa,EAAE,MAAc,EAAE,UAAkB;IAC3E,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,kCAAkC,EAAE;QAC1D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,WAAW,EAAE,MAAM;SACpB;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;KAC3E,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAE5D,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAG7B,CAAC;IAEF,MAAM,OAAO,GAAmB,EAAE,CAAC;IAEnC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK;YAC3B,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI;YACxB,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO;SAChC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QACtC,IAAI,OAAO,CAAC,MAAM,IAAI,UAAU;YAAE,MAAM;QACxC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,4DAA4D;AAC5D,KAAK,UAAU,YAAY,CAAC,KAAa,EAAE,MAAc,EAAE,UAAkB;IAC3E,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,+BAA+B,EAAE;QACvD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,OAAO,EAAE,MAAM;YACf,KAAK;YACL,WAAW,EAAE,UAAU;YACvB,cAAc,EAAE,IAAI;YACpB,YAAY,EAAE,OAAO;SACtB,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAE5D,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAG7B,CAAC;IAEF,MAAM,OAAO,GAAmB,EAAE,CAAC;IAEnC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QACtC,IAAI,OAAO,CAAC,MAAM,IAAI,UAAU;YAAE,MAAM;QACxC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1F,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAa,EAAE,UAAmB;IAChE,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,UAAU,IAAI,SAAS,CAAC,UAAU,CAAC;IACjD,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC;IAEpC,IAAI,OAAO,GAAmB,EAAE,CAAC;IAEjC,IAAI,CAAC;QACH,IAAI,QAAQ,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;YAC9C,OAAO,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC/D,CAAC;aAAM,IAAI,QAAQ,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;YACrD,OAAO,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,uBAAuB;YACvB,OAAO,GAAG,MAAM,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,iBAAiB;QACjB,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;YAC9B,OAAO,GAAG,MAAM,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACjD,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AACtC,CAAC;AAED,0BAA0B;AAC1B,MAAM,UAAU,mBAAmB,CAAC,IAAoB;IACtD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,OAAO,IAAI,CAAC,KAAK,OAAO,CAAC;IAE1D,OAAO,IAAI,CAAC,OAAO;SAChB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;SACrF,IAAI,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface Message {
|
|
2
|
+
role: 'system' | 'user' | 'assistant' | 'tool';
|
|
3
|
+
content: string;
|
|
4
|
+
tool_calls?: unknown[];
|
|
5
|
+
tool_call_id?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface PersistedSession {
|
|
8
|
+
id: string;
|
|
9
|
+
title: string;
|
|
10
|
+
model: string;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
updatedAt: string;
|
|
13
|
+
messages: Message[];
|
|
14
|
+
}
|
|
15
|
+
export declare function loadAllSessions(): PersistedSession[];
|
|
16
|
+
export declare function loadSessionById(id: string): PersistedSession | null;
|
|
17
|
+
export declare function deleteSession(id: string): boolean;
|
|
18
|
+
export declare class Session {
|
|
19
|
+
messages: Message[];
|
|
20
|
+
private systemPrompt;
|
|
21
|
+
private persistId;
|
|
22
|
+
private model;
|
|
23
|
+
private savedToHistory;
|
|
24
|
+
constructor(systemPrompt?: string, model?: string);
|
|
25
|
+
/** 从已有持久化会话恢复(用于 history resume) */
|
|
26
|
+
static fromPersisted(data: PersistedSession): Session;
|
|
27
|
+
addUser(content: string): void;
|
|
28
|
+
addAssistant(content: string, toolCalls?: unknown[]): void;
|
|
29
|
+
addToolResult(toolCallId: string, content: string): void;
|
|
30
|
+
getMessages(): Message[];
|
|
31
|
+
clear(): void;
|
|
32
|
+
get length(): number;
|
|
33
|
+
trim(maxPairs?: number): void;
|
|
34
|
+
/** 持久化当前会话到磁盘(仅当有 user+assistant 对话时才保存)*/
|
|
35
|
+
persist(): void;
|
|
36
|
+
setModel(model: string): void;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAGD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAaD,wBAAgB,eAAe,IAAI,gBAAgB,EAAE,CAepD;AAGD,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CASnE;AAoDD,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAKjD;AAGD,qBAAa,OAAO;IAClB,QAAQ,EAAE,OAAO,EAAE,CAAM;IACzB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,cAAc,CAAkB;gBAE5B,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,MAAkB;IAsB5D,oCAAoC;IACpC,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO;IAOrD,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI9B,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI;IAI1D,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAIxD,WAAW,IAAI,OAAO,EAAE;IAIxB,KAAK,IAAI,IAAI;IAIb,IAAI,MAAM,IAAI,MAAM,CAEnB;IAGD,IAAI,CAAC,QAAQ,SAAK,GAAG,IAAI;IAMzB,2CAA2C;IAC3C,OAAO,IAAI,IAAI;IAoBf,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAG9B"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
// ─── 历史存储路径 ──────────────────────────────────────────────
|
|
5
|
+
const HISTORY_DIR = path.join(os.homedir(), '.config', 'ai-cli', 'history');
|
|
6
|
+
const MAX_HISTORY_FILES = 50; // 最多保留最近 50 条会话
|
|
7
|
+
function ensureHistoryDir() {
|
|
8
|
+
if (!fs.existsSync(HISTORY_DIR)) {
|
|
9
|
+
fs.mkdirSync(HISTORY_DIR, { recursive: true });
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
// ─── 读取所有历史会话(按时间倒序)───────────────────────────
|
|
13
|
+
export function loadAllSessions() {
|
|
14
|
+
ensureHistoryDir();
|
|
15
|
+
const files = fs.readdirSync(HISTORY_DIR)
|
|
16
|
+
.filter((f) => f.endsWith('.json'))
|
|
17
|
+
.sort()
|
|
18
|
+
.reverse(); // 最新的在前
|
|
19
|
+
return files.map((f) => {
|
|
20
|
+
try {
|
|
21
|
+
const raw = fs.readFileSync(path.join(HISTORY_DIR, f), 'utf-8');
|
|
22
|
+
return JSON.parse(raw);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}).filter(Boolean);
|
|
28
|
+
}
|
|
29
|
+
// ─── 按 ID 加载单条会话 ────────────────────────────────────────
|
|
30
|
+
export function loadSessionById(id) {
|
|
31
|
+
ensureHistoryDir();
|
|
32
|
+
const filePath = path.join(HISTORY_DIR, `${id}.json`);
|
|
33
|
+
if (!fs.existsSync(filePath))
|
|
34
|
+
return null;
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// ─── 保存单条会话 ─────────────────────────────────────────────
|
|
43
|
+
function saveSession(data) {
|
|
44
|
+
ensureHistoryDir();
|
|
45
|
+
fs.writeFileSync(path.join(HISTORY_DIR, `${data.id}.json`), JSON.stringify(data, null, 2), 'utf-8');
|
|
46
|
+
pruneOldSessions();
|
|
47
|
+
}
|
|
48
|
+
// ─── 清理超出上限的旧会话 ──────────────────────────────────────
|
|
49
|
+
function pruneOldSessions() {
|
|
50
|
+
const files = fs.readdirSync(HISTORY_DIR)
|
|
51
|
+
.filter((f) => f.endsWith('.json'))
|
|
52
|
+
.sort(); // 最旧的在前
|
|
53
|
+
if (files.length > MAX_HISTORY_FILES) {
|
|
54
|
+
files.slice(0, files.length - MAX_HISTORY_FILES).forEach((f) => {
|
|
55
|
+
fs.unlinkSync(path.join(HISTORY_DIR, f));
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// ─── 敏感信息脱敏(防止 key 被意外存入历史)─────────────────
|
|
60
|
+
// 匹配常见 API Key 格式:sk-xxx / Bearer xxx / 纯随机长字符串
|
|
61
|
+
const SENSITIVE_PATTERNS = [
|
|
62
|
+
/sk-[A-Za-z0-9]{16,}/g, // OpenAI / DeepSeek / Moonshot 风格
|
|
63
|
+
/Bearer\s+[A-Za-z0-9\-_.]{16,}/gi, // Authorization header
|
|
64
|
+
/[A-Za-z0-9]{32,}\.[A-Za-z0-9]{16,}/g, // GLM 风格(含点号)
|
|
65
|
+
/eyJ[A-Za-z0-9_\-.]{20,}/g, // JWT token
|
|
66
|
+
];
|
|
67
|
+
function redactSensitive(text) {
|
|
68
|
+
let result = text;
|
|
69
|
+
for (const pattern of SENSITIVE_PATTERNS) {
|
|
70
|
+
result = result.replace(pattern, (match) => {
|
|
71
|
+
return `${match.slice(0, 6)}${'*'.repeat(8)}[REDACTED]`;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
function redactMessages(messages) {
|
|
77
|
+
return messages.map((m) => ({
|
|
78
|
+
...m,
|
|
79
|
+
content: redactSensitive(m.content),
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
// ─── 删除会话 ──────────────────────────────────────────────────
|
|
83
|
+
export function deleteSession(id) {
|
|
84
|
+
const filePath = path.join(HISTORY_DIR, `${id}.json`);
|
|
85
|
+
if (!fs.existsSync(filePath))
|
|
86
|
+
return false;
|
|
87
|
+
fs.unlinkSync(filePath);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
// ─── Session 类 ───────────────────────────────────────────────
|
|
91
|
+
export class Session {
|
|
92
|
+
messages = [];
|
|
93
|
+
systemPrompt;
|
|
94
|
+
persistId;
|
|
95
|
+
model;
|
|
96
|
+
savedToHistory = false;
|
|
97
|
+
constructor(systemPrompt, model = 'unknown') {
|
|
98
|
+
this.systemPrompt =
|
|
99
|
+
systemPrompt ??
|
|
100
|
+
`你是 XX-AI-CLI 的内置智能助手,运行在用户的命令行终端中。
|
|
101
|
+
|
|
102
|
+
## 你的能力边界
|
|
103
|
+
你不仅能回答问题,还能直接调用本工具的以下内置功能:
|
|
104
|
+
- **安装工具**:用户说"安装 openclaw"、"帮我装 xxx" → 告知用户运行 \`xxcli install openclaw\`
|
|
105
|
+
- **搜索包**:用户说"搜索/查找 xxx 包" → 告知用户运行 \`xxcli pkg search xxx\`
|
|
106
|
+
- **Shell 命令**:用户说"怎么删除文件夹" → 直接给出 Shell 命令
|
|
107
|
+
- **代码生成**:用户说"帮我写..." → 直接生成代码
|
|
108
|
+
- **文件分析**:用户说"分析这个文件" → 告知用户运行 \`xxcli file <路径> "问题"\`
|
|
109
|
+
|
|
110
|
+
## 重要原则
|
|
111
|
+
- 对于"安装 openclaw"这类需求,**不要说做不到**,要告知用户使用 \`xxcli install openclaw\` 命令,本工具内置了安装功能
|
|
112
|
+
- 回答简洁清晰,优先用中文
|
|
113
|
+
- 涉及终端操作时,直接给出可执行的命令`;
|
|
114
|
+
this.model = model;
|
|
115
|
+
// ID = 时间戳,保证文件名可排序
|
|
116
|
+
this.persistId = Date.now().toString();
|
|
117
|
+
}
|
|
118
|
+
/** 从已有持久化会话恢复(用于 history resume) */
|
|
119
|
+
static fromPersisted(data) {
|
|
120
|
+
const s = new Session(undefined, data.model);
|
|
121
|
+
s.messages = data.messages;
|
|
122
|
+
s.persistId = data.id; // 复用原 ID,更新同一文件
|
|
123
|
+
return s;
|
|
124
|
+
}
|
|
125
|
+
addUser(content) {
|
|
126
|
+
this.messages.push({ role: 'user', content });
|
|
127
|
+
}
|
|
128
|
+
addAssistant(content, toolCalls) {
|
|
129
|
+
this.messages.push({ role: 'assistant', content, ...(toolCalls ? { tool_calls: toolCalls } : {}) });
|
|
130
|
+
}
|
|
131
|
+
addToolResult(toolCallId, content) {
|
|
132
|
+
this.messages.push({ role: 'tool', content, tool_call_id: toolCallId });
|
|
133
|
+
}
|
|
134
|
+
getMessages() {
|
|
135
|
+
return [{ role: 'system', content: this.systemPrompt }, ...this.messages];
|
|
136
|
+
}
|
|
137
|
+
clear() {
|
|
138
|
+
this.messages = [];
|
|
139
|
+
}
|
|
140
|
+
get length() {
|
|
141
|
+
return this.messages.length;
|
|
142
|
+
}
|
|
143
|
+
// 限制历史长度,避免 token 超限
|
|
144
|
+
trim(maxPairs = 20) {
|
|
145
|
+
if (this.messages.length > maxPairs * 2) {
|
|
146
|
+
this.messages = this.messages.slice(-maxPairs * 2);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/** 持久化当前会话到磁盘(仅当有 user+assistant 对话时才保存)*/
|
|
150
|
+
persist() {
|
|
151
|
+
const hasDialog = this.messages.some((m) => m.role === 'user') &&
|
|
152
|
+
this.messages.some((m) => m.role === 'assistant');
|
|
153
|
+
if (!hasDialog)
|
|
154
|
+
return;
|
|
155
|
+
const firstUser = this.messages.find((m) => m.role === 'user')?.content ?? '';
|
|
156
|
+
const title = firstUser.slice(0, 40).replace(/\n/g, ' ') + (firstUser.length > 40 ? '…' : '');
|
|
157
|
+
const now = new Date().toISOString();
|
|
158
|
+
saveSession({
|
|
159
|
+
id: this.persistId,
|
|
160
|
+
title,
|
|
161
|
+
model: this.model,
|
|
162
|
+
createdAt: this.savedToHistory ? '' : now,
|
|
163
|
+
updatedAt: now,
|
|
164
|
+
messages: redactMessages(this.messages), // 存储前自动脱敏
|
|
165
|
+
});
|
|
166
|
+
this.savedToHistory = true;
|
|
167
|
+
}
|
|
168
|
+
setModel(model) {
|
|
169
|
+
this.model = model;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ModelConfig } from './config.js';
|
|
2
|
+
import type { Message } from './session.js';
|
|
3
|
+
import type { ToolCall } from './tools.js';
|
|
4
|
+
export interface ChatOptions {
|
|
5
|
+
stream?: boolean;
|
|
6
|
+
onChunk?: (chunk: string) => void;
|
|
7
|
+
tools?: object[];
|
|
8
|
+
}
|
|
9
|
+
export interface ChatResponse {
|
|
10
|
+
content: string;
|
|
11
|
+
toolCalls?: ToolCall[];
|
|
12
|
+
finishReason?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function chat(modelConfig: ModelConfig, messages: Message[], options?: ChatOptions): Promise<ChatResponse>;
|
|
15
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/core/stream.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,IAAI,CACxB,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,YAAY,CAAC,CA+HvB"}
|