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.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +328 -0
  3. package/dist/commands/agent.d.ts +12 -0
  4. package/dist/commands/agent.d.ts.map +1 -0
  5. package/dist/commands/agent.js +311 -0
  6. package/dist/commands/agent.js.map +1 -0
  7. package/dist/commands/ask.d.ts +7 -0
  8. package/dist/commands/ask.d.ts.map +1 -0
  9. package/dist/commands/ask.js +52 -0
  10. package/dist/commands/ask.js.map +1 -0
  11. package/dist/commands/chat.d.ts +9 -0
  12. package/dist/commands/chat.d.ts.map +1 -0
  13. package/dist/commands/chat.js +129 -0
  14. package/dist/commands/chat.js.map +1 -0
  15. package/dist/commands/cmd.d.ts +6 -0
  16. package/dist/commands/cmd.d.ts.map +1 -0
  17. package/dist/commands/cmd.js +52 -0
  18. package/dist/commands/cmd.js.map +1 -0
  19. package/dist/commands/code.d.ts +8 -0
  20. package/dist/commands/code.d.ts.map +1 -0
  21. package/dist/commands/code.js +75 -0
  22. package/dist/commands/code.js.map +1 -0
  23. package/dist/commands/file.d.ts +7 -0
  24. package/dist/commands/file.d.ts.map +1 -0
  25. package/dist/commands/file.js +66 -0
  26. package/dist/commands/file.js.map +1 -0
  27. package/dist/commands/history.d.ts +5 -0
  28. package/dist/commands/history.d.ts.map +1 -0
  29. package/dist/commands/history.js +159 -0
  30. package/dist/commands/history.js.map +1 -0
  31. package/dist/commands/init.d.ts +2 -0
  32. package/dist/commands/init.d.ts.map +1 -0
  33. package/dist/commands/init.js +144 -0
  34. package/dist/commands/init.js.map +1 -0
  35. package/dist/commands/install.d.ts +24 -0
  36. package/dist/commands/install.d.ts.map +1 -0
  37. package/dist/commands/install.js +328 -0
  38. package/dist/commands/install.js.map +1 -0
  39. package/dist/commands/model.d.ts +6 -0
  40. package/dist/commands/model.d.ts.map +1 -0
  41. package/dist/commands/model.js +128 -0
  42. package/dist/commands/model.js.map +1 -0
  43. package/dist/commands/pkg.d.ts +12 -0
  44. package/dist/commands/pkg.d.ts.map +1 -0
  45. package/dist/commands/pkg.js +132 -0
  46. package/dist/commands/pkg.js.map +1 -0
  47. package/dist/commands/run.d.ts +9 -0
  48. package/dist/commands/run.d.ts.map +1 -0
  49. package/dist/commands/run.js +185 -0
  50. package/dist/commands/run.js.map +1 -0
  51. package/dist/core/agentTask.d.ts +20 -0
  52. package/dist/core/agentTask.d.ts.map +1 -0
  53. package/dist/core/agentTask.js +81 -0
  54. package/dist/core/agentTask.js.map +1 -0
  55. package/dist/core/config.d.ts +41 -0
  56. package/dist/core/config.d.ts.map +1 -0
  57. package/dist/core/config.js +153 -0
  58. package/dist/core/config.js.map +1 -0
  59. package/dist/core/executor.d.ts +20 -0
  60. package/dist/core/executor.d.ts.map +1 -0
  61. package/dist/core/executor.js +68 -0
  62. package/dist/core/executor.js.map +1 -0
  63. package/dist/core/files.d.ts +24 -0
  64. package/dist/core/files.d.ts.map +1 -0
  65. package/dist/core/files.js +95 -0
  66. package/dist/core/files.js.map +1 -0
  67. package/dist/core/github.d.ts +32 -0
  68. package/dist/core/github.d.ts.map +1 -0
  69. package/dist/core/github.js +82 -0
  70. package/dist/core/github.js.map +1 -0
  71. package/dist/core/prompt.d.ts +9 -0
  72. package/dist/core/prompt.d.ts.map +1 -0
  73. package/dist/core/prompt.js +44 -0
  74. package/dist/core/prompt.js.map +1 -0
  75. package/dist/core/router.d.ts +16 -0
  76. package/dist/core/router.d.ts.map +1 -0
  77. package/dist/core/router.js +182 -0
  78. package/dist/core/router.js.map +1 -0
  79. package/dist/core/search.d.ts +14 -0
  80. package/dist/core/search.d.ts.map +1 -0
  81. package/dist/core/search.js +179 -0
  82. package/dist/core/search.js.map +1 -0
  83. package/dist/core/session.d.ts +38 -0
  84. package/dist/core/session.d.ts.map +1 -0
  85. package/dist/core/session.js +172 -0
  86. package/dist/core/session.js.map +1 -0
  87. package/dist/core/stream.d.ts +15 -0
  88. package/dist/core/stream.d.ts.map +1 -0
  89. package/dist/core/stream.js +102 -0
  90. package/dist/core/stream.js.map +1 -0
  91. package/dist/core/tools.d.ts +343 -0
  92. package/dist/core/tools.d.ts.map +1 -0
  93. package/dist/core/tools.js +293 -0
  94. package/dist/core/tools.js.map +1 -0
  95. package/dist/index.d.ts +3 -0
  96. package/dist/index.d.ts.map +1 -0
  97. package/dist/index.js +372 -0
  98. package/dist/index.js.map +1 -0
  99. package/dist/ui/renderer.d.ts +17 -0
  100. package/dist/ui/renderer.d.ts.map +1 -0
  101. package/dist/ui/renderer.js +69 -0
  102. package/dist/ui/renderer.js.map +1 -0
  103. 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":"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"}
@@ -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"}