ai-project-manage-cli 8.1.6 → 8.1.7
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 +2 -0
- package/dist/index.js +89 -22
- package/dist/worker-script.js +181 -98
- package/package.json +1 -1
- package/template/AGENTS.webide.md +2 -2
- package/template/rules/webide_merge.md +12 -4
package/README.md
CHANGED
|
@@ -39,6 +39,8 @@ apm connect
|
|
|
39
39
|
apm connect --server https://your-server.com
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
+
启动前会检测 npm registry 上当前大版本的最新包;若落后则先 `npm install -g` 更新,再以新版本重新连接。跨大版本请手动执行 `apm update --major`。
|
|
43
|
+
|
|
42
44
|
同一时刻仅允许一个 connect。
|
|
43
45
|
|
|
44
46
|
`apm connect` 处理完 WebIDE 消息后,会将 `.apm/project/<项目ID>/` 下的项目文档变更推回平台。
|
package/dist/index.js
CHANGED
|
@@ -324,6 +324,14 @@ var requestConfig = {
|
|
|
324
324
|
method: "PUT",
|
|
325
325
|
path: "/cli/webide/plan"
|
|
326
326
|
}),
|
|
327
|
+
webideUpsertChecklist: defineEndpoint({
|
|
328
|
+
method: "PUT",
|
|
329
|
+
path: "/cli/webide/checklist"
|
|
330
|
+
}),
|
|
331
|
+
webideGetChecklist: defineEndpoint({
|
|
332
|
+
method: "GET",
|
|
333
|
+
path: "/cli/webide/checklist"
|
|
334
|
+
}),
|
|
327
335
|
webideReplaceTestCases: defineEndpoint({
|
|
328
336
|
method: "PUT",
|
|
329
337
|
path: "/cli/webide/test-cases"
|
|
@@ -512,6 +520,8 @@ async function runLogin(opts) {
|
|
|
512
520
|
|
|
513
521
|
// src/commands/update.ts
|
|
514
522
|
import { spawnSync } from "child_process";
|
|
523
|
+
import { existsSync as existsSync2 } from "fs";
|
|
524
|
+
import { join as join4 } from "path";
|
|
515
525
|
|
|
516
526
|
// src/version.ts
|
|
517
527
|
import { readFileSync as readFileSync2 } from "fs";
|
|
@@ -530,6 +540,7 @@ function readCliVersion() {
|
|
|
530
540
|
}
|
|
531
541
|
|
|
532
542
|
// src/commands/update.ts
|
|
543
|
+
var APM_SKIP_SELF_UPDATE_ENV = "APM_SKIP_SELF_UPDATE";
|
|
533
544
|
var useNpmShell = process.platform === "win32";
|
|
534
545
|
function runNpm(args, options = {}) {
|
|
535
546
|
return spawnSync(useNpmShell ? "npm.cmd" : "npm", args, {
|
|
@@ -622,10 +633,17 @@ function npmAvailable() {
|
|
|
622
633
|
return !r.error && r.status === 0;
|
|
623
634
|
}
|
|
624
635
|
async function runUpdate(options = {}) {
|
|
636
|
+
if (process.env[APM_SKIP_SELF_UPDATE_ENV] === "1") {
|
|
637
|
+
return { didUpdate: false };
|
|
638
|
+
}
|
|
625
639
|
const current = readCliVersion();
|
|
626
640
|
const currentMajor = parseMajorVersion(current);
|
|
627
641
|
const globalLatest = await fetchLatestPublishedVersion();
|
|
628
642
|
const latestInMajor = options.allowMajorUpgrade ? null : await fetchLatestPublishedVersionInMajor(currentMajor);
|
|
643
|
+
if (options.quietIfCurrent && !options.allowMajorUpgrade && !latestInMajor && !globalLatest) {
|
|
644
|
+
console.warn(`[apm] \u65E0\u6CD5\u68C0\u6D4B\u6700\u65B0\u7248\u672C\uFF0C\u7EE7\u7EED\u4F7F\u7528\u5F53\u524D ${current}`);
|
|
645
|
+
return { didUpdate: false };
|
|
646
|
+
}
|
|
629
647
|
const resolved = resolveUpdateTarget({
|
|
630
648
|
current,
|
|
631
649
|
allowMajorUpgrade: options.allowMajorUpgrade,
|
|
@@ -633,8 +651,10 @@ async function runUpdate(options = {}) {
|
|
|
633
651
|
globalLatest
|
|
634
652
|
});
|
|
635
653
|
if (resolved.action === "skip") {
|
|
636
|
-
|
|
637
|
-
|
|
654
|
+
if (!options.quietIfCurrent) {
|
|
655
|
+
console.log(`[apm] \u5DF2\u662F\u6700\u65B0\u7248\u672C ${current}`);
|
|
656
|
+
}
|
|
657
|
+
return { didUpdate: false };
|
|
638
658
|
}
|
|
639
659
|
if (resolved.majorUpgradeAvailable) {
|
|
640
660
|
console.log(
|
|
@@ -671,14 +691,57 @@ async function runUpdate(options = {}) {
|
|
|
671
691
|
} else {
|
|
672
692
|
console.log(`[apm] \u5DF2\u662F\u6700\u65B0\u7248\u672C ${current}`);
|
|
673
693
|
}
|
|
694
|
+
return { didUpdate: expectedBump };
|
|
695
|
+
}
|
|
696
|
+
function resolveApmEntryPath(entryArg = process.argv[1]) {
|
|
697
|
+
const npmResult = runNpm(["root", "-g"], {
|
|
698
|
+
encoding: "utf8",
|
|
699
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
700
|
+
});
|
|
701
|
+
if (npmResult.status === 0) {
|
|
702
|
+
const globalRoot = npmResult.stdout?.toString().trim();
|
|
703
|
+
if (globalRoot) {
|
|
704
|
+
const candidate = join4(globalRoot, CLI_PACKAGE_NAME, "dist", "index.js");
|
|
705
|
+
if (existsSync2(candidate)) {
|
|
706
|
+
return candidate;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
const fromArgv = entryArg?.trim();
|
|
711
|
+
if (fromArgv && existsSync2(fromArgv)) {
|
|
712
|
+
return fromArgv;
|
|
713
|
+
}
|
|
714
|
+
if (fromArgv) {
|
|
715
|
+
return fromArgv;
|
|
716
|
+
}
|
|
717
|
+
console.error("[apm] \u65E0\u6CD5\u89E3\u6790 apm \u5165\u53E3\u8DEF\u5F84");
|
|
718
|
+
process.exit(1);
|
|
719
|
+
}
|
|
720
|
+
function reexecConnectAfterUpdate(options) {
|
|
721
|
+
console.log("[apm] \u66F4\u65B0\u5B8C\u6210\uFF0C\u6B63\u5728\u4EE5\u65B0\u7248\u672C\u91CD\u65B0\u8FDE\u63A5\u2026");
|
|
722
|
+
const apmScript = resolveApmEntryPath();
|
|
723
|
+
const args = [apmScript, "connect"];
|
|
724
|
+
const server = options.server?.trim();
|
|
725
|
+
if (server) {
|
|
726
|
+
args.push("--server", server);
|
|
727
|
+
}
|
|
728
|
+
const result = spawnSync(process.execPath, args, {
|
|
729
|
+
stdio: "inherit",
|
|
730
|
+
env: { ...process.env, [APM_SKIP_SELF_UPDATE_ENV]: "1" }
|
|
731
|
+
});
|
|
732
|
+
if (result.error) {
|
|
733
|
+
console.error("[apm] \u91CD\u542F connect \u5931\u8D25:", result.error.message);
|
|
734
|
+
process.exit(1);
|
|
735
|
+
}
|
|
736
|
+
process.exit(result.status ?? 0);
|
|
674
737
|
}
|
|
675
738
|
|
|
676
739
|
// src/commands/update-skills.ts
|
|
677
|
-
import { existsSync as
|
|
740
|
+
import { existsSync as existsSync3, statSync as statSync2 } from "fs";
|
|
678
741
|
async function syncWorkspaceSkills(workdir) {
|
|
679
742
|
const apmDir = workspaceApmDir(workdir);
|
|
680
743
|
const fsApmDir = toFsPath(apmDir);
|
|
681
|
-
if (!
|
|
744
|
+
if (!existsSync3(fsApmDir)) {
|
|
682
745
|
throw new Error("[apm] \u672A\u627E\u5230 .apm \u76EE\u5F55\uFF0C\u8BF7\u5148\u6267\u884C apm init");
|
|
683
746
|
}
|
|
684
747
|
const apmStat = statSync2(fsApmDir);
|
|
@@ -690,7 +753,7 @@ async function syncWorkspaceSkills(workdir) {
|
|
|
690
753
|
}
|
|
691
754
|
async function runUpdateSkills() {
|
|
692
755
|
const apmDir = workspaceApmDir();
|
|
693
|
-
if (!
|
|
756
|
+
if (!existsSync3(apmDir)) {
|
|
694
757
|
console.error("[apm] \u672A\u627E\u5230 .apm \u76EE\u5F55\uFF0C\u8BF7\u5148\u6267\u884C apm init");
|
|
695
758
|
process.exit(1);
|
|
696
759
|
}
|
|
@@ -703,14 +766,14 @@ async function runUpdateSkills() {
|
|
|
703
766
|
|
|
704
767
|
// src/utils/project-documents.ts
|
|
705
768
|
import {
|
|
706
|
-
existsSync as
|
|
769
|
+
existsSync as existsSync4,
|
|
707
770
|
readdirSync as readdirSync2,
|
|
708
771
|
readFileSync as readFileSync3,
|
|
709
772
|
rmSync,
|
|
710
773
|
writeFileSync as writeFileSync2
|
|
711
774
|
} from "fs";
|
|
712
775
|
import { createHash } from "crypto";
|
|
713
|
-
import { dirname as dirname3, join as
|
|
776
|
+
import { dirname as dirname3, join as join5, relative, sep } from "path";
|
|
714
777
|
|
|
715
778
|
// src/utils/git.ts
|
|
716
779
|
import { execFile as execFile2 } from "child_process";
|
|
@@ -784,11 +847,11 @@ function normalizeProjectIdForPath(projectId) {
|
|
|
784
847
|
}
|
|
785
848
|
function projectDocumentsDir(apmRoot, projectId) {
|
|
786
849
|
const id = normalizeProjectIdForPath(projectId);
|
|
787
|
-
return
|
|
850
|
+
return join5(apmRoot ?? workspaceApmDir(), "project", id);
|
|
788
851
|
}
|
|
789
852
|
function projectDocumentLocalPath(apmRoot, projectId, documentPath) {
|
|
790
853
|
const normalized = normalizeLocalDocumentPath(documentPath);
|
|
791
|
-
return
|
|
854
|
+
return join5(
|
|
792
855
|
projectDocumentsDir(apmRoot, projectId),
|
|
793
856
|
...normalized.split("/")
|
|
794
857
|
);
|
|
@@ -808,11 +871,11 @@ function hashLocalFileContent(content) {
|
|
|
808
871
|
return createHash("sha256").update(content, "utf8").digest("hex");
|
|
809
872
|
}
|
|
810
873
|
function readLocalManifest(apmRoot, projectId) {
|
|
811
|
-
const manifestPath =
|
|
874
|
+
const manifestPath = join5(
|
|
812
875
|
projectDocumentsDir(apmRoot, projectId),
|
|
813
876
|
MANIFEST_FILE
|
|
814
877
|
);
|
|
815
|
-
if (!
|
|
878
|
+
if (!existsSync4(manifestPath)) {
|
|
816
879
|
return null;
|
|
817
880
|
}
|
|
818
881
|
try {
|
|
@@ -825,13 +888,13 @@ function readLocalManifest(apmRoot, projectId) {
|
|
|
825
888
|
}
|
|
826
889
|
function listLocalDocumentPaths(apmRoot, projectId) {
|
|
827
890
|
const root = projectDocumentsDir(apmRoot, projectId);
|
|
828
|
-
if (!
|
|
891
|
+
if (!existsSync4(root)) {
|
|
829
892
|
return [];
|
|
830
893
|
}
|
|
831
894
|
const paths = [];
|
|
832
895
|
const walk = (dir) => {
|
|
833
896
|
for (const entry of readdirSync2(dir, { withFileTypes: true })) {
|
|
834
|
-
const abs =
|
|
897
|
+
const abs = join5(dir, entry.name);
|
|
835
898
|
if (entry.isDirectory()) {
|
|
836
899
|
walk(abs);
|
|
837
900
|
continue;
|
|
@@ -960,13 +1023,13 @@ ${diagnostic ?? ""}`);
|
|
|
960
1023
|
const absPath = toFsPath(
|
|
961
1024
|
projectDocumentLocalPath(targetApmDir, projectId, path)
|
|
962
1025
|
);
|
|
963
|
-
if (
|
|
1026
|
+
if (existsSync4(absPath)) {
|
|
964
1027
|
rmSync(absPath, { force: true });
|
|
965
1028
|
deleted += 1;
|
|
966
1029
|
}
|
|
967
1030
|
}
|
|
968
1031
|
writeFileSync2(
|
|
969
|
-
toFsPath(
|
|
1032
|
+
toFsPath(join5(docsDir, MANIFEST_FILE)),
|
|
970
1033
|
`${JSON.stringify(remoteManifest, null, 2)}
|
|
971
1034
|
`,
|
|
972
1035
|
"utf8"
|
|
@@ -1284,7 +1347,7 @@ function handleCancelAction(payload, ctx) {
|
|
|
1284
1347
|
}
|
|
1285
1348
|
|
|
1286
1349
|
// src/commands/connect/core/worker/worker.ts
|
|
1287
|
-
import { dirname as dirname4, join as
|
|
1350
|
+
import { dirname as dirname4, join as join6 } from "path";
|
|
1288
1351
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1289
1352
|
import { Worker } from "node:worker_threads";
|
|
1290
1353
|
|
|
@@ -1310,7 +1373,7 @@ function resolveWebIdeWorkerHeapMb(env = process.env, totalMemoryBytes = totalme
|
|
|
1310
1373
|
}
|
|
1311
1374
|
|
|
1312
1375
|
// src/commands/connect/core/worker/worker.ts
|
|
1313
|
-
var workerFile =
|
|
1376
|
+
var workerFile = join6(
|
|
1314
1377
|
dirname4(fileURLToPath3(import.meta.url)),
|
|
1315
1378
|
"worker-script.js"
|
|
1316
1379
|
);
|
|
@@ -1663,14 +1726,14 @@ function dispatchConnectAction(payload, ctx) {
|
|
|
1663
1726
|
|
|
1664
1727
|
// src/commands/connect-lock.ts
|
|
1665
1728
|
import {
|
|
1666
|
-
existsSync as
|
|
1729
|
+
existsSync as existsSync5,
|
|
1667
1730
|
mkdirSync as mkdirSync3,
|
|
1668
1731
|
readFileSync as readFileSync4,
|
|
1669
1732
|
unlinkSync,
|
|
1670
1733
|
writeFileSync as writeFileSync3
|
|
1671
1734
|
} from "fs";
|
|
1672
|
-
import { join as
|
|
1673
|
-
var CONNECT_LOCK_PATH =
|
|
1735
|
+
import { join as join7 } from "path";
|
|
1736
|
+
var CONNECT_LOCK_PATH = join7(APM_CONFIG_DIR, "connect.lock");
|
|
1674
1737
|
function isProcessAlive(pid) {
|
|
1675
1738
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
1676
1739
|
try {
|
|
@@ -1681,7 +1744,7 @@ function isProcessAlive(pid) {
|
|
|
1681
1744
|
}
|
|
1682
1745
|
}
|
|
1683
1746
|
function readConnectLock() {
|
|
1684
|
-
if (!
|
|
1747
|
+
if (!existsSync5(CONNECT_LOCK_PATH)) return null;
|
|
1685
1748
|
try {
|
|
1686
1749
|
const raw = readFileSync4(CONNECT_LOCK_PATH, "utf8");
|
|
1687
1750
|
const parsed = JSON.parse(raw);
|
|
@@ -1847,6 +1910,10 @@ function resolveConnectServerOption(options) {
|
|
|
1847
1910
|
return void 0;
|
|
1848
1911
|
}
|
|
1849
1912
|
async function runConnect(options) {
|
|
1913
|
+
const { didUpdate } = await runUpdate({ quietIfCurrent: true });
|
|
1914
|
+
if (didUpdate) {
|
|
1915
|
+
reexecConnectAfterUpdate(options);
|
|
1916
|
+
}
|
|
1850
1917
|
const cfg = await ensureLoggedConfig();
|
|
1851
1918
|
const serverOverride = resolveConnectServerOption(options);
|
|
1852
1919
|
if (serverOverride) {
|
|
@@ -1973,7 +2040,7 @@ function buildProgram() {
|
|
|
1973
2040
|
await runSyncProjectDocuments(opts);
|
|
1974
2041
|
});
|
|
1975
2042
|
program.command("connect").description(
|
|
1976
|
-
"\u8FDE\u63A5\
|
|
2043
|
+
"\u8FDE\u63A5\u524D\u68C0\u6D4B\u5E76\u66F4\u65B0\u5230\u5F53\u524D\u5927\u7248\u672C\u6700\u65B0 CLI\uFF0C\u518D\u8FDE\u63A5\u5E73\u53F0 WebSocket\uFF08/ws/agent\uFF09"
|
|
1977
2044
|
).option("--server <url>", "API \u6839\u5730\u5740\uFF0C\u8986\u76D6 config \u4E2D\u7684 baseUrl").action(async (opts) => {
|
|
1978
2045
|
await runConnect({ server: opts.server });
|
|
1979
2046
|
});
|
package/dist/worker-script.js
CHANGED
|
@@ -72,6 +72,14 @@ var requestConfig = {
|
|
|
72
72
|
method: "PUT",
|
|
73
73
|
path: "/cli/webide/plan"
|
|
74
74
|
}),
|
|
75
|
+
webideUpsertChecklist: defineEndpoint({
|
|
76
|
+
method: "PUT",
|
|
77
|
+
path: "/cli/webide/checklist"
|
|
78
|
+
}),
|
|
79
|
+
webideGetChecklist: defineEndpoint({
|
|
80
|
+
method: "GET",
|
|
81
|
+
path: "/cli/webide/checklist"
|
|
82
|
+
}),
|
|
75
83
|
webideReplaceTestCases: defineEndpoint({
|
|
76
84
|
method: "PUT",
|
|
77
85
|
path: "/cli/webide/test-cases"
|
|
@@ -1499,7 +1507,7 @@ function createMergeWebIdePullRequestsTool(options) {
|
|
|
1499
1507
|
const { webideMergePullRequests } = options;
|
|
1500
1508
|
return {
|
|
1501
1509
|
MergeWebIdePullRequests: {
|
|
1502
|
-
description: "Merge all open pull requests for this WebIDE task.
|
|
1510
|
+
description: "Merge all open pull requests for this WebIDE task. During accept, call UpsertWebIdeChecklist first with the full acceptance checklist, then call this once with confirmedConflictFree=true. No baseline sync is required before merging.",
|
|
1503
1511
|
inputSchema: {
|
|
1504
1512
|
type: "object",
|
|
1505
1513
|
properties: {
|
|
@@ -1586,6 +1594,63 @@ function createUpsertWebIdePlanTool(options) {
|
|
|
1586
1594
|
}
|
|
1587
1595
|
};
|
|
1588
1596
|
}
|
|
1597
|
+
function createUpsertWebIdeChecklistTool(options) {
|
|
1598
|
+
const { webideUpsertChecklist } = options;
|
|
1599
|
+
return {
|
|
1600
|
+
UpsertWebIdeChecklist: {
|
|
1601
|
+
description: "Persist or replace the acceptance checklist markdown for this WebIDE task. Call with the full checklist (what changed, which repos/files, how to verify) before merging PRs. Use during accept so humans can review later.",
|
|
1602
|
+
inputSchema: {
|
|
1603
|
+
type: "object",
|
|
1604
|
+
properties: {
|
|
1605
|
+
content: {
|
|
1606
|
+
type: "string",
|
|
1607
|
+
description: "Full acceptance checklist in Markdown (Chinese): summary of code changes, scope by repo, key files, verification notes"
|
|
1608
|
+
}
|
|
1609
|
+
},
|
|
1610
|
+
required: ["content"]
|
|
1611
|
+
},
|
|
1612
|
+
execute: async (args) => {
|
|
1613
|
+
const content = asString(args.content);
|
|
1614
|
+
if (!content) {
|
|
1615
|
+
throw new Error("UpsertWebIdeChecklist \u7F3A\u5C11 content");
|
|
1616
|
+
}
|
|
1617
|
+
await webideUpsertChecklist({ content });
|
|
1618
|
+
return JSON.stringify({ ok: true, chars: content.length }, null, 2);
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
};
|
|
1622
|
+
}
|
|
1623
|
+
function createGetWebIdeChecklistTool(options) {
|
|
1624
|
+
const { boundTaskId, webideGetChecklist } = options;
|
|
1625
|
+
return {
|
|
1626
|
+
GetWebIdeChecklist: {
|
|
1627
|
+
description: "Fetch the acceptance checklist markdown for a WebIDE task by taskId. Returns content=null if none has been written yet. Use when you need to read or revise an existing checklist.",
|
|
1628
|
+
inputSchema: {
|
|
1629
|
+
type: "object",
|
|
1630
|
+
properties: {
|
|
1631
|
+
taskId: {
|
|
1632
|
+
type: "string",
|
|
1633
|
+
description: "WebIDE task id whose checklist to load"
|
|
1634
|
+
}
|
|
1635
|
+
},
|
|
1636
|
+
required: ["taskId"]
|
|
1637
|
+
},
|
|
1638
|
+
execute: async (args) => {
|
|
1639
|
+
const taskId = asString(args.taskId);
|
|
1640
|
+
if (!taskId) {
|
|
1641
|
+
throw new Error("GetWebIdeChecklist \u7F3A\u5C11 taskId");
|
|
1642
|
+
}
|
|
1643
|
+
if (taskId !== boundTaskId) {
|
|
1644
|
+
throw new Error(
|
|
1645
|
+
`GetWebIdeChecklist \u7684 taskId \u987B\u4E3A\u5F53\u524D\u4EFB\u52A1 ${boundTaskId}`
|
|
1646
|
+
);
|
|
1647
|
+
}
|
|
1648
|
+
const result = await webideGetChecklist({ taskId });
|
|
1649
|
+
return JSON.stringify(result, null, 2);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
};
|
|
1653
|
+
}
|
|
1589
1654
|
|
|
1590
1655
|
// src/commands/connect/tools/webide-test-case-tools.ts
|
|
1591
1656
|
function asString2(value) {
|
|
@@ -1618,7 +1683,7 @@ function createUpsertWebIdeTestCasesTool(options) {
|
|
|
1618
1683
|
const { webideReplaceTestCases } = options;
|
|
1619
1684
|
return {
|
|
1620
1685
|
UpsertWebIdeTestCases: {
|
|
1621
|
-
description: "Persist generated automated test cases for this WebIDE task (full replace)
|
|
1686
|
+
description: "Persist generated automated test cases for this WebIDE task (full replace). Call once with the complete case list after reviewing the task and code changes. Does not change workflow phase.",
|
|
1622
1687
|
inputSchema: {
|
|
1623
1688
|
type: "object",
|
|
1624
1689
|
properties: {
|
|
@@ -2364,6 +2429,23 @@ function createCursorCustomTools(cfg2, options) {
|
|
|
2364
2429
|
})
|
|
2365
2430
|
);
|
|
2366
2431
|
}
|
|
2432
|
+
if (wantsTool("UpsertWebIdeChecklist", options, enablePlan)) {
|
|
2433
|
+
Object.assign(
|
|
2434
|
+
tools,
|
|
2435
|
+
createUpsertWebIdeChecklistTool({
|
|
2436
|
+
webideUpsertChecklist: (args) => cli.webideUpsertChecklist({ taskId, ...args })
|
|
2437
|
+
})
|
|
2438
|
+
);
|
|
2439
|
+
}
|
|
2440
|
+
if (wantsTool("GetWebIdeChecklist", options, enablePlan)) {
|
|
2441
|
+
Object.assign(
|
|
2442
|
+
tools,
|
|
2443
|
+
createGetWebIdeChecklistTool({
|
|
2444
|
+
boundTaskId: taskId,
|
|
2445
|
+
webideGetChecklist: (args) => cli.webideGetChecklist(args)
|
|
2446
|
+
})
|
|
2447
|
+
);
|
|
2448
|
+
}
|
|
2367
2449
|
if (wantsTool("UpsertWebIdeTestCases", options, enablePlan)) {
|
|
2368
2450
|
Object.assign(
|
|
2369
2451
|
tools,
|
|
@@ -4145,100 +4227,6 @@ async function cleanWebIdeWorkspaceCache(taskId, workdir, cfg2) {
|
|
|
4145
4227
|
}
|
|
4146
4228
|
}
|
|
4147
4229
|
|
|
4148
|
-
// src/commands/connect/webide-run-action.ts
|
|
4149
|
-
function startActionForInbound(action) {
|
|
4150
|
-
switch (action) {
|
|
4151
|
-
case "request-assessment":
|
|
4152
|
-
return "start-assessment";
|
|
4153
|
-
case "request-design":
|
|
4154
|
-
case "request-revise-design":
|
|
4155
|
-
return "start-design";
|
|
4156
|
-
case "request-write-plan":
|
|
4157
|
-
case "request-revise-plan":
|
|
4158
|
-
return "start-write-plan";
|
|
4159
|
-
case "request-develop":
|
|
4160
|
-
case "skip-plan":
|
|
4161
|
-
return "start-develop";
|
|
4162
|
-
case "request-start-project":
|
|
4163
|
-
return "start-project";
|
|
4164
|
-
case "request-execute-sql":
|
|
4165
|
-
return "start-execute-sql";
|
|
4166
|
-
case "request-bugfix":
|
|
4167
|
-
return "start-bugfix";
|
|
4168
|
-
case "request-organize-code":
|
|
4169
|
-
case "request-patch":
|
|
4170
|
-
return "start-organize-code";
|
|
4171
|
-
case "request-accept":
|
|
4172
|
-
return "start-accept";
|
|
4173
|
-
default:
|
|
4174
|
-
return null;
|
|
4175
|
-
}
|
|
4176
|
-
}
|
|
4177
|
-
function completeActionForInbound(action) {
|
|
4178
|
-
switch (action) {
|
|
4179
|
-
case "request-assessment":
|
|
4180
|
-
case "confirm-assumptions":
|
|
4181
|
-
return "complete-assessment";
|
|
4182
|
-
case "request-design":
|
|
4183
|
-
case "request-revise-design":
|
|
4184
|
-
return "complete-design";
|
|
4185
|
-
case "request-write-plan":
|
|
4186
|
-
case "request-revise-plan":
|
|
4187
|
-
return "complete-write-plan";
|
|
4188
|
-
case "request-develop":
|
|
4189
|
-
case "skip-plan":
|
|
4190
|
-
return "complete-develop";
|
|
4191
|
-
case "request-start-project":
|
|
4192
|
-
return "complete-project";
|
|
4193
|
-
case "request-execute-sql":
|
|
4194
|
-
return "complete-execute-sql";
|
|
4195
|
-
case "request-bugfix":
|
|
4196
|
-
return "complete-bugfix";
|
|
4197
|
-
case "request-organize-code":
|
|
4198
|
-
case "request-patch":
|
|
4199
|
-
return "complete-organize-code";
|
|
4200
|
-
case "request-accept":
|
|
4201
|
-
return "complete-accept";
|
|
4202
|
-
default:
|
|
4203
|
-
return null;
|
|
4204
|
-
}
|
|
4205
|
-
}
|
|
4206
|
-
async function webIdeRunAction(cfg2, taskId, action, params) {
|
|
4207
|
-
const api = createApmApiClient(cfg2);
|
|
4208
|
-
await api.cli.webideRunAction({ taskId, action, params });
|
|
4209
|
-
console.log(`[apm] webide runAction ok action=${action} taskId=${taskId}`);
|
|
4210
|
-
}
|
|
4211
|
-
async function webIdeSyncTransitionPrepEvents(cfg2, taskId, startAction, prepEvents) {
|
|
4212
|
-
try {
|
|
4213
|
-
const api = createApmApiClient(cfg2);
|
|
4214
|
-
await api.cli.webideUpdateTransitionPrepEvents({
|
|
4215
|
-
taskId,
|
|
4216
|
-
startAction,
|
|
4217
|
-
prepEvents
|
|
4218
|
-
});
|
|
4219
|
-
} catch (err) {
|
|
4220
|
-
console.warn(
|
|
4221
|
-
`[apm] sync transition prepEvents failed taskId=${taskId}:`,
|
|
4222
|
-
err instanceof Error ? err.message : err
|
|
4223
|
-
);
|
|
4224
|
-
}
|
|
4225
|
-
}
|
|
4226
|
-
async function webIdeDiscardTransitionPrepDraft(cfg2, taskId, startAction) {
|
|
4227
|
-
try {
|
|
4228
|
-
const api = createApmApiClient(cfg2);
|
|
4229
|
-
await api.cli.webideUpdateTransitionPrepEvents({
|
|
4230
|
-
taskId,
|
|
4231
|
-
startAction,
|
|
4232
|
-
discardDraft: true
|
|
4233
|
-
});
|
|
4234
|
-
} catch (err) {
|
|
4235
|
-
console.warn(
|
|
4236
|
-
`[apm] discard transition prep draft failed taskId=${taskId}:`,
|
|
4237
|
-
err instanceof Error ? err.message : err
|
|
4238
|
-
);
|
|
4239
|
-
}
|
|
4240
|
-
}
|
|
4241
|
-
|
|
4242
4230
|
// src/commands/connect/webide-ask-question.ts
|
|
4243
4231
|
function asString5(value) {
|
|
4244
4232
|
return typeof value === "string" ? value.trim() : "";
|
|
@@ -4298,9 +4286,8 @@ async function fetchAssumptionAnswersAndContinueAssessment(options) {
|
|
|
4298
4286
|
resolution: row.resolution
|
|
4299
4287
|
});
|
|
4300
4288
|
}
|
|
4301
|
-
await webIdeRunAction(cfg2, taskId, "continue-assessment");
|
|
4302
4289
|
console.log(
|
|
4303
|
-
`[apm] \u5047\u8BBE\u7ED3\u679C\u5DF2\u62C9\u53D6
|
|
4290
|
+
`[apm] \u5047\u8BBE\u7ED3\u679C\u5DF2\u62C9\u53D6 taskId=${taskId} count=${answers.length}`
|
|
4304
4291
|
);
|
|
4305
4292
|
return JSON.stringify({ title, answers }, null, 2);
|
|
4306
4293
|
}
|
|
@@ -4790,6 +4777,102 @@ function parseWebIdePromptPayload(content) {
|
|
|
4790
4777
|
return null;
|
|
4791
4778
|
}
|
|
4792
4779
|
|
|
4780
|
+
// src/commands/connect/webide-run-action.ts
|
|
4781
|
+
function startActionForInbound(action) {
|
|
4782
|
+
switch (action) {
|
|
4783
|
+
case "request-assessment":
|
|
4784
|
+
return "start-assessment";
|
|
4785
|
+
case "request-design":
|
|
4786
|
+
case "request-revise-design":
|
|
4787
|
+
return "start-design";
|
|
4788
|
+
case "request-write-plan":
|
|
4789
|
+
case "request-revise-plan":
|
|
4790
|
+
return "start-write-plan";
|
|
4791
|
+
case "request-develop":
|
|
4792
|
+
case "skip-plan":
|
|
4793
|
+
return "start-develop";
|
|
4794
|
+
case "request-start-project":
|
|
4795
|
+
return "start-project";
|
|
4796
|
+
case "request-execute-sql":
|
|
4797
|
+
return "start-execute-sql";
|
|
4798
|
+
case "request-bugfix":
|
|
4799
|
+
return "start-bugfix";
|
|
4800
|
+
case "request-organize-code":
|
|
4801
|
+
case "request-patch":
|
|
4802
|
+
return "start-organize-code";
|
|
4803
|
+
case "request-accept":
|
|
4804
|
+
return "start-accept";
|
|
4805
|
+
case "confirm-assumptions":
|
|
4806
|
+
return "continue-assessment";
|
|
4807
|
+
default:
|
|
4808
|
+
return null;
|
|
4809
|
+
}
|
|
4810
|
+
}
|
|
4811
|
+
function completeActionForInbound(action) {
|
|
4812
|
+
switch (action) {
|
|
4813
|
+
case "request-assessment":
|
|
4814
|
+
case "confirm-assumptions":
|
|
4815
|
+
return "complete-assessment";
|
|
4816
|
+
case "request-design":
|
|
4817
|
+
case "request-revise-design":
|
|
4818
|
+
return "complete-design";
|
|
4819
|
+
case "request-write-plan":
|
|
4820
|
+
case "request-revise-plan":
|
|
4821
|
+
return "complete-write-plan";
|
|
4822
|
+
case "request-develop":
|
|
4823
|
+
case "skip-plan":
|
|
4824
|
+
return "complete-develop";
|
|
4825
|
+
case "request-start-project":
|
|
4826
|
+
return "complete-project";
|
|
4827
|
+
case "request-execute-sql":
|
|
4828
|
+
return "complete-execute-sql";
|
|
4829
|
+
case "request-bugfix":
|
|
4830
|
+
return "complete-bugfix";
|
|
4831
|
+
case "request-organize-code":
|
|
4832
|
+
case "request-patch":
|
|
4833
|
+
return "complete-organize-code";
|
|
4834
|
+
case "request-accept":
|
|
4835
|
+
return "complete-accept";
|
|
4836
|
+
default:
|
|
4837
|
+
return null;
|
|
4838
|
+
}
|
|
4839
|
+
}
|
|
4840
|
+
async function webIdeRunAction(cfg2, taskId, action, params) {
|
|
4841
|
+
const api = createApmApiClient(cfg2);
|
|
4842
|
+
await api.cli.webideRunAction({ taskId, action, params });
|
|
4843
|
+
console.log(`[apm] webide runAction ok action=${action} taskId=${taskId}`);
|
|
4844
|
+
}
|
|
4845
|
+
async function webIdeSyncTransitionPrepEvents(cfg2, taskId, startAction, prepEvents) {
|
|
4846
|
+
try {
|
|
4847
|
+
const api = createApmApiClient(cfg2);
|
|
4848
|
+
await api.cli.webideUpdateTransitionPrepEvents({
|
|
4849
|
+
taskId,
|
|
4850
|
+
startAction,
|
|
4851
|
+
prepEvents
|
|
4852
|
+
});
|
|
4853
|
+
} catch (err) {
|
|
4854
|
+
console.warn(
|
|
4855
|
+
`[apm] sync transition prepEvents failed taskId=${taskId}:`,
|
|
4856
|
+
err instanceof Error ? err.message : err
|
|
4857
|
+
);
|
|
4858
|
+
}
|
|
4859
|
+
}
|
|
4860
|
+
async function webIdeDiscardTransitionPrepDraft(cfg2, taskId, startAction) {
|
|
4861
|
+
try {
|
|
4862
|
+
const api = createApmApiClient(cfg2);
|
|
4863
|
+
await api.cli.webideUpdateTransitionPrepEvents({
|
|
4864
|
+
taskId,
|
|
4865
|
+
startAction,
|
|
4866
|
+
discardDraft: true
|
|
4867
|
+
});
|
|
4868
|
+
} catch (err) {
|
|
4869
|
+
console.warn(
|
|
4870
|
+
`[apm] discard transition prep draft failed taskId=${taskId}:`,
|
|
4871
|
+
err instanceof Error ? err.message : err
|
|
4872
|
+
);
|
|
4873
|
+
}
|
|
4874
|
+
}
|
|
4875
|
+
|
|
4793
4876
|
// src/commands/connect/core/worker/handlers/webide-message.ts
|
|
4794
4877
|
var WEBIDE_CODE_CHANGE_ACTIONS = /* @__PURE__ */ new Set([
|
|
4795
4878
|
"skip-plan",
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
- `webide_sql_execute.md`:execute-sql 轮次连库执行 SQL 时 Read
|
|
18
18
|
- `webide_terminal.md`:长驻进程禁止用 Shell;本地服务由顶栏「启动项目」触发,开发任务不要自行起服务
|
|
19
19
|
- `webide_testcase.md`:生成测试用例并调用 `UpsertWebIdeTestCases`
|
|
20
|
-
- `webide_merge.md
|
|
20
|
+
- `webide_merge.md`:验收通过后先 `UpsertWebIdeChecklist` 写验收清单,再 `MergeWebIdePullRequests`
|
|
21
21
|
|
|
22
22
|
### 目录
|
|
23
23
|
|
|
@@ -25,4 +25,4 @@
|
|
|
25
25
|
- 任务附件:`.apm/webide/<taskId>/attachments/`(prompt 出现「任务附件」时按路径查看)
|
|
26
26
|
- 仓库清单:`.apm/workspace-repos.json`(先确认单仓 / 多仓;多仓必须写清改动范围并点名仓库)
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
计划、用例、验收清单、合并 PR 走 WebIDE 专用工具(`AskQuestion`、`RecommendPlan`、`UpsertWebIdePlan`、`UpsertWebIdeChecklist`、`GetWebIdeChecklist`、`UpsertWebIdeTestCases`、`MergeWebIdePullRequests` 等)。本地服务由用户在顶栏「启动项目」启动,开发任务不要自行起长驻进程。
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
## WebIDE 合并规范
|
|
2
2
|
|
|
3
|
-
适用场景:WebIDE 验收通过(`accept
|
|
3
|
+
适用场景:WebIDE 验收通过(`accept` / `request-accept`)后,先落库验收清单,再合并本任务 PR。
|
|
4
4
|
|
|
5
5
|
### 目标
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
1. 留下一份可事后查阅的「验收清单」(描述本任务实际改了什么)。
|
|
8
|
+
2. 将各仓库特性分支上的变更合并进基线分支(通常为 `main`)。
|
|
8
9
|
|
|
9
10
|
### 步骤
|
|
10
11
|
|
|
11
|
-
1.
|
|
12
|
-
|
|
12
|
+
1. **先写验收清单**:调用一次 `UpsertWebIdeChecklist`,提交完整 Markdown 全文(不要只提交 diff)。若需对照已有清单,可先 `GetWebIdeChecklist`(传当前 `taskId`)。建议结构:
|
|
13
|
+
- 改动摘要
|
|
14
|
+
- 按仓库的改动范围
|
|
15
|
+
- 关键改动点(模块 / 文件 / 接口 / 页面)
|
|
16
|
+
- 如何验收 / 回归点
|
|
17
|
+
- 备注(已知限制、未做事项、SQL/配置;无则写「无」)
|
|
18
|
+
2. 调用一次 `MergeWebIdePullRequests`(`confirmedConflictFree=true`),由平台合并本任务全部 OPEN PR。
|
|
19
|
+
3. 用 `AppendMessage` 汇总:清单已落库 + 合并结果(PR 编号、仓库)。
|
|
13
20
|
|
|
14
21
|
### 禁止
|
|
15
22
|
|
|
23
|
+
- **禁止**跳过 `UpsertWebIdeChecklist` 直接合并
|
|
16
24
|
- 在合并之外自行执行同步基线、代码审核、部署等额外流程
|