ai-project-manage-cli 8.1.23 → 8.1.25
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/dist/index.js +198 -73
- package/dist/worker-script.js +60 -31
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1430,9 +1430,77 @@ async function runConnect(options) {
|
|
|
1430
1430
|
}
|
|
1431
1431
|
}
|
|
1432
1432
|
|
|
1433
|
+
// src/utils/home-repository.ts
|
|
1434
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
1435
|
+
import { join as join8, resolve as resolve3 } from "path";
|
|
1436
|
+
var DEFAULT_REPOS_MANIFEST = "/home/repository.json";
|
|
1437
|
+
function isSimpleChildDirName(name) {
|
|
1438
|
+
if (!name || name === "." || name === "..") return false;
|
|
1439
|
+
if (name.includes("/") || name.includes("\\")) return false;
|
|
1440
|
+
return true;
|
|
1441
|
+
}
|
|
1442
|
+
function resolveReposManifestPath(explicit) {
|
|
1443
|
+
const fromOpt = explicit?.trim() || "";
|
|
1444
|
+
if (fromOpt) return fromOpt;
|
|
1445
|
+
const fromEnv = process.env.APM_REPOS_MANIFEST?.trim() || "";
|
|
1446
|
+
if (fromEnv) return fromEnv;
|
|
1447
|
+
return null;
|
|
1448
|
+
}
|
|
1449
|
+
function resolveCliReposManifestPath(explicit) {
|
|
1450
|
+
return resolveReposManifestPath(explicit) ?? DEFAULT_REPOS_MANIFEST;
|
|
1451
|
+
}
|
|
1452
|
+
function loadHomeRepositoryEntries(manifestPath2) {
|
|
1453
|
+
const label = manifestPath2.trim();
|
|
1454
|
+
if (!label) {
|
|
1455
|
+
throw new Error("[apm] \u591A\u4ED3\u6E05\u5355\u8DEF\u5F84\u4E3A\u7A7A");
|
|
1456
|
+
}
|
|
1457
|
+
const path = toFsPath(label);
|
|
1458
|
+
if (!existsSync6(path)) {
|
|
1459
|
+
throw new Error(`[apm] \u672A\u627E\u5230\u591A\u4ED3\u6E05\u5355 ${label}`);
|
|
1460
|
+
}
|
|
1461
|
+
let parsed;
|
|
1462
|
+
try {
|
|
1463
|
+
parsed = JSON.parse(readFileSync5(path, "utf8"));
|
|
1464
|
+
} catch (err) {
|
|
1465
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
1466
|
+
throw new Error(`[apm] \u89E3\u6790 ${label} \u5931\u8D25: ${detail}`);
|
|
1467
|
+
}
|
|
1468
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1469
|
+
throw new Error(
|
|
1470
|
+
`[apm] ${label} \u987B\u4E3A\u5BF9\u8C61\uFF1Akey=\u4E0B\u7EA7\u76EE\u5F55\uFF0Cvalue=git \u5730\u5740`
|
|
1471
|
+
);
|
|
1472
|
+
}
|
|
1473
|
+
const entries = [];
|
|
1474
|
+
for (const [rawKey, rawVal] of Object.entries(
|
|
1475
|
+
parsed
|
|
1476
|
+
)) {
|
|
1477
|
+
const pathKey = rawKey.trim();
|
|
1478
|
+
if (!isSimpleChildDirName(pathKey)) {
|
|
1479
|
+
throw new Error(
|
|
1480
|
+
`[apm] ${label} \u975E\u6CD5\u76EE\u5F55 key: ${JSON.stringify(rawKey)}\uFF08\u987B\u4E3A\u5F53\u524D\u4E0B\u7EA7\u76EE\u5F55\u540D\uFF09`
|
|
1481
|
+
);
|
|
1482
|
+
}
|
|
1483
|
+
if (typeof rawVal !== "string" || !rawVal.trim()) {
|
|
1484
|
+
throw new Error(
|
|
1485
|
+
`[apm] ${label}[${pathKey}] \u987B\u4E3A\u975E\u7A7A git \u5730\u5740\u5B57\u7B26\u4E32`
|
|
1486
|
+
);
|
|
1487
|
+
}
|
|
1488
|
+
entries.push({ path: pathKey, remoteUrl: rawVal.trim() });
|
|
1489
|
+
}
|
|
1490
|
+
entries.sort((a, b) => a.path.localeCompare(b.path));
|
|
1491
|
+
if (entries.length === 0) {
|
|
1492
|
+
throw new Error(`[apm] ${label} \u4E3A\u7A7A\uFF0C\u65E0\u4ED3\u5E93\u53EF\u786E\u8BA4`);
|
|
1493
|
+
}
|
|
1494
|
+
return entries;
|
|
1495
|
+
}
|
|
1496
|
+
function resolveHomeRepositoryAbsolutePaths(workdirInput, entries) {
|
|
1497
|
+
const workdir = resolveWorkdirPath(workdirInput);
|
|
1498
|
+
return entries.map((entry) => resolve3(join8(workdir, entry.path)));
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1433
1501
|
// src/utils/git.ts
|
|
1434
1502
|
import { execFile } from "child_process";
|
|
1435
|
-
import { dirname as dirname3, join as
|
|
1503
|
+
import { dirname as dirname3, join as join9 } from "path";
|
|
1436
1504
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1437
1505
|
import { promisify } from "util";
|
|
1438
1506
|
var execFileAsync = promisify(execFile);
|
|
@@ -1516,7 +1584,7 @@ async function resolveGitRepoRoot(cwd) {
|
|
|
1516
1584
|
return (await execGit(cwd, ["rev-parse", "--show-toplevel"], true)).trim();
|
|
1517
1585
|
}
|
|
1518
1586
|
function resolveGitScript(name) {
|
|
1519
|
-
return
|
|
1587
|
+
return join9(dirname3(fileURLToPath3(import.meta.url)), "scripts", name);
|
|
1520
1588
|
}
|
|
1521
1589
|
async function runGitScript(name, options) {
|
|
1522
1590
|
const skipCode = options.skipCode ?? 2;
|
|
@@ -1573,69 +1641,18 @@ async function pushCurrentBranch(cwd) {
|
|
|
1573
1641
|
});
|
|
1574
1642
|
}
|
|
1575
1643
|
|
|
1576
|
-
// src/
|
|
1577
|
-
import {
|
|
1578
|
-
import { join as join9, resolve as resolve3 } from "path";
|
|
1579
|
-
var DEFAULT_REPOS_MANIFEST = "/home/repository.json";
|
|
1580
|
-
function isSimpleChildDirName(name) {
|
|
1581
|
-
if (!name || name === "." || name === "..") return false;
|
|
1582
|
-
if (name.includes("/") || name.includes("\\")) return false;
|
|
1583
|
-
return true;
|
|
1584
|
-
}
|
|
1585
|
-
function resolveReposManifestPath(explicit) {
|
|
1586
|
-
const fromOpt = explicit?.trim() || "";
|
|
1587
|
-
if (fromOpt) return fromOpt;
|
|
1588
|
-
const fromEnv = process.env.APM_REPOS_MANIFEST?.trim() || "";
|
|
1589
|
-
if (fromEnv) return fromEnv;
|
|
1590
|
-
return DEFAULT_REPOS_MANIFEST;
|
|
1591
|
-
}
|
|
1592
|
-
function loadHomeRepositoryEntries(manifestPath) {
|
|
1593
|
-
const label = manifestPath.trim() || DEFAULT_REPOS_MANIFEST;
|
|
1594
|
-
const path = toFsPath(label);
|
|
1595
|
-
if (!existsSync6(path)) {
|
|
1596
|
-
throw new Error(`[apm] \u672A\u627E\u5230\u591A\u4ED3\u6E05\u5355 ${label}`);
|
|
1597
|
-
}
|
|
1598
|
-
let parsed;
|
|
1599
|
-
try {
|
|
1600
|
-
parsed = JSON.parse(readFileSync5(path, "utf8"));
|
|
1601
|
-
} catch (err) {
|
|
1602
|
-
const detail = err instanceof Error ? err.message : String(err);
|
|
1603
|
-
throw new Error(`[apm] \u89E3\u6790 ${label} \u5931\u8D25: ${detail}`);
|
|
1604
|
-
}
|
|
1605
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1606
|
-
throw new Error(
|
|
1607
|
-
`[apm] ${label} \u987B\u4E3A\u5BF9\u8C61\uFF1Akey=\u4E0B\u7EA7\u76EE\u5F55\uFF0Cvalue=git \u5730\u5740`
|
|
1608
|
-
);
|
|
1609
|
-
}
|
|
1610
|
-
const entries = [];
|
|
1611
|
-
for (const [rawKey, rawVal] of Object.entries(
|
|
1612
|
-
parsed
|
|
1613
|
-
)) {
|
|
1614
|
-
const pathKey = rawKey.trim();
|
|
1615
|
-
if (!isSimpleChildDirName(pathKey)) {
|
|
1616
|
-
throw new Error(
|
|
1617
|
-
`[apm] ${label} \u975E\u6CD5\u76EE\u5F55 key: ${JSON.stringify(rawKey)}\uFF08\u987B\u4E3A\u5F53\u524D\u4E0B\u7EA7\u76EE\u5F55\u540D\uFF09`
|
|
1618
|
-
);
|
|
1619
|
-
}
|
|
1620
|
-
if (typeof rawVal !== "string" || !rawVal.trim()) {
|
|
1621
|
-
throw new Error(
|
|
1622
|
-
`[apm] ${label}[${pathKey}] \u987B\u4E3A\u975E\u7A7A git \u5730\u5740\u5B57\u7B26\u4E32`
|
|
1623
|
-
);
|
|
1624
|
-
}
|
|
1625
|
-
entries.push({ path: pathKey, remoteUrl: rawVal.trim() });
|
|
1626
|
-
}
|
|
1627
|
-
entries.sort((a, b) => a.path.localeCompare(b.path));
|
|
1628
|
-
if (entries.length === 0) {
|
|
1629
|
-
throw new Error(`[apm] ${label} \u4E3A\u7A7A\uFF0C\u65E0\u4ED3\u5E93\u53EF\u786E\u8BA4`);
|
|
1630
|
-
}
|
|
1631
|
-
return entries;
|
|
1632
|
-
}
|
|
1633
|
-
function resolveHomeRepositoryAbsolutePaths(workdirInput, entries) {
|
|
1634
|
-
const workdir = resolveWorkdirPath(workdirInput);
|
|
1635
|
-
return entries.map((entry) => resolve3(join9(workdir, entry.path)));
|
|
1636
|
-
}
|
|
1644
|
+
// src/commands/branch.ts
|
|
1645
|
+
import { basename as basename2 } from "path";
|
|
1637
1646
|
|
|
1638
1647
|
// src/utils/workspace-repos.ts
|
|
1648
|
+
import {
|
|
1649
|
+
existsSync as existsSync7,
|
|
1650
|
+
mkdirSync as mkdirSync5,
|
|
1651
|
+
readFileSync as readFileSync6,
|
|
1652
|
+
readdirSync as readdirSync3,
|
|
1653
|
+
statSync as statSync3,
|
|
1654
|
+
writeFileSync as writeFileSync4
|
|
1655
|
+
} from "fs";
|
|
1639
1656
|
import { basename, dirname as dirname4, join as join10, relative, resolve as resolve4 } from "path";
|
|
1640
1657
|
|
|
1641
1658
|
// src/utils/git-remote.ts
|
|
@@ -1644,15 +1661,103 @@ import { promisify as promisify2 } from "util";
|
|
|
1644
1661
|
var execFileAsync2 = promisify2(execFile2);
|
|
1645
1662
|
|
|
1646
1663
|
// src/utils/workspace-repos.ts
|
|
1664
|
+
var WORKSPACE_REPOS_MANIFEST = "workspace-repos.json";
|
|
1665
|
+
var WORKSPACE_REPOS_VERSION = 1;
|
|
1666
|
+
function manifestPath(workdir) {
|
|
1667
|
+
return join10(workspaceApmDir(workdir), WORKSPACE_REPOS_MANIFEST);
|
|
1668
|
+
}
|
|
1669
|
+
function absoluteRepoPath(workdir, entry) {
|
|
1670
|
+
return resolve4(workdir, entry.path);
|
|
1671
|
+
}
|
|
1647
1672
|
function toRelativeRepoPath(workdir, repoAbs) {
|
|
1648
1673
|
return relative(workdir, repoAbs).replace(/\\/g, "/");
|
|
1649
1674
|
}
|
|
1675
|
+
function normalizeRepoEntry(raw) {
|
|
1676
|
+
if (!raw || typeof raw !== "object") return null;
|
|
1677
|
+
const o = raw;
|
|
1678
|
+
if (typeof o.path !== "string" || !o.path.trim()) return null;
|
|
1679
|
+
const path = o.path.trim().replace(/\\/g, "/");
|
|
1680
|
+
if (path === "." || path.includes("/")) return null;
|
|
1681
|
+
const entry = { path };
|
|
1682
|
+
if (typeof o.remoteUrl === "string" && o.remoteUrl.trim()) {
|
|
1683
|
+
entry.remoteUrl = o.remoteUrl.trim();
|
|
1684
|
+
} else if (o.remoteUrl === null) {
|
|
1685
|
+
entry.remoteUrl = null;
|
|
1686
|
+
}
|
|
1687
|
+
return entry;
|
|
1688
|
+
}
|
|
1689
|
+
function readManifest(workdir) {
|
|
1690
|
+
const path = toFsPath(manifestPath(workdir));
|
|
1691
|
+
if (!existsSync7(path)) {
|
|
1692
|
+
return null;
|
|
1693
|
+
}
|
|
1694
|
+
try {
|
|
1695
|
+
const raw = JSON.parse(
|
|
1696
|
+
readFileSync6(path, "utf8")
|
|
1697
|
+
);
|
|
1698
|
+
if (raw?.version !== WORKSPACE_REPOS_VERSION) {
|
|
1699
|
+
return null;
|
|
1700
|
+
}
|
|
1701
|
+
if (raw.kind !== "multi") {
|
|
1702
|
+
return null;
|
|
1703
|
+
}
|
|
1704
|
+
if (!Array.isArray(raw.repos) || raw.repos.length === 0) {
|
|
1705
|
+
return null;
|
|
1706
|
+
}
|
|
1707
|
+
if (typeof raw.workdir !== "string" || !raw.workdir.trim()) {
|
|
1708
|
+
return null;
|
|
1709
|
+
}
|
|
1710
|
+
const repos = raw.repos.map((item) => normalizeRepoEntry(item)).filter((item) => item != null);
|
|
1711
|
+
if (repos.length === 0) {
|
|
1712
|
+
return null;
|
|
1713
|
+
}
|
|
1714
|
+
return {
|
|
1715
|
+
version: WORKSPACE_REPOS_VERSION,
|
|
1716
|
+
kind: "multi",
|
|
1717
|
+
workdir: raw.workdir,
|
|
1718
|
+
repos,
|
|
1719
|
+
scannedAt: typeof raw.scannedAt === "string" && raw.scannedAt.trim() ? raw.scannedAt : (/* @__PURE__ */ new Date()).toISOString()
|
|
1720
|
+
};
|
|
1721
|
+
} catch {
|
|
1722
|
+
return null;
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
function loadWorkspaceReposCache(workdirInput) {
|
|
1726
|
+
const workdir = resolveWorkdirPath(workdirInput);
|
|
1727
|
+
const cached = readManifest(workdir);
|
|
1728
|
+
if (!cached) {
|
|
1729
|
+
throw new Error(
|
|
1730
|
+
`[apm] \u672A\u627E\u5230\u5DE5\u4F5C\u533A\u4ED3\u5E93\u7F13\u5B58 .apm/${WORKSPACE_REPOS_MANIFEST}\uFF0C\u8BF7\u5148\u6267\u884C\u4ED3\u5E93\u68C0\u6D4B`
|
|
1731
|
+
);
|
|
1732
|
+
}
|
|
1733
|
+
if (normalizeWorkdirPath(cached.workdir) !== normalizeWorkdirPath(workdir)) {
|
|
1734
|
+
throw new Error(
|
|
1735
|
+
`[apm] \u5DE5\u4F5C\u533A\u4ED3\u5E93\u7F13\u5B58 workdir \u4E0D\u5339\u914D\uFF1A\u7F13\u5B58=${cached.workdir} \u5F53\u524D=${workdir}\uFF0C\u8BF7\u5F3A\u5236\u91CD\u65B0\u626B\u63CF`
|
|
1736
|
+
);
|
|
1737
|
+
}
|
|
1738
|
+
if (!Array.isArray(cached.repos) || cached.repos.length === 0) {
|
|
1739
|
+
throw new Error(`[apm] \u5DE5\u4F5C\u533A\u4ED3\u5E93\u7F13\u5B58\u65E0\u6548\uFF08repos \u4E3A\u7A7A\uFF09\uFF0C\u8BF7\u5F3A\u5236\u91CD\u65B0\u626B\u63CF`);
|
|
1740
|
+
}
|
|
1741
|
+
console.log(
|
|
1742
|
+
`[apm] \u8BFB\u53D6\u5DE5\u4F5C\u533A\u4ED3\u5E93\u7F13\u5B58 repos=${cached.repos.map((r) => r.path).join(", ")}`
|
|
1743
|
+
);
|
|
1744
|
+
return {
|
|
1745
|
+
...cached,
|
|
1746
|
+
workdir
|
|
1747
|
+
};
|
|
1748
|
+
}
|
|
1749
|
+
function resolveWorkspaceRepoAbsolutePaths(manifest) {
|
|
1750
|
+
return manifest.repos.map(
|
|
1751
|
+
(entry) => absoluteRepoPath(manifest.workdir, entry)
|
|
1752
|
+
);
|
|
1753
|
+
}
|
|
1650
1754
|
function formatRepoLabel(workdir, repoAbs) {
|
|
1651
1755
|
const rel = toRelativeRepoPath(resolveWorkdirPath(workdir), repoAbs);
|
|
1652
1756
|
return rel || basename(repoAbs) || repoAbs;
|
|
1653
1757
|
}
|
|
1654
1758
|
|
|
1655
1759
|
// src/commands/branch.ts
|
|
1760
|
+
import { existsSync as existsSync8 } from "fs";
|
|
1656
1761
|
var TASK_BRANCH_PREFIX = "feat/task-";
|
|
1657
1762
|
async function syncTaskRepos(workdir, options = {}) {
|
|
1658
1763
|
const opts = typeof options === "string" ? { message: options } : options;
|
|
@@ -1724,12 +1829,32 @@ async function ensureTaskFeatureBranch(branch, projectId, options) {
|
|
|
1724
1829
|
await ensureFeatureBranch(gitRoot, branch, projectId);
|
|
1725
1830
|
return branch;
|
|
1726
1831
|
}
|
|
1832
|
+
function isWorkspaceReposManifestFile(manifestPath2) {
|
|
1833
|
+
return basename2(manifestPath2.replace(/\\/g, "/")) === WORKSPACE_REPOS_MANIFEST;
|
|
1834
|
+
}
|
|
1727
1835
|
function resolveTaskBranchRepoRoots(workdirPath, reposManifest) {
|
|
1728
|
-
const
|
|
1729
|
-
|
|
1730
|
-
|
|
1836
|
+
const manifestPath2 = resolveReposManifestPath(reposManifest);
|
|
1837
|
+
if (manifestPath2 && !isWorkspaceReposManifestFile(manifestPath2)) {
|
|
1838
|
+
const entries = loadHomeRepositoryEntries(manifestPath2);
|
|
1839
|
+
const roots2 = resolveHomeRepositoryAbsolutePaths(workdirPath, entries);
|
|
1840
|
+
console.log(
|
|
1841
|
+
`[apm] \u8BFB\u53D6\u5916\u90E8\u591A\u4ED3\u6E05\u5355 ${manifestPath2} repos=${entries.map((e) => `${e.path}\u2192${e.remoteUrl}`).join(", ")}`
|
|
1842
|
+
);
|
|
1843
|
+
return roots2;
|
|
1844
|
+
}
|
|
1845
|
+
if (manifestPath2 && isWorkspaceReposManifestFile(manifestPath2)) {
|
|
1846
|
+
const fsPath = toFsPath(manifestPath2);
|
|
1847
|
+
if (!existsSync8(fsPath)) {
|
|
1848
|
+
throw new Error(`[apm] \u672A\u627E\u5230\u5DE5\u4F5C\u533A\u4ED3\u5E93\u6E05\u5355 ${manifestPath2}`);
|
|
1849
|
+
}
|
|
1850
|
+
console.log(`[apm] \u4F7F\u7528\u663E\u5F0F\u5DE5\u4F5C\u533A\u4ED3\u5E93\u6E05\u5355 ${manifestPath2}`);
|
|
1851
|
+
}
|
|
1852
|
+
const workspace = loadWorkspaceReposCache(workdirPath);
|
|
1853
|
+
const roots = resolveWorkspaceRepoAbsolutePaths(workspace);
|
|
1731
1854
|
console.log(
|
|
1732
|
-
`[apm] \u8BFB\u53D6
|
|
1855
|
+
`[apm] \u8BFB\u53D6\u5DE5\u4F5C\u533A\u4ED3\u5E93\u6E05\u5355 repos=${workspace.repos.map(
|
|
1856
|
+
(r) => r.remoteUrl ? `${r.path}\u2192${r.remoteUrl}` : r.path
|
|
1857
|
+
).join(", ")}`
|
|
1733
1858
|
);
|
|
1734
1859
|
return roots;
|
|
1735
1860
|
}
|
|
@@ -1799,7 +1924,7 @@ async function runEnsureTaskBranchCli(options = {}) {
|
|
|
1799
1924
|
}
|
|
1800
1925
|
const result = await runTaskBranch(taskId, projectId, {
|
|
1801
1926
|
cwd: workdir,
|
|
1802
|
-
reposManifest: options.reposManifest
|
|
1927
|
+
reposManifest: resolveCliReposManifestPath(options.reposManifest)
|
|
1803
1928
|
});
|
|
1804
1929
|
console.log(
|
|
1805
1930
|
`[apm] \u7279\u6027\u5206\u652F\u5DF2\u5C31\u7EEA\uFF08\u5168\u90E8 ${result.repos.length} \u4E2A\u4ED3\uFF09 branch=${result.branch} projectId=${result.projectId}`
|
|
@@ -1808,7 +1933,7 @@ async function runEnsureTaskBranchCli(options = {}) {
|
|
|
1808
1933
|
|
|
1809
1934
|
// src/utils/user-prompt-cache.ts
|
|
1810
1935
|
import { createHash } from "crypto";
|
|
1811
|
-
import { existsSync as
|
|
1936
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
1812
1937
|
import { join as join11 } from "path";
|
|
1813
1938
|
import { tmpdir } from "os";
|
|
1814
1939
|
var CACHE_ROOT = join11(tmpdir(), "apm-hooks");
|
|
@@ -1830,9 +1955,9 @@ function formatUserPromptAsCommitMessage(prompt) {
|
|
|
1830
1955
|
}
|
|
1831
1956
|
function loadUserPromptCommitMessage(workdirInput) {
|
|
1832
1957
|
const path = toFsPath(userPromptCachePath(workdirInput));
|
|
1833
|
-
if (!
|
|
1958
|
+
if (!existsSync9(path)) return null;
|
|
1834
1959
|
try {
|
|
1835
|
-
const raw =
|
|
1960
|
+
const raw = readFileSync7(path, "utf8");
|
|
1836
1961
|
const msg = formatUserPromptAsCommitMessage(raw);
|
|
1837
1962
|
return msg || null;
|
|
1838
1963
|
} catch {
|
|
@@ -1873,14 +1998,14 @@ async function runCommitTaskReposCli(options = {}) {
|
|
|
1873
1998
|
}
|
|
1874
1999
|
const result = await syncTaskRepos(workdir, {
|
|
1875
2000
|
message,
|
|
1876
|
-
reposManifest: options.reposManifest
|
|
2001
|
+
reposManifest: resolveCliReposManifestPath(options.reposManifest)
|
|
1877
2002
|
});
|
|
1878
2003
|
console.log(
|
|
1879
2004
|
`[apm] \u591A\u4ED3\u6536\u5C3E\u5B8C\u6210 committed=${result.committed} commitSkipped=${result.commitSkipped} pushed=${result.pushed} pushSkipped=${result.pushSkipped} failed=${result.failed.length} repos=${result.repos.length}`
|
|
1880
2005
|
);
|
|
1881
2006
|
if (result.failed.length > 0) {
|
|
1882
2007
|
throw new Error(
|
|
1883
|
-
`[apm] \
|
|
2008
|
+
`[apm] \u591A\u4ED3\u6536\u5C3E\u90E8\u5206\u5931\u8D25: ${result.failed.join(", ")}`
|
|
1884
2009
|
);
|
|
1885
2010
|
}
|
|
1886
2011
|
}
|
package/dist/worker-script.js
CHANGED
|
@@ -518,7 +518,6 @@ async function pushCurrentBranch(cwd) {
|
|
|
518
518
|
// src/utils/home-repository.ts
|
|
519
519
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
520
520
|
import { join as join4, resolve as resolve3 } from "path";
|
|
521
|
-
var DEFAULT_REPOS_MANIFEST = "/home/repository.json";
|
|
522
521
|
function isSimpleChildDirName(name) {
|
|
523
522
|
if (!name || name === "." || name === "..") return false;
|
|
524
523
|
if (name.includes("/") || name.includes("\\")) return false;
|
|
@@ -529,10 +528,13 @@ function resolveReposManifestPath(explicit) {
|
|
|
529
528
|
if (fromOpt) return fromOpt;
|
|
530
529
|
const fromEnv = process.env.APM_REPOS_MANIFEST?.trim() || "";
|
|
531
530
|
if (fromEnv) return fromEnv;
|
|
532
|
-
return
|
|
531
|
+
return null;
|
|
533
532
|
}
|
|
534
533
|
function loadHomeRepositoryEntries(manifestPath2) {
|
|
535
|
-
const label = manifestPath2.trim()
|
|
534
|
+
const label = manifestPath2.trim();
|
|
535
|
+
if (!label) {
|
|
536
|
+
throw new Error("[apm] \u591A\u4ED3\u6E05\u5355\u8DEF\u5F84\u4E3A\u7A7A");
|
|
537
|
+
}
|
|
536
538
|
const path = toFsPath(label);
|
|
537
539
|
if (!existsSync2(path)) {
|
|
538
540
|
throw new Error(`[apm] \u672A\u627E\u5230\u591A\u4ED3\u6E05\u5355 ${label}`);
|
|
@@ -577,6 +579,9 @@ function resolveHomeRepositoryAbsolutePaths(workdirInput, entries) {
|
|
|
577
579
|
return entries.map((entry) => resolve3(join4(workdir, entry.path)));
|
|
578
580
|
}
|
|
579
581
|
|
|
582
|
+
// src/commands/branch.ts
|
|
583
|
+
import { basename as basename2 } from "path";
|
|
584
|
+
|
|
580
585
|
// src/utils/workspace-repos.ts
|
|
581
586
|
import {
|
|
582
587
|
existsSync as existsSync3,
|
|
@@ -859,6 +864,7 @@ function formatRepoLabel(workdir, repoAbs) {
|
|
|
859
864
|
}
|
|
860
865
|
|
|
861
866
|
// src/commands/branch.ts
|
|
867
|
+
import { existsSync as existsSync4 } from "fs";
|
|
862
868
|
var TASK_BRANCH_PREFIX = "feat/task-";
|
|
863
869
|
async function commitWorkspaceReposIfDirty(workdir, message, reposManifest) {
|
|
864
870
|
const result = await commitTaskReposIfDirty(workdir, message, reposManifest);
|
|
@@ -968,12 +974,32 @@ async function resolveProjectIdForTask(taskId) {
|
|
|
968
974
|
}
|
|
969
975
|
return projectId;
|
|
970
976
|
}
|
|
977
|
+
function isWorkspaceReposManifestFile(manifestPath2) {
|
|
978
|
+
return basename2(manifestPath2.replace(/\\/g, "/")) === WORKSPACE_REPOS_MANIFEST;
|
|
979
|
+
}
|
|
971
980
|
function resolveTaskBranchRepoRoots(workdirPath, reposManifest) {
|
|
972
981
|
const manifestPath2 = resolveReposManifestPath(reposManifest);
|
|
973
|
-
|
|
974
|
-
|
|
982
|
+
if (manifestPath2 && !isWorkspaceReposManifestFile(manifestPath2)) {
|
|
983
|
+
const entries = loadHomeRepositoryEntries(manifestPath2);
|
|
984
|
+
const roots2 = resolveHomeRepositoryAbsolutePaths(workdirPath, entries);
|
|
985
|
+
console.log(
|
|
986
|
+
`[apm] \u8BFB\u53D6\u5916\u90E8\u591A\u4ED3\u6E05\u5355 ${manifestPath2} repos=${entries.map((e) => `${e.path}\u2192${e.remoteUrl}`).join(", ")}`
|
|
987
|
+
);
|
|
988
|
+
return roots2;
|
|
989
|
+
}
|
|
990
|
+
if (manifestPath2 && isWorkspaceReposManifestFile(manifestPath2)) {
|
|
991
|
+
const fsPath = toFsPath(manifestPath2);
|
|
992
|
+
if (!existsSync4(fsPath)) {
|
|
993
|
+
throw new Error(`[apm] \u672A\u627E\u5230\u5DE5\u4F5C\u533A\u4ED3\u5E93\u6E05\u5355 ${manifestPath2}`);
|
|
994
|
+
}
|
|
995
|
+
console.log(`[apm] \u4F7F\u7528\u663E\u5F0F\u5DE5\u4F5C\u533A\u4ED3\u5E93\u6E05\u5355 ${manifestPath2}`);
|
|
996
|
+
}
|
|
997
|
+
const workspace = loadWorkspaceReposCache(workdirPath);
|
|
998
|
+
const roots = resolveWorkspaceRepoAbsolutePaths(workspace);
|
|
975
999
|
console.log(
|
|
976
|
-
`[apm] \u8BFB\u53D6
|
|
1000
|
+
`[apm] \u8BFB\u53D6\u5DE5\u4F5C\u533A\u4ED3\u5E93\u6E05\u5355 repos=${workspace.repos.map(
|
|
1001
|
+
(r) => r.remoteUrl ? `${r.path}\u2192${r.remoteUrl}` : r.path
|
|
1002
|
+
).join(", ")}`
|
|
977
1003
|
);
|
|
978
1004
|
return roots;
|
|
979
1005
|
}
|
|
@@ -1678,7 +1704,7 @@ function createUpsertWebIdeTestCasesTool(options) {
|
|
|
1678
1704
|
}
|
|
1679
1705
|
|
|
1680
1706
|
// src/commands/connect/tools/mysql-tools.ts
|
|
1681
|
-
import { existsSync as
|
|
1707
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, statSync as statSync3 } from "node:fs";
|
|
1682
1708
|
import { isAbsolute, relative as relative2, resolve as resolve5 } from "node:path";
|
|
1683
1709
|
import mysql from "mysql2/promise";
|
|
1684
1710
|
var MAX_RESULT_ROWS = 100;
|
|
@@ -1757,7 +1783,7 @@ function resolveSqlArtifactPath(workdir, absolutePath) {
|
|
|
1757
1783
|
return { ok: false, error: "path \u5FC5\u987B\u4F4D\u4E8E\u5F53\u524D\u5DE5\u4F5C\u533A\u5185" };
|
|
1758
1784
|
}
|
|
1759
1785
|
const fsPath = toFsPath(targetAbs);
|
|
1760
|
-
if (!
|
|
1786
|
+
if (!existsSync5(fsPath)) {
|
|
1761
1787
|
return { ok: false, error: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${absolutePath}` };
|
|
1762
1788
|
}
|
|
1763
1789
|
let st;
|
|
@@ -2632,14 +2658,14 @@ async function runCursorAgent(cfg2, ctx, options) {
|
|
|
2632
2658
|
}
|
|
2633
2659
|
|
|
2634
2660
|
// src/commands/connect/webide-agent-registry.ts
|
|
2635
|
-
import { existsSync as
|
|
2661
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "node:fs";
|
|
2636
2662
|
import { dirname as dirname3, resolve as resolve6 } from "node:path";
|
|
2637
2663
|
function registryPath(workdir, taskId, fileName = "cursor-agent.json") {
|
|
2638
2664
|
return resolve6(workdir, ".apm", "webide", taskId, fileName);
|
|
2639
2665
|
}
|
|
2640
2666
|
var DESIGN_AGENT_FILE = "design-agent.json";
|
|
2641
2667
|
function readRegistry(path) {
|
|
2642
|
-
if (!
|
|
2668
|
+
if (!existsSync6(path)) {
|
|
2643
2669
|
return {};
|
|
2644
2670
|
}
|
|
2645
2671
|
try {
|
|
@@ -2714,7 +2740,7 @@ function saveWebIdeAgentId(workdir, taskId, agentId) {
|
|
|
2714
2740
|
}
|
|
2715
2741
|
function clearWebIdeAgentId(workdir, taskId) {
|
|
2716
2742
|
const path = registryPath(workdir, taskId);
|
|
2717
|
-
if (!
|
|
2743
|
+
if (!existsSync6(path)) return;
|
|
2718
2744
|
syncWebIdeTaskState(workdir, taskId, { agentId: "" });
|
|
2719
2745
|
}
|
|
2720
2746
|
function loadWebIdeDesignAgentId(workdir, taskId) {
|
|
@@ -2734,7 +2760,7 @@ function saveWebIdeDesignAgentId(workdir, taskId, agentId) {
|
|
|
2734
2760
|
}
|
|
2735
2761
|
function clearWebIdeDesignAgentId(workdir, taskId) {
|
|
2736
2762
|
const path = registryPath(workdir, taskId, DESIGN_AGENT_FILE);
|
|
2737
|
-
if (!
|
|
2763
|
+
if (!existsSync6(path)) return;
|
|
2738
2764
|
const current = readRegistry(path);
|
|
2739
2765
|
const next = { ...current };
|
|
2740
2766
|
delete next.agentId;
|
|
@@ -2790,24 +2816,27 @@ async function fetchAssumptionAnswersAndContinueAssessment(options) {
|
|
|
2790
2816
|
if (ids.length === 0) {
|
|
2791
2817
|
throw new Error("\u6CA1\u6709\u5DF2\u786E\u8BA4\u7684\u5047\u8BBE");
|
|
2792
2818
|
}
|
|
2793
|
-
const
|
|
2819
|
+
const lines = [];
|
|
2820
|
+
if (title?.trim()) {
|
|
2821
|
+
lines.push(title.trim(), "");
|
|
2822
|
+
}
|
|
2823
|
+
let index = 0;
|
|
2794
2824
|
for (const id of ids) {
|
|
2795
2825
|
const row = byId.get(id);
|
|
2796
2826
|
if (!row || row.status !== "RESOLVED") {
|
|
2797
2827
|
throw new Error(`\u5047\u8BBE\u5C1A\u672A\u5168\u90E8\u786E\u8BA4: ${id}`);
|
|
2798
2828
|
}
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
});
|
|
2829
|
+
const text = asString4(row.resolution) || asString4(row.customAnswer) || asString4(row.selectedOptionId);
|
|
2830
|
+
if (!text) {
|
|
2831
|
+
throw new Error(`\u5047\u8BBE\u7B54\u6848\u4E3A\u7A7A: ${id}`);
|
|
2832
|
+
}
|
|
2833
|
+
index += 1;
|
|
2834
|
+
lines.push(`${index}. ${text}`);
|
|
2806
2835
|
}
|
|
2807
2836
|
console.log(
|
|
2808
|
-
`[apm] \u5047\u8BBE\u7ED3\u679C\u5DF2\u62C9\u53D6 taskId=${taskId} count=${
|
|
2837
|
+
`[apm] \u5047\u8BBE\u7ED3\u679C\u5DF2\u62C9\u53D6 taskId=${taskId} count=${index}`
|
|
2809
2838
|
);
|
|
2810
|
-
return
|
|
2839
|
+
return lines.join("\n");
|
|
2811
2840
|
}
|
|
2812
2841
|
function createWebIdeAskQuestionExecute(options) {
|
|
2813
2842
|
const { cfg: cfg2, taskId, onAwaitingAssumptions } = options;
|
|
@@ -3071,7 +3100,7 @@ function resolveMessageReplyFallback(fallback) {
|
|
|
3071
3100
|
|
|
3072
3101
|
// src/commands/sync-webide-agent.ts
|
|
3073
3102
|
import {
|
|
3074
|
-
existsSync as
|
|
3103
|
+
existsSync as existsSync7,
|
|
3075
3104
|
mkdirSync as mkdirSync5,
|
|
3076
3105
|
readdirSync as readdirSync3,
|
|
3077
3106
|
readFileSync as readFileSync6,
|
|
@@ -3087,7 +3116,7 @@ function withTrailingNewline(text) {
|
|
|
3087
3116
|
}
|
|
3088
3117
|
function readRevision(apmDir) {
|
|
3089
3118
|
const path = toFsPath(join6(apmDir, REVISION_FILE));
|
|
3090
|
-
if (!
|
|
3119
|
+
if (!existsSync7(path)) return null;
|
|
3091
3120
|
try {
|
|
3092
3121
|
const parsed = JSON.parse(readFileSync6(path, "utf8"));
|
|
3093
3122
|
if (parsed?.version === 1 && parsed.revision?.trim()) {
|
|
@@ -3388,7 +3417,7 @@ async function ensureWebIdePullRequests(cfg2, taskId, workdir) {
|
|
|
3388
3417
|
}
|
|
3389
3418
|
|
|
3390
3419
|
// src/commands/sync-webide-attachments.ts
|
|
3391
|
-
import { existsSync as
|
|
3420
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
3392
3421
|
import { join as join7 } from "path";
|
|
3393
3422
|
var MANIFEST_FILE = ".sync-manifest.json";
|
|
3394
3423
|
async function downloadAttachment(cfg2, attachmentId) {
|
|
@@ -3406,7 +3435,7 @@ async function downloadAttachment(cfg2, attachmentId) {
|
|
|
3406
3435
|
}
|
|
3407
3436
|
function loadManifest(dir) {
|
|
3408
3437
|
const path = join7(dir, MANIFEST_FILE);
|
|
3409
|
-
if (!
|
|
3438
|
+
if (!existsSync8(path)) {
|
|
3410
3439
|
return { version: 1, attachments: {} };
|
|
3411
3440
|
}
|
|
3412
3441
|
try {
|
|
@@ -3429,7 +3458,7 @@ function saveManifest(dir, manifest) {
|
|
|
3429
3458
|
);
|
|
3430
3459
|
}
|
|
3431
3460
|
function isAttachmentUpToDate(entry, item, dest) {
|
|
3432
|
-
if (!entry || !
|
|
3461
|
+
if (!entry || !existsSync8(dest)) return false;
|
|
3433
3462
|
if (entry.name !== item.name) return false;
|
|
3434
3463
|
const createdAt = item.createdAt ?? "";
|
|
3435
3464
|
return entry.createdAt === createdAt;
|
|
@@ -3476,7 +3505,7 @@ async function syncWebIdeAttachments(cfg2, taskId, workdir, attachments) {
|
|
|
3476
3505
|
|
|
3477
3506
|
// src/commands/sync-webide-design.ts
|
|
3478
3507
|
import { createHash } from "crypto";
|
|
3479
|
-
import { existsSync as
|
|
3508
|
+
import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
3480
3509
|
import { join as join8 } from "path";
|
|
3481
3510
|
|
|
3482
3511
|
// src/opc-shared-types.ts
|
|
@@ -3499,7 +3528,7 @@ function hashBuffer(buf) {
|
|
|
3499
3528
|
}
|
|
3500
3529
|
function loadManifest2(dir) {
|
|
3501
3530
|
const path = join8(dir, MANIFEST_FILE2);
|
|
3502
|
-
if (!
|
|
3531
|
+
if (!existsSync9(path)) {
|
|
3503
3532
|
return { version: 1, files: {} };
|
|
3504
3533
|
}
|
|
3505
3534
|
try {
|
|
@@ -3543,7 +3572,7 @@ async function syncWebIdeDesign(cfg2, taskId, workdir, artifacts) {
|
|
|
3543
3572
|
if (!name || !isWebIdeDesignArtifactName(name)) continue;
|
|
3544
3573
|
const localPath = join8(dir, name);
|
|
3545
3574
|
const entry = manifest.files[name];
|
|
3546
|
-
if (entry?.contentHash === art.contentHash &&
|
|
3575
|
+
if (entry?.contentHash === art.contentHash && existsSync9(localPath)) {
|
|
3547
3576
|
continue;
|
|
3548
3577
|
}
|
|
3549
3578
|
const buf = await downloadDesignFile(cfg2, taskId, name);
|
|
@@ -3556,7 +3585,7 @@ async function syncWebIdeDesign(cfg2, taskId, workdir, artifacts) {
|
|
|
3556
3585
|
}
|
|
3557
3586
|
function listLocalDesignArtifactFiles(taskId, workdir) {
|
|
3558
3587
|
const dir = webideDesignDir(taskId, workdir);
|
|
3559
|
-
if (!
|
|
3588
|
+
if (!existsSync9(dir)) return [];
|
|
3560
3589
|
const out = [];
|
|
3561
3590
|
for (const name of readdirSync4(dir)) {
|
|
3562
3591
|
if (!isWebIdeDesignArtifactName(name)) continue;
|