agent-ide 0.1.6 → 0.1.8
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/dist/core/analysis/complexity-analyzer.d.ts.map +1 -1
- package/dist/core/analysis/complexity-analyzer.js +3 -2
- package/dist/core/analysis/complexity-analyzer.js.map +1 -1
- package/dist/core/analysis/dead-code-detector.d.ts +34 -10
- package/dist/core/analysis/dead-code-detector.d.ts.map +1 -1
- package/dist/core/analysis/dead-code-detector.js +121 -82
- package/dist/core/analysis/dead-code-detector.js.map +1 -1
- package/dist/core/analysis/index.d.ts +1 -1
- package/dist/core/analysis/index.d.ts.map +1 -1
- package/dist/core/dependency/dependency-analyzer.d.ts.map +1 -1
- package/dist/core/dependency/dependency-analyzer.js +11 -4
- package/dist/core/dependency/dependency-analyzer.js.map +1 -1
- package/dist/core/indexing/index-engine.d.ts +9 -0
- package/dist/core/indexing/index-engine.d.ts.map +1 -1
- package/dist/core/indexing/index-engine.js +60 -1
- package/dist/core/indexing/index-engine.js.map +1 -1
- package/dist/core/move/import-resolver.d.ts +8 -0
- package/dist/core/move/import-resolver.d.ts.map +1 -1
- package/dist/core/move/import-resolver.js +62 -1
- package/dist/core/move/import-resolver.js.map +1 -1
- package/dist/core/move/move-service.d.ts +9 -0
- package/dist/core/move/move-service.d.ts.map +1 -1
- package/dist/core/move/move-service.js +105 -8
- package/dist/core/move/move-service.js.map +1 -1
- package/dist/core/move/types.d.ts +1 -1
- package/dist/core/move/types.d.ts.map +1 -1
- package/dist/core/refactor/extract-function.d.ts +26 -4
- package/dist/core/refactor/extract-function.d.ts.map +1 -1
- package/dist/core/refactor/extract-function.js +300 -48
- package/dist/core/refactor/extract-function.js.map +1 -1
- package/dist/core/rename/reference-updater.d.ts +10 -10
- package/dist/core/rename/reference-updater.d.ts.map +1 -1
- package/dist/core/rename/reference-updater.js +84 -79
- package/dist/core/rename/reference-updater.js.map +1 -1
- package/dist/core/rename/rename-engine.d.ts.map +1 -1
- package/dist/core/rename/rename-engine.js +68 -17
- package/dist/core/rename/rename-engine.js.map +1 -1
- package/dist/infrastructure/parser/base.d.ts +10 -0
- package/dist/infrastructure/parser/base.d.ts.map +1 -1
- package/dist/infrastructure/parser/base.js +39 -0
- package/dist/infrastructure/parser/base.js.map +1 -1
- package/dist/infrastructure/parser/interface.d.ts +12 -0
- package/dist/infrastructure/parser/interface.d.ts.map +1 -1
- package/dist/infrastructure/parser/interface.js +2 -0
- package/dist/infrastructure/parser/interface.js.map +1 -1
- package/dist/interfaces/cli/cli.d.ts +17 -1
- package/dist/interfaces/cli/cli.d.ts.map +1 -1
- package/dist/interfaces/cli/cli.js +220 -43
- package/dist/interfaces/cli/cli.js.map +1 -1
- package/dist/interfaces/cli/output-formatter.d.ts +55 -0
- package/dist/interfaces/cli/output-formatter.d.ts.map +1 -0
- package/dist/interfaces/cli/output-formatter.js +195 -0
- package/dist/interfaces/cli/output-formatter.js.map +1 -0
- package/dist/plugins/javascript/parser.d.ts +10 -0
- package/dist/plugins/javascript/parser.d.ts.map +1 -1
- package/dist/plugins/javascript/parser.js +62 -0
- package/dist/plugins/javascript/parser.js.map +1 -1
- package/dist/plugins/typescript/parser.d.ts +10 -0
- package/dist/plugins/typescript/parser.d.ts.map +1 -1
- package/dist/plugins/typescript/parser.js +59 -0
- package/dist/plugins/typescript/parser.js.map +1 -1
- package/package.json +8 -14
- package/dist/core/performance/analyzer.d.ts +0 -62
- package/dist/core/performance/analyzer.d.ts.map +0 -1
- package/dist/core/performance/analyzer.js +0 -378
- package/dist/core/performance/analyzer.js.map +0 -1
- package/dist/core/performance/cache-manager.d.ts +0 -161
- package/dist/core/performance/cache-manager.d.ts.map +0 -1
- package/dist/core/performance/cache-manager.js +0 -375
- package/dist/core/performance/cache-manager.js.map +0 -1
- package/dist/core/performance/index.d.ts +0 -14
- package/dist/core/performance/index.d.ts.map +0 -1
- package/dist/core/performance/index.js +0 -17
- package/dist/core/performance/index.js.map +0 -1
- package/dist/core/performance/interfaces.d.ts +0 -188
- package/dist/core/performance/interfaces.d.ts.map +0 -1
- package/dist/core/performance/interfaces.js +0 -17
- package/dist/core/performance/interfaces.js.map +0 -1
- package/dist/core/performance/memory-manager.d.ts +0 -176
- package/dist/core/performance/memory-manager.d.ts.map +0 -1
- package/dist/core/performance/memory-manager.js +0 -364
- package/dist/core/performance/memory-manager.js.map +0 -1
- package/dist/core/performance/monitor.d.ts +0 -92
- package/dist/core/performance/monitor.d.ts.map +0 -1
- package/dist/core/performance/monitor.js +0 -228
- package/dist/core/performance/monitor.js.map +0 -1
- package/dist/plugins/swift/index.d.ts +0 -11
- package/dist/plugins/swift/index.d.ts.map +0 -1
- package/dist/plugins/swift/index.js +0 -15
- package/dist/plugins/swift/index.js.map +0 -1
- package/dist/plugins/swift/parser.d.ts +0 -98
- package/dist/plugins/swift/parser.d.ts.map +0 -1
- package/dist/plugins/swift/parser.js +0 -612
- package/dist/plugins/swift/parser.js.map +0 -1
- package/dist/plugins/swift/types.d.ts +0 -196
- package/dist/plugins/swift/types.d.ts.map +0 -1
- package/dist/plugins/swift/types.js +0 -268
- package/dist/plugins/swift/types.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.js","sourceRoot":"","sources":["../../../src/infrastructure/parser/interface.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"interface.js","sourceRoot":"","sources":["../../../src/infrastructure/parser/interface.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6HH;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,GAAG,GAAG,KAAgC,CAAC;IAE7C,SAAS;IACT,IACE,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;QAC5B,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;QAC/B,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;QACvC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,EACtC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,eAAe;IACf,MAAM,eAAe,GAAG;QACtB,OAAO;QACP,gBAAgB;QAChB,gBAAgB;QAChB,qBAAqB;QACrB,QAAQ;QACR,iBAAiB;QACjB,gBAAgB;QAChB,YAAY;QACZ,UAAU;QACV,SAAS;KACV,CAAC;IAEF,KAAK,MAAM,MAAM,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC;YACtC,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,kBAAkB;IAClB,oDAAoD;IAEpD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAoB,EAAE,SAAiB;IACvE,OAAQ,MAAM,CAAC,mBAAgC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACtE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAoB,EAAE,QAAgB;IACrE,OAAQ,MAAM,CAAC,kBAA+B,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACpE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1C,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAuB,EACvB,QAAgB;IAEhB,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE7C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,iBAAiB,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC;YACzC,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -59,12 +59,28 @@ export declare class AgentIdeCLI {
|
|
|
59
59
|
*/
|
|
60
60
|
private fileExists;
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
62
|
+
* 正確套用程式碼編輯
|
|
63
|
+
*/
|
|
64
|
+
private applyEditCorrectly;
|
|
65
|
+
/**
|
|
66
|
+
* 將行列位置轉換為字元偏移量
|
|
67
|
+
*/
|
|
68
|
+
private positionToOffset;
|
|
69
|
+
/**
|
|
70
|
+
* @deprecated 使用 applyEditCorrectly 代替
|
|
63
71
|
*/
|
|
64
72
|
private applyCodeEdit;
|
|
65
73
|
/**
|
|
66
74
|
* 獲取專案中的所有檔案
|
|
67
75
|
*/
|
|
68
76
|
private getAllProjectFiles;
|
|
77
|
+
/**
|
|
78
|
+
* 讀取 tsconfig.json 的路徑別名設定
|
|
79
|
+
*/
|
|
80
|
+
private loadPathAliases;
|
|
81
|
+
/**
|
|
82
|
+
* 建立輸出格式化器
|
|
83
|
+
*/
|
|
84
|
+
private createFormatter;
|
|
69
85
|
}
|
|
70
86
|
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/interfaces/cli/cli.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/interfaces/cli/cli.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAiCH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,kBAAkB,CAAC,CAAqB;IAChD,OAAO,CAAC,YAAY,CAAC,CAAe;IACpC,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,aAAa,CAAC,CAAgB;;IAQtC;;OAEG;IACG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,OAAO,CAAC,iBAAiB;IAiDzB,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,kBAAkB;IAiB1B,OAAO,CAAC,oBAAoB;IAiB5B,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,kBAAkB;IAqB1B,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,mBAAmB;YAuBb,kBAAkB;YA2DlB,mBAAmB;YAuHnB,qBAAqB;YAuHrB,iBAAiB;YA2EjB,mBAAmB;IAoEjC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAwB1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAgD3B;;OAEG;IACH,OAAO,CAAC,cAAc;IAMtB;;OAEG;IACH,OAAO,CAAC,cAAc;YAYR,oBAAoB;YAiLpB,iBAAiB;IAsG/B;;OAEG;YACW,yBAAyB;YAgBzB,wBAAwB;YA2BxB,uBAAuB;IAqBrC;;OAEG;YACW,UAAU;IASxB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA4B1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;IACH,OAAO,CAAC,aAAa;IAarB;;OAEG;YACW,kBAAkB;IAkDhC;;OAEG;YACW,eAAe;IAgC7B;;OAEG;IACH,OAAO,CAAC,eAAe;CAqBxB"}
|
|
@@ -6,7 +6,6 @@ import { Command } from 'commander';
|
|
|
6
6
|
import { IndexEngine } from '../../core/indexing/index-engine.js';
|
|
7
7
|
import { DependencyAnalyzer } from '../../core/dependency/dependency-analyzer.js';
|
|
8
8
|
import { RenameEngine } from '../../core/rename/rename-engine.js';
|
|
9
|
-
import { ReferenceUpdater } from '../../core/rename/reference-updater.js';
|
|
10
9
|
import { MoveService } from '../../core/move/index.js';
|
|
11
10
|
import { SearchService } from '../../core/search/service.js';
|
|
12
11
|
import { createIndexConfig } from '../../core/indexing/types.js';
|
|
@@ -15,8 +14,23 @@ import { TypeScriptParser } from '../../plugins/typescript/parser.js';
|
|
|
15
14
|
import { JavaScriptParser } from '../../plugins/javascript/parser.js';
|
|
16
15
|
import { ComplexityAnalyzer } from '../../core/analysis/complexity-analyzer.js';
|
|
17
16
|
import { DeadCodeDetector } from '../../core/analysis/dead-code-detector.js';
|
|
17
|
+
import { OutputFormatter, OutputFormat } from './output-formatter.js';
|
|
18
18
|
import * as fs from 'fs/promises';
|
|
19
|
+
import { readFileSync } from 'fs';
|
|
19
20
|
import * as path from 'path';
|
|
21
|
+
import { fileURLToPath } from 'url';
|
|
22
|
+
// 讀取 package.json 版本
|
|
23
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
24
|
+
const __dirname = path.dirname(__filename);
|
|
25
|
+
const packageJsonPath = path.resolve(__dirname, '../../../package.json');
|
|
26
|
+
let packageVersion = '0.1.0'; // fallback
|
|
27
|
+
try {
|
|
28
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
29
|
+
packageVersion = packageJson.version;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// 使用 fallback 版本
|
|
33
|
+
}
|
|
20
34
|
export class AgentIdeCLI {
|
|
21
35
|
program;
|
|
22
36
|
indexEngine;
|
|
@@ -87,7 +101,7 @@ export class AgentIdeCLI {
|
|
|
87
101
|
this.program
|
|
88
102
|
.name('agent-ide')
|
|
89
103
|
.description('程式碼智能工具集 for AI Agents')
|
|
90
|
-
.version(
|
|
104
|
+
.version(packageVersion);
|
|
91
105
|
this.setupIndexCommand();
|
|
92
106
|
this.setupRenameCommand();
|
|
93
107
|
this.setupRefactorCommand();
|
|
@@ -105,6 +119,7 @@ export class AgentIdeCLI {
|
|
|
105
119
|
.option('-u, --update', '增量更新索引')
|
|
106
120
|
.option('-e, --extensions <exts>', '包含的檔案副檔名', '.ts,.js,.tsx,.jsx')
|
|
107
121
|
.option('-x, --exclude <patterns>', '排除模式', 'node_modules/**,*.test.*')
|
|
122
|
+
.option('--format <format>', '輸出格式 (markdown|plain|json|minimal)', 'plain')
|
|
108
123
|
.action(async (options) => {
|
|
109
124
|
await this.handleIndexCommand(options);
|
|
110
125
|
});
|
|
@@ -120,6 +135,7 @@ export class AgentIdeCLI {
|
|
|
120
135
|
.option('-o, --to <name>', '新名稱(--new-name 的別名)')
|
|
121
136
|
.option('-p, --path <path>', '檔案或目錄路徑', '.')
|
|
122
137
|
.option('--preview', '預覽變更而不執行')
|
|
138
|
+
.option('--format <format>', '輸出格式 (markdown|plain|json|minimal)', 'plain')
|
|
123
139
|
.action(async (options) => {
|
|
124
140
|
await this.handleRenameCommand(options);
|
|
125
141
|
});
|
|
@@ -132,8 +148,10 @@ export class AgentIdeCLI {
|
|
|
132
148
|
.option('-s, --start-line <line>', '起始行號')
|
|
133
149
|
.option('-e, --end-line <line>', '結束行號')
|
|
134
150
|
.option('-n, --function-name <name>', '函式名稱')
|
|
151
|
+
.option('-t, --target-file <file>', '目標檔案路徑(跨檔案提取)')
|
|
135
152
|
.option('-p, --path <path>', '專案路徑', '.')
|
|
136
153
|
.option('--preview', '預覽變更而不執行')
|
|
154
|
+
.option('--format <format>', '輸出格式 (markdown|plain|json|minimal)', 'plain')
|
|
137
155
|
.action(async (action, options) => {
|
|
138
156
|
await this.handleRefactorCommand(action, options);
|
|
139
157
|
});
|
|
@@ -146,6 +164,7 @@ export class AgentIdeCLI {
|
|
|
146
164
|
.argument('<target>', '目標路徑')
|
|
147
165
|
.option('--update-imports', '自動更新 import 路徑', true)
|
|
148
166
|
.option('--preview', '預覽變更而不執行')
|
|
167
|
+
.option('--format <format>', '輸出格式 (markdown|plain|json|minimal)', 'plain')
|
|
149
168
|
.action(async (source, target, options) => {
|
|
150
169
|
await this.handleMoveCommand(source, target, options);
|
|
151
170
|
});
|
|
@@ -214,7 +233,12 @@ export class AgentIdeCLI {
|
|
|
214
233
|
}
|
|
215
234
|
// Command handlers
|
|
216
235
|
async handleIndexCommand(options) {
|
|
217
|
-
|
|
236
|
+
const formatter = this.createFormatter(options.format);
|
|
237
|
+
const startTime = Date.now();
|
|
238
|
+
if (options.format !== 'json' && options.format !== 'minimal') {
|
|
239
|
+
console.log(formatter.formatTitle('程式碼索引', 1));
|
|
240
|
+
console.log('\n🔍 開始建立程式碼索引...\n');
|
|
241
|
+
}
|
|
218
242
|
try {
|
|
219
243
|
const config = createIndexConfig(options.path, {
|
|
220
244
|
includeExtensions: options.extensions.split(','),
|
|
@@ -222,18 +246,43 @@ export class AgentIdeCLI {
|
|
|
222
246
|
});
|
|
223
247
|
this.indexEngine = new IndexEngine(config);
|
|
224
248
|
if (options.update) {
|
|
225
|
-
|
|
226
|
-
|
|
249
|
+
if (options.format !== 'json' && options.format !== 'minimal') {
|
|
250
|
+
console.log('📝 執行增量索引更新...');
|
|
251
|
+
}
|
|
227
252
|
}
|
|
228
253
|
else {
|
|
229
254
|
await this.indexEngine.indexProject(options.path);
|
|
230
255
|
}
|
|
231
256
|
const stats = await this.indexEngine.getStats();
|
|
232
|
-
|
|
233
|
-
|
|
257
|
+
const duration = Date.now() - startTime;
|
|
258
|
+
const statsData = {
|
|
259
|
+
檔案數: stats.totalFiles,
|
|
260
|
+
符號數: stats.totalSymbols,
|
|
261
|
+
'執行時間(ms)': duration
|
|
262
|
+
};
|
|
263
|
+
if (options.format === 'json') {
|
|
264
|
+
console.log(formatter.formatSuccess('索引完成', statsData));
|
|
265
|
+
}
|
|
266
|
+
else if (options.format === 'minimal') {
|
|
267
|
+
console.log(`index:success files=${stats.totalFiles} symbols=${stats.totalSymbols} time=${duration}ms`);
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
console.log('\n' + formatter.formatSuccess('索引完成'));
|
|
271
|
+
console.log('\n' + formatter.formatTitle('統計資訊', 2));
|
|
272
|
+
console.log(formatter.formatStats(statsData));
|
|
273
|
+
}
|
|
234
274
|
}
|
|
235
275
|
catch (error) {
|
|
236
|
-
|
|
276
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
277
|
+
if (options.format === 'json') {
|
|
278
|
+
console.error(formatter.formatError(errorMessage));
|
|
279
|
+
}
|
|
280
|
+
else if (options.format === 'minimal') {
|
|
281
|
+
console.error(`index:error ${errorMessage}`);
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
console.error('\n' + formatter.formatError(`索引失敗: ${errorMessage}`));
|
|
285
|
+
}
|
|
237
286
|
if (process.env.NODE_ENV !== 'test') {
|
|
238
287
|
process.exit(1);
|
|
239
288
|
}
|
|
@@ -286,23 +335,12 @@ export class AgentIdeCLI {
|
|
|
286
335
|
if (options.preview) {
|
|
287
336
|
console.log('🔍 預覽變更...');
|
|
288
337
|
try {
|
|
289
|
-
//
|
|
290
|
-
|
|
291
|
-
if (targetSymbol.location && targetSymbol.location.filePath) {
|
|
292
|
-
filePaths = [targetSymbol.location.filePath];
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
// 如果沒有 location,使用所有已索引的檔案
|
|
296
|
-
const allFiles = this.indexEngine.getAllIndexedFiles();
|
|
297
|
-
filePaths = allFiles.map(f => f.filePath);
|
|
298
|
-
if (filePaths.length === 0) {
|
|
299
|
-
filePaths = [options.path || process.cwd()];
|
|
300
|
-
}
|
|
301
|
-
}
|
|
338
|
+
// 取得所有專案檔案以進行跨檔案引用查找
|
|
339
|
+
const allProjectFiles = await this.getAllProjectFiles(options.path || workspacePath);
|
|
302
340
|
const preview = await this.renameEngine.previewRename({
|
|
303
341
|
symbol: targetSymbol,
|
|
304
342
|
newName: to,
|
|
305
|
-
filePaths
|
|
343
|
+
filePaths: allProjectFiles
|
|
306
344
|
});
|
|
307
345
|
console.log('📝 預計變更:');
|
|
308
346
|
console.log(` 檔案數: ${preview.affectedFiles.length}`);
|
|
@@ -328,22 +366,24 @@ export class AgentIdeCLI {
|
|
|
328
366
|
}
|
|
329
367
|
// 3. 執行重新命名(處理跨檔案引用)
|
|
330
368
|
console.log('✏️ 執行重新命名...');
|
|
331
|
-
//
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
const
|
|
335
|
-
|
|
369
|
+
// 取得所有專案檔案(使用與 preview 相同的邏輯)
|
|
370
|
+
const allProjectFiles = await this.getAllProjectFiles(options.path || workspacePath);
|
|
371
|
+
// 使用 renameEngine 執行重新命名(與 preview 使用相同的引擎)
|
|
372
|
+
const renameResult = await this.renameEngine.rename({
|
|
373
|
+
symbol: targetSymbol,
|
|
374
|
+
newName: to,
|
|
375
|
+
filePaths: allProjectFiles
|
|
376
|
+
});
|
|
377
|
+
if (renameResult.success) {
|
|
336
378
|
console.log('✅ 重新命名成功!');
|
|
337
|
-
console.log(`📊 統計: ${
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
console.log(` ✓ ${file.filePath}: "${change.oldText}" → "${change.newText}"`);
|
|
341
|
-
});
|
|
379
|
+
console.log(`📊 統計: ${renameResult.affectedFiles.length} 檔案, ${renameResult.operations.length} 變更`);
|
|
380
|
+
renameResult.operations.forEach(operation => {
|
|
381
|
+
console.log(` ✓ ${operation.filePath}: "${operation.oldText}" → "${operation.newText}"`);
|
|
342
382
|
});
|
|
343
383
|
}
|
|
344
384
|
else {
|
|
345
385
|
console.error('❌ 重新命名失敗:');
|
|
346
|
-
|
|
386
|
+
renameResult.errors?.forEach(error => {
|
|
347
387
|
console.error(` - ${error}`);
|
|
348
388
|
});
|
|
349
389
|
if (process.env.NODE_ENV !== 'test') {
|
|
@@ -389,18 +429,31 @@ export class AgentIdeCLI {
|
|
|
389
429
|
const { FunctionExtractor } = await import('../../core/refactor/extract-function.js');
|
|
390
430
|
const extractor = new FunctionExtractor();
|
|
391
431
|
// 執行提取
|
|
392
|
-
const
|
|
432
|
+
const extractConfig = {
|
|
393
433
|
functionName: options.functionName,
|
|
394
434
|
generateComments: true,
|
|
395
435
|
preserveFormatting: true,
|
|
396
|
-
validateExtraction: true
|
|
397
|
-
|
|
436
|
+
validateExtraction: true,
|
|
437
|
+
...(options.targetFile ? {
|
|
438
|
+
targetFile: path.resolve(options.targetFile),
|
|
439
|
+
sourceFile: filePath
|
|
440
|
+
} : {})
|
|
441
|
+
};
|
|
442
|
+
const result = await extractor.extract(code, range, extractConfig);
|
|
398
443
|
if (result.success) {
|
|
399
|
-
//
|
|
444
|
+
// 套用編輯(按正確順序)
|
|
400
445
|
let modifiedCode = code;
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
446
|
+
// 先處理所有 insert 類型(在檔案開頭插入函式定義)
|
|
447
|
+
const insertEdits = result.edits.filter(e => e.type === 'insert');
|
|
448
|
+
const replaceEdits = result.edits.filter(e => e.type === 'replace');
|
|
449
|
+
// 先應用 replace(替換選取範圍為函式呼叫)
|
|
450
|
+
for (const edit of replaceEdits) {
|
|
451
|
+
modifiedCode = this.applyEditCorrectly(modifiedCode, edit);
|
|
452
|
+
}
|
|
453
|
+
// 再應用 insert(插入函式定義)
|
|
454
|
+
for (const edit of insertEdits) {
|
|
455
|
+
modifiedCode = this.applyEditCorrectly(modifiedCode, edit);
|
|
456
|
+
}
|
|
404
457
|
// 提取函式簽名(從修改後的程式碼中)
|
|
405
458
|
const functionSignatureMatch = modifiedCode.match(new RegExp(`(async\\s+)?function\\s+${result.functionName}\\s*\\([^)]*\\)`));
|
|
406
459
|
const functionSignature = functionSignatureMatch ? functionSignatureMatch[0] : `function ${result.functionName}`;
|
|
@@ -408,17 +461,35 @@ export class AgentIdeCLI {
|
|
|
408
461
|
console.log(`📝 提取的函式: ${functionSignature}`);
|
|
409
462
|
console.log(functionSignature);
|
|
410
463
|
if (!options.preview) {
|
|
411
|
-
//
|
|
464
|
+
// 寫入原始檔案
|
|
412
465
|
await fs.writeFile(filePath, modifiedCode, 'utf-8');
|
|
413
466
|
console.log(`✓ 已更新 ${filePath}`);
|
|
467
|
+
// 如果是跨檔案提取,寫入目標檔案
|
|
468
|
+
if (result.targetFileContent && options.targetFile) {
|
|
469
|
+
const targetPath = path.resolve(options.targetFile);
|
|
470
|
+
// 確保目標目錄存在
|
|
471
|
+
const targetDir = path.dirname(targetPath);
|
|
472
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
473
|
+
// 寫入目標檔案
|
|
474
|
+
await fs.writeFile(targetPath, result.targetFileContent, 'utf-8');
|
|
475
|
+
console.log(`✓ 已建立/更新目標檔案 ${targetPath}`);
|
|
476
|
+
if (result.importStatement) {
|
|
477
|
+
console.log(`✓ 已加入 import: ${result.importStatement}`);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
414
480
|
}
|
|
415
481
|
else {
|
|
416
482
|
console.log('\n🔍 預覽模式 - 未寫入檔案');
|
|
417
483
|
console.log(`📊 參數: ${result.parameters.map(p => p.name).join(', ')}`);
|
|
484
|
+
if (result.targetFileContent && options.targetFile) {
|
|
485
|
+
console.log(`📁 目標檔案: ${options.targetFile}`);
|
|
486
|
+
console.log(`📥 Import: ${result.importStatement || '(無)'}`);
|
|
487
|
+
}
|
|
418
488
|
}
|
|
419
489
|
}
|
|
420
490
|
else {
|
|
421
491
|
console.error('❌ 重構失敗:', result.errors.join(', '));
|
|
492
|
+
process.exitCode = 1;
|
|
422
493
|
if (process.env.NODE_ENV !== 'test') {
|
|
423
494
|
process.exit(1);
|
|
424
495
|
}
|
|
@@ -457,8 +528,10 @@ export class AgentIdeCLI {
|
|
|
457
528
|
}
|
|
458
529
|
// 初始化移動服務
|
|
459
530
|
if (!this.moveService) {
|
|
531
|
+
// 讀取 tsconfig.json 路徑別名
|
|
532
|
+
const pathAliases = await this.loadPathAliases(process.cwd());
|
|
460
533
|
this.moveService = new MoveService({
|
|
461
|
-
pathAliases
|
|
534
|
+
pathAliases,
|
|
462
535
|
supportedExtensions: ['.ts', '.tsx', '.js', '.jsx', '.vue'],
|
|
463
536
|
includeNodeModules: false
|
|
464
537
|
});
|
|
@@ -1004,7 +1077,43 @@ export class AgentIdeCLI {
|
|
|
1004
1077
|
}
|
|
1005
1078
|
}
|
|
1006
1079
|
/**
|
|
1007
|
-
*
|
|
1080
|
+
* 正確套用程式碼編輯
|
|
1081
|
+
*/
|
|
1082
|
+
applyEditCorrectly(code, edit) {
|
|
1083
|
+
const lines = code.split('\n');
|
|
1084
|
+
switch (edit.type) {
|
|
1085
|
+
case 'replace': {
|
|
1086
|
+
// 計算起始和結束位置的偏移量
|
|
1087
|
+
const startOffset = this.positionToOffset(lines, edit.range.start);
|
|
1088
|
+
const endOffset = this.positionToOffset(lines, edit.range.end);
|
|
1089
|
+
return code.substring(0, startOffset) + edit.newText + code.substring(endOffset);
|
|
1090
|
+
}
|
|
1091
|
+
case 'insert': {
|
|
1092
|
+
const offset = this.positionToOffset(lines, edit.range.start);
|
|
1093
|
+
return code.substring(0, offset) + edit.newText + code.substring(offset);
|
|
1094
|
+
}
|
|
1095
|
+
case 'delete': {
|
|
1096
|
+
const startOffset = this.positionToOffset(lines, edit.range.start);
|
|
1097
|
+
const endOffset = this.positionToOffset(lines, edit.range.end);
|
|
1098
|
+
return code.substring(0, startOffset) + code.substring(endOffset);
|
|
1099
|
+
}
|
|
1100
|
+
default:
|
|
1101
|
+
return code;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
/**
|
|
1105
|
+
* 將行列位置轉換為字元偏移量
|
|
1106
|
+
*/
|
|
1107
|
+
positionToOffset(lines, position) {
|
|
1108
|
+
let offset = 0;
|
|
1109
|
+
for (let i = 0; i < position.line - 1 && i < lines.length; i++) {
|
|
1110
|
+
offset += lines[i].length + 1; // +1 for newline
|
|
1111
|
+
}
|
|
1112
|
+
offset += position.column;
|
|
1113
|
+
return Math.min(offset, lines.join('\n').length);
|
|
1114
|
+
}
|
|
1115
|
+
/**
|
|
1116
|
+
* @deprecated 使用 applyEditCorrectly 代替
|
|
1008
1117
|
*/
|
|
1009
1118
|
applyCodeEdit(code, edit) {
|
|
1010
1119
|
const lines = code.split('\n');
|
|
@@ -1023,6 +1132,21 @@ export class AgentIdeCLI {
|
|
|
1023
1132
|
const files = [];
|
|
1024
1133
|
const allowedExtensions = ['.ts', '.tsx', '.js', '.jsx'];
|
|
1025
1134
|
const excludePatterns = ['node_modules', 'dist', '.git', 'coverage'];
|
|
1135
|
+
// 檢查路徑是檔案還是目錄
|
|
1136
|
+
try {
|
|
1137
|
+
const stats = await fs.stat(projectPath);
|
|
1138
|
+
if (stats.isFile()) {
|
|
1139
|
+
// 如果是單一檔案,直接返回
|
|
1140
|
+
if (allowedExtensions.some(ext => projectPath.endsWith(ext))) {
|
|
1141
|
+
return [projectPath];
|
|
1142
|
+
}
|
|
1143
|
+
return [];
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
catch (error) {
|
|
1147
|
+
// 路徑不存在
|
|
1148
|
+
return [];
|
|
1149
|
+
}
|
|
1026
1150
|
async function walkDir(dir) {
|
|
1027
1151
|
try {
|
|
1028
1152
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
@@ -1050,5 +1174,58 @@ export class AgentIdeCLI {
|
|
|
1050
1174
|
await walkDir(projectPath);
|
|
1051
1175
|
return files;
|
|
1052
1176
|
}
|
|
1177
|
+
/**
|
|
1178
|
+
* 讀取 tsconfig.json 的路徑別名設定
|
|
1179
|
+
*/
|
|
1180
|
+
async loadPathAliases(projectRoot) {
|
|
1181
|
+
const pathAliases = {};
|
|
1182
|
+
try {
|
|
1183
|
+
const tsconfigPath = path.join(projectRoot, 'tsconfig.json');
|
|
1184
|
+
const tsconfigContent = await fs.readFile(tsconfigPath, 'utf-8');
|
|
1185
|
+
const tsconfig = JSON.parse(tsconfigContent);
|
|
1186
|
+
if (tsconfig.compilerOptions?.paths) {
|
|
1187
|
+
const baseUrl = tsconfig.compilerOptions.baseUrl || '.';
|
|
1188
|
+
const basePath = path.resolve(projectRoot, baseUrl);
|
|
1189
|
+
for (const [alias, paths] of Object.entries(tsconfig.compilerOptions.paths)) {
|
|
1190
|
+
if (Array.isArray(paths) && paths.length > 0) {
|
|
1191
|
+
// 移除 /* 後綴
|
|
1192
|
+
const cleanAlias = alias.replace(/\/\*$/, '');
|
|
1193
|
+
const cleanPath = paths[0].replace(/\/\*$/, '');
|
|
1194
|
+
// 轉換為絕對路徑
|
|
1195
|
+
pathAliases[cleanAlias] = path.resolve(basePath, cleanPath);
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
catch (error) {
|
|
1201
|
+
// tsconfig.json 不存在或解析失敗,使用空的路徑別名
|
|
1202
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
1203
|
+
console.warn('⚠️ 無法讀取 tsconfig.json 路徑別名設定');
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
return pathAliases;
|
|
1207
|
+
}
|
|
1208
|
+
/**
|
|
1209
|
+
* 建立輸出格式化器
|
|
1210
|
+
*/
|
|
1211
|
+
createFormatter(format) {
|
|
1212
|
+
let outputFormat;
|
|
1213
|
+
switch (format?.toLowerCase()) {
|
|
1214
|
+
case 'markdown':
|
|
1215
|
+
outputFormat = OutputFormat.Markdown;
|
|
1216
|
+
break;
|
|
1217
|
+
case 'json':
|
|
1218
|
+
outputFormat = OutputFormat.Json;
|
|
1219
|
+
break;
|
|
1220
|
+
case 'minimal':
|
|
1221
|
+
outputFormat = OutputFormat.Minimal;
|
|
1222
|
+
break;
|
|
1223
|
+
case 'plain':
|
|
1224
|
+
default:
|
|
1225
|
+
outputFormat = OutputFormat.Plain;
|
|
1226
|
+
break;
|
|
1227
|
+
}
|
|
1228
|
+
return new OutputFormatter(outputFormat);
|
|
1229
|
+
}
|
|
1053
1230
|
}
|
|
1054
1231
|
//# sourceMappingURL=cli.js.map
|