@icode-js/icode 3.0.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.
Files changed (46) hide show
  1. package/README.md +346 -0
  2. package/bin/icode.js +6 -0
  3. package/package.json +34 -0
  4. package/src/cli.js +131 -0
  5. package/src/commands/ai.js +287 -0
  6. package/src/commands/checkout.js +59 -0
  7. package/src/commands/clean.js +65 -0
  8. package/src/commands/codereview.js +52 -0
  9. package/src/commands/config.js +513 -0
  10. package/src/commands/explain.js +80 -0
  11. package/src/commands/help.js +49 -0
  12. package/src/commands/info.js +57 -0
  13. package/src/commands/migrate.js +86 -0
  14. package/src/commands/push.js +125 -0
  15. package/src/commands/sync.js +74 -0
  16. package/src/commands/tag.js +53 -0
  17. package/src/commands/undo.js +66 -0
  18. package/src/core/ai-client.js +1125 -0
  19. package/src/core/ai-commit-summary.js +18 -0
  20. package/src/core/ai-config.js +342 -0
  21. package/src/core/ai-diff-range.js +117 -0
  22. package/src/core/args.js +47 -0
  23. package/src/core/commit-conventions.js +169 -0
  24. package/src/core/config-store.js +194 -0
  25. package/src/core/errors.js +25 -0
  26. package/src/core/git-context.js +105 -0
  27. package/src/core/git-service.js +428 -0
  28. package/src/core/hook-diagnostics.js +23 -0
  29. package/src/core/loading.js +36 -0
  30. package/src/core/logger.js +55 -0
  31. package/src/core/prompts.js +152 -0
  32. package/src/core/shell.js +77 -0
  33. package/src/workflows/ai-codereview-workflow.js +126 -0
  34. package/src/workflows/ai-commit-workflow.js +128 -0
  35. package/src/workflows/ai-conflict-workflow.js +102 -0
  36. package/src/workflows/ai-explain-workflow.js +116 -0
  37. package/src/workflows/ai-risk-review-workflow.js +49 -0
  38. package/src/workflows/checkout-workflow.js +85 -0
  39. package/src/workflows/clean-workflow.js +131 -0
  40. package/src/workflows/info-workflow.js +30 -0
  41. package/src/workflows/migrate-workflow.js +449 -0
  42. package/src/workflows/push-workflow.js +276 -0
  43. package/src/workflows/rollback-workflow.js +84 -0
  44. package/src/workflows/sync-workflow.js +141 -0
  45. package/src/workflows/tag-workflow.js +64 -0
  46. package/src/workflows/undo-workflow.js +328 -0
@@ -0,0 +1,86 @@
1
+ import { parseArgs } from 'node:util'
2
+ import { normalizeLegacyArgs } from '../core/args.js'
3
+ import { IcodeError } from '../core/errors.js'
4
+ import { logger } from '../core/logger.js'
5
+ import { runMigrateWorkflow } from '../workflows/migrate-workflow.js'
6
+
7
+ function printHelp() {
8
+ process.stdout.write(`
9
+ Usage:
10
+ icode migrate <sourceBranch> <targetBranch> [options]
11
+ icode migrate --interactive
12
+
13
+ Arguments:
14
+ <sourceBranch> 迁移来源分支(交互模式可省略)
15
+ <targetBranch> 迁移目标分支(交互模式可省略)
16
+
17
+ Options:
18
+ -i, --interactive 交互模式(单选/多选 source/target 与迁移范围)
19
+ --range <spec> 指定提交范围,例如 main..feature-x(交互模式下若提供则直接使用)
20
+ --push 迁移后自动推送 target 分支
21
+ -y, --yes 自动确认(跳过确认提示)
22
+ --repo-mode <mode> 仓库模式: auto(自动继承父仓库) | strict(禁止继承)
23
+ --no-verify 推送时跳过 hook/husky 校验
24
+ -h, --help 查看帮助
25
+
26
+ Notes:
27
+ 默认迁移 target..source 的增量提交。
28
+
29
+ Examples:
30
+ icode migrate feature/login release
31
+ icode migrate --interactive
32
+ icode migrate feature/login release --range HEAD~3..feature/login
33
+ icode migrate feature/login release --push -y
34
+ `)
35
+ }
36
+
37
+ export async function runMigrateCommand(rawArgs) {
38
+ const args = normalizeLegacyArgs(rawArgs)
39
+ const parsed = parseArgs({
40
+ args,
41
+ allowPositionals: true,
42
+ options: {
43
+ interactive: { type: 'boolean', short: 'i', default: false },
44
+ range: { type: 'string' },
45
+ push: { type: 'boolean', default: false },
46
+ yes: { type: 'boolean', short: 'y', default: false },
47
+ 'repo-mode': { type: 'string', default: 'auto' },
48
+ 'no-verify': { type: 'boolean', default: false },
49
+ help: { type: 'boolean', short: 'h', default: false }
50
+ }
51
+ })
52
+
53
+ if (parsed.values.help) {
54
+ printHelp()
55
+ return
56
+ }
57
+
58
+ if (parsed.positionals.length > 2) {
59
+ throw new IcodeError('参数过多: icode migrate 最多接收两个分支参数', {
60
+ code: 'MIGRATE_ARGS_TOO_MANY',
61
+ exitCode: 2
62
+ })
63
+ }
64
+
65
+ const [sourceBranch = '', targetBranch = ''] = parsed.positionals
66
+ const interactive = parsed.values.interactive || parsed.positionals.length < 2
67
+
68
+ const result = await runMigrateWorkflow({
69
+ sourceBranch,
70
+ targetBranch,
71
+ interactive,
72
+ range: parsed.values.range,
73
+ push: parsed.values.push,
74
+ yes: parsed.values.yes,
75
+ repoMode: parsed.values['repo-mode'],
76
+ noVerify: parsed.values['no-verify']
77
+ })
78
+
79
+ if (result.canceled) {
80
+ return
81
+ }
82
+
83
+ logger.success(
84
+ `migrate 完成: ${result.sourceBranch} -> ${result.targetBranch}, commits=${result.migratedCommits}, mode=${result.rangeMode || 'range'}`
85
+ )
86
+ }
@@ -0,0 +1,125 @@
1
+ import { parseArgs } from 'node:util'
2
+ import { normalizeLegacyArgs } from '../core/args.js'
3
+ import { getAiCommandOptions } from '../core/ai-config.js'
4
+ import { logger } from '../core/logger.js'
5
+ import { runPushWorkflow } from '../workflows/push-workflow.js'
6
+
7
+ function formatBranchStatus(status) {
8
+ const map = {
9
+ pushed: '已推送',
10
+ 'merged-and-pushed': '已合并并推送',
11
+ 'skipped-protected': '已跳过(受保护)',
12
+ 'skipped-missing-remote': '已跳过(远程分支不存在)'
13
+ }
14
+
15
+ return map[status] || status
16
+ }
17
+
18
+ function printHelp() {
19
+ process.stdout.write(`
20
+ Usage:
21
+ icode push [targetBranch...] [options]
22
+
23
+ Arguments:
24
+ [targetBranch...] 目标分支列表(可多个,空则默认当前分支)
25
+
26
+ Options:
27
+ -m, --message <msg> 提交信息(未填会提示输入)
28
+ -y, --yes 自动确认(跳过确认提示)
29
+ --local-merge 使用本地 merge 模式(默认,会切换分支并生成 merge commit)
30
+ --ai-commit push 前自动执行 AI commit(会参考本地 hook/commitlint 规范)
31
+ --ai-profile <name> 指定 AI profile(用于 --ai-commit)
32
+ --pull-main 提交前将主分支同步到当前分支
33
+ --not-push-current 不推送当前分支,只处理目标分支
34
+ --force-protected 强制处理配置里的受保护分支
35
+ --repo-mode <mode> 仓库模式: auto(自动继承父仓库) | strict(禁止继承)
36
+ --no-verify 跳过 hook/husky 校验
37
+ -h, --help 查看帮助
38
+
39
+ Notes:
40
+ 默认使用本地 merge 模式。
41
+ 未指定 target 时默认处理当前分支。
42
+ 布尔开关仅在命令行显式传入时生效(如 --ai-commit / --pull-main / --no-verify / -y)。
43
+ `)
44
+ }
45
+
46
+ function resolveBooleanOption(cliValue, fallback = false) {
47
+ if (typeof cliValue === 'boolean') {
48
+ return cliValue
49
+ }
50
+ if (typeof cliValue === 'string') {
51
+ const normalized = cliValue.trim().toLowerCase()
52
+ if (['true', '1', 'yes', 'y', 'on'].includes(normalized)) {
53
+ return true
54
+ }
55
+ if (['false', '0', 'no', 'n', 'off'].includes(normalized)) {
56
+ return false
57
+ }
58
+ }
59
+ return fallback
60
+ }
61
+
62
+ function resolveStringOption(cliValue, configValue, fallback = '') {
63
+ if (typeof cliValue === 'string' && cliValue.trim()) {
64
+ return cliValue
65
+ }
66
+ if (typeof configValue === 'string' && configValue.trim()) {
67
+ return configValue
68
+ }
69
+ return fallback
70
+ }
71
+
72
+ export function resolvePushWorkflowOptions(parsedValues, parsedPositionals, scopedOptions = {}) {
73
+ return {
74
+ targetBranches: parsedPositionals,
75
+ message: parsedValues.message,
76
+ // 显式传入开关才生效,避免配置项隐式开启 push 行为。
77
+ yes: resolveBooleanOption(parsedValues.yes, false),
78
+ aiCommit: resolveBooleanOption(parsedValues['ai-commit'], false),
79
+ aiCommitLang: resolveStringOption(undefined, scopedOptions.aiCommitLang, 'zh'),
80
+ aiProfile: resolveStringOption(parsedValues['ai-profile'], scopedOptions.aiProfile, ''),
81
+ pullMain: resolveBooleanOption(parsedValues['pull-main'], false),
82
+ notPushCurrent: resolveBooleanOption(parsedValues['not-push-current'], false),
83
+ forceProtected: resolveBooleanOption(parsedValues['force-protected'], false),
84
+ repoMode: resolveStringOption(parsedValues['repo-mode'], undefined, 'auto'),
85
+ noVerify: resolveBooleanOption(parsedValues['no-verify'], false)
86
+ }
87
+ }
88
+
89
+ export async function runPushCommand(rawArgs) {
90
+ const args = normalizeLegacyArgs(rawArgs)
91
+ const scopedOptions = getAiCommandOptions('push')
92
+ const parsed = parseArgs({
93
+ args,
94
+ allowPositionals: true,
95
+ options: {
96
+ message: { type: 'string', short: 'm' },
97
+ yes: { type: 'boolean', short: 'y' },
98
+ 'local-merge': { type: 'boolean' },
99
+ 'ai-commit': { type: 'boolean' },
100
+ 'ai-profile': { type: 'string' },
101
+ help: { type: 'boolean', short: 'h' },
102
+ 'pull-main': { type: 'boolean' },
103
+ 'not-push-current': { type: 'boolean' },
104
+ 'force-protected': { type: 'boolean' },
105
+ 'repo-mode': { type: 'string' },
106
+ 'no-verify': { type: 'boolean' }
107
+ }
108
+ })
109
+
110
+ if (parsed.values.help) {
111
+ printHelp()
112
+ return
113
+ }
114
+
115
+ const result = await runPushWorkflow(resolvePushWorkflowOptions(parsed.values, parsed.positionals, scopedOptions))
116
+
117
+ if (result.canceled) {
118
+ return
119
+ }
120
+
121
+ result.summary.forEach((item) => {
122
+ logger.info(`[结果] ${item.branch}: ${formatBranchStatus(item.status)}`)
123
+ })
124
+ logger.success(`push 完成,共处理 ${result.summary.length} 个分支。`)
125
+ }
@@ -0,0 +1,74 @@
1
+ import { parseArgs } from 'node:util'
2
+ import { normalizeLegacyArgs } from '../core/args.js'
3
+ import { logger } from '../core/logger.js'
4
+ import { runSyncWorkflow } from '../workflows/sync-workflow.js'
5
+
6
+ function printHelp() {
7
+ process.stdout.write(`
8
+ Usage:
9
+ icode sync [branch...] [options]
10
+
11
+ Arguments:
12
+ [branch...] 需要同步的分支列表(可多个)
13
+
14
+ Options:
15
+ --all-local 自动同步全部本地分支
16
+ --merge-main 同步后把主分支 merge 到目标分支
17
+ --rebase pull 时使用 rebase
18
+ --push 同步后自动 push
19
+ -y, --yes 自动确认(跳过确认提示)
20
+ --repo-mode <mode> 仓库模式: auto(自动继承父仓库) | strict(禁止继承)
21
+ --no-verify push 时跳过 hook/husky 校验
22
+ -h, --help 查看帮助
23
+
24
+ Notes:
25
+ 未传分支时默认同步当前分支与主分支。
26
+
27
+ Examples:
28
+ icode sync
29
+ icode sync --all-local
30
+ icode sync develop test --merge-main
31
+ icode sync release --push -y
32
+ `)
33
+ }
34
+
35
+ export async function runSyncCommand(rawArgs) {
36
+ const args = normalizeLegacyArgs(rawArgs)
37
+ const parsed = parseArgs({
38
+ args,
39
+ allowPositionals: true,
40
+ options: {
41
+ 'all-local': { type: 'boolean', default: false },
42
+ 'merge-main': { type: 'boolean', default: false },
43
+ rebase: { type: 'boolean', default: false },
44
+ push: { type: 'boolean', default: false },
45
+ yes: { type: 'boolean', short: 'y', default: false },
46
+ 'repo-mode': { type: 'string', default: 'auto' },
47
+ 'no-verify': { type: 'boolean', default: false },
48
+ help: { type: 'boolean', short: 'h', default: false }
49
+ }
50
+ })
51
+
52
+ if (parsed.values.help) {
53
+ printHelp()
54
+ return
55
+ }
56
+
57
+ const result = await runSyncWorkflow({
58
+ branches: parsed.positionals,
59
+ allLocal: parsed.values['all-local'],
60
+ mergeMain: parsed.values['merge-main'],
61
+ rebase: parsed.values.rebase,
62
+ push: parsed.values.push,
63
+ yes: parsed.values.yes,
64
+ repoMode: parsed.values['repo-mode'],
65
+ noVerify: parsed.values['no-verify']
66
+ })
67
+
68
+ if (result.canceled) {
69
+ return
70
+ }
71
+
72
+ const summaryText = result.summary.map((item) => `${item.branch}:${item.status}`).join(', ')
73
+ logger.success(`sync 完成: ${summaryText}`)
74
+ }
@@ -0,0 +1,53 @@
1
+ import { parseArgs } from 'node:util'
2
+ import { normalizeLegacyArgs } from '../core/args.js'
3
+ import { logger } from '../core/logger.js'
4
+ import { runTagWorkflow } from '../workflows/tag-workflow.js'
5
+
6
+ function printHelp() {
7
+ process.stdout.write(`
8
+ Usage:
9
+ icode tag [options]
10
+
11
+ Options:
12
+ -n, --name <tag> 指定 tag 名(默认 vYYYYMMDD_NN)
13
+ -m, --message <msg> tag 备注
14
+ --from <ref> 从指定分支/commit 创建 tag
15
+ --repo-mode <mode> 仓库模式: auto(自动继承父仓库) | strict(禁止继承)
16
+ --no-verify 跳过 hook/husky 校验
17
+ -h, --help 查看帮助
18
+
19
+ Notes:
20
+ 默认 tag 规则: vYYYYMMDD_NN(例如 v20260309_01)。
21
+ `)
22
+ }
23
+
24
+ export async function runTagCommand(rawArgs) {
25
+ const args = normalizeLegacyArgs(rawArgs)
26
+ const parsed = parseArgs({
27
+ args,
28
+ allowPositionals: true,
29
+ options: {
30
+ name: { type: 'string', short: 'n' },
31
+ message: { type: 'string', short: 'm' },
32
+ from: { type: 'string' },
33
+ 'repo-mode': { type: 'string', default: 'auto' },
34
+ 'no-verify': { type: 'boolean', default: false },
35
+ help: { type: 'boolean', short: 'h', default: false }
36
+ }
37
+ })
38
+
39
+ if (parsed.values.help) {
40
+ printHelp()
41
+ return
42
+ }
43
+
44
+ const result = await runTagWorkflow({
45
+ tagName: parsed.values.name,
46
+ message: parsed.values.message,
47
+ fromRef: parsed.values.from,
48
+ repoMode: parsed.values['repo-mode'],
49
+ noVerify: parsed.values['no-verify']
50
+ })
51
+
52
+ logger.success(`tag 完成: ${result.tagName}`)
53
+ }
@@ -0,0 +1,66 @@
1
+ import { parseArgs } from 'node:util'
2
+ import { logger } from '../core/logger.js'
3
+ import { runUndoWorkflow } from '../workflows/undo-workflow.js'
4
+
5
+ function printHelp() {
6
+ process.stdout.write(`
7
+ Usage:
8
+ icode undo [options]
9
+
10
+ Options:
11
+ --mode <mode> 回滚模式: revert | soft | mixed | hard
12
+ --ref <ref> 回滚目标,默认按 mode 自动给出
13
+ --recover <action> 冲突恢复策略: continue | abort | keep
14
+ -y, --yes 自动确认(跳过确认提示)
15
+ --repo-mode <mode> 仓库模式: auto(自动继承父仓库) | strict(禁止继承)
16
+ -h, --help 查看帮助
17
+
18
+ Notes:
19
+ revert 模式会生成新提交;reset 模式会移动 HEAD。
20
+
21
+ Examples:
22
+ icode undo
23
+ icode undo --mode revert --ref HEAD~2
24
+ icode undo --recover abort
25
+ icode undo --mode hard --ref HEAD~1 -y
26
+ `)
27
+ }
28
+
29
+ export async function runUndoCommand(rawArgs) {
30
+ const parsed = parseArgs({
31
+ args: rawArgs,
32
+ allowPositionals: true,
33
+ options: {
34
+ mode: { type: 'string' },
35
+ ref: { type: 'string' },
36
+ recover: { type: 'string' },
37
+ yes: { type: 'boolean', short: 'y', default: false },
38
+ 'repo-mode': { type: 'string', default: 'auto' },
39
+ help: { type: 'boolean', short: 'h', default: false }
40
+ }
41
+ })
42
+
43
+ if (parsed.values.help) {
44
+ printHelp()
45
+ return
46
+ }
47
+
48
+ const result = await runUndoWorkflow({
49
+ mode: parsed.values.mode,
50
+ ref: parsed.values.ref,
51
+ recover: parsed.values.recover,
52
+ yes: parsed.values.yes,
53
+ repoMode: parsed.values['repo-mode']
54
+ })
55
+
56
+ if (result.canceled) {
57
+ return
58
+ }
59
+
60
+ if (result.resolvedOperation) {
61
+ logger.success(`undo 已处理未完成操作: ${result.resolvedOperation} -> ${result.recoverAction}`)
62
+ return
63
+ }
64
+
65
+ logger.success(`undo 完成: mode=${result.mode}, ref=${result.ref}`)
66
+ }