ai-project-manage-cli 6.0.44 → 6.0.45
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 +230 -110
- 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,94 @@ function createApmApiClient(cfg) {
|
|
|
395
384
|
});
|
|
396
385
|
}
|
|
397
386
|
|
|
387
|
+
// src/deployment-config-sync.ts
|
|
388
|
+
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";
|
|
389
|
+
async function syncRemoteDeploymentConfig(workdirPath, apmDir) {
|
|
390
|
+
const cfg = await tryReadApmConfig();
|
|
391
|
+
if (!cfg || !resolveApiKey(cfg)) {
|
|
392
|
+
console.log(
|
|
393
|
+
"[apm] \u672A\u68C0\u6D4B\u5230\u767B\u5F55\u4FE1\u606F\uFF0C\u8DF3\u8FC7\u5E73\u53F0\u90E8\u7F72\u914D\u7F6E\u540C\u6B65\uFF08\u4FDD\u7559\u6A21\u677F apm.config.json\uFF09\u3002\n[apm] \u8BF7\u5148\u6267\u884C apm login\uFF0C\u518D\u6267\u884C apm sync-deploy-config \u62C9\u53D6\u6700\u65B0\u914D\u7F6E\u3002"
|
|
394
|
+
);
|
|
395
|
+
return { synced: false, repositoryId: null };
|
|
396
|
+
}
|
|
397
|
+
const api = createApmApiClient(cfg);
|
|
398
|
+
const baseline = await api.cli.workspaceBaseline({ workdirPath });
|
|
399
|
+
const repositoryId = baseline.repositoryId;
|
|
400
|
+
if (!repositoryId) {
|
|
401
|
+
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`;
|
|
402
|
+
console.log(
|
|
403
|
+
`[apm] \u672A\u80FD\u540C\u6B65\u5E73\u53F0\u90E8\u7F72\u914D\u7F6E\uFF0C\u4FDD\u7559\u6A21\u677F apm.config.json\u3002
|
|
404
|
+
${detail}
|
|
405
|
+
[apm] ${SYNC_HINT}`
|
|
406
|
+
);
|
|
407
|
+
return { synced: false, repositoryId: null };
|
|
408
|
+
}
|
|
409
|
+
const { config } = await api.cli.getDeploymentConfiguration({ repositoryId });
|
|
410
|
+
if (!config) {
|
|
411
|
+
console.log(
|
|
412
|
+
`[apm] \u672A\u627E\u5230\u5173\u8054\u4ED3\u5E93\u7684\u90E8\u7F72\u914D\u7F6E\uFF0C\u4FDD\u7559\u6A21\u677F apm.config.json\uFF08repositoryId\uFF1A${repositoryId}\uFF09\u3002
|
|
413
|
+
[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`
|
|
414
|
+
);
|
|
415
|
+
return { synced: false, repositoryId };
|
|
416
|
+
}
|
|
417
|
+
let parsed;
|
|
418
|
+
try {
|
|
419
|
+
parsed = JSON.parse(config.content);
|
|
420
|
+
} catch {
|
|
421
|
+
console.warn(
|
|
422
|
+
`[apm] \u8FDC\u7A0B\u90E8\u7F72\u914D\u7F6E\u300C${config.name}\u300DJSON \u65E0\u6548\uFF0C\u4F7F\u7528\u6A21\u677F\u90E8\u7F72\u914D\u7F6E`
|
|
423
|
+
);
|
|
424
|
+
return { synced: false, repositoryId };
|
|
425
|
+
}
|
|
426
|
+
const targetApmDir = apmDir ?? workspaceApmDir(workdirPath);
|
|
427
|
+
const apmConfigPath = toFsPath(join3(targetApmDir, "apm.config.json"));
|
|
428
|
+
writeFileSync2(apmConfigPath, `${JSON.stringify(parsed, null, 2)}
|
|
429
|
+
`, "utf8");
|
|
430
|
+
const deployDir = join3(targetApmDir, "deploy");
|
|
431
|
+
await ensureDirExists(deployDir);
|
|
432
|
+
writeFileSync2(
|
|
433
|
+
toFsPath(join3(deployDir, "README.md")),
|
|
434
|
+
config.deploymentDoc ?? "",
|
|
435
|
+
"utf8"
|
|
436
|
+
);
|
|
437
|
+
console.log(`[apm] \u5DF2\u540C\u6B65\u5E73\u53F0\u90E8\u7F72\u914D\u7F6E: ${config.name}`);
|
|
438
|
+
console.log("[apm] \u5DF2\u5199\u5165 .apm/apm.config.json \u4E0E .apm/deploy/README.md");
|
|
439
|
+
return { synced: true, repositoryId, configName: config.name };
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// src/commands/init.ts
|
|
443
|
+
async function runInit(name) {
|
|
444
|
+
const workdir = resolveWorkdirPath();
|
|
445
|
+
await ensureWorkspaceApmDirForInit(workdir);
|
|
446
|
+
const apmDir = workspaceApmDir(workdir);
|
|
447
|
+
await copyTemplateFiles(apmDir, workdir);
|
|
448
|
+
const syncResult = await syncRemoteDeploymentConfig(workdir, apmDir);
|
|
449
|
+
const trimmedName = name?.trim();
|
|
450
|
+
if (trimmedName) {
|
|
451
|
+
const apmConfigPath = toFsPath(join4(apmDir, "apm.config.json"));
|
|
452
|
+
const config = readFileSync2(apmConfigPath, "utf8");
|
|
453
|
+
const configJson = JSON.parse(config);
|
|
454
|
+
configJson.name = trimmedName;
|
|
455
|
+
writeFileSync3(
|
|
456
|
+
apmConfigPath,
|
|
457
|
+
`${JSON.stringify(configJson, null, 2)}
|
|
458
|
+
`,
|
|
459
|
+
"utf8"
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
console.log(`[apm] \u5DF2\u521D\u59CB\u5316\u5DE5\u4F5C\u533A\uFF1A${apmDir}`);
|
|
463
|
+
console.log(`[apm] \u5DE5\u4F5C\u76EE\u5F55\u8DEF\u5F84\uFF1A${workdir}`);
|
|
464
|
+
if (!syncResult.synced) {
|
|
465
|
+
console.log(
|
|
466
|
+
"[apm] \u5F53\u524D apm.config.json \u4E3A\u6A21\u677F\u9ED8\u8BA4\u503C\uFF1B\u5B8C\u6210\u5E73\u53F0\u767B\u8BB0\u540E\u6267\u884C apm sync-deploy-config \u62C9\u53D6\u90E8\u7F72\u914D\u7F6E"
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
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");
|
|
470
|
+
}
|
|
471
|
+
|
|
398
472
|
// src/commands/login.ts
|
|
473
|
+
import { existsSync as existsSync2 } from "fs";
|
|
474
|
+
import { ApiError } from "listpage-http";
|
|
399
475
|
async function runLogin(opts) {
|
|
400
476
|
const baseUrl = (opts.server?.trim() || process.env.AI_PM_SERVER?.trim() || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
401
477
|
const apiKey = (opts.apiKey?.trim() || process.env.APM_API_KEY?.trim() || "").replace(/^Bearer\s+/i, "");
|
|
@@ -447,6 +523,11 @@ async function runLogin(opts) {
|
|
|
447
523
|
2
|
|
448
524
|
)
|
|
449
525
|
);
|
|
526
|
+
const workdir = resolveWorkdirPath();
|
|
527
|
+
const apmDir = workspaceApmDir(workdir);
|
|
528
|
+
if (existsSync2(apmDir)) {
|
|
529
|
+
await syncRemoteDeploymentConfig(workdir, apmDir);
|
|
530
|
+
}
|
|
450
531
|
}
|
|
451
532
|
|
|
452
533
|
// src/commands/branch.ts
|
|
@@ -617,8 +698,8 @@ async function runBranch(sessionId, options = {}) {
|
|
|
617
698
|
}
|
|
618
699
|
|
|
619
700
|
// src/commands/pull.ts
|
|
620
|
-
import { writeFileSync as
|
|
621
|
-
import { join as
|
|
701
|
+
import { writeFileSync as writeFileSync7 } from "fs";
|
|
702
|
+
import { join as join8 } from "path";
|
|
622
703
|
import { stringify as yamlStringify } from "yaml";
|
|
623
704
|
|
|
624
705
|
// src/session-messages-xml.ts
|
|
@@ -651,8 +732,8 @@ function formatSessionMessagesXml(sessionId, messages) {
|
|
|
651
732
|
}
|
|
652
733
|
|
|
653
734
|
// src/commands/sync-session-attachments.ts
|
|
654
|
-
import { existsSync as
|
|
655
|
-
import { join as
|
|
735
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
736
|
+
import { join as join5 } from "path";
|
|
656
737
|
var MANIFEST_FILE = ".sync-manifest.json";
|
|
657
738
|
async function downloadAttachment(cfg, attachmentId) {
|
|
658
739
|
const base = cfg.baseUrl.trim().replace(/\/+$/, "");
|
|
@@ -666,8 +747,8 @@ async function downloadAttachment(cfg, attachmentId) {
|
|
|
666
747
|
return Buffer.from(await res.arrayBuffer());
|
|
667
748
|
}
|
|
668
749
|
function loadManifest(dir) {
|
|
669
|
-
const path10 =
|
|
670
|
-
if (!
|
|
750
|
+
const path10 = join5(dir, MANIFEST_FILE);
|
|
751
|
+
if (!existsSync3(path10)) {
|
|
671
752
|
return { version: 1, attachments: {} };
|
|
672
753
|
}
|
|
673
754
|
try {
|
|
@@ -682,21 +763,21 @@ function loadManifest(dir) {
|
|
|
682
763
|
return { version: 1, attachments: {} };
|
|
683
764
|
}
|
|
684
765
|
function saveManifest(dir, manifest) {
|
|
685
|
-
|
|
686
|
-
|
|
766
|
+
writeFileSync4(
|
|
767
|
+
join5(dir, MANIFEST_FILE),
|
|
687
768
|
`${JSON.stringify(manifest, null, 2)}
|
|
688
769
|
`,
|
|
689
770
|
"utf8"
|
|
690
771
|
);
|
|
691
772
|
}
|
|
692
773
|
function isAttachmentUpToDate(entry, item, dest) {
|
|
693
|
-
if (!entry || !
|
|
774
|
+
if (!entry || !existsSync3(dest)) return false;
|
|
694
775
|
if (entry.name !== item.name) return false;
|
|
695
776
|
const createdAt = item.createdAt ?? "";
|
|
696
777
|
return entry.createdAt === createdAt;
|
|
697
778
|
}
|
|
698
779
|
async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
|
|
699
|
-
const dir =
|
|
780
|
+
const dir = join5(sessionDir(sessionId, apmRoot), SESSION_ATTACHMENTS_SUBDIR);
|
|
700
781
|
await ensureDirExists(dir);
|
|
701
782
|
if (attachments.length === 0) {
|
|
702
783
|
saveManifest(dir, { version: 1, attachments: {} });
|
|
@@ -705,7 +786,7 @@ async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
|
|
|
705
786
|
const manifest = loadManifest(dir);
|
|
706
787
|
const nextManifest = { version: 1, attachments: {} };
|
|
707
788
|
for (const item of attachments) {
|
|
708
|
-
const dest =
|
|
789
|
+
const dest = join5(dir, item.name);
|
|
709
790
|
const entry = manifest.attachments[item.id];
|
|
710
791
|
const createdAt = item.createdAt ?? "";
|
|
711
792
|
if (isAttachmentUpToDate(entry, item, dest)) {
|
|
@@ -716,7 +797,7 @@ async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
|
|
|
716
797
|
continue;
|
|
717
798
|
}
|
|
718
799
|
const buffer = await downloadAttachment(cfg, item.id);
|
|
719
|
-
|
|
800
|
+
writeFileSync4(dest, buffer);
|
|
720
801
|
nextManifest.attachments[item.id] = {
|
|
721
802
|
name: item.name,
|
|
722
803
|
createdAt
|
|
@@ -727,46 +808,46 @@ async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
|
|
|
727
808
|
}
|
|
728
809
|
|
|
729
810
|
// src/rules-sync.ts
|
|
730
|
-
import { basename as basename2, extname as extname2, join as
|
|
731
|
-
import { existsSync as
|
|
811
|
+
import { basename as basename2, extname as extname2, join as join7 } from "path";
|
|
812
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
732
813
|
|
|
733
814
|
// src/skills-sync.ts
|
|
734
815
|
import {
|
|
735
816
|
copyFileSync as copyFileSync2,
|
|
736
817
|
cpSync,
|
|
737
|
-
existsSync as
|
|
818
|
+
existsSync as existsSync4,
|
|
738
819
|
mkdirSync as mkdirSync3,
|
|
739
820
|
readdirSync as readdirSync2,
|
|
740
821
|
rmSync,
|
|
741
822
|
statSync as statSync2,
|
|
742
|
-
writeFileSync as
|
|
823
|
+
writeFileSync as writeFileSync5
|
|
743
824
|
} from "fs";
|
|
744
|
-
import { join as
|
|
745
|
-
var AGENTS_TEMPLATE_PATH =
|
|
746
|
-
var BASE_SKILLS_TEMPLATE_DIR =
|
|
747
|
-
var BASE_RULES_TEMPLATE_DIR =
|
|
825
|
+
import { join as join6 } from "path";
|
|
826
|
+
var AGENTS_TEMPLATE_PATH = join6(CLI_TEMPLATE_DIR, "AGENTS.md");
|
|
827
|
+
var BASE_SKILLS_TEMPLATE_DIR = join6(CLI_TEMPLATE_DIR, "skills");
|
|
828
|
+
var BASE_RULES_TEMPLATE_DIR = join6(CLI_TEMPLATE_DIR, "rules");
|
|
748
829
|
function sanitizeSkillDirName(name) {
|
|
749
830
|
const trimmed = name.trim();
|
|
750
831
|
if (!trimmed) return "skill";
|
|
751
832
|
return trimmed.replace(/[/\\:*?"<>|]/g, "_");
|
|
752
833
|
}
|
|
753
834
|
function listBaseSkillDirNames() {
|
|
754
|
-
if (!
|
|
835
|
+
if (!existsSync4(BASE_SKILLS_TEMPLATE_DIR)) return [];
|
|
755
836
|
return readdirSync2(BASE_SKILLS_TEMPLATE_DIR).filter((name) => {
|
|
756
|
-
const path10 =
|
|
837
|
+
const path10 = join6(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
757
838
|
return statSync2(path10).isDirectory();
|
|
758
839
|
});
|
|
759
840
|
}
|
|
760
841
|
function syncAgentsGuide(apmDir) {
|
|
761
|
-
if (!
|
|
842
|
+
if (!existsSync4(AGENTS_TEMPLATE_PATH)) return false;
|
|
762
843
|
mkdirSync3(apmDir, { recursive: true });
|
|
763
|
-
copyFileSync2(AGENTS_TEMPLATE_PATH,
|
|
844
|
+
copyFileSync2(AGENTS_TEMPLATE_PATH, join6(apmDir, "AGENTS.md"));
|
|
764
845
|
return true;
|
|
765
846
|
}
|
|
766
847
|
function listBaseRuleFileNames() {
|
|
767
|
-
if (!
|
|
848
|
+
if (!existsSync4(BASE_RULES_TEMPLATE_DIR)) return [];
|
|
768
849
|
return readdirSync2(BASE_RULES_TEMPLATE_DIR).filter((name) => {
|
|
769
|
-
const path10 =
|
|
850
|
+
const path10 = join6(BASE_RULES_TEMPLATE_DIR, name);
|
|
770
851
|
return statSync2(path10).isFile();
|
|
771
852
|
});
|
|
772
853
|
}
|
|
@@ -774,8 +855,8 @@ function syncBaseRules(rulesDir) {
|
|
|
774
855
|
mkdirSync3(rulesDir, { recursive: true });
|
|
775
856
|
const names = listBaseRuleFileNames();
|
|
776
857
|
for (const name of names) {
|
|
777
|
-
const src =
|
|
778
|
-
const dest =
|
|
858
|
+
const src = join6(BASE_RULES_TEMPLATE_DIR, name);
|
|
859
|
+
const dest = join6(rulesDir, name);
|
|
779
860
|
copyFileSync2(src, dest);
|
|
780
861
|
}
|
|
781
862
|
return names;
|
|
@@ -784,8 +865,8 @@ function syncBaseSkills(skillsDir) {
|
|
|
784
865
|
mkdirSync3(skillsDir, { recursive: true });
|
|
785
866
|
const names = listBaseSkillDirNames();
|
|
786
867
|
for (const name of names) {
|
|
787
|
-
const src =
|
|
788
|
-
const dest =
|
|
868
|
+
const src = join6(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
869
|
+
const dest = join6(skillsDir, name);
|
|
789
870
|
cpSync(src, dest, { recursive: true, force: true });
|
|
790
871
|
}
|
|
791
872
|
return names;
|
|
@@ -802,15 +883,15 @@ function syncSupplementarySkills(skillsDir, list) {
|
|
|
802
883
|
skipped.push(dirName);
|
|
803
884
|
continue;
|
|
804
885
|
}
|
|
805
|
-
const skillDir =
|
|
886
|
+
const skillDir = join6(skillsDir, dirName);
|
|
806
887
|
mkdirSync3(skillDir, { recursive: true });
|
|
807
|
-
|
|
888
|
+
writeFileSync5(join6(skillDir, "SKILL.md"), skill.content ?? "", "utf8");
|
|
808
889
|
written.push(dirName);
|
|
809
890
|
}
|
|
810
891
|
const removed = [];
|
|
811
|
-
if (!
|
|
892
|
+
if (!existsSync4(skillsDir)) return { written, skipped, removed };
|
|
812
893
|
for (const entry of readdirSync2(skillsDir)) {
|
|
813
|
-
const full =
|
|
894
|
+
const full = join6(skillsDir, entry);
|
|
814
895
|
if (!statSync2(full).isDirectory()) continue;
|
|
815
896
|
if (baseNames.has(entry)) continue;
|
|
816
897
|
if (apiDirNames.has(entry)) continue;
|
|
@@ -830,8 +911,8 @@ function ruleLocalFileName(ruleName) {
|
|
|
830
911
|
return `${sanitized}.md`;
|
|
831
912
|
}
|
|
832
913
|
function loadManifest2(rulesDir) {
|
|
833
|
-
const path10 =
|
|
834
|
-
if (!
|
|
914
|
+
const path10 = join7(rulesDir, MANIFEST_FILE2);
|
|
915
|
+
if (!existsSync5(toFsPath(path10))) {
|
|
835
916
|
return { version: 1, rules: {} };
|
|
836
917
|
}
|
|
837
918
|
try {
|
|
@@ -846,8 +927,8 @@ function loadManifest2(rulesDir) {
|
|
|
846
927
|
return { version: 1, rules: {} };
|
|
847
928
|
}
|
|
848
929
|
function saveManifest2(rulesDir, manifest) {
|
|
849
|
-
|
|
850
|
-
toFsPath(
|
|
930
|
+
writeFileSync6(
|
|
931
|
+
toFsPath(join7(rulesDir, MANIFEST_FILE2)),
|
|
851
932
|
`${JSON.stringify(manifest, null, 2)}
|
|
852
933
|
`,
|
|
853
934
|
"utf8"
|
|
@@ -857,7 +938,7 @@ function isBaseRuleFileName(fileName) {
|
|
|
857
938
|
return listBaseRuleFileNames().includes(basename2(fileName));
|
|
858
939
|
}
|
|
859
940
|
function isRuleUpToDate(entry, rule, dest) {
|
|
860
|
-
if (!entry || !
|
|
941
|
+
if (!entry || !existsSync5(toFsPath(dest))) return false;
|
|
861
942
|
if (entry.fileName !== ruleLocalFileName(rule.name)) return false;
|
|
862
943
|
const updatedAt = rule.updatedAt ?? "";
|
|
863
944
|
if (entry.updatedAt !== updatedAt) return false;
|
|
@@ -868,7 +949,7 @@ async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
|
|
|
868
949
|
const api = createApmApiClient(cfg);
|
|
869
950
|
const baseline = await api.cli.branchBaseline({ sessionId, workdirPath });
|
|
870
951
|
const repositoryId = baseline.repositoryId;
|
|
871
|
-
const rulesDir =
|
|
952
|
+
const rulesDir = join7(apmRoot ?? workspaceApmDir(workdirPath), "rules");
|
|
872
953
|
await ensureDirExists(rulesDir);
|
|
873
954
|
if (!repositoryId) {
|
|
874
955
|
console.log(
|
|
@@ -885,7 +966,7 @@ async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
|
|
|
885
966
|
for (const rule of list) {
|
|
886
967
|
remoteIds.add(rule.id);
|
|
887
968
|
const fileName = ruleLocalFileName(rule.name);
|
|
888
|
-
const dest =
|
|
969
|
+
const dest = join7(rulesDir, fileName);
|
|
889
970
|
const entry = manifest.rules[rule.id];
|
|
890
971
|
const updatedAt = rule.updatedAt ?? "";
|
|
891
972
|
if (isRuleUpToDate(entry, rule, dest)) {
|
|
@@ -894,7 +975,7 @@ async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
|
|
|
894
975
|
console.log(`[apm] \u89C4\u5219\u65E0\u53D8\u5316\uFF0C\u5DF2\u8DF3\u8FC7: rules/${fileName}`);
|
|
895
976
|
continue;
|
|
896
977
|
}
|
|
897
|
-
|
|
978
|
+
writeFileSync6(toFsPath(dest), rule.content ?? "", "utf8");
|
|
898
979
|
nextManifest.rules[rule.id] = { fileName, updatedAt };
|
|
899
980
|
written.push(fileName);
|
|
900
981
|
console.log(`[apm] \u5DF2\u540C\u6B65\u5E73\u53F0\u89C4\u5219: rules/${fileName}`);
|
|
@@ -903,8 +984,8 @@ async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
|
|
|
903
984
|
for (const [ruleId, entry] of Object.entries(manifest.rules)) {
|
|
904
985
|
if (remoteIds.has(ruleId)) continue;
|
|
905
986
|
if (isBaseRuleFileName(entry.fileName)) continue;
|
|
906
|
-
const dest =
|
|
907
|
-
if (
|
|
987
|
+
const dest = join7(rulesDir, entry.fileName);
|
|
988
|
+
if (existsSync5(toFsPath(dest))) {
|
|
908
989
|
rmSync2(toFsPath(dest), { force: true });
|
|
909
990
|
}
|
|
910
991
|
removed.push(entry.fileName);
|
|
@@ -937,20 +1018,20 @@ async function runPull(sessionId, remoteWorkdir) {
|
|
|
937
1018
|
const dir = sessionDir(trimmedId, apmRoot);
|
|
938
1019
|
const docsDir = sessionDocsDir(trimmedId, apmRoot);
|
|
939
1020
|
await ensureDirExists(docsDir);
|
|
940
|
-
|
|
1021
|
+
writeFileSync7(
|
|
941
1022
|
sessionRulePath(trimmedId, apmRoot),
|
|
942
1023
|
detail.description ?? "",
|
|
943
1024
|
"utf8"
|
|
944
1025
|
);
|
|
945
|
-
|
|
1026
|
+
writeFileSync7(
|
|
946
1027
|
sessionTaskPath(trimmedId, apmRoot),
|
|
947
1028
|
detail.task.description ?? "",
|
|
948
1029
|
"utf8"
|
|
949
1030
|
);
|
|
950
|
-
|
|
1031
|
+
writeFileSync7(sessionTodoPath(trimmedId, apmRoot), detail.todo ?? "", "utf8");
|
|
951
1032
|
for (const doc of documents) {
|
|
952
1033
|
const fileName = documentLocalFileName(doc.name);
|
|
953
|
-
|
|
1034
|
+
writeFileSync7(join8(docsDir, fileName), doc.content ?? "", "utf8");
|
|
954
1035
|
}
|
|
955
1036
|
const sessionYaml = yamlStringify(
|
|
956
1037
|
{
|
|
@@ -967,13 +1048,13 @@ async function runPull(sessionId, remoteWorkdir) {
|
|
|
967
1048
|
},
|
|
968
1049
|
{ lineWidth: 0 }
|
|
969
1050
|
);
|
|
970
|
-
|
|
1051
|
+
writeFileSync7(
|
|
971
1052
|
sessionYamlPath(trimmedId, apmRoot),
|
|
972
1053
|
sessionYaml.endsWith("\n") ? sessionYaml : `${sessionYaml}
|
|
973
1054
|
`,
|
|
974
1055
|
"utf8"
|
|
975
1056
|
);
|
|
976
|
-
|
|
1057
|
+
writeFileSync7(
|
|
977
1058
|
sessionMessagesXmlPath(trimmedId, apmRoot),
|
|
978
1059
|
formatSessionMessagesXml(trimmedId, messages),
|
|
979
1060
|
"utf8"
|
|
@@ -989,13 +1070,13 @@ import { spawnSync } from "child_process";
|
|
|
989
1070
|
|
|
990
1071
|
// src/version.ts
|
|
991
1072
|
import { readFileSync as readFileSync5 } from "fs";
|
|
992
|
-
import { dirname as dirname2, join as
|
|
1073
|
+
import { dirname as dirname2, join as join9 } from "path";
|
|
993
1074
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
994
1075
|
var CLI_PACKAGE_NAME = "ai-project-manage-cli";
|
|
995
1076
|
function readCliVersion() {
|
|
996
1077
|
try {
|
|
997
1078
|
const dir = dirname2(fileURLToPath2(import.meta.url));
|
|
998
|
-
const pkgPath =
|
|
1079
|
+
const pkgPath = join9(dir, "..", "package.json");
|
|
999
1080
|
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
|
|
1000
1081
|
return pkg.version ?? "0.0.0";
|
|
1001
1082
|
} catch {
|
|
@@ -1063,11 +1144,11 @@ async function runUpdate() {
|
|
|
1063
1144
|
}
|
|
1064
1145
|
|
|
1065
1146
|
// src/commands/update-skills.ts
|
|
1066
|
-
import { existsSync as
|
|
1067
|
-
import { join as
|
|
1147
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync4, statSync as statSync3 } from "fs";
|
|
1148
|
+
import { join as join10 } from "path";
|
|
1068
1149
|
async function runUpdateSkills() {
|
|
1069
1150
|
const apmDir = workspaceApmDir();
|
|
1070
|
-
if (!
|
|
1151
|
+
if (!existsSync6(apmDir)) {
|
|
1071
1152
|
console.error("[apm] \u672A\u627E\u5230 .apm \u76EE\u5F55\uFF0C\u8BF7\u5148\u6267\u884C apm init");
|
|
1072
1153
|
process.exit(1);
|
|
1073
1154
|
}
|
|
@@ -1081,12 +1162,12 @@ async function runUpdateSkills() {
|
|
|
1081
1162
|
if (syncAgentsGuide(apmDir)) {
|
|
1082
1163
|
console.log("[apm] \u5DF2\u540C\u6B65 APM \u6307\u5357: .apm/AGENTS.md");
|
|
1083
1164
|
}
|
|
1084
|
-
const rulesDir =
|
|
1165
|
+
const rulesDir = join10(apmDir, "rules");
|
|
1085
1166
|
const ruleNames = syncBaseRules(rulesDir);
|
|
1086
1167
|
for (const name of ruleNames) {
|
|
1087
1168
|
console.log(`[apm] \u5DF2\u540C\u6B65\u57FA\u7840\u89C4\u5219: rules/${name}`);
|
|
1088
1169
|
}
|
|
1089
|
-
const skillsDir =
|
|
1170
|
+
const skillsDir = join10(apmDir, "skills");
|
|
1090
1171
|
mkdirSync4(skillsDir, { recursive: true });
|
|
1091
1172
|
const baseNames = syncBaseSkills(skillsDir);
|
|
1092
1173
|
for (const name of baseNames) {
|
|
@@ -1112,15 +1193,35 @@ async function runUpdateSkills() {
|
|
|
1112
1193
|
);
|
|
1113
1194
|
}
|
|
1114
1195
|
|
|
1196
|
+
// src/commands/sync-deploy-config.ts
|
|
1197
|
+
import { existsSync as existsSync7, statSync as statSync4 } from "fs";
|
|
1198
|
+
async function runSyncDeployConfig() {
|
|
1199
|
+
const workdir = resolveWorkdirPath();
|
|
1200
|
+
const apmDir = workspaceApmDir(workdir);
|
|
1201
|
+
if (!existsSync7(apmDir)) {
|
|
1202
|
+
console.error("[apm] \u672A\u627E\u5230 .apm \u76EE\u5F55\uFF0C\u8BF7\u5148\u6267\u884C apm init");
|
|
1203
|
+
process.exit(1);
|
|
1204
|
+
}
|
|
1205
|
+
const apmStat = statSync4(apmDir);
|
|
1206
|
+
if (!apmStat.isDirectory()) {
|
|
1207
|
+
throw new Error(`[apm] \u8DEF\u5F84\u5DF2\u5B58\u5728\u4F46\u4E0D\u662F\u76EE\u5F55: ${apmDir}`);
|
|
1208
|
+
}
|
|
1209
|
+
await ensureLoggedConfig();
|
|
1210
|
+
const result = await syncRemoteDeploymentConfig(workdir, apmDir);
|
|
1211
|
+
if (!result.synced) {
|
|
1212
|
+
process.exit(1);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1115
1216
|
// src/commands/sync-document.ts
|
|
1116
|
-
import { existsSync as
|
|
1217
|
+
import { existsSync as existsSync9 } from "fs";
|
|
1117
1218
|
import { basename as basename3 } from "path";
|
|
1118
1219
|
|
|
1119
1220
|
// src/commands/sync-session-documents.ts
|
|
1120
|
-
import { existsSync as
|
|
1121
|
-
import { join as
|
|
1221
|
+
import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync6 } from "fs";
|
|
1222
|
+
import { join as join11 } from "path";
|
|
1122
1223
|
function listLocalMarkdownFiles(docsDir) {
|
|
1123
|
-
if (!
|
|
1224
|
+
if (!existsSync8(docsDir)) {
|
|
1124
1225
|
return [];
|
|
1125
1226
|
}
|
|
1126
1227
|
return readdirSync3(docsDir).filter(
|
|
@@ -1135,7 +1236,7 @@ function remoteDocumentByLocalName(remoteDocuments, localFileName) {
|
|
|
1135
1236
|
});
|
|
1136
1237
|
}
|
|
1137
1238
|
async function upsertLocalDocumentFile(api, sessionId, docsDir, fileName) {
|
|
1138
|
-
const absPath =
|
|
1239
|
+
const absPath = join11(docsDir, fileName);
|
|
1139
1240
|
const content = readFileSync6(absPath, "utf8");
|
|
1140
1241
|
const name = documentPlatformName(absPath);
|
|
1141
1242
|
return api.cli.upsertDocument({
|
|
@@ -1158,7 +1259,7 @@ async function syncSessionDocuments(cfg, sessionId, apmRoot, options) {
|
|
|
1158
1259
|
const remoteDocuments = options?.remoteDocuments ?? await api.cli.listDocuments({ sessionId: trimmedSessionId });
|
|
1159
1260
|
let synced = 0;
|
|
1160
1261
|
for (const fileName of localFiles) {
|
|
1161
|
-
const absPath =
|
|
1262
|
+
const absPath = join11(docsDir, fileName);
|
|
1162
1263
|
const content = readFileSync6(absPath, "utf8");
|
|
1163
1264
|
const remote = remoteDocumentByLocalName(remoteDocuments, fileName);
|
|
1164
1265
|
if (remote && remote.content === content) {
|
|
@@ -1192,7 +1293,7 @@ async function runSyncDocument(sessionId, options) {
|
|
|
1192
1293
|
process.exit(1);
|
|
1193
1294
|
}
|
|
1194
1295
|
const absPath = resolveSessionDocumentPath(trimmedSessionId, fileArg);
|
|
1195
|
-
if (!
|
|
1296
|
+
if (!existsSync9(absPath)) {
|
|
1196
1297
|
const docsDir2 = sessionDocsDir(trimmedSessionId);
|
|
1197
1298
|
console.error(
|
|
1198
1299
|
`[apm] \u6587\u6863\u4E0D\u5B58\u5728: ${absPath}
|
|
@@ -1592,13 +1693,13 @@ ${JSON.stringify(event, null, 2)}
|
|
|
1592
1693
|
}
|
|
1593
1694
|
|
|
1594
1695
|
// src/commands/connect/agent-session-registry.ts
|
|
1595
|
-
import { existsSync as
|
|
1696
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync8 } from "node:fs";
|
|
1596
1697
|
import { dirname as dirname3, resolve as resolve3 } from "node:path";
|
|
1597
1698
|
function registryPath(workdir, sessionId) {
|
|
1598
1699
|
return resolve3(workdir, ".apm", "sessions", sessionId, "cursor-agents.json");
|
|
1599
1700
|
}
|
|
1600
1701
|
function readRegistry(path10) {
|
|
1601
|
-
if (!
|
|
1702
|
+
if (!existsSync10(path10)) {
|
|
1602
1703
|
return {};
|
|
1603
1704
|
}
|
|
1604
1705
|
try {
|
|
@@ -1620,7 +1721,7 @@ function readRegistry(path10) {
|
|
|
1620
1721
|
}
|
|
1621
1722
|
function writeRegistry(path10, registry) {
|
|
1622
1723
|
mkdirSync5(dirname3(path10), { recursive: true });
|
|
1623
|
-
|
|
1724
|
+
writeFileSync8(path10, `${JSON.stringify(registry, null, 2)}
|
|
1624
1725
|
`, "utf8");
|
|
1625
1726
|
}
|
|
1626
1727
|
function loadSessionAgentId(workdir, sessionId, user) {
|
|
@@ -1756,6 +1857,16 @@ function createAppendMessageCustomTools(cfg, messageId) {
|
|
|
1756
1857
|
};
|
|
1757
1858
|
}
|
|
1758
1859
|
|
|
1860
|
+
// src/commands/connect/playwright-mcp.ts
|
|
1861
|
+
function createPlaywrightMcpServers() {
|
|
1862
|
+
return {
|
|
1863
|
+
playwright: {
|
|
1864
|
+
command: "npx",
|
|
1865
|
+
args: ["@playwright/mcp@latest", "--browser", "chrome", "--vision"]
|
|
1866
|
+
}
|
|
1867
|
+
};
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1759
1870
|
// src/commands/connect/cursor-agent.ts
|
|
1760
1871
|
setMaxListeners2(50);
|
|
1761
1872
|
installAbortSignalDebug();
|
|
@@ -1783,7 +1894,8 @@ async function obtainAgent(ctx) {
|
|
|
1783
1894
|
model: { id: ctx.model || "default" },
|
|
1784
1895
|
local: {
|
|
1785
1896
|
cwd: ctx.cwd
|
|
1786
|
-
}
|
|
1897
|
+
},
|
|
1898
|
+
mcpServers: createPlaywrightMcpServers()
|
|
1787
1899
|
};
|
|
1788
1900
|
const savedAgentId = ctx.user ? loadSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user) : void 0;
|
|
1789
1901
|
if (savedAgentId) {
|
|
@@ -1851,6 +1963,7 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
1851
1963
|
logAbortSignalStats(signal, "runCursorAgent:after-addListener");
|
|
1852
1964
|
try {
|
|
1853
1965
|
const run = await agent.send(prompt, {
|
|
1966
|
+
mcpServers: createPlaywrightMcpServers(),
|
|
1854
1967
|
local: {
|
|
1855
1968
|
customTools: createAppendMessageCustomTools(cfg, ctx.messageId)
|
|
1856
1969
|
}
|
|
@@ -2226,14 +2339,14 @@ async function runConnect(options) {
|
|
|
2226
2339
|
import path5 from "node:path";
|
|
2227
2340
|
|
|
2228
2341
|
// src/commands/deploy/internal/apm-config.ts
|
|
2229
|
-
import { existsSync as
|
|
2342
|
+
import { existsSync as existsSync11, readFileSync as readFileSync8 } from "node:fs";
|
|
2230
2343
|
import { resolve as resolve4 } from "node:path";
|
|
2231
2344
|
function loadApmConfig(options) {
|
|
2232
2345
|
const p = resolve4(
|
|
2233
2346
|
process.cwd(),
|
|
2234
2347
|
options?.configPath ?? resolve4(workspaceApmDir(), "apm.config.json")
|
|
2235
2348
|
);
|
|
2236
|
-
if (!
|
|
2349
|
+
if (!existsSync11(p)) {
|
|
2237
2350
|
console.error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF1A${p}`);
|
|
2238
2351
|
process.exit(1);
|
|
2239
2352
|
}
|
|
@@ -2360,7 +2473,7 @@ import path4 from "node:path";
|
|
|
2360
2473
|
import Docker from "dockerode";
|
|
2361
2474
|
|
|
2362
2475
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
|
|
2363
|
-
import { existsSync as
|
|
2476
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "node:fs";
|
|
2364
2477
|
import path from "node:path";
|
|
2365
2478
|
function asOptionalTlsBuffer(value) {
|
|
2366
2479
|
if (typeof value !== "string") {
|
|
@@ -2372,7 +2485,7 @@ function asOptionalTlsBuffer(value) {
|
|
|
2372
2485
|
if (normalized === "") {
|
|
2373
2486
|
return void 0;
|
|
2374
2487
|
}
|
|
2375
|
-
if (
|
|
2488
|
+
if (existsSync12(normalized)) {
|
|
2376
2489
|
return readFileSync9(normalized);
|
|
2377
2490
|
}
|
|
2378
2491
|
const looksLikePath = /[\\/]/.test(normalized) || normalized.endsWith(".pem");
|
|
@@ -2583,7 +2696,7 @@ var DockerodeClient = class {
|
|
|
2583
2696
|
var createDockerodeClient = (config) => new DockerodeClient(config);
|
|
2584
2697
|
|
|
2585
2698
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
|
|
2586
|
-
import { existsSync as
|
|
2699
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10, statSync as statSync5 } from "node:fs";
|
|
2587
2700
|
import path2 from "node:path";
|
|
2588
2701
|
function stripSurroundingQuotes(value) {
|
|
2589
2702
|
const t = value.trim();
|
|
@@ -2600,7 +2713,7 @@ function loadEnvFromFile(envFilePath) {
|
|
|
2600
2713
|
return {};
|
|
2601
2714
|
}
|
|
2602
2715
|
const targetPath = path2.resolve(envFilePath);
|
|
2603
|
-
if (!
|
|
2716
|
+
if (!existsSync13(targetPath) || !statSync5(targetPath).isFile()) {
|
|
2604
2717
|
return {};
|
|
2605
2718
|
}
|
|
2606
2719
|
const raw = readFileSync10(targetPath, "utf-8");
|
|
@@ -2774,12 +2887,12 @@ function dockerPushImage(params, cwd) {
|
|
|
2774
2887
|
}
|
|
2775
2888
|
|
|
2776
2889
|
// src/commands/deploy/internal/backend-deploy/resolve-dockerfile.ts
|
|
2777
|
-
import { existsSync as
|
|
2890
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
2778
2891
|
import path3 from "node:path";
|
|
2779
2892
|
function resolveDockerBuildPaths(cwd) {
|
|
2780
2893
|
const dockerfilePath = path3.join(cwd, "Dockerfile");
|
|
2781
2894
|
Logger.info(`\u67E5\u627EDockerfile\u6587\u4EF6\uFF0C\u8DEF\u5F84: ${dockerfilePath}`);
|
|
2782
|
-
if (!
|
|
2895
|
+
if (!existsSync14(dockerfilePath)) {
|
|
2783
2896
|
throw new Error(`Dockerfile \u4E0D\u5B58\u5728\uFF1A${dockerfilePath}`);
|
|
2784
2897
|
}
|
|
2785
2898
|
Logger.info("\u2713 Dockerfile \u5B58\u5728");
|
|
@@ -2908,14 +3021,14 @@ import { copyFile, readdir as readdir2, stat } from "node:fs/promises";
|
|
|
2908
3021
|
import path7 from "node:path";
|
|
2909
3022
|
|
|
2910
3023
|
// src/commands/deploy/internal/minio.ts
|
|
2911
|
-
import { statSync as
|
|
3024
|
+
import { statSync as statSync6 } from "node:fs";
|
|
2912
3025
|
import { readdir, readFile } from "node:fs/promises";
|
|
2913
3026
|
import path6 from "node:path";
|
|
2914
3027
|
import * as Minio from "minio";
|
|
2915
3028
|
var DEFAULT_MAX_FILE_SIZE_MB = 50;
|
|
2916
3029
|
async function isDirectoryPath(dir) {
|
|
2917
3030
|
try {
|
|
2918
|
-
const st =
|
|
3031
|
+
const st = statSync6(dir);
|
|
2919
3032
|
return st.isDirectory();
|
|
2920
3033
|
} catch {
|
|
2921
3034
|
return false;
|
|
@@ -2945,7 +3058,7 @@ async function collectFiles(root) {
|
|
|
2945
3058
|
if (e.isDirectory()) {
|
|
2946
3059
|
await walk(abs, rel);
|
|
2947
3060
|
} else if (e.isFile()) {
|
|
2948
|
-
const st =
|
|
3061
|
+
const st = statSync6(abs);
|
|
2949
3062
|
out.push({
|
|
2950
3063
|
absPath: abs,
|
|
2951
3064
|
relativePath: rel.replace(/\\/g, "/"),
|
|
@@ -3388,7 +3501,9 @@ function buildProgram() {
|
|
|
3388
3501
|
).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
3502
|
await runLogin(opts);
|
|
3390
3503
|
});
|
|
3391
|
-
program.command("init").description(
|
|
3504
|
+
program.command("init").description(
|
|
3505
|
+
"\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"
|
|
3506
|
+
).option("--name <name>", "\u5DE5\u4F5C\u76EE\u5F55\u540D\u79F0").action(async (opts) => {
|
|
3392
3507
|
await runInit(opts.name);
|
|
3393
3508
|
});
|
|
3394
3509
|
program.command("update").description(
|
|
@@ -3401,6 +3516,11 @@ function buildProgram() {
|
|
|
3401
3516
|
).action(async () => {
|
|
3402
3517
|
await runUpdateSkills();
|
|
3403
3518
|
});
|
|
3519
|
+
program.command("sync-deploy-config").description(
|
|
3520
|
+
"\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"
|
|
3521
|
+
).action(async () => {
|
|
3522
|
+
await runSyncDeployConfig();
|
|
3523
|
+
});
|
|
3404
3524
|
program.command("pull").description(
|
|
3405
3525
|
"\u62C9\u53D6\u6C9F\u901A\u7FA4\u6570\u636E\u5230 .apm/sessions/<sessionId>/\uFF08session.yaml\u3001RULE.md\u3001TASK.md\u3001TODO.md\u3001docs\u3001attachments\uFF09"
|
|
3406
3526
|
).argument("<sessionId>", "\u6C9F\u901A\u7FA4 ID").action(async (sessionId) => {
|