@haaaiawd/anws 2.3.0 → 2.4.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.
- package/README.md +1 -1
- package/bin/cli.js +53 -23
- package/lib/diff.js +5 -2
- package/lib/init.js +217 -96
- package/lib/install-state.js +18 -3
- package/lib/manifest.js +364 -79
- package/lib/prompt.js +68 -0
- package/lib/resources/index.js +36 -2
- package/lib/update.js +12 -6
- package/package.json +48 -47
- package/templates/.agents/skills/anws-system/SKILL.md +107 -105
- package/templates/.agents/skills/code-reviewer/SKILL.md +171 -115
- package/templates/.agents/skills/concept-modeler/SKILL.md +230 -179
- package/templates/.agents/skills/craft-authoring/SKILL.md +186 -183
- package/templates/.agents/skills/craft-authoring/references/BUNDLE_POLICY.md +42 -0
- package/templates/.agents/skills/design-reviewer/SKILL.md +265 -190
- package/templates/.agents/skills/e2e-testing-guide/SKILL.md +246 -135
- package/templates/.agents/skills/nexus-mapper/SKILL.md +321 -321
- package/templates/.agents/skills/nexus-mapper/references/probe-protocol.md +1 -1
- package/templates/.agents/skills/nexus-query/SKILL.md +1 -1
- package/templates/.agents/skills/output-contract/SKILL.md +37 -0
- package/templates/.agents/skills/runtime-inspector/SKILL.md +150 -99
- package/templates/.agents/skills/sequential-thinking/SKILL.md +222 -225
- package/templates/.agents/skills/spec-writer/SKILL.md +75 -30
- package/templates/.agents/skills/system-architect/SKILL.md +538 -678
- package/templates/.agents/skills/system-designer/SKILL.md +124 -537
- package/templates/.agents/skills/task-planner/SKILL.md +1 -2
- package/templates/.agents/skills/task-planner/references/TASK_TEMPLATE_05A.md +2 -2
- package/templates/.agents/skills/task-reviewer/SKILL.md +421 -386
- package/templates/.agents/skills/tech-evaluator/SKILL.md +252 -144
- package/templates/.agents/workflows/blueprint.md +156 -68
- package/templates/.agents/workflows/challenge.md +322 -494
- package/templates/.agents/workflows/change.md +182 -339
- package/templates/.agents/workflows/craft.md +159 -197
- package/templates/.agents/workflows/design-system.md +202 -674
- package/templates/.agents/workflows/explore.md +187 -399
- package/templates/.agents/workflows/forge.md +650 -609
- package/templates/.agents/workflows/genesis.md +438 -351
- package/templates/.agents/workflows/probe.md +215 -240
- package/templates/.agents/workflows/quickstart.md +304 -123
- package/templates/.agents/workflows/upgrade.md +145 -182
- package/templates_en/.agents/skills/anws-system/SKILL.md +110 -0
- package/templates_en/.agents/skills/code-reviewer/SKILL.md +171 -0
- package/templates_en/.agents/skills/concept-modeler/SKILL.md +230 -0
- package/templates_en/.agents/skills/craft-authoring/SKILL.md +179 -0
- package/templates_en/.agents/skills/craft-authoring/references/BUNDLE_POLICY.md +42 -0
- package/templates_en/.agents/skills/craft-authoring/references/PROMPT_QUALITY_RUBRIC.md +92 -0
- package/templates_en/.agents/skills/craft-authoring/references/SCORECARD_TEMPLATE.md +52 -0
- package/templates_en/.agents/skills/design-reviewer/SKILL.md +264 -0
- package/templates_en/.agents/skills/e2e-testing-guide/SKILL.md +246 -0
- package/templates_en/.agents/skills/nexus-mapper/SKILL.md +306 -0
- package/templates_en/.agents/skills/nexus-mapper/references/language-customization.md +167 -0
- package/templates_en/.agents/skills/nexus-mapper/references/output-schema.md +311 -0
- package/templates_en/.agents/skills/nexus-mapper/references/probe-protocol.md +246 -0
- package/templates_en/.agents/skills/nexus-mapper/scripts/extract_ast.py +706 -0
- package/templates_en/.agents/skills/nexus-mapper/scripts/git_detective.py +194 -0
- package/templates_en/.agents/skills/nexus-mapper/scripts/languages.json +127 -0
- package/templates_en/.agents/skills/nexus-mapper/scripts/query_graph.py +556 -0
- package/templates_en/.agents/skills/nexus-mapper/scripts/requirements.txt +6 -0
- package/templates_en/.agents/skills/nexus-query/SKILL.md +114 -0
- package/templates_en/.agents/skills/nexus-query/scripts/extract_ast.py +706 -0
- package/templates_en/.agents/skills/nexus-query/scripts/git_detective.py +194 -0
- package/templates_en/.agents/skills/nexus-query/scripts/languages.json +127 -0
- package/templates_en/.agents/skills/nexus-query/scripts/query_graph.py +556 -0
- package/templates_en/.agents/skills/nexus-query/scripts/requirements.txt +6 -0
- package/templates_en/.agents/skills/output-contract/SKILL.md +37 -0
- package/templates_en/.agents/skills/runtime-inspector/SKILL.md +150 -0
- package/templates_en/.agents/skills/sequential-thinking/SKILL.md +214 -0
- package/templates_en/.agents/skills/spec-writer/SKILL.md +153 -0
- package/templates_en/.agents/skills/spec-writer/references/prd_template.md +177 -0
- package/templates_en/.agents/skills/system-architect/SKILL.md +538 -0
- package/templates_en/.agents/skills/system-architect/references/rfc_template.md +59 -0
- package/templates_en/.agents/skills/system-designer/SKILL.md +188 -0
- package/templates_en/.agents/skills/system-designer/references/system-design-detail-template.md +187 -0
- package/templates_en/.agents/skills/system-designer/references/system-design-template.md +605 -0
- package/templates_en/.agents/skills/task-planner/SKILL.md +251 -0
- package/templates_en/.agents/skills/task-planner/references/TASK_TEMPLATE_05A.md +109 -0
- package/templates_en/.agents/skills/task-planner/references/TASK_TEMPLATE_05B.md +176 -0
- package/templates_en/.agents/skills/task-reviewer/SKILL.md +422 -0
- package/templates_en/.agents/skills/tech-evaluator/SKILL.md +252 -0
- package/templates_en/.agents/skills/tech-evaluator/references/ADR_TEMPLATE.md +78 -0
- package/templates_en/.agents/workflows/blueprint.md +200 -0
- package/templates_en/.agents/workflows/challenge.md +326 -0
- package/templates_en/.agents/workflows/change.md +182 -0
- package/templates_en/.agents/workflows/craft.md +159 -0
- package/templates_en/.agents/workflows/design-system.md +202 -0
- package/templates_en/.agents/workflows/explore.md +187 -0
- package/templates_en/.agents/workflows/forge.md +651 -0
- package/templates_en/.agents/workflows/genesis.md +438 -0
- package/templates_en/.agents/workflows/probe.md +215 -0
- package/templates_en/.agents/workflows/quickstart.md +305 -0
- package/templates_en/.agents/workflows/upgrade.md +145 -0
- package/templates_en/AGENTS.md +149 -0
- package/templates/.agents/skills/report-template/SKILL.md +0 -92
- package/templates/.agents/skills/report-template/references/REPORT_TEMPLATE.md +0 -100
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<img src="assets/logo-cli.png" width="260" alt="Anws">
|
|
5
5
|
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
|
-
[](https://github.com/Haaaiawd/ANWS/releases)
|
|
8
8
|
[](https://github.com/Haaaiawd/ANWS)
|
|
9
9
|
|
|
10
10
|
[English](./README.md) | [中文](./README_CN.md)
|
package/bin/cli.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
"use strict";
|
|
3
3
|
|
|
4
|
-
const { parseArgs } = require(
|
|
5
|
-
const path = require(
|
|
6
|
-
const { listTargets, getTarget } = require(
|
|
7
|
-
const { blank, error, info, logo } = require(
|
|
4
|
+
const { parseArgs } = require("node:util");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
const { listTargets, getTarget } = require("../lib/adapters");
|
|
7
|
+
const { blank, error, info, logo } = require("../lib/output");
|
|
8
8
|
|
|
9
9
|
// ─── 版本号从 package.json 读取 ─────────────────────────────────────────────
|
|
10
|
-
const { version } = require(path.join(__dirname,
|
|
10
|
+
const { version } = require(path.join(__dirname, "..", "package.json"));
|
|
11
11
|
const TARGET_IDS = listTargets().map((target) => target.id);
|
|
12
12
|
|
|
13
13
|
// ─── 帮助文本 ─────────────────────────────────────────────────────────────────
|
|
@@ -17,12 +17,24 @@ USAGE
|
|
|
17
17
|
|
|
18
18
|
COMMANDS
|
|
19
19
|
init Install one or more target AI IDE workflow projections
|
|
20
|
-
|
|
20
|
+
Init skips a target if its installedVersion equals the current CLI version
|
|
21
|
+
(since v2.4.1). Run update to refresh templates instead.
|
|
22
|
+
update One-click update: scan install-lock or directory layout and refresh templates
|
|
23
|
+
Preserves the templateLocale recorded in install-lock. Generates a changelog.
|
|
21
24
|
|
|
22
25
|
OPTIONS
|
|
23
26
|
-v, --version Print version number
|
|
24
27
|
-h, --help Show this help message
|
|
25
|
-
--
|
|
28
|
+
-y, --yes Auto-confirm overwrite prompts (non-interactive)
|
|
29
|
+
--target Target AI IDE(s) for init, comma-separated (${TARGET_IDS.join(", ")})
|
|
30
|
+
--locale Template bundle: zh (templates/) or en (templates_en/)
|
|
31
|
+
Default: zh; interactive init prompts after IDE selection
|
|
32
|
+
Update preserves the locale recorded in install-lock
|
|
33
|
+
|
|
34
|
+
INIT VS UPDATE
|
|
35
|
+
Use init for first-time install or adding a new target IDE.
|
|
36
|
+
Use update when the CLI package has been upgraded and you want to refresh
|
|
37
|
+
templates without changing target selection or locale.
|
|
26
38
|
|
|
27
39
|
SUPPORTED TARGETS
|
|
28
40
|
windsurf workflows + skills
|
|
@@ -37,20 +49,22 @@ SUPPORTED TARGETS
|
|
|
37
49
|
kilo workflows + skills
|
|
38
50
|
|
|
39
51
|
EXAMPLES
|
|
40
|
-
anws init #
|
|
52
|
+
anws init # Interactive: choose targets, then locale
|
|
41
53
|
anws init --target windsurf,codex,opencode
|
|
42
|
-
anws
|
|
54
|
+
anws init --target windsurf --locale en -y
|
|
55
|
+
anws update # Refresh all matched targets from install-lock
|
|
43
56
|
`.trimStart();
|
|
44
57
|
|
|
45
58
|
// ─── 参数解析 ─────────────────────────────────────────────────────────────────
|
|
46
59
|
const { values, positionals } = parseArgs({
|
|
47
60
|
args: process.argv.slice(2),
|
|
48
61
|
options: {
|
|
49
|
-
version: { type:
|
|
50
|
-
help:
|
|
51
|
-
yes:
|
|
52
|
-
target:
|
|
53
|
-
|
|
62
|
+
version: { type: "boolean", short: "v", default: false },
|
|
63
|
+
help: { type: "boolean", short: "h", default: false },
|
|
64
|
+
yes: { type: "boolean", short: "y", default: false },
|
|
65
|
+
target: { type: "string" },
|
|
66
|
+
locale: { type: "string" },
|
|
67
|
+
check: { type: "boolean", default: false },
|
|
54
68
|
},
|
|
55
69
|
strict: false,
|
|
56
70
|
allowPositionals: true,
|
|
@@ -60,8 +74,20 @@ if (values.yes) {
|
|
|
60
74
|
global.__ANWS_FORCE_YES = true;
|
|
61
75
|
}
|
|
62
76
|
|
|
77
|
+
if (values.locale !== undefined) {
|
|
78
|
+
const loc = String(values.locale).trim().toLowerCase();
|
|
79
|
+
if (loc !== "zh" && loc !== "en") {
|
|
80
|
+
error("--locale must be zh or en");
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
global.__ANWS_TEMPLATE_LOCALE = loc;
|
|
84
|
+
}
|
|
85
|
+
|
|
63
86
|
if (values.target !== undefined) {
|
|
64
|
-
const targetIds = values.target
|
|
87
|
+
const targetIds = values.target
|
|
88
|
+
.split(",")
|
|
89
|
+
.map((item) => item.trim())
|
|
90
|
+
.filter(Boolean);
|
|
65
91
|
targetIds.forEach((targetId) => getTarget(targetId));
|
|
66
92
|
global.__ANWS_TARGET_IDS = Array.from(new Set(targetIds));
|
|
67
93
|
}
|
|
@@ -83,25 +109,29 @@ async function main() {
|
|
|
83
109
|
const command = positionals[0];
|
|
84
110
|
|
|
85
111
|
switch (command) {
|
|
86
|
-
case
|
|
87
|
-
await require(
|
|
112
|
+
case "init":
|
|
113
|
+
await require("../lib/init")();
|
|
88
114
|
break;
|
|
89
115
|
|
|
90
|
-
case
|
|
116
|
+
case "update":
|
|
91
117
|
if (values.target !== undefined) {
|
|
92
|
-
error(
|
|
118
|
+
error(
|
|
119
|
+
"`anws update --target` has been removed. Use `anws update` to update all matched targets.",
|
|
120
|
+
);
|
|
93
121
|
process.exit(1);
|
|
94
122
|
}
|
|
95
123
|
if (values.check) {
|
|
96
|
-
error(
|
|
124
|
+
error(
|
|
125
|
+
"`anws update --check` has been removed. Use `anws update` directly.",
|
|
126
|
+
);
|
|
97
127
|
process.exit(1);
|
|
98
128
|
}
|
|
99
|
-
await require(
|
|
129
|
+
await require("../lib/update")();
|
|
100
130
|
break;
|
|
101
131
|
|
|
102
132
|
default:
|
|
103
133
|
error(`Unknown command: "${command}"`);
|
|
104
|
-
info(
|
|
134
|
+
info("Run `anws --help` to see available commands.");
|
|
105
135
|
process.exit(1);
|
|
106
136
|
}
|
|
107
137
|
}
|
package/lib/diff.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const fs = require('node:fs/promises');
|
|
4
4
|
const path = require('node:path');
|
|
5
5
|
const { c } = require('./output');
|
|
6
|
+
const { resolveCanonicalPath } = require('./resources');
|
|
6
7
|
|
|
7
8
|
async function pathExists(targetPath) {
|
|
8
9
|
return fs.access(targetPath).then(() => true).catch(() => false);
|
|
@@ -127,9 +128,11 @@ async function collectManagedFileDiffs({
|
|
|
127
128
|
projectionEntries = [],
|
|
128
129
|
srcAgents,
|
|
129
130
|
shouldWriteRootAgents,
|
|
130
|
-
agentsUpdatePlan = null
|
|
131
|
+
agentsUpdatePlan = null,
|
|
132
|
+
resolveCanonicalPath: resolveCanonicalPathFn = null
|
|
131
133
|
}) {
|
|
132
134
|
const results = [];
|
|
135
|
+
const resolveSrc = resolveCanonicalPathFn || ((rel) => resolveCanonicalPath(rel, 'zh'));
|
|
133
136
|
const normalizedProjectionEntries = projectionEntries.length > 0
|
|
134
137
|
? projectionEntries
|
|
135
138
|
: projectionPlan.flatMap((item) => item.projectionEntries || []);
|
|
@@ -164,7 +167,7 @@ async function collectManagedFileDiffs({
|
|
|
164
167
|
};
|
|
165
168
|
const srcPath = rel === 'AGENTS.md'
|
|
166
169
|
? srcAgents
|
|
167
|
-
:
|
|
170
|
+
: resolveSrc(entry.source);
|
|
168
171
|
|
|
169
172
|
if (rel !== 'AGENTS.md' && !(await pathExists(srcPath))) {
|
|
170
173
|
throw new Error(
|
package/lib/init.js
CHANGED
|
@@ -1,16 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const path = require(
|
|
4
|
-
const fs = require(
|
|
5
|
-
const { buildProjectionPlan } = require(
|
|
6
|
-
const { getTarget, listTargets } = require(
|
|
7
|
-
const {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const {
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const path = require("node:path");
|
|
4
|
+
const fs = require("node:fs/promises");
|
|
5
|
+
const { buildProjectionPlan } = require("./manifest");
|
|
6
|
+
const { getTarget, listTargets } = require("./adapters");
|
|
7
|
+
const {
|
|
8
|
+
planAgentsUpdate,
|
|
9
|
+
resolveAgentsInstall,
|
|
10
|
+
printLegacyMigrationWarning,
|
|
11
|
+
pathExists,
|
|
12
|
+
} = require("./agents");
|
|
13
|
+
const { ensureChangelogDir } = require("./changelog");
|
|
14
|
+
const { resolveCanonicalPath, resolveRootAgentsPath } = require("./resources");
|
|
15
|
+
const { writeTargetFiles } = require("./copy");
|
|
16
|
+
const {
|
|
17
|
+
createInstallLock,
|
|
18
|
+
dedupeTargets,
|
|
19
|
+
detectInstallState,
|
|
20
|
+
summarizeTargetState,
|
|
21
|
+
writeInstallLock,
|
|
22
|
+
} = require("./install-state");
|
|
23
|
+
const { selectMultiple, selectRadio, confirm } = require("./prompt");
|
|
24
|
+
const {
|
|
25
|
+
success,
|
|
26
|
+
warn,
|
|
27
|
+
info,
|
|
28
|
+
fileLine,
|
|
29
|
+
skippedLine,
|
|
30
|
+
blank,
|
|
31
|
+
logo,
|
|
32
|
+
section,
|
|
33
|
+
} = require("./output");
|
|
14
34
|
|
|
15
35
|
async function init() {
|
|
16
36
|
const cwd = process.cwd();
|
|
@@ -18,18 +38,30 @@ async function init() {
|
|
|
18
38
|
const installState = await detectInstallState(cwd);
|
|
19
39
|
const retainedTargetIds = await resolveRetainedTargetIds(cwd, installState);
|
|
20
40
|
const targets = await selectTargets(installState, retainedTargetIds);
|
|
41
|
+
const templateLocale = await resolveTemplateLocaleForInit(installState);
|
|
21
42
|
const targetIds = Array.from(new Set(targets.map((item) => item.id)));
|
|
22
43
|
const targetPlans = buildProjectionPlan(targetIds);
|
|
23
|
-
const srcAgents =
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
44
|
+
const srcAgents = resolveRootAgentsPath(templateLocale);
|
|
45
|
+
const resolveCanonicalSource = (relPath) =>
|
|
46
|
+
resolveCanonicalPath(relPath, templateLocale);
|
|
47
|
+
const cliVersion = require(
|
|
48
|
+
path.join(__dirname, "..", "package.json"),
|
|
49
|
+
).version;
|
|
50
|
+
|
|
51
|
+
info("Initializing Anws...");
|
|
52
|
+
info(`Target IDEs: ${targets.map((item) => item.label).join(", ")}`);
|
|
53
|
+
info(
|
|
54
|
+
`Template locale: ${templateLocale} (${templateLocale === "en" ? "templates_en/" : "templates/"})`,
|
|
55
|
+
);
|
|
28
56
|
if (installState.needsFallback) {
|
|
29
|
-
info(
|
|
57
|
+
info(
|
|
58
|
+
"Install lock missing or unreadable. Falling back to scanned target state.",
|
|
59
|
+
);
|
|
30
60
|
}
|
|
31
61
|
if (installState.drift.hasDrift) {
|
|
32
|
-
warn(
|
|
62
|
+
warn(
|
|
63
|
+
`Detected install-state drift. Missing on disk: ${installState.drift.missingOnDisk.join(", ") || "none"}; untracked on disk: ${installState.drift.untrackedOnDisk.join(", ") || "none"}.`,
|
|
64
|
+
);
|
|
33
65
|
}
|
|
34
66
|
blank();
|
|
35
67
|
|
|
@@ -42,30 +74,51 @@ async function init() {
|
|
|
42
74
|
for (const targetPlan of targetPlans) {
|
|
43
75
|
const target = getTarget(targetPlan.targetId);
|
|
44
76
|
const targetAlreadyInstalled = retainedTargetIds.includes(target.id);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
77
|
+
|
|
78
|
+
// Skip re-init of the same target at the same CLI version
|
|
79
|
+
const existingTarget = installState.lockResult.lock?.targets?.find(
|
|
80
|
+
(t) => t.targetId === target.id,
|
|
81
|
+
);
|
|
82
|
+
if (
|
|
83
|
+
targetAlreadyInstalled &&
|
|
84
|
+
existingTarget?.installedVersion === cliVersion
|
|
85
|
+
) {
|
|
86
|
+
info(
|
|
87
|
+
`${target.label} already installed at v${cliVersion}. Skipping — run \`anws update\` to refresh templates.`,
|
|
88
|
+
);
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const rootAgentsExists = await pathExists(path.join(cwd, "AGENTS.md"));
|
|
93
|
+
const agentsDecision =
|
|
94
|
+
target.id === "antigravity"
|
|
95
|
+
? await resolveAgentsInstall({
|
|
96
|
+
cwd,
|
|
97
|
+
askMigrate,
|
|
98
|
+
forceYes: !!global.__ANWS_FORCE_YES,
|
|
99
|
+
})
|
|
100
|
+
: {
|
|
101
|
+
shouldWriteRootAgents: true,
|
|
102
|
+
shouldWarnMigration: false,
|
|
103
|
+
rootExists: rootAgentsExists,
|
|
104
|
+
};
|
|
57
105
|
|
|
58
106
|
let agentsUpdatePlan = null;
|
|
59
107
|
if (agentsDecision.shouldWriteRootAgents && agentsDecision.rootExists) {
|
|
60
|
-
const templateContent = await fs.readFile(srcAgents,
|
|
61
|
-
const existingContent = await fs.readFile(
|
|
108
|
+
const templateContent = await fs.readFile(srcAgents, "utf8");
|
|
109
|
+
const existingContent = await fs.readFile(
|
|
110
|
+
path.join(cwd, "AGENTS.md"),
|
|
111
|
+
"utf8",
|
|
112
|
+
);
|
|
62
113
|
agentsUpdatePlan = planAgentsUpdate({ templateContent, existingContent });
|
|
63
114
|
}
|
|
64
115
|
|
|
65
116
|
const conflicting = await findConflicts(
|
|
66
117
|
cwd,
|
|
67
|
-
targetAlreadyInstalled
|
|
68
|
-
|
|
118
|
+
targetAlreadyInstalled
|
|
119
|
+
? []
|
|
120
|
+
: targetPlan.managedFiles.filter((rel) => rel !== "AGENTS.md"),
|
|
121
|
+
sessionWrittenFiles,
|
|
69
122
|
);
|
|
70
123
|
if (conflicting.length > 0) {
|
|
71
124
|
const confirmed = await askOverwrite(conflicting.length, target.label);
|
|
@@ -74,7 +127,7 @@ async function init() {
|
|
|
74
127
|
failedTargets.push({
|
|
75
128
|
targetId: target.id,
|
|
76
129
|
targetLabel: target.label,
|
|
77
|
-
reason: `Skipped ${conflicting.length} conflicting managed file(s)
|
|
130
|
+
reason: `Skipped ${conflicting.length} conflicting managed file(s)`,
|
|
78
131
|
});
|
|
79
132
|
continue;
|
|
80
133
|
}
|
|
@@ -86,7 +139,7 @@ async function init() {
|
|
|
86
139
|
srcAgents,
|
|
87
140
|
shouldWriteRootAgents: agentsDecision.shouldWriteRootAgents,
|
|
88
141
|
agentsUpdatePlan,
|
|
89
|
-
resolveCanonicalSource
|
|
142
|
+
resolveCanonicalSource,
|
|
90
143
|
});
|
|
91
144
|
|
|
92
145
|
written.push(...result.written);
|
|
@@ -103,37 +156,56 @@ async function init() {
|
|
|
103
156
|
|
|
104
157
|
await ensureChangelogDir(cwd);
|
|
105
158
|
const existingTargets = installState.lockResult.lock?.targets || [];
|
|
159
|
+
const mergedTargets = dedupeTargets([
|
|
160
|
+
...existingTargets,
|
|
161
|
+
...successfulTargets,
|
|
162
|
+
]);
|
|
163
|
+
const priorTemplateLocale = installState.lockResult.lock?.templateLocale;
|
|
164
|
+
const effectiveTemplateLocale =
|
|
165
|
+
written.length === 0 && priorTemplateLocale
|
|
166
|
+
? priorTemplateLocale
|
|
167
|
+
: templateLocale;
|
|
106
168
|
const generatedAt = new Date().toISOString();
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
169
|
+
|
|
170
|
+
if (mergedTargets.length > 0) {
|
|
171
|
+
await writeInstallLock(
|
|
172
|
+
cwd,
|
|
173
|
+
createInstallLock({
|
|
174
|
+
cliVersion,
|
|
175
|
+
generatedAt,
|
|
176
|
+
templateLocale: effectiveTemplateLocale,
|
|
177
|
+
targets: mergedTargets,
|
|
178
|
+
lastUpdateSummary: {
|
|
179
|
+
successfulTargets: successfulTargets.map((item) => item.targetId),
|
|
180
|
+
failedTargets: failedTargets.map((item) => item.targetId),
|
|
181
|
+
updatedAt: generatedAt,
|
|
182
|
+
},
|
|
183
|
+
}),
|
|
184
|
+
);
|
|
185
|
+
} else {
|
|
186
|
+
warn(
|
|
187
|
+
"Install-lock was not written: no targets were installed and no prior lock targets to retain.",
|
|
188
|
+
);
|
|
189
|
+
}
|
|
120
190
|
|
|
121
191
|
printTargetSummary(successfulTargets, failedTargets);
|
|
122
192
|
|
|
123
193
|
for (const rel of written) {
|
|
124
|
-
fileLine(rel.replace(/\\/g,
|
|
194
|
+
fileLine(rel.replace(/\\/g, "/"));
|
|
125
195
|
}
|
|
126
196
|
|
|
127
197
|
if (skipped.length > 0) {
|
|
128
198
|
blank();
|
|
129
|
-
info(
|
|
199
|
+
info("Skipped (project-specific, preserved):");
|
|
130
200
|
for (const rel of skipped) {
|
|
131
|
-
skippedLine(rel.replace(/\\/g,
|
|
201
|
+
skippedLine(rel.replace(/\\/g, "/"));
|
|
132
202
|
}
|
|
133
203
|
}
|
|
134
204
|
|
|
135
205
|
blank();
|
|
136
|
-
success(
|
|
206
|
+
success(
|
|
207
|
+
`Done! ${written.length} files written for ${successfulTargets.map((item) => item.targetLabel).join(", ") || "selected targets"}.`,
|
|
208
|
+
);
|
|
137
209
|
printNextSteps(targets);
|
|
138
210
|
}
|
|
139
211
|
|
|
@@ -143,7 +215,11 @@ async function init() {
|
|
|
143
215
|
* 找出 cwd 中已存在的托管文件列表。
|
|
144
216
|
* @returns {Promise<string[]>} 已存在的托管文件相对路径数组
|
|
145
217
|
*/
|
|
146
|
-
async function findConflicts(
|
|
218
|
+
async function findConflicts(
|
|
219
|
+
cwd,
|
|
220
|
+
managedFiles,
|
|
221
|
+
sessionWrittenFiles = new Set(),
|
|
222
|
+
) {
|
|
147
223
|
const conflicts = [];
|
|
148
224
|
for (const rel of managedFiles) {
|
|
149
225
|
if (sessionWrittenFiles.has(rel)) {
|
|
@@ -165,15 +241,17 @@ async function askOverwrite(count, label) {
|
|
|
165
241
|
if (global.__ANWS_FORCE_YES) return true;
|
|
166
242
|
|
|
167
243
|
if (!process.stdin.isTTY) {
|
|
168
|
-
warn(
|
|
244
|
+
warn(
|
|
245
|
+
`${count} managed file(s) already exist. Non-TTY: skipping overwrite.`,
|
|
246
|
+
);
|
|
169
247
|
return false;
|
|
170
248
|
}
|
|
171
249
|
|
|
172
250
|
return confirm({
|
|
173
251
|
message: `Overwrite ${count} managed file(s) for ${label}?`,
|
|
174
|
-
confirmLabel:
|
|
175
|
-
cancelLabel:
|
|
176
|
-
defaultValue: false
|
|
252
|
+
confirmLabel: "Overwrite",
|
|
253
|
+
cancelLabel: "Skip",
|
|
254
|
+
defaultValue: false,
|
|
177
255
|
});
|
|
178
256
|
}
|
|
179
257
|
|
|
@@ -185,10 +263,10 @@ async function askMigrate() {
|
|
|
185
263
|
}
|
|
186
264
|
|
|
187
265
|
return confirm({
|
|
188
|
-
message:
|
|
189
|
-
confirmLabel:
|
|
190
|
-
cancelLabel:
|
|
191
|
-
defaultValue: false
|
|
266
|
+
message: "Legacy .agent/ directory detected. Migrate to .agents/?",
|
|
267
|
+
confirmLabel: "Migrate",
|
|
268
|
+
cancelLabel: "Keep legacy",
|
|
269
|
+
defaultValue: false,
|
|
192
270
|
});
|
|
193
271
|
}
|
|
194
272
|
|
|
@@ -199,41 +277,71 @@ async function askMigrate() {
|
|
|
199
277
|
* @param {string} action
|
|
200
278
|
*/
|
|
201
279
|
function printSummary(files, skipped = [], action) {
|
|
202
|
-
const verb = action ===
|
|
280
|
+
const verb = action === "updated" ? "Updating" : "Writing";
|
|
203
281
|
blank();
|
|
204
282
|
info(`${verb} files...`);
|
|
205
283
|
blank();
|
|
206
284
|
for (const rel of files) {
|
|
207
|
-
fileLine(rel.replace(/\\/g,
|
|
285
|
+
fileLine(rel.replace(/\\/g, "/"));
|
|
208
286
|
}
|
|
209
287
|
if (skipped.length > 0) {
|
|
210
288
|
blank();
|
|
211
|
-
info(
|
|
289
|
+
info("Skipped (project-specific, preserved):");
|
|
212
290
|
for (const rel of skipped) {
|
|
213
|
-
skippedLine(rel.replace(/\\/g,
|
|
291
|
+
skippedLine(rel.replace(/\\/g, "/"));
|
|
214
292
|
}
|
|
215
293
|
}
|
|
216
294
|
blank();
|
|
217
|
-
success(
|
|
218
|
-
|
|
219
|
-
|
|
295
|
+
success(
|
|
296
|
+
`Done! ${files.length} file(s) ${action}${skipped.length > 0 ? `, ${skipped.length} skipped` : ""}.`,
|
|
297
|
+
);
|
|
298
|
+
if (action === "updated") {
|
|
299
|
+
info("Managed files have been updated to the latest version.");
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async function resolveTemplateLocaleForInit(installState) {
|
|
304
|
+
if (
|
|
305
|
+
global.__ANWS_TEMPLATE_LOCALE === "zh" ||
|
|
306
|
+
global.__ANWS_TEMPLATE_LOCALE === "en"
|
|
307
|
+
) {
|
|
308
|
+
return global.__ANWS_TEMPLATE_LOCALE;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
let fromLock = "zh";
|
|
312
|
+
if (installState.lockResult.lock) {
|
|
313
|
+
fromLock = installState.lockResult.lock.templateLocale || "zh";
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (!process.stdin.isTTY) {
|
|
317
|
+
return fromLock === "en" ? "en" : "zh";
|
|
220
318
|
}
|
|
319
|
+
|
|
320
|
+
const initialIndex = fromLock === "en" ? 1 : 0;
|
|
321
|
+
return selectRadio({
|
|
322
|
+
message:
|
|
323
|
+
"Workflow template bundle (manifest paths are the same; text is zh or en):",
|
|
324
|
+
options: [
|
|
325
|
+
{ label: "中文 (templates/)", value: "zh" },
|
|
326
|
+
{ label: "English (templates_en/)", value: "en" },
|
|
327
|
+
],
|
|
328
|
+
initialIndex,
|
|
329
|
+
});
|
|
221
330
|
}
|
|
222
331
|
|
|
223
332
|
async function selectTargets(installState, retainedTargetIds = []) {
|
|
224
333
|
const installedTargetIds = new Set(retainedTargetIds);
|
|
225
334
|
|
|
226
335
|
if (global.__ANWS_TARGET_IDS && global.__ANWS_TARGET_IDS.length > 0) {
|
|
227
|
-
return Array.from(
|
|
228
|
-
...retainedTargetIds,
|
|
229
|
-
|
|
230
|
-
])).map((targetId) => getTarget(targetId));
|
|
336
|
+
return Array.from(
|
|
337
|
+
new Set([...retainedTargetIds, ...global.__ANWS_TARGET_IDS]),
|
|
338
|
+
).map((targetId) => getTarget(targetId));
|
|
231
339
|
}
|
|
232
340
|
|
|
233
341
|
if (!process.stdin.isTTY) {
|
|
234
342
|
return retainedTargetIds.length > 0
|
|
235
343
|
? retainedTargetIds.map((targetId) => getTarget(targetId))
|
|
236
|
-
: [getTarget(
|
|
344
|
+
: [getTarget("antigravity")];
|
|
237
345
|
}
|
|
238
346
|
|
|
239
347
|
const targets = listTargets();
|
|
@@ -248,22 +356,26 @@ async function selectTargets(installState, retainedTargetIds = []) {
|
|
|
248
356
|
}
|
|
249
357
|
|
|
250
358
|
if (initialSelectedIndexes.length === 0) {
|
|
251
|
-
const antigravityIndex = targets.findIndex(
|
|
359
|
+
const antigravityIndex = targets.findIndex(
|
|
360
|
+
(target) => target.id === "antigravity",
|
|
361
|
+
);
|
|
252
362
|
if (antigravityIndex >= 0) {
|
|
253
363
|
initialSelectedIndexes.push(antigravityIndex);
|
|
254
364
|
}
|
|
255
365
|
}
|
|
256
366
|
|
|
257
367
|
return selectMultiple({
|
|
258
|
-
message:
|
|
368
|
+
message: "Choose your target AI IDEs:",
|
|
259
369
|
options: targets.map((target) => ({
|
|
260
370
|
label: target.label,
|
|
261
371
|
value: target.id,
|
|
262
|
-
locked: installedTargetIds.has(target.id)
|
|
372
|
+
locked: installedTargetIds.has(target.id),
|
|
263
373
|
})),
|
|
264
374
|
initialSelectedIndexes,
|
|
265
|
-
lockedIndexes
|
|
266
|
-
}).then((selectedOptions) =>
|
|
375
|
+
lockedIndexes,
|
|
376
|
+
}).then((selectedOptions) =>
|
|
377
|
+
selectedOptions.map((option) => getTarget(option.value)),
|
|
378
|
+
);
|
|
267
379
|
}
|
|
268
380
|
|
|
269
381
|
async function resolveRetainedTargetIds(cwd, installState) {
|
|
@@ -275,14 +387,16 @@ async function resolveRetainedTargetIds(cwd, installState) {
|
|
|
275
387
|
|
|
276
388
|
for (const targetId of installState.selectedTargets) {
|
|
277
389
|
const [targetPlan] = buildProjectionPlan([targetId]);
|
|
278
|
-
const managedFiles = (targetPlan?.managedFiles || []).filter(
|
|
390
|
+
const managedFiles = (targetPlan?.managedFiles || []).filter(
|
|
391
|
+
(rel) => rel !== "AGENTS.md",
|
|
392
|
+
);
|
|
279
393
|
if (managedFiles.length === 0) {
|
|
280
394
|
retainedTargetIds.push(targetId);
|
|
281
395
|
continue;
|
|
282
396
|
}
|
|
283
397
|
|
|
284
398
|
const managedExists = await Promise.all(
|
|
285
|
-
managedFiles.map((rel) => pathExists(path.join(cwd, rel)))
|
|
399
|
+
managedFiles.map((rel) => pathExists(path.join(cwd, rel))),
|
|
286
400
|
);
|
|
287
401
|
|
|
288
402
|
if (managedExists.every(Boolean)) {
|
|
@@ -295,24 +409,31 @@ async function resolveRetainedTargetIds(cwd, installState) {
|
|
|
295
409
|
|
|
296
410
|
function printNextSteps(targets) {
|
|
297
411
|
blank();
|
|
298
|
-
section(
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
412
|
+
section(
|
|
413
|
+
"Next steps",
|
|
414
|
+
targets.some((target) => target.rootAgentFile)
|
|
415
|
+
? [
|
|
416
|
+
"1. Read AGENTS.md to understand the system",
|
|
417
|
+
"2. Run /quickstart in your AI assistant to analyze and start the workflow",
|
|
418
|
+
]
|
|
419
|
+
: [
|
|
420
|
+
"1. Review files written under the selected target directories",
|
|
421
|
+
"2. Run /quickstart in your AI assistant to analyze and start the workflow",
|
|
422
|
+
],
|
|
423
|
+
);
|
|
307
424
|
}
|
|
308
425
|
|
|
309
426
|
function printTargetSummary(successfulTargets, failedTargets) {
|
|
310
427
|
blank();
|
|
311
|
-
section(
|
|
312
|
-
...successfulTargets.map(
|
|
313
|
-
|
|
428
|
+
section("Target summary", [
|
|
429
|
+
...successfulTargets.map(
|
|
430
|
+
(target) => `✔ ${target.targetLabel} (${target.targetId})`,
|
|
431
|
+
),
|
|
432
|
+
...failedTargets.map(
|
|
433
|
+
(target) =>
|
|
434
|
+
`✖ ${target.targetLabel} (${target.targetId}) — ${target.reason}`,
|
|
435
|
+
),
|
|
314
436
|
]);
|
|
315
437
|
}
|
|
316
438
|
|
|
317
439
|
module.exports = init;
|
|
318
|
-
|