ai-project-manage-cli 6.0.37 → 6.0.39
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 +371 -192
- package/package.json +1 -1
- package/template/deploy/README.md +15 -0
- package/template/sessions/.gitkeep +0 -0
package/dist/index.js
CHANGED
|
@@ -84,13 +84,55 @@ import { join as join3 } from "path";
|
|
|
84
84
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
85
85
|
|
|
86
86
|
// src/command-utils.ts
|
|
87
|
-
import {
|
|
88
|
-
import { basename, dirname, extname, join as join2, resolve } from "path";
|
|
87
|
+
import { copyFileSync, existsSync, mkdirSync as mkdirSync2, readdirSync, statSync } from "fs";
|
|
88
|
+
import { basename, dirname, extname, join as join2, resolve as resolve2 } from "path";
|
|
89
89
|
import { fileURLToPath } from "url";
|
|
90
|
+
|
|
91
|
+
// src/workdir-path.ts
|
|
92
|
+
import { realpathSync } from "fs";
|
|
93
|
+
import { platform } from "os";
|
|
94
|
+
import { resolve } from "path";
|
|
95
|
+
function toFsPath(inputPath) {
|
|
96
|
+
const absolute = resolve(inputPath);
|
|
97
|
+
if (platform() !== "win32") return absolute;
|
|
98
|
+
if (absolute.startsWith("\\\\?\\")) return absolute;
|
|
99
|
+
const normalized = absolute.replace(/\//g, "\\");
|
|
100
|
+
if (normalized.startsWith("\\\\")) {
|
|
101
|
+
return `\\\\?\\UNC\\${normalized.slice(2)}`;
|
|
102
|
+
}
|
|
103
|
+
return `\\\\?\\${normalized}`;
|
|
104
|
+
}
|
|
105
|
+
function normalizeWorkdirPath(path10) {
|
|
106
|
+
let normalized = path10.trim().replace(/\\/g, "/").normalize("NFC");
|
|
107
|
+
if (normalized.startsWith("//?/")) {
|
|
108
|
+
normalized = normalized.slice(4);
|
|
109
|
+
}
|
|
110
|
+
const windowsDrive = /^([A-Za-z]:)\/*(.*)$/.exec(normalized);
|
|
111
|
+
if (windowsDrive) {
|
|
112
|
+
const drive = windowsDrive[1].toLowerCase();
|
|
113
|
+
const rest = windowsDrive[2].replace(/\/+/g, "/").replace(/\/$/, "");
|
|
114
|
+
return rest ? `${drive}/${rest}` : drive;
|
|
115
|
+
}
|
|
116
|
+
normalized = normalized.replace(/\/+/g, "/");
|
|
117
|
+
if (normalized.length > 1 && normalized.endsWith("/")) {
|
|
118
|
+
normalized = normalized.slice(0, -1);
|
|
119
|
+
}
|
|
120
|
+
return normalized;
|
|
121
|
+
}
|
|
122
|
+
function resolveWorkdirPath(cwd = process.cwd()) {
|
|
123
|
+
const absolute = resolve(cwd);
|
|
124
|
+
try {
|
|
125
|
+
return normalizeWorkdirPath(realpathSync.native(absolute));
|
|
126
|
+
} catch {
|
|
127
|
+
return normalizeWorkdirPath(absolute);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/command-utils.ts
|
|
90
132
|
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
91
|
-
var CLI_TEMPLATE_DIR =
|
|
92
|
-
function workspaceApmDir(cwd =
|
|
93
|
-
return
|
|
133
|
+
var CLI_TEMPLATE_DIR = resolve2(__dirname, "../template");
|
|
134
|
+
function workspaceApmDir(cwd = resolveWorkdirPath()) {
|
|
135
|
+
return resolve2(resolve2(cwd), ".apm");
|
|
94
136
|
}
|
|
95
137
|
var SESSIONS_SUBDIR = "sessions";
|
|
96
138
|
var SESSION_DOCS_SUBDIR = "docs";
|
|
@@ -147,78 +189,106 @@ async function ensureLoggedConfig() {
|
|
|
147
189
|
async function ensureDirExists(dir) {
|
|
148
190
|
mkdirSync2(dir, { recursive: true });
|
|
149
191
|
}
|
|
150
|
-
async function ensureWorkspaceApmDirForInit() {
|
|
151
|
-
const dir = workspaceApmDir();
|
|
152
|
-
|
|
153
|
-
|
|
192
|
+
async function ensureWorkspaceApmDirForInit(cwd = resolveWorkdirPath()) {
|
|
193
|
+
const dir = workspaceApmDir(cwd);
|
|
194
|
+
const fsDir = toFsPath(dir);
|
|
195
|
+
if (!existsSync(fsDir)) {
|
|
196
|
+
mkdirSync2(fsDir, { recursive: true });
|
|
154
197
|
return;
|
|
155
198
|
}
|
|
156
|
-
const st = statSync(
|
|
199
|
+
const st = statSync(fsDir);
|
|
157
200
|
if (!st.isDirectory()) {
|
|
158
201
|
throw new Error(`[apm] \u8DEF\u5F84\u5DF2\u5B58\u5728\u4F46\u4E0D\u662F\u76EE\u5F55: ${dir}`);
|
|
159
202
|
}
|
|
160
|
-
if (readdirSync(
|
|
203
|
+
if (readdirSync(fsDir).length > 0) {
|
|
161
204
|
throw new Error(
|
|
162
205
|
"[apm] .apm \u76EE\u5F55\u5DF2\u5B58\u5728\u4E14\u975E\u7A7A\uFF0C\u8BF7\u5148\u5907\u4EFD\u3001\u6E05\u7A7A\u6216\u5220\u9664\u540E\u518D\u6267\u884C init"
|
|
163
206
|
);
|
|
164
207
|
}
|
|
165
208
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
209
|
+
var WORKSPACE_TEMPLATE_SUBDIRS = [
|
|
210
|
+
"sessions",
|
|
211
|
+
"skills",
|
|
212
|
+
"rules",
|
|
213
|
+
"deploy"
|
|
214
|
+
];
|
|
215
|
+
function shouldSkipTemplateEntry(name) {
|
|
216
|
+
return name === ".DS_Store" || name === "Thumbs.db";
|
|
217
|
+
}
|
|
218
|
+
function copyTemplateEntry(src, dest) {
|
|
219
|
+
const fsSrc = toFsPath(src);
|
|
220
|
+
const fsDest = toFsPath(dest);
|
|
221
|
+
const st = statSync(fsSrc);
|
|
222
|
+
if (st.isDirectory()) {
|
|
223
|
+
mkdirSync2(fsDest, { recursive: true });
|
|
224
|
+
for (const name of readdirSync(fsSrc)) {
|
|
225
|
+
if (shouldSkipTemplateEntry(name)) continue;
|
|
226
|
+
copyTemplateEntry(join2(src, name), join2(dest, name));
|
|
227
|
+
}
|
|
228
|
+
return;
|
|
173
229
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
230
|
+
if (!st.isFile()) return;
|
|
231
|
+
mkdirSync2(toFsPath(dirname(dest)), { recursive: true });
|
|
232
|
+
copyFileSync(fsSrc, fsDest);
|
|
233
|
+
}
|
|
234
|
+
function assertTemplateCopiedToApm(apmDir, workdir) {
|
|
235
|
+
const required = [
|
|
236
|
+
"AGENTS.md",
|
|
237
|
+
"apm.config.json",
|
|
238
|
+
"rules",
|
|
239
|
+
"skills",
|
|
240
|
+
"sessions"
|
|
241
|
+
];
|
|
242
|
+
for (const item of required) {
|
|
243
|
+
const path10 = join2(apmDir, item);
|
|
244
|
+
if (!existsSync(toFsPath(path10))) {
|
|
245
|
+
throw new Error(`[apm] \u521D\u59CB\u5316\u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5C11: ${path10}`);
|
|
246
|
+
}
|
|
177
247
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
248
|
+
const leakedRules = join2(workdir, "rules");
|
|
249
|
+
const apmRules = join2(apmDir, "rules");
|
|
250
|
+
if (existsSync(toFsPath(leakedRules)) && !existsSync(toFsPath(join2(apmRules, "reply.md")))) {
|
|
251
|
+
throw new Error(
|
|
252
|
+
`[apm] \u6A21\u677F\u88AB\u590D\u5236\u5230\u9519\u8BEF\u4F4D\u7F6E: ${leakedRules}\uFF08\u5E94\u5728 ${apmRules}\uFF09`
|
|
253
|
+
);
|
|
182
254
|
}
|
|
183
255
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if (normalized.startsWith("//?/")) {
|
|
191
|
-
normalized = normalized.slice(4);
|
|
256
|
+
async function copyTemplateFiles(targetDir, workdir = resolveWorkdirPath()) {
|
|
257
|
+
const resolvedTarget = resolve2(targetDir);
|
|
258
|
+
const templateDir = resolve2(CLI_TEMPLATE_DIR);
|
|
259
|
+
const fsTemplateDir = toFsPath(templateDir);
|
|
260
|
+
if (!existsSync(fsTemplateDir)) {
|
|
261
|
+
throw new Error(`[apm] \u672A\u627E\u5230 CLI \u6A21\u677F\u76EE\u5F55: ${templateDir}`);
|
|
192
262
|
}
|
|
193
|
-
const
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
const rest = windowsDrive[2].replace(/\/+/g, "/").replace(/\/$/, "");
|
|
197
|
-
return rest ? `${drive}/${rest}` : drive;
|
|
263
|
+
const dirStat = statSync(fsTemplateDir);
|
|
264
|
+
if (!dirStat.isDirectory()) {
|
|
265
|
+
throw new Error(`[apm] CLI \u6A21\u677F\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${templateDir}`);
|
|
198
266
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
267
|
+
const entries = readdirSync(fsTemplateDir).filter(
|
|
268
|
+
(name) => !shouldSkipTemplateEntry(name)
|
|
269
|
+
);
|
|
270
|
+
if (entries.length === 0) {
|
|
271
|
+
throw new Error(`[apm] CLI \u6A21\u677F\u76EE\u5F55\u4E3A\u7A7A: ${templateDir}`);
|
|
202
272
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
} catch {
|
|
210
|
-
return normalizeWorkdirPath(absolute);
|
|
273
|
+
mkdirSync2(toFsPath(resolvedTarget), { recursive: true });
|
|
274
|
+
for (const name of entries) {
|
|
275
|
+
copyTemplateEntry(join2(templateDir, name), join2(resolvedTarget, name));
|
|
276
|
+
}
|
|
277
|
+
for (const subdir of WORKSPACE_TEMPLATE_SUBDIRS) {
|
|
278
|
+
mkdirSync2(toFsPath(join2(resolvedTarget, subdir)), { recursive: true });
|
|
211
279
|
}
|
|
280
|
+
assertTemplateCopiedToApm(resolvedTarget, resolve2(workdir));
|
|
212
281
|
}
|
|
213
282
|
|
|
214
283
|
// src/commands/init.ts
|
|
215
284
|
async function runInit(name) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
285
|
+
const workdir = resolveWorkdirPath();
|
|
286
|
+
await ensureWorkspaceApmDirForInit(workdir);
|
|
287
|
+
const apmDir = workspaceApmDir(workdir);
|
|
288
|
+
await copyTemplateFiles(apmDir, workdir);
|
|
219
289
|
const trimmedName = name?.trim();
|
|
220
290
|
if (trimmedName) {
|
|
221
|
-
const apmConfigPath = join3(apmDir, "apm.config.json");
|
|
291
|
+
const apmConfigPath = toFsPath(join3(apmDir, "apm.config.json"));
|
|
222
292
|
const config = readFileSync2(apmConfigPath, "utf8");
|
|
223
293
|
const configJson = JSON.parse(config);
|
|
224
294
|
configJson.name = trimmedName;
|
|
@@ -229,7 +299,6 @@ async function runInit(name) {
|
|
|
229
299
|
"utf8"
|
|
230
300
|
);
|
|
231
301
|
}
|
|
232
|
-
const workdir = resolveWorkdirPath();
|
|
233
302
|
console.log(`[apm] \u5DF2\u521D\u59CB\u5316\u5DE5\u4F5C\u533A\uFF1A${apmDir}`);
|
|
234
303
|
console.log(`[apm] \u5DE5\u4F5C\u76EE\u5F55\u8DEF\u5F84\uFF1A${workdir}`);
|
|
235
304
|
console.log("[apm] \u8BF7\u5728\u5E73\u53F0\u300C\u5BA2\u6237\u673A\u7BA1\u7406 \u2192 \u5DE5\u4F5C\u7A7A\u95F4\u300D\u767B\u8BB0\u4E0A\u8FF0\u76EE\u5F55\u8DEF\u5F84");
|
|
@@ -245,10 +314,12 @@ import { createApiClient } from "listpage-http";
|
|
|
245
314
|
import { defineEndpoint } from "listpage-http";
|
|
246
315
|
var requestConfig = {
|
|
247
316
|
cli: {
|
|
248
|
-
me: defineEndpoint(
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
317
|
+
me: defineEndpoint(
|
|
318
|
+
{
|
|
319
|
+
method: "GET",
|
|
320
|
+
path: "/cli/me"
|
|
321
|
+
}
|
|
322
|
+
),
|
|
252
323
|
sessionDetail: defineEndpoint({
|
|
253
324
|
method: "GET",
|
|
254
325
|
path: "/cli/sessions/detail"
|
|
@@ -298,6 +369,10 @@ var requestConfig = {
|
|
|
298
369
|
listSkills: defineEndpoint({
|
|
299
370
|
method: "GET",
|
|
300
371
|
path: "/cli/skills"
|
|
372
|
+
}),
|
|
373
|
+
listRules: defineEndpoint({
|
|
374
|
+
method: "GET",
|
|
375
|
+
path: "/cli/rules"
|
|
301
376
|
})
|
|
302
377
|
}
|
|
303
378
|
};
|
|
@@ -535,8 +610,8 @@ async function runBranch(sessionId, options = {}) {
|
|
|
535
610
|
}
|
|
536
611
|
|
|
537
612
|
// src/commands/pull.ts
|
|
538
|
-
import { writeFileSync as
|
|
539
|
-
import { join as
|
|
613
|
+
import { writeFileSync as writeFileSync6 } from "fs";
|
|
614
|
+
import { dirname as dirname2, join as join7 } from "path";
|
|
540
615
|
import { stringify as yamlStringify } from "yaml";
|
|
541
616
|
|
|
542
617
|
// src/session-messages-xml.ts
|
|
@@ -644,7 +719,201 @@ async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
|
|
|
644
719
|
saveManifest(dir, nextManifest);
|
|
645
720
|
}
|
|
646
721
|
|
|
722
|
+
// src/rules-sync.ts
|
|
723
|
+
import { basename as basename2, extname as extname2, join as join6 } from "path";
|
|
724
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
725
|
+
|
|
726
|
+
// src/skills-sync.ts
|
|
727
|
+
import {
|
|
728
|
+
copyFileSync as copyFileSync2,
|
|
729
|
+
cpSync,
|
|
730
|
+
existsSync as existsSync3,
|
|
731
|
+
mkdirSync as mkdirSync3,
|
|
732
|
+
readdirSync as readdirSync2,
|
|
733
|
+
rmSync,
|
|
734
|
+
statSync as statSync2,
|
|
735
|
+
writeFileSync as writeFileSync4
|
|
736
|
+
} from "fs";
|
|
737
|
+
import { join as join5 } from "path";
|
|
738
|
+
var AGENTS_TEMPLATE_PATH = join5(CLI_TEMPLATE_DIR, "AGENTS.md");
|
|
739
|
+
var BASE_SKILLS_TEMPLATE_DIR = join5(CLI_TEMPLATE_DIR, "skills");
|
|
740
|
+
var BASE_RULES_TEMPLATE_DIR = join5(CLI_TEMPLATE_DIR, "rules");
|
|
741
|
+
function sanitizeSkillDirName(name) {
|
|
742
|
+
const trimmed = name.trim();
|
|
743
|
+
if (!trimmed) return "skill";
|
|
744
|
+
return trimmed.replace(/[/\\:*?"<>|]/g, "_");
|
|
745
|
+
}
|
|
746
|
+
function listBaseSkillDirNames() {
|
|
747
|
+
if (!existsSync3(BASE_SKILLS_TEMPLATE_DIR)) return [];
|
|
748
|
+
return readdirSync2(BASE_SKILLS_TEMPLATE_DIR).filter((name) => {
|
|
749
|
+
const path10 = join5(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
750
|
+
return statSync2(path10).isDirectory();
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
function syncAgentsGuide(apmDir) {
|
|
754
|
+
if (!existsSync3(AGENTS_TEMPLATE_PATH)) return false;
|
|
755
|
+
mkdirSync3(apmDir, { recursive: true });
|
|
756
|
+
copyFileSync2(AGENTS_TEMPLATE_PATH, join5(apmDir, "AGENTS.md"));
|
|
757
|
+
return true;
|
|
758
|
+
}
|
|
759
|
+
function listBaseRuleFileNames() {
|
|
760
|
+
if (!existsSync3(BASE_RULES_TEMPLATE_DIR)) return [];
|
|
761
|
+
return readdirSync2(BASE_RULES_TEMPLATE_DIR).filter((name) => {
|
|
762
|
+
const path10 = join5(BASE_RULES_TEMPLATE_DIR, name);
|
|
763
|
+
return statSync2(path10).isFile();
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
function syncBaseRules(rulesDir) {
|
|
767
|
+
mkdirSync3(rulesDir, { recursive: true });
|
|
768
|
+
const names = listBaseRuleFileNames();
|
|
769
|
+
for (const name of names) {
|
|
770
|
+
const src = join5(BASE_RULES_TEMPLATE_DIR, name);
|
|
771
|
+
const dest = join5(rulesDir, name);
|
|
772
|
+
copyFileSync2(src, dest);
|
|
773
|
+
}
|
|
774
|
+
return names;
|
|
775
|
+
}
|
|
776
|
+
function syncBaseSkills(skillsDir) {
|
|
777
|
+
mkdirSync3(skillsDir, { recursive: true });
|
|
778
|
+
const names = listBaseSkillDirNames();
|
|
779
|
+
for (const name of names) {
|
|
780
|
+
const src = join5(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
781
|
+
const dest = join5(skillsDir, name);
|
|
782
|
+
cpSync(src, dest, { recursive: true, force: true });
|
|
783
|
+
}
|
|
784
|
+
return names;
|
|
785
|
+
}
|
|
786
|
+
function syncSupplementarySkills(skillsDir, list) {
|
|
787
|
+
const baseNames = new Set(listBaseSkillDirNames());
|
|
788
|
+
const apiDirNames = /* @__PURE__ */ new Set();
|
|
789
|
+
const written = [];
|
|
790
|
+
const skipped = [];
|
|
791
|
+
for (const skill of list) {
|
|
792
|
+
const dirName = sanitizeSkillDirName(skill.name);
|
|
793
|
+
apiDirNames.add(dirName);
|
|
794
|
+
if (baseNames.has(dirName)) {
|
|
795
|
+
skipped.push(dirName);
|
|
796
|
+
continue;
|
|
797
|
+
}
|
|
798
|
+
const skillDir = join5(skillsDir, dirName);
|
|
799
|
+
mkdirSync3(skillDir, { recursive: true });
|
|
800
|
+
writeFileSync4(join5(skillDir, "SKILL.md"), skill.content ?? "", "utf8");
|
|
801
|
+
written.push(dirName);
|
|
802
|
+
}
|
|
803
|
+
const removed = [];
|
|
804
|
+
if (!existsSync3(skillsDir)) return { written, skipped, removed };
|
|
805
|
+
for (const entry of readdirSync2(skillsDir)) {
|
|
806
|
+
const full = join5(skillsDir, entry);
|
|
807
|
+
if (!statSync2(full).isDirectory()) continue;
|
|
808
|
+
if (baseNames.has(entry)) continue;
|
|
809
|
+
if (apiDirNames.has(entry)) continue;
|
|
810
|
+
rmSync(full, { recursive: true, force: true });
|
|
811
|
+
removed.push(entry);
|
|
812
|
+
}
|
|
813
|
+
return { written, skipped, removed };
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// src/rules-sync.ts
|
|
817
|
+
var MANIFEST_FILE2 = ".rules-sync-manifest.json";
|
|
818
|
+
function ruleLocalFileName(ruleName) {
|
|
819
|
+
const trimmed = ruleName.trim();
|
|
820
|
+
if (!trimmed) return "rule.md";
|
|
821
|
+
const sanitized = trimmed.replace(/[/\\:*?"<>|]/g, "_");
|
|
822
|
+
if (extname2(sanitized).toLowerCase() === ".md") return sanitized;
|
|
823
|
+
return `${sanitized}.md`;
|
|
824
|
+
}
|
|
825
|
+
function loadManifest2(rulesDir) {
|
|
826
|
+
const path10 = join6(rulesDir, MANIFEST_FILE2);
|
|
827
|
+
if (!existsSync4(toFsPath(path10))) {
|
|
828
|
+
return { version: 1, rules: {} };
|
|
829
|
+
}
|
|
830
|
+
try {
|
|
831
|
+
const parsed = JSON.parse(
|
|
832
|
+
readFileSync4(toFsPath(path10), "utf8")
|
|
833
|
+
);
|
|
834
|
+
if (parsed?.version === 1 && parsed.rules && typeof parsed.rules === "object") {
|
|
835
|
+
return parsed;
|
|
836
|
+
}
|
|
837
|
+
} catch {
|
|
838
|
+
}
|
|
839
|
+
return { version: 1, rules: {} };
|
|
840
|
+
}
|
|
841
|
+
function saveManifest2(rulesDir, manifest) {
|
|
842
|
+
writeFileSync5(
|
|
843
|
+
toFsPath(join6(rulesDir, MANIFEST_FILE2)),
|
|
844
|
+
`${JSON.stringify(manifest, null, 2)}
|
|
845
|
+
`,
|
|
846
|
+
"utf8"
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
function isBaseRuleFileName(fileName) {
|
|
850
|
+
return listBaseRuleFileNames().includes(basename2(fileName));
|
|
851
|
+
}
|
|
852
|
+
function isRuleUpToDate(entry, rule, dest) {
|
|
853
|
+
if (!entry || !existsSync4(toFsPath(dest))) return false;
|
|
854
|
+
if (entry.fileName !== ruleLocalFileName(rule.name)) return false;
|
|
855
|
+
const updatedAt = rule.updatedAt ?? "";
|
|
856
|
+
if (entry.updatedAt !== updatedAt) return false;
|
|
857
|
+
const localContent = readFileSync4(toFsPath(dest), "utf8");
|
|
858
|
+
return localContent === (rule.content ?? "");
|
|
859
|
+
}
|
|
860
|
+
async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
|
|
861
|
+
const api = createApmApiClient(cfg);
|
|
862
|
+
const baseline = await api.cli.branchBaseline({ sessionId, workdirPath });
|
|
863
|
+
const repositoryId = baseline.repositoryId;
|
|
864
|
+
const rulesDir = join6(apmRoot ?? workspaceApmDir(workdirPath), "rules");
|
|
865
|
+
await ensureDirExists(rulesDir);
|
|
866
|
+
if (!repositoryId) {
|
|
867
|
+
console.log(
|
|
868
|
+
`[apm] \u672A\u5339\u914D\u5230\u7ED1\u5B9A\u4ED3\u5E93\u7684\u5DE5\u4F5C\u7A7A\u95F4\uFF0C\u8DF3\u8FC7\u5E73\u53F0\u89C4\u5219\u540C\u6B65\uFF08\u8DEF\u5F84\uFF1A${workdirPath}\uFF09`
|
|
869
|
+
);
|
|
870
|
+
return { written: [], skipped: [], removed: [], repositoryId: null };
|
|
871
|
+
}
|
|
872
|
+
const { list } = await api.cli.listRules({ repositoryId });
|
|
873
|
+
const manifest = loadManifest2(rulesDir);
|
|
874
|
+
const nextManifest = { version: 1, rules: {} };
|
|
875
|
+
const remoteIds = /* @__PURE__ */ new Set();
|
|
876
|
+
const written = [];
|
|
877
|
+
const skipped = [];
|
|
878
|
+
for (const rule of list) {
|
|
879
|
+
remoteIds.add(rule.id);
|
|
880
|
+
const fileName = ruleLocalFileName(rule.name);
|
|
881
|
+
const dest = join6(rulesDir, fileName);
|
|
882
|
+
const entry = manifest.rules[rule.id];
|
|
883
|
+
const updatedAt = rule.updatedAt ?? "";
|
|
884
|
+
if (isRuleUpToDate(entry, rule, dest)) {
|
|
885
|
+
nextManifest.rules[rule.id] = entry;
|
|
886
|
+
skipped.push(fileName);
|
|
887
|
+
console.log(`[apm] \u89C4\u5219\u65E0\u53D8\u5316\uFF0C\u5DF2\u8DF3\u8FC7: rules/${fileName}`);
|
|
888
|
+
continue;
|
|
889
|
+
}
|
|
890
|
+
writeFileSync5(toFsPath(dest), rule.content ?? "", "utf8");
|
|
891
|
+
nextManifest.rules[rule.id] = { fileName, updatedAt };
|
|
892
|
+
written.push(fileName);
|
|
893
|
+
console.log(`[apm] \u5DF2\u540C\u6B65\u5E73\u53F0\u89C4\u5219: rules/${fileName}`);
|
|
894
|
+
}
|
|
895
|
+
const removed = [];
|
|
896
|
+
for (const [ruleId, entry] of Object.entries(manifest.rules)) {
|
|
897
|
+
if (remoteIds.has(ruleId)) continue;
|
|
898
|
+
if (isBaseRuleFileName(entry.fileName)) continue;
|
|
899
|
+
const dest = join6(rulesDir, entry.fileName);
|
|
900
|
+
if (existsSync4(toFsPath(dest))) {
|
|
901
|
+
rmSync2(toFsPath(dest), { force: true });
|
|
902
|
+
}
|
|
903
|
+
removed.push(entry.fileName);
|
|
904
|
+
console.log(`[apm] \u5DF2\u79FB\u9664\u5DF2\u4E0B\u7EBF\u7684\u5E73\u53F0\u89C4\u5219: rules/${entry.fileName}`);
|
|
905
|
+
}
|
|
906
|
+
saveManifest2(rulesDir, nextManifest);
|
|
907
|
+
return { written, skipped, removed, repositoryId };
|
|
908
|
+
}
|
|
909
|
+
|
|
647
910
|
// src/commands/pull.ts
|
|
911
|
+
function resolvePullWorkdir(apmRoot) {
|
|
912
|
+
if (apmRoot) {
|
|
913
|
+
return resolveWorkdirPath(dirname2(apmRoot));
|
|
914
|
+
}
|
|
915
|
+
return resolveWorkdirPath();
|
|
916
|
+
}
|
|
648
917
|
async function runPull(sessionId, apmRoot) {
|
|
649
918
|
const trimmedId = sessionId.trim();
|
|
650
919
|
if (!trimmedId) {
|
|
@@ -665,20 +934,20 @@ async function runPull(sessionId, apmRoot) {
|
|
|
665
934
|
const dir = sessionDir(trimmedId, apmRoot);
|
|
666
935
|
const docsDir = sessionDocsDir(trimmedId, apmRoot);
|
|
667
936
|
await ensureDirExists(docsDir);
|
|
668
|
-
|
|
937
|
+
writeFileSync6(
|
|
669
938
|
sessionRulePath(trimmedId, apmRoot),
|
|
670
939
|
detail.description ?? "",
|
|
671
940
|
"utf8"
|
|
672
941
|
);
|
|
673
|
-
|
|
942
|
+
writeFileSync6(
|
|
674
943
|
sessionTaskPath(trimmedId, apmRoot),
|
|
675
944
|
detail.task.description ?? "",
|
|
676
945
|
"utf8"
|
|
677
946
|
);
|
|
678
|
-
|
|
947
|
+
writeFileSync6(sessionTodoPath(trimmedId, apmRoot), detail.todo ?? "", "utf8");
|
|
679
948
|
for (const doc of documents) {
|
|
680
949
|
const fileName = documentLocalFileName(doc.name);
|
|
681
|
-
|
|
950
|
+
writeFileSync6(join7(docsDir, fileName), doc.content ?? "", "utf8");
|
|
682
951
|
}
|
|
683
952
|
const sessionYaml = yamlStringify(
|
|
684
953
|
{
|
|
@@ -695,18 +964,20 @@ async function runPull(sessionId, apmRoot) {
|
|
|
695
964
|
},
|
|
696
965
|
{ lineWidth: 0 }
|
|
697
966
|
);
|
|
698
|
-
|
|
967
|
+
writeFileSync6(
|
|
699
968
|
sessionYamlPath(trimmedId, apmRoot),
|
|
700
969
|
sessionYaml.endsWith("\n") ? sessionYaml : `${sessionYaml}
|
|
701
970
|
`,
|
|
702
971
|
"utf8"
|
|
703
972
|
);
|
|
704
|
-
|
|
973
|
+
writeFileSync6(
|
|
705
974
|
sessionMessagesXmlPath(trimmedId, apmRoot),
|
|
706
975
|
formatSessionMessagesXml(trimmedId, messages),
|
|
707
976
|
"utf8"
|
|
708
977
|
);
|
|
709
978
|
await syncSessionAttachments(cfg, trimmedId, attachments, apmRoot);
|
|
979
|
+
const workdirPath = resolvePullWorkdir(apmRoot);
|
|
980
|
+
await syncPlatformRules(cfg, trimmedId, workdirPath, apmRoot);
|
|
710
981
|
console.log(`[apm] \u5DF2\u540C\u6B65\u4F1A\u8BDD\u5DE5\u4F5C\u533A: ${dir}`);
|
|
711
982
|
return dir;
|
|
712
983
|
}
|
|
@@ -715,15 +986,15 @@ async function runPull(sessionId, apmRoot) {
|
|
|
715
986
|
import { spawnSync } from "child_process";
|
|
716
987
|
|
|
717
988
|
// src/version.ts
|
|
718
|
-
import { readFileSync as
|
|
719
|
-
import { dirname as
|
|
989
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
990
|
+
import { dirname as dirname3, join as join8 } from "path";
|
|
720
991
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
721
992
|
var CLI_PACKAGE_NAME = "ai-project-manage-cli";
|
|
722
993
|
function readCliVersion() {
|
|
723
994
|
try {
|
|
724
|
-
const dir =
|
|
725
|
-
const pkgPath =
|
|
726
|
-
const pkg = JSON.parse(
|
|
995
|
+
const dir = dirname3(fileURLToPath2(import.meta.url));
|
|
996
|
+
const pkgPath = join8(dir, "..", "package.json");
|
|
997
|
+
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
|
|
727
998
|
return pkg.version ?? "0.0.0";
|
|
728
999
|
} catch {
|
|
729
1000
|
return "0.0.0";
|
|
@@ -790,103 +1061,11 @@ async function runUpdate() {
|
|
|
790
1061
|
}
|
|
791
1062
|
|
|
792
1063
|
// src/commands/update-skills.ts
|
|
793
|
-
import { existsSync as
|
|
794
|
-
import { join as
|
|
795
|
-
|
|
796
|
-
// src/skills-sync.ts
|
|
797
|
-
import {
|
|
798
|
-
copyFileSync,
|
|
799
|
-
cpSync as cpSync2,
|
|
800
|
-
existsSync as existsSync3,
|
|
801
|
-
mkdirSync as mkdirSync3,
|
|
802
|
-
readdirSync as readdirSync2,
|
|
803
|
-
rmSync,
|
|
804
|
-
statSync as statSync2,
|
|
805
|
-
writeFileSync as writeFileSync5
|
|
806
|
-
} from "fs";
|
|
807
|
-
import { join as join7 } from "path";
|
|
808
|
-
var AGENTS_TEMPLATE_PATH = join7(CLI_TEMPLATE_DIR, "AGENTS.md");
|
|
809
|
-
var BASE_SKILLS_TEMPLATE_DIR = join7(CLI_TEMPLATE_DIR, "skills");
|
|
810
|
-
var BASE_RULES_TEMPLATE_DIR = join7(CLI_TEMPLATE_DIR, "rules");
|
|
811
|
-
function sanitizeSkillDirName(name) {
|
|
812
|
-
const trimmed = name.trim();
|
|
813
|
-
if (!trimmed) return "skill";
|
|
814
|
-
return trimmed.replace(/[/\\:*?"<>|]/g, "_");
|
|
815
|
-
}
|
|
816
|
-
function listBaseSkillDirNames() {
|
|
817
|
-
if (!existsSync3(BASE_SKILLS_TEMPLATE_DIR)) return [];
|
|
818
|
-
return readdirSync2(BASE_SKILLS_TEMPLATE_DIR).filter((name) => {
|
|
819
|
-
const path10 = join7(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
820
|
-
return statSync2(path10).isDirectory();
|
|
821
|
-
});
|
|
822
|
-
}
|
|
823
|
-
function syncAgentsGuide(apmDir) {
|
|
824
|
-
if (!existsSync3(AGENTS_TEMPLATE_PATH)) return false;
|
|
825
|
-
mkdirSync3(apmDir, { recursive: true });
|
|
826
|
-
copyFileSync(AGENTS_TEMPLATE_PATH, join7(apmDir, "AGENTS.md"));
|
|
827
|
-
return true;
|
|
828
|
-
}
|
|
829
|
-
function listBaseRuleFileNames() {
|
|
830
|
-
if (!existsSync3(BASE_RULES_TEMPLATE_DIR)) return [];
|
|
831
|
-
return readdirSync2(BASE_RULES_TEMPLATE_DIR).filter((name) => {
|
|
832
|
-
const path10 = join7(BASE_RULES_TEMPLATE_DIR, name);
|
|
833
|
-
return statSync2(path10).isFile();
|
|
834
|
-
});
|
|
835
|
-
}
|
|
836
|
-
function syncBaseRules(rulesDir) {
|
|
837
|
-
mkdirSync3(rulesDir, { recursive: true });
|
|
838
|
-
const names = listBaseRuleFileNames();
|
|
839
|
-
for (const name of names) {
|
|
840
|
-
const src = join7(BASE_RULES_TEMPLATE_DIR, name);
|
|
841
|
-
const dest = join7(rulesDir, name);
|
|
842
|
-
copyFileSync(src, dest);
|
|
843
|
-
}
|
|
844
|
-
return names;
|
|
845
|
-
}
|
|
846
|
-
function syncBaseSkills(skillsDir) {
|
|
847
|
-
mkdirSync3(skillsDir, { recursive: true });
|
|
848
|
-
const names = listBaseSkillDirNames();
|
|
849
|
-
for (const name of names) {
|
|
850
|
-
const src = join7(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
851
|
-
const dest = join7(skillsDir, name);
|
|
852
|
-
cpSync2(src, dest, { recursive: true, force: true });
|
|
853
|
-
}
|
|
854
|
-
return names;
|
|
855
|
-
}
|
|
856
|
-
function syncSupplementarySkills(skillsDir, list) {
|
|
857
|
-
const baseNames = new Set(listBaseSkillDirNames());
|
|
858
|
-
const apiDirNames = /* @__PURE__ */ new Set();
|
|
859
|
-
const written = [];
|
|
860
|
-
const skipped = [];
|
|
861
|
-
for (const skill of list) {
|
|
862
|
-
const dirName = sanitizeSkillDirName(skill.name);
|
|
863
|
-
apiDirNames.add(dirName);
|
|
864
|
-
if (baseNames.has(dirName)) {
|
|
865
|
-
skipped.push(dirName);
|
|
866
|
-
continue;
|
|
867
|
-
}
|
|
868
|
-
const skillDir = join7(skillsDir, dirName);
|
|
869
|
-
mkdirSync3(skillDir, { recursive: true });
|
|
870
|
-
writeFileSync5(join7(skillDir, "SKILL.md"), skill.content ?? "", "utf8");
|
|
871
|
-
written.push(dirName);
|
|
872
|
-
}
|
|
873
|
-
const removed = [];
|
|
874
|
-
if (!existsSync3(skillsDir)) return { written, skipped, removed };
|
|
875
|
-
for (const entry of readdirSync2(skillsDir)) {
|
|
876
|
-
const full = join7(skillsDir, entry);
|
|
877
|
-
if (!statSync2(full).isDirectory()) continue;
|
|
878
|
-
if (baseNames.has(entry)) continue;
|
|
879
|
-
if (apiDirNames.has(entry)) continue;
|
|
880
|
-
rmSync(full, { recursive: true, force: true });
|
|
881
|
-
removed.push(entry);
|
|
882
|
-
}
|
|
883
|
-
return { written, skipped, removed };
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
// src/commands/update-skills.ts
|
|
1064
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, statSync as statSync3 } from "fs";
|
|
1065
|
+
import { join as join9 } from "path";
|
|
887
1066
|
async function runUpdateSkills() {
|
|
888
1067
|
const apmDir = workspaceApmDir();
|
|
889
|
-
if (!
|
|
1068
|
+
if (!existsSync5(apmDir)) {
|
|
890
1069
|
console.error("[apm] \u672A\u627E\u5230 .apm \u76EE\u5F55\uFF0C\u8BF7\u5148\u6267\u884C apm init");
|
|
891
1070
|
process.exit(1);
|
|
892
1071
|
}
|
|
@@ -900,12 +1079,12 @@ async function runUpdateSkills() {
|
|
|
900
1079
|
if (syncAgentsGuide(apmDir)) {
|
|
901
1080
|
console.log("[apm] \u5DF2\u540C\u6B65 APM \u6307\u5357: .apm/AGENTS.md");
|
|
902
1081
|
}
|
|
903
|
-
const rulesDir =
|
|
1082
|
+
const rulesDir = join9(apmDir, "rules");
|
|
904
1083
|
const ruleNames = syncBaseRules(rulesDir);
|
|
905
1084
|
for (const name of ruleNames) {
|
|
906
1085
|
console.log(`[apm] \u5DF2\u540C\u6B65\u57FA\u7840\u89C4\u5219: rules/${name}`);
|
|
907
1086
|
}
|
|
908
|
-
const skillsDir =
|
|
1087
|
+
const skillsDir = join9(apmDir, "skills");
|
|
909
1088
|
mkdirSync4(skillsDir, { recursive: true });
|
|
910
1089
|
const baseNames = syncBaseSkills(skillsDir);
|
|
911
1090
|
for (const name of baseNames) {
|
|
@@ -932,14 +1111,14 @@ async function runUpdateSkills() {
|
|
|
932
1111
|
}
|
|
933
1112
|
|
|
934
1113
|
// src/commands/sync-document.ts
|
|
935
|
-
import { existsSync as
|
|
936
|
-
import { basename as
|
|
1114
|
+
import { existsSync as existsSync7 } from "fs";
|
|
1115
|
+
import { basename as basename3 } from "path";
|
|
937
1116
|
|
|
938
1117
|
// src/commands/sync-session-documents.ts
|
|
939
|
-
import { existsSync as
|
|
940
|
-
import { join as
|
|
1118
|
+
import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync6 } from "fs";
|
|
1119
|
+
import { join as join10 } from "path";
|
|
941
1120
|
function listLocalMarkdownFiles(docsDir) {
|
|
942
|
-
if (!
|
|
1121
|
+
if (!existsSync6(docsDir)) {
|
|
943
1122
|
return [];
|
|
944
1123
|
}
|
|
945
1124
|
return readdirSync3(docsDir).filter(
|
|
@@ -954,8 +1133,8 @@ function remoteDocumentByLocalName(remoteDocuments, localFileName) {
|
|
|
954
1133
|
});
|
|
955
1134
|
}
|
|
956
1135
|
async function upsertLocalDocumentFile(api, sessionId, docsDir, fileName) {
|
|
957
|
-
const absPath =
|
|
958
|
-
const content =
|
|
1136
|
+
const absPath = join10(docsDir, fileName);
|
|
1137
|
+
const content = readFileSync6(absPath, "utf8");
|
|
959
1138
|
const name = documentPlatformName(absPath);
|
|
960
1139
|
return api.cli.upsertDocument({
|
|
961
1140
|
sessionId,
|
|
@@ -977,8 +1156,8 @@ async function syncSessionDocuments(cfg, sessionId, apmRoot, options) {
|
|
|
977
1156
|
const remoteDocuments = options?.remoteDocuments ?? await api.cli.listDocuments({ sessionId: trimmedSessionId });
|
|
978
1157
|
let synced = 0;
|
|
979
1158
|
for (const fileName of localFiles) {
|
|
980
|
-
const absPath =
|
|
981
|
-
const content =
|
|
1159
|
+
const absPath = join10(docsDir, fileName);
|
|
1160
|
+
const content = readFileSync6(absPath, "utf8");
|
|
982
1161
|
const remote = remoteDocumentByLocalName(remoteDocuments, fileName);
|
|
983
1162
|
if (remote && remote.content === content) {
|
|
984
1163
|
continue;
|
|
@@ -1011,7 +1190,7 @@ async function runSyncDocument(sessionId, options) {
|
|
|
1011
1190
|
process.exit(1);
|
|
1012
1191
|
}
|
|
1013
1192
|
const absPath = resolveSessionDocumentPath(trimmedSessionId, fileArg);
|
|
1014
|
-
if (!
|
|
1193
|
+
if (!existsSync7(absPath)) {
|
|
1015
1194
|
const docsDir2 = sessionDocsDir(trimmedSessionId);
|
|
1016
1195
|
console.error(
|
|
1017
1196
|
`[apm] \u6587\u6863\u4E0D\u5B58\u5728: ${absPath}
|
|
@@ -1026,7 +1205,7 @@ async function runSyncDocument(sessionId, options) {
|
|
|
1026
1205
|
api,
|
|
1027
1206
|
trimmedSessionId,
|
|
1028
1207
|
docsDir,
|
|
1029
|
-
|
|
1208
|
+
basename3(absPath)
|
|
1030
1209
|
);
|
|
1031
1210
|
console.log(`[apm] \u5DF2\u540C\u6B65\u6587\u6863: ${doc.name} (id=${doc.id})`);
|
|
1032
1211
|
}
|
|
@@ -1904,19 +2083,19 @@ async function runConnect(options) {
|
|
|
1904
2083
|
import path5 from "node:path";
|
|
1905
2084
|
|
|
1906
2085
|
// src/commands/deploy/internal/apm-config.ts
|
|
1907
|
-
import { existsSync as
|
|
2086
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7 } from "node:fs";
|
|
1908
2087
|
import { resolve as resolve4 } from "node:path";
|
|
1909
2088
|
function loadApmConfig(options) {
|
|
1910
2089
|
const p = resolve4(
|
|
1911
2090
|
process.cwd(),
|
|
1912
2091
|
options?.configPath ?? resolve4(workspaceApmDir(), "apm.config.json")
|
|
1913
2092
|
);
|
|
1914
|
-
if (!
|
|
2093
|
+
if (!existsSync8(p)) {
|
|
1915
2094
|
console.error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF1A${p}`);
|
|
1916
2095
|
process.exit(1);
|
|
1917
2096
|
}
|
|
1918
2097
|
try {
|
|
1919
|
-
const raw =
|
|
2098
|
+
const raw = readFileSync7(p, "utf8");
|
|
1920
2099
|
return JSON.parse(raw);
|
|
1921
2100
|
} catch (e) {
|
|
1922
2101
|
console.error(`\u65E0\u6CD5\u89E3\u6790 apm.config.json\uFF1A${p}`, e);
|
|
@@ -2038,7 +2217,7 @@ import path4 from "node:path";
|
|
|
2038
2217
|
import Docker from "dockerode";
|
|
2039
2218
|
|
|
2040
2219
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
|
|
2041
|
-
import { existsSync as
|
|
2220
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8 } from "node:fs";
|
|
2042
2221
|
import path from "node:path";
|
|
2043
2222
|
function asOptionalTlsBuffer(value) {
|
|
2044
2223
|
if (typeof value !== "string") {
|
|
@@ -2050,8 +2229,8 @@ function asOptionalTlsBuffer(value) {
|
|
|
2050
2229
|
if (normalized === "") {
|
|
2051
2230
|
return void 0;
|
|
2052
2231
|
}
|
|
2053
|
-
if (
|
|
2054
|
-
return
|
|
2232
|
+
if (existsSync9(normalized)) {
|
|
2233
|
+
return readFileSync8(normalized);
|
|
2055
2234
|
}
|
|
2056
2235
|
const looksLikePath = /[\\/]/.test(normalized) || normalized.endsWith(".pem");
|
|
2057
2236
|
if (looksLikePath) {
|
|
@@ -2261,7 +2440,7 @@ var DockerodeClient = class {
|
|
|
2261
2440
|
var createDockerodeClient = (config) => new DockerodeClient(config);
|
|
2262
2441
|
|
|
2263
2442
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
|
|
2264
|
-
import { existsSync as
|
|
2443
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9, statSync as statSync4 } from "node:fs";
|
|
2265
2444
|
import path2 from "node:path";
|
|
2266
2445
|
function stripSurroundingQuotes(value) {
|
|
2267
2446
|
const t = value.trim();
|
|
@@ -2278,10 +2457,10 @@ function loadEnvFromFile(envFilePath) {
|
|
|
2278
2457
|
return {};
|
|
2279
2458
|
}
|
|
2280
2459
|
const targetPath = path2.resolve(envFilePath);
|
|
2281
|
-
if (!
|
|
2460
|
+
if (!existsSync10(targetPath) || !statSync4(targetPath).isFile()) {
|
|
2282
2461
|
return {};
|
|
2283
2462
|
}
|
|
2284
|
-
const raw =
|
|
2463
|
+
const raw = readFileSync9(targetPath, "utf-8");
|
|
2285
2464
|
const result = {};
|
|
2286
2465
|
for (const line of raw.split(/\r?\n/)) {
|
|
2287
2466
|
const normalized = line.trim();
|
|
@@ -2346,7 +2525,7 @@ function assertDeployImageTag(tag) {
|
|
|
2346
2525
|
}
|
|
2347
2526
|
|
|
2348
2527
|
// src/commands/deploy/internal/backend-deploy/local-docker-build.ts
|
|
2349
|
-
import { platform } from "node:os";
|
|
2528
|
+
import { platform as platform2 } from "node:os";
|
|
2350
2529
|
|
|
2351
2530
|
// src/commands/deploy/internal/backend-deploy/command-runner.ts
|
|
2352
2531
|
import { execSync } from "child_process";
|
|
@@ -2406,7 +2585,7 @@ var CommandRunner = class {
|
|
|
2406
2585
|
|
|
2407
2586
|
// src/commands/deploy/internal/backend-deploy/local-docker-build.ts
|
|
2408
2587
|
function dockerBuildPlatformFlags() {
|
|
2409
|
-
return
|
|
2588
|
+
return platform2() === "darwin" ? ["--platform", "linux/amd64"] : [];
|
|
2410
2589
|
}
|
|
2411
2590
|
function buildDockerImageLocally(params, cwd) {
|
|
2412
2591
|
const platformFlags = dockerBuildPlatformFlags();
|
|
@@ -2452,12 +2631,12 @@ function dockerPushImage(params, cwd) {
|
|
|
2452
2631
|
}
|
|
2453
2632
|
|
|
2454
2633
|
// src/commands/deploy/internal/backend-deploy/resolve-dockerfile.ts
|
|
2455
|
-
import { existsSync as
|
|
2634
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
2456
2635
|
import path3 from "node:path";
|
|
2457
2636
|
function resolveDockerBuildPaths(cwd) {
|
|
2458
2637
|
const dockerfilePath = path3.join(cwd, "Dockerfile");
|
|
2459
2638
|
Logger.info(`\u67E5\u627EDockerfile\u6587\u4EF6\uFF0C\u8DEF\u5F84: ${dockerfilePath}`);
|
|
2460
|
-
if (!
|
|
2639
|
+
if (!existsSync11(dockerfilePath)) {
|
|
2461
2640
|
throw new Error(`Dockerfile \u4E0D\u5B58\u5728\uFF1A${dockerfilePath}`);
|
|
2462
2641
|
}
|
|
2463
2642
|
Logger.info("\u2713 Dockerfile \u5B58\u5728");
|
package/package.json
CHANGED
|
File without changes
|