aico-cli 0.4.0 → 0.4.2
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/chunks/simple-config.mjs +41 -15
- package/dist/cli.mjs +35 -31
- package/package.json +4 -1
- package/templates/agents/aico/plan/function-point-analyzer.md +219 -0
- package/templates/agents/aico/requirement/test-crossplatform.ps1 +0 -0
- package/templates/agents/aico/requirement/test-crossplatform.sh +456 -0
- package/templates/commands/base//344/273/243/347/240/201/345/256/241/346/237/245/346/231/272/350/203/275/344/275/223.md +2 -5
- package/templates/commands/base//345/212/237/350/203/275/347/202/271/346/265/213/347/256/227.md +469 -19
- package/templates/skills/slack-gif-creator/LICENSE.txt +202 -0
- package/templates/skills/slack-gif-creator/SKILL.md +646 -0
- package/templates/skills/slack-gif-creator/core/color_palettes.py +302 -0
- package/templates/skills/slack-gif-creator/core/easing.py +230 -0
- package/templates/skills/slack-gif-creator/core/frame_composer.py +469 -0
- package/templates/skills/slack-gif-creator/core/gif_builder.py +246 -0
- package/templates/skills/slack-gif-creator/core/typography.py +357 -0
- package/templates/skills/slack-gif-creator/core/validators.py +264 -0
- package/templates/skills/slack-gif-creator/core/visual_effects.py +494 -0
- package/templates/skills/slack-gif-creator/requirements.txt +4 -0
- package/templates/skills/slack-gif-creator/templates/bounce.py +106 -0
- package/templates/skills/slack-gif-creator/templates/explode.py +331 -0
- package/templates/skills/slack-gif-creator/templates/fade.py +329 -0
- package/templates/skills/slack-gif-creator/templates/flip.py +291 -0
- package/templates/skills/slack-gif-creator/templates/kaleidoscope.py +211 -0
- package/templates/skills/slack-gif-creator/templates/morph.py +329 -0
- package/templates/skills/slack-gif-creator/templates/move.py +293 -0
- package/templates/skills/slack-gif-creator/templates/pulse.py +268 -0
- package/templates/skills/slack-gif-creator/templates/shake.py +127 -0
- package/templates/skills/slack-gif-creator/templates/slide.py +291 -0
- package/templates/skills/slack-gif-creator/templates/spin.py +269 -0
- package/templates/skills/slack-gif-creator/templates/wiggle.py +300 -0
- package/templates/skills/slack-gif-creator/templates/zoom.py +312 -0
- package/templates/skills/swimlane-diagram/README.md +373 -0
- package/templates/skills/swimlane-diagram/SKILL.md +242 -0
- package/templates/skills/swimlane-diagram/examples.md +405 -0
- package/templates/skills/swimlane-diagram/generators.mjs +258 -0
- package/templates/skills/swimlane-diagram/package.json +126 -0
- package/templates/skills/swimlane-diagram/reference.md +368 -0
- package/templates/skills/swimlane-diagram/swimlane-diagram.mjs +215 -0
- package/templates/skills/swimlane-diagram/swimlane-diagram.test.mjs +358 -0
- package/templates/skills/swimlane-diagram/validators.mjs +291 -0
- package/templates/skills/theme-factory/LICENSE.txt +202 -0
- package/templates/skills/theme-factory/SKILL.md +59 -0
- package/templates/skills/theme-factory/theme-showcase.pdf +0 -0
- package/templates/skills/theme-factory/themes/arctic-frost.md +19 -0
- package/templates/skills/theme-factory/themes/botanical-garden.md +19 -0
- package/templates/skills/theme-factory/themes/desert-rose.md +19 -0
- package/templates/skills/theme-factory/themes/forest-canopy.md +19 -0
- package/templates/skills/theme-factory/themes/golden-hour.md +19 -0
- package/templates/skills/theme-factory/themes/midnight-galaxy.md +19 -0
- package/templates/skills/theme-factory/themes/modern-minimalist.md +19 -0
- package/templates/skills/theme-factory/themes/ocean-depths.md +19 -0
- package/templates/skills/theme-factory/themes/sunset-boulevard.md +19 -0
- package/templates/skills/theme-factory/themes/tech-innovation.md +19 -0
- package/templates/code.md +0 -70
- package/templates/windows-bootstrap.ps1 +0 -390
|
@@ -13,7 +13,7 @@ import { join as join$1 } from 'node:path';
|
|
|
13
13
|
import { join, dirname, basename } from 'pathe';
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
|
|
16
|
-
const version = "0.4.
|
|
16
|
+
const version = "0.4.2";
|
|
17
17
|
|
|
18
18
|
function displayBanner(subtitle) {
|
|
19
19
|
const defaultSubtitle = "\u4E00\u952E\u914D\u7F6E\u4F60\u7684\u5F00\u53D1\u73AF\u5883";
|
|
@@ -4678,18 +4678,18 @@ const DEFAULT_FILE_COPY_CONFIGS = [
|
|
|
4678
4678
|
}
|
|
4679
4679
|
},
|
|
4680
4680
|
{
|
|
4681
|
-
source: "templates/
|
|
4682
|
-
destination: join(CLAUDE_DIR, "
|
|
4683
|
-
type: "
|
|
4681
|
+
source: "templates/skills",
|
|
4682
|
+
destination: join(CLAUDE_DIR, "skills"),
|
|
4683
|
+
type: "directory",
|
|
4684
4684
|
options: {
|
|
4685
|
-
mergeStrategy: "
|
|
4685
|
+
mergeStrategy: "copy",
|
|
4686
4686
|
backupBeforeCopy: true,
|
|
4687
4687
|
deleteBeforeCopy: true
|
|
4688
4688
|
}
|
|
4689
4689
|
},
|
|
4690
4690
|
{
|
|
4691
|
-
source: "templates/
|
|
4692
|
-
destination: join(CLAUDE_DIR, "
|
|
4691
|
+
source: "templates/personality.md",
|
|
4692
|
+
destination: join(CLAUDE_DIR, "personality.md"),
|
|
4693
4693
|
type: "file",
|
|
4694
4694
|
options: {
|
|
4695
4695
|
mergeStrategy: "merge",
|
|
@@ -4941,7 +4941,10 @@ class ConfigInstaller extends AbstractInstaller {
|
|
|
4941
4941
|
const settingsInstalled = existsSync(SETTINGS_FILE);
|
|
4942
4942
|
const personalityInstalled = existsSync(join(CLAUDE_DIR, "personality.md"));
|
|
4943
4943
|
const languageInstalled = existsSync(join(CLAUDE_DIR, "language.md"));
|
|
4944
|
-
|
|
4944
|
+
const skillsInstalled = existsSync(join(CLAUDE_DIR, "skills"));
|
|
4945
|
+
return {
|
|
4946
|
+
isInstalled: settingsInstalled && personalityInstalled && languageInstalled && skillsInstalled
|
|
4947
|
+
};
|
|
4945
4948
|
}
|
|
4946
4949
|
async install(options = {}) {
|
|
4947
4950
|
try {
|
|
@@ -5151,35 +5154,58 @@ class ConfigCheckerInstaller extends AbstractInstaller {
|
|
|
5151
5154
|
name = "Config Checker";
|
|
5152
5155
|
async checkStatus() {
|
|
5153
5156
|
const configType = await this.detectConfigType();
|
|
5157
|
+
const skillsInstalled = exists(join(CLAUDE_DIR, "skills"));
|
|
5154
5158
|
return {
|
|
5155
|
-
isInstalled: configType !== "none",
|
|
5159
|
+
isInstalled: configType !== "none" && skillsInstalled,
|
|
5156
5160
|
version: void 0
|
|
5157
5161
|
};
|
|
5158
5162
|
}
|
|
5159
5163
|
async install(options = {}) {
|
|
5160
5164
|
try {
|
|
5161
5165
|
const configType = await this.detectConfigType();
|
|
5162
|
-
|
|
5163
|
-
|
|
5166
|
+
const skillsInstalled = exists(join(CLAUDE_DIR, "skills"));
|
|
5167
|
+
if (configType !== "none" && skillsInstalled && !options.force) {
|
|
5168
|
+
this.log(`\u68C0\u6D4B\u5230 ${configType === "company" ? "\u516C\u53F8" : "\u4E2A\u4EBA"} \u914D\u7F6E\u4E14\u6280\u80FD\u76EE\u5F55\u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7\u914D\u7F6E`, "success");
|
|
5164
5169
|
return this.createSkipResult(
|
|
5165
|
-
`${configType === "company" ? "\u516C\u53F8" : "\u4E2A\u4EBA"} \u914D\u7F6E\u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7\u914D\u7F6E`,
|
|
5170
|
+
`${configType === "company" ? "\u516C\u53F8" : "\u4E2A\u4EBA"} \u914D\u7F6E\u548C\u6280\u80FD\u76EE\u5F55\u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7\u914D\u7F6E`,
|
|
5166
5171
|
"already_configured",
|
|
5167
|
-
{ configType }
|
|
5172
|
+
{ configType, skillsInstalled }
|
|
5168
5173
|
);
|
|
5169
5174
|
}
|
|
5170
5175
|
if (!options.silent) {
|
|
5171
5176
|
if (configType !== "none" && options.force) {
|
|
5172
5177
|
this.log(`\u5F3A\u5236\u8986\u76D6\u73B0\u6709${configType === "company" ? "\u516C\u53F8" : "\u4E2A\u4EBA"}\u914D\u7F6E...`, "info");
|
|
5178
|
+
} else if (!skillsInstalled) {
|
|
5179
|
+
this.log("\u68C0\u6D4B\u5230\u6280\u80FD\u76EE\u5F55\u672A\u5B89\u88C5\uFF0C\u5C06\u8FDB\u884C\u5B89\u88C5...", "info");
|
|
5173
5180
|
} else {
|
|
5174
5181
|
this.log("\u5F00\u59CB\u914D\u7F6E\u68C0\u67E5...", "info");
|
|
5175
5182
|
}
|
|
5176
5183
|
}
|
|
5177
5184
|
const operation = configType !== "none" && options.force ? "\u8986\u76D6\u68C0\u67E5" : "\u914D\u7F6E\u68C0\u67E5";
|
|
5178
|
-
|
|
5185
|
+
const skillsMessage = skillsInstalled ? "\u6280\u80FD\u76EE\u5F55\u5DF2\u5B58\u5728" : "\u6280\u80FD\u76EE\u5F55\u672A\u5B89\u88C5";
|
|
5186
|
+
return this.createSuccessResult(
|
|
5187
|
+
`\u914D\u7F6E\u68C0\u67E5\u5B8C\u6210\uFF0C${operation}\u6210\u529F\uFF0C${skillsMessage}`,
|
|
5188
|
+
void 0,
|
|
5189
|
+
{ configType, skillsInstalled }
|
|
5190
|
+
);
|
|
5179
5191
|
} catch (error) {
|
|
5180
5192
|
return this.handleError(error, "\u914D\u7F6E\u68C0\u67E5");
|
|
5181
5193
|
}
|
|
5182
5194
|
}
|
|
5195
|
+
/**
|
|
5196
|
+
* 检查版本一致性
|
|
5197
|
+
*/
|
|
5198
|
+
async checkVersionConsistency() {
|
|
5199
|
+
try {
|
|
5200
|
+
const aicoConfig = readAicoConfig();
|
|
5201
|
+
if (!aicoConfig) {
|
|
5202
|
+
return false;
|
|
5203
|
+
}
|
|
5204
|
+
return aicoConfig.version === version;
|
|
5205
|
+
} catch (error) {
|
|
5206
|
+
return false;
|
|
5207
|
+
}
|
|
5208
|
+
}
|
|
5183
5209
|
/**
|
|
5184
5210
|
* 检测配置类型
|
|
5185
5211
|
*/
|
|
@@ -5544,4 +5570,4 @@ async function openSettingsJson() {
|
|
|
5544
5570
|
}
|
|
5545
5571
|
}
|
|
5546
5572
|
|
|
5547
|
-
export { AICO_CONFIG_FILE as A, getMcpConfigPath as B, CLAUDE_DIR as C, DEFAULT_FILE_COPY_CONFIGS as D, readMcpConfig as E, writeMcpConfig as F, backupMcpConfig as G, mergeMcpServers as H, buildMcpServerConfig as I, fixWindowsMcpConfig as J, addCompletedOnboarding as K, LEGACY_AICO_CONFIG_FILE as L, MCP_SERVICES as M, createEscapablePrompt as N, displayBannerWithInfo as O, executeWithEscapeSupport as P, handleExitPromptError as Q, handleGeneralError as R, SETTINGS_FILE as S, EscapeKeyPressed as T, displayBanner as U, ConfigCheckerInstaller as V,
|
|
5573
|
+
export { AICO_CONFIG_FILE as A, getMcpConfigPath as B, CLAUDE_DIR as C, DEFAULT_FILE_COPY_CONFIGS as D, readMcpConfig as E, writeMcpConfig as F, backupMcpConfig as G, mergeMcpServers as H, buildMcpServerConfig as I, fixWindowsMcpConfig as J, addCompletedOnboarding as K, LEGACY_AICO_CONFIG_FILE as L, MCP_SERVICES as M, createEscapablePrompt as N, displayBannerWithInfo as O, executeWithEscapeSupport as P, handleExitPromptError as Q, handleGeneralError as R, SETTINGS_FILE as S, EscapeKeyPressed as T, displayBanner as U, ConfigCheckerInstaller as V, updateAicoConfig as W, version as X, InstallationComposer as Y, readAicoConfig as Z, init$1 as _, init as a, getPlatform as b, commandExists as c, importRecommendedEnv as d, importRecommendedPermissions as e, cleanupPermissions as f, getTermuxPrefix as g, mergeAndCleanPermissions as h, isTermux as i, CLAUDE_MD_FILE as j, ClAUDE_CONFIG_FILE as k, SUPPORTED_LANGS as l, messages as m, LANG_LABELS as n, openSettingsJson as o, AI_OUTPUT_LANGUAGES as p, ensureClaudeDir as q, backupExistingConfig as r, copyConfigFiles as s, copyConfigFilesWithConfig as t, configureApi as u, mergeConfigs as v, updateDefaultModel as w, mergeSettingsFile as x, getExistingApiConfig as y, applyAiLanguageDirective as z };
|
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import cac from 'cac';
|
|
3
3
|
import ansis from 'ansis';
|
|
4
|
-
import { N as createEscapablePrompt, O as displayBannerWithInfo, a as init, P as executeWithEscapeSupport, Q as handleExitPromptError, R as handleGeneralError, T as EscapeKeyPressed, U as displayBanner, V as ConfigCheckerInstaller, W as
|
|
4
|
+
import { N as createEscapablePrompt, O as displayBannerWithInfo, a as init, P as executeWithEscapeSupport, Q as handleExitPromptError, R as handleGeneralError, T as EscapeKeyPressed, U as displayBanner, V as ConfigCheckerInstaller, W as updateAicoConfig, X as version, Y as InstallationComposer, Z as readAicoConfig } from './chunks/simple-config.mjs';
|
|
5
5
|
import inquirer$1 from 'inquirer';
|
|
6
6
|
import { spawn, exec as exec$1 } from 'node:child_process';
|
|
7
7
|
import 'tinyexec';
|
|
@@ -356,9 +356,10 @@ async function update(options = {}) {
|
|
|
356
356
|
const configType = await checker.detectConfigType();
|
|
357
357
|
console.log(ansis.cyan(`\u{1F4CB} \u68C0\u6D4B\u5230\u914D\u7F6E\u7C7B\u578B: ${configType === "company" ? "\u516C\u53F8\u914D\u7F6E" : configType === "personal" ? "\u4E2A\u4EBA\u914D\u7F6E" : "\u65E0\u914D\u7F6E"}`));
|
|
358
358
|
await updateAicoCli();
|
|
359
|
+
updateAicoConfig({ version });
|
|
359
360
|
if (configType === "none") {
|
|
360
361
|
console.log(ansis.yellow("\n\u26A0\uFE0F \u672A\u68C0\u6D4B\u5230\u914D\u7F6E\uFF0C\u5C06\u6267\u884C\u521D\u59CB\u5316..."));
|
|
361
|
-
const { init } = await import('./chunks/simple-config.mjs').then(function (n) { return n.
|
|
362
|
+
const { init } = await import('./chunks/simple-config.mjs').then(function (n) { return n._; });
|
|
362
363
|
await init({
|
|
363
364
|
force: false,
|
|
364
365
|
skipBanner: true,
|
|
@@ -404,7 +405,7 @@ function setupCommands(cli) {
|
|
|
404
405
|
} else if (options.update) {
|
|
405
406
|
await update({});
|
|
406
407
|
} else if (options.company) {
|
|
407
|
-
const { init: init2 } = await import('./chunks/simple-config.mjs').then(function (n) { return n.
|
|
408
|
+
const { init: init2 } = await import('./chunks/simple-config.mjs').then(function (n) { return n._; });
|
|
408
409
|
await init2({
|
|
409
410
|
apiType: "auth_token",
|
|
410
411
|
force: options.force,
|
|
@@ -412,7 +413,7 @@ function setupCommands(cli) {
|
|
|
412
413
|
skipPrompt: true
|
|
413
414
|
});
|
|
414
415
|
} else if (options.personal) {
|
|
415
|
-
const { init: init2 } = await import('./chunks/simple-config.mjs').then(function (n) { return n.
|
|
416
|
+
const { init: init2 } = await import('./chunks/simple-config.mjs').then(function (n) { return n._; });
|
|
416
417
|
await init2({
|
|
417
418
|
apiType: "ccr_proxy",
|
|
418
419
|
force: options.force,
|
|
@@ -434,7 +435,7 @@ function setupCommands(cli) {
|
|
|
434
435
|
await update({});
|
|
435
436
|
});
|
|
436
437
|
cli.command("c", "\u5FEB\u901F\u914D\u7F6E\u516C\u53F8\u8BBE\u7F6E").action(async () => {
|
|
437
|
-
const { init: init2 } = await import('./chunks/simple-config.mjs').then(function (n) { return n.
|
|
438
|
+
const { init: init2 } = await import('./chunks/simple-config.mjs').then(function (n) { return n._; });
|
|
438
439
|
await init2({
|
|
439
440
|
apiType: "auth_token",
|
|
440
441
|
force: false,
|
|
@@ -443,7 +444,7 @@ function setupCommands(cli) {
|
|
|
443
444
|
});
|
|
444
445
|
});
|
|
445
446
|
cli.command("p", "\u5FEB\u901F\u914D\u7F6E\u4E2A\u4EBA\u8BBE\u7F6E").action(async () => {
|
|
446
|
-
const { init: init2 } = await import('./chunks/simple-config.mjs').then(function (n) { return n.
|
|
447
|
+
const { init: init2 } = await import('./chunks/simple-config.mjs').then(function (n) { return n._; });
|
|
447
448
|
await init2({
|
|
448
449
|
apiType: "ccr_proxy",
|
|
449
450
|
force: false,
|
|
@@ -468,31 +469,34 @@ async function startCodeEditor() {
|
|
|
468
469
|
const configType = await checker.detectConfigType();
|
|
469
470
|
const aicoConfig = readAicoConfig();
|
|
470
471
|
const needsReinstall = !aicoConfig || aicoConfig.version !== version;
|
|
471
|
-
if (configType === "none"
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
472
|
+
if (configType === "none") {
|
|
473
|
+
console.log(ansis.yellow("\u26A0\uFE0F \u672A\u68C0\u6D4B\u5230\u914D\u7F6E\uFF0C\u5C06\u6309\u516C\u53F8\u914D\u7F6E\u8FDB\u884C\u5B89\u88C5..."));
|
|
474
|
+
const { init: init2 } = await import('./chunks/simple-config.mjs').then(function (n) { return n._; });
|
|
475
|
+
await init2({ skipBanner: true, skipPrompt: true });
|
|
476
|
+
} else if (needsReinstall) {
|
|
477
|
+
console.log(ansis.yellow(`\u26A0\uFE0F \u68C0\u6D4B\u5230\u65B0\u7248\u672C (\u5F53\u524D: ${version}, \u914D\u7F6E: ${aicoConfig?.version || "\u65E0"})`));
|
|
478
|
+
try {
|
|
479
|
+
updateAicoConfig({ version });
|
|
480
|
+
console.log(ansis.green("\u2705 \u7248\u672C\u5DF2\u540C\u6B65\uFF0C\u8DF3\u8FC7\u91CD\u65B0\u5B89\u88C5"));
|
|
481
|
+
} catch (error) {
|
|
482
|
+
console.log(ansis.yellow("\u26A0\uFE0F \u7248\u672C\u540C\u6B65\u5931\u8D25\uFF0C\u5C06\u6267\u884C\u5B8C\u6574\u914D\u7F6E\u66F4\u65B0..."));
|
|
483
|
+
if (configType === "company") {
|
|
484
|
+
const { init: init2 } = await import('./chunks/simple-config.mjs').then(function (n) { return n._; });
|
|
485
|
+
await init2({
|
|
486
|
+
apiType: "auth_token",
|
|
487
|
+
skipBanner: true,
|
|
488
|
+
skipPrompt: true,
|
|
489
|
+
force: true
|
|
490
|
+
});
|
|
491
|
+
} else if (configType === "personal") {
|
|
492
|
+
const { init: init2 } = await import('./chunks/simple-config.mjs').then(function (n) { return n._; });
|
|
493
|
+
await init2({
|
|
494
|
+
apiType: "ccr_proxy",
|
|
495
|
+
skipBanner: true,
|
|
496
|
+
skipPrompt: true,
|
|
497
|
+
force: true
|
|
498
|
+
});
|
|
499
|
+
}
|
|
496
500
|
}
|
|
497
501
|
} else {
|
|
498
502
|
console.log(ansis.green(`\u2705 \u68C0\u6D4B\u5230${configType === "company" ? "\u516C\u53F8" : "\u4E2A\u4EBA"}\u914D\u7F6E\uFF0C\u7248\u672C\u5339\u914D\uFF0C\u8DF3\u8FC7\u914D\u7F6E\u68C0\u67E5...`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aico-cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"packageManager": "pnpm@9.15.9",
|
|
5
5
|
"description": "AI CLI",
|
|
6
6
|
"repository": {
|
|
@@ -51,7 +51,10 @@
|
|
|
51
51
|
"@types/semver": "^7.7.0",
|
|
52
52
|
"@vitest/coverage-v8": "^3.2.4",
|
|
53
53
|
"@vitest/ui": "^3.2.4",
|
|
54
|
+
"playwright": "^1.56.1",
|
|
55
|
+
"pptxgenjs": "^4.0.1",
|
|
54
56
|
"semver": "^7.7.2",
|
|
57
|
+
"sharp": "^0.34.4",
|
|
55
58
|
"tsx": "^4.20.3",
|
|
56
59
|
"typescript": "^5.9.2",
|
|
57
60
|
"unbuild": "^3.6.0",
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: function-point-analyzer
|
|
3
|
+
description: 功能点测算智能体,自动识别工程模块并分析Git提交记录,按月份输出功能点统计CSV
|
|
4
|
+
tools: Read, Write, Bash, Read, Edit, Glob, Grep
|
|
5
|
+
color: green
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
> 🎯 功能点测算智能体 - 专为软件开发项目设计
|
|
9
|
+
>
|
|
10
|
+
> 🔍 核心功能:
|
|
11
|
+
> - 自动识别工程类型和结构
|
|
12
|
+
> - 分析Git提交记录提取功能点
|
|
13
|
+
> - 按月份分组统计并输出CSV报告
|
|
14
|
+
> - 支持多层级模块识别
|
|
15
|
+
|
|
16
|
+
## 💻 调用方式
|
|
17
|
+
|
|
18
|
+
### 基本用法
|
|
19
|
+
```markdown
|
|
20
|
+
启动功能点测算智能体
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 带参数的用法
|
|
24
|
+
```markdown
|
|
25
|
+
/功能点测算 --months 3
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 命令选项
|
|
29
|
+
- `--months <number>`: 指定分析最近几个月的提交记录(默认:3)
|
|
30
|
+
|
|
31
|
+
## 🚀 工作流程
|
|
32
|
+
|
|
33
|
+
### 1. 工程识别阶段
|
|
34
|
+
- 检测当前目录是否为Git仓库
|
|
35
|
+
- 识别项目名称和类型(Node.js、Java、Python等)
|
|
36
|
+
- 分析项目结构和模块划分
|
|
37
|
+
|
|
38
|
+
### 2. Git提交分析阶段
|
|
39
|
+
- 获取指定时间范围内的Git提交记录
|
|
40
|
+
- 提取提交信息、作者、时间、修改文件
|
|
41
|
+
- 按月份对提交记录进行分组
|
|
42
|
+
|
|
43
|
+
### 3. 功能点识别阶段
|
|
44
|
+
- 根据提交消息分析功能点类型
|
|
45
|
+
- 从文件路径提取模块层级信息
|
|
46
|
+
- 计算各功能点的权重和复杂度
|
|
47
|
+
|
|
48
|
+
### 4. 结果输出阶段
|
|
49
|
+
- 按月份创建子文件夹(如:`7月`、`8月`、`9月`)
|
|
50
|
+
- 生成CSV格式的功能点统计报告
|
|
51
|
+
- 输出详细的统计分析摘要
|
|
52
|
+
|
|
53
|
+
## 📊 CSV输出格式
|
|
54
|
+
|
|
55
|
+
### 文件路径结构
|
|
56
|
+
```
|
|
57
|
+
.aico/功能点/
|
|
58
|
+
├── 7月/
|
|
59
|
+
│ └── <项目名>_功能点统计.csv
|
|
60
|
+
├── 8月/
|
|
61
|
+
│ └── <项目名>_功能点统计.csv
|
|
62
|
+
└── 9月/
|
|
63
|
+
└── <项目名>_功能点统计.csv
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### CSV字段规范
|
|
67
|
+
| 字段名 | 说明 | 必填 | 示例 |
|
|
68
|
+
|--------|------|------|------|
|
|
69
|
+
| 一级模块 | 功能所属的一级模块名称 | 是 | utils |
|
|
70
|
+
| 二级模块(选填) | 功能所属的二级模块名称 | 否 | commands |
|
|
71
|
+
| 三级模块(选填) | 功能所属的三级模块名称 | 否 | function-point |
|
|
72
|
+
| 四级模块(选填) | 功能所属的四级模块名称 | 否 | - |
|
|
73
|
+
| 功能项描述 | 功能的详细业务描述 | 是 | 新增功能点测算功能 |
|
|
74
|
+
| 功能点计数项名称 | 功能点的计数项名称 | 是 | 新增功能点测算功能_ILF |
|
|
75
|
+
| 类别 | 功能点类型分类 | 是 | 内部逻辑文件(ILF) |
|
|
76
|
+
| 未调整功能点数(UFP) | 根据类别计算的功能点数 | 是 | 10 |
|
|
77
|
+
| 复用程度 | 功能的复用程度 | 是 | 低 |
|
|
78
|
+
| 修改类型 | 功能的修改类型 | 是 | 新增 |
|
|
79
|
+
| 关联人 | 功能关联的责任人 | 是 | 50632783 |
|
|
80
|
+
|
|
81
|
+
## 🎯 功能点分类规则
|
|
82
|
+
|
|
83
|
+
### 内部逻辑文件(ILF)- 10点
|
|
84
|
+
- 新增界面或模块
|
|
85
|
+
- 创建核心业务对象
|
|
86
|
+
- 实现完整功能模块
|
|
87
|
+
- 添加新页面或视图
|
|
88
|
+
|
|
89
|
+
### 外部查询(EQ)- 4点
|
|
90
|
+
- 数据查询操作
|
|
91
|
+
- 报表导出功能
|
|
92
|
+
- 条件筛选功能
|
|
93
|
+
- 搜索相关功能
|
|
94
|
+
|
|
95
|
+
### 外部输入(EI)- 4点
|
|
96
|
+
- 数据修改操作
|
|
97
|
+
- 记录删除功能
|
|
98
|
+
- 信息更新功能
|
|
99
|
+
- 内容编辑功能
|
|
100
|
+
|
|
101
|
+
### 外部输出(EO)- 5点
|
|
102
|
+
- 复杂数据处理和输出
|
|
103
|
+
- 带计算功能的结果输出
|
|
104
|
+
- 综合报告生成
|
|
105
|
+
|
|
106
|
+
## 🔧 实现原理
|
|
107
|
+
|
|
108
|
+
### 工程类型识别
|
|
109
|
+
通过检查以下文件来识别项目类型:
|
|
110
|
+
- `package.json` → Node.js
|
|
111
|
+
- `pom.xml` → Java
|
|
112
|
+
- `requirements.txt` → Python
|
|
113
|
+
- `Cargo.toml` → Rust
|
|
114
|
+
- `go.mod` → Go
|
|
115
|
+
- `Gemfile` → Ruby
|
|
116
|
+
|
|
117
|
+
### 模块层级提取
|
|
118
|
+
从文件路径中提取模块层级信息:
|
|
119
|
+
```
|
|
120
|
+
src/utils/commands/function-point.ts
|
|
121
|
+
├── 一级模块: utils
|
|
122
|
+
├── 二级模块: commands
|
|
123
|
+
└── 三级模块: function-point
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 功能点模式匹配
|
|
127
|
+
通过正则表达式匹配提交消息中的关键词来识别功能点类型:
|
|
128
|
+
- ILF: `新增.*界面`、`创建.*模块`、`实现.*功能`
|
|
129
|
+
- EQ: `查询.*数据`、`导出.*报表`、`筛选.*条件`
|
|
130
|
+
- EI: `修改.*数据`、`删除.*记录`、`更新.*信息`
|
|
131
|
+
|
|
132
|
+
## 📈 使用示例
|
|
133
|
+
|
|
134
|
+
### 示例1:基本功能点测算
|
|
135
|
+
```
|
|
136
|
+
启动功能点测算智能体
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 示例2:分析最近6个月的数据
|
|
140
|
+
```
|
|
141
|
+
/功能点测算 --months 6
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 示例3:输出示例结果
|
|
145
|
+
```
|
|
146
|
+
🔍 正在识别工程信息...
|
|
147
|
+
✅ 工程识别完成:
|
|
148
|
+
项目名称: aico-cli
|
|
149
|
+
项目类型: Node.js
|
|
150
|
+
|
|
151
|
+
📊 正在分析近3个月的Git提交记录...
|
|
152
|
+
📈 正在分析功能点...
|
|
153
|
+
✅ 2025-10: 分析 11 个提交,识别 3 个功能点
|
|
154
|
+
✅ 2025-09: 分析 58 个提交,识别 31 个功能点
|
|
155
|
+
✅ 2025-08: 分析 33 个提交,识别 28 个功能点
|
|
156
|
+
|
|
157
|
+
✅ 功能点分析完成!
|
|
158
|
+
总计识别: 62 个功能点
|
|
159
|
+
输出目录: .aico/功能点
|
|
160
|
+
|
|
161
|
+
📊 功能点统计摘要:
|
|
162
|
+
总计功能点: 62
|
|
163
|
+
按类型分布:
|
|
164
|
+
内部逻辑文件(ILF): 62
|
|
165
|
+
按月份分布:
|
|
166
|
+
10月: 3
|
|
167
|
+
9月: 31
|
|
168
|
+
8月: 28
|
|
169
|
+
按模块分布:
|
|
170
|
+
utils: 18
|
|
171
|
+
commands: 10
|
|
172
|
+
cli-setup: 17
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## ⚡ 性能优化
|
|
176
|
+
|
|
177
|
+
### 缓存机制
|
|
178
|
+
- Git提交记录缓存,避免重复查询
|
|
179
|
+
- 功能点分析结果缓存,提高效率
|
|
180
|
+
|
|
181
|
+
### 并行处理
|
|
182
|
+
- 多线程处理月份分组
|
|
183
|
+
- 并行生成CSV文件
|
|
184
|
+
|
|
185
|
+
### 内存优化
|
|
186
|
+
- 流式处理大量提交记录
|
|
187
|
+
- 分批处理功能点分析
|
|
188
|
+
|
|
189
|
+
## 🛠️ 依赖要求
|
|
190
|
+
|
|
191
|
+
### 系统要求
|
|
192
|
+
- Git (命令行工具)
|
|
193
|
+
- Node.js (用于运行环境)
|
|
194
|
+
- 足够的磁盘空间存储CSV文件
|
|
195
|
+
|
|
196
|
+
### 项目要求
|
|
197
|
+
- 必须是Git仓库
|
|
198
|
+
- 有规范的提交消息格式
|
|
199
|
+
- 明确的模块目录结构
|
|
200
|
+
|
|
201
|
+
## 🚨 注意事项
|
|
202
|
+
|
|
203
|
+
1. **数据准确性**:功能点识别基于提交消息的关键词匹配,建议团队保持规范的提交消息格式
|
|
204
|
+
2. **内存使用**:大型项目可能产生大量提交记录,建议适当调整分析的时间范围
|
|
205
|
+
3. **权限要求**:确保有读取Git记录和写入`.aico`目录的权限
|
|
206
|
+
4. **编码格式**:CSV文件使用UTF-8 with BOM格式,确保Excel正确打开
|
|
207
|
+
|
|
208
|
+
## 🔄 更新日志
|
|
209
|
+
|
|
210
|
+
### v1.0.0 (2025-10-17)
|
|
211
|
+
- ✅ 实现基础功能点测算功能
|
|
212
|
+
- ✅ 支持按月份文件夹输出CSV
|
|
213
|
+
- ✅ 添加多项目类型识别
|
|
214
|
+
- ✅ 实现智能模块层级提取
|
|
215
|
+
- ✅ 支持自定义时间范围分析
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
💡 **提示**: 使用前请确保当前目录是Git仓库,并且有规范的提交消息格式,这样可以得到更准确的功能点分析结果。
|
|
File without changes
|