wangchuan 2.16.0 → 2.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,37 +1,130 @@
1
1
  /**
2
- * prompt.ts — Interactive user confirmation
2
+ * prompt.ts — Interactive user confirmation with enhanced conflict resolution
3
3
  *
4
- * Provides single-file conflict prompt and batch conflict strategy,
5
- * supports TTY interactive and CI non-interactive mode (WANGCHUAN_NONINTERACTIVE=1).
4
+ * Provides single-file conflict prompt with:
5
+ * - Compact 3-line diff preview (red deletions, green additions)
6
+ * - File size comparison
7
+ * - [d] show full diff
8
+ * - [m] attempt three-way merge
9
+ * - Standard [o] overwrite / [s] skip / [A] overwrite all / [S] skip all
10
+ *
11
+ * Supports TTY interactive and CI non-interactive mode (WANGCHUAN_NONINTERACTIVE=1).
6
12
  */
7
13
  import readline from 'readline';
14
+ import chalk from 'chalk';
8
15
  import { t } from '../i18n.js';
16
+ import { diffText } from './linediff.js';
9
17
  /** Default strategy for non-interactive mode (CI) */
10
18
  const NON_INTERACTIVE_DEFAULT = 'skip';
19
+ /** Format file size in human-readable form */
20
+ function formatSize(bytes) {
21
+ if (bytes < 1024)
22
+ return `${bytes}B`;
23
+ if (bytes < 1024 * 1024)
24
+ return `${(bytes / 1024).toFixed(1)}KB`;
25
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
26
+ }
27
+ /** Build a compact diff preview (first N changed lines from each side) */
28
+ function buildDiffPreview(localContent, remoteContent, maxLines = 3) {
29
+ const lines = diffText(localContent, remoteContent, 1);
30
+ if (lines.length === 0)
31
+ return '';
32
+ const output = [];
33
+ let shown = 0;
34
+ for (const line of lines) {
35
+ if (shown >= maxLines)
36
+ break;
37
+ if (line.type === 'removed') {
38
+ output.push(` ${chalk.red(`- ${line.content}`)}`);
39
+ shown++;
40
+ }
41
+ else if (line.type === 'added') {
42
+ output.push(` ${chalk.green(`+ ${line.content}`)}`);
43
+ shown++;
44
+ }
45
+ }
46
+ const totalChanges = lines.filter(l => l.type !== 'context').length;
47
+ if (totalChanges > maxLines) {
48
+ output.push(chalk.gray(` … ${t('prompt.moreChanges', { count: totalChanges - maxLines })}`));
49
+ }
50
+ return output.join('\n');
51
+ }
52
+ /** Build the full diff output */
53
+ function buildFullDiff(localContent, remoteContent) {
54
+ const lines = diffText(localContent, remoteContent, 3);
55
+ if (lines.length === 0)
56
+ return chalk.gray(' (identical)');
57
+ return lines.map(line => {
58
+ if (line.type === 'removed')
59
+ return ` ${chalk.red(`- ${line.content}`)}`;
60
+ if (line.type === 'added')
61
+ return ` ${chalk.green(`+ ${line.content}`)}`;
62
+ return ` ${chalk.gray(` ${line.content}`)}`;
63
+ }).join('\n');
64
+ }
11
65
  /**
12
66
  * Ask how to handle a single conflicting file.
13
67
  * When overwrite_all / skip_all is returned, caller should apply to all subsequent conflicts.
68
+ *
69
+ * @param localContent Local file content (for diff preview)
70
+ * @param remoteContent Remote file content (for diff preview)
71
+ * @param canMerge Whether three-way merge is available for this file
14
72
  */
15
- export async function askConflict(repoRel) {
73
+ export async function askConflict(repoRel, localContent, remoteContent, canMerge) {
16
74
  if (process.env['WANGCHUAN_NONINTERACTIVE'] === '1' || !process.stdin.isTTY) {
17
75
  return NON_INTERACTIVE_DEFAULT;
18
76
  }
77
+ // Build header
78
+ let header = `\n ⚡ ${t('prompt.conflict', { file: repoRel })}\n` +
79
+ ` ${t('prompt.conflictDesc')}\n`;
80
+ // Show file size comparison if content is available
81
+ if (localContent !== undefined && remoteContent !== undefined) {
82
+ const localSize = formatSize(Buffer.byteLength(localContent, 'utf-8'));
83
+ const remoteSize = formatSize(Buffer.byteLength(remoteContent, 'utf-8'));
84
+ header += ` ${t('prompt.sizeCompare', { local: localSize, remote: remoteSize })}\n`;
85
+ // Show compact diff preview
86
+ const preview = buildDiffPreview(localContent, remoteContent);
87
+ if (preview) {
88
+ header += `\n${preview}\n`;
89
+ }
90
+ }
91
+ // Build choices line
92
+ const mergeChoice = canMerge ? ` [m] ${t('prompt.merge')}` : '';
93
+ header +=
94
+ ` ${t('prompt.conflictChoices')}` +
95
+ ` [d] ${t('prompt.showDiff')}${mergeChoice}\n`;
96
+ const validChoices = canMerge ? 'o/s/A/S/d/m' : 'o/s/A/S/d';
97
+ // Interactive loop (allows 'd' to show full diff and re-prompt)
19
98
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
20
99
  return new Promise(resolve => {
21
- process.stdout.write(`\n ⚡ ${t('prompt.conflict', { file: repoRel })}\n` +
22
- ` ${t('prompt.conflictDesc')}\n` +
23
- ` ${t('prompt.conflictChoices')}\n` +
24
- ` ${t('prompt.choose')}`);
25
- rl.once('line', (ans) => {
26
- rl.close();
27
- switch (ans.trim()) {
28
- case 'o': return resolve('overwrite');
29
- case 'A': return resolve('overwrite_all');
30
- case 'S': return resolve('skip_all');
31
- case 's':
32
- default: return resolve('skip');
33
- }
34
- });
100
+ function prompt() {
101
+ process.stdout.write(header + ` ${t('prompt.choose', { choices: validChoices })}`);
102
+ rl.once('line', (ans) => {
103
+ const choice = ans.trim();
104
+ if (choice === 'd' && localContent !== undefined && remoteContent !== undefined) {
105
+ // Show full diff and re-prompt
106
+ console.log();
107
+ console.log(buildFullDiff(localContent, remoteContent));
108
+ console.log();
109
+ // Reset header to just choices for re-prompt
110
+ header =
111
+ ` ${t('prompt.conflictChoices')}` +
112
+ ` [d] ${t('prompt.showDiff')}${mergeChoice}\n`;
113
+ prompt();
114
+ return;
115
+ }
116
+ rl.close();
117
+ switch (choice) {
118
+ case 'o': return resolve('overwrite');
119
+ case 'A': return resolve('overwrite_all');
120
+ case 'S': return resolve('skip_all');
121
+ case 'm': return resolve(canMerge ? 'merge' : 'skip');
122
+ case 's':
123
+ default: return resolve('skip');
124
+ }
125
+ });
126
+ }
127
+ prompt();
35
128
  });
36
129
  }
37
130
  //# sourceMappingURL=prompt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../src/utils/prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AAS/B,qDAAqD;AACrD,MAAM,uBAAuB,GAAqB,MAAM,CAAC;AAEzD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe;IAC/C,IAAI,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAC5E,OAAO,uBAAuB,CAAC;IACjC,CAAC;IAED,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEtF,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;QAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,SAAS,CAAC,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI;YACpD,QAAQ,CAAC,CAAC,qBAAqB,CAAC,IAAI;YACpC,QAAQ,CAAC,CAAC,wBAAwB,CAAC,IAAI;YACvC,KAAK,CAAC,CAAC,eAAe,CAAC,EAAE,CAC1B,CAAC;QAEF,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAW,EAAE,EAAE;YAC9B,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,QAAQ,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;gBACnB,KAAK,GAAG,CAAC,CAAC,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC;gBACtC,KAAK,GAAG,CAAC,CAAC,OAAO,OAAO,CAAC,eAAe,CAAC,CAAC;gBAC1C,KAAK,GAAG,CAAC,CAAC,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;gBACrC,KAAK,GAAG,CAAC;gBACT,OAAO,CAAC,CAAE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;YACnC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../src/utils/prompt.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wangchuan",
3
- "version": "2.16.0",
3
+ "version": "2.17.1",
4
4
  "description": "忘川 · AI 记忆同步系统 — 智能体记忆永不遗失",
5
5
  "bin": {
6
6
  "wangchuan": "./dist/bin/wangchuan.js"
@@ -23,8 +23,8 @@ At the end of each task session, evaluate whether the conversation produced any
23
23
 
24
24
  | Category | What to look for | Where to update |
25
25
  |----------|-----------------|-----------------|
26
- | **New skill learned** | Reusable workflow, automation pattern, or domain knowledge | Create/update skill in `~/.claude-internal/skills/` |
27
- | **User preference discovered** | Coding style, tool preference, communication preference | Append to `~/.claude-internal/CLAUDE.md` |
26
+ | **New skill learned** | Reusable workflow, automation pattern, or domain knowledge | Create/update skill in `~/.claude/skills/` |
27
+ | **User preference discovered** | Coding style, tool preference, communication preference | Append to `~/.claude/CLAUDE.md` |
28
28
  | **Memory worth preserving** | Key decisions, project context, recurring patterns | Append to agent memory file |
29
29
  | **Config change made** | MCP servers added, settings changed, permissions updated | Already tracked by file sync |
30
30