@buaa_smat/hometrans 0.1.13 → 0.1.15
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 +194 -136
- package/agents/build-fixer.md +38 -48
- package/agents/code-reviewer.md +20 -20
- package/agents/logic-coder.md +8 -8
- package/agents/logic-context-builder.md +5 -5
- package/agents/review-fixer.md +16 -16
- package/agents/self-test-fixer.md +15 -15
- package/agents/self-tester.md +56 -55
- package/agents/spec-generator.md +16 -16
- package/dist/cli/config-store.js +120 -9
- package/dist/cli/config.js +4 -4
- package/dist/cli/env-vars.js +129 -0
- package/dist/cli/init.js +315 -276
- package/dist/cli/uninstall.js +152 -17
- package/dist/context/index.js +10 -197
- package/env-requirements.json +181 -181
- package/package.json +1 -1
- package/resource/choose_editor.png +0 -0
- package/resource/common_config.png +0 -0
- package/resource/integration_test_config.png +0 -0
- package/resource/migration_process.svg +94 -0
- package/resource/migration_process_transparent.svg +93 -0
- package/resource/set_env.png +0 -0
- package/resource/ui_align_config.png +0 -0
- package/skills/hmos-batch-ui-align/SKILL.md +10 -0
- package/skills/hmos-batch-ui-align/references/conversion-procedure.md +180 -180
- package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2533 -2533
- package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -555
- package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -117
- package/skills/hmos-batch-ui-align/references/mvvm/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -648
- package/skills/hmos-batch-ui-align/references/mvvm/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2088 -2088
- package/skills/hmos-batch-ui-align/references/mvvm/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -1033
- package/skills/hmos-batch-ui-align/references/mvvm/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -1183
- package/skills/hmos-batch-ui-align/references/mvvm/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -576
- package/skills/hmos-batch-ui-align/references/mvvm/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -297
- package/skills/hmos-batch-ui-align/references/mvvm/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -395
- package/skills/hmos-batch-ui-align/references/mvvm/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +902 -902
- package/skills/hmos-batch-ui-align/references/mvvm/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -106
- package/skills/hmos-batch-ui-align/references/mvvm/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -1178
- package/skills/hmos-batch-ui-align/references/mvvm/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -911
- package/skills/hmos-batch-ui-align/references/mvvm/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +354 -354
- package/skills/hmos-batch-ui-align/references/mvvm//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -11
- package/skills/hmos-convert-pipeline/SKILL.md +63 -49
- package/skills/hmos-fix-build-errors/SKILL.md +5 -6
- package/skills/hmos-fix-build-errors/references/arkts-strict-patterns.md +219 -219
- package/skills/hmos-fix-build-errors/references/known-patterns.md +157 -157
- package/skills/hmos-fix-build-errors/references/rdb-entity-pattern.md +131 -131
- package/skills/hmos-incremental-ui-align/{readme.md → README.md} +28 -21
- package/skills/hmos-incremental-ui-align/SKILL.md +46 -27
- package/skills/hmos-incremental-ui-align/diff_analysis.md +52 -52
- package/skills/hmos-incremental-ui-align/page_align.md +62 -62
- package/skills/hmos-incremental-ui-align/references/Comparison_Template.md +2 -2
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -648
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2088 -2088
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -1033
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -1183
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -576
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -297
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -395
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +902 -902
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -106
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -1178
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/MVVM/346/250/241/345/274/217V1.md +911 -911
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +354 -354
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -11
- package/skills/hmos-incremental-ui-align/references/UI_Analysis_Template.md +3 -3
- package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2533 -2533
- package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -555
- package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -117
- package/skills/hmos-incremental-ui-align/scripts/navigation-capure.md +37 -37
- package/skills/hmos-integration-test/{readme.md → README.md} +38 -38
- package/skills/hmos-integration-test/SKILL.md +63 -52
- package/skills/hmos-resources-convert/SKILL.md +5 -5
- package/skills/hmos-resources-convert/references/conversion-rules.md +663 -663
- package/skills/hmos-resources-convert/references/dependency-analysis-rules.md +388 -388
- package/skills/hmos-resources-convert/references/resource-mapping-rules.md +457 -457
- package/skills/hmos-resources-convert/references/xml-drawable-to-svg-rules.md +513 -513
- package/skills/hmos-spec-generate/SKILL.md +19 -19
- package/skills/hmos-spec-generate/references/android-platform-tokens.md +105 -105
- package/skills/hmos-spec-generate/references/spec-sample-1.md +78 -78
- package/skills/hmos-spec-generate/references/spec-sample-2.md +58 -58
- package/skills/hmos-spec-generate/references/spec-sample-3.md +116 -116
- package/skills/hmos-spec-generate/references/step4-report-template.md +33 -33
- package/tools/test-tools/autotest/README.md +33 -17
- package/tools/test-tools/autotest/self_test_runner.py +109 -15
- package/resource/hometrans_config.png +0 -0
- package/skills/hmos-incremental-ui-align/config-example.json +0 -11
- package/tools/test-tools/autotest/config.yaml.example +0 -58
package/dist/cli/uninstall.js
CHANGED
|
@@ -16,11 +16,16 @@ import { promisify } from 'node:util';
|
|
|
16
16
|
import chalk from 'chalk';
|
|
17
17
|
import inquirer from 'inquirer';
|
|
18
18
|
import { modify, applyEdits } from 'jsonc-parser';
|
|
19
|
-
import { expandHome, loadHomeTransConfig, } from './config-store.js';
|
|
20
|
-
import { dirExists, isPromptAbort, prettyHome } from './init.js';
|
|
19
|
+
import { expandHome, getConfigDir, loadHomeTransConfig, } from './config-store.js';
|
|
20
|
+
import { dirExists, isPromptAbort, prettyHome, MACHINE_ENV_KEYS } from './init.js';
|
|
21
|
+
import { removeEnvVars } from './env-vars.js';
|
|
21
22
|
const execFileAsync = promisify(execFile);
|
|
22
23
|
const __filename = fileURLToPath(import.meta.url);
|
|
23
24
|
const __dirname = path.dirname(__filename);
|
|
25
|
+
/** Names + readable count of env vars that have a non-empty value in config. */
|
|
26
|
+
function plannedEnvVarNames(env) {
|
|
27
|
+
return MACHINE_ENV_KEYS.filter((k) => (env[k] ?? '').trim().length > 0);
|
|
28
|
+
}
|
|
24
29
|
/* ------------------------------------------------------------------ */
|
|
25
30
|
/* Bundled content discovery */
|
|
26
31
|
/* ------------------------------------------------------------------ */
|
|
@@ -85,7 +90,7 @@ async function tryRemoveJsoncKey(filePath, keyPath) {
|
|
|
85
90
|
const edits = modify(raw, keyPath, undefined, { formattingOptions });
|
|
86
91
|
if (edits.length === 0)
|
|
87
92
|
return null;
|
|
88
|
-
return applyEdits(raw, edits);
|
|
93
|
+
return { oldContent: raw, newContent: applyEdits(raw, edits) };
|
|
89
94
|
}
|
|
90
95
|
async function tryRemoveTomlSection(filePath, sectionHeader) {
|
|
91
96
|
let raw;
|
|
@@ -116,7 +121,7 @@ async function tryRemoveTomlSection(filePath, sectionHeader) {
|
|
|
116
121
|
let content = result.join('\n').replace(/\n{3,}/g, '\n\n').trimEnd();
|
|
117
122
|
if (content.length > 0)
|
|
118
123
|
content += '\n';
|
|
119
|
-
return content;
|
|
124
|
+
return { oldContent: raw, newContent: content };
|
|
120
125
|
}
|
|
121
126
|
/* ------------------------------------------------------------------ */
|
|
122
127
|
/* Plan building */
|
|
@@ -165,13 +170,14 @@ async function buildPlanForEditor(editor, skillNames, agentEntries, plan) {
|
|
|
165
170
|
if (!mcp.path || !mcp.keyPath)
|
|
166
171
|
break;
|
|
167
172
|
const configPath = expandHome(mcp.path);
|
|
168
|
-
const
|
|
169
|
-
if (
|
|
173
|
+
const change = await tryRemoveJsoncKey(configPath, mcp.keyPath);
|
|
174
|
+
if (change !== null) {
|
|
170
175
|
plan.modifications.push({
|
|
171
176
|
display: `${editor.name}: ${prettyHome(configPath)}`,
|
|
172
177
|
absPath: configPath,
|
|
173
178
|
reason: 'Remove hometrans MCP entry',
|
|
174
|
-
|
|
179
|
+
oldContent: change.oldContent,
|
|
180
|
+
newContent: change.newContent,
|
|
175
181
|
});
|
|
176
182
|
}
|
|
177
183
|
break;
|
|
@@ -180,13 +186,14 @@ async function buildPlanForEditor(editor, skillNames, agentEntries, plan) {
|
|
|
180
186
|
plan.codexRemove = true;
|
|
181
187
|
if (mcp.path && mcp.section) {
|
|
182
188
|
const configPath = expandHome(mcp.path);
|
|
183
|
-
const
|
|
184
|
-
if (
|
|
189
|
+
const change = await tryRemoveTomlSection(configPath, mcp.section);
|
|
190
|
+
if (change !== null) {
|
|
185
191
|
plan.modifications.push({
|
|
186
192
|
display: `${editor.name}: ${prettyHome(configPath)}`,
|
|
187
193
|
absPath: configPath,
|
|
188
194
|
reason: 'Remove hometrans MCP section',
|
|
189
|
-
|
|
195
|
+
oldContent: change.oldContent,
|
|
196
|
+
newContent: change.newContent,
|
|
190
197
|
});
|
|
191
198
|
}
|
|
192
199
|
}
|
|
@@ -196,13 +203,14 @@ async function buildPlanForEditor(editor, skillNames, agentEntries, plan) {
|
|
|
196
203
|
if (!mcp.path || !mcp.section)
|
|
197
204
|
break;
|
|
198
205
|
const configPath = expandHome(mcp.path);
|
|
199
|
-
const
|
|
200
|
-
if (
|
|
206
|
+
const change = await tryRemoveTomlSection(configPath, mcp.section);
|
|
207
|
+
if (change !== null) {
|
|
201
208
|
plan.modifications.push({
|
|
202
209
|
display: `${editor.name}: ${prettyHome(configPath)}`,
|
|
203
210
|
absPath: configPath,
|
|
204
211
|
reason: 'Remove hometrans MCP section',
|
|
205
|
-
|
|
212
|
+
oldContent: change.oldContent,
|
|
213
|
+
newContent: change.newContent,
|
|
206
214
|
});
|
|
207
215
|
}
|
|
208
216
|
break;
|
|
@@ -211,12 +219,92 @@ async function buildPlanForEditor(editor, skillNames, agentEntries, plan) {
|
|
|
211
219
|
break;
|
|
212
220
|
}
|
|
213
221
|
}
|
|
222
|
+
/** Line-based diff via an LCS table. Files here are small config files. */
|
|
223
|
+
function diffLines(oldLines, newLines) {
|
|
224
|
+
const n = oldLines.length;
|
|
225
|
+
const m = newLines.length;
|
|
226
|
+
const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
|
|
227
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
228
|
+
for (let j = m - 1; j >= 0; j--) {
|
|
229
|
+
dp[i][j] =
|
|
230
|
+
oldLines[i] === newLines[j]
|
|
231
|
+
? dp[i + 1][j + 1] + 1
|
|
232
|
+
: Math.max(dp[i + 1][j], dp[i][j + 1]);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
const out = [];
|
|
236
|
+
let i = 0;
|
|
237
|
+
let j = 0;
|
|
238
|
+
while (i < n && j < m) {
|
|
239
|
+
if (oldLines[i] === newLines[j]) {
|
|
240
|
+
out.push({ type: ' ', text: oldLines[i] });
|
|
241
|
+
i++;
|
|
242
|
+
j++;
|
|
243
|
+
}
|
|
244
|
+
else if (dp[i + 1][j] >= dp[i][j + 1]) {
|
|
245
|
+
out.push({ type: '-', text: oldLines[i] });
|
|
246
|
+
i++;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
out.push({ type: '+', text: newLines[j] });
|
|
250
|
+
j++;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
while (i < n)
|
|
254
|
+
out.push({ type: '-', text: oldLines[i++] });
|
|
255
|
+
while (j < m)
|
|
256
|
+
out.push({ type: '+', text: newLines[j++] });
|
|
257
|
+
return out;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Render a unified, git-style diff with `context` unchanged lines around each
|
|
261
|
+
* change; long unchanged runs collapse to a `⋮` marker. Returns coloured,
|
|
262
|
+
* pre-indented lines ready to print.
|
|
263
|
+
*/
|
|
264
|
+
function renderDiff(oldContent, newContent, context = 3) {
|
|
265
|
+
const diff = diffLines(oldContent.split('\n'), newContent.split('\n'));
|
|
266
|
+
const keep = new Array(diff.length).fill(false);
|
|
267
|
+
for (let k = 0; k < diff.length; k++) {
|
|
268
|
+
if (diff[k].type === ' ')
|
|
269
|
+
continue;
|
|
270
|
+
const from = Math.max(0, k - context);
|
|
271
|
+
const to = Math.min(diff.length - 1, k + context);
|
|
272
|
+
for (let c = from; c <= to; c++)
|
|
273
|
+
keep[c] = true;
|
|
274
|
+
}
|
|
275
|
+
const lines = [];
|
|
276
|
+
let gapOpen = false;
|
|
277
|
+
for (let k = 0; k < diff.length; k++) {
|
|
278
|
+
if (!keep[k]) {
|
|
279
|
+
if (!gapOpen) {
|
|
280
|
+
lines.push(chalk.gray(' ⋮'));
|
|
281
|
+
gapOpen = true;
|
|
282
|
+
}
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
gapOpen = false;
|
|
286
|
+
const { type, text } = diff[k];
|
|
287
|
+
if (type === '-')
|
|
288
|
+
lines.push(chalk.red(` - ${text}`));
|
|
289
|
+
else if (type === '+')
|
|
290
|
+
lines.push(chalk.green(` + ${text}`));
|
|
291
|
+
else
|
|
292
|
+
lines.push(chalk.gray(` ${text}`));
|
|
293
|
+
}
|
|
294
|
+
return lines;
|
|
295
|
+
}
|
|
214
296
|
/* ------------------------------------------------------------------ */
|
|
215
297
|
/* Render */
|
|
216
298
|
/* ------------------------------------------------------------------ */
|
|
299
|
+
function isPlanEmpty(plan) {
|
|
300
|
+
return (plan.deletions.length === 0 &&
|
|
301
|
+
plan.modifications.length === 0 &&
|
|
302
|
+
plan.envVars.length === 0 &&
|
|
303
|
+
plan.configDir === null);
|
|
304
|
+
}
|
|
217
305
|
function renderPlan(plan) {
|
|
218
306
|
console.log(chalk.bold('\nHomeTrans uninstall plan\n'));
|
|
219
|
-
if (plan
|
|
307
|
+
if (isPlanEmpty(plan)) {
|
|
220
308
|
console.log(chalk.gray(' Nothing to uninstall — no hometrans files found in configured editors.\n'));
|
|
221
309
|
return;
|
|
222
310
|
}
|
|
@@ -231,9 +319,27 @@ function renderPlan(plan) {
|
|
|
231
319
|
console.log(chalk.yellow.bold(` Will be modified (${plan.modifications.length} files):`));
|
|
232
320
|
for (const m of plan.modifications) {
|
|
233
321
|
console.log(` ${chalk.yellow('~')} ${m.display} ${chalk.gray(`(${m.reason})`)}`);
|
|
322
|
+
for (const line of renderDiff(m.oldContent, m.newContent)) {
|
|
323
|
+
console.log(line);
|
|
324
|
+
}
|
|
325
|
+
console.log('');
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (plan.envVars.length > 0) {
|
|
329
|
+
console.log(chalk.red.bold(` Environment variables to remove (${plan.envVars.length}):`));
|
|
330
|
+
console.log(chalk.gray(process.platform === 'win32'
|
|
331
|
+
? ' (Windows: deleted from the per-user environment)'
|
|
332
|
+
: ' (macOS/Linux: the hometrans export block is removed from your shell profile)'));
|
|
333
|
+
for (const name of plan.envVars) {
|
|
334
|
+
console.log(` ${chalk.red('-')} ${name}`);
|
|
234
335
|
}
|
|
235
336
|
console.log('');
|
|
236
337
|
}
|
|
338
|
+
if (plan.configDir) {
|
|
339
|
+
console.log(chalk.red.bold(' Config directory to delete:'));
|
|
340
|
+
console.log(` ${chalk.red('-')} ${prettyHome(plan.configDir)}/`);
|
|
341
|
+
console.log('');
|
|
342
|
+
}
|
|
237
343
|
}
|
|
238
344
|
/* ------------------------------------------------------------------ */
|
|
239
345
|
/* Execute */
|
|
@@ -241,6 +347,7 @@ function renderPlan(plan) {
|
|
|
241
347
|
async function executePlan(plan) {
|
|
242
348
|
let deleted = 0;
|
|
243
349
|
let modified = 0;
|
|
350
|
+
let envNote = null;
|
|
244
351
|
for (const mod of plan.modifications) {
|
|
245
352
|
await fs.writeFile(mod.absPath, mod.newContent, 'utf-8');
|
|
246
353
|
modified++;
|
|
@@ -264,7 +371,20 @@ async function executePlan(plan) {
|
|
|
264
371
|
// best-effort
|
|
265
372
|
}
|
|
266
373
|
}
|
|
267
|
-
|
|
374
|
+
// Remove machine environment variables (names captured from config.json env)
|
|
375
|
+
// before deleting the config directory that holds config.json.
|
|
376
|
+
if (plan.envVars.length > 0) {
|
|
377
|
+
envNote = await removeEnvVars(plan.envVars);
|
|
378
|
+
}
|
|
379
|
+
if (plan.configDir) {
|
|
380
|
+
try {
|
|
381
|
+
await fs.rm(plan.configDir, { recursive: true, force: true });
|
|
382
|
+
}
|
|
383
|
+
catch {
|
|
384
|
+
// best-effort
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return { deleted, modified, envNote };
|
|
268
388
|
}
|
|
269
389
|
/* ------------------------------------------------------------------ */
|
|
270
390
|
/* Entry point */
|
|
@@ -278,17 +398,26 @@ export async function uninstallCommand() {
|
|
|
278
398
|
console.log(chalk.gray(' Reinstall hometrans or manually remove skill/agent directories from your editors.\n'));
|
|
279
399
|
return;
|
|
280
400
|
}
|
|
281
|
-
const { editors } = await loadHomeTransConfig();
|
|
401
|
+
const { editors, env } = await loadHomeTransConfig();
|
|
282
402
|
const plan = {
|
|
283
403
|
deletions: [],
|
|
284
404
|
modifications: [],
|
|
285
405
|
codexRemove: false,
|
|
406
|
+
envVars: [],
|
|
407
|
+
configDir: null,
|
|
286
408
|
};
|
|
287
409
|
for (const editor of editors) {
|
|
288
410
|
await buildPlanForEditor(editor, skillNames, agentEntries, plan);
|
|
289
411
|
}
|
|
412
|
+
// Env vars to remove come from config.json `env`; the ~/.hometrans dir
|
|
413
|
+
// (which holds config.json) is deleted last.
|
|
414
|
+
plan.envVars = plannedEnvVarNames(env);
|
|
415
|
+
const configDir = getConfigDir();
|
|
416
|
+
if (await dirExists(configDir)) {
|
|
417
|
+
plan.configDir = configDir;
|
|
418
|
+
}
|
|
290
419
|
renderPlan(plan);
|
|
291
|
-
if (plan
|
|
420
|
+
if (isPlanEmpty(plan)) {
|
|
292
421
|
return;
|
|
293
422
|
}
|
|
294
423
|
let proceed;
|
|
@@ -317,5 +446,11 @@ export async function uninstallCommand() {
|
|
|
317
446
|
const summary = await executePlan(plan);
|
|
318
447
|
console.log('');
|
|
319
448
|
console.log(chalk.green(` Uninstalled: ${summary.deleted} entries deleted, ${summary.modified} files modified.`));
|
|
449
|
+
if (summary.envNote) {
|
|
450
|
+
console.log(chalk.green(` Environment variables: ${summary.envNote}`));
|
|
451
|
+
}
|
|
452
|
+
if (plan.configDir) {
|
|
453
|
+
console.log(chalk.green(` Removed config directory: ${prettyHome(plan.configDir)}/`));
|
|
454
|
+
}
|
|
320
455
|
console.log('');
|
|
321
456
|
}
|
package/dist/context/index.js
CHANGED
|
@@ -10,38 +10,8 @@ import {
|
|
|
10
10
|
} from "arkanalyzer";
|
|
11
11
|
|
|
12
12
|
// src/cli/config-store.ts
|
|
13
|
-
import fs from "node:fs/promises";
|
|
14
13
|
import path from "node:path";
|
|
15
14
|
import os from "node:os";
|
|
16
|
-
function deriveSdkPaths(devecoSdkHome) {
|
|
17
|
-
const home = devecoSdkHome.trim().replace(/[\\/]+$/, "");
|
|
18
|
-
if (!home) {
|
|
19
|
-
return { DEVECO_SDK_HOME: "", DEVECO_PATH: "", OHOS_SDK_PATH: "", HMS_SDK_PATH: "" };
|
|
20
|
-
}
|
|
21
|
-
return {
|
|
22
|
-
DEVECO_SDK_HOME: home,
|
|
23
|
-
DEVECO_PATH: path.dirname(home),
|
|
24
|
-
OHOS_SDK_PATH: path.join(home, "default", "openharmony", "ets"),
|
|
25
|
-
HMS_SDK_PATH: path.join(home, "default", "hms", "ets")
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
function sdkHomeFromLegacyPaths(env) {
|
|
29
|
-
const tryStrip = (p, suffix) => {
|
|
30
|
-
if (!p) return "";
|
|
31
|
-
const norm = p.replace(/[\\/]+$/, "").split(/[\\/]/);
|
|
32
|
-
if (norm.length <= suffix.length) return "";
|
|
33
|
-
const tail = norm.slice(-suffix.length).map((s) => s.toLowerCase());
|
|
34
|
-
if (tail.join("/") !== suffix.join("/")) return "";
|
|
35
|
-
return norm.slice(0, -suffix.length).join(path.sep);
|
|
36
|
-
};
|
|
37
|
-
return tryStrip(env.OHOS_SDK_PATH, ["default", "openharmony", "ets"]) || tryStrip(env.HMS_SDK_PATH, ["default", "hms", "ets"]);
|
|
38
|
-
}
|
|
39
|
-
function getConfigDir() {
|
|
40
|
-
return path.join(os.homedir(), ".hometrans");
|
|
41
|
-
}
|
|
42
|
-
function getConfigPath() {
|
|
43
|
-
return path.join(getConfigDir(), "config.json");
|
|
44
|
-
}
|
|
45
15
|
function expandHome(p) {
|
|
46
16
|
if (!p) return p;
|
|
47
17
|
if (p === "~") return os.homedir();
|
|
@@ -50,162 +20,6 @@ function expandHome(p) {
|
|
|
50
20
|
}
|
|
51
21
|
return p;
|
|
52
22
|
}
|
|
53
|
-
function defaultEditors() {
|
|
54
|
-
return [
|
|
55
|
-
{
|
|
56
|
-
name: "Claude Code",
|
|
57
|
-
markerDir: "~/.claude",
|
|
58
|
-
skillsDir: "~/.claude/skills",
|
|
59
|
-
agentsDir: "~/.claude/agents",
|
|
60
|
-
mcp: {
|
|
61
|
-
format: "jsonc-object",
|
|
62
|
-
path: "~/.claude.json",
|
|
63
|
-
keyPath: ["mcpServers", "hometrans"]
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
name: "Cursor",
|
|
68
|
-
markerDir: "~/.cursor",
|
|
69
|
-
skillsDir: "~/.cursor/skills",
|
|
70
|
-
agentsDir: "~/.cursor/agents",
|
|
71
|
-
mcp: {
|
|
72
|
-
format: "jsonc-object",
|
|
73
|
-
path: "~/.cursor/mcp.json",
|
|
74
|
-
keyPath: ["mcpServers", "hometrans"]
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
name: "OpenCode",
|
|
79
|
-
markerDir: "~/.config/opencode",
|
|
80
|
-
skillsDir: "~/.config/opencode/skills",
|
|
81
|
-
agentsDir: "~/.config/opencode/agents",
|
|
82
|
-
mcp: {
|
|
83
|
-
format: "jsonc-command-array",
|
|
84
|
-
path: "~/.config/opencode/opencode.json",
|
|
85
|
-
keyPath: ["mcp", "hometrans"]
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
name: "Codex",
|
|
90
|
-
markerDir: "~/.codex",
|
|
91
|
-
// Codex 复用 Agent Skills 公共目录,agent 定义独立。
|
|
92
|
-
skillsDir: "~/.agents/skills",
|
|
93
|
-
agentsDir: "~/.codex/agents",
|
|
94
|
-
mcp: {
|
|
95
|
-
format: "codex-cli",
|
|
96
|
-
path: "~/.codex/config.toml",
|
|
97
|
-
section: "mcp_servers.hometrans"
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
// CodeBuddy(腾讯):与 Claude Code 同构的 .codebuddy/ 目录,
|
|
102
|
-
// 全局安装映射到 ~/.codebuddy/{skills,agents},MCP 走 mcpServers JSON。
|
|
103
|
-
name: "CodeBuddy",
|
|
104
|
-
markerDir: "~/.codebuddy",
|
|
105
|
-
skillsDir: "~/.codebuddy/skills",
|
|
106
|
-
agentsDir: "~/.codebuddy/agents",
|
|
107
|
-
mcp: {
|
|
108
|
-
format: "jsonc-object",
|
|
109
|
-
path: "~/.codebuddy/mcp.json",
|
|
110
|
-
keyPath: ["mcpServers", "hometrans"]
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
];
|
|
114
|
-
}
|
|
115
|
-
async function fileExists(p) {
|
|
116
|
-
try {
|
|
117
|
-
await fs.access(p);
|
|
118
|
-
return true;
|
|
119
|
-
} catch {
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
function defaultEnv() {
|
|
124
|
-
return {
|
|
125
|
-
DEVECO_SDK_HOME: "",
|
|
126
|
-
DEVECO_PATH: "",
|
|
127
|
-
OHOS_SDK_PATH: "",
|
|
128
|
-
HMS_SDK_PATH: "",
|
|
129
|
-
TEST_API_KEY: "",
|
|
130
|
-
GLM_API_KEY: "",
|
|
131
|
-
TOOL_PATH: ""
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
async function loadHomeTransConfig() {
|
|
135
|
-
const configPath = getConfigPath();
|
|
136
|
-
if (!await fileExists(configPath)) {
|
|
137
|
-
const config2 = {
|
|
138
|
-
editors: defaultEditors(),
|
|
139
|
-
env: defaultEnv()
|
|
140
|
-
};
|
|
141
|
-
await fs.mkdir(getConfigDir(), { recursive: true });
|
|
142
|
-
await fs.writeFile(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
|
|
143
|
-
return config2;
|
|
144
|
-
}
|
|
145
|
-
const raw = await fs.readFile(configPath, "utf-8");
|
|
146
|
-
let parsed;
|
|
147
|
-
try {
|
|
148
|
-
parsed = JSON.parse(raw);
|
|
149
|
-
} catch (err) {
|
|
150
|
-
throw new Error(
|
|
151
|
-
`Failed to parse ${configPath}: ${err.message}. Fix the JSON or delete the file to restore defaults.`
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.editors)) {
|
|
155
|
-
throw new Error(
|
|
156
|
-
`Invalid config.json shape at ${configPath}: top-level must be { "editors": [...] }.`
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
const config = parsed;
|
|
160
|
-
const anyParsed = parsed;
|
|
161
|
-
const legacyParams = anyParsed.params ?? anyParsed.sdkPaths;
|
|
162
|
-
const legacyToolPath = typeof anyParsed.tool_path === "string" ? anyParsed.tool_path : void 0;
|
|
163
|
-
config.env = {
|
|
164
|
-
...defaultEnv(),
|
|
165
|
-
...legacyParams ?? {},
|
|
166
|
-
...config.env ?? {}
|
|
167
|
-
};
|
|
168
|
-
if (legacyToolPath && !config.env.TOOL_PATH) {
|
|
169
|
-
config.env.TOOL_PATH = legacyToolPath;
|
|
170
|
-
}
|
|
171
|
-
delete anyParsed.sdkPaths;
|
|
172
|
-
delete anyParsed.params;
|
|
173
|
-
delete anyParsed.tool_path;
|
|
174
|
-
let envDirty = false;
|
|
175
|
-
if (!config.env.DEVECO_SDK_HOME) {
|
|
176
|
-
const migrated = sdkHomeFromLegacyPaths(config.env);
|
|
177
|
-
if (migrated) {
|
|
178
|
-
config.env.DEVECO_SDK_HOME = migrated;
|
|
179
|
-
envDirty = true;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
if (config.env.DEVECO_SDK_HOME) {
|
|
183
|
-
const derived = deriveSdkPaths(config.env.DEVECO_SDK_HOME);
|
|
184
|
-
for (const key of ["DEVECO_PATH", "OHOS_SDK_PATH", "HMS_SDK_PATH"]) {
|
|
185
|
-
if (!config.env[key]) {
|
|
186
|
-
config.env[key] = derived[key];
|
|
187
|
-
envDirty = true;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
if (envDirty) {
|
|
192
|
-
await saveHomeTransConfig(config);
|
|
193
|
-
}
|
|
194
|
-
const existingNames = new Set(config.editors.map((e) => e.name));
|
|
195
|
-
const missingEditors = defaultEditors().filter(
|
|
196
|
-
(e) => !existingNames.has(e.name)
|
|
197
|
-
);
|
|
198
|
-
if (missingEditors.length > 0) {
|
|
199
|
-
config.editors.push(...missingEditors);
|
|
200
|
-
await saveHomeTransConfig(config);
|
|
201
|
-
}
|
|
202
|
-
return config;
|
|
203
|
-
}
|
|
204
|
-
async function saveHomeTransConfig(config) {
|
|
205
|
-
const configPath = getConfigPath();
|
|
206
|
-
await fs.mkdir(getConfigDir(), { recursive: true });
|
|
207
|
-
await fs.writeFile(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
208
|
-
}
|
|
209
23
|
|
|
210
24
|
// src/context/analysis/ArkTsGitInfoAnalysis.ts
|
|
211
25
|
import {
|
|
@@ -218,12 +32,12 @@ import {
|
|
|
218
32
|
parseJsonText
|
|
219
33
|
} from "arkanalyzer";
|
|
220
34
|
import path3 from "path";
|
|
221
|
-
import
|
|
35
|
+
import fs2 from "fs";
|
|
222
36
|
|
|
223
37
|
// src/context/utils/util.ts
|
|
224
38
|
import LoggerMod, { LOG_MODULE_TYPE } from "arkanalyzer/lib/utils/logger.js";
|
|
225
39
|
import path2 from "path";
|
|
226
|
-
import
|
|
40
|
+
import fs from "fs";
|
|
227
41
|
var Logger = LoggerMod.default ?? LoggerMod;
|
|
228
42
|
var logger = Logger.getLogger(LOG_MODULE_TYPE.DEFAULT, "util");
|
|
229
43
|
function safePush(target, source, maxBatchSize = 1e4) {
|
|
@@ -233,21 +47,21 @@ function safePush(target, source, maxBatchSize = 1e4) {
|
|
|
233
47
|
}
|
|
234
48
|
}
|
|
235
49
|
function getAllFiles(dirPath, exts, filenameArr = [], visited = /* @__PURE__ */ new Set()) {
|
|
236
|
-
if (!
|
|
50
|
+
if (!fs.existsSync(dirPath)) {
|
|
237
51
|
logger.error(`'${dirPath}' is not exist, please check!`);
|
|
238
52
|
return filenameArr;
|
|
239
53
|
}
|
|
240
|
-
const realSrc =
|
|
54
|
+
const realSrc = fs.realpathSync(dirPath);
|
|
241
55
|
if (visited.has(realSrc)) {
|
|
242
56
|
return filenameArr;
|
|
243
57
|
}
|
|
244
58
|
visited.add(realSrc);
|
|
245
|
-
|
|
59
|
+
fs.readdirSync(realSrc).forEach((fileName) => {
|
|
246
60
|
if (shouldSkipFile(fileName)) {
|
|
247
61
|
return;
|
|
248
62
|
}
|
|
249
63
|
const realFile = path2.resolve(realSrc, fileName);
|
|
250
|
-
if (
|
|
64
|
+
if (fs.statSync(realFile).isDirectory()) {
|
|
251
65
|
getAllFiles(realFile, exts, filenameArr, visited);
|
|
252
66
|
} else {
|
|
253
67
|
if (exts.length === 0) {
|
|
@@ -442,7 +256,7 @@ var ArkTsGitInfoAnalysis = class {
|
|
|
442
256
|
const jsonItems = [];
|
|
443
257
|
const results = getAllFiles(resourcePath, [fileName]);
|
|
444
258
|
for (const result of results) {
|
|
445
|
-
const configText =
|
|
259
|
+
const configText = fs2.readFileSync(result, "utf8");
|
|
446
260
|
const json = parseJsonText(configText);
|
|
447
261
|
jsonItems.push({ path: result, content: json });
|
|
448
262
|
}
|
|
@@ -779,12 +593,11 @@ function loadSdks(ohosSdkPath, hmsSdkPath) {
|
|
|
779
593
|
async function extractCommitContext(input) {
|
|
780
594
|
const { projectPath, commitId } = input;
|
|
781
595
|
const mode = input.mode ?? "default";
|
|
782
|
-
const config = await loadHomeTransConfig();
|
|
783
596
|
const ohosSdkPath = expandHome(
|
|
784
|
-
input.ohosSdkPath ??
|
|
597
|
+
input.ohosSdkPath ?? process.env.OHOS_SDK_PATH ?? ""
|
|
785
598
|
);
|
|
786
599
|
const hmsSdkPath = expandHome(
|
|
787
|
-
input.hmsSdkPath ??
|
|
600
|
+
input.hmsSdkPath ?? process.env.HMS_SDK_PATH ?? ""
|
|
788
601
|
);
|
|
789
602
|
if (!projectPath) {
|
|
790
603
|
throw new Error("extractCommitContext: projectPath is required");
|
|
@@ -794,7 +607,7 @@ async function extractCommitContext(input) {
|
|
|
794
607
|
}
|
|
795
608
|
if (!ohosSdkPath && !hmsSdkPath) {
|
|
796
609
|
throw new Error(
|
|
797
|
-
"extractCommitContext:
|
|
610
|
+
"extractCommitContext: OHOS_SDK_PATH / HMS_SDK_PATH not found in the OS environment. Run `ht init` to set them as machine environment variables (and open a new terminal), or pass ohosSdkPath / hmsSdkPath as tool input (e.g. D:\\DevEco Studio\\sdk\\default\\openharmony\\ets)."
|
|
798
611
|
);
|
|
799
612
|
}
|
|
800
613
|
console.error(
|