ai-project-manage-cli 7.1.37 → 7.1.38
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 +380 -388
- package/dist/webide-message-worker.js +429 -564
- package/package.json +1 -1
|
@@ -601,57 +601,6 @@ async function pushCurrentBranch(cwd) {
|
|
|
601
601
|
return true;
|
|
602
602
|
}
|
|
603
603
|
|
|
604
|
-
// src/baseline-resolve.ts
|
|
605
|
-
function formatBaselineDiagnostic(workdirPath, baselineWorkdirPath, diagnostic) {
|
|
606
|
-
return diagnostic?.message ?? `\u672A\u5728\u5E73\u53F0\u627E\u5230\u4E0E\u5F53\u524D\u76EE\u5F55\u5339\u914D\u7684\u5DE5\u4F5C\u76EE\u5F55\u767B\u8BB0\uFF1A${workdirPath}\uFF08\u89C4\u8303\u5316\uFF1A${baselineWorkdirPath}\uFF09
|
|
607
|
-
\u8BF7\u5148\u5728\u5E73\u53F0\u767B\u8BB0\u8BE5\u8DEF\u5F84\u5BF9\u5E94\u7684\u5DE5\u4F5C\u76EE\u5F55\u4E0E\u4ED3\u5E93\u3002`;
|
|
608
|
-
}
|
|
609
|
-
async function matchRepositoryByGitRemote(api, workdirPath) {
|
|
610
|
-
const gitRoot = await resolveGitRepoRoot(workdirPath);
|
|
611
|
-
const gitUrl = await tryReadGitOriginUrl(gitRoot);
|
|
612
|
-
if (!gitUrl) {
|
|
613
|
-
return null;
|
|
614
|
-
}
|
|
615
|
-
const matched = await api.cli.matchRepository({ url: gitUrl });
|
|
616
|
-
const repositoryId = matched.repositoryId?.trim();
|
|
617
|
-
const defaultBranch = matched.defaultBranch?.trim();
|
|
618
|
-
if (!repositoryId || !defaultBranch) {
|
|
619
|
-
return null;
|
|
620
|
-
}
|
|
621
|
-
console.log(
|
|
622
|
-
`[apm] \u5DE5\u4F5C\u7A7A\u95F4\u8DEF\u5F84\u672A\u5339\u914D\uFF0C\u5DF2\u901A\u8FC7 git remote \u5173\u8054\u4ED3\u5E93: ${gitUrl}`
|
|
623
|
-
);
|
|
624
|
-
return { repositoryId, defaultBranch };
|
|
625
|
-
}
|
|
626
|
-
async function resolveWorkspaceBaseline(api, workdirPath) {
|
|
627
|
-
const baseline = await api.cli.workspaceBaseline({ workdirPath });
|
|
628
|
-
const repositoryId = baseline.repositoryId?.trim();
|
|
629
|
-
const defaultBranch = baseline.defaultBranch?.trim();
|
|
630
|
-
if (repositoryId && defaultBranch) {
|
|
631
|
-
return {
|
|
632
|
-
repositoryId,
|
|
633
|
-
defaultBranch,
|
|
634
|
-
workdirPath: baseline.workdirPath,
|
|
635
|
-
matchedViaGitRemote: false
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
const viaGit = await matchRepositoryByGitRemote(api, workdirPath);
|
|
639
|
-
if (viaGit) {
|
|
640
|
-
return {
|
|
641
|
-
...viaGit,
|
|
642
|
-
workdirPath: baseline.workdirPath,
|
|
643
|
-
matchedViaGitRemote: true
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
|
-
throw new Error(
|
|
647
|
-
`[apm] ${formatBaselineDiagnostic(
|
|
648
|
-
workdirPath,
|
|
649
|
-
baseline.workdirPath,
|
|
650
|
-
baseline.diagnostic
|
|
651
|
-
)}`
|
|
652
|
-
);
|
|
653
|
-
}
|
|
654
|
-
|
|
655
604
|
// src/command-utils.ts
|
|
656
605
|
import { copyFileSync, existsSync, mkdirSync as mkdirSync2, readdirSync, statSync } from "fs";
|
|
657
606
|
import { basename, dirname, extname, join as join2, resolve as resolve2 } from "path";
|
|
@@ -2923,493 +2872,142 @@ function resolveMessageReplyFallback(fallback) {
|
|
|
2923
2872
|
}
|
|
2924
2873
|
|
|
2925
2874
|
// src/commands/init.ts
|
|
2926
|
-
import { join as join6 } from "path";
|
|
2927
|
-
import { readFileSync as readFileSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
2928
|
-
|
|
2929
|
-
// src/deployment-config-sync.ts
|
|
2930
2875
|
import { join as join4 } from "path";
|
|
2931
|
-
import { writeFileSync as writeFileSync5 } from "fs";
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
const
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
let parsed;
|
|
2948
|
-
try {
|
|
2949
|
-
parsed = JSON.parse(content);
|
|
2950
|
-
} catch {
|
|
2951
|
-
console.warn(
|
|
2952
|
-
`[apm] \u8FDC\u7A0B\u90E8\u7F72\u914D\u7F6E\u300C${configName}\u300DJSON \u65E0\u6548\uFF08${TEMPLATE_HINT}\uFF09`
|
|
2876
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
2877
|
+
async function initializeWorkspace(workdir, options) {
|
|
2878
|
+
await ensureWorkspaceApmDirForInit(workdir);
|
|
2879
|
+
const apmDir = workspaceApmDir(workdir);
|
|
2880
|
+
await copyTemplateFiles(apmDir, workdir);
|
|
2881
|
+
const trimmedName = options?.name?.trim();
|
|
2882
|
+
if (trimmedName) {
|
|
2883
|
+
const apmConfigPath = toFsPath(join4(apmDir, "apm.config.json"));
|
|
2884
|
+
const config = readFileSync5(apmConfigPath, "utf8");
|
|
2885
|
+
const configJson = JSON.parse(config);
|
|
2886
|
+
configJson.name = trimmedName;
|
|
2887
|
+
writeFileSync5(
|
|
2888
|
+
apmConfigPath,
|
|
2889
|
+
`${JSON.stringify(configJson, null, 2)}
|
|
2890
|
+
`,
|
|
2891
|
+
"utf8"
|
|
2953
2892
|
);
|
|
2954
|
-
return false;
|
|
2955
2893
|
}
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
`, "utf8");
|
|
2959
|
-
console.log(`[apm] \u5DF2\u540C\u6B65\u5E73\u53F0\u90E8\u7F72\u914D\u7F6E: ${configName}`);
|
|
2960
|
-
console.log("[apm] \u5DF2\u5199\u5165 .apm/apm.config.json");
|
|
2961
|
-
return true;
|
|
2894
|
+
console.log(`[apm] \u5DF2\u521D\u59CB\u5316\u5DE5\u4F5C\u533A\uFF1A${apmDir}`);
|
|
2895
|
+
return { didInit: true };
|
|
2962
2896
|
}
|
|
2963
|
-
async function
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
console.log(
|
|
2967
|
-
`[apm] \u672A\u68C0\u6D4B\u5230\u767B\u5F55\u4FE1\u606F\uFF0C\u8DF3\u8FC7\u5E73\u53F0\u90E8\u7F72\u914D\u7F6E\u540C\u6B65\uFF08${TEMPLATE_HINT}\uFF09\u3002
|
|
2968
|
-
[apm] \u8BF7\u5148\u6267\u884C apm login\uFF0C\u518D\u6267\u884C apm sync-deploy-config \u62C9\u53D6\u6700\u65B0\u914D\u7F6E\u3002`
|
|
2969
|
-
);
|
|
2970
|
-
return { synced: false, repositoryId: null };
|
|
2971
|
-
}
|
|
2972
|
-
const api = createApmApiClient(cfg);
|
|
2973
|
-
const preferredId = options?.repositoryId?.trim() || "";
|
|
2974
|
-
let repositoryId = preferredId || null;
|
|
2975
|
-
let diagnostic = null;
|
|
2976
|
-
if (!repositoryId) {
|
|
2977
|
-
const resolved = await resolveRepositoryIdForSync(api, workdirPath);
|
|
2978
|
-
repositoryId = resolved.repositoryId;
|
|
2979
|
-
diagnostic = resolved.diagnostic;
|
|
2980
|
-
}
|
|
2981
|
-
if (!repositoryId) {
|
|
2982
|
-
console.log(
|
|
2983
|
-
`[apm] \u672A\u80FD\u540C\u6B65\u5E73\u53F0\u90E8\u7F72\u914D\u7F6E\uFF08${TEMPLATE_HINT}\uFF09\u3002
|
|
2984
|
-
${diagnostic ?? ""}
|
|
2985
|
-
[apm] ${SYNC_HINT}`
|
|
2986
|
-
);
|
|
2987
|
-
return { synced: false, repositoryId: null };
|
|
2988
|
-
}
|
|
2989
|
-
const { config } = await api.cli.getDeploymentConfiguration({ repositoryId });
|
|
2990
|
-
if (!config) {
|
|
2991
|
-
console.log(
|
|
2992
|
-
`[apm] \u672A\u627E\u5230\u5173\u8054\u4ED3\u5E93\u7684\u90E8\u7F72\u914D\u7F6E\uFF08${TEMPLATE_HINT}\uFF0CrepositoryId\uFF1A${repositoryId}\uFF09\u3002
|
|
2993
|
-
[apm] \u8BF7\u5728\u5E73\u53F0\u300C\u90E8\u7F72\u914D\u7F6E\u300D\u4E2D\u521B\u5EFA\u914D\u7F6E\u5E76\u5173\u8054\u8BE5\u4ED3\u5E93\uFF0C\u7136\u540E\u6267\u884C: apm sync-deploy-config`
|
|
2994
|
-
);
|
|
2995
|
-
return { synced: false, repositoryId };
|
|
2897
|
+
async function ensureWorkspaceInitialized(workdir, options) {
|
|
2898
|
+
if (isWorkspaceApmInitialized(workdir)) {
|
|
2899
|
+
return { didInit: false };
|
|
2996
2900
|
}
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
targetApmDir,
|
|
3000
|
-
config.content,
|
|
3001
|
-
config.name
|
|
2901
|
+
console.log(
|
|
2902
|
+
`[apm] \u5DE5\u4F5C\u76EE\u5F55 ${workdir} \u672A\u68C0\u6D4B\u5230\u5DF2\u521D\u59CB\u5316\u7684 .apm\uFF0C\u6B63\u5728\u81EA\u52A8\u521D\u59CB\u5316\u2026`
|
|
3002
2903
|
);
|
|
3003
|
-
|
|
3004
|
-
return { synced: false, repositoryId };
|
|
3005
|
-
}
|
|
3006
|
-
return { synced: true, repositoryId, configName: config.name };
|
|
2904
|
+
return initializeWorkspace(workdir, options);
|
|
3007
2905
|
}
|
|
3008
2906
|
|
|
3009
|
-
// src/
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
readdirSync as readdirSync3,
|
|
3013
|
-
readFileSync as readFileSync5,
|
|
3014
|
-
rmSync as rmSync2,
|
|
3015
|
-
writeFileSync as writeFileSync6
|
|
3016
|
-
} from "fs";
|
|
3017
|
-
import { createHash } from "crypto";
|
|
3018
|
-
import { dirname as dirname5, join as join5, relative as relative2, sep } from "path";
|
|
3019
|
-
var MANIFEST_FILE = "manifest.json";
|
|
3020
|
-
function normalizeProjectIdForPath(projectId) {
|
|
3021
|
-
const id = projectId.trim();
|
|
3022
|
-
if (!id) {
|
|
3023
|
-
throw new Error("projectId \u4E0D\u80FD\u4E3A\u7A7A");
|
|
3024
|
-
}
|
|
3025
|
-
if (id.includes("..") || id.includes("/") || id.includes("\\") || id.includes("\0")) {
|
|
3026
|
-
throw new Error(`\u975E\u6CD5 projectId: ${projectId}`);
|
|
3027
|
-
}
|
|
3028
|
-
return id;
|
|
2907
|
+
// src/commands/connect/pre-step-cache.ts
|
|
2908
|
+
function sessionWorkdirKey(sessionId, workdir) {
|
|
2909
|
+
return `${sessionId}\0${workdir}`;
|
|
3029
2910
|
}
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
return
|
|
2911
|
+
var lastBranchKey = null;
|
|
2912
|
+
function shouldRunBranch(sessionId, workdir) {
|
|
2913
|
+
return lastBranchKey !== sessionWorkdirKey(sessionId, workdir);
|
|
3033
2914
|
}
|
|
3034
|
-
function
|
|
3035
|
-
|
|
3036
|
-
return join5(
|
|
3037
|
-
projectDocumentsDir(apmRoot, projectId),
|
|
3038
|
-
...normalized.split("/")
|
|
3039
|
-
);
|
|
2915
|
+
function markBranchDone(sessionId, workdir) {
|
|
2916
|
+
lastBranchKey = sessionWorkdirKey(sessionId, workdir);
|
|
3040
2917
|
}
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
2918
|
+
|
|
2919
|
+
// src/commands/connect/webide-pull-requests.ts
|
|
2920
|
+
var PRE_AGENT_PR_ACTIONS = /* @__PURE__ */ new Set([
|
|
2921
|
+
"generate-cases",
|
|
2922
|
+
"run-auto-test",
|
|
2923
|
+
// 验收合并前兜底确保 PR 存在
|
|
2924
|
+
"accept"
|
|
2925
|
+
]);
|
|
2926
|
+
var POST_AGENT_PR_ACTIONS = /* @__PURE__ */ new Set(["create-pr", "finish-manual-test"]);
|
|
2927
|
+
function shouldEnsureWebIdePullRequests(action) {
|
|
2928
|
+
return PRE_AGENT_PR_ACTIONS.has(action);
|
|
3051
2929
|
}
|
|
3052
|
-
function
|
|
3053
|
-
return
|
|
2930
|
+
function shouldEnsureWebIdePullRequestsAfterAgent(action) {
|
|
2931
|
+
return POST_AGENT_PR_ACTIONS.has(action);
|
|
3054
2932
|
}
|
|
3055
|
-
function
|
|
3056
|
-
const
|
|
3057
|
-
|
|
3058
|
-
|
|
2933
|
+
function formatWebIdePullRequestSummary(result) {
|
|
2934
|
+
const lines = [];
|
|
2935
|
+
lines.push("## PR \u521B\u5EFA\u7ED3\u679C");
|
|
2936
|
+
lines.push(
|
|
2937
|
+
`\u5408\u8BA1\uFF1A\u6210\u529F ${result.ensured} \u6761\uFF0C\u65E0\u53D8\u66F4\u8DF3\u8FC7 ${result.skippedNoChanges} \u6761\uFF0C\u5176\u4ED6\u8DF3\u8FC7 ${result.skipped} \u6761\uFF0C\u5931\u8D25 ${result.failed} \u6761\u3002`
|
|
3059
2938
|
);
|
|
3060
|
-
if (
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
try {
|
|
3064
|
-
return JSON.parse(
|
|
3065
|
-
readFileSync5(manifestPath3, "utf8")
|
|
3066
|
-
);
|
|
3067
|
-
} catch {
|
|
3068
|
-
return null;
|
|
3069
|
-
}
|
|
3070
|
-
}
|
|
3071
|
-
function listLocalDocumentPaths(apmRoot, projectId) {
|
|
3072
|
-
const root = projectDocumentsDir(apmRoot, projectId);
|
|
3073
|
-
if (!existsSync6(root)) {
|
|
3074
|
-
return [];
|
|
2939
|
+
if (result.items.length === 0) {
|
|
2940
|
+
lines.push("\u672A\u5904\u7406\u4EFB\u4F55\u4ED3\u5E93\u3002");
|
|
2941
|
+
return lines.join("\n");
|
|
3075
2942
|
}
|
|
3076
|
-
|
|
3077
|
-
const
|
|
3078
|
-
|
|
3079
|
-
const
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
const rel = relative2(root, abs).split(sep).join("/");
|
|
3088
|
-
paths.push(rel);
|
|
2943
|
+
lines.push("");
|
|
2944
|
+
for (const item of result.items) {
|
|
2945
|
+
if (item.outcome === "created") {
|
|
2946
|
+
const num = item.number != null && item.number > 0 ? `#${item.number}` : "\uFF08\u65E0\u7F16\u53F7\uFF09";
|
|
2947
|
+
const branch = item.headBranch && item.baseBranch ? `${item.headBranch} \u2192 ${item.baseBranch}` : item.baseBranch ? `\u76EE\u6807\u5206\u652F ${item.baseBranch}` : "";
|
|
2948
|
+
const state = item.state ? `\u72B6\u6001 ${item.state}` : "";
|
|
2949
|
+
const url = item.url?.trim() ? item.url.trim() : "";
|
|
2950
|
+
lines.push(
|
|
2951
|
+
`- **${item.label}**\uFF1A\u5DF2\u521B\u5EFA ${num}${branch ? `\uFF0C${branch}` : ""}${state ? `\uFF0C${state}` : ""}${url ? `\uFF0C${url}` : ""}`
|
|
2952
|
+
);
|
|
2953
|
+
continue;
|
|
3089
2954
|
}
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
const remoteMap = new Map(
|
|
3096
|
-
(remote?.documents ?? []).map((doc) => [doc.path, doc.contentHash])
|
|
3097
|
-
);
|
|
3098
|
-
const localMap = new Map(
|
|
3099
|
-
(local?.documents ?? []).map((doc) => [doc.path, doc.contentHash])
|
|
3100
|
-
);
|
|
3101
|
-
const download = [];
|
|
3102
|
-
for (const [path, hash] of remoteMap) {
|
|
3103
|
-
if (localMap.get(path) !== hash) {
|
|
3104
|
-
download.push(path);
|
|
2955
|
+
if (item.outcome === "skipped_no_changes") {
|
|
2956
|
+
lines.push(
|
|
2957
|
+
`- **${item.label}**\uFF1A\u76F8\u5BF9\u57FA\u7EBF ${item.baseBranch || "\uFF08\u672A\u77E5\uFF09"} \u65E0\u4EE3\u7801\u53D8\u66F4\uFF0C\u672A\u521B\u5EFA PR`
|
|
2958
|
+
);
|
|
2959
|
+
continue;
|
|
3105
2960
|
}
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
if (!remoteMap.has(path)) {
|
|
3110
|
-
deleteLocal.push(path);
|
|
2961
|
+
if (item.outcome === "skipped") {
|
|
2962
|
+
lines.push(`- **${item.label}**\uFF1A\u5DF2\u8DF3\u8FC7 \u2014 ${item.detail}`);
|
|
2963
|
+
continue;
|
|
3111
2964
|
}
|
|
2965
|
+
lines.push(`- **${item.label}**\uFF1A\u521B\u5EFA\u5931\u8D25 \u2014 ${item.detail}`);
|
|
3112
2966
|
}
|
|
3113
|
-
return
|
|
2967
|
+
return lines.join("\n");
|
|
3114
2968
|
}
|
|
3115
|
-
async function
|
|
3116
|
-
const
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
2969
|
+
async function ensureWebIdePullRequests(cfg, taskId, workdir) {
|
|
2970
|
+
const api = createApmApiClient(cfg);
|
|
2971
|
+
const empty = () => ({
|
|
2972
|
+
ensured: 0,
|
|
2973
|
+
skipped: 0,
|
|
2974
|
+
skippedNoChanges: 0,
|
|
2975
|
+
failed: 0,
|
|
2976
|
+
items: [],
|
|
2977
|
+
tips: []
|
|
2978
|
+
});
|
|
2979
|
+
let repoRoots;
|
|
3120
2980
|
try {
|
|
3121
|
-
const
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
}
|
|
3126
|
-
const projectIds = baseline.projectIds ?? [];
|
|
3127
|
-
if (projectIds.length === 0) {
|
|
3128
|
-
return {
|
|
3129
|
-
projectId: null,
|
|
3130
|
-
diagnostic: baseline.diagnostic?.message ?? `\u5DE5\u4F5C\u7A7A\u95F4\u672A\u5173\u8054\u9879\u76EE\uFF0C\u65E0\u6CD5\u540C\u6B65\u9879\u76EE\u6587\u6863\uFF08\u76EE\u5F55\uFF1A${workdirPath}\uFF09\u3002
|
|
3131
|
-
\u8BF7\u5728\u5E73\u53F0\u5C06\u5DE5\u4F5C\u7A7A\u95F4\u5173\u8054\u5230\u552F\u4E00\u9879\u76EE\u3002`
|
|
3132
|
-
};
|
|
3133
|
-
}
|
|
2981
|
+
const manifest = loadWorkspaceReposCache(workdir);
|
|
2982
|
+
repoRoots = resolveWorkspaceRepoAbsolutePaths(manifest);
|
|
2983
|
+
} catch (err) {
|
|
2984
|
+
const tip = `\u8BFB\u53D6\u4ED3\u5E93\u6E05\u5355\u5931\u8D25: ${err instanceof Error ? err.message : err}`;
|
|
2985
|
+
console.warn(`[apm] WebIDE PR\uFF1A${tip}`);
|
|
3134
2986
|
return {
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
2987
|
+
...empty(),
|
|
2988
|
+
failed: 1,
|
|
2989
|
+
tips: [tip],
|
|
2990
|
+
items: [
|
|
2991
|
+
{
|
|
2992
|
+
label: "\u5DE5\u4F5C\u533A",
|
|
2993
|
+
outcome: "failed",
|
|
2994
|
+
detail: tip
|
|
2995
|
+
}
|
|
2996
|
+
]
|
|
3138
2997
|
};
|
|
2998
|
+
}
|
|
2999
|
+
let projectBaseBranch = "";
|
|
3000
|
+
try {
|
|
3001
|
+
const baseline = await api.cli.projectBaseBranch({ taskId });
|
|
3002
|
+
projectBaseBranch = baseline.baseBranch?.trim() ?? "";
|
|
3139
3003
|
} catch (err) {
|
|
3140
|
-
const
|
|
3004
|
+
const tip = `\u8BFB\u53D6\u9879\u76EE\u57FA\u7EBF\u5206\u652F\u5931\u8D25: ${err instanceof Error ? err.message : err}`;
|
|
3005
|
+
console.warn(`[apm] WebIDE PR\uFF1A${tip}`);
|
|
3141
3006
|
return {
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
}
|
|
3147
|
-
async function syncProjectDocumentsPull(workdirPath, apmDir, options) {
|
|
3148
|
-
const empty = {
|
|
3149
|
-
synced: false,
|
|
3150
|
-
projectId: null,
|
|
3151
|
-
downloaded: 0,
|
|
3152
|
-
deleted: 0
|
|
3153
|
-
};
|
|
3154
|
-
const cfg = await tryReadApmConfig();
|
|
3155
|
-
if (!cfg || !resolveApiKey(cfg)) {
|
|
3156
|
-
console.log(
|
|
3157
|
-
"[apm] \u672A\u68C0\u6D4B\u5230\u767B\u5F55\u4FE1\u606F\uFF0C\u8DF3\u8FC7\u9879\u76EE\u6587\u6863\u540C\u6B65\u3002\n[apm] \u8BF7\u5148\u6267\u884C apm login\u3002"
|
|
3158
|
-
);
|
|
3159
|
-
return empty;
|
|
3160
|
-
}
|
|
3161
|
-
const api = createApmApiClient(cfg);
|
|
3162
|
-
const { projectId, diagnostic } = await resolveProjectIdForSync(
|
|
3163
|
-
api,
|
|
3164
|
-
workdirPath,
|
|
3165
|
-
options
|
|
3166
|
-
);
|
|
3167
|
-
if (!projectId) {
|
|
3168
|
-
console.log(`[apm] \u672A\u80FD\u540C\u6B65\u9879\u76EE\u6587\u6863\u3002
|
|
3169
|
-
${diagnostic ?? ""}`);
|
|
3170
|
-
return empty;
|
|
3171
|
-
}
|
|
3172
|
-
const targetApmDir = apmDir ?? workspaceApmDir(workdirPath);
|
|
3173
|
-
const docsDir = projectDocumentsDir(targetApmDir, projectId);
|
|
3174
|
-
await ensureDirExists(docsDir);
|
|
3175
|
-
const { manifest: remoteManifest } = await api.cli.getProjectDocumentManifest(
|
|
3176
|
-
{ projectId }
|
|
3177
|
-
);
|
|
3178
|
-
if (!remoteManifest) {
|
|
3179
|
-
console.log(`[apm] \u9879\u76EE ${projectId} \u65E0\u9879\u76EE\u6587\u6863 manifest\uFF0C\u8DF3\u8FC7\u540C\u6B65\u3002`);
|
|
3180
|
-
return { ...empty, projectId };
|
|
3181
|
-
}
|
|
3182
|
-
const localManifest = readLocalManifest(targetApmDir, projectId);
|
|
3183
|
-
const { download, deleteLocal } = diffManifestPaths(
|
|
3184
|
-
remoteManifest,
|
|
3185
|
-
localManifest
|
|
3186
|
-
);
|
|
3187
|
-
let downloaded = 0;
|
|
3188
|
-
if (download.length > 0) {
|
|
3189
|
-
const { list } = await api.cli.listProjectDocuments({
|
|
3190
|
-
projectId,
|
|
3191
|
-
paths: download.join(",")
|
|
3192
|
-
});
|
|
3193
|
-
for (const doc of list) {
|
|
3194
|
-
const absPath = toFsPath(
|
|
3195
|
-
projectDocumentLocalPath(targetApmDir, projectId, doc.path)
|
|
3196
|
-
);
|
|
3197
|
-
await ensureDirExists(dirname5(absPath));
|
|
3198
|
-
writeFileSync6(absPath, doc.content, "utf8");
|
|
3199
|
-
downloaded += 1;
|
|
3200
|
-
}
|
|
3201
|
-
}
|
|
3202
|
-
let deleted = 0;
|
|
3203
|
-
for (const path of deleteLocal) {
|
|
3204
|
-
const absPath = toFsPath(
|
|
3205
|
-
projectDocumentLocalPath(targetApmDir, projectId, path)
|
|
3206
|
-
);
|
|
3207
|
-
if (existsSync6(absPath)) {
|
|
3208
|
-
rmSync2(absPath, { force: true });
|
|
3209
|
-
deleted += 1;
|
|
3210
|
-
}
|
|
3211
|
-
}
|
|
3212
|
-
writeFileSync6(
|
|
3213
|
-
toFsPath(join5(docsDir, MANIFEST_FILE)),
|
|
3214
|
-
`${JSON.stringify(remoteManifest, null, 2)}
|
|
3215
|
-
`,
|
|
3216
|
-
"utf8"
|
|
3217
|
-
);
|
|
3218
|
-
console.log(
|
|
3219
|
-
`[apm] \u5DF2\u540C\u6B65\u9879\u76EE\u6587\u6863: projectId=${projectId} \u4E0B\u8F7D ${downloaded}\uFF0C\u5220\u9664\u672C\u5730 ${deleted} \u2192 .apm/project/${projectId}/`
|
|
3220
|
-
);
|
|
3221
|
-
return {
|
|
3222
|
-
synced: true,
|
|
3223
|
-
projectId,
|
|
3224
|
-
downloaded,
|
|
3225
|
-
deleted
|
|
3226
|
-
};
|
|
3227
|
-
}
|
|
3228
|
-
async function syncProjectDocumentsPush(cfg, workdirPath, apmRoot, options) {
|
|
3229
|
-
const api = createApmApiClient(cfg);
|
|
3230
|
-
const { projectId } = await resolveProjectIdForSync(
|
|
3231
|
-
api,
|
|
3232
|
-
workdirPath,
|
|
3233
|
-
options
|
|
3234
|
-
);
|
|
3235
|
-
if (!projectId) {
|
|
3236
|
-
return 0;
|
|
3237
|
-
}
|
|
3238
|
-
const targetApmDir = apmRoot ?? workspaceApmDir(workdirPath);
|
|
3239
|
-
const localPaths = listLocalDocumentPaths(targetApmDir, projectId);
|
|
3240
|
-
if (localPaths.length === 0) {
|
|
3241
|
-
console.log("[apm] \u9879\u76EE\u6587\u6863\u65E0\u672C\u5730\u6587\u4EF6\uFF0C\u8DF3\u8FC7\u63A8\u9001");
|
|
3242
|
-
return 0;
|
|
3243
|
-
}
|
|
3244
|
-
const remoteManifest = (await api.cli.getProjectDocumentManifest({ projectId })).manifest ?? null;
|
|
3245
|
-
const remoteHashByPath = new Map(
|
|
3246
|
-
(remoteManifest?.documents ?? []).map((doc) => [doc.path, doc.contentHash])
|
|
3247
|
-
);
|
|
3248
|
-
const remoteDescriptionByPath = new Map(
|
|
3249
|
-
(remoteManifest?.documents ?? []).map((doc) => [doc.path, doc.description])
|
|
3250
|
-
);
|
|
3251
|
-
let synced = 0;
|
|
3252
|
-
for (const path of localPaths) {
|
|
3253
|
-
const absPath = toFsPath(
|
|
3254
|
-
projectDocumentLocalPath(targetApmDir, projectId, path)
|
|
3255
|
-
);
|
|
3256
|
-
const content = readFileSync5(absPath, "utf8");
|
|
3257
|
-
const contentHash = hashLocalFileContent(content);
|
|
3258
|
-
if (remoteHashByPath.get(path) === contentHash) {
|
|
3259
|
-
continue;
|
|
3260
|
-
}
|
|
3261
|
-
await api.cli.upsertProjectDocument({
|
|
3262
|
-
projectId,
|
|
3263
|
-
path,
|
|
3264
|
-
content,
|
|
3265
|
-
description: remoteDescriptionByPath.get(path) ?? void 0
|
|
3266
|
-
});
|
|
3267
|
-
synced += 1;
|
|
3268
|
-
console.log(`[apm] \u5DF2\u540C\u6B65\u9879\u76EE\u6587\u6863: ${path}`);
|
|
3269
|
-
}
|
|
3270
|
-
if (synced === 0) {
|
|
3271
|
-
console.log("[apm] \u9879\u76EE\u6587\u6863\u65E0\u53D8\u5316\uFF0C\u8DF3\u8FC7\u63A8\u9001");
|
|
3272
|
-
}
|
|
3273
|
-
return synced;
|
|
3274
|
-
}
|
|
3275
|
-
|
|
3276
|
-
// src/commands/init.ts
|
|
3277
|
-
async function initializeWorkspace(workdir, options) {
|
|
3278
|
-
await ensureWorkspaceApmDirForInit(workdir);
|
|
3279
|
-
const apmDir = workspaceApmDir(workdir);
|
|
3280
|
-
await copyTemplateFiles(apmDir, workdir);
|
|
3281
|
-
const syncResult = await syncRemoteDeploymentConfig(workdir, apmDir);
|
|
3282
|
-
await syncProjectDocumentsPull(workdir, apmDir);
|
|
3283
|
-
const trimmedName = options?.name?.trim();
|
|
3284
|
-
if (trimmedName) {
|
|
3285
|
-
const apmConfigPath = toFsPath(join6(apmDir, "apm.config.json"));
|
|
3286
|
-
const config = readFileSync6(apmConfigPath, "utf8");
|
|
3287
|
-
const configJson = JSON.parse(config);
|
|
3288
|
-
configJson.name = trimmedName;
|
|
3289
|
-
writeFileSync7(
|
|
3290
|
-
apmConfigPath,
|
|
3291
|
-
`${JSON.stringify(configJson, null, 2)}
|
|
3292
|
-
`,
|
|
3293
|
-
"utf8"
|
|
3294
|
-
);
|
|
3295
|
-
}
|
|
3296
|
-
console.log(`[apm] \u5DF2\u521D\u59CB\u5316\u5DE5\u4F5C\u533A\uFF1A${apmDir}`);
|
|
3297
|
-
return { didInit: true, syncResult };
|
|
3298
|
-
}
|
|
3299
|
-
async function ensureWorkspaceInitialized(workdir, options) {
|
|
3300
|
-
if (isWorkspaceApmInitialized(workdir)) {
|
|
3301
|
-
return { didInit: false };
|
|
3302
|
-
}
|
|
3303
|
-
console.log(
|
|
3304
|
-
`[apm] \u5DE5\u4F5C\u76EE\u5F55 ${workdir} \u672A\u68C0\u6D4B\u5230\u5DF2\u521D\u59CB\u5316\u7684 .apm\uFF0C\u6B63\u5728\u81EA\u52A8\u521D\u59CB\u5316\u2026`
|
|
3305
|
-
);
|
|
3306
|
-
return initializeWorkspace(workdir, options);
|
|
3307
|
-
}
|
|
3308
|
-
|
|
3309
|
-
// src/commands/connect/pre-step-cache.ts
|
|
3310
|
-
function sessionWorkdirKey(sessionId, workdir) {
|
|
3311
|
-
return `${sessionId}\0${workdir}`;
|
|
3312
|
-
}
|
|
3313
|
-
var lastBranchKey = null;
|
|
3314
|
-
function shouldRunBranch(sessionId, workdir) {
|
|
3315
|
-
return lastBranchKey !== sessionWorkdirKey(sessionId, workdir);
|
|
3316
|
-
}
|
|
3317
|
-
function markBranchDone(sessionId, workdir) {
|
|
3318
|
-
lastBranchKey = sessionWorkdirKey(sessionId, workdir);
|
|
3319
|
-
}
|
|
3320
|
-
|
|
3321
|
-
// src/commands/connect/webide-pull-requests.ts
|
|
3322
|
-
var PRE_AGENT_PR_ACTIONS = /* @__PURE__ */ new Set([
|
|
3323
|
-
"generate-cases",
|
|
3324
|
-
"run-auto-test",
|
|
3325
|
-
// 验收合并前兜底确保 PR 存在
|
|
3326
|
-
"accept"
|
|
3327
|
-
]);
|
|
3328
|
-
var POST_AGENT_PR_ACTIONS = /* @__PURE__ */ new Set(["create-pr", "finish-manual-test"]);
|
|
3329
|
-
function shouldEnsureWebIdePullRequests(action) {
|
|
3330
|
-
return PRE_AGENT_PR_ACTIONS.has(action);
|
|
3331
|
-
}
|
|
3332
|
-
function shouldEnsureWebIdePullRequestsAfterAgent(action) {
|
|
3333
|
-
return POST_AGENT_PR_ACTIONS.has(action);
|
|
3334
|
-
}
|
|
3335
|
-
function formatWebIdePullRequestSummary(result) {
|
|
3336
|
-
const lines = [];
|
|
3337
|
-
lines.push("## PR \u521B\u5EFA\u7ED3\u679C");
|
|
3338
|
-
lines.push(
|
|
3339
|
-
`\u5408\u8BA1\uFF1A\u6210\u529F ${result.ensured} \u6761\uFF0C\u65E0\u53D8\u66F4\u8DF3\u8FC7 ${result.skippedNoChanges} \u6761\uFF0C\u5176\u4ED6\u8DF3\u8FC7 ${result.skipped} \u6761\uFF0C\u5931\u8D25 ${result.failed} \u6761\u3002`
|
|
3340
|
-
);
|
|
3341
|
-
if (result.items.length === 0) {
|
|
3342
|
-
lines.push("\u672A\u5904\u7406\u4EFB\u4F55\u4ED3\u5E93\u3002");
|
|
3343
|
-
return lines.join("\n");
|
|
3344
|
-
}
|
|
3345
|
-
lines.push("");
|
|
3346
|
-
for (const item of result.items) {
|
|
3347
|
-
if (item.outcome === "created") {
|
|
3348
|
-
const num = item.number != null && item.number > 0 ? `#${item.number}` : "\uFF08\u65E0\u7F16\u53F7\uFF09";
|
|
3349
|
-
const branch = item.headBranch && item.baseBranch ? `${item.headBranch} \u2192 ${item.baseBranch}` : item.baseBranch ? `\u76EE\u6807\u5206\u652F ${item.baseBranch}` : "";
|
|
3350
|
-
const state = item.state ? `\u72B6\u6001 ${item.state}` : "";
|
|
3351
|
-
const url = item.url?.trim() ? item.url.trim() : "";
|
|
3352
|
-
lines.push(
|
|
3353
|
-
`- **${item.label}**\uFF1A\u5DF2\u521B\u5EFA ${num}${branch ? `\uFF0C${branch}` : ""}${state ? `\uFF0C${state}` : ""}${url ? `\uFF0C${url}` : ""}`
|
|
3354
|
-
);
|
|
3355
|
-
continue;
|
|
3356
|
-
}
|
|
3357
|
-
if (item.outcome === "skipped_no_changes") {
|
|
3358
|
-
lines.push(
|
|
3359
|
-
`- **${item.label}**\uFF1A\u76F8\u5BF9\u57FA\u7EBF ${item.baseBranch || "\uFF08\u672A\u77E5\uFF09"} \u65E0\u4EE3\u7801\u53D8\u66F4\uFF0C\u672A\u521B\u5EFA PR`
|
|
3360
|
-
);
|
|
3361
|
-
continue;
|
|
3362
|
-
}
|
|
3363
|
-
if (item.outcome === "skipped") {
|
|
3364
|
-
lines.push(`- **${item.label}**\uFF1A\u5DF2\u8DF3\u8FC7 \u2014 ${item.detail}`);
|
|
3365
|
-
continue;
|
|
3366
|
-
}
|
|
3367
|
-
lines.push(`- **${item.label}**\uFF1A\u521B\u5EFA\u5931\u8D25 \u2014 ${item.detail}`);
|
|
3368
|
-
}
|
|
3369
|
-
return lines.join("\n");
|
|
3370
|
-
}
|
|
3371
|
-
async function ensureWebIdePullRequests(cfg, taskId, workdir) {
|
|
3372
|
-
const api = createApmApiClient(cfg);
|
|
3373
|
-
const empty = () => ({
|
|
3374
|
-
ensured: 0,
|
|
3375
|
-
skipped: 0,
|
|
3376
|
-
skippedNoChanges: 0,
|
|
3377
|
-
failed: 0,
|
|
3378
|
-
items: [],
|
|
3379
|
-
tips: []
|
|
3380
|
-
});
|
|
3381
|
-
let repoRoots;
|
|
3382
|
-
try {
|
|
3383
|
-
const manifest = loadWorkspaceReposCache(workdir);
|
|
3384
|
-
repoRoots = resolveWorkspaceRepoAbsolutePaths(manifest);
|
|
3385
|
-
} catch (err) {
|
|
3386
|
-
const tip = `\u8BFB\u53D6\u4ED3\u5E93\u6E05\u5355\u5931\u8D25: ${err instanceof Error ? err.message : err}`;
|
|
3387
|
-
console.warn(`[apm] WebIDE PR\uFF1A${tip}`);
|
|
3388
|
-
return {
|
|
3389
|
-
...empty(),
|
|
3390
|
-
failed: 1,
|
|
3391
|
-
tips: [tip],
|
|
3392
|
-
items: [
|
|
3393
|
-
{
|
|
3394
|
-
label: "\u5DE5\u4F5C\u533A",
|
|
3395
|
-
outcome: "failed",
|
|
3396
|
-
detail: tip
|
|
3397
|
-
}
|
|
3398
|
-
]
|
|
3399
|
-
};
|
|
3400
|
-
}
|
|
3401
|
-
let projectBaseBranch = "";
|
|
3402
|
-
try {
|
|
3403
|
-
const baseline = await api.cli.projectBaseBranch({ taskId });
|
|
3404
|
-
projectBaseBranch = baseline.baseBranch?.trim() ?? "";
|
|
3405
|
-
} catch (err) {
|
|
3406
|
-
const tip = `\u8BFB\u53D6\u9879\u76EE\u57FA\u7EBF\u5206\u652F\u5931\u8D25: ${err instanceof Error ? err.message : err}`;
|
|
3407
|
-
console.warn(`[apm] WebIDE PR\uFF1A${tip}`);
|
|
3408
|
-
return {
|
|
3409
|
-
...empty(),
|
|
3410
|
-
failed: 1,
|
|
3411
|
-
tips: [tip],
|
|
3412
|
-
items: [{ label: "\u5DE5\u4F5C\u533A", outcome: "failed", detail: tip }]
|
|
3007
|
+
...empty(),
|
|
3008
|
+
failed: 1,
|
|
3009
|
+
tips: [tip],
|
|
3010
|
+
items: [{ label: "\u5DE5\u4F5C\u533A", outcome: "failed", detail: tip }]
|
|
3413
3011
|
};
|
|
3414
3012
|
}
|
|
3415
3013
|
if (!projectBaseBranch) {
|
|
@@ -3555,14 +3153,14 @@ async function ensureWebIdePullRequests(cfg, taskId, workdir) {
|
|
|
3555
3153
|
}
|
|
3556
3154
|
|
|
3557
3155
|
// src/version.ts
|
|
3558
|
-
import { readFileSync as
|
|
3559
|
-
import { dirname as
|
|
3156
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
3157
|
+
import { dirname as dirname5, join as join5 } from "path";
|
|
3560
3158
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3561
3159
|
function readCliVersion() {
|
|
3562
3160
|
try {
|
|
3563
|
-
const dir =
|
|
3564
|
-
const pkgPath =
|
|
3565
|
-
const pkg = JSON.parse(
|
|
3161
|
+
const dir = dirname5(fileURLToPath2(import.meta.url));
|
|
3162
|
+
const pkgPath = join5(dir, "..", "package.json");
|
|
3163
|
+
const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
|
|
3566
3164
|
return pkg.version ?? "0.0.0";
|
|
3567
3165
|
} catch {
|
|
3568
3166
|
return "0.0.0";
|
|
@@ -3570,46 +3168,46 @@ function readCliVersion() {
|
|
|
3570
3168
|
}
|
|
3571
3169
|
|
|
3572
3170
|
// src/commands/update-skills.ts
|
|
3573
|
-
import { existsSync as
|
|
3574
|
-
import { join as
|
|
3171
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync7, statSync as statSync4 } from "fs";
|
|
3172
|
+
import { join as join7 } from "path";
|
|
3575
3173
|
|
|
3576
3174
|
// src/skills-sync.ts
|
|
3577
3175
|
import {
|
|
3578
3176
|
copyFileSync as copyFileSync2,
|
|
3579
3177
|
cpSync,
|
|
3580
|
-
existsSync as
|
|
3178
|
+
existsSync as existsSync6,
|
|
3581
3179
|
mkdirSync as mkdirSync6,
|
|
3582
|
-
readdirSync as
|
|
3583
|
-
rmSync as
|
|
3180
|
+
readdirSync as readdirSync3,
|
|
3181
|
+
rmSync as rmSync2,
|
|
3584
3182
|
statSync as statSync3,
|
|
3585
|
-
writeFileSync as
|
|
3183
|
+
writeFileSync as writeFileSync6
|
|
3586
3184
|
} from "fs";
|
|
3587
|
-
import { join as
|
|
3588
|
-
var AGENTS_TEMPLATE_PATH =
|
|
3589
|
-
var BASE_SKILLS_TEMPLATE_DIR =
|
|
3590
|
-
var BASE_RULES_TEMPLATE_DIR =
|
|
3185
|
+
import { join as join6 } from "path";
|
|
3186
|
+
var AGENTS_TEMPLATE_PATH = join6(CLI_TEMPLATE_DIR, "AGENTS.md");
|
|
3187
|
+
var BASE_SKILLS_TEMPLATE_DIR = join6(CLI_TEMPLATE_DIR, "skills");
|
|
3188
|
+
var BASE_RULES_TEMPLATE_DIR = join6(CLI_TEMPLATE_DIR, "rules");
|
|
3591
3189
|
function sanitizeSkillDirName(name) {
|
|
3592
3190
|
const trimmed = name.trim();
|
|
3593
3191
|
if (!trimmed) return "skill";
|
|
3594
3192
|
return trimmed.replace(/[/\\:*?"<>|]/g, "_");
|
|
3595
3193
|
}
|
|
3596
3194
|
function listBaseSkillDirNames() {
|
|
3597
|
-
if (!
|
|
3598
|
-
return
|
|
3599
|
-
const path =
|
|
3195
|
+
if (!existsSync6(BASE_SKILLS_TEMPLATE_DIR)) return [];
|
|
3196
|
+
return readdirSync3(BASE_SKILLS_TEMPLATE_DIR).filter((name) => {
|
|
3197
|
+
const path = join6(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
3600
3198
|
return statSync3(path).isDirectory();
|
|
3601
3199
|
});
|
|
3602
3200
|
}
|
|
3603
3201
|
function syncAgentsGuide(apmDir) {
|
|
3604
|
-
if (!
|
|
3202
|
+
if (!existsSync6(AGENTS_TEMPLATE_PATH)) return false;
|
|
3605
3203
|
mkdirSync6(apmDir, { recursive: true });
|
|
3606
|
-
copyFileSync2(AGENTS_TEMPLATE_PATH,
|
|
3204
|
+
copyFileSync2(AGENTS_TEMPLATE_PATH, join6(apmDir, "AGENTS.md"));
|
|
3607
3205
|
return true;
|
|
3608
3206
|
}
|
|
3609
3207
|
function listBaseRuleFileNames() {
|
|
3610
|
-
if (!
|
|
3611
|
-
return
|
|
3612
|
-
const path =
|
|
3208
|
+
if (!existsSync6(BASE_RULES_TEMPLATE_DIR)) return [];
|
|
3209
|
+
return readdirSync3(BASE_RULES_TEMPLATE_DIR).filter((name) => {
|
|
3210
|
+
const path = join6(BASE_RULES_TEMPLATE_DIR, name);
|
|
3613
3211
|
return statSync3(path).isFile();
|
|
3614
3212
|
});
|
|
3615
3213
|
}
|
|
@@ -3617,8 +3215,8 @@ function syncBaseRules(rulesDir) {
|
|
|
3617
3215
|
mkdirSync6(rulesDir, { recursive: true });
|
|
3618
3216
|
const names = listBaseRuleFileNames();
|
|
3619
3217
|
for (const name of names) {
|
|
3620
|
-
const src =
|
|
3621
|
-
const dest =
|
|
3218
|
+
const src = join6(BASE_RULES_TEMPLATE_DIR, name);
|
|
3219
|
+
const dest = join6(rulesDir, name);
|
|
3622
3220
|
copyFileSync2(src, dest);
|
|
3623
3221
|
}
|
|
3624
3222
|
return names;
|
|
@@ -3627,8 +3225,8 @@ function syncBaseSkills(skillsDir) {
|
|
|
3627
3225
|
mkdirSync6(skillsDir, { recursive: true });
|
|
3628
3226
|
const names = listBaseSkillDirNames();
|
|
3629
3227
|
for (const name of names) {
|
|
3630
|
-
const src =
|
|
3631
|
-
const dest =
|
|
3228
|
+
const src = join6(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
3229
|
+
const dest = join6(skillsDir, name);
|
|
3632
3230
|
cpSync(src, dest, { recursive: true, force: true });
|
|
3633
3231
|
}
|
|
3634
3232
|
return names;
|
|
@@ -3645,19 +3243,19 @@ function syncSupplementarySkills(skillsDir, list) {
|
|
|
3645
3243
|
skipped.push(dirName);
|
|
3646
3244
|
continue;
|
|
3647
3245
|
}
|
|
3648
|
-
const skillDir =
|
|
3246
|
+
const skillDir = join6(skillsDir, dirName);
|
|
3649
3247
|
mkdirSync6(skillDir, { recursive: true });
|
|
3650
|
-
|
|
3248
|
+
writeFileSync6(join6(skillDir, "SKILL.md"), skill.content ?? "", "utf8");
|
|
3651
3249
|
written.push(dirName);
|
|
3652
3250
|
}
|
|
3653
3251
|
const removed = [];
|
|
3654
|
-
if (!
|
|
3655
|
-
for (const entry of
|
|
3656
|
-
const full =
|
|
3252
|
+
if (!existsSync6(skillsDir)) return { written, skipped, removed };
|
|
3253
|
+
for (const entry of readdirSync3(skillsDir)) {
|
|
3254
|
+
const full = join6(skillsDir, entry);
|
|
3657
3255
|
if (!statSync3(full).isDirectory()) continue;
|
|
3658
3256
|
if (baseNames.has(entry)) continue;
|
|
3659
3257
|
if (apiDirNames.has(entry)) continue;
|
|
3660
|
-
|
|
3258
|
+
rmSync2(full, { recursive: true, force: true });
|
|
3661
3259
|
removed.push(entry);
|
|
3662
3260
|
}
|
|
3663
3261
|
return { written, skipped, removed };
|
|
@@ -3667,7 +3265,7 @@ function syncSupplementarySkills(skillsDir, list) {
|
|
|
3667
3265
|
async function syncWorkspaceSkills(cfg, workdir) {
|
|
3668
3266
|
const apmDir = workspaceApmDir(workdir);
|
|
3669
3267
|
const fsApmDir = toFsPath(apmDir);
|
|
3670
|
-
if (!
|
|
3268
|
+
if (!existsSync7(fsApmDir)) {
|
|
3671
3269
|
throw new Error("[apm] \u672A\u627E\u5230 .apm \u76EE\u5F55\uFF0C\u8BF7\u5148\u6267\u884C apm init");
|
|
3672
3270
|
}
|
|
3673
3271
|
const apmStat = statSync4(fsApmDir);
|
|
@@ -3679,12 +3277,12 @@ async function syncWorkspaceSkills(cfg, workdir) {
|
|
|
3679
3277
|
if (syncAgentsGuide(apmDir)) {
|
|
3680
3278
|
console.log("[apm] \u5DF2\u540C\u6B65 APM \u6307\u5357: .apm/AGENTS.md");
|
|
3681
3279
|
}
|
|
3682
|
-
const rulesDir =
|
|
3280
|
+
const rulesDir = join7(apmDir, "rules");
|
|
3683
3281
|
const ruleNames = syncBaseRules(rulesDir);
|
|
3684
3282
|
for (const name of ruleNames) {
|
|
3685
3283
|
console.log(`[apm] \u5DF2\u540C\u6B65\u57FA\u7840\u89C4\u5219: rules/${name}`);
|
|
3686
3284
|
}
|
|
3687
|
-
const skillsDir =
|
|
3285
|
+
const skillsDir = join7(apmDir, "skills");
|
|
3688
3286
|
mkdirSync7(toFsPath(skillsDir), { recursive: true });
|
|
3689
3287
|
const baseNames = syncBaseSkills(skillsDir);
|
|
3690
3288
|
for (const name of baseNames) {
|
|
@@ -3711,9 +3309,9 @@ async function syncWorkspaceSkills(cfg, workdir) {
|
|
|
3711
3309
|
}
|
|
3712
3310
|
|
|
3713
3311
|
// src/commands/sync-session-attachments.ts
|
|
3714
|
-
import { existsSync as
|
|
3715
|
-
import { join as
|
|
3716
|
-
var
|
|
3312
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "fs";
|
|
3313
|
+
import { join as join8 } from "path";
|
|
3314
|
+
var MANIFEST_FILE = ".sync-manifest.json";
|
|
3717
3315
|
async function downloadAttachment(cfg, attachmentId) {
|
|
3718
3316
|
const base = cfg.baseUrl.trim().replace(/\/+$/, "");
|
|
3719
3317
|
const url = `${base}/api/v1/tasks/attachments/file?${new URLSearchParams({
|
|
@@ -3728,13 +3326,13 @@ async function downloadAttachment(cfg, attachmentId) {
|
|
|
3728
3326
|
return Buffer.from(await res.arrayBuffer());
|
|
3729
3327
|
}
|
|
3730
3328
|
function loadManifest(dir) {
|
|
3731
|
-
const path =
|
|
3732
|
-
if (!
|
|
3329
|
+
const path = join8(dir, MANIFEST_FILE);
|
|
3330
|
+
if (!existsSync8(path)) {
|
|
3733
3331
|
return { version: 1, attachments: {} };
|
|
3734
3332
|
}
|
|
3735
3333
|
try {
|
|
3736
3334
|
const parsed = JSON.parse(
|
|
3737
|
-
|
|
3335
|
+
readFileSync7(path, "utf8")
|
|
3738
3336
|
);
|
|
3739
3337
|
if (parsed?.version === 1 && parsed.attachments && typeof parsed.attachments === "object") {
|
|
3740
3338
|
return parsed;
|
|
@@ -3744,15 +3342,15 @@ function loadManifest(dir) {
|
|
|
3744
3342
|
return { version: 1, attachments: {} };
|
|
3745
3343
|
}
|
|
3746
3344
|
function saveManifest(dir, manifest) {
|
|
3747
|
-
|
|
3748
|
-
|
|
3345
|
+
writeFileSync7(
|
|
3346
|
+
join8(dir, MANIFEST_FILE),
|
|
3749
3347
|
`${JSON.stringify(manifest, null, 2)}
|
|
3750
3348
|
`,
|
|
3751
3349
|
"utf8"
|
|
3752
3350
|
);
|
|
3753
3351
|
}
|
|
3754
3352
|
function isAttachmentUpToDate(entry, item, dest) {
|
|
3755
|
-
if (!entry || !
|
|
3353
|
+
if (!entry || !existsSync8(dest)) return false;
|
|
3756
3354
|
if (entry.name !== item.name) return false;
|
|
3757
3355
|
const createdAt = item.createdAt ?? "";
|
|
3758
3356
|
return entry.createdAt === createdAt;
|
|
@@ -3767,7 +3365,7 @@ async function syncAttachmentsToDirectory(cfg, attachments, dir, logLabel) {
|
|
|
3767
3365
|
const nextManifest = { version: 1, attachments: {} };
|
|
3768
3366
|
const names = [];
|
|
3769
3367
|
for (const item of attachments) {
|
|
3770
|
-
const dest =
|
|
3368
|
+
const dest = join8(dir, item.name);
|
|
3771
3369
|
const entry = manifest.attachments[item.id];
|
|
3772
3370
|
const createdAt = item.createdAt ?? "";
|
|
3773
3371
|
names.push(item.name);
|
|
@@ -3777,7 +3375,7 @@ async function syncAttachmentsToDirectory(cfg, attachments, dir, logLabel) {
|
|
|
3777
3375
|
continue;
|
|
3778
3376
|
}
|
|
3779
3377
|
const buffer = await downloadAttachment(cfg, item.id);
|
|
3780
|
-
|
|
3378
|
+
writeFileSync7(dest, buffer);
|
|
3781
3379
|
nextManifest.attachments[item.id] = {
|
|
3782
3380
|
name: item.name,
|
|
3783
3381
|
createdAt
|
|
@@ -3797,12 +3395,279 @@ async function syncWebIdeAttachments(cfg, taskId, workdir, attachments) {
|
|
|
3797
3395
|
);
|
|
3798
3396
|
}
|
|
3799
3397
|
|
|
3398
|
+
// src/project-documents-sync.ts
|
|
3399
|
+
import {
|
|
3400
|
+
existsSync as existsSync9,
|
|
3401
|
+
readdirSync as readdirSync4,
|
|
3402
|
+
readFileSync as readFileSync8,
|
|
3403
|
+
rmSync as rmSync3,
|
|
3404
|
+
writeFileSync as writeFileSync8
|
|
3405
|
+
} from "fs";
|
|
3406
|
+
import { createHash } from "crypto";
|
|
3407
|
+
import { dirname as dirname6, join as join9, relative as relative2, sep } from "path";
|
|
3408
|
+
var MANIFEST_FILE2 = "manifest.json";
|
|
3409
|
+
function normalizeProjectIdForPath(projectId) {
|
|
3410
|
+
const id = projectId.trim();
|
|
3411
|
+
if (!id) {
|
|
3412
|
+
throw new Error("projectId \u4E0D\u80FD\u4E3A\u7A7A");
|
|
3413
|
+
}
|
|
3414
|
+
if (id.includes("..") || id.includes("/") || id.includes("\\") || id.includes("\0")) {
|
|
3415
|
+
throw new Error(`\u975E\u6CD5 projectId: ${projectId}`);
|
|
3416
|
+
}
|
|
3417
|
+
return id;
|
|
3418
|
+
}
|
|
3419
|
+
function projectDocumentsDir(apmRoot, projectId) {
|
|
3420
|
+
const id = normalizeProjectIdForPath(projectId);
|
|
3421
|
+
return join9(apmRoot ?? workspaceApmDir(), "project", id);
|
|
3422
|
+
}
|
|
3423
|
+
function projectDocumentLocalPath(apmRoot, projectId, documentPath) {
|
|
3424
|
+
const normalized = normalizeLocalDocumentPath(documentPath);
|
|
3425
|
+
return join9(
|
|
3426
|
+
projectDocumentsDir(apmRoot, projectId),
|
|
3427
|
+
...normalized.split("/")
|
|
3428
|
+
);
|
|
3429
|
+
}
|
|
3430
|
+
function normalizeLocalDocumentPath(path) {
|
|
3431
|
+
const trimmed = path.trim().replace(/\\/g, "/");
|
|
3432
|
+
if (!trimmed || trimmed.startsWith("/") || /^[a-zA-Z]:/.test(trimmed)) {
|
|
3433
|
+
throw new Error(`\u975E\u6CD5\u6587\u6863\u8DEF\u5F84: ${path}`);
|
|
3434
|
+
}
|
|
3435
|
+
const segments = trimmed.split("/").filter(Boolean);
|
|
3436
|
+
if (segments.some((segment) => segment === ".." || segment === ".")) {
|
|
3437
|
+
throw new Error(`\u975E\u6CD5\u6587\u6863\u8DEF\u5F84: ${path}`);
|
|
3438
|
+
}
|
|
3439
|
+
return segments.join("/");
|
|
3440
|
+
}
|
|
3441
|
+
function hashLocalFileContent(content) {
|
|
3442
|
+
return createHash("sha256").update(content, "utf8").digest("hex");
|
|
3443
|
+
}
|
|
3444
|
+
function readLocalManifest(apmRoot, projectId) {
|
|
3445
|
+
const manifestPath3 = join9(
|
|
3446
|
+
projectDocumentsDir(apmRoot, projectId),
|
|
3447
|
+
MANIFEST_FILE2
|
|
3448
|
+
);
|
|
3449
|
+
if (!existsSync9(manifestPath3)) {
|
|
3450
|
+
return null;
|
|
3451
|
+
}
|
|
3452
|
+
try {
|
|
3453
|
+
return JSON.parse(
|
|
3454
|
+
readFileSync8(manifestPath3, "utf8")
|
|
3455
|
+
);
|
|
3456
|
+
} catch {
|
|
3457
|
+
return null;
|
|
3458
|
+
}
|
|
3459
|
+
}
|
|
3460
|
+
function listLocalDocumentPaths(apmRoot, projectId) {
|
|
3461
|
+
const root = projectDocumentsDir(apmRoot, projectId);
|
|
3462
|
+
if (!existsSync9(root)) {
|
|
3463
|
+
return [];
|
|
3464
|
+
}
|
|
3465
|
+
const paths = [];
|
|
3466
|
+
const walk = (dir) => {
|
|
3467
|
+
for (const entry of readdirSync4(dir, { withFileTypes: true })) {
|
|
3468
|
+
const abs = join9(dir, entry.name);
|
|
3469
|
+
if (entry.isDirectory()) {
|
|
3470
|
+
walk(abs);
|
|
3471
|
+
continue;
|
|
3472
|
+
}
|
|
3473
|
+
if (entry.isFile() && entry.name === MANIFEST_FILE2) {
|
|
3474
|
+
continue;
|
|
3475
|
+
}
|
|
3476
|
+
const rel = relative2(root, abs).split(sep).join("/");
|
|
3477
|
+
paths.push(rel);
|
|
3478
|
+
}
|
|
3479
|
+
};
|
|
3480
|
+
walk(root);
|
|
3481
|
+
return paths.sort();
|
|
3482
|
+
}
|
|
3483
|
+
function diffManifestPaths(remote, local) {
|
|
3484
|
+
const remoteMap = new Map(
|
|
3485
|
+
(remote?.documents ?? []).map((doc) => [doc.path, doc.contentHash])
|
|
3486
|
+
);
|
|
3487
|
+
const localMap = new Map(
|
|
3488
|
+
(local?.documents ?? []).map((doc) => [doc.path, doc.contentHash])
|
|
3489
|
+
);
|
|
3490
|
+
const download = [];
|
|
3491
|
+
for (const [path, hash] of remoteMap) {
|
|
3492
|
+
if (localMap.get(path) !== hash) {
|
|
3493
|
+
download.push(path);
|
|
3494
|
+
}
|
|
3495
|
+
}
|
|
3496
|
+
const deleteLocal = [];
|
|
3497
|
+
for (const path of localMap.keys()) {
|
|
3498
|
+
if (!remoteMap.has(path)) {
|
|
3499
|
+
deleteLocal.push(path);
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
return { download, deleteLocal };
|
|
3503
|
+
}
|
|
3504
|
+
async function resolveProjectIdForSync(api, workdirPath, options) {
|
|
3505
|
+
const explicit = options?.projectId?.trim();
|
|
3506
|
+
if (explicit) {
|
|
3507
|
+
return { projectId: explicit, diagnostic: null };
|
|
3508
|
+
}
|
|
3509
|
+
try {
|
|
3510
|
+
const baseline = await api.cli.workspaceBaseline({ workdirPath });
|
|
3511
|
+
const projectId = baseline.projectId?.trim() || null;
|
|
3512
|
+
if (projectId) {
|
|
3513
|
+
return { projectId, diagnostic: null };
|
|
3514
|
+
}
|
|
3515
|
+
const projectIds = baseline.projectIds ?? [];
|
|
3516
|
+
if (projectIds.length === 0) {
|
|
3517
|
+
return {
|
|
3518
|
+
projectId: null,
|
|
3519
|
+
diagnostic: baseline.diagnostic?.message ?? `\u5DE5\u4F5C\u7A7A\u95F4\u672A\u5173\u8054\u9879\u76EE\uFF0C\u65E0\u6CD5\u540C\u6B65\u9879\u76EE\u6587\u6863\uFF08\u76EE\u5F55\uFF1A${workdirPath}\uFF09\u3002
|
|
3520
|
+
\u8BF7\u5728\u5E73\u53F0\u5C06\u5DE5\u4F5C\u7A7A\u95F4\u5173\u8054\u5230\u552F\u4E00\u9879\u76EE\u3002`
|
|
3521
|
+
};
|
|
3522
|
+
}
|
|
3523
|
+
return {
|
|
3524
|
+
projectId: null,
|
|
3525
|
+
diagnostic: `\u5DE5\u4F5C\u7A7A\u95F4\u5173\u8054\u4E86 ${projectIds.length} \u4E2A\u9879\u76EE\uFF0C\u65E0\u6CD5\u786E\u5B9A\u540C\u6B65\u76EE\u6807\u3002
|
|
3526
|
+
\u8BF7\u786E\u4FDD\u8BE5\u5DE5\u4F5C\u7A7A\u95F4\u53EA\u5173\u8054\u4E00\u4E2A\u9879\u76EE\u540E\u518D\u540C\u6B65\u9879\u76EE\u6587\u6863\u3002`
|
|
3527
|
+
};
|
|
3528
|
+
} catch (err) {
|
|
3529
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
3530
|
+
return {
|
|
3531
|
+
projectId: null,
|
|
3532
|
+
diagnostic: detail.replace(/^\[apm\]\s*/, "")
|
|
3533
|
+
};
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3536
|
+
async function syncProjectDocumentsPull(workdirPath, apmDir, options) {
|
|
3537
|
+
const empty = {
|
|
3538
|
+
synced: false,
|
|
3539
|
+
projectId: null,
|
|
3540
|
+
downloaded: 0,
|
|
3541
|
+
deleted: 0
|
|
3542
|
+
};
|
|
3543
|
+
const cfg = await tryReadApmConfig();
|
|
3544
|
+
if (!cfg || !resolveApiKey(cfg)) {
|
|
3545
|
+
console.log(
|
|
3546
|
+
"[apm] \u672A\u68C0\u6D4B\u5230\u767B\u5F55\u4FE1\u606F\uFF0C\u8DF3\u8FC7\u9879\u76EE\u6587\u6863\u540C\u6B65\u3002\n[apm] \u8BF7\u5148\u6267\u884C apm login\u3002"
|
|
3547
|
+
);
|
|
3548
|
+
return empty;
|
|
3549
|
+
}
|
|
3550
|
+
const api = createApmApiClient(cfg);
|
|
3551
|
+
const { projectId, diagnostic } = await resolveProjectIdForSync(
|
|
3552
|
+
api,
|
|
3553
|
+
workdirPath,
|
|
3554
|
+
options
|
|
3555
|
+
);
|
|
3556
|
+
if (!projectId) {
|
|
3557
|
+
console.log(`[apm] \u672A\u80FD\u540C\u6B65\u9879\u76EE\u6587\u6863\u3002
|
|
3558
|
+
${diagnostic ?? ""}`);
|
|
3559
|
+
return empty;
|
|
3560
|
+
}
|
|
3561
|
+
const targetApmDir = apmDir ?? workspaceApmDir(workdirPath);
|
|
3562
|
+
const docsDir = projectDocumentsDir(targetApmDir, projectId);
|
|
3563
|
+
await ensureDirExists(docsDir);
|
|
3564
|
+
const { manifest: remoteManifest } = await api.cli.getProjectDocumentManifest(
|
|
3565
|
+
{ projectId }
|
|
3566
|
+
);
|
|
3567
|
+
if (!remoteManifest) {
|
|
3568
|
+
console.log(`[apm] \u9879\u76EE ${projectId} \u65E0\u9879\u76EE\u6587\u6863 manifest\uFF0C\u8DF3\u8FC7\u540C\u6B65\u3002`);
|
|
3569
|
+
return { ...empty, projectId };
|
|
3570
|
+
}
|
|
3571
|
+
const localManifest = readLocalManifest(targetApmDir, projectId);
|
|
3572
|
+
const { download, deleteLocal } = diffManifestPaths(
|
|
3573
|
+
remoteManifest,
|
|
3574
|
+
localManifest
|
|
3575
|
+
);
|
|
3576
|
+
let downloaded = 0;
|
|
3577
|
+
if (download.length > 0) {
|
|
3578
|
+
const { list } = await api.cli.listProjectDocuments({
|
|
3579
|
+
projectId,
|
|
3580
|
+
paths: download.join(",")
|
|
3581
|
+
});
|
|
3582
|
+
for (const doc of list) {
|
|
3583
|
+
const absPath = toFsPath(
|
|
3584
|
+
projectDocumentLocalPath(targetApmDir, projectId, doc.path)
|
|
3585
|
+
);
|
|
3586
|
+
await ensureDirExists(dirname6(absPath));
|
|
3587
|
+
writeFileSync8(absPath, doc.content, "utf8");
|
|
3588
|
+
downloaded += 1;
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
let deleted = 0;
|
|
3592
|
+
for (const path of deleteLocal) {
|
|
3593
|
+
const absPath = toFsPath(
|
|
3594
|
+
projectDocumentLocalPath(targetApmDir, projectId, path)
|
|
3595
|
+
);
|
|
3596
|
+
if (existsSync9(absPath)) {
|
|
3597
|
+
rmSync3(absPath, { force: true });
|
|
3598
|
+
deleted += 1;
|
|
3599
|
+
}
|
|
3600
|
+
}
|
|
3601
|
+
writeFileSync8(
|
|
3602
|
+
toFsPath(join9(docsDir, MANIFEST_FILE2)),
|
|
3603
|
+
`${JSON.stringify(remoteManifest, null, 2)}
|
|
3604
|
+
`,
|
|
3605
|
+
"utf8"
|
|
3606
|
+
);
|
|
3607
|
+
console.log(
|
|
3608
|
+
`[apm] \u5DF2\u540C\u6B65\u9879\u76EE\u6587\u6863: projectId=${projectId} \u4E0B\u8F7D ${downloaded}\uFF0C\u5220\u9664\u672C\u5730 ${deleted} \u2192 .apm/project/${projectId}/`
|
|
3609
|
+
);
|
|
3610
|
+
return {
|
|
3611
|
+
synced: true,
|
|
3612
|
+
projectId,
|
|
3613
|
+
downloaded,
|
|
3614
|
+
deleted
|
|
3615
|
+
};
|
|
3616
|
+
}
|
|
3617
|
+
async function syncProjectDocumentsPush(cfg, workdirPath, apmRoot, options) {
|
|
3618
|
+
const api = createApmApiClient(cfg);
|
|
3619
|
+
const { projectId } = await resolveProjectIdForSync(
|
|
3620
|
+
api,
|
|
3621
|
+
workdirPath,
|
|
3622
|
+
options
|
|
3623
|
+
);
|
|
3624
|
+
if (!projectId) {
|
|
3625
|
+
return 0;
|
|
3626
|
+
}
|
|
3627
|
+
const targetApmDir = apmRoot ?? workspaceApmDir(workdirPath);
|
|
3628
|
+
const localPaths = listLocalDocumentPaths(targetApmDir, projectId);
|
|
3629
|
+
if (localPaths.length === 0) {
|
|
3630
|
+
console.log("[apm] \u9879\u76EE\u6587\u6863\u65E0\u672C\u5730\u6587\u4EF6\uFF0C\u8DF3\u8FC7\u63A8\u9001");
|
|
3631
|
+
return 0;
|
|
3632
|
+
}
|
|
3633
|
+
const remoteManifest = (await api.cli.getProjectDocumentManifest({ projectId })).manifest ?? null;
|
|
3634
|
+
const remoteHashByPath = new Map(
|
|
3635
|
+
(remoteManifest?.documents ?? []).map((doc) => [doc.path, doc.contentHash])
|
|
3636
|
+
);
|
|
3637
|
+
const remoteDescriptionByPath = new Map(
|
|
3638
|
+
(remoteManifest?.documents ?? []).map((doc) => [doc.path, doc.description])
|
|
3639
|
+
);
|
|
3640
|
+
let synced = 0;
|
|
3641
|
+
for (const path of localPaths) {
|
|
3642
|
+
const absPath = toFsPath(
|
|
3643
|
+
projectDocumentLocalPath(targetApmDir, projectId, path)
|
|
3644
|
+
);
|
|
3645
|
+
const content = readFileSync8(absPath, "utf8");
|
|
3646
|
+
const contentHash = hashLocalFileContent(content);
|
|
3647
|
+
if (remoteHashByPath.get(path) === contentHash) {
|
|
3648
|
+
continue;
|
|
3649
|
+
}
|
|
3650
|
+
await api.cli.upsertProjectDocument({
|
|
3651
|
+
projectId,
|
|
3652
|
+
path,
|
|
3653
|
+
content,
|
|
3654
|
+
description: remoteDescriptionByPath.get(path) ?? void 0
|
|
3655
|
+
});
|
|
3656
|
+
synced += 1;
|
|
3657
|
+
console.log(`[apm] \u5DF2\u540C\u6B65\u9879\u76EE\u6587\u6863: ${path}`);
|
|
3658
|
+
}
|
|
3659
|
+
if (synced === 0) {
|
|
3660
|
+
console.log("[apm] \u9879\u76EE\u6587\u6863\u65E0\u53D8\u5316\uFF0C\u8DF3\u8FC7\u63A8\u9001");
|
|
3661
|
+
}
|
|
3662
|
+
return synced;
|
|
3663
|
+
}
|
|
3664
|
+
|
|
3800
3665
|
// src/commands/connect/cli-version-sync.ts
|
|
3801
|
-
import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as
|
|
3802
|
-
import { join as
|
|
3666
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
3667
|
+
import { join as join10 } from "path";
|
|
3803
3668
|
var CLI_VERSION_FILE = ".cli-version.json";
|
|
3804
3669
|
function manifestPath2(apmDir) {
|
|
3805
|
-
return
|
|
3670
|
+
return join10(apmDir, CLI_VERSION_FILE);
|
|
3806
3671
|
}
|
|
3807
3672
|
function loadManifest2(apmDir) {
|
|
3808
3673
|
const path = toFsPath(manifestPath2(apmDir));
|
|
@@ -3822,7 +3687,7 @@ function loadManifest2(apmDir) {
|
|
|
3822
3687
|
}
|
|
3823
3688
|
function saveManifest2(apmDir, cliVersion) {
|
|
3824
3689
|
const manifest = { version: 1, cliVersion };
|
|
3825
|
-
|
|
3690
|
+
writeFileSync9(
|
|
3826
3691
|
toFsPath(manifestPath2(apmDir)),
|
|
3827
3692
|
`${JSON.stringify(manifest, null, 2)}
|
|
3828
3693
|
`,
|