codemate-ai 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -7
- package/dist/cli.js +179 -214
- package/package.json +20 -19
package/README.md
CHANGED
|
@@ -69,19 +69,18 @@ Base URL: https://api.deepseek.com
|
|
|
69
69
|
试试:codemate "创建一个 Hello World 程序"
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
###
|
|
72
|
+
### 基础使用
|
|
73
73
|
|
|
74
74
|
```bash
|
|
75
|
-
#
|
|
76
|
-
codemate "create a REST API with Express and TypeScript"
|
|
77
|
-
|
|
78
|
-
# Interactive mode
|
|
75
|
+
# 启动交互式模式
|
|
79
76
|
codemate
|
|
80
77
|
|
|
81
|
-
#
|
|
82
|
-
|
|
78
|
+
# 在交互界面中输入你的需求
|
|
79
|
+
> 创建一个 Express API 服务器
|
|
83
80
|
```
|
|
84
81
|
|
|
82
|
+
**注意**:当前版本仅支持交互式模式。一次性命令模式(如 `codemate "prompt"`)将在未来版本中支持。
|
|
83
|
+
|
|
85
84
|
## 📖 Usage Examples
|
|
86
85
|
|
|
87
86
|
### Create a New Project
|
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import path14__default from 'path';
|
|
2
|
+
import path from 'path';
|
|
4
3
|
import { fileURLToPath } from 'url';
|
|
5
4
|
import * as fs15 from 'fs';
|
|
6
5
|
import fs15__default from 'fs';
|
|
6
|
+
import * as path14 from 'pathe';
|
|
7
7
|
import 'dotenv/config';
|
|
8
8
|
import { Command } from 'commander';
|
|
9
9
|
import * as fs16 from 'fs/promises';
|
|
@@ -13,9 +13,9 @@ import { generateText, tool } from 'ai';
|
|
|
13
13
|
import { z } from 'zod';
|
|
14
14
|
import { exec, spawn } from 'child_process';
|
|
15
15
|
import { promisify } from 'util';
|
|
16
|
-
import * as readline from 'readline/promises';
|
|
17
16
|
import * as os from 'os';
|
|
18
17
|
import os__default from 'os';
|
|
18
|
+
import * as readline from 'readline/promises';
|
|
19
19
|
import express from 'express';
|
|
20
20
|
import { createServer } from 'http';
|
|
21
21
|
import { WebSocketServer as WebSocketServer$1, WebSocket } from 'ws';
|
|
@@ -53,7 +53,7 @@ var getFilename, getDirname, __dirname$1;
|
|
|
53
53
|
var init_esm_shims = __esm({
|
|
54
54
|
"../node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.56.0_@types+node@22.19.13__@swc+core@1.12.1_jiti@_8ad23c210f594f4b7beb5a64b2d0cb77/node_modules/tsup/assets/esm_shims.js"() {
|
|
55
55
|
getFilename = () => fileURLToPath(import.meta.url);
|
|
56
|
-
getDirname = () =>
|
|
56
|
+
getDirname = () => path.dirname(getFilename());
|
|
57
57
|
__dirname$1 = /* @__PURE__ */ getDirname();
|
|
58
58
|
}
|
|
59
59
|
});
|
|
@@ -1329,14 +1329,14 @@ var EditFileTool = class extends Tool {
|
|
|
1329
1329
|
regex: z.boolean().optional().describe("Use regex for matching")
|
|
1330
1330
|
});
|
|
1331
1331
|
async execute(input) {
|
|
1332
|
-
const { path:
|
|
1333
|
-
console.log(`\u270F\uFE0F Editing file: ${
|
|
1332
|
+
const { path: path19, oldContent, newContent, regex = false } = input;
|
|
1333
|
+
console.log(`\u270F\uFE0F Editing file: ${path19}`);
|
|
1334
1334
|
try {
|
|
1335
1335
|
if (this.container) {
|
|
1336
1336
|
const fileHistory = this.container.getFileHistory();
|
|
1337
1337
|
await fileHistory.trackFile(input.path);
|
|
1338
1338
|
}
|
|
1339
|
-
const content = await fs16.readFile(
|
|
1339
|
+
const content = await fs16.readFile(path19, "utf-8");
|
|
1340
1340
|
let newFileContent;
|
|
1341
1341
|
if (regex) {
|
|
1342
1342
|
const pattern = new RegExp(oldContent, "g");
|
|
@@ -1350,15 +1350,15 @@ var EditFileTool = class extends Tool {
|
|
|
1350
1350
|
message: "No changes made (old content not found)"
|
|
1351
1351
|
};
|
|
1352
1352
|
}
|
|
1353
|
-
await fs16.writeFile(
|
|
1353
|
+
await fs16.writeFile(path19, newFileContent, "utf-8");
|
|
1354
1354
|
console.log(`\u2705 File edited successfully`);
|
|
1355
1355
|
return {
|
|
1356
1356
|
success: true,
|
|
1357
|
-
message: `File edited: ${
|
|
1357
|
+
message: `File edited: ${path19}`,
|
|
1358
1358
|
changes: newFileContent.length - content.length
|
|
1359
1359
|
};
|
|
1360
1360
|
} catch (error) {
|
|
1361
|
-
console.error(`\u274C Failed to edit file: ${
|
|
1361
|
+
console.error(`\u274C Failed to edit file: ${path19}`, error);
|
|
1362
1362
|
if (error instanceof Error) {
|
|
1363
1363
|
throw new Error(`Failed to edit file: ${error.message}`);
|
|
1364
1364
|
}
|
|
@@ -1377,30 +1377,30 @@ var DeleteFileTool = class extends Tool {
|
|
|
1377
1377
|
recursive: z.boolean().optional().describe("Delete directory recursively")
|
|
1378
1378
|
});
|
|
1379
1379
|
async execute(input) {
|
|
1380
|
-
const { path:
|
|
1381
|
-
console.log(`\u{1F5D1}\uFE0F Deleting: ${
|
|
1380
|
+
const { path: path19, recursive = false } = input;
|
|
1381
|
+
console.log(`\u{1F5D1}\uFE0F Deleting: ${path19}`);
|
|
1382
1382
|
try {
|
|
1383
1383
|
if (this.container) {
|
|
1384
1384
|
const fileHistory = this.container.getFileHistory();
|
|
1385
1385
|
await fileHistory.trackFile(input.path);
|
|
1386
1386
|
}
|
|
1387
|
-
const stats = await fs16.stat(
|
|
1387
|
+
const stats = await fs16.stat(path19);
|
|
1388
1388
|
if (stats.isDirectory()) {
|
|
1389
1389
|
if (!recursive) {
|
|
1390
1390
|
throw new Error("Cannot delete directory without recursive flag");
|
|
1391
1391
|
}
|
|
1392
|
-
await fs16.rm(
|
|
1392
|
+
await fs16.rm(path19, { recursive: true, force: true });
|
|
1393
1393
|
} else {
|
|
1394
|
-
await fs16.unlink(
|
|
1394
|
+
await fs16.unlink(path19);
|
|
1395
1395
|
}
|
|
1396
1396
|
console.log(`\u2705 Deleted successfully`);
|
|
1397
1397
|
return {
|
|
1398
1398
|
success: true,
|
|
1399
|
-
message: `Deleted: ${
|
|
1399
|
+
message: `Deleted: ${path19}`,
|
|
1400
1400
|
type: stats.isDirectory() ? "directory" : "file"
|
|
1401
1401
|
};
|
|
1402
1402
|
} catch (error) {
|
|
1403
|
-
console.error(`\u274C Failed to delete: ${
|
|
1403
|
+
console.error(`\u274C Failed to delete: ${path19}`, error);
|
|
1404
1404
|
if (error instanceof Error) {
|
|
1405
1405
|
throw new Error(`Failed to delete: ${error.message}`);
|
|
1406
1406
|
}
|
|
@@ -1567,10 +1567,53 @@ var GlobTool = class extends Tool {
|
|
|
1567
1567
|
|
|
1568
1568
|
// src/tools/system/BashTool.ts
|
|
1569
1569
|
init_esm_shims();
|
|
1570
|
-
|
|
1570
|
+
|
|
1571
|
+
// src/utils/commandHelper.ts
|
|
1572
|
+
init_esm_shims();
|
|
1573
|
+
promisify(exec);
|
|
1574
|
+
function getShell() {
|
|
1575
|
+
const platform4 = os.platform();
|
|
1576
|
+
switch (platform4) {
|
|
1577
|
+
case "win32":
|
|
1578
|
+
return process.env.SHELL || "powershell.exe";
|
|
1579
|
+
case "darwin":
|
|
1580
|
+
case "linux":
|
|
1581
|
+
return process.env.SHELL || "/bin/bash";
|
|
1582
|
+
default:
|
|
1583
|
+
return "/bin/sh";
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
function adaptCommand(command) {
|
|
1587
|
+
const platform4 = os.platform();
|
|
1588
|
+
if (platform4 !== "win32") {
|
|
1589
|
+
return command;
|
|
1590
|
+
}
|
|
1591
|
+
const commandMap = {
|
|
1592
|
+
ls: "dir",
|
|
1593
|
+
"ls -la": "dir",
|
|
1594
|
+
"ls -l": "dir",
|
|
1595
|
+
cat: "type",
|
|
1596
|
+
rm: "del",
|
|
1597
|
+
"rm -rf": "rmdir /s /q",
|
|
1598
|
+
cp: "copy",
|
|
1599
|
+
mv: "move",
|
|
1600
|
+
pwd: "cd",
|
|
1601
|
+
clear: "cls",
|
|
1602
|
+
which: "where"
|
|
1603
|
+
};
|
|
1604
|
+
for (const [unixCmd, winCmd] of Object.entries(commandMap)) {
|
|
1605
|
+
if (command.startsWith(unixCmd)) {
|
|
1606
|
+
const adapted = command.replace(unixCmd, winCmd);
|
|
1607
|
+
console.log(` \u2139\uFE0F Adapted command for Windows: ${adapted}`);
|
|
1608
|
+
return adapted;
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
return command;
|
|
1612
|
+
}
|
|
1613
|
+
var execAsync2 = promisify(exec);
|
|
1571
1614
|
var BashTool = class extends Tool {
|
|
1572
1615
|
name = "bash";
|
|
1573
|
-
description = "Execute shell commands";
|
|
1616
|
+
description = "Execute shell commands (cross-platform)";
|
|
1574
1617
|
schema = z.object({
|
|
1575
1618
|
command: z.string().describe("Shell command to execute"),
|
|
1576
1619
|
cwd: z.string().optional().describe("Working directory")
|
|
@@ -1579,11 +1622,18 @@ var BashTool = class extends Tool {
|
|
|
1579
1622
|
const { command, cwd } = input;
|
|
1580
1623
|
console.log(`\u26A1 Executing: ${command}`);
|
|
1581
1624
|
try {
|
|
1582
|
-
const
|
|
1625
|
+
const shell = getShell();
|
|
1626
|
+
const adaptedCommand = adaptCommand(command);
|
|
1627
|
+
const { stdout, stderr } = await execAsync2(adaptedCommand, {
|
|
1628
|
+
cwd,
|
|
1629
|
+
shell
|
|
1630
|
+
// 指定 shell
|
|
1631
|
+
});
|
|
1583
1632
|
return {
|
|
1584
1633
|
success: true,
|
|
1585
1634
|
stdout: stdout.trim(),
|
|
1586
|
-
stderr: stderr.trim()
|
|
1635
|
+
stderr: stderr.trim(),
|
|
1636
|
+
platform: os.platform()
|
|
1587
1637
|
};
|
|
1588
1638
|
} catch (error) {
|
|
1589
1639
|
throw new Error(`Command failed: ${error.message}`);
|
|
@@ -1593,7 +1643,7 @@ var BashTool = class extends Tool {
|
|
|
1593
1643
|
|
|
1594
1644
|
// src/tools/system/ExecTool.ts
|
|
1595
1645
|
init_esm_shims();
|
|
1596
|
-
var
|
|
1646
|
+
var execAsync3 = promisify(exec);
|
|
1597
1647
|
var ExecTool = class extends Tool {
|
|
1598
1648
|
name = "exec";
|
|
1599
1649
|
description = "Execute a script file";
|
|
@@ -1608,7 +1658,7 @@ var ExecTool = class extends Tool {
|
|
|
1608
1658
|
try {
|
|
1609
1659
|
await fs16.access(scriptPath);
|
|
1610
1660
|
const command = `${scriptPath} ${args.join(" ")}`;
|
|
1611
|
-
const { stdout, stderr } = await
|
|
1661
|
+
const { stdout, stderr } = await execAsync3(command, { cwd });
|
|
1612
1662
|
console.log(`\u2705 Script executed successfully`);
|
|
1613
1663
|
return {
|
|
1614
1664
|
success: true,
|
|
@@ -3550,137 +3600,6 @@ var GeneralAgent = class extends Agent {
|
|
|
3550
3600
|
|
|
3551
3601
|
// src/server/HTTPServer.ts
|
|
3552
3602
|
init_esm_shims();
|
|
3553
|
-
|
|
3554
|
-
// node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.mjs
|
|
3555
|
-
init_esm_shims();
|
|
3556
|
-
|
|
3557
|
-
// node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs
|
|
3558
|
-
init_esm_shims();
|
|
3559
|
-
var _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
3560
|
-
function normalizeWindowsPath(input = "") {
|
|
3561
|
-
if (!input) {
|
|
3562
|
-
return input;
|
|
3563
|
-
}
|
|
3564
|
-
return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
|
3565
|
-
}
|
|
3566
|
-
var _UNC_REGEX = /^[/\\]{2}/;
|
|
3567
|
-
var _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
3568
|
-
var _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
|
|
3569
|
-
var normalize = function(path18) {
|
|
3570
|
-
if (path18.length === 0) {
|
|
3571
|
-
return ".";
|
|
3572
|
-
}
|
|
3573
|
-
path18 = normalizeWindowsPath(path18);
|
|
3574
|
-
const isUNCPath = path18.match(_UNC_REGEX);
|
|
3575
|
-
const isPathAbsolute = isAbsolute3(path18);
|
|
3576
|
-
const trailingSeparator = path18[path18.length - 1] === "/";
|
|
3577
|
-
path18 = normalizeString(path18, !isPathAbsolute);
|
|
3578
|
-
if (path18.length === 0) {
|
|
3579
|
-
if (isPathAbsolute) {
|
|
3580
|
-
return "/";
|
|
3581
|
-
}
|
|
3582
|
-
return trailingSeparator ? "./" : ".";
|
|
3583
|
-
}
|
|
3584
|
-
if (trailingSeparator) {
|
|
3585
|
-
path18 += "/";
|
|
3586
|
-
}
|
|
3587
|
-
if (_DRIVE_LETTER_RE.test(path18)) {
|
|
3588
|
-
path18 += "/";
|
|
3589
|
-
}
|
|
3590
|
-
if (isUNCPath) {
|
|
3591
|
-
if (!isPathAbsolute) {
|
|
3592
|
-
return `//./${path18}`;
|
|
3593
|
-
}
|
|
3594
|
-
return `//${path18}`;
|
|
3595
|
-
}
|
|
3596
|
-
return isPathAbsolute && !isAbsolute3(path18) ? `/${path18}` : path18;
|
|
3597
|
-
};
|
|
3598
|
-
var join10 = function(...segments) {
|
|
3599
|
-
let path18 = "";
|
|
3600
|
-
for (const seg of segments) {
|
|
3601
|
-
if (!seg) {
|
|
3602
|
-
continue;
|
|
3603
|
-
}
|
|
3604
|
-
if (path18.length > 0) {
|
|
3605
|
-
const pathTrailing = path18[path18.length - 1] === "/";
|
|
3606
|
-
const segLeading = seg[0] === "/";
|
|
3607
|
-
const both = pathTrailing && segLeading;
|
|
3608
|
-
if (both) {
|
|
3609
|
-
path18 += seg.slice(1);
|
|
3610
|
-
} else {
|
|
3611
|
-
path18 += pathTrailing || segLeading ? seg : `/${seg}`;
|
|
3612
|
-
}
|
|
3613
|
-
} else {
|
|
3614
|
-
path18 += seg;
|
|
3615
|
-
}
|
|
3616
|
-
}
|
|
3617
|
-
return normalize(path18);
|
|
3618
|
-
};
|
|
3619
|
-
function normalizeString(path18, allowAboveRoot) {
|
|
3620
|
-
let res = "";
|
|
3621
|
-
let lastSegmentLength = 0;
|
|
3622
|
-
let lastSlash = -1;
|
|
3623
|
-
let dots = 0;
|
|
3624
|
-
let char = null;
|
|
3625
|
-
for (let index = 0; index <= path18.length; ++index) {
|
|
3626
|
-
if (index < path18.length) {
|
|
3627
|
-
char = path18[index];
|
|
3628
|
-
} else if (char === "/") {
|
|
3629
|
-
break;
|
|
3630
|
-
} else {
|
|
3631
|
-
char = "/";
|
|
3632
|
-
}
|
|
3633
|
-
if (char === "/") {
|
|
3634
|
-
if (lastSlash === index - 1 || dots === 1) ;
|
|
3635
|
-
else if (dots === 2) {
|
|
3636
|
-
if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
|
|
3637
|
-
if (res.length > 2) {
|
|
3638
|
-
const lastSlashIndex = res.lastIndexOf("/");
|
|
3639
|
-
if (lastSlashIndex === -1) {
|
|
3640
|
-
res = "";
|
|
3641
|
-
lastSegmentLength = 0;
|
|
3642
|
-
} else {
|
|
3643
|
-
res = res.slice(0, lastSlashIndex);
|
|
3644
|
-
lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
|
|
3645
|
-
}
|
|
3646
|
-
lastSlash = index;
|
|
3647
|
-
dots = 0;
|
|
3648
|
-
continue;
|
|
3649
|
-
} else if (res.length > 0) {
|
|
3650
|
-
res = "";
|
|
3651
|
-
lastSegmentLength = 0;
|
|
3652
|
-
lastSlash = index;
|
|
3653
|
-
dots = 0;
|
|
3654
|
-
continue;
|
|
3655
|
-
}
|
|
3656
|
-
}
|
|
3657
|
-
if (allowAboveRoot) {
|
|
3658
|
-
res += res.length > 0 ? "/.." : "..";
|
|
3659
|
-
lastSegmentLength = 2;
|
|
3660
|
-
}
|
|
3661
|
-
} else {
|
|
3662
|
-
if (res.length > 0) {
|
|
3663
|
-
res += `/${path18.slice(lastSlash + 1, index)}`;
|
|
3664
|
-
} else {
|
|
3665
|
-
res = path18.slice(lastSlash + 1, index);
|
|
3666
|
-
}
|
|
3667
|
-
lastSegmentLength = index - lastSlash - 1;
|
|
3668
|
-
}
|
|
3669
|
-
lastSlash = index;
|
|
3670
|
-
dots = 0;
|
|
3671
|
-
} else if (char === "." && dots !== -1) {
|
|
3672
|
-
++dots;
|
|
3673
|
-
} else {
|
|
3674
|
-
dots = -1;
|
|
3675
|
-
}
|
|
3676
|
-
}
|
|
3677
|
-
return res;
|
|
3678
|
-
}
|
|
3679
|
-
var isAbsolute3 = function(p) {
|
|
3680
|
-
return _IS_ABSOLUTE_RE.test(p);
|
|
3681
|
-
};
|
|
3682
|
-
|
|
3683
|
-
// src/server/HTTPServer.ts
|
|
3684
3603
|
var HTTPServer = class {
|
|
3685
3604
|
app;
|
|
3686
3605
|
server = null;
|
|
@@ -3704,7 +3623,7 @@ var HTTPServer = class {
|
|
|
3704
3623
|
res.header("Access-Control-Allow-Headers", "Content-Type");
|
|
3705
3624
|
next();
|
|
3706
3625
|
});
|
|
3707
|
-
const webDir =
|
|
3626
|
+
const webDir = path14.join(__dirname$1, "../../web");
|
|
3708
3627
|
this.app.use(express.static(webDir));
|
|
3709
3628
|
}
|
|
3710
3629
|
/**
|
|
@@ -3716,7 +3635,7 @@ var HTTPServer = class {
|
|
|
3716
3635
|
});
|
|
3717
3636
|
this.app.use("/api", this.createAPIRouter());
|
|
3718
3637
|
this.app.get("*", (_req, res) => {
|
|
3719
|
-
const indexPath =
|
|
3638
|
+
const indexPath = path14.join(__dirname$1, "../../web/index.html");
|
|
3720
3639
|
res.sendFile(indexPath);
|
|
3721
3640
|
});
|
|
3722
3641
|
}
|
|
@@ -3910,11 +3829,11 @@ var HTTPServer = class {
|
|
|
3910
3829
|
* 启动服务器
|
|
3911
3830
|
*/
|
|
3912
3831
|
async start() {
|
|
3913
|
-
return new Promise((
|
|
3832
|
+
return new Promise((resolve7) => {
|
|
3914
3833
|
this.server = createServer(this.app);
|
|
3915
3834
|
this.server.listen(this.port, () => {
|
|
3916
3835
|
console.log(`\u{1F310} HTTP Server running at http://localhost:${this.port}`);
|
|
3917
|
-
|
|
3836
|
+
resolve7();
|
|
3918
3837
|
});
|
|
3919
3838
|
});
|
|
3920
3839
|
}
|
|
@@ -3922,9 +3841,9 @@ var HTTPServer = class {
|
|
|
3922
3841
|
* 停止服务器
|
|
3923
3842
|
*/
|
|
3924
3843
|
async stop() {
|
|
3925
|
-
return new Promise((
|
|
3844
|
+
return new Promise((resolve7, reject) => {
|
|
3926
3845
|
if (!this.server) {
|
|
3927
|
-
|
|
3846
|
+
resolve7();
|
|
3928
3847
|
return;
|
|
3929
3848
|
}
|
|
3930
3849
|
this.server.close((err) => {
|
|
@@ -3932,7 +3851,7 @@ var HTTPServer = class {
|
|
|
3932
3851
|
reject(err);
|
|
3933
3852
|
} else {
|
|
3934
3853
|
console.log("\u{1F310} HTTP Server stopped");
|
|
3935
|
-
|
|
3854
|
+
resolve7();
|
|
3936
3855
|
}
|
|
3937
3856
|
});
|
|
3938
3857
|
});
|
|
@@ -4155,60 +4074,60 @@ var CodeLocator = class {
|
|
|
4155
4074
|
let found = null;
|
|
4156
4075
|
traverseFunction(ast, {
|
|
4157
4076
|
// 查找函数
|
|
4158
|
-
FunctionDeclaration(
|
|
4159
|
-
if (type === "function" &&
|
|
4160
|
-
const parentPath =
|
|
4077
|
+
FunctionDeclaration(path19) {
|
|
4078
|
+
if (type === "function" && path19.node.id?.name === name) {
|
|
4079
|
+
const parentPath = path19.parentPath;
|
|
4161
4080
|
const isExported = parentPath && t.isExportNamedDeclaration(parentPath.node);
|
|
4162
4081
|
found = {
|
|
4163
4082
|
type: "function",
|
|
4164
4083
|
name,
|
|
4165
|
-
location: isExported ? getLocation(parentPath.node) : getLocation(
|
|
4166
|
-
code: isExported ? parentPath.toString() :
|
|
4084
|
+
location: isExported ? getLocation(parentPath.node) : getLocation(path19.node),
|
|
4085
|
+
code: isExported ? parentPath.toString() : path19.toString()
|
|
4167
4086
|
};
|
|
4168
|
-
|
|
4087
|
+
path19.stop();
|
|
4169
4088
|
}
|
|
4170
4089
|
},
|
|
4171
4090
|
// 查找类
|
|
4172
|
-
ClassDeclaration(
|
|
4173
|
-
if (type === "class" &&
|
|
4174
|
-
const parentPath =
|
|
4091
|
+
ClassDeclaration(path19) {
|
|
4092
|
+
if (type === "class" && path19.node.id?.name === name) {
|
|
4093
|
+
const parentPath = path19.parentPath;
|
|
4175
4094
|
const isExported = parentPath && t.isExportNamedDeclaration(parentPath.node);
|
|
4176
4095
|
found = {
|
|
4177
4096
|
type: "class",
|
|
4178
4097
|
name,
|
|
4179
|
-
location: isExported ? getLocation(parentPath.node) : getLocation(
|
|
4180
|
-
code: isExported ? parentPath.toString() :
|
|
4098
|
+
location: isExported ? getLocation(parentPath.node) : getLocation(path19.node),
|
|
4099
|
+
code: isExported ? parentPath.toString() : path19.toString()
|
|
4181
4100
|
};
|
|
4182
|
-
|
|
4101
|
+
path19.stop();
|
|
4183
4102
|
}
|
|
4184
4103
|
},
|
|
4185
4104
|
// 查找方法
|
|
4186
|
-
ClassMethod(
|
|
4105
|
+
ClassMethod(path19) {
|
|
4187
4106
|
if (type === "method") {
|
|
4188
|
-
const classPath =
|
|
4107
|
+
const classPath = path19.findParent((p) => p.isClassDeclaration());
|
|
4189
4108
|
const className = classPath && t.isClassDeclaration(classPath.node) ? classPath.node.id?.name : void 0;
|
|
4190
|
-
if (className === parent && t.isIdentifier(
|
|
4109
|
+
if (className === parent && t.isIdentifier(path19.node.key) && path19.node.key.name === name) {
|
|
4191
4110
|
found = {
|
|
4192
4111
|
type: "method",
|
|
4193
4112
|
name,
|
|
4194
|
-
location: getLocation(
|
|
4195
|
-
code:
|
|
4113
|
+
location: getLocation(path19.node),
|
|
4114
|
+
code: path19.toString(),
|
|
4196
4115
|
parent: className
|
|
4197
4116
|
};
|
|
4198
|
-
|
|
4117
|
+
path19.stop();
|
|
4199
4118
|
}
|
|
4200
4119
|
}
|
|
4201
4120
|
},
|
|
4202
4121
|
// 查找变量
|
|
4203
|
-
VariableDeclarator(
|
|
4204
|
-
if (type === "variable" && t.isIdentifier(
|
|
4122
|
+
VariableDeclarator(path19) {
|
|
4123
|
+
if (type === "variable" && t.isIdentifier(path19.node.id) && path19.node.id.name === name) {
|
|
4205
4124
|
found = {
|
|
4206
4125
|
type: "variable",
|
|
4207
4126
|
name,
|
|
4208
|
-
location: getLocation(
|
|
4209
|
-
code:
|
|
4127
|
+
location: getLocation(path19.node),
|
|
4128
|
+
code: path19.toString()
|
|
4210
4129
|
};
|
|
4211
|
-
|
|
4130
|
+
path19.stop();
|
|
4212
4131
|
}
|
|
4213
4132
|
}
|
|
4214
4133
|
});
|
|
@@ -4223,15 +4142,15 @@ var CodeLocator = class {
|
|
|
4223
4142
|
listFunctions(ast) {
|
|
4224
4143
|
const functions = [];
|
|
4225
4144
|
traverseFunction(ast, {
|
|
4226
|
-
FunctionDeclaration(
|
|
4227
|
-
if (
|
|
4228
|
-
const parentPath =
|
|
4145
|
+
FunctionDeclaration(path19) {
|
|
4146
|
+
if (path19.node.id) {
|
|
4147
|
+
const parentPath = path19.parentPath;
|
|
4229
4148
|
const isExported = parentPath && t.isExportNamedDeclaration(parentPath.node);
|
|
4230
4149
|
functions.push({
|
|
4231
4150
|
type: "function",
|
|
4232
|
-
name:
|
|
4233
|
-
location: isExported ? getLocation(parentPath.node) : getLocation(
|
|
4234
|
-
code: isExported ? parentPath.toString() :
|
|
4151
|
+
name: path19.node.id.name,
|
|
4152
|
+
location: isExported ? getLocation(parentPath.node) : getLocation(path19.node),
|
|
4153
|
+
code: isExported ? parentPath.toString() : path19.toString()
|
|
4235
4154
|
});
|
|
4236
4155
|
}
|
|
4237
4156
|
}
|
|
@@ -4247,15 +4166,15 @@ var CodeLocator = class {
|
|
|
4247
4166
|
listClasses(ast) {
|
|
4248
4167
|
const classes = [];
|
|
4249
4168
|
traverseFunction(ast, {
|
|
4250
|
-
ClassDeclaration(
|
|
4251
|
-
if (
|
|
4252
|
-
const parentPath =
|
|
4169
|
+
ClassDeclaration(path19) {
|
|
4170
|
+
if (path19.node.id) {
|
|
4171
|
+
const parentPath = path19.parentPath;
|
|
4253
4172
|
const isExported = parentPath && t.isExportNamedDeclaration(parentPath.node);
|
|
4254
4173
|
classes.push({
|
|
4255
4174
|
type: "class",
|
|
4256
|
-
name:
|
|
4257
|
-
location: isExported ? getLocation(parentPath.node) : getLocation(
|
|
4258
|
-
code: isExported ? parentPath.toString() :
|
|
4175
|
+
name: path19.node.id.name,
|
|
4176
|
+
location: isExported ? getLocation(parentPath.node) : getLocation(path19.node),
|
|
4177
|
+
code: isExported ? parentPath.toString() : path19.toString()
|
|
4259
4178
|
});
|
|
4260
4179
|
}
|
|
4261
4180
|
}
|
|
@@ -4480,8 +4399,8 @@ var MCPClient = class {
|
|
|
4480
4399
|
method,
|
|
4481
4400
|
params
|
|
4482
4401
|
};
|
|
4483
|
-
const promise = new Promise((
|
|
4484
|
-
this.pendingRequests.set(id, { resolve:
|
|
4402
|
+
const promise = new Promise((resolve7, reject) => {
|
|
4403
|
+
this.pendingRequests.set(id, { resolve: resolve7, reject });
|
|
4485
4404
|
setTimeout(() => {
|
|
4486
4405
|
if (this.pendingRequests.has(id)) {
|
|
4487
4406
|
this.pendingRequests.delete(id);
|
|
@@ -5316,7 +5235,7 @@ function isFirstRun() {
|
|
|
5316
5235
|
}
|
|
5317
5236
|
function getConfigPath() {
|
|
5318
5237
|
const homeDir = os__default.homedir();
|
|
5319
|
-
return
|
|
5238
|
+
return path14.join(homeDir, ".aiclirc.json");
|
|
5320
5239
|
}
|
|
5321
5240
|
function createDefaultConfig(apiKey, provider, model, baseURL) {
|
|
5322
5241
|
const defaultModels = {
|
|
@@ -5326,15 +5245,58 @@ function createDefaultConfig(apiKey, provider, model, baseURL) {
|
|
|
5326
5245
|
openrouter: "anthropic/claude-3.5-sonnet",
|
|
5327
5246
|
custom: "gpt-4"
|
|
5328
5247
|
};
|
|
5248
|
+
const defaultBaseURLs = {
|
|
5249
|
+
openai: void 0,
|
|
5250
|
+
anthropic: void 0,
|
|
5251
|
+
deepseek: "https://api.deepseek.com",
|
|
5252
|
+
openrouter: "https://openrouter.ai/api/v1",
|
|
5253
|
+
custom: void 0
|
|
5254
|
+
};
|
|
5329
5255
|
const config = {
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5256
|
+
app: {
|
|
5257
|
+
name: "codemate",
|
|
5258
|
+
version: "1.0.4",
|
|
5259
|
+
logLevel: "info",
|
|
5260
|
+
workDir: process.cwd()
|
|
5261
|
+
},
|
|
5262
|
+
model: {
|
|
5263
|
+
apiKey,
|
|
5264
|
+
baseURL: baseURL || defaultBaseURLs[provider] || "https://api.openai.com/v1",
|
|
5265
|
+
model: model || defaultModels[provider] || "gpt-4",
|
|
5266
|
+
temperature: 0.7
|
|
5267
|
+
},
|
|
5268
|
+
tools: {
|
|
5269
|
+
enabled: [
|
|
5270
|
+
"read_file",
|
|
5271
|
+
"write_file",
|
|
5272
|
+
"list_files",
|
|
5273
|
+
"edit_file",
|
|
5274
|
+
"delete_file",
|
|
5275
|
+
"grep",
|
|
5276
|
+
"glob",
|
|
5277
|
+
"bash"
|
|
5278
|
+
]
|
|
5279
|
+
},
|
|
5280
|
+
ui: {
|
|
5281
|
+
theme: "dark",
|
|
5282
|
+
showTimestamp: false
|
|
5283
|
+
},
|
|
5284
|
+
performance: {
|
|
5285
|
+
compression: {
|
|
5286
|
+
enabled: true,
|
|
5287
|
+
triggerRatio: 0.7,
|
|
5288
|
+
protectThreshold: 1e4,
|
|
5289
|
+
minimumPrune: 1e3,
|
|
5290
|
+
protectedTools: ["read_file", "list_files"],
|
|
5291
|
+
protectTurns: 2
|
|
5292
|
+
}
|
|
5293
|
+
},
|
|
5294
|
+
// 保存元数据用于参考
|
|
5295
|
+
_metadata: {
|
|
5296
|
+
provider,
|
|
5297
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5298
|
+
}
|
|
5334
5299
|
};
|
|
5335
|
-
if (baseURL) {
|
|
5336
|
-
config.baseURL = baseURL;
|
|
5337
|
-
}
|
|
5338
5300
|
const configPath = getConfigPath();
|
|
5339
5301
|
fs15__default.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
5340
5302
|
}
|
|
@@ -5421,23 +5383,26 @@ function getProviderKey(choice) {
|
|
|
5421
5383
|
}
|
|
5422
5384
|
}
|
|
5423
5385
|
function question(rl, query) {
|
|
5424
|
-
return new Promise((
|
|
5425
|
-
rl.question(query,
|
|
5386
|
+
return new Promise((resolve7) => {
|
|
5387
|
+
rl.question(query, resolve7);
|
|
5426
5388
|
});
|
|
5427
5389
|
}
|
|
5428
|
-
|
|
5429
|
-
// src/cli.ts
|
|
5430
5390
|
var program = new Command();
|
|
5431
|
-
program.name("codemate").description("AI-powered CLI assistant").version("1.0.
|
|
5391
|
+
program.name("codemate").description("AI-powered CLI assistant").version("1.0.5");
|
|
5392
|
+
if (os.platform() === "win32") {
|
|
5393
|
+
console.log("\u2139\uFE0F Windows \u7528\u6237\u63D0\u793A\uFF1A");
|
|
5394
|
+
console.log(" - \u5EFA\u8BAE\u5B89\u88C5 Git Bash \u4EE5\u83B7\u5F97\u66F4\u597D\u7684\u547D\u4EE4\u884C\u4F53\u9A8C");
|
|
5395
|
+
console.log(" - \u6216\u4F7F\u7528 WSL2 (Windows Subsystem for Linux)");
|
|
5396
|
+
console.log(" - \u90E8\u5206 Unix \u547D\u4EE4\u4F1A\u81EA\u52A8\u8F6C\u6362\u4E3A Windows \u547D\u4EE4\n");
|
|
5397
|
+
}
|
|
5432
5398
|
program.command("chat", { isDefault: true }).description("Start interactive chat mode").action(async () => {
|
|
5433
5399
|
try {
|
|
5434
5400
|
if (isFirstRun()) {
|
|
5435
5401
|
console.log("\n\u6B22\u8FCE\u4F7F\u7528 CodeMate AI! \u{1F389}\n");
|
|
5436
5402
|
console.log("\u68C0\u6D4B\u5230\u8FD9\u662F\u9996\u6B21\u8FD0\u884C\uFF0C\u9700\u8981\u8FDB\u884C\u521D\u59CB\u914D\u7F6E\u3002\n");
|
|
5437
5403
|
await runFirstTimeSetup();
|
|
5438
|
-
console.log("\n\u914D\u7F6E\u5B8C\u6210\uFF01\
|
|
5439
|
-
console.log(
|
|
5440
|
-
return;
|
|
5404
|
+
console.log("\n\u2705 \u914D\u7F6E\u5B8C\u6210\uFF01\n");
|
|
5405
|
+
console.log("\u73B0\u5728\u542F\u52A8\u4EA4\u4E92\u5F0F\u754C\u9762...\n");
|
|
5441
5406
|
}
|
|
5442
5407
|
const configService = new ConfigService();
|
|
5443
5408
|
const configPath = getConfigPath();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codemate-ai",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Enterprise-grade AI coding assistant CLI",
|
|
6
6
|
"main": "dist/cli.js",
|
|
@@ -23,24 +23,6 @@
|
|
|
23
23
|
"url": "https://github.com/your-org/aicli/issues"
|
|
24
24
|
},
|
|
25
25
|
"homepage": "https://github.com/your-org/aicli#readme",
|
|
26
|
-
"scripts": {
|
|
27
|
-
"dev": "tsx src/cli.ts",
|
|
28
|
-
"build": "tsup",
|
|
29
|
-
"test": "vitest run",
|
|
30
|
-
"test:watch": "vitest",
|
|
31
|
-
"test:ui": "vitest --ui",
|
|
32
|
-
"test:install": "./scripts/test-install.sh",
|
|
33
|
-
"typecheck": "tsc --noEmit",
|
|
34
|
-
"format": "biome format --write .",
|
|
35
|
-
"format:check": "biome format .",
|
|
36
|
-
"lint": "biome lint .",
|
|
37
|
-
"lint:fix": "biome lint --write .",
|
|
38
|
-
"ci": "npm run typecheck && npm run format:check && npm run test",
|
|
39
|
-
"ci:quick": "npm run typecheck && npm run format:check",
|
|
40
|
-
"prepublishOnly": "npm run ci:quick && npm run build",
|
|
41
|
-
"release": "./scripts/release.sh",
|
|
42
|
-
"test:local": "./scripts/test-local.sh"
|
|
43
|
-
},
|
|
44
26
|
"keywords": [
|
|
45
27
|
"ai",
|
|
46
28
|
"cli",
|
|
@@ -63,6 +45,7 @@
|
|
|
63
45
|
"ink-spinner": "^5.0.0",
|
|
64
46
|
"ink-text-input": "^6.0.0",
|
|
65
47
|
"openai": "^6.25.0",
|
|
48
|
+
"pathe": "^2.0.3",
|
|
66
49
|
"react": "^18.3.1",
|
|
67
50
|
"tsup": "^8.5.1",
|
|
68
51
|
"ws": "^8.19.0",
|
|
@@ -82,5 +65,23 @@
|
|
|
82
65
|
"tsx": "^4.19.2",
|
|
83
66
|
"typescript": "^5.7.2",
|
|
84
67
|
"vitest": "^3.0.4"
|
|
68
|
+
},
|
|
69
|
+
"scripts": {
|
|
70
|
+
"dev": "tsx src/cli.ts",
|
|
71
|
+
"build": "tsup",
|
|
72
|
+
"test": "vitest run",
|
|
73
|
+
"test:watch": "vitest",
|
|
74
|
+
"test:ui": "vitest --ui",
|
|
75
|
+
"test:install": "./scripts/test-install.sh",
|
|
76
|
+
"test:platform": "tsx scripts/test-platform.ts",
|
|
77
|
+
"typecheck": "tsc --noEmit",
|
|
78
|
+
"format": "biome format --write .",
|
|
79
|
+
"format:check": "biome format .",
|
|
80
|
+
"lint": "biome lint .",
|
|
81
|
+
"lint:fix": "biome lint --write .",
|
|
82
|
+
"ci": "npm run typecheck && npm run format:check && npm run test",
|
|
83
|
+
"ci:quick": "npm run typecheck && npm run format:check",
|
|
84
|
+
"release": "./scripts/release.sh",
|
|
85
|
+
"test:local": "./scripts/test-local.sh"
|
|
85
86
|
}
|
|
86
87
|
}
|