ai-project-manage-cli 7.1.17 → 7.1.19

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 CHANGED
@@ -333,13 +333,13 @@ var init_client = __esm({
333
333
  });
334
334
 
335
335
  // src/commands/deploy/internal/minio.ts
336
- import { statSync as statSync5 } from "node:fs";
336
+ import { statSync as statSync6 } from "node:fs";
337
337
  import { readdir, readFile } from "node:fs/promises";
338
338
  import path from "node:path";
339
339
  import * as Minio from "minio";
340
340
  async function isDirectoryPath(dir) {
341
341
  try {
342
- const st = statSync5(dir);
342
+ const st = statSync6(dir);
343
343
  return st.isDirectory();
344
344
  } catch {
345
345
  return false;
@@ -369,7 +369,7 @@ async function collectFiles(root) {
369
369
  if (e.isDirectory()) {
370
370
  await walk(abs, rel);
371
371
  } else if (e.isFile()) {
372
- const st = statSync5(abs);
372
+ const st = statSync6(abs);
373
373
  out.push({
374
374
  absPath: abs,
375
375
  relativePath: rel.replace(/\\/g, "/"),
@@ -436,14 +436,14 @@ var init_minio = __esm({
436
436
  async deleteObjectsByPrefix(bucket, prefix) {
437
437
  const objectsStream = this.inner.listObjectsV2(bucket, prefix, true);
438
438
  const keys = [];
439
- await new Promise((resolve7, reject) => {
439
+ await new Promise((resolve8, reject) => {
440
440
  objectsStream.on("data", (obj) => {
441
441
  if (obj.name) {
442
442
  keys.push(obj.name);
443
443
  }
444
444
  });
445
445
  objectsStream.on("error", reject);
446
- objectsStream.on("end", resolve7);
446
+ objectsStream.on("end", resolve8);
447
447
  });
448
448
  const chunkSize = 500;
449
449
  for (let i = 0; i < keys.length; i += chunkSize) {
@@ -1099,8 +1099,8 @@ import { Command } from "commander";
1099
1099
  init_config();
1100
1100
 
1101
1101
  // src/commands/init.ts
1102
- import { join as join5 } from "path";
1103
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync5 } from "fs";
1102
+ import { join as join6 } from "path";
1103
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync6 } from "fs";
1104
1104
 
1105
1105
  // src/command-utils.ts
1106
1106
  init_config();
@@ -1388,13 +1388,43 @@ async function copyTemplateFiles(targetDir, workdir = resolveWorkdirPath()) {
1388
1388
 
1389
1389
  // src/deployment-config-sync.ts
1390
1390
  init_client();
1391
- import { join as join3 } from "path";
1392
- import { writeFileSync as writeFileSync3 } from "fs";
1391
+ import { join as join4 } from "path";
1392
+ import { writeFileSync as writeFileSync4 } from "fs";
1393
1393
 
1394
1394
  // src/git-remote.ts
1395
1395
  import { execFile } from "child_process";
1396
1396
  import { promisify } from "util";
1397
1397
  var execFileAsync = promisify(execFile);
1398
+ function toHttpsGitRemoteUrl(raw) {
1399
+ let s = raw.trim();
1400
+ if (!s) return null;
1401
+ const sshScp = /^git@([^:]+):(.+)$/.exec(s);
1402
+ if (sshScp) {
1403
+ s = `https://${sshScp[1]}/${sshScp[2]}`;
1404
+ } else {
1405
+ const sshUri = /^ssh:\/\/(?:git@)?([^/]+)\/(.+)$/i.exec(s);
1406
+ if (sshUri) {
1407
+ s = `https://${sshUri[1]}/${sshUri[2]}`;
1408
+ } else if (/^http:\/\//i.test(s)) {
1409
+ s = `https://${s.slice("http://".length)}`;
1410
+ } else if (!/^https:\/\//i.test(s)) {
1411
+ const scpLike = /^([^/:]+):(.+)$/.exec(s);
1412
+ if (scpLike && !scpLike[1].includes(".")) {
1413
+ return null;
1414
+ }
1415
+ if (scpLike) {
1416
+ s = `https://${scpLike[1]}/${scpLike[2]}`;
1417
+ } else if (s.includes("/")) {
1418
+ s = `https://${s}`;
1419
+ } else {
1420
+ return null;
1421
+ }
1422
+ }
1423
+ }
1424
+ s = s.replace(/\/+$/, "");
1425
+ if (!/^https:\/\//i.test(s)) return null;
1426
+ return s;
1427
+ }
1398
1428
  async function tryReadGitOriginUrl(cwd) {
1399
1429
  try {
1400
1430
  const { stdout } = await execFileAsync(
@@ -1408,6 +1438,11 @@ async function tryReadGitOriginUrl(cwd) {
1408
1438
  return null;
1409
1439
  }
1410
1440
  }
1441
+ async function tryReadHttpsGitOriginUrl(cwd) {
1442
+ const raw = await tryReadGitOriginUrl(cwd);
1443
+ if (!raw) return null;
1444
+ return toHttpsGitRemoteUrl(raw);
1445
+ }
1411
1446
 
1412
1447
  // src/git-utils.ts
1413
1448
  import { execFile as execFile2 } from "child_process";
@@ -1470,6 +1505,24 @@ async function ensureRemoteBaselineBranch(cwd, baselineBranch) {
1470
1505
  `[apm] \u8FDC\u7A0B\u4E0D\u5B58\u5728\u57FA\u7EBF\u5206\u652F origin/${baselineBranch}\uFF0C\u8BF7\u786E\u8BA4\u4ED3\u5E93\u9ED8\u8BA4\u5206\u652F\u5DF2\u63A8\u9001\u5230 origin`
1471
1506
  );
1472
1507
  }
1508
+ async function resolveDefaultRemoteBranch(cwd) {
1509
+ try {
1510
+ const ref = (await execGit(cwd, ["symbolic-ref", "refs/remotes/origin/HEAD"], true)).trim();
1511
+ const match = ref.match(/^refs\/remotes\/origin\/(.+)$/);
1512
+ if (match?.[1]) {
1513
+ return match[1];
1514
+ }
1515
+ } catch {
1516
+ }
1517
+ for (const candidate of ["main", "master"]) {
1518
+ if (await remoteBranchExists(cwd, candidate)) {
1519
+ return candidate;
1520
+ }
1521
+ }
1522
+ throw new Error(
1523
+ "[apm] \u65E0\u6CD5\u786E\u5B9A\u8FDC\u7A0B\u9ED8\u8BA4\u5206\u652F\uFF08origin/HEAD\u3001main\u3001master \u5747\u4E0D\u53EF\u7528\uFF09"
1524
+ );
1525
+ }
1473
1526
  async function hasUpstream(cwd) {
1474
1527
  try {
1475
1528
  await execGit(cwd, ["rev-parse", "--abbrev-ref", "@{upstream}"], true);
@@ -1596,6 +1649,162 @@ async function resolveBranchBaseline(api, sessionId, workdirPath) {
1596
1649
 
1597
1650
  // src/deployment-config-sync.ts
1598
1651
  init_config();
1652
+
1653
+ // src/workspace-repos.ts
1654
+ import {
1655
+ existsSync as existsSync2,
1656
+ mkdirSync as mkdirSync3,
1657
+ readFileSync as readFileSync3,
1658
+ readdirSync as readdirSync2,
1659
+ statSync as statSync2,
1660
+ writeFileSync as writeFileSync3
1661
+ } from "fs";
1662
+ import { basename as basename2, dirname as dirname2, join as join3, relative, resolve as resolve3 } from "path";
1663
+ var WORKSPACE_REPOS_MANIFEST = "workspace-repos.json";
1664
+ var WORKSPACE_REPOS_VERSION = 1;
1665
+ function manifestPath(workdir) {
1666
+ return join3(workspaceApmDir(workdir), WORKSPACE_REPOS_MANIFEST);
1667
+ }
1668
+ function absoluteRepoPath(workdir, entry) {
1669
+ if (entry.path === "." || entry.path === "") {
1670
+ return workdir;
1671
+ }
1672
+ return resolve3(workdir, entry.path);
1673
+ }
1674
+ function normalizeRepoEntry(raw) {
1675
+ if (!raw || typeof raw !== "object") return null;
1676
+ const o = raw;
1677
+ if (typeof o.path !== "string" || !o.path.trim()) return null;
1678
+ const entry = {
1679
+ path: o.path.trim().replace(/\\/g, "/")
1680
+ };
1681
+ if (typeof o.remoteUrl === "string" && o.remoteUrl.trim()) {
1682
+ entry.remoteUrl = o.remoteUrl.trim();
1683
+ } else if (o.remoteUrl === null) {
1684
+ entry.remoteUrl = null;
1685
+ }
1686
+ return entry;
1687
+ }
1688
+ function readManifest(workdir) {
1689
+ const path19 = toFsPath(manifestPath(workdir));
1690
+ if (!existsSync2(path19)) {
1691
+ return null;
1692
+ }
1693
+ try {
1694
+ const raw = JSON.parse(
1695
+ readFileSync3(path19, "utf8")
1696
+ );
1697
+ if (raw?.version !== WORKSPACE_REPOS_VERSION) {
1698
+ return null;
1699
+ }
1700
+ if (raw.kind !== "single" && raw.kind !== "multi") {
1701
+ return null;
1702
+ }
1703
+ if (!Array.isArray(raw.repos) || raw.repos.length === 0) {
1704
+ return null;
1705
+ }
1706
+ if (typeof raw.workdir !== "string" || !raw.workdir.trim()) {
1707
+ return null;
1708
+ }
1709
+ const repos = raw.repos.map((item) => normalizeRepoEntry(item)).filter((item) => item != null);
1710
+ if (repos.length === 0) {
1711
+ return null;
1712
+ }
1713
+ return {
1714
+ version: WORKSPACE_REPOS_VERSION,
1715
+ kind: raw.kind,
1716
+ workdir: raw.workdir,
1717
+ repos,
1718
+ scannedAt: typeof raw.scannedAt === "string" && raw.scannedAt.trim() ? raw.scannedAt : (/* @__PURE__ */ new Date()).toISOString()
1719
+ };
1720
+ } catch {
1721
+ return null;
1722
+ }
1723
+ }
1724
+ function writeManifest(workdir, manifest) {
1725
+ const apmDir = toFsPath(workspaceApmDir(workdir));
1726
+ mkdirSync3(apmDir, { recursive: true });
1727
+ const path19 = toFsPath(manifestPath(workdir));
1728
+ writeFileSync3(path19, `${JSON.stringify(manifest, null, 2)}
1729
+ `, "utf8");
1730
+ }
1731
+ function isPathInsideOrEqual(parentAbs, childAbs) {
1732
+ const parent = normalizeWorkdirPath(parentAbs);
1733
+ const child = normalizeWorkdirPath(childAbs);
1734
+ if (child === parent) return true;
1735
+ const prefix = parent.endsWith("/") ? parent : `${parent}/`;
1736
+ return child.startsWith(prefix);
1737
+ }
1738
+ function findWorkspaceReposManifestNearPath(startDirInput) {
1739
+ let current = resolve3(startDirInput);
1740
+ for (; ; ) {
1741
+ const candidates = /* @__PURE__ */ new Set([normalizeWorkdirPath(current)]);
1742
+ try {
1743
+ if (existsSync2(toFsPath(current))) {
1744
+ candidates.add(resolveWorkdirPath(current));
1745
+ }
1746
+ } catch {
1747
+ }
1748
+ for (const candidate of candidates) {
1749
+ const cached = readManifest(candidate);
1750
+ if (!cached) continue;
1751
+ const cachedWorkdir = resolveWorkdirPath(cached.workdir);
1752
+ const candidateNorm = resolveWorkdirPath(candidate);
1753
+ if (cachedWorkdir === candidateNorm) {
1754
+ return { ...cached, workdir: cachedWorkdir };
1755
+ }
1756
+ }
1757
+ const parent = dirname2(current);
1758
+ if (parent === current) {
1759
+ return null;
1760
+ }
1761
+ current = parent;
1762
+ }
1763
+ }
1764
+ function matchWorkspaceRepoEntryForPath(manifest, pathInput) {
1765
+ const target = resolveWorkdirPath(pathInput);
1766
+ const workdir = resolveWorkdirPath(manifest.workdir);
1767
+ let best = null;
1768
+ let bestLen = -1;
1769
+ for (const entry of manifest.repos) {
1770
+ const abs = resolveWorkdirPath(absoluteRepoPath(workdir, entry));
1771
+ if (!isPathInsideOrEqual(abs, target)) {
1772
+ continue;
1773
+ }
1774
+ if (abs.length > bestLen) {
1775
+ best = entry;
1776
+ bestLen = abs.length;
1777
+ }
1778
+ }
1779
+ return best;
1780
+ }
1781
+ async function enrichWorkspaceReposRemoteUrls(manifest) {
1782
+ let changed = false;
1783
+ const repos = [];
1784
+ for (const entry of manifest.repos) {
1785
+ const abs = absoluteRepoPath(manifest.workdir, entry);
1786
+ const remoteUrl = await tryReadHttpsGitOriginUrl(abs);
1787
+ const next = {
1788
+ path: entry.path,
1789
+ remoteUrl: remoteUrl || null
1790
+ };
1791
+ if ((entry.remoteUrl ?? null) !== next.remoteUrl) {
1792
+ changed = true;
1793
+ }
1794
+ repos.push(next);
1795
+ }
1796
+ const nextManifest = {
1797
+ ...manifest,
1798
+ repos,
1799
+ scannedAt: changed ? (/* @__PURE__ */ new Date()).toISOString() : manifest.scannedAt
1800
+ };
1801
+ if (changed) {
1802
+ writeManifest(manifest.workdir, nextManifest);
1803
+ }
1804
+ return nextManifest;
1805
+ }
1806
+
1807
+ // src/deployment-config-sync.ts
1599
1808
  var TEMPLATE_HINT = "\u4FDD\u7559\u6A21\u677F .apm/apm.config.json";
1600
1809
  var SYNC_HINT = "\u767B\u8BB0\u5DE5\u4F5C\u7A7A\u95F4\u8DEF\u5F84\u3001\u7ED1\u5B9A\u4ED3\u5E93\u540E\uFF0C\u53EF\u6267\u884C: apm sync-deploy-config";
1601
1810
  async function resolveRepositoryIdForSync(api, workdirPath) {
@@ -1610,7 +1819,73 @@ async function resolveRepositoryIdForSync(api, workdirPath) {
1610
1819
  };
1611
1820
  }
1612
1821
  }
1613
- async function syncRemoteDeploymentConfig(workdirPath, apmDir) {
1822
+ async function resolveDeployCwdForRepository(workspaceRoot, repositoryId, api) {
1823
+ const start = resolveWorkdirPath(workspaceRoot);
1824
+ let manifest = findWorkspaceReposManifestNearPath(start);
1825
+ if (!manifest) {
1826
+ return null;
1827
+ }
1828
+ try {
1829
+ manifest = await enrichWorkspaceReposRemoteUrls(manifest);
1830
+ } catch {
1831
+ return null;
1832
+ }
1833
+ let client = api;
1834
+ if (!client) {
1835
+ const cfg = await tryReadApmConfig();
1836
+ if (!cfg || !resolveApiKey(cfg)) {
1837
+ return null;
1838
+ }
1839
+ client = createApmApiClient(cfg);
1840
+ }
1841
+ for (const entry of manifest.repos) {
1842
+ const abs = absoluteRepoPath(manifest.workdir, entry);
1843
+ const remoteUrl = toHttpsGitRemoteUrl(entry.remoteUrl ?? "");
1844
+ if (!remoteUrl) {
1845
+ continue;
1846
+ }
1847
+ let baseBranch = "";
1848
+ try {
1849
+ const gitRoot = await resolveGitRepoRoot(abs);
1850
+ baseBranch = (await resolveDefaultRemoteBranch(gitRoot)).trim();
1851
+ } catch {
1852
+ continue;
1853
+ }
1854
+ if (!baseBranch) {
1855
+ continue;
1856
+ }
1857
+ try {
1858
+ const matched = await client.cli.matchRepository({
1859
+ url: remoteUrl,
1860
+ baseBranch
1861
+ });
1862
+ if (matched.repositoryId?.trim() === repositoryId) {
1863
+ return abs;
1864
+ }
1865
+ } catch {
1866
+ continue;
1867
+ }
1868
+ }
1869
+ return null;
1870
+ }
1871
+ async function writeDeploymentConfigContent(apmDir, content, configName) {
1872
+ let parsed;
1873
+ try {
1874
+ parsed = JSON.parse(content);
1875
+ } catch {
1876
+ console.warn(
1877
+ `[apm] \u8FDC\u7A0B\u90E8\u7F72\u914D\u7F6E\u300C${configName}\u300DJSON \u65E0\u6548\uFF08${TEMPLATE_HINT}\uFF09`
1878
+ );
1879
+ return false;
1880
+ }
1881
+ const apmConfigPath = toFsPath(join4(apmDir, "apm.config.json"));
1882
+ writeFileSync4(apmConfigPath, `${JSON.stringify(parsed, null, 2)}
1883
+ `, "utf8");
1884
+ console.log(`[apm] \u5DF2\u540C\u6B65\u5E73\u53F0\u90E8\u7F72\u914D\u7F6E: ${configName}`);
1885
+ console.log("[apm] \u5DF2\u5199\u5165 .apm/apm.config.json");
1886
+ return true;
1887
+ }
1888
+ async function syncRemoteDeploymentConfig(workdirPath, apmDir, options) {
1614
1889
  const cfg = await tryReadApmConfig();
1615
1890
  if (!cfg || !resolveApiKey(cfg)) {
1616
1891
  console.log(
@@ -1620,10 +1895,14 @@ async function syncRemoteDeploymentConfig(workdirPath, apmDir) {
1620
1895
  return { synced: false, repositoryId: null };
1621
1896
  }
1622
1897
  const api = createApmApiClient(cfg);
1623
- const { repositoryId, diagnostic } = await resolveRepositoryIdForSync(
1624
- api,
1625
- workdirPath
1626
- );
1898
+ const preferredId = options?.repositoryId?.trim() || "";
1899
+ let repositoryId = preferredId || null;
1900
+ let diagnostic = null;
1901
+ if (!repositoryId) {
1902
+ const resolved = await resolveRepositoryIdForSync(api, workdirPath);
1903
+ repositoryId = resolved.repositoryId;
1904
+ diagnostic = resolved.diagnostic;
1905
+ }
1627
1906
  if (!repositoryId) {
1628
1907
  console.log(
1629
1908
  `[apm] \u672A\u80FD\u540C\u6B65\u5E73\u53F0\u90E8\u7F72\u914D\u7F6E\uFF08${TEMPLATE_HINT}\uFF09\u3002
@@ -1640,21 +1919,15 @@ ${diagnostic ?? ""}
1640
1919
  );
1641
1920
  return { synced: false, repositoryId };
1642
1921
  }
1643
- let parsed;
1644
- try {
1645
- parsed = JSON.parse(config.content);
1646
- } catch {
1647
- console.warn(
1648
- `[apm] \u8FDC\u7A0B\u90E8\u7F72\u914D\u7F6E\u300C${config.name}\u300DJSON \u65E0\u6548\uFF08${TEMPLATE_HINT}\uFF09`
1649
- );
1922
+ const targetApmDir = apmDir ?? workspaceApmDir(workdirPath);
1923
+ const wrote = await writeDeploymentConfigContent(
1924
+ targetApmDir,
1925
+ config.content,
1926
+ config.name
1927
+ );
1928
+ if (!wrote) {
1650
1929
  return { synced: false, repositoryId };
1651
1930
  }
1652
- const targetApmDir = apmDir ?? workspaceApmDir(workdirPath);
1653
- const apmConfigPath = toFsPath(join3(targetApmDir, "apm.config.json"));
1654
- writeFileSync3(apmConfigPath, `${JSON.stringify(parsed, null, 2)}
1655
- `, "utf8");
1656
- console.log(`[apm] \u5DF2\u540C\u6B65\u5E73\u53F0\u90E8\u7F72\u914D\u7F6E: ${config.name}`);
1657
- console.log("[apm] \u5DF2\u5199\u5165 .apm/apm.config.json");
1658
1931
  return { synced: true, repositoryId, configName: config.name };
1659
1932
  }
1660
1933
 
@@ -1662,14 +1935,14 @@ ${diagnostic ?? ""}
1662
1935
  init_client();
1663
1936
  init_config();
1664
1937
  import {
1665
- existsSync as existsSync2,
1666
- readdirSync as readdirSync2,
1667
- readFileSync as readFileSync3,
1938
+ existsSync as existsSync3,
1939
+ readdirSync as readdirSync3,
1940
+ readFileSync as readFileSync4,
1668
1941
  rmSync,
1669
- writeFileSync as writeFileSync4
1942
+ writeFileSync as writeFileSync5
1670
1943
  } from "fs";
1671
1944
  import { createHash } from "crypto";
1672
- import { dirname as dirname2, join as join4, relative, sep } from "path";
1945
+ import { dirname as dirname3, join as join5, relative as relative2, sep } from "path";
1673
1946
  var MANIFEST_FILE = "manifest.json";
1674
1947
  function normalizeProjectIdForPath(projectId) {
1675
1948
  const id = projectId.trim();
@@ -1683,11 +1956,11 @@ function normalizeProjectIdForPath(projectId) {
1683
1956
  }
1684
1957
  function projectDocumentsDir(apmRoot, projectId) {
1685
1958
  const id = normalizeProjectIdForPath(projectId);
1686
- return join4(apmRoot ?? workspaceApmDir(), "project", id);
1959
+ return join5(apmRoot ?? workspaceApmDir(), "project", id);
1687
1960
  }
1688
1961
  function projectDocumentLocalPath(apmRoot, projectId, documentPath) {
1689
1962
  const normalized = normalizeLocalDocumentPath(documentPath);
1690
- return join4(
1963
+ return join5(
1691
1964
  projectDocumentsDir(apmRoot, projectId),
1692
1965
  ...normalized.split("/")
1693
1966
  );
@@ -1707,16 +1980,16 @@ function hashLocalFileContent(content) {
1707
1980
  return createHash("sha256").update(content, "utf8").digest("hex");
1708
1981
  }
1709
1982
  function readLocalManifest(apmRoot, projectId) {
1710
- const manifestPath2 = join4(
1983
+ const manifestPath3 = join5(
1711
1984
  projectDocumentsDir(apmRoot, projectId),
1712
1985
  MANIFEST_FILE
1713
1986
  );
1714
- if (!existsSync2(manifestPath2)) {
1987
+ if (!existsSync3(manifestPath3)) {
1715
1988
  return null;
1716
1989
  }
1717
1990
  try {
1718
1991
  return JSON.parse(
1719
- readFileSync3(manifestPath2, "utf8")
1992
+ readFileSync4(manifestPath3, "utf8")
1720
1993
  );
1721
1994
  } catch {
1722
1995
  return null;
@@ -1724,13 +1997,13 @@ function readLocalManifest(apmRoot, projectId) {
1724
1997
  }
1725
1998
  function listLocalDocumentPaths(apmRoot, projectId) {
1726
1999
  const root = projectDocumentsDir(apmRoot, projectId);
1727
- if (!existsSync2(root)) {
2000
+ if (!existsSync3(root)) {
1728
2001
  return [];
1729
2002
  }
1730
2003
  const paths = [];
1731
2004
  const walk = (dir) => {
1732
- for (const entry of readdirSync2(dir, { withFileTypes: true })) {
1733
- const abs = join4(dir, entry.name);
2005
+ for (const entry of readdirSync3(dir, { withFileTypes: true })) {
2006
+ const abs = join5(dir, entry.name);
1734
2007
  if (entry.isDirectory()) {
1735
2008
  walk(abs);
1736
2009
  continue;
@@ -1738,7 +2011,7 @@ function listLocalDocumentPaths(apmRoot, projectId) {
1738
2011
  if (entry.isFile() && entry.name === MANIFEST_FILE) {
1739
2012
  continue;
1740
2013
  }
1741
- const rel = relative(root, abs).split(sep).join("/");
2014
+ const rel = relative2(root, abs).split(sep).join("/");
1742
2015
  paths.push(rel);
1743
2016
  }
1744
2017
  };
@@ -1848,8 +2121,8 @@ ${diagnostic ?? ""}`);
1848
2121
  const absPath = toFsPath(
1849
2122
  projectDocumentLocalPath(targetApmDir, projectId, doc.path)
1850
2123
  );
1851
- await ensureDirExists(dirname2(absPath));
1852
- writeFileSync4(absPath, doc.content, "utf8");
2124
+ await ensureDirExists(dirname3(absPath));
2125
+ writeFileSync5(absPath, doc.content, "utf8");
1853
2126
  downloaded += 1;
1854
2127
  }
1855
2128
  }
@@ -1858,13 +2131,13 @@ ${diagnostic ?? ""}`);
1858
2131
  const absPath = toFsPath(
1859
2132
  projectDocumentLocalPath(targetApmDir, projectId, path19)
1860
2133
  );
1861
- if (existsSync2(absPath)) {
2134
+ if (existsSync3(absPath)) {
1862
2135
  rmSync(absPath, { force: true });
1863
2136
  deleted += 1;
1864
2137
  }
1865
2138
  }
1866
- writeFileSync4(
1867
- toFsPath(join4(docsDir, MANIFEST_FILE)),
2139
+ writeFileSync5(
2140
+ toFsPath(join5(docsDir, MANIFEST_FILE)),
1868
2141
  `${JSON.stringify(remoteManifest, null, 2)}
1869
2142
  `,
1870
2143
  "utf8"
@@ -1907,7 +2180,7 @@ async function syncProjectDocumentsPush(cfg, workdirPath, apmRoot, options) {
1907
2180
  const absPath = toFsPath(
1908
2181
  projectDocumentLocalPath(targetApmDir, projectId, path19)
1909
2182
  );
1910
- const content = readFileSync3(absPath, "utf8");
2183
+ const content = readFileSync4(absPath, "utf8");
1911
2184
  const contentHash = hashLocalFileContent(content);
1912
2185
  if (remoteHashByPath.get(path19) === contentHash) {
1913
2186
  continue;
@@ -1946,11 +2219,11 @@ async function ensureWorkspaceInitialized(workdir, options) {
1946
2219
  await syncProjectDocumentsPull(workdir, apmDir);
1947
2220
  const trimmedName = options?.name?.trim();
1948
2221
  if (trimmedName) {
1949
- const apmConfigPath = toFsPath(join5(apmDir, "apm.config.json"));
1950
- const config = readFileSync4(apmConfigPath, "utf8");
2222
+ const apmConfigPath = toFsPath(join6(apmDir, "apm.config.json"));
2223
+ const config = readFileSync5(apmConfigPath, "utf8");
1951
2224
  const configJson = JSON.parse(config);
1952
2225
  configJson.name = trimmedName;
1953
- writeFileSync5(
2226
+ writeFileSync6(
1954
2227
  apmConfigPath,
1955
2228
  `${JSON.stringify(configJson, null, 2)}
1956
2229
  `,
@@ -1983,7 +2256,7 @@ async function runInit(name) {
1983
2256
  // src/commands/login.ts
1984
2257
  init_config();
1985
2258
  init_client();
1986
- import { existsSync as existsSync3 } from "fs";
2259
+ import { existsSync as existsSync4 } from "fs";
1987
2260
  import { ApiError } from "listpage-http";
1988
2261
  async function runLogin(opts) {
1989
2262
  const baseUrl = (opts.server?.trim() || process.env.AI_PM_SERVER?.trim() || DEFAULT_BASE_URL).replace(/\/+$/, "");
@@ -2038,7 +2311,7 @@ async function runLogin(opts) {
2038
2311
  );
2039
2312
  const workdir = resolveWorkdirPath();
2040
2313
  const apmDir = workspaceApmDir(workdir);
2041
- if (existsSync3(apmDir)) {
2314
+ if (existsSync4(apmDir)) {
2042
2315
  await syncRemoteDeploymentConfig(workdir, apmDir);
2043
2316
  }
2044
2317
  }
@@ -2494,8 +2767,8 @@ async function runCleanBranches(options = {}) {
2494
2767
 
2495
2768
  // src/commands/pull.ts
2496
2769
  init_client();
2497
- import { writeFileSync as writeFileSync9 } from "fs";
2498
- import { join as join9 } from "path";
2770
+ import { writeFileSync as writeFileSync10 } from "fs";
2771
+ import { join as join10 } from "path";
2499
2772
  import { stringify as yamlStringify } from "yaml";
2500
2773
 
2501
2774
  // src/session-messages-xml.ts
@@ -2528,8 +2801,8 @@ function formatSessionMessagesXml(sessionId, messages) {
2528
2801
  }
2529
2802
 
2530
2803
  // src/commands/sync-session-attachments.ts
2531
- import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync6 } from "fs";
2532
- import { join as join6 } from "path";
2804
+ import { existsSync as existsSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync7 } from "fs";
2805
+ import { join as join7 } from "path";
2533
2806
  var MANIFEST_FILE2 = ".sync-manifest.json";
2534
2807
  async function downloadAttachment(cfg, attachmentId) {
2535
2808
  const base = cfg.baseUrl.trim().replace(/\/+$/, "");
@@ -2545,13 +2818,13 @@ async function downloadAttachment(cfg, attachmentId) {
2545
2818
  return Buffer.from(await res.arrayBuffer());
2546
2819
  }
2547
2820
  function loadManifest(dir) {
2548
- const path19 = join6(dir, MANIFEST_FILE2);
2549
- if (!existsSync4(path19)) {
2821
+ const path19 = join7(dir, MANIFEST_FILE2);
2822
+ if (!existsSync5(path19)) {
2550
2823
  return { version: 1, attachments: {} };
2551
2824
  }
2552
2825
  try {
2553
2826
  const parsed = JSON.parse(
2554
- readFileSync5(path19, "utf8")
2827
+ readFileSync6(path19, "utf8")
2555
2828
  );
2556
2829
  if (parsed?.version === 1 && parsed.attachments && typeof parsed.attachments === "object") {
2557
2830
  return parsed;
@@ -2561,15 +2834,15 @@ function loadManifest(dir) {
2561
2834
  return { version: 1, attachments: {} };
2562
2835
  }
2563
2836
  function saveManifest(dir, manifest) {
2564
- writeFileSync6(
2565
- join6(dir, MANIFEST_FILE2),
2837
+ writeFileSync7(
2838
+ join7(dir, MANIFEST_FILE2),
2566
2839
  `${JSON.stringify(manifest, null, 2)}
2567
2840
  `,
2568
2841
  "utf8"
2569
2842
  );
2570
2843
  }
2571
2844
  function isAttachmentUpToDate(entry, item, dest) {
2572
- if (!entry || !existsSync4(dest)) return false;
2845
+ if (!entry || !existsSync5(dest)) return false;
2573
2846
  if (entry.name !== item.name) return false;
2574
2847
  const createdAt = item.createdAt ?? "";
2575
2848
  return entry.createdAt === createdAt;
@@ -2584,7 +2857,7 @@ async function syncAttachmentsToDirectory(cfg, attachments, dir, logLabel) {
2584
2857
  const nextManifest = { version: 1, attachments: {} };
2585
2858
  const names = [];
2586
2859
  for (const item of attachments) {
2587
- const dest = join6(dir, item.name);
2860
+ const dest = join7(dir, item.name);
2588
2861
  const entry = manifest.attachments[item.id];
2589
2862
  const createdAt = item.createdAt ?? "";
2590
2863
  names.push(item.name);
@@ -2594,7 +2867,7 @@ async function syncAttachmentsToDirectory(cfg, attachments, dir, logLabel) {
2594
2867
  continue;
2595
2868
  }
2596
2869
  const buffer = await downloadAttachment(cfg, item.id);
2597
- writeFileSync6(dest, buffer);
2870
+ writeFileSync7(dest, buffer);
2598
2871
  nextManifest.attachments[item.id] = {
2599
2872
  name: item.name,
2600
2873
  createdAt
@@ -2605,7 +2878,7 @@ async function syncAttachmentsToDirectory(cfg, attachments, dir, logLabel) {
2605
2878
  return names;
2606
2879
  }
2607
2880
  async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
2608
- const dir = join6(sessionDir(sessionId, apmRoot), SESSION_ATTACHMENTS_SUBDIR);
2881
+ const dir = join7(sessionDir(sessionId, apmRoot), SESSION_ATTACHMENTS_SUBDIR);
2609
2882
  return syncAttachmentsToDirectory(
2610
2883
  cfg,
2611
2884
  attachments,
@@ -2616,65 +2889,65 @@ async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
2616
2889
 
2617
2890
  // src/rules-sync.ts
2618
2891
  init_client();
2619
- import { basename as basename2, extname as extname2, join as join8 } from "path";
2620
- import { existsSync as existsSync6, readFileSync as readFileSync6, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
2892
+ import { basename as basename3, extname as extname2, join as join9 } from "path";
2893
+ import { existsSync as existsSync7, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync9 } from "fs";
2621
2894
 
2622
2895
  // src/skills-sync.ts
2623
2896
  import {
2624
2897
  copyFileSync as copyFileSync2,
2625
2898
  cpSync,
2626
- existsSync as existsSync5,
2627
- mkdirSync as mkdirSync3,
2628
- readdirSync as readdirSync3,
2899
+ existsSync as existsSync6,
2900
+ mkdirSync as mkdirSync4,
2901
+ readdirSync as readdirSync4,
2629
2902
  rmSync as rmSync2,
2630
- statSync as statSync2,
2631
- writeFileSync as writeFileSync7
2903
+ statSync as statSync3,
2904
+ writeFileSync as writeFileSync8
2632
2905
  } from "fs";
2633
- import { join as join7 } from "path";
2634
- var AGENTS_TEMPLATE_PATH = join7(CLI_TEMPLATE_DIR, "AGENTS.md");
2635
- var BASE_SKILLS_TEMPLATE_DIR = join7(CLI_TEMPLATE_DIR, "skills");
2636
- var BASE_RULES_TEMPLATE_DIR = join7(CLI_TEMPLATE_DIR, "rules");
2906
+ import { join as join8 } from "path";
2907
+ var AGENTS_TEMPLATE_PATH = join8(CLI_TEMPLATE_DIR, "AGENTS.md");
2908
+ var BASE_SKILLS_TEMPLATE_DIR = join8(CLI_TEMPLATE_DIR, "skills");
2909
+ var BASE_RULES_TEMPLATE_DIR = join8(CLI_TEMPLATE_DIR, "rules");
2637
2910
  function sanitizeSkillDirName(name) {
2638
2911
  const trimmed = name.trim();
2639
2912
  if (!trimmed) return "skill";
2640
2913
  return trimmed.replace(/[/\\:*?"<>|]/g, "_");
2641
2914
  }
2642
2915
  function listBaseSkillDirNames() {
2643
- if (!existsSync5(BASE_SKILLS_TEMPLATE_DIR)) return [];
2644
- return readdirSync3(BASE_SKILLS_TEMPLATE_DIR).filter((name) => {
2645
- const path19 = join7(BASE_SKILLS_TEMPLATE_DIR, name);
2646
- return statSync2(path19).isDirectory();
2916
+ if (!existsSync6(BASE_SKILLS_TEMPLATE_DIR)) return [];
2917
+ return readdirSync4(BASE_SKILLS_TEMPLATE_DIR).filter((name) => {
2918
+ const path19 = join8(BASE_SKILLS_TEMPLATE_DIR, name);
2919
+ return statSync3(path19).isDirectory();
2647
2920
  });
2648
2921
  }
2649
2922
  function syncAgentsGuide(apmDir) {
2650
- if (!existsSync5(AGENTS_TEMPLATE_PATH)) return false;
2651
- mkdirSync3(apmDir, { recursive: true });
2652
- copyFileSync2(AGENTS_TEMPLATE_PATH, join7(apmDir, "AGENTS.md"));
2923
+ if (!existsSync6(AGENTS_TEMPLATE_PATH)) return false;
2924
+ mkdirSync4(apmDir, { recursive: true });
2925
+ copyFileSync2(AGENTS_TEMPLATE_PATH, join8(apmDir, "AGENTS.md"));
2653
2926
  return true;
2654
2927
  }
2655
2928
  function listBaseRuleFileNames() {
2656
- if (!existsSync5(BASE_RULES_TEMPLATE_DIR)) return [];
2657
- return readdirSync3(BASE_RULES_TEMPLATE_DIR).filter((name) => {
2658
- const path19 = join7(BASE_RULES_TEMPLATE_DIR, name);
2659
- return statSync2(path19).isFile();
2929
+ if (!existsSync6(BASE_RULES_TEMPLATE_DIR)) return [];
2930
+ return readdirSync4(BASE_RULES_TEMPLATE_DIR).filter((name) => {
2931
+ const path19 = join8(BASE_RULES_TEMPLATE_DIR, name);
2932
+ return statSync3(path19).isFile();
2660
2933
  });
2661
2934
  }
2662
2935
  function syncBaseRules(rulesDir) {
2663
- mkdirSync3(rulesDir, { recursive: true });
2936
+ mkdirSync4(rulesDir, { recursive: true });
2664
2937
  const names = listBaseRuleFileNames();
2665
2938
  for (const name of names) {
2666
- const src = join7(BASE_RULES_TEMPLATE_DIR, name);
2667
- const dest = join7(rulesDir, name);
2939
+ const src = join8(BASE_RULES_TEMPLATE_DIR, name);
2940
+ const dest = join8(rulesDir, name);
2668
2941
  copyFileSync2(src, dest);
2669
2942
  }
2670
2943
  return names;
2671
2944
  }
2672
2945
  function syncBaseSkills(skillsDir) {
2673
- mkdirSync3(skillsDir, { recursive: true });
2946
+ mkdirSync4(skillsDir, { recursive: true });
2674
2947
  const names = listBaseSkillDirNames();
2675
2948
  for (const name of names) {
2676
- const src = join7(BASE_SKILLS_TEMPLATE_DIR, name);
2677
- const dest = join7(skillsDir, name);
2949
+ const src = join8(BASE_SKILLS_TEMPLATE_DIR, name);
2950
+ const dest = join8(skillsDir, name);
2678
2951
  cpSync(src, dest, { recursive: true, force: true });
2679
2952
  }
2680
2953
  return names;
@@ -2691,16 +2964,16 @@ function syncSupplementarySkills(skillsDir, list) {
2691
2964
  skipped.push(dirName);
2692
2965
  continue;
2693
2966
  }
2694
- const skillDir = join7(skillsDir, dirName);
2695
- mkdirSync3(skillDir, { recursive: true });
2696
- writeFileSync7(join7(skillDir, "SKILL.md"), skill.content ?? "", "utf8");
2967
+ const skillDir = join8(skillsDir, dirName);
2968
+ mkdirSync4(skillDir, { recursive: true });
2969
+ writeFileSync8(join8(skillDir, "SKILL.md"), skill.content ?? "", "utf8");
2697
2970
  written.push(dirName);
2698
2971
  }
2699
2972
  const removed = [];
2700
- if (!existsSync5(skillsDir)) return { written, skipped, removed };
2701
- for (const entry of readdirSync3(skillsDir)) {
2702
- const full = join7(skillsDir, entry);
2703
- if (!statSync2(full).isDirectory()) continue;
2973
+ if (!existsSync6(skillsDir)) return { written, skipped, removed };
2974
+ for (const entry of readdirSync4(skillsDir)) {
2975
+ const full = join8(skillsDir, entry);
2976
+ if (!statSync3(full).isDirectory()) continue;
2704
2977
  if (baseNames.has(entry)) continue;
2705
2978
  if (apiDirNames.has(entry)) continue;
2706
2979
  rmSync2(full, { recursive: true, force: true });
@@ -2719,13 +2992,13 @@ function ruleLocalFileName(ruleName) {
2719
2992
  return `${sanitized}.md`;
2720
2993
  }
2721
2994
  function loadManifest2(rulesDir) {
2722
- const path19 = join8(rulesDir, MANIFEST_FILE3);
2723
- if (!existsSync6(toFsPath(path19))) {
2995
+ const path19 = join9(rulesDir, MANIFEST_FILE3);
2996
+ if (!existsSync7(toFsPath(path19))) {
2724
2997
  return { version: 1, rules: {} };
2725
2998
  }
2726
2999
  try {
2727
3000
  const parsed = JSON.parse(
2728
- readFileSync6(toFsPath(path19), "utf8")
3001
+ readFileSync7(toFsPath(path19), "utf8")
2729
3002
  );
2730
3003
  if (parsed?.version === 1 && parsed.rules && typeof parsed.rules === "object") {
2731
3004
  return parsed;
@@ -2735,29 +3008,29 @@ function loadManifest2(rulesDir) {
2735
3008
  return { version: 1, rules: {} };
2736
3009
  }
2737
3010
  function saveManifest2(rulesDir, manifest) {
2738
- writeFileSync8(
2739
- toFsPath(join8(rulesDir, MANIFEST_FILE3)),
3011
+ writeFileSync9(
3012
+ toFsPath(join9(rulesDir, MANIFEST_FILE3)),
2740
3013
  `${JSON.stringify(manifest, null, 2)}
2741
3014
  `,
2742
3015
  "utf8"
2743
3016
  );
2744
3017
  }
2745
3018
  function isBaseRuleFileName(fileName) {
2746
- return listBaseRuleFileNames().includes(basename2(fileName));
3019
+ return listBaseRuleFileNames().includes(basename3(fileName));
2747
3020
  }
2748
3021
  function isRuleUpToDate(entry, rule, dest) {
2749
- if (!entry || !existsSync6(toFsPath(dest))) return false;
3022
+ if (!entry || !existsSync7(toFsPath(dest))) return false;
2750
3023
  if (entry.fileName !== ruleLocalFileName(rule.name)) return false;
2751
3024
  const updatedAt = rule.updatedAt ?? "";
2752
3025
  if (entry.updatedAt !== updatedAt) return false;
2753
- const localContent = readFileSync6(toFsPath(dest), "utf8");
3026
+ const localContent = readFileSync7(toFsPath(dest), "utf8");
2754
3027
  return localContent === (rule.content ?? "");
2755
3028
  }
2756
3029
  async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
2757
3030
  const api = createApmApiClient(cfg);
2758
3031
  const baseline = await resolveBranchBaseline(api, sessionId, workdirPath);
2759
3032
  const repositoryId = baseline.repositoryId;
2760
- const rulesDir = join8(apmRoot ?? workspaceApmDir(workdirPath), "rules");
3033
+ const rulesDir = join9(apmRoot ?? workspaceApmDir(workdirPath), "rules");
2761
3034
  await ensureDirExists(rulesDir);
2762
3035
  if (!repositoryId) {
2763
3036
  console.log(
@@ -2774,7 +3047,7 @@ async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
2774
3047
  for (const rule of list) {
2775
3048
  remoteIds.add(rule.id);
2776
3049
  const fileName = ruleLocalFileName(rule.name);
2777
- const dest = join8(rulesDir, fileName);
3050
+ const dest = join9(rulesDir, fileName);
2778
3051
  const entry = manifest.rules[rule.id];
2779
3052
  const updatedAt = rule.updatedAt ?? "";
2780
3053
  if (isRuleUpToDate(entry, rule, dest)) {
@@ -2783,7 +3056,7 @@ async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
2783
3056
  console.log(`[apm] \u89C4\u5219\u65E0\u53D8\u5316\uFF0C\u5DF2\u8DF3\u8FC7: rules/${fileName}`);
2784
3057
  continue;
2785
3058
  }
2786
- writeFileSync8(toFsPath(dest), rule.content ?? "", "utf8");
3059
+ writeFileSync9(toFsPath(dest), rule.content ?? "", "utf8");
2787
3060
  nextManifest.rules[rule.id] = { fileName, updatedAt };
2788
3061
  written.push(fileName);
2789
3062
  console.log(`[apm] \u5DF2\u540C\u6B65\u5E73\u53F0\u89C4\u5219: rules/${fileName}`);
@@ -2792,8 +3065,8 @@ async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
2792
3065
  for (const [ruleId, entry] of Object.entries(manifest.rules)) {
2793
3066
  if (remoteIds.has(ruleId)) continue;
2794
3067
  if (isBaseRuleFileName(entry.fileName)) continue;
2795
- const dest = join8(rulesDir, entry.fileName);
2796
- if (existsSync6(toFsPath(dest))) {
3068
+ const dest = join9(rulesDir, entry.fileName);
3069
+ if (existsSync7(toFsPath(dest))) {
2797
3070
  rmSync3(toFsPath(dest), { force: true });
2798
3071
  }
2799
3072
  removed.push(entry.fileName);
@@ -2824,20 +3097,20 @@ async function runPull(sessionId, remoteWorkdir) {
2824
3097
  const dir = sessionDir(trimmedId, apmRoot);
2825
3098
  const docsDir = sessionDocsDir(trimmedId, apmRoot);
2826
3099
  await ensureDirExists(docsDir);
2827
- writeFileSync9(
3100
+ writeFileSync10(
2828
3101
  sessionRulePath(trimmedId, apmRoot),
2829
3102
  detail.description ?? "",
2830
3103
  "utf8"
2831
3104
  );
2832
- writeFileSync9(
3105
+ writeFileSync10(
2833
3106
  sessionTaskPath(trimmedId, apmRoot),
2834
3107
  detail.task.description ?? "",
2835
3108
  "utf8"
2836
3109
  );
2837
- writeFileSync9(sessionTodoPath(trimmedId, apmRoot), detail.todo ?? "", "utf8");
3110
+ writeFileSync10(sessionTodoPath(trimmedId, apmRoot), detail.todo ?? "", "utf8");
2838
3111
  for (const doc of documents) {
2839
3112
  const fileName = documentLocalFileName(doc.name);
2840
- writeFileSync9(join9(docsDir, fileName), doc.content ?? "", "utf8");
3113
+ writeFileSync10(join10(docsDir, fileName), doc.content ?? "", "utf8");
2841
3114
  }
2842
3115
  const sessionYaml = yamlStringify(
2843
3116
  {
@@ -2854,13 +3127,13 @@ async function runPull(sessionId, remoteWorkdir) {
2854
3127
  },
2855
3128
  { lineWidth: 0 }
2856
3129
  );
2857
- writeFileSync9(
3130
+ writeFileSync10(
2858
3131
  sessionYamlPath(trimmedId, apmRoot),
2859
3132
  sessionYaml.endsWith("\n") ? sessionYaml : `${sessionYaml}
2860
3133
  `,
2861
3134
  "utf8"
2862
3135
  );
2863
- writeFileSync9(
3136
+ writeFileSync10(
2864
3137
  sessionMessagesXmlPath(trimmedId, apmRoot),
2865
3138
  formatSessionMessagesXml(trimmedId, messages),
2866
3139
  "utf8"
@@ -2877,15 +3150,15 @@ async function runPull(sessionId, remoteWorkdir) {
2877
3150
  import { spawnSync } from "child_process";
2878
3151
 
2879
3152
  // src/version.ts
2880
- import { readFileSync as readFileSync7 } from "fs";
2881
- import { dirname as dirname3, join as join10 } from "path";
3153
+ import { readFileSync as readFileSync8 } from "fs";
3154
+ import { dirname as dirname4, join as join11 } from "path";
2882
3155
  import { fileURLToPath as fileURLToPath2 } from "url";
2883
3156
  var CLI_PACKAGE_NAME = "ai-project-manage-cli";
2884
3157
  function readCliVersion() {
2885
3158
  try {
2886
- const dir = dirname3(fileURLToPath2(import.meta.url));
2887
- const pkgPath = join10(dir, "..", "package.json");
2888
- const pkg = JSON.parse(readFileSync7(pkgPath, "utf8"));
3159
+ const dir = dirname4(fileURLToPath2(import.meta.url));
3160
+ const pkgPath = join11(dir, "..", "package.json");
3161
+ const pkg = JSON.parse(readFileSync8(pkgPath, "utf8"));
2889
3162
  return pkg.version ?? "0.0.0";
2890
3163
  } catch {
2891
3164
  return "0.0.0";
@@ -3039,15 +3312,15 @@ async function runUpdate(options = {}) {
3039
3312
 
3040
3313
  // src/commands/update-skills.ts
3041
3314
  init_client();
3042
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, statSync as statSync3 } from "fs";
3043
- import { join as join11 } from "path";
3315
+ import { existsSync as existsSync8, mkdirSync as mkdirSync5, statSync as statSync4 } from "fs";
3316
+ import { join as join12 } from "path";
3044
3317
  async function syncWorkspaceSkills(cfg, workdir) {
3045
3318
  const apmDir = workspaceApmDir(workdir);
3046
3319
  const fsApmDir = toFsPath(apmDir);
3047
- if (!existsSync7(fsApmDir)) {
3320
+ if (!existsSync8(fsApmDir)) {
3048
3321
  throw new Error("[apm] \u672A\u627E\u5230 .apm \u76EE\u5F55\uFF0C\u8BF7\u5148\u6267\u884C apm init");
3049
3322
  }
3050
- const apmStat = statSync3(fsApmDir);
3323
+ const apmStat = statSync4(fsApmDir);
3051
3324
  if (!apmStat.isDirectory()) {
3052
3325
  throw new Error(`[apm] \u8DEF\u5F84\u5DF2\u5B58\u5728\u4F46\u4E0D\u662F\u76EE\u5F55: ${apmDir}`);
3053
3326
  }
@@ -3056,13 +3329,13 @@ async function syncWorkspaceSkills(cfg, workdir) {
3056
3329
  if (syncAgentsGuide(apmDir)) {
3057
3330
  console.log("[apm] \u5DF2\u540C\u6B65 APM \u6307\u5357: .apm/AGENTS.md");
3058
3331
  }
3059
- const rulesDir = join11(apmDir, "rules");
3332
+ const rulesDir = join12(apmDir, "rules");
3060
3333
  const ruleNames = syncBaseRules(rulesDir);
3061
3334
  for (const name of ruleNames) {
3062
3335
  console.log(`[apm] \u5DF2\u540C\u6B65\u57FA\u7840\u89C4\u5219: rules/${name}`);
3063
3336
  }
3064
- const skillsDir = join11(apmDir, "skills");
3065
- mkdirSync4(toFsPath(skillsDir), { recursive: true });
3337
+ const skillsDir = join12(apmDir, "skills");
3338
+ mkdirSync5(toFsPath(skillsDir), { recursive: true });
3066
3339
  const baseNames = syncBaseSkills(skillsDir);
3067
3340
  for (const name of baseNames) {
3068
3341
  console.log(`[apm] \u5DF2\u540C\u6B65\u57FA\u7840\u6280\u80FD: skills/${name}/`);
@@ -3088,11 +3361,11 @@ async function syncWorkspaceSkills(cfg, workdir) {
3088
3361
  }
3089
3362
  async function runUpdateSkills() {
3090
3363
  const apmDir = workspaceApmDir();
3091
- if (!existsSync7(apmDir)) {
3364
+ if (!existsSync8(apmDir)) {
3092
3365
  console.error("[apm] \u672A\u627E\u5230 .apm \u76EE\u5F55\uFF0C\u8BF7\u5148\u6267\u884C apm init");
3093
3366
  process.exit(1);
3094
3367
  }
3095
- const apmStat = statSync3(apmDir);
3368
+ const apmStat = statSync4(apmDir);
3096
3369
  if (!apmStat.isDirectory()) {
3097
3370
  throw new Error(`[apm] \u8DEF\u5F84\u5DF2\u5B58\u5728\u4F46\u4E0D\u662F\u76EE\u5F55: ${apmDir}`);
3098
3371
  }
@@ -3101,15 +3374,15 @@ async function runUpdateSkills() {
3101
3374
  }
3102
3375
 
3103
3376
  // src/commands/sync-deploy-config.ts
3104
- import { existsSync as existsSync8, statSync as statSync4 } from "fs";
3377
+ import { existsSync as existsSync9, statSync as statSync5 } from "fs";
3105
3378
  async function runSyncDeployConfig() {
3106
3379
  const workdir = resolveWorkdirPath();
3107
3380
  const apmDir = workspaceApmDir(workdir);
3108
- if (!existsSync8(apmDir)) {
3381
+ if (!existsSync9(apmDir)) {
3109
3382
  console.error("[apm] \u672A\u627E\u5230 .apm \u76EE\u5F55\uFF0C\u8BF7\u5148\u6267\u884C apm init");
3110
3383
  process.exit(1);
3111
3384
  }
3112
- const apmStat = statSync4(apmDir);
3385
+ const apmStat = statSync5(apmDir);
3113
3386
  if (!apmStat.isDirectory()) {
3114
3387
  throw new Error(`[apm] \u8DEF\u5F84\u5DF2\u5B58\u5728\u4F46\u4E0D\u662F\u76EE\u5F55: ${apmDir}`);
3115
3388
  }
@@ -3140,8 +3413,8 @@ async function runSyncProjectDocuments(options) {
3140
3413
  }
3141
3414
 
3142
3415
  // src/commands/sync-document.ts
3143
- import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
3144
- import { basename as basename3 } from "path";
3416
+ import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
3417
+ import { basename as basename4 } from "path";
3145
3418
 
3146
3419
  // src/assumptions/local-validate.ts
3147
3420
  var NO_ASSUMPTIONS_RE = /无[,,]?\s*口径均有依据/;
@@ -3311,13 +3584,13 @@ init_client();
3311
3584
 
3312
3585
  // src/commands/sync-session-documents.ts
3313
3586
  init_client();
3314
- import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync8 } from "fs";
3315
- import { join as join12 } from "path";
3587
+ import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync9 } from "fs";
3588
+ import { join as join13 } from "path";
3316
3589
  function listLocalMarkdownFiles(docsDir) {
3317
- if (!existsSync9(docsDir)) {
3590
+ if (!existsSync10(docsDir)) {
3318
3591
  return [];
3319
3592
  }
3320
- return readdirSync4(docsDir).filter(
3593
+ return readdirSync5(docsDir).filter(
3321
3594
  (name) => name.toLowerCase().endsWith(".md")
3322
3595
  );
3323
3596
  }
@@ -3329,8 +3602,8 @@ function remoteDocumentByLocalName(remoteDocuments, localFileName) {
3329
3602
  });
3330
3603
  }
3331
3604
  async function upsertLocalDocumentFile(api, sessionId, docsDir, fileName) {
3332
- const absPath = join12(docsDir, fileName);
3333
- const content = readFileSync8(absPath, "utf8");
3605
+ const absPath = join13(docsDir, fileName);
3606
+ const content = readFileSync9(absPath, "utf8");
3334
3607
  const name = documentPlatformName(absPath);
3335
3608
  return api.cli.upsertDocument({
3336
3609
  sessionId,
@@ -3352,8 +3625,8 @@ async function syncSessionDocuments(cfg, sessionId, apmRoot, options) {
3352
3625
  const remoteDocuments = options?.remoteDocuments ?? await api.cli.listDocuments({ sessionId: trimmedSessionId });
3353
3626
  let synced = 0;
3354
3627
  for (const fileName of localFiles) {
3355
- const absPath = join12(docsDir, fileName);
3356
- const content = readFileSync8(absPath, "utf8");
3628
+ const absPath = join13(docsDir, fileName);
3629
+ const content = readFileSync9(absPath, "utf8");
3357
3630
  const remote = remoteDocumentByLocalName(remoteDocuments, fileName);
3358
3631
  if (remote && remote.content === content) {
3359
3632
  continue;
@@ -3386,7 +3659,7 @@ async function runSyncDocument(sessionId, options) {
3386
3659
  process.exit(1);
3387
3660
  }
3388
3661
  const absPath = resolveSessionDocumentPath(trimmedSessionId, fileArg);
3389
- if (!existsSync10(absPath)) {
3662
+ if (!existsSync11(absPath)) {
3390
3663
  const docsDir2 = sessionDocsDir(trimmedSessionId);
3391
3664
  console.error(
3392
3665
  `[apm] \u6587\u6863\u4E0D\u5B58\u5728: ${absPath}
@@ -3394,10 +3667,10 @@ async function runSyncDocument(sessionId, options) {
3394
3667
  );
3395
3668
  process.exit(1);
3396
3669
  }
3397
- const fileName = basename3(absPath);
3670
+ const fileName = basename4(absPath);
3398
3671
  const assumptionSource = resolveAssumptionSourceFromFileName(fileName);
3399
3672
  if (assumptionSource) {
3400
- const content = readFileSync9(absPath, "utf8");
3673
+ const content = readFileSync10(absPath, "utf8");
3401
3674
  const validation = validateAssumptionsMarkdown(content, assumptionSource);
3402
3675
  if (!validation.ok) {
3403
3676
  printAssumptionValidationResult(validation);
@@ -3414,7 +3687,7 @@ async function runSyncDocument(sessionId, options) {
3414
3687
  api,
3415
3688
  trimmedSessionId,
3416
3689
  docsDir,
3417
- basename3(absPath)
3690
+ basename4(absPath)
3418
3691
  );
3419
3692
  console.log(`[apm] \u5DF2\u540C\u6B65\u6587\u6863: ${doc.name} (id=${doc.id})`);
3420
3693
  const assumptionSync = doc.assumptionSync;
@@ -3652,6 +3925,7 @@ function validateDeployPush(o) {
3652
3925
  deploymentRunId: o.deploymentRunId.trim(),
3653
3926
  workdir: o.workdir.trim(),
3654
3927
  environment,
3928
+ ...typeof o.repositoryId === "string" && o.repositoryId.trim() ? { repositoryId: o.repositoryId.trim() } : {},
3655
3929
  ...o.packOnly === true ? { packOnly: true } : {}
3656
3930
  }
3657
3931
  };
@@ -3759,8 +4033,8 @@ init_client();
3759
4033
  import path11 from "node:path";
3760
4034
 
3761
4035
  // src/commands/deploy/internal/apm-config.ts
3762
- import { existsSync as existsSync12, readFileSync as readFileSync11 } from "node:fs";
3763
- import { resolve as resolve4 } from "node:path";
4036
+ import { existsSync as existsSync13, readFileSync as readFileSync12 } from "node:fs";
4037
+ import { resolve as resolve5 } from "node:path";
3764
4038
 
3765
4039
  // src/commands/deploy/internal/config/config-validation.ts
3766
4040
  function req(v, field, section) {
@@ -3852,9 +4126,9 @@ function resolveFrontendDeployFromApmConfig(cfg) {
3852
4126
  }
3853
4127
 
3854
4128
  // src/commands/deploy/internal/config/maven-repo.ts
3855
- import { existsSync as existsSync11, readFileSync as readFileSync10 } from "node:fs";
4129
+ import { existsSync as existsSync12, readFileSync as readFileSync11 } from "node:fs";
3856
4130
  import { homedir as homedir2 } from "node:os";
3857
- import { join as join13, resolve as resolve3 } from "node:path";
4131
+ import { join as join14, resolve as resolve4 } from "node:path";
3858
4132
  var MAVEN_REPO_ENV_KEYS = [
3859
4133
  "MAVEN_LOCAL_REPO",
3860
4134
  "M2_REPO",
@@ -3887,7 +4161,7 @@ function expandUserPath(pathStr, env = process.env) {
3887
4161
  if (/^[a-zA-Z]:[/\\]/.test(expanded)) {
3888
4162
  return expanded;
3889
4163
  }
3890
- return resolve3(expanded);
4164
+ return resolve4(expanded);
3891
4165
  }
3892
4166
  function readMavenLocalRepoFromMavenOpts(mavenOpts, env = process.env) {
3893
4167
  const match = mavenOpts.match(/-Dmaven\.repo\.local=(?:"([^"]+)"|(\S+))/);
@@ -3911,12 +4185,12 @@ function readMavenLocalRepoFromEnv(env = process.env) {
3911
4185
  return null;
3912
4186
  }
3913
4187
  function readMavenLocalRepoFromSettings() {
3914
- const settingsPath = join13(homedir2(), ".m2", "settings.xml");
3915
- if (!existsSync11(settingsPath)) {
4188
+ const settingsPath = join14(homedir2(), ".m2", "settings.xml");
4189
+ if (!existsSync12(settingsPath)) {
3916
4190
  return null;
3917
4191
  }
3918
4192
  try {
3919
- const xml = readFileSync10(settingsPath, "utf8");
4193
+ const xml = readFileSync11(settingsPath, "utf8");
3920
4194
  const match = xml.match(
3921
4195
  /<localRepository>\s*([^<]+?)\s*<\/localRepository>/
3922
4196
  );
@@ -3947,7 +4221,7 @@ function resolveMavenLocalRepoWithSource() {
3947
4221
  };
3948
4222
  }
3949
4223
  return {
3950
- path: join13(homedir2(), ".m2", "repository"),
4224
+ path: join14(homedir2(), ".m2", "repository"),
3951
4225
  source: "default",
3952
4226
  sourceDetail: "~/.m2/repository"
3953
4227
  };
@@ -4043,16 +4317,16 @@ function resolveWisdomBackendDeployFromApmConfig(cfg) {
4043
4317
 
4044
4318
  // src/commands/deploy/internal/apm-config.ts
4045
4319
  function loadApmConfig(options) {
4046
- const p = resolve4(
4320
+ const p = resolve5(
4047
4321
  process.cwd(),
4048
- options?.configPath ?? resolve4(workspaceApmDir(), "apm.config.json")
4322
+ options?.configPath ?? resolve5(workspaceApmDir(), "apm.config.json")
4049
4323
  );
4050
- if (!existsSync12(p)) {
4324
+ if (!existsSync13(p)) {
4051
4325
  console.error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF1A${p}`);
4052
4326
  process.exit(1);
4053
4327
  }
4054
4328
  try {
4055
- const raw = readFileSync11(p, "utf8");
4329
+ const raw = readFileSync12(p, "utf8");
4056
4330
  return JSON.parse(raw);
4057
4331
  } catch (e) {
4058
4332
  console.error(`\u65E0\u6CD5\u89E3\u6790 apm.config.json\uFF1A${p}`, e);
@@ -4098,32 +4372,32 @@ var DeployExecutionError = class extends Error {
4098
4372
  // src/commands/deploy/deploy-debug-log.ts
4099
4373
  init_deploy_artifact_minio();
4100
4374
  import { spawnSync as spawnSync4 } from "node:child_process";
4101
- import { existsSync as existsSync16 } from "node:fs";
4102
- import { dirname as dirname5, join as join17 } from "node:path";
4375
+ import { existsSync as existsSync17 } from "node:fs";
4376
+ import { dirname as dirname6, join as join18 } from "node:path";
4103
4377
 
4104
4378
  // src/commands/deploy/internal/deploy-shell-env.ts
4105
4379
  import { spawnSync as spawnSync3 } from "node:child_process";
4106
- import { existsSync as existsSync15 } from "node:fs";
4107
- import { dirname as dirname4, join as join16 } from "node:path";
4380
+ import { existsSync as existsSync16 } from "node:fs";
4381
+ import { dirname as dirname5, join as join17 } from "node:path";
4108
4382
 
4109
4383
  // src/commands/daemon.ts
4110
4384
  init_config();
4111
4385
  import { spawnSync as spawnSync2 } from "child_process";
4112
4386
  import { setTimeout as delay } from "node:timers/promises";
4113
- import { existsSync as existsSync14, mkdirSync as mkdirSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync11 } from "fs";
4114
- import { join as join15 } from "path";
4387
+ import { existsSync as existsSync15, mkdirSync as mkdirSync7, unlinkSync as unlinkSync2, writeFileSync as writeFileSync12 } from "fs";
4388
+ import { join as join16 } from "path";
4115
4389
 
4116
4390
  // src/commands/connect-lock.ts
4117
4391
  init_config();
4118
4392
  import {
4119
- existsSync as existsSync13,
4120
- mkdirSync as mkdirSync5,
4121
- readFileSync as readFileSync12,
4393
+ existsSync as existsSync14,
4394
+ mkdirSync as mkdirSync6,
4395
+ readFileSync as readFileSync13,
4122
4396
  unlinkSync,
4123
- writeFileSync as writeFileSync10
4397
+ writeFileSync as writeFileSync11
4124
4398
  } from "fs";
4125
- import { join as join14 } from "path";
4126
- var CONNECT_LOCK_PATH = join14(APM_CONFIG_DIR, "connect.lock");
4399
+ import { join as join15 } from "path";
4400
+ var CONNECT_LOCK_PATH = join15(APM_CONFIG_DIR, "connect.lock");
4127
4401
  function isProcessAlive(pid) {
4128
4402
  if (!Number.isInteger(pid) || pid <= 0) return false;
4129
4403
  try {
@@ -4150,9 +4424,9 @@ function waitForPm2LockHandoff(timeoutMs = 5e3) {
4150
4424
  }
4151
4425
  }
4152
4426
  function readConnectLock() {
4153
- if (!existsSync13(CONNECT_LOCK_PATH)) return null;
4427
+ if (!existsSync14(CONNECT_LOCK_PATH)) return null;
4154
4428
  try {
4155
- const raw = readFileSync12(CONNECT_LOCK_PATH, "utf8");
4429
+ const raw = readFileSync13(CONNECT_LOCK_PATH, "utf8");
4156
4430
  const parsed = JSON.parse(raw);
4157
4431
  if (typeof parsed.pid !== "number" || parsed.mode !== "foreground" && parsed.mode !== "pm2" || typeof parsed.startedAt !== "string") {
4158
4432
  return null;
@@ -4187,13 +4461,13 @@ function acquireConnectLock(mode) {
4187
4461
  process.exit(1);
4188
4462
  }
4189
4463
  }
4190
- mkdirSync5(APM_CONFIG_DIR, { recursive: true });
4464
+ mkdirSync6(APM_CONFIG_DIR, { recursive: true });
4191
4465
  const lock = {
4192
4466
  pid: process.pid,
4193
4467
  mode,
4194
4468
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
4195
4469
  };
4196
- writeFileSync10(
4470
+ writeFileSync11(
4197
4471
  CONNECT_LOCK_PATH,
4198
4472
  JSON.stringify(lock, null, 2) + "\n",
4199
4473
  "utf8"
@@ -4209,7 +4483,7 @@ function releaseConnectLock() {
4209
4483
  }
4210
4484
  function forceReleaseConnectLock() {
4211
4485
  try {
4212
- if (existsSync13(CONNECT_LOCK_PATH)) {
4486
+ if (existsSync14(CONNECT_LOCK_PATH)) {
4213
4487
  unlinkSync(CONNECT_LOCK_PATH);
4214
4488
  }
4215
4489
  } catch {
@@ -4218,16 +4492,16 @@ function forceReleaseConnectLock() {
4218
4492
 
4219
4493
  // src/commands/daemon.ts
4220
4494
  var PM2_APP_NAME = "apm-connect";
4221
- var PM2_ECOSYSTEM_PATH = join15(
4495
+ var PM2_ECOSYSTEM_PATH = join16(
4222
4496
  APM_CONFIG_DIR,
4223
4497
  "connect.ecosystem.config.cjs"
4224
4498
  );
4225
- var PM2_CONNECT_ENTRY_PATH = join15(APM_CONFIG_DIR, "connect.entry.cjs");
4226
- var PM2_CONNECT_LAUNCH_PATH = join15(
4499
+ var PM2_CONNECT_ENTRY_PATH = join16(APM_CONFIG_DIR, "connect.entry.cjs");
4500
+ var PM2_CONNECT_LAUNCH_PATH = join16(
4227
4501
  APM_CONFIG_DIR,
4228
4502
  "connect.launch.json"
4229
4503
  );
4230
- var LEGACY_PM2_ECOSYSTEM_PATH = join15(
4504
+ var LEGACY_PM2_ECOSYSTEM_PATH = join16(
4231
4505
  APM_CONFIG_DIR,
4232
4506
  "connect.ecosystem.cjs"
4233
4507
  );
@@ -4358,8 +4632,8 @@ function resolvePm2FromNpmRoot() {
4358
4632
  const root = rootResult.stdout?.toString().trim();
4359
4633
  if (!root) return null;
4360
4634
  for (const rel of ["pm2/bin/pm2", "pm2/bin/pm2.js"]) {
4361
- const candidate = join15(root, ...rel.split("/"));
4362
- if (existsSync14(candidate)) {
4635
+ const candidate = join16(root, ...rel.split("/"));
4636
+ if (existsSync15(candidate)) {
4363
4637
  return candidate;
4364
4638
  }
4365
4639
  }
@@ -4396,7 +4670,7 @@ function spawnPm2At(binPath, args, options = {}) {
4396
4670
  return spawnPm2Target(buildPm2SpawnTarget(binPath), args, options);
4397
4671
  }
4398
4672
  function verifyPm2Bin(pm2Bin) {
4399
- if (!pm2Bin.trim() || !existsSync14(pm2Bin)) {
4673
+ if (!pm2Bin.trim() || !existsSync15(pm2Bin)) {
4400
4674
  return false;
4401
4675
  }
4402
4676
  const result = spawnPm2At(pm2Bin, ["--version"], {
@@ -4409,10 +4683,10 @@ function collectPm2Candidates() {
4409
4683
  const globalBin = resolveNpmGlobalBin();
4410
4684
  if (globalBin) {
4411
4685
  if (useNpmShell2) {
4412
- candidates.push(join15(globalBin, "pm2.cmd"));
4413
- candidates.push(join15(globalBin, "pm2"));
4686
+ candidates.push(join16(globalBin, "pm2.cmd"));
4687
+ candidates.push(join16(globalBin, "pm2"));
4414
4688
  } else {
4415
- candidates.push(join15(globalBin, "pm2"));
4689
+ candidates.push(join16(globalBin, "pm2"));
4416
4690
  }
4417
4691
  }
4418
4692
  const fromRoot = resolvePm2FromNpmRoot();
@@ -4535,7 +4809,7 @@ function ensureGlobalPm2(options) {
4535
4809
  }
4536
4810
  function resolveApmEntryPath(entryArg = process.argv[1]) {
4537
4811
  const fromArgv = entryArg?.trim();
4538
- if (fromArgv && existsSync14(fromArgv)) {
4812
+ if (fromArgv && existsSync15(fromArgv)) {
4539
4813
  return fromArgv;
4540
4814
  }
4541
4815
  const npmResult = spawnSync2(useNpmShell2 ? "npm.cmd" : "npm", ["root", "-g"], {
@@ -4546,8 +4820,8 @@ function resolveApmEntryPath(entryArg = process.argv[1]) {
4546
4820
  if (npmResult.status === 0) {
4547
4821
  const globalRoot = npmResult.stdout?.toString().trim();
4548
4822
  if (globalRoot) {
4549
- const candidate = join15(globalRoot, CLI_PACKAGE_NAME, "dist", "index.js");
4550
- if (existsSync14(candidate)) {
4823
+ const candidate = join16(globalRoot, CLI_PACKAGE_NAME, "dist", "index.js");
4824
+ if (existsSync15(candidate)) {
4551
4825
  return candidate;
4552
4826
  }
4553
4827
  }
@@ -4705,8 +4979,8 @@ async function resolveBaseUrl(server) {
4705
4979
  return cfg?.baseUrl;
4706
4980
  }
4707
4981
  function writeConnectLaunchFiles(options) {
4708
- mkdirSync6(APM_CONFIG_DIR, { recursive: true });
4709
- writeFileSync11(PM2_CONNECT_ENTRY_PATH, CONNECT_ENTRY_SCRIPT, "utf8");
4982
+ mkdirSync7(APM_CONFIG_DIR, { recursive: true });
4983
+ writeFileSync12(PM2_CONNECT_ENTRY_PATH, CONNECT_ENTRY_SCRIPT, "utf8");
4710
4984
  const env = {
4711
4985
  ...collectPm2LaunchEnv()
4712
4986
  };
@@ -4721,7 +4995,7 @@ function writeConnectLaunchFiles(options) {
4721
4995
  cwd: options.cwd,
4722
4996
  env
4723
4997
  };
4724
- writeFileSync11(
4998
+ writeFileSync12(
4725
4999
  PM2_CONNECT_LAUNCH_PATH,
4726
5000
  JSON.stringify(launch, null, 2) + "\n",
4727
5001
  "utf8"
@@ -4733,12 +5007,12 @@ function writeEcosystemFile(options) {
4733
5007
  entryScript: PM2_CONNECT_ENTRY_PATH,
4734
5008
  baseUrl: options.baseUrl
4735
5009
  });
4736
- writeFileSync11(
5010
+ writeFileSync12(
4737
5011
  PM2_ECOSYSTEM_PATH,
4738
5012
  formatConnectPm2EcosystemFile(ecosystem),
4739
5013
  "utf8"
4740
5014
  );
4741
- if (existsSync14(LEGACY_PM2_ECOSYSTEM_PATH)) {
5015
+ if (existsSync15(LEGACY_PM2_ECOSYSTEM_PATH)) {
4742
5016
  try {
4743
5017
  unlinkSync2(LEGACY_PM2_ECOSYSTEM_PATH);
4744
5018
  } catch {
@@ -4897,14 +5171,14 @@ function writeEnvPath(env, value) {
4897
5171
  env.PATH = value;
4898
5172
  }
4899
5173
  function resolveNodeInstallDir() {
4900
- return dirname4(process.execPath);
5174
+ return dirname5(process.execPath);
4901
5175
  }
4902
5176
  function resolveNpmCmdPath() {
4903
5177
  if (process.platform !== "win32") {
4904
5178
  return null;
4905
5179
  }
4906
- const candidate = join16(resolveNodeInstallDir(), "npm.cmd");
4907
- return existsSync15(candidate) ? candidate : null;
5180
+ const candidate = join17(resolveNodeInstallDir(), "npm.cmd");
5181
+ return existsSync16(candidate) ? candidate : null;
4908
5182
  }
4909
5183
  function formatNpmRunShellCommand(scriptName) {
4910
5184
  const trimmed = scriptName.trim();
@@ -5076,7 +5350,7 @@ function logExecuteDeployContext(input) {
5076
5350
  const deploymentRunId = process.env[APM_DEPLOYMENT_RUN_ID_ENV]?.trim() || null;
5077
5351
  const shellEnv = buildDeployShellEnv();
5078
5352
  const npmGlobalBin = resolveNpmGlobalBin2();
5079
- const packageJsonPath = join17(input.cwd, "package.json");
5353
+ const packageJsonPath = join18(input.cwd, "package.json");
5080
5354
  logLine("========== executeDeploy \u4E0A\u4E0B\u6587 ==========");
5081
5355
  logLine(`trigger=${trigger} deployEnv=${input.env}`);
5082
5356
  logLine(`cwd(input)=${input.cwdInput}`);
@@ -5086,12 +5360,12 @@ function logExecuteDeployContext(input) {
5086
5360
  `cwdMatchProcess=${input.cwd === input.processCwd ? "yes" : "no"} (connect \u901A\u5E38\u4E3A no)`
5087
5361
  );
5088
5362
  logLine(
5089
- `apm.config=${input.apmConfigPath} exists=${existsSync16(
5363
+ `apm.config=${input.apmConfigPath} exists=${existsSync17(
5090
5364
  input.apmConfigPath
5091
5365
  )}`
5092
5366
  );
5093
5367
  logLine(
5094
- `package.json=${packageJsonPath} exists=${existsSync16(packageJsonPath)}`
5368
+ `package.json=${packageJsonPath} exists=${existsSync17(packageJsonPath)}`
5095
5369
  );
5096
5370
  logLine(
5097
5371
  `flags captureOutput=${input.captureOutput} packOnly=${Boolean(
@@ -5105,7 +5379,7 @@ function logExecuteDeployContext(input) {
5105
5379
  );
5106
5380
  logLine(`process argv=${process.argv.join(" ")}`);
5107
5381
  logLine(`npmGlobalBin=${npmGlobalBin ?? "(resolve failed)"}`);
5108
- logLine(`nodeDir=${dirname5(process.execPath)}`);
5382
+ logLine(`nodeDir=${dirname6(process.execPath)}`);
5109
5383
  logLine("--- process.env\uFF08\u8282\u9009\uFF09---");
5110
5384
  for (const [key, value] of Object.entries(
5111
5385
  collectInterestingEnv(process.env)
@@ -5147,14 +5421,14 @@ function logWisdomFrontendDeployContext(input) {
5147
5421
  logLine(
5148
5422
  `buildKey=build:${input.env} buildCmd=${input.buildCmd ?? "(missing)"}`
5149
5423
  );
5150
- logLine(`distDir=${input.distDir} exists=${existsSync16(input.distDir)}`);
5424
+ logLine(`distDir=${input.distDir} exists=${existsSync17(input.distDir)}`);
5151
5425
  logLine(
5152
5426
  `packOnly=${input.packOnly} archiveDeployArtifact=${input.archiveDeployArtifact}`
5153
5427
  );
5154
5428
  }
5155
5429
 
5156
5430
  // src/commands/deploy/internal/wisdom-deploy.ts
5157
- import { existsSync as existsSync20, readFileSync as readFileSync15, statSync as statSync9 } from "node:fs";
5431
+ import { existsSync as existsSync21, readFileSync as readFileSync16, statSync as statSync10 } from "node:fs";
5158
5432
  import path10 from "node:path";
5159
5433
 
5160
5434
  // src/commands/deploy/deploy-shell-run.ts
@@ -5253,22 +5527,22 @@ init_deploy_artifact_minio();
5253
5527
 
5254
5528
  // src/commands/deploy/internal/wisdom-backend/jar-incremental.ts
5255
5529
  import {
5256
- mkdirSync as mkdirSync8,
5257
- readdirSync as readdirSync5,
5258
- readFileSync as readFileSync14,
5259
- statSync as statSync7,
5260
- writeFileSync as writeFileSync13
5530
+ mkdirSync as mkdirSync9,
5531
+ readdirSync as readdirSync6,
5532
+ readFileSync as readFileSync15,
5533
+ statSync as statSync8,
5534
+ writeFileSync as writeFileSync14
5261
5535
  } from "node:fs";
5262
5536
  import path6 from "node:path";
5263
5537
  import JSZip2 from "jszip";
5264
5538
 
5265
5539
  // src/commands/deploy/internal/wisdom-backend/manifest.ts
5266
5540
  import {
5267
- existsSync as existsSync17,
5268
- mkdirSync as mkdirSync7,
5269
- readFileSync as readFileSync13,
5270
- statSync as statSync6,
5271
- writeFileSync as writeFileSync12
5541
+ existsSync as existsSync18,
5542
+ mkdirSync as mkdirSync8,
5543
+ readFileSync as readFileSync14,
5544
+ statSync as statSync7,
5545
+ writeFileSync as writeFileSync13
5272
5546
  } from "node:fs";
5273
5547
  import path2 from "node:path";
5274
5548
  function deployCacheDir() {
@@ -5281,20 +5555,20 @@ function relativeKey(projectRoot, filePath) {
5281
5555
  return path2.relative(projectRoot, filePath).split(path2.sep).join("/");
5282
5556
  }
5283
5557
  function fileSignature(filePath) {
5284
- const stat2 = statSync6(filePath);
5558
+ const stat2 = statSync7(filePath);
5285
5559
  return { size: stat2.size, mtime: stat2.mtimeMs / 1e3 };
5286
5560
  }
5287
5561
  function loadManifest3() {
5288
- const manifestPath2 = manifestFilePath();
5289
- if (!existsSync17(manifestPath2)) {
5562
+ const manifestPath3 = manifestFilePath();
5563
+ if (!existsSync18(manifestPath3)) {
5290
5564
  return {};
5291
5565
  }
5292
- return JSON.parse(readFileSync13(manifestPath2, "utf8"));
5566
+ return JSON.parse(readFileSync14(manifestPath3, "utf8"));
5293
5567
  }
5294
5568
  function saveManifest3(manifest) {
5295
5569
  const dir = deployCacheDir();
5296
- mkdirSync7(dir, { recursive: true });
5297
- writeFileSync12(manifestFilePath(), JSON.stringify(manifest, null, 2), "utf8");
5570
+ mkdirSync8(dir, { recursive: true });
5571
+ writeFileSync13(manifestFilePath(), JSON.stringify(manifest, null, 2), "utf8");
5298
5572
  }
5299
5573
  function updateManifestEntries(manifest, entries, projectRoot) {
5300
5574
  for (const entry of entries) {
@@ -5427,7 +5701,7 @@ function buildSftpConnectOptions(settings) {
5427
5701
  };
5428
5702
  }
5429
5703
  async function sleep(ms) {
5430
- await new Promise((resolve7) => setTimeout(resolve7, ms));
5704
+ await new Promise((resolve8) => setTimeout(resolve8, ms));
5431
5705
  }
5432
5706
  async function uploadZipWithRetry(settings, localZip, remoteZipPath) {
5433
5707
  let lastError;
@@ -5471,7 +5745,7 @@ async function ensureRemoteDir(sftp, dir) {
5471
5745
  }
5472
5746
  }
5473
5747
  function execCommand(client, command) {
5474
- return new Promise((resolve7, reject) => {
5748
+ return new Promise((resolve8, reject) => {
5475
5749
  client.exec(command, (err, stream) => {
5476
5750
  if (err) return reject(err);
5477
5751
  let stdout = "";
@@ -5481,7 +5755,7 @@ function execCommand(client, command) {
5481
5755
  reject(new Error(`\u8FDC\u7A0B\u547D\u4EE4\u5931\u8D25 (${code}): ${stderr || stdout}`));
5482
5756
  return;
5483
5757
  }
5484
- resolve7(stdout);
5758
+ resolve8(stdout);
5485
5759
  }).on("data", (data) => {
5486
5760
  stdout += data.toString();
5487
5761
  });
@@ -5664,7 +5938,7 @@ function shouldUploadLibFile(localPath, remoteAttr, manifest, projectRoot) {
5664
5938
  if (!remoteAttr) {
5665
5939
  return [false, "\u8FDC\u7A0B\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7"];
5666
5940
  }
5667
- const localSize = statSync7(localPath).size;
5941
+ const localSize = statSync8(localPath).size;
5668
5942
  const remoteSize = remoteAttr.size;
5669
5943
  if (localSize !== remoteSize) {
5670
5944
  return [true, `\u5927\u5C0F\u53D8\u5316 ${remoteSize} -> ${localSize}`];
@@ -5687,7 +5961,7 @@ function shouldUploadLibFile(localPath, remoteAttr, manifest, projectRoot) {
5687
5961
  }
5688
5962
  function listLibFilesToUpload(localLibDir, remoteStats, projectRoot, manifest = null) {
5689
5963
  const entries = [];
5690
- const jarFiles = readdirSync5(localLibDir).filter((name) => name.endsWith(".jar")).sort();
5964
+ const jarFiles = readdirSync6(localLibDir).filter((name) => name.endsWith(".jar")).sort();
5691
5965
  for (const jarName of jarFiles) {
5692
5966
  const jarPath = path6.join(localLibDir, jarName);
5693
5967
  const remoteAttr = remoteStats.get(jarName);
@@ -5705,12 +5979,12 @@ function listLibFilesToUpload(localLibDir, remoteStats, projectRoot, manifest =
5705
5979
  }
5706
5980
  async function createUpdatePackage(entries, packageName) {
5707
5981
  const dir = deployCacheDirectory();
5708
- mkdirSync8(dir, { recursive: true });
5982
+ mkdirSync9(dir, { recursive: true });
5709
5983
  const zipPath = path6.join(dir, packageName);
5710
5984
  log(`\u521B\u5EFA\u66F4\u65B0\u5305: ${path6.basename(zipPath)}\uFF08${entries.length} \u4E2A\u6587\u4EF6\uFF09`);
5711
5985
  const zip = new JSZip2();
5712
5986
  for (const entry of entries) {
5713
- const content = readFileSync14(entry.path);
5987
+ const content = readFileSync15(entry.path);
5714
5988
  zip.file(entry.arcname, content);
5715
5989
  log(` \u6253\u5305: ${entry.arcname} (${entry.reason})`);
5716
5990
  }
@@ -5719,11 +5993,11 @@ async function createUpdatePackage(entries, packageName) {
5719
5993
  compression: "DEFLATE",
5720
5994
  compressionOptions: { level: 6 }
5721
5995
  });
5722
- writeFileSync13(zipPath, buffer);
5996
+ writeFileSync14(zipPath, buffer);
5723
5997
  return zipPath;
5724
5998
  }
5725
5999
  function listAllLibFilesForArchive(libDir) {
5726
- return readdirSync5(libDir).filter((name) => name.endsWith(".jar")).sort().map((jarName) => ({
6000
+ return readdirSync6(libDir).filter((name) => name.endsWith(".jar")).sort().map((jarName) => ({
5727
6001
  path: path6.join(libDir, jarName),
5728
6002
  arcname: jarName,
5729
6003
  reason: "\u4EC5\u6253\u5305\u5F52\u6863"
@@ -5731,7 +6005,7 @@ function listAllLibFilesForArchive(libDir) {
5731
6005
  }
5732
6006
 
5733
6007
  // src/commands/deploy/internal/wisdom-backend/maven-build.ts
5734
- import { existsSync as existsSync19, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
6008
+ import { existsSync as existsSync20, readdirSync as readdirSync7, statSync as statSync9 } from "node:fs";
5735
6009
  import path7 from "node:path";
5736
6010
  import { spawnSync as spawnSync6 } from "node:child_process";
5737
6011
  function getMvnExecutable() {
@@ -5780,14 +6054,14 @@ function runMavenBuild(projectRoot, mavenLocalRepo, repoSource) {
5780
6054
  }
5781
6055
  function locateLibDir(projectRoot) {
5782
6056
  const targetDir = getTargetDir(projectRoot);
5783
- if (!existsSync19(targetDir)) {
6057
+ if (!existsSync20(targetDir)) {
5784
6058
  fail(`\u6784\u5EFA\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728: ${targetDir}`);
5785
6059
  }
5786
6060
  const libDir = path7.join(targetDir, "lib");
5787
- if (!existsSync19(libDir) || !statSync8(libDir).isDirectory()) {
6061
+ if (!existsSync20(libDir) || !statSync9(libDir).isDirectory()) {
5788
6062
  fail(`lib \u76EE\u5F55\u4E0D\u5B58\u5728: ${libDir}`);
5789
6063
  }
5790
- const libJars = readdirSync6(libDir).filter((name) => name.endsWith(".jar"));
6064
+ const libJars = readdirSync7(libDir).filter((name) => name.endsWith(".jar"));
5791
6065
  if (libJars.length === 0) {
5792
6066
  fail(`lib \u76EE\u5F55\u4E0B\u6CA1\u6709\u4F9D\u8D56 JAR: ${libDir}`);
5793
6067
  }
@@ -5796,10 +6070,10 @@ function locateLibDir(projectRoot) {
5796
6070
  }
5797
6071
  function locateMainJar(projectRoot) {
5798
6072
  const targetDir = getTargetDir(projectRoot);
5799
- if (!existsSync19(targetDir)) {
6073
+ if (!existsSync20(targetDir)) {
5800
6074
  fail(`\u6784\u5EFA\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728: ${targetDir}`);
5801
6075
  }
5802
- const jarFiles = readdirSync6(targetDir).filter((name) => name.endsWith(".jar") && !name.endsWith(".jar.original")).map((name) => path7.join(targetDir, name)).sort((a, b) => statSync8(b).mtimeMs - statSync8(a).mtimeMs);
6076
+ const jarFiles = readdirSync7(targetDir).filter((name) => name.endsWith(".jar") && !name.endsWith(".jar.original")).map((name) => path7.join(targetDir, name)).sort((a, b) => statSync9(b).mtimeMs - statSync9(a).mtimeMs);
5803
6077
  if (jarFiles.length === 0) {
5804
6078
  fail(`target \u76EE\u5F55\u4E0B\u6CA1\u6709\u4E3B JAR: ${targetDir}`);
5805
6079
  }
@@ -5956,8 +6230,8 @@ function springbootOutputIndicatesSuccess(action, combined) {
5956
6230
  async function connectSsh(config) {
5957
6231
  const client = new Client2();
5958
6232
  log(`\u8FDE\u63A5\u670D\u52A1\u5668 ${config.username}@${config.host}:${config.port}`);
5959
- await new Promise((resolve7, reject) => {
5960
- client.on("ready", () => resolve7()).on("error", (err) => reject(err)).connect({
6233
+ await new Promise((resolve8, reject) => {
6234
+ client.on("ready", () => resolve8()).on("error", (err) => reject(err)).connect({
5961
6235
  host: config.host,
5962
6236
  port: config.port,
5963
6237
  username: config.username,
@@ -6025,7 +6299,7 @@ async function runRemoteCommand(client, command, options) {
6025
6299
  const check = options?.check ?? true;
6026
6300
  const stream = options?.stream ?? false;
6027
6301
  const label = options?.label ?? "\u8FDC\u7A0B\u547D\u4EE4";
6028
- return new Promise((resolve7, reject) => {
6302
+ return new Promise((resolve8, reject) => {
6029
6303
  client.exec(command, (err, execStream) => {
6030
6304
  if (err) {
6031
6305
  reject(err);
@@ -6055,7 +6329,7 @@ ${errText}`.trim();
6055
6329
  \u8F93\u51FA: ${combined}` : "")
6056
6330
  );
6057
6331
  }
6058
- resolve7({ exitCode: code, out: out.trim(), err: errText.trim() });
6332
+ resolve8({ exitCode: code, out: out.trim(), err: errText.trim() });
6059
6333
  });
6060
6334
  });
6061
6335
  });
@@ -6285,15 +6559,15 @@ function isWisdomDeployConfigured(cfg) {
6285
6559
  return Boolean(w?.host?.trim() && w?.remotePath?.trim());
6286
6560
  }
6287
6561
  function detectWisdomProjectType(cwd) {
6288
- return existsSync20(path10.join(cwd, "package.json")) ? "frontend" : "backend";
6562
+ return existsSync21(path10.join(cwd, "package.json")) ? "frontend" : "backend";
6289
6563
  }
6290
6564
  function readPackageScripts(cwd) {
6291
6565
  const pkgPath = path10.join(cwd, "package.json");
6292
- if (!existsSync20(pkgPath)) {
6566
+ if (!existsSync21(pkgPath)) {
6293
6567
  return {};
6294
6568
  }
6295
6569
  try {
6296
- const raw = readFileSync15(pkgPath, "utf8");
6570
+ const raw = readFileSync16(pkgPath, "utf8");
6297
6571
  const parsed = JSON.parse(raw);
6298
6572
  return parsed.scripts ?? {};
6299
6573
  } catch {
@@ -6316,7 +6590,7 @@ function resolveFrontendDistDir(cwd) {
6316
6590
  for (const rel of candidates) {
6317
6591
  const full = path10.join(cwd, rel);
6318
6592
  try {
6319
- if (existsSync20(full) && statSync9(full).isDirectory()) {
6593
+ if (existsSync21(full) && statSync10(full).isDirectory()) {
6320
6594
  return full;
6321
6595
  }
6322
6596
  } catch {
@@ -6565,7 +6839,8 @@ async function executeDeploy(options) {
6565
6839
  try {
6566
6840
  const configSyncResult = await syncRemoteDeploymentConfig(
6567
6841
  cwd,
6568
- workspaceApmDir(cwd)
6842
+ workspaceApmDir(cwd),
6843
+ options.repositoryId ? { repositoryId: options.repositoryId } : void 0
6569
6844
  );
6570
6845
  if (configSyncResult.synced && configSyncResult.configName) {
6571
6846
  outputParts.push(
@@ -6840,6 +7115,7 @@ async function handleInboundDeploy(cfg, msg, signal) {
6840
7115
  if (signal.aborted) return;
6841
7116
  const api = createApmApiClient(cfg);
6842
7117
  const deploymentRunId = msg.deploymentRunId;
7118
+ const repositoryId = msg.repositoryId?.trim() || "";
6843
7119
  await api.cli.updateTaskDeploymentStatus({
6844
7120
  id: deploymentRunId,
6845
7121
  status: "DEPLOYING"
@@ -6848,13 +7124,33 @@ async function handleInboundDeploy(cfg, msg, signal) {
6848
7124
  api,
6849
7125
  deploymentRunId,
6850
7126
  run: async (appendLog) => {
6851
- const workdir = requireRemoteWorkdir(msg.workdir);
7127
+ const workspaceRoot = requireRemoteWorkdir(msg.workdir);
7128
+ let cwd = workspaceRoot;
7129
+ if (repositoryId) {
7130
+ const resolved = await resolveDeployCwdForRepository(
7131
+ workspaceRoot,
7132
+ repositoryId,
7133
+ api
7134
+ );
7135
+ if (resolved) {
7136
+ cwd = resolved;
7137
+ appendLog(
7138
+ `[apm] \u591A\u4ED3\u90E8\u7F72\uFF1A\u6309 repositoryId=${repositoryId} \u89E3\u6790 cwd=${cwd}
7139
+ `
7140
+ );
7141
+ } else {
7142
+ appendLog(
7143
+ `[apm] \u672A\u5728 workspace-repos \u547D\u4E2D repositoryId=${repositoryId}\uFF0C\u4F7F\u7528\u5DE5\u4F5C\u7A7A\u95F4\u76EE\u5F55 cwd=${cwd}
7144
+ `
7145
+ );
7146
+ }
7147
+ }
6852
7148
  const displayCommand = resolveDeployCommand(
6853
7149
  msg.environment,
6854
7150
  msg.packOnly
6855
7151
  );
6856
7152
  console.log(
6857
- `[apm] deploy start id=${deploymentRunId} env=${msg.environment} cwd=${workdir}`
7153
+ `[apm] deploy start id=${deploymentRunId} env=${msg.environment} cwd=${cwd}` + (repositoryId ? ` repositoryId=${repositoryId}` : "")
6858
7154
  );
6859
7155
  console.log(`[apm] deploy command: ${displayCommand}`);
6860
7156
  if (signal.aborted) {
@@ -6862,11 +7158,12 @@ async function handleInboundDeploy(cfg, msg, signal) {
6862
7158
  }
6863
7159
  const deployOptions = {
6864
7160
  env: msg.environment,
6865
- cwd: workdir,
7161
+ cwd,
6866
7162
  packOnly: msg.packOnly,
6867
7163
  captureOutput: true,
6868
7164
  archiveDeployArtifact: true,
6869
- deployTrigger: "connect"
7165
+ deployTrigger: "connect",
7166
+ ...repositoryId ? { repositoryId } : {}
6870
7167
  };
6871
7168
  const output = await executeDeploy(deployOptions);
6872
7169
  if (output.trim()) {
@@ -6884,7 +7181,7 @@ async function handleInboundDeploy(cfg, msg, signal) {
6884
7181
  }
6885
7182
 
6886
7183
  // src/commands/clean-session-cache.ts
6887
- import { existsSync as existsSync21, rmSync as rmSync4 } from "node:fs";
7184
+ import { existsSync as existsSync22, rmSync as rmSync4 } from "node:fs";
6888
7185
 
6889
7186
  // src/commands/connect/pre-step-cache.ts
6890
7187
  var PULL_TTL_MS = 3e4;
@@ -6926,7 +7223,7 @@ function cleanSessionWorkspaceCache(sessionId, workdir) {
6926
7223
  return;
6927
7224
  }
6928
7225
  const dir = sessionDir(trimmedSessionId, workspaceApmDir(trimmedWorkdir));
6929
- if (existsSync21(dir)) {
7226
+ if (existsSync22(dir)) {
6930
7227
  rmSync4(dir, { recursive: true, force: true });
6931
7228
  console.log(`[apm] \u5DF2\u6E05\u7406\u4F1A\u8BDD\u7F13\u5B58 ${dir}`);
6932
7229
  } else {
@@ -6936,16 +7233,16 @@ function cleanSessionWorkspaceCache(sessionId, workdir) {
6936
7233
  }
6937
7234
 
6938
7235
  // src/commands/clean-webide-cache.ts
6939
- import { existsSync as existsSync22, rmSync as rmSync5 } from "node:fs";
6940
- import { resolve as resolve5 } from "node:path";
7236
+ import { existsSync as existsSync23, rmSync as rmSync5 } from "node:fs";
7237
+ import { resolve as resolve6 } from "node:path";
6941
7238
  function cleanWebIdeWorkspaceCache(taskId, workdir) {
6942
7239
  const trimmedTaskId = taskId.trim();
6943
7240
  const trimmedWorkdir = workdir.trim();
6944
7241
  if (!trimmedTaskId || !trimmedWorkdir) {
6945
7242
  return;
6946
7243
  }
6947
- const dir = resolve5(trimmedWorkdir, ".apm", "webide", trimmedTaskId);
6948
- if (existsSync22(dir)) {
7244
+ const dir = resolve6(trimmedWorkdir, ".apm", "webide", trimmedTaskId);
7245
+ if (existsSync23(dir)) {
6949
7246
  rmSync5(dir, { recursive: true, force: true });
6950
7247
  console.log(`[apm] \u5DF2\u6E05\u7406 WebIDE \u7F13\u5B58 ${dir}`);
6951
7248
  } else {
@@ -7296,17 +7593,17 @@ ${JSON.stringify(event, null, 2)}
7296
7593
  }
7297
7594
 
7298
7595
  // src/commands/connect/agent-session-registry.ts
7299
- import { existsSync as existsSync23, mkdirSync as mkdirSync9, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "node:fs";
7300
- import { dirname as dirname6, resolve as resolve6 } from "node:path";
7596
+ import { existsSync as existsSync24, mkdirSync as mkdirSync10, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "node:fs";
7597
+ import { dirname as dirname7, resolve as resolve7 } from "node:path";
7301
7598
  function registryPath(workdir, sessionId) {
7302
- return resolve6(workdir, ".apm", "sessions", sessionId, "cursor-agents.json");
7599
+ return resolve7(workdir, ".apm", "sessions", sessionId, "cursor-agents.json");
7303
7600
  }
7304
7601
  function readRegistry(path19) {
7305
- if (!existsSync23(path19)) {
7602
+ if (!existsSync24(path19)) {
7306
7603
  return {};
7307
7604
  }
7308
7605
  try {
7309
- const parsed = JSON.parse(readFileSync16(path19, "utf8"));
7606
+ const parsed = JSON.parse(readFileSync17(path19, "utf8"));
7310
7607
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
7311
7608
  const result = {};
7312
7609
  for (const [key, value] of Object.entries(
@@ -7323,8 +7620,8 @@ function readRegistry(path19) {
7323
7620
  return {};
7324
7621
  }
7325
7622
  function writeRegistry(path19, registry) {
7326
- mkdirSync9(dirname6(path19), { recursive: true });
7327
- writeFileSync14(path19, `${JSON.stringify(registry, null, 2)}
7623
+ mkdirSync10(dirname7(path19), { recursive: true });
7624
+ writeFileSync15(path19, `${JSON.stringify(registry, null, 2)}
7328
7625
  `, "utf8");
7329
7626
  }
7330
7627
  function loadSessionAgentId(workdir, sessionId, user) {
@@ -7927,12 +8224,12 @@ ${WORKSPACE_BOUNDARY_HINT}`;
7927
8224
  }
7928
8225
 
7929
8226
  // src/commands/connect/local-agent-store.ts
7930
- import { mkdirSync as mkdirSync10 } from "node:fs";
7931
- import { join as join18 } from "node:path";
8227
+ import { mkdirSync as mkdirSync11 } from "node:fs";
8228
+ import { join as join19 } from "node:path";
7932
8229
  import { JsonlLocalAgentStore } from "@cursor/sdk";
7933
8230
  function createWorkspaceLocalAgentStore(workdir) {
7934
- const rootDir = join18(workdir, ".apm", "cursor-agent-store");
7935
- mkdirSync10(rootDir, { recursive: true });
8231
+ const rootDir = join19(workdir, ".apm", "cursor-agent-store");
8232
+ mkdirSync11(rootDir, { recursive: true });
7936
8233
  return new JsonlLocalAgentStore(rootDir);
7937
8234
  }
7938
8235
 
@@ -8212,20 +8509,20 @@ async function ensureMessageHasReply(cfg, sessionId, messageId, fallback) {
8212
8509
  }
8213
8510
 
8214
8511
  // src/commands/connect/cli-version-sync.ts
8215
- import { existsSync as existsSync24, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "fs";
8216
- import { join as join19 } from "path";
8512
+ import { existsSync as existsSync25, readFileSync as readFileSync18, writeFileSync as writeFileSync16 } from "fs";
8513
+ import { join as join20 } from "path";
8217
8514
  var CLI_VERSION_FILE = ".cli-version.json";
8218
- function manifestPath(apmDir) {
8219
- return join19(apmDir, CLI_VERSION_FILE);
8515
+ function manifestPath2(apmDir) {
8516
+ return join20(apmDir, CLI_VERSION_FILE);
8220
8517
  }
8221
8518
  function loadManifest4(apmDir) {
8222
- const path19 = toFsPath(manifestPath(apmDir));
8223
- if (!existsSync24(path19)) {
8519
+ const path19 = toFsPath(manifestPath2(apmDir));
8520
+ if (!existsSync25(path19)) {
8224
8521
  return null;
8225
8522
  }
8226
8523
  try {
8227
8524
  const parsed = JSON.parse(
8228
- readFileSync17(path19, "utf8")
8525
+ readFileSync18(path19, "utf8")
8229
8526
  );
8230
8527
  if (parsed?.version === 1 && typeof parsed.cliVersion === "string" && parsed.cliVersion.trim()) {
8231
8528
  return parsed;
@@ -8236,8 +8533,8 @@ function loadManifest4(apmDir) {
8236
8533
  }
8237
8534
  function saveManifest4(apmDir, cliVersion) {
8238
8535
  const manifest = { version: 1, cliVersion };
8239
- writeFileSync15(
8240
- toFsPath(manifestPath(apmDir)),
8536
+ writeFileSync16(
8537
+ toFsPath(manifestPath2(apmDir)),
8241
8538
  `${JSON.stringify(manifest, null, 2)}
8242
8539
  `,
8243
8540
  "utf8"
@@ -8290,7 +8587,7 @@ function createRunSlotPool(maxConcurrent = DEFAULT_MAX_CONCURRENT, options = {})
8290
8587
  );
8291
8588
  }
8292
8589
  const queuedAt = Date.now();
8293
- return new Promise((resolve7) => {
8590
+ return new Promise((resolve8) => {
8294
8591
  waiters.push(() => {
8295
8592
  active += 1;
8296
8593
  const waitedMs = Date.now() - queuedAt;
@@ -8301,7 +8598,7 @@ function createRunSlotPool(maxConcurrent = DEFAULT_MAX_CONCURRENT, options = {})
8301
8598
  )}s\uFF0C\u5F53\u524D\u5360\u7528 ${active}/${maxConcurrent}`
8302
8599
  );
8303
8600
  }
8304
- resolve7();
8601
+ resolve8();
8305
8602
  });
8306
8603
  });
8307
8604
  };
@@ -8322,9 +8619,9 @@ function createRunSlotPool(maxConcurrent = DEFAULT_MAX_CONCURRENT, options = {})
8322
8619
  init_webide_terminal_registry();
8323
8620
  import { Worker } from "node:worker_threads";
8324
8621
  import { fileURLToPath as fileURLToPath3 } from "node:url";
8325
- import { dirname as dirname7, join as join20 } from "node:path";
8326
- var workerFile = join20(
8327
- dirname7(fileURLToPath3(import.meta.url)),
8622
+ import { dirname as dirname8, join as join21 } from "node:path";
8623
+ var workerFile = join21(
8624
+ dirname8(fileURLToPath3(import.meta.url)),
8328
8625
  "webide-message-worker.js"
8329
8626
  );
8330
8627
  function spawnWebIdeMessageWorker(cfg, msg) {
@@ -8333,8 +8630,8 @@ function spawnWebIdeMessageWorker(cfg, msg) {
8333
8630
  });
8334
8631
  const registry = getWebIdeTerminalRegistry(cfg);
8335
8632
  let resolveDone;
8336
- const done = new Promise((resolve7) => {
8337
- resolveDone = resolve7;
8633
+ const done = new Promise((resolve8) => {
8634
+ resolveDone = resolve8;
8338
8635
  });
8339
8636
  worker.on("message", (m) => {
8340
8637
  if (m?.type === "terminal-rpc") {
@@ -8579,11 +8876,11 @@ async function handleInboundMessage(cfg, msg, signal, ctx) {
8579
8876
  }
8580
8877
  function interruptibleSleep(ms, signal) {
8581
8878
  if (signal.aborted) return Promise.resolve();
8582
- return new Promise((resolve7) => {
8583
- const timer = setTimeout(resolve7, ms);
8879
+ return new Promise((resolve8) => {
8880
+ const timer = setTimeout(resolve8, ms);
8584
8881
  const onAbort = () => {
8585
8882
  clearTimeout(timer);
8586
- resolve7();
8883
+ resolve8();
8587
8884
  };
8588
8885
  signal.addEventListener("abort", onAbort, { once: true });
8589
8886
  });
@@ -8795,7 +9092,7 @@ function attachWsHandlers(ws, ctx, onOpen) {
8795
9092
  });
8796
9093
  }
8797
9094
  function connectOnce(url, ctx, connectionAbort, onConnected) {
8798
- return new Promise((resolve7, reject) => {
9095
+ return new Promise((resolve8, reject) => {
8799
9096
  const ws = new WebSocket(url);
8800
9097
  let stopHeartbeat;
8801
9098
  let settled = false;
@@ -8824,7 +9121,7 @@ function connectOnce(url, ctx, connectionAbort, onConnected) {
8824
9121
  finish(() => reject(new Error("shutdown")));
8825
9122
  return;
8826
9123
  }
8827
- finish(resolve7);
9124
+ finish(resolve8);
8828
9125
  });
8829
9126
  ws.on("error", (err) => {
8830
9127
  console.error("[apm] WebSocket \u9519\u8BEF:", err.message);
@@ -9110,38 +9407,111 @@ function normalizeDeployEnvironment(env) {
9110
9407
  if (normalized === "online") return "ONLINE";
9111
9408
  return null;
9112
9409
  }
9410
+ async function resolveRepositoryIdForWebIdeDeploy(cwd, api) {
9411
+ const start = resolveWorkdirPath(cwd);
9412
+ let manifest = findWorkspaceReposManifestNearPath(start);
9413
+ if (!manifest) {
9414
+ throw new DeployExecutionError(
9415
+ "\u672A\u627E\u5230 .apm/workspace-repos.json\uFF0C\u65E0\u6CD5\u5339\u914D\u5E73\u53F0\u4ED3\u5E93",
9416
+ 1
9417
+ );
9418
+ }
9419
+ try {
9420
+ manifest = await enrichWorkspaceReposRemoteUrls(manifest);
9421
+ } catch (err) {
9422
+ const detail = err instanceof Error ? err.message : String(err);
9423
+ throw new DeployExecutionError(
9424
+ `\u5237\u65B0 workspace-repos remoteUrl \u5931\u8D25: ${detail}`,
9425
+ 1
9426
+ );
9427
+ }
9428
+ const entry = matchWorkspaceRepoEntryForPath(manifest, start);
9429
+ if (!entry) {
9430
+ throw new DeployExecutionError(
9431
+ `\u5F53\u524D\u76EE\u5F55\u672A\u547D\u4E2D workspace-repos \u4E2D\u7684\u4ED3\u5E93: ${start}`,
9432
+ 1
9433
+ );
9434
+ }
9435
+ const abs = absoluteRepoPath(manifest.workdir, entry);
9436
+ const remoteUrl = toHttpsGitRemoteUrl(entry.remoteUrl ?? "") || await tryReadHttpsGitOriginUrl(abs);
9437
+ if (!remoteUrl) {
9438
+ throw new DeployExecutionError(
9439
+ `\u4ED3 ${entry.path} \u65E0\u53EF\u7528\u7684 https remote\uFF0C\u65E0\u6CD5\u5339\u914D\u5E73\u53F0\u4ED3\u5E93`,
9440
+ 1
9441
+ );
9442
+ }
9443
+ let baseBranch = "";
9444
+ try {
9445
+ const gitRoot = await resolveGitRepoRoot(abs);
9446
+ baseBranch = (await resolveDefaultRemoteBranch(gitRoot)).trim();
9447
+ } catch (err) {
9448
+ const detail = err instanceof Error ? err.message : String(err);
9449
+ throw new DeployExecutionError(`\u89E3\u6790\u5F53\u524D\u4ED3\u57FA\u7EBF\u5206\u652F\u5931\u8D25: ${detail}`, 1);
9450
+ }
9451
+ if (!baseBranch) {
9452
+ throw new DeployExecutionError(
9453
+ "\u65E0\u6CD5\u786E\u5B9A\u5F53\u524D\u4ED3\u57FA\u7EBF\u5206\u652F\uFF0C\u65E0\u6CD5\u5339\u914D\u5E73\u53F0\u4ED3\u5E93",
9454
+ 1
9455
+ );
9456
+ }
9457
+ let matched;
9458
+ try {
9459
+ matched = await api.cli.matchRepository({
9460
+ url: remoteUrl,
9461
+ baseBranch
9462
+ });
9463
+ } catch (err) {
9464
+ const detail = err instanceof Error ? err.message : String(err);
9465
+ throw new DeployExecutionError(
9466
+ `\u6309 https remote + \u57FA\u7EBF\u5206\u652F\u5339\u914D\u5E73\u53F0\u4ED3\u5E93\u5931\u8D25: ${detail}`,
9467
+ 1
9468
+ );
9469
+ }
9470
+ const repositoryId = matched.repositoryId?.trim() || "";
9471
+ if (!repositoryId) {
9472
+ throw new DeployExecutionError(
9473
+ `\u672A\u5339\u914D\u5230\u5E73\u53F0\u4ED3\u5E93 path=${entry.path} url=${remoteUrl} baseBranch=${baseBranch}`,
9474
+ 1
9475
+ );
9476
+ }
9477
+ console.log(
9478
+ `[apm] \u90E8\u7F72\u8BB0\u5F55\u4ED3\u5E93 path=${entry.path} https+baseBranch=${baseBranch} \u2192 repositoryId=${repositoryId}`
9479
+ );
9480
+ return repositoryId;
9481
+ }
9113
9482
  async function runDeployWithBackendTracking(options) {
9483
+ const { tracking, ...deployOptions } = options;
9114
9484
  const cfg = await tryReadApmConfig();
9115
9485
  if (!cfg || !resolveApiKey(cfg)) {
9116
- console.warn("[apm] \u672A\u767B\u5F55\uFF0C\u8DF3\u8FC7\u540E\u7AEF\u90E8\u7F72\u8BB0\u5F55");
9117
- await executeDeploy(options);
9118
- return;
9486
+ throw new DeployExecutionError("\u672A\u767B\u5F55\uFF0C\u65E0\u6CD5\u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55", 1);
9119
9487
  }
9120
- const environment = normalizeDeployEnvironment(options.env);
9488
+ const environment = normalizeDeployEnvironment(deployOptions.env);
9121
9489
  if (!environment) {
9122
- console.warn(
9123
- `[apm] \u672A\u77E5\u90E8\u7F72\u73AF\u5883 ${options.env}\uFF0C\u8DF3\u8FC7\u540E\u7AEF\u90E8\u7F72\u8BB0\u5F55\uFF08\u4EC5\u652F\u6301 test/online\uFF09`
9490
+ throw new DeployExecutionError(
9491
+ `\u672A\u77E5\u90E8\u7F72\u73AF\u5883 ${deployOptions.env}\uFF0C\u4EC5\u652F\u6301 test/online`,
9492
+ 1
9124
9493
  );
9125
- await executeDeploy(options);
9126
- return;
9127
9494
  }
9128
9495
  const api = createApmApiClient(cfg);
9496
+ const repositoryId = tracking.kind === "task" ? await resolveRepositoryIdForWebIdeDeploy(deployOptions.cwd, api) : void 0;
9129
9497
  let deploymentRunId;
9130
9498
  try {
9131
9499
  const run = await api.cli.createTaskDeployment({
9132
- sessionId: options.sessionId,
9500
+ ...tracking.kind === "session" ? { sessionId: tracking.sessionId } : { taskId: tracking.taskId },
9133
9501
  environment,
9134
- workdirPath: resolveWorkdirPath(options.cwd)
9502
+ workdirPath: resolveWorkdirPath(deployOptions.cwd),
9503
+ ...repositoryId ? { repositoryId } : {}
9135
9504
  });
9136
9505
  deploymentRunId = run.id;
9137
9506
  console.log(
9138
9507
  `[apm] \u5DF2\u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55 id=${deploymentRunId} env=${environment}`
9139
9508
  );
9140
9509
  } catch (error) {
9510
+ if (error instanceof DeployExecutionError) {
9511
+ throw error;
9512
+ }
9141
9513
  const detail = error instanceof Error ? error.message : String(error);
9142
- console.warn(`[apm] \u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55\u5931\u8D25\uFF0C\u7EE7\u7EED\u90E8\u7F72: ${detail}`);
9143
- await executeDeploy(options);
9144
- return;
9514
+ throw new DeployExecutionError(`\u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55\u5931\u8D25: ${detail}`, 1);
9145
9515
  }
9146
9516
  await api.cli.updateTaskDeploymentStatus({
9147
9517
  id: deploymentRunId,
@@ -9152,7 +9522,7 @@ async function runDeployWithBackendTracking(options) {
9152
9522
  deploymentRunId,
9153
9523
  run: async (appendLog) => {
9154
9524
  const output = await executeDeploy({
9155
- ...options,
9525
+ ...deployOptions,
9156
9526
  captureOutput: true,
9157
9527
  archiveDeployArtifact: true
9158
9528
  });
@@ -9178,7 +9548,10 @@ function registerDeployMainCommand(program) {
9178
9548
  "apm.config.json \u8DEF\u5F84\uFF08\u9ED8\u8BA4 .apm/apm.config.json\uFF09"
9179
9549
  ).option(
9180
9550
  "--session <sessionId>",
9181
- "\u6C9F\u901A\u7FA4 ID\uFF1B\u4F20\u5165\u65F6\u5728\u5E73\u53F0\u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55\u5E76\u540C\u6B65\u65E5\u5FD7"
9551
+ "\u6C9F\u901A\u7FA4 ID\uFF1B\u4F20\u5165\u65F6\u5728\u5E73\u53F0\u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55\u5E76\u540C\u6B65\u65E5\u5FD7\uFF08\u4E0E --task \u4E8C\u9009\u4E00\uFF09"
9552
+ ).option(
9553
+ "--task <taskId>",
9554
+ "WebIDE \u4EFB\u52A1 ID\uFF1B\u4F20\u5165\u65F6\u5728\u5E73\u53F0\u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55\u5E76\u540C\u6B65\u65E5\u5FD7\uFF08\u4E0E --session \u4E8C\u9009\u4E00\uFF09"
9182
9555
  ).option(
9183
9556
  "--pack-only",
9184
9557
  "\u4EC5\u6784\u5EFA/\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5F52\u6863\uFF0C\u4E0D\u4E0A\u4F20\u8FDC\u7A0B SFTP/SSH\uFF08\u65E0\u9700 wisdomDeploy\uFF09"
@@ -9186,14 +9559,30 @@ function registerDeployMainCommand(program) {
9186
9559
  async (env, opts) => {
9187
9560
  const cwd = process.cwd();
9188
9561
  const sessionId = opts.session?.trim();
9562
+ const taskId = opts.task?.trim();
9189
9563
  const packOnly = Boolean(opts.packOnly);
9564
+ if (sessionId && taskId) {
9565
+ console.error("[apm] --session \u4E0E --task \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
9566
+ process.exit(1);
9567
+ }
9190
9568
  try {
9191
9569
  if (sessionId) {
9192
9570
  await runDeployWithBackendTracking({
9193
9571
  env,
9194
9572
  cwd,
9195
9573
  configPath: opts.config,
9196
- sessionId,
9574
+ tracking: { kind: "session", sessionId },
9575
+ packOnly,
9576
+ deployTrigger: "session"
9577
+ });
9578
+ return;
9579
+ }
9580
+ if (taskId) {
9581
+ await runDeployWithBackendTracking({
9582
+ env,
9583
+ cwd,
9584
+ configPath: opts.config,
9585
+ tracking: { kind: "task", taskId },
9197
9586
  packOnly,
9198
9587
  deployTrigger: "session"
9199
9588
  });
@@ -9227,7 +9616,7 @@ import path15 from "node:path";
9227
9616
  import Docker from "dockerode";
9228
9617
 
9229
9618
  // src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
9230
- import { existsSync as existsSync25, readFileSync as readFileSync18 } from "node:fs";
9619
+ import { existsSync as existsSync26, readFileSync as readFileSync19 } from "node:fs";
9231
9620
  import path12 from "node:path";
9232
9621
  function asOptionalTlsBuffer(value) {
9233
9622
  if (typeof value !== "string") {
@@ -9239,8 +9628,8 @@ function asOptionalTlsBuffer(value) {
9239
9628
  if (normalized === "") {
9240
9629
  return void 0;
9241
9630
  }
9242
- if (existsSync25(normalized)) {
9243
- return readFileSync18(normalized);
9631
+ if (existsSync26(normalized)) {
9632
+ return readFileSync19(normalized);
9244
9633
  }
9245
9634
  const looksLikePath = /[\\/]/.test(normalized) || normalized.endsWith(".pem");
9246
9635
  if (looksLikePath) {
@@ -9365,17 +9754,17 @@ var DockerodeClient = class {
9365
9754
  await this.client.getImage(image).remove({ force: true });
9366
9755
  }
9367
9756
  async pullImage(image, auth) {
9368
- const stream = await new Promise((resolve7, reject) => {
9757
+ const stream = await new Promise((resolve8, reject) => {
9369
9758
  const pullOptions = auth ? { authconfig: auth } : void 0;
9370
9759
  this.client.pull(image, pullOptions, (err, output) => {
9371
9760
  if (err || !output) {
9372
9761
  reject(err ?? new Error("docker pull \u8FD4\u56DE\u7A7A\u8F93\u51FA"));
9373
9762
  return;
9374
9763
  }
9375
- resolve7(output);
9764
+ resolve8(output);
9376
9765
  });
9377
9766
  });
9378
- await new Promise((resolve7, reject) => {
9767
+ await new Promise((resolve8, reject) => {
9379
9768
  this.client.modem.followProgress(
9380
9769
  stream,
9381
9770
  (err) => {
@@ -9383,7 +9772,7 @@ var DockerodeClient = class {
9383
9772
  reject(err);
9384
9773
  return;
9385
9774
  }
9386
- resolve7();
9775
+ resolve8();
9387
9776
  },
9388
9777
  () => void 0
9389
9778
  );
@@ -9450,7 +9839,7 @@ var DockerodeClient = class {
9450
9839
  var createDockerodeClient = (config) => new DockerodeClient(config);
9451
9840
 
9452
9841
  // src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
9453
- import { existsSync as existsSync26, readFileSync as readFileSync19, statSync as statSync10 } from "node:fs";
9842
+ import { existsSync as existsSync27, readFileSync as readFileSync20, statSync as statSync11 } from "node:fs";
9454
9843
  import path13 from "node:path";
9455
9844
  function stripSurroundingQuotes(value) {
9456
9845
  const t = value.trim();
@@ -9467,10 +9856,10 @@ function loadEnvFromFile(envFilePath) {
9467
9856
  return {};
9468
9857
  }
9469
9858
  const targetPath = path13.resolve(envFilePath);
9470
- if (!existsSync26(targetPath) || !statSync10(targetPath).isFile()) {
9859
+ if (!existsSync27(targetPath) || !statSync11(targetPath).isFile()) {
9471
9860
  return {};
9472
9861
  }
9473
- const raw = readFileSync19(targetPath, "utf-8");
9862
+ const raw = readFileSync20(targetPath, "utf-8");
9474
9863
  const result = {};
9475
9864
  for (const line of raw.split(/\r?\n/)) {
9476
9865
  const normalized = line.trim();
@@ -9641,12 +10030,12 @@ function dockerPushImage(params, cwd) {
9641
10030
  }
9642
10031
 
9643
10032
  // src/commands/deploy/internal/backend-deploy/resolve-dockerfile.ts
9644
- import { existsSync as existsSync27 } from "node:fs";
10033
+ import { existsSync as existsSync28 } from "node:fs";
9645
10034
  import path14 from "node:path";
9646
10035
  function resolveDockerBuildPaths(cwd) {
9647
10036
  const dockerfilePath = path14.join(cwd, "Dockerfile");
9648
10037
  Logger.info(`\u67E5\u627EDockerfile\u6587\u4EF6\uFF0C\u8DEF\u5F84: ${dockerfilePath}`);
9649
- if (!existsSync27(dockerfilePath)) {
10038
+ if (!existsSync28(dockerfilePath)) {
9650
10039
  throw new Error(`Dockerfile \u4E0D\u5B58\u5728\uFF1A${dockerfilePath}`);
9651
10040
  }
9652
10041
  Logger.info("\u2713 Dockerfile \u5B58\u5728");