@zhanngning/hecode 0.1.0 → 0.2.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.
- package/README.md +52 -1
- package/dist/{chunk-ECQ3AREB.js → chunk-I4W33CWB.js} +307 -2
- package/dist/chunk-I4W33CWB.js.map +1 -0
- package/dist/index.js +17 -6
- package/dist/index.js.map +1 -1
- package/dist/orchestrator-QX3OE4IN.js +7 -0
- package/package.json +20 -3
- package/skills/coding/SKILL.md +11 -0
- package/skills/finance/SKILL.md +51 -0
- package/dist/chunk-ECQ3AREB.js.map +0 -1
- package/dist/orchestrator-VEQUC74P.js +0 -7
- /package/dist/{orchestrator-VEQUC74P.js.map → orchestrator-QX3OE4IN.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Hecode
|
|
2
2
|
|
|
3
|
-
Your AI Coding Assistant CLI.
|
|
3
|
+
Your AI Coding Assistant CLI with Financial Analysis.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
@@ -9,6 +9,7 @@ Your AI Coding Assistant CLI.
|
|
|
9
9
|
- **Skill System**: Loadable domain skills (coding, data analysis, finance, etc.)
|
|
10
10
|
- **Memory System**: Session, project, and global memory with search
|
|
11
11
|
- **Interactive REPL**: Streaming output, slash commands, tool status display
|
|
12
|
+
- **Financial Analysis**: Stock analysis, technical indicators, research reports
|
|
12
13
|
|
|
13
14
|
## Install
|
|
14
15
|
|
|
@@ -68,6 +69,56 @@ Edit `~/.hecode/config.json`:
|
|
|
68
69
|
| `bash` | Execute shell commands |
|
|
69
70
|
| `glob` | File pattern matching |
|
|
70
71
|
| `grep` | Content regex search |
|
|
72
|
+
| `finance_analyze` | Financial analysis and research reports |
|
|
73
|
+
|
|
74
|
+
## Financial Analysis
|
|
75
|
+
|
|
76
|
+
Analyze stocks and generate research reports using free data sources.
|
|
77
|
+
|
|
78
|
+
### Usage
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Interactive mode with finance skill
|
|
82
|
+
hecode --skill finance "分析贵州茅台"
|
|
83
|
+
|
|
84
|
+
# Direct tool call
|
|
85
|
+
hecode "分析股票 600519"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Features
|
|
89
|
+
|
|
90
|
+
- **Price Analysis**: Current price, change percentage, volume
|
|
91
|
+
- **Technical Indicators**: MA5, MA10, MA20, RSI(14)
|
|
92
|
+
- **Trend Detection**: Uptrend, downtrend, or neutral
|
|
93
|
+
- **Research Reports**: Comprehensive Markdown reports
|
|
94
|
+
|
|
95
|
+
### Supported Markets
|
|
96
|
+
|
|
97
|
+
- **A-Shares**: Shanghai and Shenzhen stock exchanges
|
|
98
|
+
- **HK Stocks**: Hong Kong stock exchange
|
|
99
|
+
|
|
100
|
+
### Prerequisites
|
|
101
|
+
|
|
102
|
+
Install Python and akshare:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pip install akshare pandas
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Example Output
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
# 贵州茅台 (600519) 研究报告
|
|
112
|
+
|
|
113
|
+
## 价格信息
|
|
114
|
+
- 当前价格: ¥1168.63
|
|
115
|
+
- 涨跌幅: -1.3%
|
|
116
|
+
|
|
117
|
+
## 技术分析
|
|
118
|
+
- 5日均线: ¥1180.25
|
|
119
|
+
- RSI(14): 45.32
|
|
120
|
+
- 趋势信号: 中性
|
|
121
|
+
```
|
|
71
122
|
|
|
72
123
|
## REPL Commands
|
|
73
124
|
|
|
@@ -228,6 +228,310 @@ function matchGlob(filename, pattern) {
|
|
|
228
228
|
return new RegExp(regexStr, "i").test(filename);
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
+
// src/datasources/akshare.ts
|
|
232
|
+
import { exec as exec2 } from "child_process";
|
|
233
|
+
import { promisify } from "util";
|
|
234
|
+
import path from "path";
|
|
235
|
+
var execAsync = promisify(exec2);
|
|
236
|
+
var AkshareDataSource = class {
|
|
237
|
+
scriptPath;
|
|
238
|
+
constructor() {
|
|
239
|
+
this.scriptPath = path.join(import.meta.dirname, "akshare_datasource.py");
|
|
240
|
+
}
|
|
241
|
+
async getStockInfo(code, market = "A") {
|
|
242
|
+
const { stdout } = await execAsync(
|
|
243
|
+
`python ${this.scriptPath} info ${code} ${market}`
|
|
244
|
+
);
|
|
245
|
+
const data = JSON.parse(stdout);
|
|
246
|
+
if (data.error) throw new Error(data.error);
|
|
247
|
+
return {
|
|
248
|
+
code,
|
|
249
|
+
name: data[0]?.name || code,
|
|
250
|
+
market,
|
|
251
|
+
date: data[0]?.date,
|
|
252
|
+
open: data[0]?.open,
|
|
253
|
+
close: data[0]?.close,
|
|
254
|
+
high: data[0]?.high,
|
|
255
|
+
low: data[0]?.low,
|
|
256
|
+
volume: data[0]?.volume,
|
|
257
|
+
amount: data[0]?.amount,
|
|
258
|
+
change_pct: data[0]?.change_pct
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
async getFinancialData(code, market = "A") {
|
|
262
|
+
const { stdout } = await execAsync(
|
|
263
|
+
`python ${this.scriptPath} financial ${code} ${market}`
|
|
264
|
+
);
|
|
265
|
+
const data = JSON.parse(stdout);
|
|
266
|
+
if (data.error) throw new Error(data.error);
|
|
267
|
+
return {
|
|
268
|
+
code,
|
|
269
|
+
price: data[0]?.price,
|
|
270
|
+
change_pct: data[0]?.change_pct,
|
|
271
|
+
volume: data[0]?.volume,
|
|
272
|
+
amount: data[0]?.amount,
|
|
273
|
+
turnover: data[0]?.turnover
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
async getStockHistory(code, market = "A", days = 30) {
|
|
277
|
+
const { stdout } = await execAsync(
|
|
278
|
+
`python ${this.scriptPath} history ${code} ${market} ${days}`
|
|
279
|
+
);
|
|
280
|
+
const data = JSON.parse(stdout);
|
|
281
|
+
if (data.error) throw new Error(data.error);
|
|
282
|
+
return data.map((item) => ({
|
|
283
|
+
date: item.date,
|
|
284
|
+
open: item.open,
|
|
285
|
+
close: item.close,
|
|
286
|
+
high: item.high,
|
|
287
|
+
low: item.low,
|
|
288
|
+
volume: item.volume,
|
|
289
|
+
change_pct: item.change_pct
|
|
290
|
+
}));
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
// src/workflow/state.ts
|
|
295
|
+
function createInitialState(target) {
|
|
296
|
+
return {
|
|
297
|
+
target,
|
|
298
|
+
data: {},
|
|
299
|
+
analysis: {},
|
|
300
|
+
output: {},
|
|
301
|
+
status: "pending"
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// src/workflow/engine.ts
|
|
306
|
+
var WorkflowEngine = class {
|
|
307
|
+
nodes;
|
|
308
|
+
onStateChange;
|
|
309
|
+
constructor(config) {
|
|
310
|
+
this.nodes = config.nodes;
|
|
311
|
+
this.onStateChange = config.onStateChange;
|
|
312
|
+
}
|
|
313
|
+
async execute(target) {
|
|
314
|
+
let state = createInitialState(target);
|
|
315
|
+
for (const node of this.nodes) {
|
|
316
|
+
state = await node(state);
|
|
317
|
+
this.onStateChange?.(state);
|
|
318
|
+
if (state.status === "error") {
|
|
319
|
+
throw new Error(state.error);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return state;
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
// src/workflow/nodes/data-collection.ts
|
|
327
|
+
async function dataCollectionNode(state, dataSource) {
|
|
328
|
+
const { code, market } = state.target;
|
|
329
|
+
try {
|
|
330
|
+
const [stockInfo, financial, history] = await Promise.all([
|
|
331
|
+
dataSource.getStockInfo(code, market),
|
|
332
|
+
dataSource.getFinancialData(code, market),
|
|
333
|
+
dataSource.getStockHistory(code, market, 30)
|
|
334
|
+
]);
|
|
335
|
+
return {
|
|
336
|
+
...state,
|
|
337
|
+
data: {
|
|
338
|
+
stockInfo,
|
|
339
|
+
financial,
|
|
340
|
+
history
|
|
341
|
+
},
|
|
342
|
+
status: "collecting"
|
|
343
|
+
};
|
|
344
|
+
} catch (error) {
|
|
345
|
+
return {
|
|
346
|
+
...state,
|
|
347
|
+
status: "error",
|
|
348
|
+
error: `\u6570\u636E\u91C7\u96C6\u5931\u8D25: ${error.message}`
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// src/workflow/nodes/analysis.ts
|
|
354
|
+
function calculateMA(data, period) {
|
|
355
|
+
if (data.length < period) return void 0;
|
|
356
|
+
const slice = data.slice(-period);
|
|
357
|
+
return slice.reduce((a, b) => a + b, 0) / period;
|
|
358
|
+
}
|
|
359
|
+
function calculateRSI(prices, period = 14) {
|
|
360
|
+
if (prices.length < period + 1) return void 0;
|
|
361
|
+
let gains = 0;
|
|
362
|
+
let losses = 0;
|
|
363
|
+
for (let i = prices.length - period; i < prices.length; i++) {
|
|
364
|
+
const change = prices[i] - prices[i - 1];
|
|
365
|
+
if (change > 0) {
|
|
366
|
+
gains += change;
|
|
367
|
+
} else {
|
|
368
|
+
losses -= change;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
const avgGain = gains / period;
|
|
372
|
+
const avgLoss = losses / period;
|
|
373
|
+
if (avgLoss === 0) return 100;
|
|
374
|
+
const rs = avgGain / avgLoss;
|
|
375
|
+
return 100 - 100 / (1 + rs);
|
|
376
|
+
}
|
|
377
|
+
async function analysisNode(state) {
|
|
378
|
+
if (state.status === "error") return state;
|
|
379
|
+
const { financial, history, stockInfo } = state.data;
|
|
380
|
+
try {
|
|
381
|
+
const prices = history?.map((h) => h.close) || [];
|
|
382
|
+
const ma5 = calculateMA(prices, 5);
|
|
383
|
+
const ma10 = calculateMA(prices, 10);
|
|
384
|
+
const ma20 = calculateMA(prices, 20);
|
|
385
|
+
const rsi = calculateRSI(prices);
|
|
386
|
+
const financialAnalysis = {
|
|
387
|
+
price: financial?.price,
|
|
388
|
+
change_pct: financial?.change_pct,
|
|
389
|
+
volume: financial?.volume,
|
|
390
|
+
amount: financial?.amount,
|
|
391
|
+
turnover: financial?.turnover
|
|
392
|
+
};
|
|
393
|
+
const trend = {
|
|
394
|
+
ma5: ma5 ? Math.round(ma5 * 100) / 100 : void 0,
|
|
395
|
+
ma10: ma10 ? Math.round(ma10 * 100) / 100 : void 0,
|
|
396
|
+
ma20: ma20 ? Math.round(ma20 * 100) / 100 : void 0,
|
|
397
|
+
rsi: rsi ? Math.round(rsi * 100) / 100 : void 0
|
|
398
|
+
};
|
|
399
|
+
let trendSignal = "\u4E2D\u6027";
|
|
400
|
+
if (ma5 && ma10 && ma20) {
|
|
401
|
+
if (ma5 > ma10 && ma10 > ma20) {
|
|
402
|
+
trendSignal = "\u4E0A\u5347\u8D8B\u52BF";
|
|
403
|
+
} else if (ma5 < ma10 && ma10 < ma20) {
|
|
404
|
+
trendSignal = "\u4E0B\u964D\u8D8B\u52BF";
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return {
|
|
408
|
+
...state,
|
|
409
|
+
analysis: {
|
|
410
|
+
financial: financialAnalysis,
|
|
411
|
+
trend,
|
|
412
|
+
comparison: {
|
|
413
|
+
industry: stockInfo?.industry || "\u672A\u77E5",
|
|
414
|
+
trendSignal
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
status: "analyzing"
|
|
418
|
+
};
|
|
419
|
+
} catch (error) {
|
|
420
|
+
return {
|
|
421
|
+
...state,
|
|
422
|
+
status: "error",
|
|
423
|
+
error: `\u5206\u6790\u5931\u8D25: ${error.message}`
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// src/workflow/nodes/report.ts
|
|
429
|
+
async function reportNode(state) {
|
|
430
|
+
if (state.status === "error") return state;
|
|
431
|
+
const { target, analysis, data } = state;
|
|
432
|
+
try {
|
|
433
|
+
const report = `# ${target.company} (${target.code}) \u7814\u7A76\u62A5\u544A
|
|
434
|
+
|
|
435
|
+
## \u516C\u53F8\u6982\u51B5
|
|
436
|
+
- **\u80A1\u7968\u4EE3\u7801**: ${target.code}
|
|
437
|
+
- **\u5E02\u573A**: ${target.market}
|
|
438
|
+
- **\u884C\u4E1A**: ${analysis.comparison?.industry || "\u672A\u77E5"}
|
|
439
|
+
|
|
440
|
+
## \u4EF7\u683C\u4FE1\u606F
|
|
441
|
+
- **\u5F53\u524D\u4EF7\u683C**: \xA5${analysis.financial?.price || "N/A"}
|
|
442
|
+
- **\u6DA8\u8DCC\u5E45**: ${analysis.financial?.change_pct || "N/A"}%
|
|
443
|
+
- **\u6210\u4EA4\u91CF**: ${analysis.financial?.volume ? (analysis.financial.volume / 1e4).toFixed(2) + "\u4E07\u624B" : "N/A"}
|
|
444
|
+
- **\u6210\u4EA4\u989D**: ${analysis.financial?.amount ? (analysis.financial.amount / 1e8).toFixed(2) + "\u4EBF" : "N/A"}
|
|
445
|
+
|
|
446
|
+
## \u6280\u672F\u5206\u6790
|
|
447
|
+
- **5\u65E5\u5747\u7EBF**: \xA5${analysis.trend?.ma5 || "N/A"}
|
|
448
|
+
- **10\u65E5\u5747\u7EBF**: \xA5${analysis.trend?.ma10 || "N/A"}
|
|
449
|
+
- **20\u65E5\u5747\u7EBF**: \xA5${analysis.trend?.ma20 || "N/A"}
|
|
450
|
+
- **RSI(14)**: ${analysis.trend?.rsi || "N/A"}
|
|
451
|
+
- **\u8D8B\u52BF\u4FE1\u53F7**: ${analysis.comparison?.trendSignal || "\u4E2D\u6027"}
|
|
452
|
+
|
|
453
|
+
## \u8FD1\u671F\u8D70\u52BF
|
|
454
|
+
${data.history ? data.history.slice(-5).map(
|
|
455
|
+
(h) => `- ${h.date}: \u5F00\u76D8 \xA5${h.open} | \u6536\u76D8 \xA5${h.close} | \u6DA8\u8DCC ${h.change_pct}%`
|
|
456
|
+
).join("\n") : "\u65E0\u6570\u636E"}
|
|
457
|
+
|
|
458
|
+
## \u6295\u8D44\u5EFA\u8BAE
|
|
459
|
+
\u57FA\u4E8E\u6280\u672F\u5206\u6790\uFF0C${target.company} \u5F53\u524D\u5904\u4E8E **${analysis.comparison?.trendSignal || "\u4E2D\u6027"}**\u3002
|
|
460
|
+
|
|
461
|
+
${analysis.trend?.rsi && analysis.trend.rsi > 70 ? "\u26A0\uFE0F RSI \u8D85\u4E70\u533A\u57DF\uFF0C\u6CE8\u610F\u56DE\u8C03\u98CE\u9669" : ""}
|
|
462
|
+
${analysis.trend?.rsi && analysis.trend.rsi < 30 ? "\u2705 RSI \u8D85\u5356\u533A\u57DF\uFF0C\u53EF\u80FD\u5B58\u5728\u53CD\u5F39\u673A\u4F1A" : ""}
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
*\u62A5\u544A\u751F\u6210\u65F6\u95F4: ${(/* @__PURE__ */ new Date()).toISOString()}*
|
|
466
|
+
*\u6570\u636E\u6765\u6E90: akshare (\u514D\u8D39\u6570\u636E)*
|
|
467
|
+
`;
|
|
468
|
+
return {
|
|
469
|
+
...state,
|
|
470
|
+
output: {
|
|
471
|
+
report,
|
|
472
|
+
format: "markdown"
|
|
473
|
+
},
|
|
474
|
+
status: "done"
|
|
475
|
+
};
|
|
476
|
+
} catch (error) {
|
|
477
|
+
return {
|
|
478
|
+
...state,
|
|
479
|
+
status: "error",
|
|
480
|
+
error: `\u62A5\u544A\u751F\u6210\u5931\u8D25: ${error.message}`
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// src/tools/finance.ts
|
|
486
|
+
var financeTool = {
|
|
487
|
+
name: "finance_analyze",
|
|
488
|
+
description: "\u5206\u6790\u4E0A\u5E02\u516C\u53F8\u8D22\u52A1\u6570\u636E\u5E76\u751F\u6210\u7814\u7A76\u62A5\u544A",
|
|
489
|
+
parameters: {
|
|
490
|
+
type: "object",
|
|
491
|
+
properties: {
|
|
492
|
+
company: {
|
|
493
|
+
type: "string",
|
|
494
|
+
description: "\u516C\u53F8\u540D\u79F0"
|
|
495
|
+
},
|
|
496
|
+
code: {
|
|
497
|
+
type: "string",
|
|
498
|
+
description: "\u80A1\u7968\u4EE3\u7801"
|
|
499
|
+
},
|
|
500
|
+
market: {
|
|
501
|
+
type: "string",
|
|
502
|
+
enum: ["A", "HK"],
|
|
503
|
+
description: "\u5E02\u573A\u7C7B\u578B (A: A\u80A1, HK: \u6E2F\u80A1)"
|
|
504
|
+
}
|
|
505
|
+
},
|
|
506
|
+
required: ["company", "code"]
|
|
507
|
+
},
|
|
508
|
+
execute: async (params) => {
|
|
509
|
+
try {
|
|
510
|
+
const dataSource = new AkshareDataSource();
|
|
511
|
+
const engine = new WorkflowEngine({
|
|
512
|
+
nodes: [
|
|
513
|
+
(state) => dataCollectionNode(state, dataSource),
|
|
514
|
+
analysisNode,
|
|
515
|
+
reportNode
|
|
516
|
+
]
|
|
517
|
+
});
|
|
518
|
+
const result = await engine.execute({
|
|
519
|
+
company: params.company,
|
|
520
|
+
code: params.code,
|
|
521
|
+
market: params.market || "A"
|
|
522
|
+
});
|
|
523
|
+
return {
|
|
524
|
+
output: result.output.report || "\u5206\u6790\u5B8C\u6210"
|
|
525
|
+
};
|
|
526
|
+
} catch (error) {
|
|
527
|
+
return {
|
|
528
|
+
output: "",
|
|
529
|
+
error: error.message
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
|
|
231
535
|
// src/tools/index.ts
|
|
232
536
|
var builtinTools = [
|
|
233
537
|
readFileTool,
|
|
@@ -235,7 +539,8 @@ var builtinTools = [
|
|
|
235
539
|
editFileTool,
|
|
236
540
|
bashTool,
|
|
237
541
|
globTool,
|
|
238
|
-
grepTool
|
|
542
|
+
grepTool,
|
|
543
|
+
financeTool
|
|
239
544
|
];
|
|
240
545
|
|
|
241
546
|
// src/core/orchestrator.ts
|
|
@@ -362,4 +667,4 @@ Key principles:
|
|
|
362
667
|
export {
|
|
363
668
|
Orchestrator
|
|
364
669
|
};
|
|
365
|
-
//# sourceMappingURL=chunk-
|
|
670
|
+
//# sourceMappingURL=chunk-I4W33CWB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tools/read_file.ts","../src/tools/write_file.ts","../src/tools/edit_file.ts","../src/tools/bash.ts","../src/tools/glob.ts","../src/tools/grep.ts","../src/datasources/akshare.ts","../src/workflow/state.ts","../src/workflow/engine.ts","../src/workflow/nodes/data-collection.ts","../src/workflow/nodes/analysis.ts","../src/workflow/nodes/report.ts","../src/tools/finance.ts","../src/tools/index.ts","../src/core/orchestrator.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport type { Tool, ToolResult } from \"../core/types.js\";\n\nexport const readFileTool: Tool = {\n name: \"read_file\",\n description: \"Read file content. Supports offset and limit for large files.\",\n parameters: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\", description: \"Absolute path to the file\" },\n offset: { type: \"number\", description: \"Line number to start from (1-indexed)\" },\n limit: { type: \"number\", description: \"Max lines to read (default 2000)\" },\n },\n required: [\"file_path\"],\n },\n async execute(params): Promise<ToolResult> {\n try {\n const content = await readFile(params.file_path as string, \"utf-8\");\n const lines = content.split(\"\\n\");\n const offset = (params.offset as number) || 1;\n const limit = (params.limit as number) || 2000;\n const sliced = lines.slice(offset - 1, offset - 1 + limit);\n const numbered = sliced.map((line, i) => `${offset + i}: ${line}`).join(\"\\n\");\n return { output: numbered };\n } catch (e: any) {\n return { output: \"\", error: e.message };\n }\n },\n};\n","import { writeFile, mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { Tool, ToolResult } from \"../core/types.js\";\n\nexport const writeFileTool: Tool = {\n name: \"write_file\",\n description: \"Write content to a file. Creates parent directories if needed.\",\n parameters: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\", description: \"Absolute path to the file\" },\n content: { type: \"string\", description: \"Content to write\" },\n },\n required: [\"file_path\", \"content\"],\n },\n async execute(params): Promise<ToolResult> {\n try {\n await mkdir(dirname(params.file_path as string), { recursive: true });\n await writeFile(params.file_path as string, params.content as string, \"utf-8\");\n return { output: `File written: ${params.file_path}` };\n } catch (e: any) {\n return { output: \"\", error: e.message };\n }\n },\n};\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport type { Tool, ToolResult } from \"../core/types.js\";\n\nexport const editFileTool: Tool = {\n name: \"edit_file\",\n description:\n \"Replace exact string match in a file. Fails if old_string not found or matches multiple times.\",\n parameters: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\", description: \"Absolute path to the file\" },\n old_string: { type: \"string\", description: \"Exact string to replace\" },\n new_string: { type: \"string\", description: \"Replacement string\" },\n replace_all: { type: \"boolean\", description: \"Replace all occurrences (default false)\" },\n },\n required: [\"file_path\", \"old_string\", \"new_string\"],\n },\n async execute(params): Promise<ToolResult> {\n try {\n const content = await readFile(params.file_path as string, \"utf-8\");\n const oldStr = params.old_string as string;\n const newStr = params.new_string as string;\n const replaceAll = params.replace_all as boolean;\n\n if (!content.includes(oldStr)) {\n return { output: \"\", error: `old_string not found in ${params.file_path}` };\n }\n\n let result: string;\n if (replaceAll) {\n result = content.replaceAll(oldStr, newStr);\n } else {\n const count = content.split(oldStr).length - 1;\n if (count > 1) {\n return {\n output: \"\",\n error: `Found ${count} matches for old_string. Provide more context or set replace_all=true.`,\n };\n }\n result = content.replace(oldStr, newStr);\n }\n\n await writeFile(params.file_path as string, result, \"utf-8\");\n return { output: `Edited: ${params.file_path}` };\n } catch (e: any) {\n return { output: \"\", error: e.message };\n }\n },\n};\n","import { exec } from \"node:child_process\";\nimport type { Tool, ToolResult } from \"../core/types.js\";\n\nexport const bashTool: Tool = {\n name: \"bash\",\n description: \"Execute a shell command. Returns stdout and stderr.\",\n parameters: {\n type: \"object\",\n properties: {\n command: { type: \"string\", description: \"The command to execute\" },\n timeout: { type: \"number\", description: \"Timeout in ms (default 120000)\" },\n workdir: { type: \"string\", description: \"Working directory\" },\n },\n required: [\"command\"],\n },\n async execute(params): Promise<ToolResult> {\n return new Promise((resolve) => {\n const timeout = (params.timeout as number) || 120_000;\n exec(\n params.command as string,\n {\n timeout,\n cwd: (params.workdir as string) || process.cwd(),\n encoding: \"utf-8\",\n },\n (error, stdout, stderr) => {\n if (error && error.killed) {\n resolve({\n output: stdout ?? \"\",\n error: `Command timed out after ${timeout}ms`,\n });\n } else if (error && !stdout && !stderr) {\n resolve({ output: \"\", error: error.message });\n } else {\n resolve({ output: [stdout, stderr].filter(Boolean).join(\"\\n\").trim() });\n }\n },\n );\n });\n },\n};\n","import { glob } from \"node:fs/promises\";\nimport type { Tool, ToolResult } from \"../core/types.js\";\n\nexport const globTool: Tool = {\n name: \"glob\",\n description: \"Find files matching a glob pattern.\",\n parameters: {\n type: \"object\",\n properties: {\n pattern: {\n type: \"string\",\n description: \"Glob pattern (e.g. '**/*.ts', 'src/**/*.test.*')\",\n },\n path: { type: \"string\", description: \"Directory to search in (default: cwd)\" },\n },\n required: [\"pattern\"],\n },\n async execute(params): Promise<ToolResult> {\n try {\n const files: string[] = [];\n for await (const f of glob(params.pattern as string, {\n cwd: (params.path as string) || process.cwd(),\n })) {\n files.push(f);\n }\n files.sort();\n return { output: files.join(\"\\n\") || \"No files found\" };\n } catch (e: any) {\n return { output: \"\", error: e.message };\n }\n },\n};\n","import { readFile, readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { Tool, ToolResult } from \"../core/types.js\";\n\nexport const grepTool: Tool = {\n name: \"grep\",\n description:\n \"Search file contents using regex. Returns file paths and matching line numbers.\",\n parameters: {\n type: \"object\",\n properties: {\n pattern: { type: \"string\", description: \"Regex pattern to search for\" },\n path: { type: \"string\", description: \"Directory to search in (default: cwd)\" },\n include: { type: \"string\", description: \"File pattern to include (e.g. '*.ts')\" },\n },\n required: [\"pattern\"],\n },\n async execute(params): Promise<ToolResult> {\n try {\n const regex = new RegExp(params.pattern as string, \"gi\");\n const rootDir = (params.path as string) || process.cwd();\n const includePattern = params.include as string | undefined;\n const results: string[] = [];\n\n async function searchDir(dir: string, depth: number) {\n if (depth > 10 || results.length >= 200) return;\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n await searchDir(fullPath, depth + 1);\n } else if (entry.isFile()) {\n if (includePattern && !matchGlob(entry.name, includePattern)) continue;\n try {\n const content = await readFile(fullPath, \"utf-8\");\n const lines = content.split(\"\\n\");\n for (let i = 0; i < lines.length; i++) {\n if (regex.test(lines[i]!)) {\n results.push(`${fullPath}:${i + 1}: ${lines[i]!.trim()}`);\n if (results.length >= 200) return;\n }\n regex.lastIndex = 0;\n }\n } catch {\n /* skip binary/unreadable files */\n }\n }\n }\n }\n\n await searchDir(rootDir, 0);\n return { output: results.join(\"\\n\") || \"No matches found\" };\n } catch (e: any) {\n return { output: \"\", error: e.message };\n }\n },\n};\n\nfunction matchGlob(filename: string, pattern: string): boolean {\n const regexStr = \"^\" + pattern.replace(/\\*/g, \".*\").replace(/\\?/g, \".\") + \"$\";\n return new RegExp(regexStr, \"i\").test(filename);\n}\n","import { exec } from \"child_process\";\nimport { promisify } from \"util\";\nimport path from \"path\";\nimport { DataSource, StockInfo, FinancialData, HistoryData } from \"./index.js\";\n\nconst execAsync = promisify(exec);\n\nexport class AkshareDataSource implements DataSource {\n private scriptPath: string;\n\n constructor() {\n this.scriptPath = path.join(import.meta.dirname, \"akshare_datasource.py\");\n }\n\n async getStockInfo(code: string, market: string = \"A\"): Promise<StockInfo> {\n const { stdout } = await execAsync(\n `python ${this.scriptPath} info ${code} ${market}`\n );\n const data = JSON.parse(stdout);\n if (data.error) throw new Error(data.error);\n \n return {\n code,\n name: data[0]?.name || code,\n market,\n date: data[0]?.date,\n open: data[0]?.open,\n close: data[0]?.close,\n high: data[0]?.high,\n low: data[0]?.low,\n volume: data[0]?.volume,\n amount: data[0]?.amount,\n change_pct: data[0]?.change_pct,\n };\n }\n\n async getFinancialData(code: string, market: string = \"A\"): Promise<FinancialData> {\n const { stdout } = await execAsync(\n `python ${this.scriptPath} financial ${code} ${market}`\n );\n const data = JSON.parse(stdout);\n if (data.error) throw new Error(data.error);\n \n return {\n code,\n price: data[0]?.price,\n change_pct: data[0]?.change_pct,\n volume: data[0]?.volume,\n amount: data[0]?.amount,\n turnover: data[0]?.turnover,\n };\n }\n\n async getStockHistory(code: string, market: string = \"A\", days: number = 30): Promise<HistoryData[]> {\n const { stdout } = await execAsync(\n `python ${this.scriptPath} history ${code} ${market} ${days}`\n );\n const data = JSON.parse(stdout);\n if (data.error) throw new Error(data.error);\n \n return data.map((item: any) => ({\n date: item.date,\n open: item.open,\n close: item.close,\n high: item.high,\n low: item.low,\n volume: item.volume,\n change_pct: item.change_pct,\n }));\n }\n}\n","export interface TargetInfo {\n company: string;\n code: string;\n market: string;\n}\n\nexport interface CollectedData {\n stockInfo?: any;\n financial?: any;\n history?: any[];\n shareholder?: any;\n industry?: any;\n}\n\nexport interface AnalysisResult {\n financial?: {\n revenue?: number;\n netProfit?: number;\n roe?: number;\n growth?: number;\n price?: number;\n change_pct?: number;\n volume?: number;\n amount?: number;\n turnover?: number;\n };\n valuation?: {\n pe?: number;\n pb?: number;\n dcf?: number;\n };\n comparison?: {\n industry?: string;\n peers?: any[];\n trendSignal?: string;\n };\n trend?: {\n ma5?: number;\n ma10?: number;\n ma20?: number;\n rsi?: number;\n macd?: number;\n };\n}\n\nexport interface OutputResult {\n report?: string;\n charts?: string[];\n format?: \"markdown\" | \"word\";\n}\n\nexport interface WorkflowState {\n target: TargetInfo;\n data: CollectedData;\n analysis: AnalysisResult;\n output: OutputResult;\n status: \"pending\" | \"collecting\" | \"analyzing\" | \"generating\" | \"done\" | \"error\";\n error?: string;\n}\n\nexport function createInitialState(target: TargetInfo): WorkflowState {\n return {\n target,\n data: {},\n analysis: {},\n output: {},\n status: \"pending\",\n };\n}\n","import { WorkflowState, createInitialState, TargetInfo } from \"./state.js\";\n\nexport type NodeFunction = (state: WorkflowState) => Promise<WorkflowState>;\n\nexport interface WorkflowConfig {\n nodes: NodeFunction[];\n onStateChange?: (state: WorkflowState) => void;\n}\n\nexport class WorkflowEngine {\n private nodes: NodeFunction[];\n private onStateChange?: (state: WorkflowState) => void;\n\n constructor(config: WorkflowConfig) {\n this.nodes = config.nodes;\n this.onStateChange = config.onStateChange;\n }\n\n async execute(target: TargetInfo): Promise<WorkflowState> {\n let state = createInitialState(target);\n\n for (const node of this.nodes) {\n state = await node(state);\n this.onStateChange?.(state);\n\n if (state.status === \"error\") {\n throw new Error(state.error);\n }\n }\n\n return state;\n }\n}\n","import { WorkflowState } from \"../state.js\";\nimport { DataSource } from \"../../datasources/index.js\";\n\nexport async function dataCollectionNode(\n state: WorkflowState,\n dataSource: DataSource\n): Promise<WorkflowState> {\n const { code, market } = state.target;\n \n try {\n const [stockInfo, financial, history] = await Promise.all([\n dataSource.getStockInfo(code, market),\n dataSource.getFinancialData(code, market),\n dataSource.getStockHistory(code, market, 30),\n ]);\n\n return {\n ...state,\n data: {\n stockInfo,\n financial,\n history,\n },\n status: \"collecting\",\n };\n } catch (error: any) {\n return {\n ...state,\n status: \"error\",\n error: `数据采集失败: ${error.message}`,\n };\n }\n}\n","import { WorkflowState } from \"../state.js\";\n\nfunction calculateMA(data: number[], period: number): number | undefined {\n if (data.length < period) return undefined;\n const slice = data.slice(-period);\n return slice.reduce((a, b) => a + b, 0) / period;\n}\n\nfunction calculateRSI(prices: number[], period: number = 14): number | undefined {\n if (prices.length < period + 1) return undefined;\n \n let gains = 0;\n let losses = 0;\n \n for (let i = prices.length - period; i < prices.length; i++) {\n const change = prices[i] - prices[i - 1];\n if (change > 0) {\n gains += change;\n } else {\n losses -= change;\n }\n }\n \n const avgGain = gains / period;\n const avgLoss = losses / period;\n \n if (avgLoss === 0) return 100;\n \n const rs = avgGain / avgLoss;\n return 100 - (100 / (1 + rs));\n}\n\nexport async function analysisNode(state: WorkflowState): Promise<WorkflowState> {\n if (state.status === \"error\") return state;\n\n const { financial, history, stockInfo } = state.data;\n\n try {\n // 价格数据\n const prices = history?.map((h: any) => h.close) || [];\n \n // 计算技术指标\n const ma5 = calculateMA(prices, 5);\n const ma10 = calculateMA(prices, 10);\n const ma20 = calculateMA(prices, 20);\n const rsi = calculateRSI(prices);\n\n // 财务分析\n const financialAnalysis = {\n price: financial?.price,\n change_pct: financial?.change_pct,\n volume: financial?.volume,\n amount: financial?.amount,\n turnover: financial?.turnover,\n };\n\n // 趋势分析\n const trend = {\n ma5: ma5 ? Math.round(ma5 * 100) / 100 : undefined,\n ma10: ma10 ? Math.round(ma10 * 100) / 100 : undefined,\n ma20: ma20 ? Math.round(ma20 * 100) / 100 : undefined,\n rsi: rsi ? Math.round(rsi * 100) / 100 : undefined,\n };\n\n // 趋势判断\n let trendSignal = \"中性\";\n if (ma5 && ma10 && ma20) {\n if (ma5 > ma10 && ma10 > ma20) {\n trendSignal = \"上升趋势\";\n } else if (ma5 < ma10 && ma10 < ma20) {\n trendSignal = \"下降趋势\";\n }\n }\n\n return {\n ...state,\n analysis: {\n financial: financialAnalysis,\n trend,\n comparison: {\n industry: stockInfo?.industry || \"未知\",\n trendSignal,\n },\n },\n status: \"analyzing\",\n };\n } catch (error: any) {\n return {\n ...state,\n status: \"error\",\n error: `分析失败: ${error.message}`,\n };\n }\n}\n","import { WorkflowState } from \"../state.js\";\n\nexport async function reportNode(state: WorkflowState): Promise<WorkflowState> {\n if (state.status === \"error\") return state;\n\n const { target, analysis, data } = state;\n\n try {\n const report = `# ${target.company} (${target.code}) 研究报告\n\n## 公司概况\n- **股票代码**: ${target.code}\n- **市场**: ${target.market}\n- **行业**: ${analysis.comparison?.industry || \"未知\"}\n\n## 价格信息\n- **当前价格**: ¥${analysis.financial?.price || \"N/A\"}\n- **涨跌幅**: ${analysis.financial?.change_pct || \"N/A\"}%\n- **成交量**: ${analysis.financial?.volume ? (analysis.financial.volume / 10000).toFixed(2) + \"万手\" : \"N/A\"}\n- **成交额**: ${analysis.financial?.amount ? (analysis.financial.amount / 100000000).toFixed(2) + \"亿\" : \"N/A\"}\n\n## 技术分析\n- **5日均线**: ¥${analysis.trend?.ma5 || \"N/A\"}\n- **10日均线**: ¥${analysis.trend?.ma10 || \"N/A\"}\n- **20日均线**: ¥${analysis.trend?.ma20 || \"N/A\"}\n- **RSI(14)**: ${analysis.trend?.rsi || \"N/A\"}\n- **趋势信号**: ${analysis.comparison?.trendSignal || \"中性\"}\n\n## 近期走势\n${data.history ? data.history.slice(-5).map((h: any) => \n `- ${h.date}: 开盘 ¥${h.open} | 收盘 ¥${h.close} | 涨跌 ${h.change_pct}%`\n).join(\"\\n\") : \"无数据\"}\n\n## 投资建议\n基于技术分析,${target.company} 当前处于 **${analysis.comparison?.trendSignal || \"中性\"}**。\n\n${analysis.trend?.rsi && analysis.trend.rsi > 70 ? \"⚠️ RSI 超买区域,注意回调风险\" : \"\"}\n${analysis.trend?.rsi && analysis.trend.rsi < 30 ? \"✅ RSI 超卖区域,可能存在反弹机会\" : \"\"}\n\n---\n*报告生成时间: ${new Date().toISOString()}*\n*数据来源: akshare (免费数据)*\n`;\n\n return {\n ...state,\n output: {\n report,\n format: \"markdown\",\n },\n status: \"done\",\n };\n } catch (error: any) {\n return {\n ...state,\n status: \"error\",\n error: `报告生成失败: ${error.message}`,\n };\n }\n}\n","import { AkshareDataSource } from \"../datasources/akshare.js\";\nimport { WorkflowEngine } from \"../workflow/engine.js\";\nimport { dataCollectionNode } from \"../workflow/nodes/data-collection.js\";\nimport { analysisNode } from \"../workflow/nodes/analysis.js\";\nimport { reportNode } from \"../workflow/nodes/report.js\";\nimport type { Tool, ToolResult } from \"../core/types.js\";\n\nexport const financeTool: Tool = {\n name: \"finance_analyze\",\n description: \"分析上市公司财务数据并生成研究报告\",\n parameters: {\n type: \"object\",\n properties: {\n company: {\n type: \"string\",\n description: \"公司名称\",\n },\n code: {\n type: \"string\",\n description: \"股票代码\",\n },\n market: {\n type: \"string\",\n enum: [\"A\", \"HK\"],\n description: \"市场类型 (A: A股, HK: 港股)\",\n },\n },\n required: [\"company\", \"code\"],\n },\n execute: async (params: Record<string, unknown>): Promise<ToolResult> => {\n try {\n const dataSource = new AkshareDataSource();\n \n const engine = new WorkflowEngine({\n nodes: [\n (state) => dataCollectionNode(state, dataSource),\n analysisNode,\n reportNode,\n ],\n });\n\n const result = await engine.execute({\n company: params.company as string,\n code: params.code as string,\n market: (params.market as string) || \"A\",\n });\n\n return {\n output: result.output.report || \"分析完成\",\n };\n } catch (error: any) {\n return {\n output: \"\",\n error: error.message,\n };\n }\n },\n};\n\nexport const financeTools = [financeTool];\n","import type { Tool } from \"../core/types.js\";\nimport { readFileTool } from \"./read_file.js\";\nimport { writeFileTool } from \"./write_file.js\";\nimport { editFileTool } from \"./edit_file.js\";\nimport { bashTool } from \"./bash.js\";\nimport { globTool } from \"./glob.js\";\nimport { grepTool } from \"./grep.js\";\nimport { financeTool } from \"./finance.js\";\n\nexport const builtinTools: Tool[] = [\n readFileTool,\n writeFileTool,\n editFileTool,\n bashTool,\n globTool,\n grepTool,\n financeTool,\n];\n\nexport function getToolsByNames(names: string[]): Tool[] {\n return builtinTools.filter((t) => names.includes(t.name));\n}\n\nexport { readFileTool } from \"./read_file.js\";\nexport { writeFileTool } from \"./write_file.js\";\nexport { editFileTool } from \"./edit_file.js\";\nexport { bashTool } from \"./bash.js\";\nexport { globTool } from \"./glob.js\";\nexport { grepTool } from \"./grep.js\";\nexport { financeTool } from \"./finance.js\";\n","import type { ModelProvider, Message, Tool, ToolCall, ToolResult } from \"./types.js\";\nimport { builtinTools } from \"../tools/index.js\";\n\nexport interface OrchestratorOptions {\n model: ModelProvider;\n systemPrompt?: string;\n skillInstructions?: string;\n tools?: Tool[];\n maxIterations?: number;\n onToken?: (token: string) => void;\n onToolStart?: (name: string, params: Record<string, unknown>) => void;\n onToolEnd?: (name: string, result: ToolResult) => void;\n}\n\nexport class Orchestrator {\n private messages: Message[] = [];\n private tools: Tool[];\n private model: ModelProvider;\n private systemPrompt: string;\n private maxIterations: number;\n private callbacks: Pick<\n OrchestratorOptions,\n \"onToken\" | \"onToolStart\" | \"onToolEnd\"\n >;\n\n constructor(opts: OrchestratorOptions) {\n this.model = opts.model;\n this.systemPrompt = opts.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;\n if (opts.skillInstructions) {\n this.systemPrompt += \"\\n\\n\" + opts.skillInstructions;\n }\n this.tools = opts.tools ?? builtinTools;\n this.maxIterations = opts.maxIterations ?? 20;\n this.callbacks = {\n onToken: opts.onToken,\n onToolStart: opts.onToolStart,\n onToolEnd: opts.onToolEnd,\n };\n\n if (this.systemPrompt) {\n this.messages.push({ role: \"system\", content: this.systemPrompt });\n }\n }\n\n async run(userMessage: string): Promise<string> {\n this.messages.push({ role: \"user\", content: userMessage });\n\n for (let i = 0; i < this.maxIterations; i++) {\n const response = await this.model.chat(this.messages, this.tools);\n\n if (response.content) {\n this.messages.push({\n role: \"assistant\",\n content: response.content,\n tool_calls: response.tool_calls,\n });\n }\n\n if (!response.tool_calls?.length) {\n return response.content;\n }\n\n for (const tc of response.tool_calls) {\n this.callbacks.onToolStart?.(\n tc.function.name,\n JSON.parse(tc.function.arguments),\n );\n const result = await this.executeTool(tc);\n this.callbacks.onToolEnd?.(tc.function.name, result);\n this.messages.push({\n role: \"tool\",\n content: result.error ? `Error: ${result.error}` : result.output,\n tool_call_id: tc.id,\n });\n }\n }\n\n return \"Max iterations reached.\";\n }\n\n async *runStream(userMessage: string): AsyncIterable<string> {\n this.messages.push({ role: \"user\", content: userMessage });\n\n for (let i = 0; i < this.maxIterations; i++) {\n let fullContent = \"\";\n let toolCalls: ToolCall[] = [];\n\n for await (const chunk of this.model.stream(this.messages, this.tools)) {\n if (chunk.content) {\n fullContent += chunk.content;\n yield chunk.content;\n }\n if (chunk.tool_calls) {\n toolCalls = chunk.tool_calls;\n }\n }\n\n if (!toolCalls.length) {\n this.messages.push({ role: \"assistant\", content: fullContent });\n return;\n }\n\n this.messages.push({\n role: \"assistant\",\n content: fullContent,\n tool_calls: toolCalls,\n });\n\n for (const tc of toolCalls) {\n this.callbacks.onToolStart?.(\n tc.function.name,\n JSON.parse(tc.function.arguments),\n );\n const result = await this.executeTool(tc);\n this.callbacks.onToolEnd?.(tc.function.name, result);\n this.messages.push({\n role: \"tool\",\n content: result.error ? `Error: ${result.error}` : result.output,\n tool_call_id: tc.id,\n });\n }\n }\n }\n\n private async executeTool(tc: ToolCall): Promise<ToolResult> {\n const tool = this.tools.find((t) => t.name === tc.function.name);\n if (!tool) return { output: \"\", error: `Unknown tool: ${tc.function.name}` };\n try {\n const params = JSON.parse(tc.function.arguments);\n return await tool.execute(params);\n } catch (e: any) {\n return { output: \"\", error: e.message };\n }\n }\n\n getMessages(): Message[] {\n return [...this.messages];\n }\n\n clearMessages(): void {\n this.messages = [];\n if (this.systemPrompt) {\n this.messages.push({ role: \"system\", content: this.systemPrompt });\n }\n }\n}\n\nconst DEFAULT_SYSTEM_PROMPT = `You are Hecode, an AI coding assistant. You help users with software engineering tasks using the tools available to you.\n\nKey principles:\n- Be concise and direct\n- Use tools to read/write files, execute commands, and search code\n- Verify your work by running tests or checks when possible\n- Follow existing code conventions in the project`;\n"],"mappings":"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","names":["readFile","writeFile","readFile","exec"]}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
Orchestrator
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-I4W33CWB.js";
|
|
5
5
|
|
|
6
6
|
// src/cli/commands.ts
|
|
7
7
|
import { Command } from "commander";
|
|
@@ -393,12 +393,23 @@ async function startREPL(model, opts) {
|
|
|
393
393
|
output: process.stdout,
|
|
394
394
|
prompt: chalk.cyan("hecode> ")
|
|
395
395
|
});
|
|
396
|
-
|
|
397
|
-
|
|
396
|
+
const logo = chalk.cyan(`
|
|
397
|
+
\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
398
|
+
\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D
|
|
399
|
+
\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557
|
|
400
|
+
\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D
|
|
401
|
+
\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
402
|
+
\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
403
|
+
`);
|
|
404
|
+
console.log(logo);
|
|
405
|
+
console.log(chalk.bold.white(" Your AI Coding Assistant") + chalk.gray(" v0.2.0"));
|
|
406
|
+
console.log(chalk.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
407
|
+
console.log(chalk.gray(` Session: ${session.sessionId}`));
|
|
398
408
|
if (skills.length) {
|
|
399
|
-
console.log(chalk.gray(`Skills
|
|
409
|
+
console.log(chalk.gray(` Skills: ${skills.map((s) => s.name).join(", ")}`));
|
|
400
410
|
}
|
|
401
|
-
console.log(chalk.gray("
|
|
411
|
+
console.log(chalk.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
412
|
+
console.log(chalk.gray(" Type /help for commands, Ctrl+C to exit\n"));
|
|
402
413
|
rl.prompt();
|
|
403
414
|
rl.on("line", async (line) => {
|
|
404
415
|
const input = line.trim();
|
|
@@ -484,7 +495,7 @@ function createProgram() {
|
|
|
484
495
|
if (model) modelConfig.model = model;
|
|
485
496
|
const modelProvider = createProvider(provider, modelConfig);
|
|
486
497
|
if (prompt.length) {
|
|
487
|
-
const { Orchestrator: Orchestrator2 } = await import("./orchestrator-
|
|
498
|
+
const { Orchestrator: Orchestrator2 } = await import("./orchestrator-QX3OE4IN.js");
|
|
488
499
|
const orch = new Orchestrator2({ model: modelProvider });
|
|
489
500
|
const result = await orch.run(prompt.join(" "));
|
|
490
501
|
console.log(result);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/commands.ts","../src/cli/config.ts","../src/models/openai.ts","../src/models/anthropic.ts","../src/models/ollama.ts","../src/models/factory.ts","../src/cli/repl.ts","../src/memory/session.ts","../src/skills/loader.ts","../src/index.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { loadConfig } from \"./config.js\";\nimport { createProvider, parseModelString } from \"../models/factory.js\";\nimport { startREPL } from \"./repl.js\";\n\nexport function createProgram(): Command {\n const program = new Command();\n\n program\n .name(\"hecode\")\n .description(\"Hecode — Your AI Coding Assistant CLI\")\n .version(\"0.1.0\")\n .option(\"-m, --model <model>\", \"Model to use (e.g. openai:gpt-4o, claude:sonnet)\")\n .option(\"-s, --skill <skill>\", \"Skill to activate\")\n .argument(\"[prompt...]\", \"Single-shot prompt (non-interactive)\")\n .action(async (prompt: string[], opts: { model?: string; skill?: string }) => {\n const config = await loadConfig();\n const modelStr = opts.model ?? config.defaultModel;\n const { provider, model } = parseModelString(modelStr);\n const modelConfig = config.models[provider] ?? {};\n if (model) modelConfig.model = model;\n const modelProvider = createProvider(provider, modelConfig as Record<string, unknown>);\n\n if (prompt.length) {\n const { Orchestrator } = await import(\"../core/orchestrator.js\");\n const orch = new Orchestrator({ model: modelProvider });\n const result = await orch.run(prompt.join(\" \"));\n console.log(result);\n } else {\n await startREPL(modelProvider, { skillName: opts.skill });\n }\n });\n\n program\n .command(\"config\")\n .description(\"Show or edit configuration\")\n .action(async () => {\n const config = await loadConfig();\n console.log(JSON.stringify(config, null, 2));\n });\n\n return program;\n}\n","import { readFile, mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { Config } from \"../core/types.js\";\n\nconst CONFIG_DIR = join(homedir(), \".hecode\");\nconst CONFIG_FILE = join(CONFIG_DIR, \"config.json\");\n\nexport async function loadConfig(): Promise<Config> {\n try {\n const raw = await readFile(CONFIG_FILE, \"utf-8\");\n return JSON.parse(raw);\n } catch {\n return { defaultModel: \"openai:gpt-4o\", models: {} };\n }\n}\n\nexport async function saveConfig(config: Config): Promise<void> {\n await mkdir(CONFIG_DIR, { recursive: true });\n await writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), \"utf-8\");\n}\n","import OpenAI from \"openai\";\nimport type { ModelProvider, Message, Tool, Response, Chunk } from \"../core/types.js\";\n\nexport class OpenAIProvider implements ModelProvider {\n name = \"openai\";\n private client: OpenAI;\n private model: string;\n\n constructor(config: { apiKey?: string; baseUrl?: string; model?: string }) {\n this.client = new OpenAI({\n apiKey: config.apiKey ?? process.env.OPENAI_API_KEY,\n baseURL: config.baseUrl,\n });\n this.model = config.model ?? \"gpt-4o\";\n }\n\n async chat(messages: Message[], tools?: Tool[]): Promise<Response> {\n const params: OpenAI.ChatCompletionCreateParams = {\n model: this.model,\n messages: this.convertMessages(messages),\n ...(tools?.length && { tools: this.convertTools(tools) }),\n };\n const completion = await this.client.chat.completions.create(params);\n const choice = completion.choices[0]!;\n return {\n content: choice.message.content ?? \"\",\n tool_calls: choice.message.tool_calls\n ?.filter((tc) => tc.type === \"function\")\n .map((tc) => ({\n id: tc.id,\n type: \"function\" as const,\n function: { name: tc.function.name, arguments: tc.function.arguments },\n })),\n usage: completion.usage\n ? { prompt: completion.usage.prompt_tokens, completion: completion.usage.completion_tokens }\n : undefined,\n };\n }\n\n async *stream(messages: Message[], tools?: Tool[]): AsyncIterable<Chunk> {\n const stream = await this.client.chat.completions.create({\n model: this.model,\n messages: this.convertMessages(messages),\n stream: true,\n ...(tools?.length && { tools: this.convertTools(tools) }),\n });\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n if (!delta) continue;\n yield {\n content: delta.content ?? undefined,\n tool_calls: delta.tool_calls?.map((tc) => ({\n id: tc.id ?? \"\",\n type: \"function\" as const,\n function: { name: tc.function?.name ?? \"\", arguments: tc.function?.arguments ?? \"\" },\n })),\n done: chunk.choices[0]?.finish_reason != null,\n };\n }\n }\n\n private convertMessages(messages: Message[]): OpenAI.ChatCompletionMessageParam[] {\n return messages.map((m) => {\n if (m.role === \"tool\") {\n return { role: \"tool\" as const, content: m.content, tool_call_id: m.tool_call_id! };\n }\n if (m.role === \"assistant\" && m.tool_calls?.length) {\n return {\n role: \"assistant\" as const,\n content: m.content,\n tool_calls: m.tool_calls.map((tc) => ({\n id: tc.id,\n type: \"function\" as const,\n function: tc.function,\n })),\n };\n }\n return { role: m.role as \"system\" | \"user\" | \"assistant\", content: m.content };\n });\n }\n\n private convertTools(tools: Tool[]): OpenAI.ChatCompletionTool[] {\n return tools.map((t) => ({\n type: \"function\" as const,\n function: { name: t.name, description: t.description, parameters: t.parameters },\n }));\n }\n}\n","import Anthropic from \"@anthropic-ai/sdk\";\nimport type { ModelProvider, Message, Tool, Response, Chunk } from \"../core/types.js\";\n\nexport class AnthropicProvider implements ModelProvider {\n name = \"anthropic\";\n private client: Anthropic;\n private model: string;\n\n constructor(config: { apiKey?: string; model?: string }) {\n this.client = new Anthropic({ apiKey: config.apiKey ?? process.env.ANTHROPIC_API_KEY });\n this.model = config.model ?? \"claude-sonnet-4-20250514\";\n }\n\n async chat(messages: Message[], tools?: Tool[]): Promise<Response> {\n const system = messages.find((m) => m.role === \"system\")?.content ?? \"\";\n const convMessages = messages.filter((m) => m.role !== \"system\");\n const params: Anthropic.MessageCreateParams = {\n model: this.model,\n max_tokens: 8192,\n system,\n messages: this.convertMessages(convMessages),\n ...(tools?.length && { tools: this.convertTools(tools) }),\n };\n const msg = await this.client.messages.create(params);\n const textBlock = msg.content.find((b) => b.type === \"text\");\n const toolBlocks = msg.content.filter((b) => b.type === \"tool_use\");\n return {\n content: textBlock?.text ?? \"\",\n tool_calls: toolBlocks.map((tb) => ({\n id: tb.id,\n type: \"function\" as const,\n function: { name: tb.name, arguments: JSON.stringify(tb.input) },\n })),\n usage: { prompt: msg.usage.input_tokens, completion: msg.usage.output_tokens },\n };\n }\n\n async *stream(messages: Message[], tools?: Tool[]): AsyncIterable<Chunk> {\n const system = messages.find((m) => m.role === \"system\")?.content ?? \"\";\n const convMessages = messages.filter((m) => m.role !== \"system\");\n const stream = this.client.messages.stream({\n model: this.model,\n max_tokens: 8192,\n system,\n messages: this.convertMessages(convMessages),\n ...(tools?.length && { tools: this.convertTools(tools) }),\n });\n for await (const event of stream) {\n if (event.type === \"content_block_delta\" && event.delta.type === \"text_delta\") {\n yield { content: event.delta.text, done: false };\n }\n }\n yield { content: undefined, done: true };\n }\n\n private convertMessages(messages: Message[]): Anthropic.MessageParam[] {\n return messages.map((m) => ({\n role: m.role === \"assistant\" ? \"assistant\" : \"user\",\n content: m.content,\n }));\n }\n\n private convertTools(tools: Tool[]): Anthropic.Tool[] {\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: t.parameters as Anthropic.Tool[\"input_schema\"],\n }));\n }\n}\n","import type { ModelProvider, Message, Tool, Response, Chunk } from \"../core/types.js\";\n\nexport class OllamaProvider implements ModelProvider {\n name = \"ollama\";\n private baseUrl: string;\n private model: string;\n\n constructor(config: { baseUrl?: string; model?: string }) {\n this.baseUrl = config.baseUrl ?? \"http://localhost:11434\";\n this.model = config.model ?? \"llama3.1\";\n }\n\n async chat(messages: Message[], tools?: Tool[]): Promise<Response> {\n const res = await fetch(`${this.baseUrl}/api/chat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n model: this.model,\n messages: messages.map((m) => ({ role: m.role, content: m.content })),\n stream: false,\n ...(tools?.length && { tools: this.convertTools(tools) }),\n }),\n });\n const data = (await res.json()) as any;\n return {\n content: data.message?.content ?? \"\",\n tool_calls: data.message?.tool_calls?.map((tc: any, i: number) => ({\n id: `call_${i}`,\n type: \"function\" as const,\n function: {\n name: tc.function?.name ?? \"\",\n arguments: JSON.stringify(tc.function?.arguments ?? {}),\n },\n })),\n };\n }\n\n async *stream(messages: Message[], tools?: Tool[]): AsyncIterable<Chunk> {\n const res = await fetch(`${this.baseUrl}/api/chat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n model: this.model,\n messages: messages.map((m) => ({ role: m.role, content: m.content })),\n stream: true,\n ...(tools?.length && { tools: this.convertTools(tools) }),\n }),\n });\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop()!;\n for (const line of lines) {\n if (!line.trim()) continue;\n const data = JSON.parse(line);\n yield {\n content: data.message?.content ?? undefined,\n done: data.done ?? false,\n };\n }\n }\n yield { done: true };\n }\n\n private convertTools(tools: Tool[]) {\n return tools.map((t) => ({\n type: \"function\",\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n },\n }));\n }\n}\n","import type { ModelProvider } from \"../core/types.js\";\nimport { OpenAIProvider } from \"./openai.js\";\nimport { AnthropicProvider } from \"./anthropic.js\";\nimport { OllamaProvider } from \"./ollama.js\";\n\ntype ProviderFactory = (config: Record<string, unknown>) => ModelProvider;\n\nconst registry = new Map<string, ProviderFactory>();\n\nregistry.set(\"openai\", (c) => new OpenAIProvider(c as any));\nregistry.set(\"claude\", (c) => new AnthropicProvider(c as any));\nregistry.set(\"anthropic\", (c) => new AnthropicProvider(c as any));\nregistry.set(\"ollama\", (c) => new OllamaProvider(c as any));\n\nexport function registerProvider(name: string, factory: ProviderFactory) {\n registry.set(name, factory);\n}\n\nexport function createProvider(name: string, config: Record<string, unknown>): ModelProvider {\n const factory = registry.get(name);\n if (!factory)\n throw new Error(\n `Unknown model provider: ${name}. Available: ${[...registry.keys()].join(\", \")}`,\n );\n return factory(config);\n}\n\nexport function parseModelString(modelStr: string): { provider: string; model: string } {\n const [provider, ...rest] = modelStr.split(\":\");\n return { provider: provider!, model: rest.join(\":\") || \"\" };\n}\n","import * as readline from \"node:readline\";\nimport chalk from \"chalk\";\nimport { join } from \"node:path\";\nimport { Orchestrator } from \"../core/orchestrator.js\";\nimport { SessionMemory } from \"../memory/session.js\";\nimport { loadSkills, matchSkill } from \"../skills/loader.js\";\nimport type { ModelProvider, ToolResult } from \"../core/types.js\";\n\nexport async function startREPL(\n model: ModelProvider,\n opts?: { skillName?: string },\n): Promise<void> {\n const session = new SessionMemory();\n const skillsDir = join(process.cwd(), \"skills\");\n const skills = await loadSkills(skillsDir);\n\n let skillInstructions: string | undefined;\n if (opts?.skillName) {\n const skill = skills.find((s) => s.name === opts.skillName);\n if (skill) skillInstructions = skill.instructions;\n }\n\n const orchestrator = new Orchestrator({\n model,\n skillInstructions,\n onToolStart: (name) => console.log(chalk.yellow(` ⚙ ${name}...`)),\n onToolEnd: (_name, result: ToolResult) => {\n if (result.error) console.log(chalk.red(` ✗ ${_name}: ${result.error}`));\n else console.log(chalk.green(` ✓ ${_name}`));\n },\n });\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n prompt: chalk.cyan(\"hecode> \"),\n });\n\n console.log(chalk.bold(\"Hecode v0.1.0 — Your AI Coding Assistant\"));\n console.log(chalk.gray(`Session: ${session.sessionId}`));\n if (skills.length) {\n console.log(chalk.gray(`Skills loaded: ${skills.map((s) => s.name).join(\", \")}`));\n }\n console.log(chalk.gray(\"Type /help for commands, Ctrl+C to exit\\n\"));\n rl.prompt();\n\n rl.on(\"line\", async (line) => {\n const input = line.trim();\n if (!input) {\n rl.prompt();\n return;\n }\n\n if (input.startsWith(\"/\")) {\n handleCommand(input, orchestrator, session);\n rl.prompt();\n return;\n }\n\n // Auto-match skill if not already set\n if (!skillInstructions) {\n const matched = matchSkill(skills, input);\n if (matched) {\n console.log(chalk.gray(` [skill: ${matched.name}]`));\n }\n }\n\n try {\n process.stdout.write(chalk.white(\"\\n\"));\n for await (const token of orchestrator.runStream(input)) {\n process.stdout.write(token);\n }\n process.stdout.write(\"\\n\\n\");\n\n // Auto-save session after each exchange\n await session.save(orchestrator.getMessages());\n } catch (e: any) {\n console.log(chalk.red(`\\nError: ${e.message}\\n`));\n }\n\n rl.prompt();\n });\n\n rl.on(\"close\", () => {\n console.log(chalk.gray(\"\\nGoodbye!\"));\n process.exit(0);\n });\n}\n\nfunction handleCommand(\n input: string,\n orchestrator: Orchestrator,\n session: SessionMemory,\n): void {\n const cmd = input.split(\" \")[0];\n switch (cmd) {\n case \"/help\":\n console.log(\n chalk.cyan(`\n /help — Show this help\n /clear — Clear conversation\n /history — Show message count\n /save — Save session manually\n /session — Show session ID\n /exit — Exit Hecode\n `),\n );\n break;\n case \"/clear\":\n orchestrator.clearMessages();\n console.log(chalk.gray(\"Conversation cleared.\"));\n break;\n case \"/history\":\n console.log(chalk.gray(`Messages: ${orchestrator.getMessages().length}`));\n break;\n case \"/save\":\n session.save(orchestrator.getMessages()).then(() => {\n console.log(chalk.gray(\"Session saved.\"));\n });\n break;\n case \"/session\":\n console.log(chalk.gray(`Session ID: ${session.sessionId}`));\n break;\n case \"/exit\":\n process.exit(0);\n default:\n console.log(chalk.red(`Unknown command: ${cmd}`));\n }\n}\n","import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { randomUUID } from \"node:crypto\";\nimport type { Message } from \"../core/types.js\";\n\nconst SESSIONS_DIR = join(homedir(), \".hecode\", \"sessions\");\n\nexport interface Session {\n id: string;\n messages: Message[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport class SessionMemory {\n private sessionDir: string;\n\n constructor(sessionId?: string) {\n const id = sessionId ?? randomUUID().slice(0, 12);\n this.sessionDir = join(SESSIONS_DIR, id);\n }\n\n get sessionId(): string {\n return this.sessionDir.split(/[\\\\/]/).pop()!;\n }\n\n async save(messages: Message[]): Promise<void> {\n await mkdir(this.sessionDir, { recursive: true });\n const session: Session = {\n id: this.sessionId,\n messages,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n await writeFile(\n join(this.sessionDir, \"session.json\"),\n JSON.stringify(session, null, 2),\n );\n }\n\n async load(): Promise<Message[]> {\n try {\n const raw = await readFile(\n join(this.sessionDir, \"session.json\"),\n \"utf-8\",\n );\n const session: Session = JSON.parse(raw);\n return session.messages;\n } catch {\n return [];\n }\n }\n\n async saveCheckpoint(data: Record<string, unknown>): Promise<void> {\n await mkdir(this.sessionDir, { recursive: true });\n await writeFile(\n join(this.sessionDir, \"checkpoint.md\"),\n JSON.stringify(data, null, 2),\n );\n }\n\n async saveNote(content: string): Promise<void> {\n await mkdir(this.sessionDir, { recursive: true });\n const notePath = join(this.sessionDir, \"notes.md\");\n let existing = \"\";\n try {\n existing = await readFile(notePath, \"utf-8\");\n } catch {}\n await writeFile(notePath, existing + \"\\n\\n\" + content);\n }\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface Skill {\n name: string;\n description: string;\n trigger: string;\n instructions: string;\n tools?: string[];\n}\n\nexport async function loadSkills(skillsDir: string): Promise<Skill[]> {\n const skills: Skill[] = [];\n try {\n const entries = await readdir(skillsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const skillPath = join(skillsDir, entry.name, \"SKILL.md\");\n try {\n const content = await readFile(skillPath, \"utf-8\");\n const skill = parseSkill(entry.name, content);\n if (skill) skills.push(skill);\n } catch {\n /* no SKILL.md, skip */\n }\n }\n } catch {\n /* skills dir doesn't exist */\n }\n return skills;\n}\n\nfunction parseSkill(name: string, content: string): Skill | null {\n const descMatch = content.match(/^#\\s+(.+)$/m);\n const triggerMatch = content.match(/trigger:\\s*(.+)/i);\n if (!descMatch) return null;\n\n return {\n name,\n description: descMatch[1] ?? name,\n trigger: triggerMatch?.[1] ?? \"\",\n instructions: content,\n };\n}\n\nexport function matchSkill(skills: Skill[], userMessage: string): Skill | null {\n const lower = userMessage.toLowerCase();\n for (const skill of skills) {\n if (skill.trigger) {\n const triggers = skill.trigger.split(\",\").map((t) => t.trim().toLowerCase());\n for (const t of triggers) {\n if (lower.includes(t)) return skill;\n }\n }\n }\n return null;\n}\n","#!/usr/bin/env node\nimport { createProgram } from \"./cli/commands.js\";\n\nconst program = createProgram();\nprogram.parse();\n"],"mappings":"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","names":["join","readFile","writeFile","mkdir","join","homedir","readFile","join","join","program","Orchestrator"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands.ts","../src/cli/config.ts","../src/models/openai.ts","../src/models/anthropic.ts","../src/models/ollama.ts","../src/models/factory.ts","../src/cli/repl.ts","../src/memory/session.ts","../src/skills/loader.ts","../src/index.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { loadConfig } from \"./config.js\";\nimport { createProvider, parseModelString } from \"../models/factory.js\";\nimport { startREPL } from \"./repl.js\";\n\nexport function createProgram(): Command {\n const program = new Command();\n\n program\n .name(\"hecode\")\n .description(\"Hecode — Your AI Coding Assistant CLI\")\n .version(\"0.1.0\")\n .option(\"-m, --model <model>\", \"Model to use (e.g. openai:gpt-4o, claude:sonnet)\")\n .option(\"-s, --skill <skill>\", \"Skill to activate\")\n .argument(\"[prompt...]\", \"Single-shot prompt (non-interactive)\")\n .action(async (prompt: string[], opts: { model?: string; skill?: string }) => {\n const config = await loadConfig();\n const modelStr = opts.model ?? config.defaultModel;\n const { provider, model } = parseModelString(modelStr);\n const modelConfig = config.models[provider] ?? {};\n if (model) modelConfig.model = model;\n const modelProvider = createProvider(provider, modelConfig as Record<string, unknown>);\n\n if (prompt.length) {\n const { Orchestrator } = await import(\"../core/orchestrator.js\");\n const orch = new Orchestrator({ model: modelProvider });\n const result = await orch.run(prompt.join(\" \"));\n console.log(result);\n } else {\n await startREPL(modelProvider, { skillName: opts.skill });\n }\n });\n\n program\n .command(\"config\")\n .description(\"Show or edit configuration\")\n .action(async () => {\n const config = await loadConfig();\n console.log(JSON.stringify(config, null, 2));\n });\n\n return program;\n}\n","import { readFile, mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { Config } from \"../core/types.js\";\n\nconst CONFIG_DIR = join(homedir(), \".hecode\");\nconst CONFIG_FILE = join(CONFIG_DIR, \"config.json\");\n\nexport async function loadConfig(): Promise<Config> {\n try {\n const raw = await readFile(CONFIG_FILE, \"utf-8\");\n return JSON.parse(raw);\n } catch {\n return { defaultModel: \"openai:gpt-4o\", models: {} };\n }\n}\n\nexport async function saveConfig(config: Config): Promise<void> {\n await mkdir(CONFIG_DIR, { recursive: true });\n await writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), \"utf-8\");\n}\n","import OpenAI from \"openai\";\nimport type { ModelProvider, Message, Tool, Response, Chunk } from \"../core/types.js\";\n\nexport class OpenAIProvider implements ModelProvider {\n name = \"openai\";\n private client: OpenAI;\n private model: string;\n\n constructor(config: { apiKey?: string; baseUrl?: string; model?: string }) {\n this.client = new OpenAI({\n apiKey: config.apiKey ?? process.env.OPENAI_API_KEY,\n baseURL: config.baseUrl,\n });\n this.model = config.model ?? \"gpt-4o\";\n }\n\n async chat(messages: Message[], tools?: Tool[]): Promise<Response> {\n const params: OpenAI.ChatCompletionCreateParams = {\n model: this.model,\n messages: this.convertMessages(messages),\n ...(tools?.length && { tools: this.convertTools(tools) }),\n };\n const completion = await this.client.chat.completions.create(params);\n const choice = completion.choices[0]!;\n return {\n content: choice.message.content ?? \"\",\n tool_calls: choice.message.tool_calls\n ?.filter((tc) => tc.type === \"function\")\n .map((tc) => ({\n id: tc.id,\n type: \"function\" as const,\n function: { name: tc.function.name, arguments: tc.function.arguments },\n })),\n usage: completion.usage\n ? { prompt: completion.usage.prompt_tokens, completion: completion.usage.completion_tokens }\n : undefined,\n };\n }\n\n async *stream(messages: Message[], tools?: Tool[]): AsyncIterable<Chunk> {\n const stream = await this.client.chat.completions.create({\n model: this.model,\n messages: this.convertMessages(messages),\n stream: true,\n ...(tools?.length && { tools: this.convertTools(tools) }),\n });\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n if (!delta) continue;\n yield {\n content: delta.content ?? undefined,\n tool_calls: delta.tool_calls?.map((tc) => ({\n id: tc.id ?? \"\",\n type: \"function\" as const,\n function: { name: tc.function?.name ?? \"\", arguments: tc.function?.arguments ?? \"\" },\n })),\n done: chunk.choices[0]?.finish_reason != null,\n };\n }\n }\n\n private convertMessages(messages: Message[]): OpenAI.ChatCompletionMessageParam[] {\n return messages.map((m) => {\n if (m.role === \"tool\") {\n return { role: \"tool\" as const, content: m.content, tool_call_id: m.tool_call_id! };\n }\n if (m.role === \"assistant\" && m.tool_calls?.length) {\n return {\n role: \"assistant\" as const,\n content: m.content,\n tool_calls: m.tool_calls.map((tc) => ({\n id: tc.id,\n type: \"function\" as const,\n function: tc.function,\n })),\n };\n }\n return { role: m.role as \"system\" | \"user\" | \"assistant\", content: m.content };\n });\n }\n\n private convertTools(tools: Tool[]): OpenAI.ChatCompletionTool[] {\n return tools.map((t) => ({\n type: \"function\" as const,\n function: { name: t.name, description: t.description, parameters: t.parameters },\n }));\n }\n}\n","import Anthropic from \"@anthropic-ai/sdk\";\nimport type { ModelProvider, Message, Tool, Response, Chunk } from \"../core/types.js\";\n\nexport class AnthropicProvider implements ModelProvider {\n name = \"anthropic\";\n private client: Anthropic;\n private model: string;\n\n constructor(config: { apiKey?: string; model?: string }) {\n this.client = new Anthropic({ apiKey: config.apiKey ?? process.env.ANTHROPIC_API_KEY });\n this.model = config.model ?? \"claude-sonnet-4-20250514\";\n }\n\n async chat(messages: Message[], tools?: Tool[]): Promise<Response> {\n const system = messages.find((m) => m.role === \"system\")?.content ?? \"\";\n const convMessages = messages.filter((m) => m.role !== \"system\");\n const params: Anthropic.MessageCreateParams = {\n model: this.model,\n max_tokens: 8192,\n system,\n messages: this.convertMessages(convMessages),\n ...(tools?.length && { tools: this.convertTools(tools) }),\n };\n const msg = await this.client.messages.create(params);\n const textBlock = msg.content.find((b) => b.type === \"text\");\n const toolBlocks = msg.content.filter((b) => b.type === \"tool_use\");\n return {\n content: textBlock?.text ?? \"\",\n tool_calls: toolBlocks.map((tb) => ({\n id: tb.id,\n type: \"function\" as const,\n function: { name: tb.name, arguments: JSON.stringify(tb.input) },\n })),\n usage: { prompt: msg.usage.input_tokens, completion: msg.usage.output_tokens },\n };\n }\n\n async *stream(messages: Message[], tools?: Tool[]): AsyncIterable<Chunk> {\n const system = messages.find((m) => m.role === \"system\")?.content ?? \"\";\n const convMessages = messages.filter((m) => m.role !== \"system\");\n const stream = this.client.messages.stream({\n model: this.model,\n max_tokens: 8192,\n system,\n messages: this.convertMessages(convMessages),\n ...(tools?.length && { tools: this.convertTools(tools) }),\n });\n for await (const event of stream) {\n if (event.type === \"content_block_delta\" && event.delta.type === \"text_delta\") {\n yield { content: event.delta.text, done: false };\n }\n }\n yield { content: undefined, done: true };\n }\n\n private convertMessages(messages: Message[]): Anthropic.MessageParam[] {\n return messages.map((m) => ({\n role: m.role === \"assistant\" ? \"assistant\" : \"user\",\n content: m.content,\n }));\n }\n\n private convertTools(tools: Tool[]): Anthropic.Tool[] {\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: t.parameters as Anthropic.Tool[\"input_schema\"],\n }));\n }\n}\n","import type { ModelProvider, Message, Tool, Response, Chunk } from \"../core/types.js\";\n\nexport class OllamaProvider implements ModelProvider {\n name = \"ollama\";\n private baseUrl: string;\n private model: string;\n\n constructor(config: { baseUrl?: string; model?: string }) {\n this.baseUrl = config.baseUrl ?? \"http://localhost:11434\";\n this.model = config.model ?? \"llama3.1\";\n }\n\n async chat(messages: Message[], tools?: Tool[]): Promise<Response> {\n const res = await fetch(`${this.baseUrl}/api/chat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n model: this.model,\n messages: messages.map((m) => ({ role: m.role, content: m.content })),\n stream: false,\n ...(tools?.length && { tools: this.convertTools(tools) }),\n }),\n });\n const data = (await res.json()) as any;\n return {\n content: data.message?.content ?? \"\",\n tool_calls: data.message?.tool_calls?.map((tc: any, i: number) => ({\n id: `call_${i}`,\n type: \"function\" as const,\n function: {\n name: tc.function?.name ?? \"\",\n arguments: JSON.stringify(tc.function?.arguments ?? {}),\n },\n })),\n };\n }\n\n async *stream(messages: Message[], tools?: Tool[]): AsyncIterable<Chunk> {\n const res = await fetch(`${this.baseUrl}/api/chat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n model: this.model,\n messages: messages.map((m) => ({ role: m.role, content: m.content })),\n stream: true,\n ...(tools?.length && { tools: this.convertTools(tools) }),\n }),\n });\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop()!;\n for (const line of lines) {\n if (!line.trim()) continue;\n const data = JSON.parse(line);\n yield {\n content: data.message?.content ?? undefined,\n done: data.done ?? false,\n };\n }\n }\n yield { done: true };\n }\n\n private convertTools(tools: Tool[]) {\n return tools.map((t) => ({\n type: \"function\",\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n },\n }));\n }\n}\n","import type { ModelProvider } from \"../core/types.js\";\nimport { OpenAIProvider } from \"./openai.js\";\nimport { AnthropicProvider } from \"./anthropic.js\";\nimport { OllamaProvider } from \"./ollama.js\";\n\ntype ProviderFactory = (config: Record<string, unknown>) => ModelProvider;\n\nconst registry = new Map<string, ProviderFactory>();\n\nregistry.set(\"openai\", (c) => new OpenAIProvider(c as any));\nregistry.set(\"claude\", (c) => new AnthropicProvider(c as any));\nregistry.set(\"anthropic\", (c) => new AnthropicProvider(c as any));\nregistry.set(\"ollama\", (c) => new OllamaProvider(c as any));\n\nexport function registerProvider(name: string, factory: ProviderFactory) {\n registry.set(name, factory);\n}\n\nexport function createProvider(name: string, config: Record<string, unknown>): ModelProvider {\n const factory = registry.get(name);\n if (!factory)\n throw new Error(\n `Unknown model provider: ${name}. Available: ${[...registry.keys()].join(\", \")}`,\n );\n return factory(config);\n}\n\nexport function parseModelString(modelStr: string): { provider: string; model: string } {\n const [provider, ...rest] = modelStr.split(\":\");\n return { provider: provider!, model: rest.join(\":\") || \"\" };\n}\n","import * as readline from \"node:readline\";\nimport chalk from \"chalk\";\nimport { join } from \"node:path\";\nimport { Orchestrator } from \"../core/orchestrator.js\";\nimport { SessionMemory } from \"../memory/session.js\";\nimport { loadSkills, matchSkill } from \"../skills/loader.js\";\nimport type { ModelProvider, ToolResult } from \"../core/types.js\";\n\nexport async function startREPL(\n model: ModelProvider,\n opts?: { skillName?: string },\n): Promise<void> {\n const session = new SessionMemory();\n const skillsDir = join(process.cwd(), \"skills\");\n const skills = await loadSkills(skillsDir);\n\n let skillInstructions: string | undefined;\n if (opts?.skillName) {\n const skill = skills.find((s) => s.name === opts.skillName);\n if (skill) skillInstructions = skill.instructions;\n }\n\n const orchestrator = new Orchestrator({\n model,\n skillInstructions,\n onToolStart: (name) => console.log(chalk.yellow(` ⚙ ${name}...`)),\n onToolEnd: (_name, result: ToolResult) => {\n if (result.error) console.log(chalk.red(` ✗ ${_name}: ${result.error}`));\n else console.log(chalk.green(` ✓ ${_name}`));\n },\n });\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n prompt: chalk.cyan(\"hecode> \"),\n });\n\n const logo = chalk.cyan(`\n ██╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ███████╗\n ██║ ██║██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔════╝\n ███████║█████╗ ██║ ██║ ██║██║ ██║█████╗ \n ██╔══██║██╔══╝ ██║ ██║ ██║██║ ██║██╔══╝ \n ██║ ██║███████╗╚██████╗╚██████╔╝██████╔╝███████╗\n ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝\n `);\n\n console.log(logo);\n console.log(chalk.bold.white(\" Your AI Coding Assistant\") + chalk.gray(\" v0.2.0\"));\n console.log(chalk.gray(\" ─────────────────────────────────────────────\"));\n console.log(chalk.gray(` Session: ${session.sessionId}`));\n if (skills.length) {\n console.log(chalk.gray(` Skills: ${skills.map((s) => s.name).join(\", \")}`));\n }\n console.log(chalk.gray(\" ─────────────────────────────────────────────\"));\n console.log(chalk.gray(\" Type /help for commands, Ctrl+C to exit\\n\"));\n rl.prompt();\n\n rl.on(\"line\", async (line) => {\n const input = line.trim();\n if (!input) {\n rl.prompt();\n return;\n }\n\n if (input.startsWith(\"/\")) {\n handleCommand(input, orchestrator, session);\n rl.prompt();\n return;\n }\n\n // Auto-match skill if not already set\n if (!skillInstructions) {\n const matched = matchSkill(skills, input);\n if (matched) {\n console.log(chalk.gray(` [skill: ${matched.name}]`));\n }\n }\n\n try {\n process.stdout.write(chalk.white(\"\\n\"));\n for await (const token of orchestrator.runStream(input)) {\n process.stdout.write(token);\n }\n process.stdout.write(\"\\n\\n\");\n\n // Auto-save session after each exchange\n await session.save(orchestrator.getMessages());\n } catch (e: any) {\n console.log(chalk.red(`\\nError: ${e.message}\\n`));\n }\n\n rl.prompt();\n });\n\n rl.on(\"close\", () => {\n console.log(chalk.gray(\"\\nGoodbye!\"));\n process.exit(0);\n });\n}\n\nfunction handleCommand(\n input: string,\n orchestrator: Orchestrator,\n session: SessionMemory,\n): void {\n const cmd = input.split(\" \")[0];\n switch (cmd) {\n case \"/help\":\n console.log(\n chalk.cyan(`\n /help — Show this help\n /clear — Clear conversation\n /history — Show message count\n /save — Save session manually\n /session — Show session ID\n /exit — Exit Hecode\n `),\n );\n break;\n case \"/clear\":\n orchestrator.clearMessages();\n console.log(chalk.gray(\"Conversation cleared.\"));\n break;\n case \"/history\":\n console.log(chalk.gray(`Messages: ${orchestrator.getMessages().length}`));\n break;\n case \"/save\":\n session.save(orchestrator.getMessages()).then(() => {\n console.log(chalk.gray(\"Session saved.\"));\n });\n break;\n case \"/session\":\n console.log(chalk.gray(`Session ID: ${session.sessionId}`));\n break;\n case \"/exit\":\n process.exit(0);\n default:\n console.log(chalk.red(`Unknown command: ${cmd}`));\n }\n}\n","import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { randomUUID } from \"node:crypto\";\nimport type { Message } from \"../core/types.js\";\n\nconst SESSIONS_DIR = join(homedir(), \".hecode\", \"sessions\");\n\nexport interface Session {\n id: string;\n messages: Message[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport class SessionMemory {\n private sessionDir: string;\n\n constructor(sessionId?: string) {\n const id = sessionId ?? randomUUID().slice(0, 12);\n this.sessionDir = join(SESSIONS_DIR, id);\n }\n\n get sessionId(): string {\n return this.sessionDir.split(/[\\\\/]/).pop()!;\n }\n\n async save(messages: Message[]): Promise<void> {\n await mkdir(this.sessionDir, { recursive: true });\n const session: Session = {\n id: this.sessionId,\n messages,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n await writeFile(\n join(this.sessionDir, \"session.json\"),\n JSON.stringify(session, null, 2),\n );\n }\n\n async load(): Promise<Message[]> {\n try {\n const raw = await readFile(\n join(this.sessionDir, \"session.json\"),\n \"utf-8\",\n );\n const session: Session = JSON.parse(raw);\n return session.messages;\n } catch {\n return [];\n }\n }\n\n async saveCheckpoint(data: Record<string, unknown>): Promise<void> {\n await mkdir(this.sessionDir, { recursive: true });\n await writeFile(\n join(this.sessionDir, \"checkpoint.md\"),\n JSON.stringify(data, null, 2),\n );\n }\n\n async saveNote(content: string): Promise<void> {\n await mkdir(this.sessionDir, { recursive: true });\n const notePath = join(this.sessionDir, \"notes.md\");\n let existing = \"\";\n try {\n existing = await readFile(notePath, \"utf-8\");\n } catch {}\n await writeFile(notePath, existing + \"\\n\\n\" + content);\n }\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface Skill {\n name: string;\n description: string;\n trigger: string;\n instructions: string;\n tools?: string[];\n}\n\nexport async function loadSkills(skillsDir: string): Promise<Skill[]> {\n const skills: Skill[] = [];\n try {\n const entries = await readdir(skillsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const skillPath = join(skillsDir, entry.name, \"SKILL.md\");\n try {\n const content = await readFile(skillPath, \"utf-8\");\n const skill = parseSkill(entry.name, content);\n if (skill) skills.push(skill);\n } catch {\n /* no SKILL.md, skip */\n }\n }\n } catch {\n /* skills dir doesn't exist */\n }\n return skills;\n}\n\nfunction parseSkill(name: string, content: string): Skill | null {\n const descMatch = content.match(/^#\\s+(.+)$/m);\n const triggerMatch = content.match(/trigger:\\s*(.+)/i);\n if (!descMatch) return null;\n\n return {\n name,\n description: descMatch[1] ?? name,\n trigger: triggerMatch?.[1] ?? \"\",\n instructions: content,\n };\n}\n\nexport function matchSkill(skills: Skill[], userMessage: string): Skill | null {\n const lower = userMessage.toLowerCase();\n for (const skill of skills) {\n if (skill.trigger) {\n const triggers = skill.trigger.split(\",\").map((t) => t.trim().toLowerCase());\n for (const t of triggers) {\n if (lower.includes(t)) return skill;\n }\n }\n }\n return null;\n}\n","#!/usr/bin/env node\nimport { createProgram } from \"./cli/commands.js\";\n\nconst program = createProgram();\nprogram.parse();\n"],"mappings":"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","names":["join","readFile","writeFile","mkdir","join","homedir","readFile","join","join","program","Orchestrator"]}
|
package/package.json
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhanngning/hecode",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"hecode": "./dist/index.js"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
9
|
"dist",
|
|
10
|
-
"README.md"
|
|
10
|
+
"README.md",
|
|
11
|
+
"skills"
|
|
11
12
|
],
|
|
12
13
|
"scripts": {
|
|
13
14
|
"build": "tsup",
|
|
14
15
|
"dev": "tsx src/index.ts",
|
|
15
16
|
"test": "vitest run",
|
|
16
|
-
"lint": "tsc --noEmit"
|
|
17
|
+
"lint": "tsc --noEmit",
|
|
18
|
+
"finance": "python src/datasources/akshare_datasource.py"
|
|
17
19
|
},
|
|
18
20
|
"engines": {
|
|
19
21
|
"node": ">=20.0.0"
|
|
@@ -31,5 +33,20 @@
|
|
|
31
33
|
"chalk": "^5.6.2",
|
|
32
34
|
"commander": "^15.0.0",
|
|
33
35
|
"openai": "^6.45.0"
|
|
36
|
+
},
|
|
37
|
+
"optionalDependencies": {
|
|
38
|
+
"akshare": ">=1.18.0"
|
|
39
|
+
},
|
|
40
|
+
"description": "Your AI Coding Assistant CLI with financial analysis capabilities",
|
|
41
|
+
"keywords": [
|
|
42
|
+
"ai",
|
|
43
|
+
"cli",
|
|
44
|
+
"coding",
|
|
45
|
+
"financial-analysis",
|
|
46
|
+
"stock"
|
|
47
|
+
],
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "https://github.com/zhanngning/hecode"
|
|
34
51
|
}
|
|
35
52
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Coding Assistant
|
|
2
|
+
|
|
3
|
+
trigger: code, fix, debug, refactor, implement, write, create, build, test
|
|
4
|
+
|
|
5
|
+
You are a skilled software engineer. Follow these principles:
|
|
6
|
+
- Write clean, minimal code
|
|
7
|
+
- Follow existing project conventions
|
|
8
|
+
- Run tests to verify changes
|
|
9
|
+
- Be concise in explanations
|
|
10
|
+
- Use tools to read files before editing them
|
|
11
|
+
- Verify builds pass after changes
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# 金融分析技能
|
|
2
|
+
|
|
3
|
+
trigger: finance, 金融, 股票分析, 财务分析, 研究报告, 股票, 股价
|
|
4
|
+
|
|
5
|
+
## 功能
|
|
6
|
+
|
|
7
|
+
分析上市公司财务数据,生成研究报告。
|
|
8
|
+
|
|
9
|
+
## 使用方法
|
|
10
|
+
|
|
11
|
+
用户可以说:
|
|
12
|
+
- "分析贵州茅台"
|
|
13
|
+
- "生成腾讯的研究报告"
|
|
14
|
+
- "分析股票 600519"
|
|
15
|
+
- "查看比亚迪股价"
|
|
16
|
+
|
|
17
|
+
## 工具
|
|
18
|
+
|
|
19
|
+
使用 `finance_analyze` 工具,参数:
|
|
20
|
+
- company: 公司名称
|
|
21
|
+
- code: 股票代码
|
|
22
|
+
- market: 市场(A股/HK)
|
|
23
|
+
|
|
24
|
+
## 输出
|
|
25
|
+
|
|
26
|
+
生成包含以下内容的报告:
|
|
27
|
+
1. 公司概况(股票代码、市场、行业)
|
|
28
|
+
2. 价格信息(当前价格、涨跌幅、成交量)
|
|
29
|
+
3. 技术分析(均线、RSI、趋势信号)
|
|
30
|
+
4. 近期走势
|
|
31
|
+
5. 投资建议
|
|
32
|
+
|
|
33
|
+
## 数据源
|
|
34
|
+
|
|
35
|
+
使用 akshare 获取免费金融数据:
|
|
36
|
+
- A股数据:沪深交易所
|
|
37
|
+
- 港股数据:港交所
|
|
38
|
+
|
|
39
|
+
## 示例
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
用户: 分析贵州茅台
|
|
43
|
+
助手: 我来分析贵州茅台的财务数据...
|
|
44
|
+
[调用 finance_analyze 工具,参数: { company: "贵州茅台", code: "600519", market: "A" }]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## 注意事项
|
|
48
|
+
|
|
49
|
+
- 数据仅供参考,不构成投资建议
|
|
50
|
+
- 数据来源为免费公开数据
|
|
51
|
+
- 历史数据最近30天
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tools/read_file.ts","../src/tools/write_file.ts","../src/tools/edit_file.ts","../src/tools/bash.ts","../src/tools/glob.ts","../src/tools/grep.ts","../src/tools/index.ts","../src/core/orchestrator.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport type { Tool, ToolResult } from \"../core/types.js\";\n\nexport const readFileTool: Tool = {\n name: \"read_file\",\n description: \"Read file content. Supports offset and limit for large files.\",\n parameters: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\", description: \"Absolute path to the file\" },\n offset: { type: \"number\", description: \"Line number to start from (1-indexed)\" },\n limit: { type: \"number\", description: \"Max lines to read (default 2000)\" },\n },\n required: [\"file_path\"],\n },\n async execute(params): Promise<ToolResult> {\n try {\n const content = await readFile(params.file_path as string, \"utf-8\");\n const lines = content.split(\"\\n\");\n const offset = (params.offset as number) || 1;\n const limit = (params.limit as number) || 2000;\n const sliced = lines.slice(offset - 1, offset - 1 + limit);\n const numbered = sliced.map((line, i) => `${offset + i}: ${line}`).join(\"\\n\");\n return { output: numbered };\n } catch (e: any) {\n return { output: \"\", error: e.message };\n }\n },\n};\n","import { writeFile, mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { Tool, ToolResult } from \"../core/types.js\";\n\nexport const writeFileTool: Tool = {\n name: \"write_file\",\n description: \"Write content to a file. Creates parent directories if needed.\",\n parameters: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\", description: \"Absolute path to the file\" },\n content: { type: \"string\", description: \"Content to write\" },\n },\n required: [\"file_path\", \"content\"],\n },\n async execute(params): Promise<ToolResult> {\n try {\n await mkdir(dirname(params.file_path as string), { recursive: true });\n await writeFile(params.file_path as string, params.content as string, \"utf-8\");\n return { output: `File written: ${params.file_path}` };\n } catch (e: any) {\n return { output: \"\", error: e.message };\n }\n },\n};\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport type { Tool, ToolResult } from \"../core/types.js\";\n\nexport const editFileTool: Tool = {\n name: \"edit_file\",\n description:\n \"Replace exact string match in a file. Fails if old_string not found or matches multiple times.\",\n parameters: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\", description: \"Absolute path to the file\" },\n old_string: { type: \"string\", description: \"Exact string to replace\" },\n new_string: { type: \"string\", description: \"Replacement string\" },\n replace_all: { type: \"boolean\", description: \"Replace all occurrences (default false)\" },\n },\n required: [\"file_path\", \"old_string\", \"new_string\"],\n },\n async execute(params): Promise<ToolResult> {\n try {\n const content = await readFile(params.file_path as string, \"utf-8\");\n const oldStr = params.old_string as string;\n const newStr = params.new_string as string;\n const replaceAll = params.replace_all as boolean;\n\n if (!content.includes(oldStr)) {\n return { output: \"\", error: `old_string not found in ${params.file_path}` };\n }\n\n let result: string;\n if (replaceAll) {\n result = content.replaceAll(oldStr, newStr);\n } else {\n const count = content.split(oldStr).length - 1;\n if (count > 1) {\n return {\n output: \"\",\n error: `Found ${count} matches for old_string. Provide more context or set replace_all=true.`,\n };\n }\n result = content.replace(oldStr, newStr);\n }\n\n await writeFile(params.file_path as string, result, \"utf-8\");\n return { output: `Edited: ${params.file_path}` };\n } catch (e: any) {\n return { output: \"\", error: e.message };\n }\n },\n};\n","import { exec } from \"node:child_process\";\nimport type { Tool, ToolResult } from \"../core/types.js\";\n\nexport const bashTool: Tool = {\n name: \"bash\",\n description: \"Execute a shell command. Returns stdout and stderr.\",\n parameters: {\n type: \"object\",\n properties: {\n command: { type: \"string\", description: \"The command to execute\" },\n timeout: { type: \"number\", description: \"Timeout in ms (default 120000)\" },\n workdir: { type: \"string\", description: \"Working directory\" },\n },\n required: [\"command\"],\n },\n async execute(params): Promise<ToolResult> {\n return new Promise((resolve) => {\n const timeout = (params.timeout as number) || 120_000;\n exec(\n params.command as string,\n {\n timeout,\n cwd: (params.workdir as string) || process.cwd(),\n encoding: \"utf-8\",\n },\n (error, stdout, stderr) => {\n if (error && error.killed) {\n resolve({\n output: stdout ?? \"\",\n error: `Command timed out after ${timeout}ms`,\n });\n } else if (error && !stdout && !stderr) {\n resolve({ output: \"\", error: error.message });\n } else {\n resolve({ output: [stdout, stderr].filter(Boolean).join(\"\\n\").trim() });\n }\n },\n );\n });\n },\n};\n","import { glob } from \"node:fs/promises\";\nimport type { Tool, ToolResult } from \"../core/types.js\";\n\nexport const globTool: Tool = {\n name: \"glob\",\n description: \"Find files matching a glob pattern.\",\n parameters: {\n type: \"object\",\n properties: {\n pattern: {\n type: \"string\",\n description: \"Glob pattern (e.g. '**/*.ts', 'src/**/*.test.*')\",\n },\n path: { type: \"string\", description: \"Directory to search in (default: cwd)\" },\n },\n required: [\"pattern\"],\n },\n async execute(params): Promise<ToolResult> {\n try {\n const files: string[] = [];\n for await (const f of glob(params.pattern as string, {\n cwd: (params.path as string) || process.cwd(),\n })) {\n files.push(f);\n }\n files.sort();\n return { output: files.join(\"\\n\") || \"No files found\" };\n } catch (e: any) {\n return { output: \"\", error: e.message };\n }\n },\n};\n","import { readFile, readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { Tool, ToolResult } from \"../core/types.js\";\n\nexport const grepTool: Tool = {\n name: \"grep\",\n description:\n \"Search file contents using regex. Returns file paths and matching line numbers.\",\n parameters: {\n type: \"object\",\n properties: {\n pattern: { type: \"string\", description: \"Regex pattern to search for\" },\n path: { type: \"string\", description: \"Directory to search in (default: cwd)\" },\n include: { type: \"string\", description: \"File pattern to include (e.g. '*.ts')\" },\n },\n required: [\"pattern\"],\n },\n async execute(params): Promise<ToolResult> {\n try {\n const regex = new RegExp(params.pattern as string, \"gi\");\n const rootDir = (params.path as string) || process.cwd();\n const includePattern = params.include as string | undefined;\n const results: string[] = [];\n\n async function searchDir(dir: string, depth: number) {\n if (depth > 10 || results.length >= 200) return;\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n await searchDir(fullPath, depth + 1);\n } else if (entry.isFile()) {\n if (includePattern && !matchGlob(entry.name, includePattern)) continue;\n try {\n const content = await readFile(fullPath, \"utf-8\");\n const lines = content.split(\"\\n\");\n for (let i = 0; i < lines.length; i++) {\n if (regex.test(lines[i]!)) {\n results.push(`${fullPath}:${i + 1}: ${lines[i]!.trim()}`);\n if (results.length >= 200) return;\n }\n regex.lastIndex = 0;\n }\n } catch {\n /* skip binary/unreadable files */\n }\n }\n }\n }\n\n await searchDir(rootDir, 0);\n return { output: results.join(\"\\n\") || \"No matches found\" };\n } catch (e: any) {\n return { output: \"\", error: e.message };\n }\n },\n};\n\nfunction matchGlob(filename: string, pattern: string): boolean {\n const regexStr = \"^\" + pattern.replace(/\\*/g, \".*\").replace(/\\?/g, \".\") + \"$\";\n return new RegExp(regexStr, \"i\").test(filename);\n}\n","import type { Tool } from \"../core/types.js\";\nimport { readFileTool } from \"./read_file.js\";\nimport { writeFileTool } from \"./write_file.js\";\nimport { editFileTool } from \"./edit_file.js\";\nimport { bashTool } from \"./bash.js\";\nimport { globTool } from \"./glob.js\";\nimport { grepTool } from \"./grep.js\";\n\nexport const builtinTools: Tool[] = [\n readFileTool,\n writeFileTool,\n editFileTool,\n bashTool,\n globTool,\n grepTool,\n];\n\nexport function getToolsByNames(names: string[]): Tool[] {\n return builtinTools.filter((t) => names.includes(t.name));\n}\n\nexport { readFileTool } from \"./read_file.js\";\nexport { writeFileTool } from \"./write_file.js\";\nexport { editFileTool } from \"./edit_file.js\";\nexport { bashTool } from \"./bash.js\";\nexport { globTool } from \"./glob.js\";\nexport { grepTool } from \"./grep.js\";\n","import type { ModelProvider, Message, Tool, ToolCall, ToolResult } from \"./types.js\";\nimport { builtinTools } from \"../tools/index.js\";\n\nexport interface OrchestratorOptions {\n model: ModelProvider;\n systemPrompt?: string;\n skillInstructions?: string;\n tools?: Tool[];\n maxIterations?: number;\n onToken?: (token: string) => void;\n onToolStart?: (name: string, params: Record<string, unknown>) => void;\n onToolEnd?: (name: string, result: ToolResult) => void;\n}\n\nexport class Orchestrator {\n private messages: Message[] = [];\n private tools: Tool[];\n private model: ModelProvider;\n private systemPrompt: string;\n private maxIterations: number;\n private callbacks: Pick<\n OrchestratorOptions,\n \"onToken\" | \"onToolStart\" | \"onToolEnd\"\n >;\n\n constructor(opts: OrchestratorOptions) {\n this.model = opts.model;\n this.systemPrompt = opts.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;\n if (opts.skillInstructions) {\n this.systemPrompt += \"\\n\\n\" + opts.skillInstructions;\n }\n this.tools = opts.tools ?? builtinTools;\n this.maxIterations = opts.maxIterations ?? 20;\n this.callbacks = {\n onToken: opts.onToken,\n onToolStart: opts.onToolStart,\n onToolEnd: opts.onToolEnd,\n };\n\n if (this.systemPrompt) {\n this.messages.push({ role: \"system\", content: this.systemPrompt });\n }\n }\n\n async run(userMessage: string): Promise<string> {\n this.messages.push({ role: \"user\", content: userMessage });\n\n for (let i = 0; i < this.maxIterations; i++) {\n const response = await this.model.chat(this.messages, this.tools);\n\n if (response.content) {\n this.messages.push({\n role: \"assistant\",\n content: response.content,\n tool_calls: response.tool_calls,\n });\n }\n\n if (!response.tool_calls?.length) {\n return response.content;\n }\n\n for (const tc of response.tool_calls) {\n this.callbacks.onToolStart?.(\n tc.function.name,\n JSON.parse(tc.function.arguments),\n );\n const result = await this.executeTool(tc);\n this.callbacks.onToolEnd?.(tc.function.name, result);\n this.messages.push({\n role: \"tool\",\n content: result.error ? `Error: ${result.error}` : result.output,\n tool_call_id: tc.id,\n });\n }\n }\n\n return \"Max iterations reached.\";\n }\n\n async *runStream(userMessage: string): AsyncIterable<string> {\n this.messages.push({ role: \"user\", content: userMessage });\n\n for (let i = 0; i < this.maxIterations; i++) {\n let fullContent = \"\";\n let toolCalls: ToolCall[] = [];\n\n for await (const chunk of this.model.stream(this.messages, this.tools)) {\n if (chunk.content) {\n fullContent += chunk.content;\n yield chunk.content;\n }\n if (chunk.tool_calls) {\n toolCalls = chunk.tool_calls;\n }\n }\n\n if (!toolCalls.length) {\n this.messages.push({ role: \"assistant\", content: fullContent });\n return;\n }\n\n this.messages.push({\n role: \"assistant\",\n content: fullContent,\n tool_calls: toolCalls,\n });\n\n for (const tc of toolCalls) {\n this.callbacks.onToolStart?.(\n tc.function.name,\n JSON.parse(tc.function.arguments),\n );\n const result = await this.executeTool(tc);\n this.callbacks.onToolEnd?.(tc.function.name, result);\n this.messages.push({\n role: \"tool\",\n content: result.error ? `Error: ${result.error}` : result.output,\n tool_call_id: tc.id,\n });\n }\n }\n }\n\n private async executeTool(tc: ToolCall): Promise<ToolResult> {\n const tool = this.tools.find((t) => t.name === tc.function.name);\n if (!tool) return { output: \"\", error: `Unknown tool: ${tc.function.name}` };\n try {\n const params = JSON.parse(tc.function.arguments);\n return await tool.execute(params);\n } catch (e: any) {\n return { output: \"\", error: e.message };\n }\n }\n\n getMessages(): Message[] {\n return [...this.messages];\n }\n\n clearMessages(): void {\n this.messages = [];\n if (this.systemPrompt) {\n this.messages.push({ role: \"system\", content: this.systemPrompt });\n }\n }\n}\n\nconst DEFAULT_SYSTEM_PROMPT = `You are Hecode, an AI coding assistant. You help users with software engineering tasks using the tools available to you.\n\nKey principles:\n- Be concise and direct\n- Use tools to read/write files, execute commands, and search code\n- Verify your work by running tests or checks when possible\n- Follow existing code conventions in the project`;\n"],"mappings":"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","names":["readFile","writeFile","readFile"]}
|
|
File without changes
|