ai-project-manage-cli 6.0.44 → 6.0.46
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 +271 -114
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ function resolveClientMachineId(cfg) {
|
|
|
16
16
|
function resolveApiKey(cfg) {
|
|
17
17
|
return (cfg.apiKey ?? cfg.token ?? "").trim();
|
|
18
18
|
}
|
|
19
|
-
async function
|
|
19
|
+
async function tryReadApmConfig() {
|
|
20
20
|
try {
|
|
21
21
|
const raw = readFileSync(APM_CONFIG_PATH, "utf8");
|
|
22
22
|
const v = JSON.parse(raw);
|
|
@@ -54,7 +54,7 @@ function httpBaseToWsOrigin(httpBase) {
|
|
|
54
54
|
throw new Error("baseUrl \u5FC5\u987B\u4EE5 http:// \u6216 https:// \u5F00\u5934");
|
|
55
55
|
}
|
|
56
56
|
async function ensureApmConfig() {
|
|
57
|
-
const existing = await
|
|
57
|
+
const existing = await tryReadApmConfig();
|
|
58
58
|
if (existing) return existing;
|
|
59
59
|
const defaults = defaultApmConfig();
|
|
60
60
|
await writeApmConfig(defaults);
|
|
@@ -80,8 +80,8 @@ function buildAgentWsUrl(httpBase, apiKey) {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
// src/commands/init.ts
|
|
83
|
-
import { join as
|
|
84
|
-
import { readFileSync as readFileSync2, writeFileSync as
|
|
83
|
+
import { join as join4 } from "path";
|
|
84
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
85
85
|
|
|
86
86
|
// src/command-utils.ts
|
|
87
87
|
import { copyFileSync, existsSync, mkdirSync as mkdirSync2, readdirSync, statSync } from "fs";
|
|
@@ -287,32 +287,9 @@ async function copyTemplateFiles(targetDir, workdir = resolveWorkdirPath()) {
|
|
|
287
287
|
assertTemplateCopiedToApm(resolvedTarget, resolve2(workdir));
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
-
// src/
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
await ensureWorkspaceApmDirForInit(workdir);
|
|
294
|
-
const apmDir = workspaceApmDir(workdir);
|
|
295
|
-
await copyTemplateFiles(apmDir, workdir);
|
|
296
|
-
const trimmedName = name?.trim();
|
|
297
|
-
if (trimmedName) {
|
|
298
|
-
const apmConfigPath = toFsPath(join3(apmDir, "apm.config.json"));
|
|
299
|
-
const config = readFileSync2(apmConfigPath, "utf8");
|
|
300
|
-
const configJson = JSON.parse(config);
|
|
301
|
-
configJson.name = trimmedName;
|
|
302
|
-
writeFileSync2(
|
|
303
|
-
apmConfigPath,
|
|
304
|
-
`${JSON.stringify(configJson, null, 2)}
|
|
305
|
-
`,
|
|
306
|
-
"utf8"
|
|
307
|
-
);
|
|
308
|
-
}
|
|
309
|
-
console.log(`[apm] \u5DF2\u521D\u59CB\u5316\u5DE5\u4F5C\u533A\uFF1A${apmDir}`);
|
|
310
|
-
console.log(`[apm] \u5DE5\u4F5C\u76EE\u5F55\u8DEF\u5F84\uFF1A${workdir}`);
|
|
311
|
-
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");
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// src/commands/login.ts
|
|
315
|
-
import { ApiError } from "listpage-http";
|
|
290
|
+
// src/deployment-config-sync.ts
|
|
291
|
+
import { join as join3 } from "path";
|
|
292
|
+
import { writeFileSync as writeFileSync2 } from "fs";
|
|
316
293
|
|
|
317
294
|
// src/api/client.ts
|
|
318
295
|
import { createApiClient } from "listpage-http";
|
|
@@ -373,6 +350,18 @@ var requestConfig = {
|
|
|
373
350
|
method: "GET",
|
|
374
351
|
path: "/cli/tasks/branch-baseline"
|
|
375
352
|
}),
|
|
353
|
+
workspaceBaseline: defineEndpoint({
|
|
354
|
+
method: "GET",
|
|
355
|
+
path: "/cli/workspaces/baseline"
|
|
356
|
+
}),
|
|
357
|
+
getDeploymentConfiguration: defineEndpoint({
|
|
358
|
+
method: "GET",
|
|
359
|
+
path: "/cli/deployment-configurations"
|
|
360
|
+
}),
|
|
361
|
+
matchRepository: defineEndpoint({
|
|
362
|
+
method: "GET",
|
|
363
|
+
path: "/cli/repositories/match"
|
|
364
|
+
}),
|
|
376
365
|
listSkills: defineEndpoint({
|
|
377
366
|
method: "GET",
|
|
378
367
|
path: "/cli/skills"
|
|
@@ -395,7 +384,131 @@ function createApmApiClient(cfg) {
|
|
|
395
384
|
});
|
|
396
385
|
}
|
|
397
386
|
|
|
387
|
+
// src/git-remote.ts
|
|
388
|
+
import { execFile } from "child_process";
|
|
389
|
+
import { promisify } from "util";
|
|
390
|
+
var execFileAsync = promisify(execFile);
|
|
391
|
+
async function tryReadGitOriginUrl(cwd) {
|
|
392
|
+
try {
|
|
393
|
+
const { stdout } = await execFileAsync(
|
|
394
|
+
"git",
|
|
395
|
+
["config", "--get", "remote.origin.url"],
|
|
396
|
+
{ cwd, encoding: "utf8", maxBuffer: 1024 * 1024 }
|
|
397
|
+
);
|
|
398
|
+
const url = stdout.trim();
|
|
399
|
+
return url || null;
|
|
400
|
+
} catch {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// src/deployment-config-sync.ts
|
|
406
|
+
var TEMPLATE_HINT = "\u4FDD\u7559\u6A21\u677F .apm/apm.config.json \u4E0E .apm/deploy/README.md";
|
|
407
|
+
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";
|
|
408
|
+
async function resolveRepositoryIdForSync(api, workdirPath) {
|
|
409
|
+
const baseline = await api.cli.workspaceBaseline({ workdirPath });
|
|
410
|
+
if (baseline.repositoryId) {
|
|
411
|
+
return { repositoryId: baseline.repositoryId, diagnostic: null };
|
|
412
|
+
}
|
|
413
|
+
const gitUrl = await tryReadGitOriginUrl(workdirPath);
|
|
414
|
+
if (gitUrl) {
|
|
415
|
+
const matched = await api.cli.matchRepository({ url: gitUrl });
|
|
416
|
+
if (matched.repositoryId) {
|
|
417
|
+
console.log(`[apm] \u5DE5\u4F5C\u7A7A\u95F4\u8DEF\u5F84\u672A\u5339\u914D\uFF0C\u5DF2\u901A\u8FC7 git remote \u5173\u8054\u4ED3\u5E93: ${gitUrl}`);
|
|
418
|
+
return { repositoryId: matched.repositoryId, diagnostic: null };
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
const detail = baseline.diagnostic?.message ?? `\u5F53\u524D\u8DEF\u5F84\uFF08\u89C4\u8303\u5316\uFF1A${baseline.workdirPath}\uFF09\u672A\u5339\u914D\u5230\u5DF2\u7ED1\u5B9A\u4ED3\u5E93\u7684\u5DE5\u4F5C\u7A7A\u95F4\u3002`;
|
|
422
|
+
return { repositoryId: null, diagnostic: detail };
|
|
423
|
+
}
|
|
424
|
+
async function syncRemoteDeploymentConfig(workdirPath, apmDir) {
|
|
425
|
+
const cfg = await tryReadApmConfig();
|
|
426
|
+
if (!cfg || !resolveApiKey(cfg)) {
|
|
427
|
+
console.log(
|
|
428
|
+
`[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
|
|
429
|
+
[apm] \u8BF7\u5148\u6267\u884C apm login\uFF0C\u518D\u6267\u884C apm sync-deploy-config \u62C9\u53D6\u6700\u65B0\u914D\u7F6E\u3002`
|
|
430
|
+
);
|
|
431
|
+
return { synced: false, repositoryId: null };
|
|
432
|
+
}
|
|
433
|
+
const api = createApmApiClient(cfg);
|
|
434
|
+
const { repositoryId, diagnostic } = await resolveRepositoryIdForSync(
|
|
435
|
+
api,
|
|
436
|
+
workdirPath
|
|
437
|
+
);
|
|
438
|
+
if (!repositoryId) {
|
|
439
|
+
console.log(
|
|
440
|
+
`[apm] \u672A\u80FD\u540C\u6B65\u5E73\u53F0\u90E8\u7F72\u914D\u7F6E\uFF08${TEMPLATE_HINT}\uFF09\u3002
|
|
441
|
+
${diagnostic ?? ""}
|
|
442
|
+
[apm] ${SYNC_HINT}`
|
|
443
|
+
);
|
|
444
|
+
return { synced: false, repositoryId: null };
|
|
445
|
+
}
|
|
446
|
+
const { config } = await api.cli.getDeploymentConfiguration({ repositoryId });
|
|
447
|
+
if (!config) {
|
|
448
|
+
console.log(
|
|
449
|
+
`[apm] \u672A\u627E\u5230\u5173\u8054\u4ED3\u5E93\u7684\u90E8\u7F72\u914D\u7F6E\uFF08${TEMPLATE_HINT}\uFF0CrepositoryId\uFF1A${repositoryId}\uFF09\u3002
|
|
450
|
+
[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`
|
|
451
|
+
);
|
|
452
|
+
return { synced: false, repositoryId };
|
|
453
|
+
}
|
|
454
|
+
let parsed;
|
|
455
|
+
try {
|
|
456
|
+
parsed = JSON.parse(config.content);
|
|
457
|
+
} catch {
|
|
458
|
+
console.warn(
|
|
459
|
+
`[apm] \u8FDC\u7A0B\u90E8\u7F72\u914D\u7F6E\u300C${config.name}\u300DJSON \u65E0\u6548\uFF08${TEMPLATE_HINT}\uFF09`
|
|
460
|
+
);
|
|
461
|
+
return { synced: false, repositoryId };
|
|
462
|
+
}
|
|
463
|
+
const targetApmDir = apmDir ?? workspaceApmDir(workdirPath);
|
|
464
|
+
const apmConfigPath = toFsPath(join3(targetApmDir, "apm.config.json"));
|
|
465
|
+
writeFileSync2(apmConfigPath, `${JSON.stringify(parsed, null, 2)}
|
|
466
|
+
`, "utf8");
|
|
467
|
+
const deployDir = join3(targetApmDir, "deploy");
|
|
468
|
+
await ensureDirExists(deployDir);
|
|
469
|
+
writeFileSync2(
|
|
470
|
+
toFsPath(join3(deployDir, "README.md")),
|
|
471
|
+
config.deploymentDoc ?? "",
|
|
472
|
+
"utf8"
|
|
473
|
+
);
|
|
474
|
+
console.log(`[apm] \u5DF2\u540C\u6B65\u5E73\u53F0\u90E8\u7F72\u914D\u7F6E: ${config.name}`);
|
|
475
|
+
console.log("[apm] \u5DF2\u5199\u5165 .apm/apm.config.json \u4E0E .apm/deploy/README.md");
|
|
476
|
+
return { synced: true, repositoryId, configName: config.name };
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// src/commands/init.ts
|
|
480
|
+
async function runInit(name) {
|
|
481
|
+
const workdir = resolveWorkdirPath();
|
|
482
|
+
await ensureWorkspaceApmDirForInit(workdir);
|
|
483
|
+
const apmDir = workspaceApmDir(workdir);
|
|
484
|
+
await copyTemplateFiles(apmDir, workdir);
|
|
485
|
+
const syncResult = await syncRemoteDeploymentConfig(workdir, apmDir);
|
|
486
|
+
const trimmedName = name?.trim();
|
|
487
|
+
if (trimmedName) {
|
|
488
|
+
const apmConfigPath = toFsPath(join4(apmDir, "apm.config.json"));
|
|
489
|
+
const config = readFileSync2(apmConfigPath, "utf8");
|
|
490
|
+
const configJson = JSON.parse(config);
|
|
491
|
+
configJson.name = trimmedName;
|
|
492
|
+
writeFileSync3(
|
|
493
|
+
apmConfigPath,
|
|
494
|
+
`${JSON.stringify(configJson, null, 2)}
|
|
495
|
+
`,
|
|
496
|
+
"utf8"
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
console.log(`[apm] \u5DF2\u521D\u59CB\u5316\u5DE5\u4F5C\u533A\uFF1A${apmDir}`);
|
|
500
|
+
console.log(`[apm] \u5DE5\u4F5C\u76EE\u5F55\u8DEF\u5F84\uFF1A${workdir}`);
|
|
501
|
+
if (!syncResult.synced) {
|
|
502
|
+
console.log(
|
|
503
|
+
"[apm] \u5F53\u524D .apm/apm.config.json \u4E0E .apm/deploy/README.md \u4E3A\u6A21\u677F\u9ED8\u8BA4\u503C\uFF1B\u5B8C\u6210\u5E73\u53F0\u767B\u8BB0\u540E\u6267\u884C apm sync-deploy-config"
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
console.log("[apm] \u8BF7\u5728\u5E73\u53F0\u300C\u63A5\u5165\u7BA1\u7406 \u2192 \u5DE5\u4F5C\u7A7A\u95F4\u300D\u767B\u8BB0\u4E0A\u8FF0\u76EE\u5F55\u8DEF\u5F84");
|
|
507
|
+
}
|
|
508
|
+
|
|
398
509
|
// src/commands/login.ts
|
|
510
|
+
import { existsSync as existsSync2 } from "fs";
|
|
511
|
+
import { ApiError } from "listpage-http";
|
|
399
512
|
async function runLogin(opts) {
|
|
400
513
|
const baseUrl = (opts.server?.trim() || process.env.AI_PM_SERVER?.trim() || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
401
514
|
const apiKey = (opts.apiKey?.trim() || process.env.APM_API_KEY?.trim() || "").replace(/^Bearer\s+/i, "");
|
|
@@ -447,12 +560,17 @@ async function runLogin(opts) {
|
|
|
447
560
|
2
|
|
448
561
|
)
|
|
449
562
|
);
|
|
563
|
+
const workdir = resolveWorkdirPath();
|
|
564
|
+
const apmDir = workspaceApmDir(workdir);
|
|
565
|
+
if (existsSync2(apmDir)) {
|
|
566
|
+
await syncRemoteDeploymentConfig(workdir, apmDir);
|
|
567
|
+
}
|
|
450
568
|
}
|
|
451
569
|
|
|
452
570
|
// src/commands/branch.ts
|
|
453
|
-
import { execFile } from "child_process";
|
|
454
|
-
import { promisify } from "util";
|
|
455
|
-
var
|
|
571
|
+
import { execFile as execFile2 } from "child_process";
|
|
572
|
+
import { promisify as promisify2 } from "util";
|
|
573
|
+
var execFileAsync2 = promisify2(execFile2);
|
|
456
574
|
function branchNameForSession(sessionId) {
|
|
457
575
|
const id = sessionId.trim();
|
|
458
576
|
if (!id) {
|
|
@@ -467,7 +585,7 @@ function branchNameForSession(sessionId) {
|
|
|
467
585
|
}
|
|
468
586
|
async function execGit(cwd, args, quiet) {
|
|
469
587
|
try {
|
|
470
|
-
const { stdout, stderr } = await
|
|
588
|
+
const { stdout, stderr } = await execFileAsync2("git", args, {
|
|
471
589
|
cwd,
|
|
472
590
|
encoding: "utf8",
|
|
473
591
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -617,8 +735,8 @@ async function runBranch(sessionId, options = {}) {
|
|
|
617
735
|
}
|
|
618
736
|
|
|
619
737
|
// src/commands/pull.ts
|
|
620
|
-
import { writeFileSync as
|
|
621
|
-
import { join as
|
|
738
|
+
import { writeFileSync as writeFileSync7 } from "fs";
|
|
739
|
+
import { join as join8 } from "path";
|
|
622
740
|
import { stringify as yamlStringify } from "yaml";
|
|
623
741
|
|
|
624
742
|
// src/session-messages-xml.ts
|
|
@@ -651,8 +769,8 @@ function formatSessionMessagesXml(sessionId, messages) {
|
|
|
651
769
|
}
|
|
652
770
|
|
|
653
771
|
// src/commands/sync-session-attachments.ts
|
|
654
|
-
import { existsSync as
|
|
655
|
-
import { join as
|
|
772
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
773
|
+
import { join as join5 } from "path";
|
|
656
774
|
var MANIFEST_FILE = ".sync-manifest.json";
|
|
657
775
|
async function downloadAttachment(cfg, attachmentId) {
|
|
658
776
|
const base = cfg.baseUrl.trim().replace(/\/+$/, "");
|
|
@@ -666,8 +784,8 @@ async function downloadAttachment(cfg, attachmentId) {
|
|
|
666
784
|
return Buffer.from(await res.arrayBuffer());
|
|
667
785
|
}
|
|
668
786
|
function loadManifest(dir) {
|
|
669
|
-
const path10 =
|
|
670
|
-
if (!
|
|
787
|
+
const path10 = join5(dir, MANIFEST_FILE);
|
|
788
|
+
if (!existsSync3(path10)) {
|
|
671
789
|
return { version: 1, attachments: {} };
|
|
672
790
|
}
|
|
673
791
|
try {
|
|
@@ -682,21 +800,21 @@ function loadManifest(dir) {
|
|
|
682
800
|
return { version: 1, attachments: {} };
|
|
683
801
|
}
|
|
684
802
|
function saveManifest(dir, manifest) {
|
|
685
|
-
|
|
686
|
-
|
|
803
|
+
writeFileSync4(
|
|
804
|
+
join5(dir, MANIFEST_FILE),
|
|
687
805
|
`${JSON.stringify(manifest, null, 2)}
|
|
688
806
|
`,
|
|
689
807
|
"utf8"
|
|
690
808
|
);
|
|
691
809
|
}
|
|
692
810
|
function isAttachmentUpToDate(entry, item, dest) {
|
|
693
|
-
if (!entry || !
|
|
811
|
+
if (!entry || !existsSync3(dest)) return false;
|
|
694
812
|
if (entry.name !== item.name) return false;
|
|
695
813
|
const createdAt = item.createdAt ?? "";
|
|
696
814
|
return entry.createdAt === createdAt;
|
|
697
815
|
}
|
|
698
816
|
async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
|
|
699
|
-
const dir =
|
|
817
|
+
const dir = join5(sessionDir(sessionId, apmRoot), SESSION_ATTACHMENTS_SUBDIR);
|
|
700
818
|
await ensureDirExists(dir);
|
|
701
819
|
if (attachments.length === 0) {
|
|
702
820
|
saveManifest(dir, { version: 1, attachments: {} });
|
|
@@ -705,7 +823,7 @@ async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
|
|
|
705
823
|
const manifest = loadManifest(dir);
|
|
706
824
|
const nextManifest = { version: 1, attachments: {} };
|
|
707
825
|
for (const item of attachments) {
|
|
708
|
-
const dest =
|
|
826
|
+
const dest = join5(dir, item.name);
|
|
709
827
|
const entry = manifest.attachments[item.id];
|
|
710
828
|
const createdAt = item.createdAt ?? "";
|
|
711
829
|
if (isAttachmentUpToDate(entry, item, dest)) {
|
|
@@ -716,7 +834,7 @@ async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
|
|
|
716
834
|
continue;
|
|
717
835
|
}
|
|
718
836
|
const buffer = await downloadAttachment(cfg, item.id);
|
|
719
|
-
|
|
837
|
+
writeFileSync4(dest, buffer);
|
|
720
838
|
nextManifest.attachments[item.id] = {
|
|
721
839
|
name: item.name,
|
|
722
840
|
createdAt
|
|
@@ -727,46 +845,46 @@ async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
|
|
|
727
845
|
}
|
|
728
846
|
|
|
729
847
|
// src/rules-sync.ts
|
|
730
|
-
import { basename as basename2, extname as extname2, join as
|
|
731
|
-
import { existsSync as
|
|
848
|
+
import { basename as basename2, extname as extname2, join as join7 } from "path";
|
|
849
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
732
850
|
|
|
733
851
|
// src/skills-sync.ts
|
|
734
852
|
import {
|
|
735
853
|
copyFileSync as copyFileSync2,
|
|
736
854
|
cpSync,
|
|
737
|
-
existsSync as
|
|
855
|
+
existsSync as existsSync4,
|
|
738
856
|
mkdirSync as mkdirSync3,
|
|
739
857
|
readdirSync as readdirSync2,
|
|
740
858
|
rmSync,
|
|
741
859
|
statSync as statSync2,
|
|
742
|
-
writeFileSync as
|
|
860
|
+
writeFileSync as writeFileSync5
|
|
743
861
|
} from "fs";
|
|
744
|
-
import { join as
|
|
745
|
-
var AGENTS_TEMPLATE_PATH =
|
|
746
|
-
var BASE_SKILLS_TEMPLATE_DIR =
|
|
747
|
-
var BASE_RULES_TEMPLATE_DIR =
|
|
862
|
+
import { join as join6 } from "path";
|
|
863
|
+
var AGENTS_TEMPLATE_PATH = join6(CLI_TEMPLATE_DIR, "AGENTS.md");
|
|
864
|
+
var BASE_SKILLS_TEMPLATE_DIR = join6(CLI_TEMPLATE_DIR, "skills");
|
|
865
|
+
var BASE_RULES_TEMPLATE_DIR = join6(CLI_TEMPLATE_DIR, "rules");
|
|
748
866
|
function sanitizeSkillDirName(name) {
|
|
749
867
|
const trimmed = name.trim();
|
|
750
868
|
if (!trimmed) return "skill";
|
|
751
869
|
return trimmed.replace(/[/\\:*?"<>|]/g, "_");
|
|
752
870
|
}
|
|
753
871
|
function listBaseSkillDirNames() {
|
|
754
|
-
if (!
|
|
872
|
+
if (!existsSync4(BASE_SKILLS_TEMPLATE_DIR)) return [];
|
|
755
873
|
return readdirSync2(BASE_SKILLS_TEMPLATE_DIR).filter((name) => {
|
|
756
|
-
const path10 =
|
|
874
|
+
const path10 = join6(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
757
875
|
return statSync2(path10).isDirectory();
|
|
758
876
|
});
|
|
759
877
|
}
|
|
760
878
|
function syncAgentsGuide(apmDir) {
|
|
761
|
-
if (!
|
|
879
|
+
if (!existsSync4(AGENTS_TEMPLATE_PATH)) return false;
|
|
762
880
|
mkdirSync3(apmDir, { recursive: true });
|
|
763
|
-
copyFileSync2(AGENTS_TEMPLATE_PATH,
|
|
881
|
+
copyFileSync2(AGENTS_TEMPLATE_PATH, join6(apmDir, "AGENTS.md"));
|
|
764
882
|
return true;
|
|
765
883
|
}
|
|
766
884
|
function listBaseRuleFileNames() {
|
|
767
|
-
if (!
|
|
885
|
+
if (!existsSync4(BASE_RULES_TEMPLATE_DIR)) return [];
|
|
768
886
|
return readdirSync2(BASE_RULES_TEMPLATE_DIR).filter((name) => {
|
|
769
|
-
const path10 =
|
|
887
|
+
const path10 = join6(BASE_RULES_TEMPLATE_DIR, name);
|
|
770
888
|
return statSync2(path10).isFile();
|
|
771
889
|
});
|
|
772
890
|
}
|
|
@@ -774,8 +892,8 @@ function syncBaseRules(rulesDir) {
|
|
|
774
892
|
mkdirSync3(rulesDir, { recursive: true });
|
|
775
893
|
const names = listBaseRuleFileNames();
|
|
776
894
|
for (const name of names) {
|
|
777
|
-
const src =
|
|
778
|
-
const dest =
|
|
895
|
+
const src = join6(BASE_RULES_TEMPLATE_DIR, name);
|
|
896
|
+
const dest = join6(rulesDir, name);
|
|
779
897
|
copyFileSync2(src, dest);
|
|
780
898
|
}
|
|
781
899
|
return names;
|
|
@@ -784,8 +902,8 @@ function syncBaseSkills(skillsDir) {
|
|
|
784
902
|
mkdirSync3(skillsDir, { recursive: true });
|
|
785
903
|
const names = listBaseSkillDirNames();
|
|
786
904
|
for (const name of names) {
|
|
787
|
-
const src =
|
|
788
|
-
const dest =
|
|
905
|
+
const src = join6(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
906
|
+
const dest = join6(skillsDir, name);
|
|
789
907
|
cpSync(src, dest, { recursive: true, force: true });
|
|
790
908
|
}
|
|
791
909
|
return names;
|
|
@@ -802,15 +920,15 @@ function syncSupplementarySkills(skillsDir, list) {
|
|
|
802
920
|
skipped.push(dirName);
|
|
803
921
|
continue;
|
|
804
922
|
}
|
|
805
|
-
const skillDir =
|
|
923
|
+
const skillDir = join6(skillsDir, dirName);
|
|
806
924
|
mkdirSync3(skillDir, { recursive: true });
|
|
807
|
-
|
|
925
|
+
writeFileSync5(join6(skillDir, "SKILL.md"), skill.content ?? "", "utf8");
|
|
808
926
|
written.push(dirName);
|
|
809
927
|
}
|
|
810
928
|
const removed = [];
|
|
811
|
-
if (!
|
|
929
|
+
if (!existsSync4(skillsDir)) return { written, skipped, removed };
|
|
812
930
|
for (const entry of readdirSync2(skillsDir)) {
|
|
813
|
-
const full =
|
|
931
|
+
const full = join6(skillsDir, entry);
|
|
814
932
|
if (!statSync2(full).isDirectory()) continue;
|
|
815
933
|
if (baseNames.has(entry)) continue;
|
|
816
934
|
if (apiDirNames.has(entry)) continue;
|
|
@@ -830,8 +948,8 @@ function ruleLocalFileName(ruleName) {
|
|
|
830
948
|
return `${sanitized}.md`;
|
|
831
949
|
}
|
|
832
950
|
function loadManifest2(rulesDir) {
|
|
833
|
-
const path10 =
|
|
834
|
-
if (!
|
|
951
|
+
const path10 = join7(rulesDir, MANIFEST_FILE2);
|
|
952
|
+
if (!existsSync5(toFsPath(path10))) {
|
|
835
953
|
return { version: 1, rules: {} };
|
|
836
954
|
}
|
|
837
955
|
try {
|
|
@@ -846,8 +964,8 @@ function loadManifest2(rulesDir) {
|
|
|
846
964
|
return { version: 1, rules: {} };
|
|
847
965
|
}
|
|
848
966
|
function saveManifest2(rulesDir, manifest) {
|
|
849
|
-
|
|
850
|
-
toFsPath(
|
|
967
|
+
writeFileSync6(
|
|
968
|
+
toFsPath(join7(rulesDir, MANIFEST_FILE2)),
|
|
851
969
|
`${JSON.stringify(manifest, null, 2)}
|
|
852
970
|
`,
|
|
853
971
|
"utf8"
|
|
@@ -857,7 +975,7 @@ function isBaseRuleFileName(fileName) {
|
|
|
857
975
|
return listBaseRuleFileNames().includes(basename2(fileName));
|
|
858
976
|
}
|
|
859
977
|
function isRuleUpToDate(entry, rule, dest) {
|
|
860
|
-
if (!entry || !
|
|
978
|
+
if (!entry || !existsSync5(toFsPath(dest))) return false;
|
|
861
979
|
if (entry.fileName !== ruleLocalFileName(rule.name)) return false;
|
|
862
980
|
const updatedAt = rule.updatedAt ?? "";
|
|
863
981
|
if (entry.updatedAt !== updatedAt) return false;
|
|
@@ -868,7 +986,7 @@ async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
|
|
|
868
986
|
const api = createApmApiClient(cfg);
|
|
869
987
|
const baseline = await api.cli.branchBaseline({ sessionId, workdirPath });
|
|
870
988
|
const repositoryId = baseline.repositoryId;
|
|
871
|
-
const rulesDir =
|
|
989
|
+
const rulesDir = join7(apmRoot ?? workspaceApmDir(workdirPath), "rules");
|
|
872
990
|
await ensureDirExists(rulesDir);
|
|
873
991
|
if (!repositoryId) {
|
|
874
992
|
console.log(
|
|
@@ -885,7 +1003,7 @@ async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
|
|
|
885
1003
|
for (const rule of list) {
|
|
886
1004
|
remoteIds.add(rule.id);
|
|
887
1005
|
const fileName = ruleLocalFileName(rule.name);
|
|
888
|
-
const dest =
|
|
1006
|
+
const dest = join7(rulesDir, fileName);
|
|
889
1007
|
const entry = manifest.rules[rule.id];
|
|
890
1008
|
const updatedAt = rule.updatedAt ?? "";
|
|
891
1009
|
if (isRuleUpToDate(entry, rule, dest)) {
|
|
@@ -894,7 +1012,7 @@ async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
|
|
|
894
1012
|
console.log(`[apm] \u89C4\u5219\u65E0\u53D8\u5316\uFF0C\u5DF2\u8DF3\u8FC7: rules/${fileName}`);
|
|
895
1013
|
continue;
|
|
896
1014
|
}
|
|
897
|
-
|
|
1015
|
+
writeFileSync6(toFsPath(dest), rule.content ?? "", "utf8");
|
|
898
1016
|
nextManifest.rules[rule.id] = { fileName, updatedAt };
|
|
899
1017
|
written.push(fileName);
|
|
900
1018
|
console.log(`[apm] \u5DF2\u540C\u6B65\u5E73\u53F0\u89C4\u5219: rules/${fileName}`);
|
|
@@ -903,8 +1021,8 @@ async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
|
|
|
903
1021
|
for (const [ruleId, entry] of Object.entries(manifest.rules)) {
|
|
904
1022
|
if (remoteIds.has(ruleId)) continue;
|
|
905
1023
|
if (isBaseRuleFileName(entry.fileName)) continue;
|
|
906
|
-
const dest =
|
|
907
|
-
if (
|
|
1024
|
+
const dest = join7(rulesDir, entry.fileName);
|
|
1025
|
+
if (existsSync5(toFsPath(dest))) {
|
|
908
1026
|
rmSync2(toFsPath(dest), { force: true });
|
|
909
1027
|
}
|
|
910
1028
|
removed.push(entry.fileName);
|
|
@@ -937,20 +1055,20 @@ async function runPull(sessionId, remoteWorkdir) {
|
|
|
937
1055
|
const dir = sessionDir(trimmedId, apmRoot);
|
|
938
1056
|
const docsDir = sessionDocsDir(trimmedId, apmRoot);
|
|
939
1057
|
await ensureDirExists(docsDir);
|
|
940
|
-
|
|
1058
|
+
writeFileSync7(
|
|
941
1059
|
sessionRulePath(trimmedId, apmRoot),
|
|
942
1060
|
detail.description ?? "",
|
|
943
1061
|
"utf8"
|
|
944
1062
|
);
|
|
945
|
-
|
|
1063
|
+
writeFileSync7(
|
|
946
1064
|
sessionTaskPath(trimmedId, apmRoot),
|
|
947
1065
|
detail.task.description ?? "",
|
|
948
1066
|
"utf8"
|
|
949
1067
|
);
|
|
950
|
-
|
|
1068
|
+
writeFileSync7(sessionTodoPath(trimmedId, apmRoot), detail.todo ?? "", "utf8");
|
|
951
1069
|
for (const doc of documents) {
|
|
952
1070
|
const fileName = documentLocalFileName(doc.name);
|
|
953
|
-
|
|
1071
|
+
writeFileSync7(join8(docsDir, fileName), doc.content ?? "", "utf8");
|
|
954
1072
|
}
|
|
955
1073
|
const sessionYaml = yamlStringify(
|
|
956
1074
|
{
|
|
@@ -967,13 +1085,13 @@ async function runPull(sessionId, remoteWorkdir) {
|
|
|
967
1085
|
},
|
|
968
1086
|
{ lineWidth: 0 }
|
|
969
1087
|
);
|
|
970
|
-
|
|
1088
|
+
writeFileSync7(
|
|
971
1089
|
sessionYamlPath(trimmedId, apmRoot),
|
|
972
1090
|
sessionYaml.endsWith("\n") ? sessionYaml : `${sessionYaml}
|
|
973
1091
|
`,
|
|
974
1092
|
"utf8"
|
|
975
1093
|
);
|
|
976
|
-
|
|
1094
|
+
writeFileSync7(
|
|
977
1095
|
sessionMessagesXmlPath(trimmedId, apmRoot),
|
|
978
1096
|
formatSessionMessagesXml(trimmedId, messages),
|
|
979
1097
|
"utf8"
|
|
@@ -989,13 +1107,13 @@ import { spawnSync } from "child_process";
|
|
|
989
1107
|
|
|
990
1108
|
// src/version.ts
|
|
991
1109
|
import { readFileSync as readFileSync5 } from "fs";
|
|
992
|
-
import { dirname as dirname2, join as
|
|
1110
|
+
import { dirname as dirname2, join as join9 } from "path";
|
|
993
1111
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
994
1112
|
var CLI_PACKAGE_NAME = "ai-project-manage-cli";
|
|
995
1113
|
function readCliVersion() {
|
|
996
1114
|
try {
|
|
997
1115
|
const dir = dirname2(fileURLToPath2(import.meta.url));
|
|
998
|
-
const pkgPath =
|
|
1116
|
+
const pkgPath = join9(dir, "..", "package.json");
|
|
999
1117
|
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
|
|
1000
1118
|
return pkg.version ?? "0.0.0";
|
|
1001
1119
|
} catch {
|
|
@@ -1063,11 +1181,11 @@ async function runUpdate() {
|
|
|
1063
1181
|
}
|
|
1064
1182
|
|
|
1065
1183
|
// src/commands/update-skills.ts
|
|
1066
|
-
import { existsSync as
|
|
1067
|
-
import { join as
|
|
1184
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync4, statSync as statSync3 } from "fs";
|
|
1185
|
+
import { join as join10 } from "path";
|
|
1068
1186
|
async function runUpdateSkills() {
|
|
1069
1187
|
const apmDir = workspaceApmDir();
|
|
1070
|
-
if (!
|
|
1188
|
+
if (!existsSync6(apmDir)) {
|
|
1071
1189
|
console.error("[apm] \u672A\u627E\u5230 .apm \u76EE\u5F55\uFF0C\u8BF7\u5148\u6267\u884C apm init");
|
|
1072
1190
|
process.exit(1);
|
|
1073
1191
|
}
|
|
@@ -1081,12 +1199,12 @@ async function runUpdateSkills() {
|
|
|
1081
1199
|
if (syncAgentsGuide(apmDir)) {
|
|
1082
1200
|
console.log("[apm] \u5DF2\u540C\u6B65 APM \u6307\u5357: .apm/AGENTS.md");
|
|
1083
1201
|
}
|
|
1084
|
-
const rulesDir =
|
|
1202
|
+
const rulesDir = join10(apmDir, "rules");
|
|
1085
1203
|
const ruleNames = syncBaseRules(rulesDir);
|
|
1086
1204
|
for (const name of ruleNames) {
|
|
1087
1205
|
console.log(`[apm] \u5DF2\u540C\u6B65\u57FA\u7840\u89C4\u5219: rules/${name}`);
|
|
1088
1206
|
}
|
|
1089
|
-
const skillsDir =
|
|
1207
|
+
const skillsDir = join10(apmDir, "skills");
|
|
1090
1208
|
mkdirSync4(skillsDir, { recursive: true });
|
|
1091
1209
|
const baseNames = syncBaseSkills(skillsDir);
|
|
1092
1210
|
for (const name of baseNames) {
|
|
@@ -1112,15 +1230,35 @@ async function runUpdateSkills() {
|
|
|
1112
1230
|
);
|
|
1113
1231
|
}
|
|
1114
1232
|
|
|
1233
|
+
// src/commands/sync-deploy-config.ts
|
|
1234
|
+
import { existsSync as existsSync7, statSync as statSync4 } from "fs";
|
|
1235
|
+
async function runSyncDeployConfig() {
|
|
1236
|
+
const workdir = resolveWorkdirPath();
|
|
1237
|
+
const apmDir = workspaceApmDir(workdir);
|
|
1238
|
+
if (!existsSync7(apmDir)) {
|
|
1239
|
+
console.error("[apm] \u672A\u627E\u5230 .apm \u76EE\u5F55\uFF0C\u8BF7\u5148\u6267\u884C apm init");
|
|
1240
|
+
process.exit(1);
|
|
1241
|
+
}
|
|
1242
|
+
const apmStat = statSync4(apmDir);
|
|
1243
|
+
if (!apmStat.isDirectory()) {
|
|
1244
|
+
throw new Error(`[apm] \u8DEF\u5F84\u5DF2\u5B58\u5728\u4F46\u4E0D\u662F\u76EE\u5F55: ${apmDir}`);
|
|
1245
|
+
}
|
|
1246
|
+
await ensureLoggedConfig();
|
|
1247
|
+
const result = await syncRemoteDeploymentConfig(workdir, apmDir);
|
|
1248
|
+
if (!result.synced) {
|
|
1249
|
+
process.exit(1);
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1115
1253
|
// src/commands/sync-document.ts
|
|
1116
|
-
import { existsSync as
|
|
1254
|
+
import { existsSync as existsSync9 } from "fs";
|
|
1117
1255
|
import { basename as basename3 } from "path";
|
|
1118
1256
|
|
|
1119
1257
|
// src/commands/sync-session-documents.ts
|
|
1120
|
-
import { existsSync as
|
|
1121
|
-
import { join as
|
|
1258
|
+
import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync6 } from "fs";
|
|
1259
|
+
import { join as join11 } from "path";
|
|
1122
1260
|
function listLocalMarkdownFiles(docsDir) {
|
|
1123
|
-
if (!
|
|
1261
|
+
if (!existsSync8(docsDir)) {
|
|
1124
1262
|
return [];
|
|
1125
1263
|
}
|
|
1126
1264
|
return readdirSync3(docsDir).filter(
|
|
@@ -1135,7 +1273,7 @@ function remoteDocumentByLocalName(remoteDocuments, localFileName) {
|
|
|
1135
1273
|
});
|
|
1136
1274
|
}
|
|
1137
1275
|
async function upsertLocalDocumentFile(api, sessionId, docsDir, fileName) {
|
|
1138
|
-
const absPath =
|
|
1276
|
+
const absPath = join11(docsDir, fileName);
|
|
1139
1277
|
const content = readFileSync6(absPath, "utf8");
|
|
1140
1278
|
const name = documentPlatformName(absPath);
|
|
1141
1279
|
return api.cli.upsertDocument({
|
|
@@ -1158,7 +1296,7 @@ async function syncSessionDocuments(cfg, sessionId, apmRoot, options) {
|
|
|
1158
1296
|
const remoteDocuments = options?.remoteDocuments ?? await api.cli.listDocuments({ sessionId: trimmedSessionId });
|
|
1159
1297
|
let synced = 0;
|
|
1160
1298
|
for (const fileName of localFiles) {
|
|
1161
|
-
const absPath =
|
|
1299
|
+
const absPath = join11(docsDir, fileName);
|
|
1162
1300
|
const content = readFileSync6(absPath, "utf8");
|
|
1163
1301
|
const remote = remoteDocumentByLocalName(remoteDocuments, fileName);
|
|
1164
1302
|
if (remote && remote.content === content) {
|
|
@@ -1192,7 +1330,7 @@ async function runSyncDocument(sessionId, options) {
|
|
|
1192
1330
|
process.exit(1);
|
|
1193
1331
|
}
|
|
1194
1332
|
const absPath = resolveSessionDocumentPath(trimmedSessionId, fileArg);
|
|
1195
|
-
if (!
|
|
1333
|
+
if (!existsSync9(absPath)) {
|
|
1196
1334
|
const docsDir2 = sessionDocsDir(trimmedSessionId);
|
|
1197
1335
|
console.error(
|
|
1198
1336
|
`[apm] \u6587\u6863\u4E0D\u5B58\u5728: ${absPath}
|
|
@@ -1592,13 +1730,13 @@ ${JSON.stringify(event, null, 2)}
|
|
|
1592
1730
|
}
|
|
1593
1731
|
|
|
1594
1732
|
// src/commands/connect/agent-session-registry.ts
|
|
1595
|
-
import { existsSync as
|
|
1733
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync8 } from "node:fs";
|
|
1596
1734
|
import { dirname as dirname3, resolve as resolve3 } from "node:path";
|
|
1597
1735
|
function registryPath(workdir, sessionId) {
|
|
1598
1736
|
return resolve3(workdir, ".apm", "sessions", sessionId, "cursor-agents.json");
|
|
1599
1737
|
}
|
|
1600
1738
|
function readRegistry(path10) {
|
|
1601
|
-
if (!
|
|
1739
|
+
if (!existsSync10(path10)) {
|
|
1602
1740
|
return {};
|
|
1603
1741
|
}
|
|
1604
1742
|
try {
|
|
@@ -1620,7 +1758,7 @@ function readRegistry(path10) {
|
|
|
1620
1758
|
}
|
|
1621
1759
|
function writeRegistry(path10, registry) {
|
|
1622
1760
|
mkdirSync5(dirname3(path10), { recursive: true });
|
|
1623
|
-
|
|
1761
|
+
writeFileSync8(path10, `${JSON.stringify(registry, null, 2)}
|
|
1624
1762
|
`, "utf8");
|
|
1625
1763
|
}
|
|
1626
1764
|
function loadSessionAgentId(workdir, sessionId, user) {
|
|
@@ -1756,6 +1894,16 @@ function createAppendMessageCustomTools(cfg, messageId) {
|
|
|
1756
1894
|
};
|
|
1757
1895
|
}
|
|
1758
1896
|
|
|
1897
|
+
// src/commands/connect/playwright-mcp.ts
|
|
1898
|
+
function createPlaywrightMcpServers() {
|
|
1899
|
+
return {
|
|
1900
|
+
playwright: {
|
|
1901
|
+
command: "npx",
|
|
1902
|
+
args: ["@playwright/mcp@latest", "--browser", "chrome", "--vision"]
|
|
1903
|
+
}
|
|
1904
|
+
};
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1759
1907
|
// src/commands/connect/cursor-agent.ts
|
|
1760
1908
|
setMaxListeners2(50);
|
|
1761
1909
|
installAbortSignalDebug();
|
|
@@ -1783,7 +1931,8 @@ async function obtainAgent(ctx) {
|
|
|
1783
1931
|
model: { id: ctx.model || "default" },
|
|
1784
1932
|
local: {
|
|
1785
1933
|
cwd: ctx.cwd
|
|
1786
|
-
}
|
|
1934
|
+
},
|
|
1935
|
+
mcpServers: createPlaywrightMcpServers()
|
|
1787
1936
|
};
|
|
1788
1937
|
const savedAgentId = ctx.user ? loadSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user) : void 0;
|
|
1789
1938
|
if (savedAgentId) {
|
|
@@ -1851,6 +2000,7 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
1851
2000
|
logAbortSignalStats(signal, "runCursorAgent:after-addListener");
|
|
1852
2001
|
try {
|
|
1853
2002
|
const run = await agent.send(prompt, {
|
|
2003
|
+
mcpServers: createPlaywrightMcpServers(),
|
|
1854
2004
|
local: {
|
|
1855
2005
|
customTools: createAppendMessageCustomTools(cfg, ctx.messageId)
|
|
1856
2006
|
}
|
|
@@ -2226,14 +2376,14 @@ async function runConnect(options) {
|
|
|
2226
2376
|
import path5 from "node:path";
|
|
2227
2377
|
|
|
2228
2378
|
// src/commands/deploy/internal/apm-config.ts
|
|
2229
|
-
import { existsSync as
|
|
2379
|
+
import { existsSync as existsSync11, readFileSync as readFileSync8 } from "node:fs";
|
|
2230
2380
|
import { resolve as resolve4 } from "node:path";
|
|
2231
2381
|
function loadApmConfig(options) {
|
|
2232
2382
|
const p = resolve4(
|
|
2233
2383
|
process.cwd(),
|
|
2234
2384
|
options?.configPath ?? resolve4(workspaceApmDir(), "apm.config.json")
|
|
2235
2385
|
);
|
|
2236
|
-
if (!
|
|
2386
|
+
if (!existsSync11(p)) {
|
|
2237
2387
|
console.error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF1A${p}`);
|
|
2238
2388
|
process.exit(1);
|
|
2239
2389
|
}
|
|
@@ -2360,7 +2510,7 @@ import path4 from "node:path";
|
|
|
2360
2510
|
import Docker from "dockerode";
|
|
2361
2511
|
|
|
2362
2512
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
|
|
2363
|
-
import { existsSync as
|
|
2513
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "node:fs";
|
|
2364
2514
|
import path from "node:path";
|
|
2365
2515
|
function asOptionalTlsBuffer(value) {
|
|
2366
2516
|
if (typeof value !== "string") {
|
|
@@ -2372,7 +2522,7 @@ function asOptionalTlsBuffer(value) {
|
|
|
2372
2522
|
if (normalized === "") {
|
|
2373
2523
|
return void 0;
|
|
2374
2524
|
}
|
|
2375
|
-
if (
|
|
2525
|
+
if (existsSync12(normalized)) {
|
|
2376
2526
|
return readFileSync9(normalized);
|
|
2377
2527
|
}
|
|
2378
2528
|
const looksLikePath = /[\\/]/.test(normalized) || normalized.endsWith(".pem");
|
|
@@ -2583,7 +2733,7 @@ var DockerodeClient = class {
|
|
|
2583
2733
|
var createDockerodeClient = (config) => new DockerodeClient(config);
|
|
2584
2734
|
|
|
2585
2735
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
|
|
2586
|
-
import { existsSync as
|
|
2736
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10, statSync as statSync5 } from "node:fs";
|
|
2587
2737
|
import path2 from "node:path";
|
|
2588
2738
|
function stripSurroundingQuotes(value) {
|
|
2589
2739
|
const t = value.trim();
|
|
@@ -2600,7 +2750,7 @@ function loadEnvFromFile(envFilePath) {
|
|
|
2600
2750
|
return {};
|
|
2601
2751
|
}
|
|
2602
2752
|
const targetPath = path2.resolve(envFilePath);
|
|
2603
|
-
if (!
|
|
2753
|
+
if (!existsSync13(targetPath) || !statSync5(targetPath).isFile()) {
|
|
2604
2754
|
return {};
|
|
2605
2755
|
}
|
|
2606
2756
|
const raw = readFileSync10(targetPath, "utf-8");
|
|
@@ -2774,12 +2924,12 @@ function dockerPushImage(params, cwd) {
|
|
|
2774
2924
|
}
|
|
2775
2925
|
|
|
2776
2926
|
// src/commands/deploy/internal/backend-deploy/resolve-dockerfile.ts
|
|
2777
|
-
import { existsSync as
|
|
2927
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
2778
2928
|
import path3 from "node:path";
|
|
2779
2929
|
function resolveDockerBuildPaths(cwd) {
|
|
2780
2930
|
const dockerfilePath = path3.join(cwd, "Dockerfile");
|
|
2781
2931
|
Logger.info(`\u67E5\u627EDockerfile\u6587\u4EF6\uFF0C\u8DEF\u5F84: ${dockerfilePath}`);
|
|
2782
|
-
if (!
|
|
2932
|
+
if (!existsSync14(dockerfilePath)) {
|
|
2783
2933
|
throw new Error(`Dockerfile \u4E0D\u5B58\u5728\uFF1A${dockerfilePath}`);
|
|
2784
2934
|
}
|
|
2785
2935
|
Logger.info("\u2713 Dockerfile \u5B58\u5728");
|
|
@@ -2908,14 +3058,14 @@ import { copyFile, readdir as readdir2, stat } from "node:fs/promises";
|
|
|
2908
3058
|
import path7 from "node:path";
|
|
2909
3059
|
|
|
2910
3060
|
// src/commands/deploy/internal/minio.ts
|
|
2911
|
-
import { statSync as
|
|
3061
|
+
import { statSync as statSync6 } from "node:fs";
|
|
2912
3062
|
import { readdir, readFile } from "node:fs/promises";
|
|
2913
3063
|
import path6 from "node:path";
|
|
2914
3064
|
import * as Minio from "minio";
|
|
2915
3065
|
var DEFAULT_MAX_FILE_SIZE_MB = 50;
|
|
2916
3066
|
async function isDirectoryPath(dir) {
|
|
2917
3067
|
try {
|
|
2918
|
-
const st =
|
|
3068
|
+
const st = statSync6(dir);
|
|
2919
3069
|
return st.isDirectory();
|
|
2920
3070
|
} catch {
|
|
2921
3071
|
return false;
|
|
@@ -2945,7 +3095,7 @@ async function collectFiles(root) {
|
|
|
2945
3095
|
if (e.isDirectory()) {
|
|
2946
3096
|
await walk(abs, rel);
|
|
2947
3097
|
} else if (e.isFile()) {
|
|
2948
|
-
const st =
|
|
3098
|
+
const st = statSync6(abs);
|
|
2949
3099
|
out.push({
|
|
2950
3100
|
absPath: abs,
|
|
2951
3101
|
relativePath: rel.replace(/\\/g, "/"),
|
|
@@ -3388,7 +3538,9 @@ function buildProgram() {
|
|
|
3388
3538
|
).option("--api-key <key>", "\u5BA2\u6237\u673A API Key\uFF08cm_ \u5F00\u5934\uFF09").option("--server <url>", "API \u6839\u5730\u5740\uFF0C\u4F8B\u5982 http://127.0.0.1:3000").action(async (opts) => {
|
|
3389
3539
|
await runLogin(opts);
|
|
3390
3540
|
});
|
|
3391
|
-
program.command("init").description(
|
|
3541
|
+
program.command("init").description(
|
|
3542
|
+
"\u5728\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u521D\u59CB\u5316 .apm \u6A21\u677F\uFF08\u82E5 .apm \u5DF2\u5B58\u5728\u4E14\u975E\u7A7A\u5219\u62A5\u9519\uFF09\uFF1B\u5DF2\u767B\u5F55\u4E14\u5E73\u53F0\u6709\u5339\u914D\u90E8\u7F72\u914D\u7F6E\u65F6\u4F1A\u540C\u6B65 apm.config.json \u4E0E deploy/README.md"
|
|
3543
|
+
).option("--name <name>", "\u5DE5\u4F5C\u76EE\u5F55\u540D\u79F0").action(async (opts) => {
|
|
3392
3544
|
await runInit(opts.name);
|
|
3393
3545
|
});
|
|
3394
3546
|
program.command("update").description(
|
|
@@ -3401,6 +3553,11 @@ function buildProgram() {
|
|
|
3401
3553
|
).action(async () => {
|
|
3402
3554
|
await runUpdateSkills();
|
|
3403
3555
|
});
|
|
3556
|
+
program.command("sync-deploy-config").description(
|
|
3557
|
+
"\u4ECE\u5E73\u53F0\u62C9\u53D6\u90E8\u7F72\u914D\u7F6E\uFF0C\u8986\u76D6 .apm/apm.config.json \u4E0E .apm/deploy/README.md\uFF08\u9700\u5DF2 login \u4E14\u5DE5\u4F5C\u7A7A\u95F4\u5DF2\u767B\u8BB0\u5E76\u7ED1\u5B9A\u4ED3\u5E93\uFF09"
|
|
3558
|
+
).action(async () => {
|
|
3559
|
+
await runSyncDeployConfig();
|
|
3560
|
+
});
|
|
3404
3561
|
program.command("pull").description(
|
|
3405
3562
|
"\u62C9\u53D6\u6C9F\u901A\u7FA4\u6570\u636E\u5230 .apm/sessions/<sessionId>/\uFF08session.yaml\u3001RULE.md\u3001TASK.md\u3001TODO.md\u3001docs\u3001attachments\uFF09"
|
|
3406
3563
|
).argument("<sessionId>", "\u6C9F\u901A\u7FA4 ID").action(async (sessionId) => {
|