ai-project-manage-cli 6.0.44-alpha.1 → 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 +217 -109
- 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) {
|
|
@@ -2238,14 +2339,14 @@ async function runConnect(options) {
|
|
|
2238
2339
|
import path5 from "node:path";
|
|
2239
2340
|
|
|
2240
2341
|
// src/commands/deploy/internal/apm-config.ts
|
|
2241
|
-
import { existsSync as
|
|
2342
|
+
import { existsSync as existsSync11, readFileSync as readFileSync8 } from "node:fs";
|
|
2242
2343
|
import { resolve as resolve4 } from "node:path";
|
|
2243
2344
|
function loadApmConfig(options) {
|
|
2244
2345
|
const p = resolve4(
|
|
2245
2346
|
process.cwd(),
|
|
2246
2347
|
options?.configPath ?? resolve4(workspaceApmDir(), "apm.config.json")
|
|
2247
2348
|
);
|
|
2248
|
-
if (!
|
|
2349
|
+
if (!existsSync11(p)) {
|
|
2249
2350
|
console.error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF1A${p}`);
|
|
2250
2351
|
process.exit(1);
|
|
2251
2352
|
}
|
|
@@ -2372,7 +2473,7 @@ import path4 from "node:path";
|
|
|
2372
2473
|
import Docker from "dockerode";
|
|
2373
2474
|
|
|
2374
2475
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
|
|
2375
|
-
import { existsSync as
|
|
2476
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "node:fs";
|
|
2376
2477
|
import path from "node:path";
|
|
2377
2478
|
function asOptionalTlsBuffer(value) {
|
|
2378
2479
|
if (typeof value !== "string") {
|
|
@@ -2384,7 +2485,7 @@ function asOptionalTlsBuffer(value) {
|
|
|
2384
2485
|
if (normalized === "") {
|
|
2385
2486
|
return void 0;
|
|
2386
2487
|
}
|
|
2387
|
-
if (
|
|
2488
|
+
if (existsSync12(normalized)) {
|
|
2388
2489
|
return readFileSync9(normalized);
|
|
2389
2490
|
}
|
|
2390
2491
|
const looksLikePath = /[\\/]/.test(normalized) || normalized.endsWith(".pem");
|
|
@@ -2595,7 +2696,7 @@ var DockerodeClient = class {
|
|
|
2595
2696
|
var createDockerodeClient = (config) => new DockerodeClient(config);
|
|
2596
2697
|
|
|
2597
2698
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
|
|
2598
|
-
import { existsSync as
|
|
2699
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10, statSync as statSync5 } from "node:fs";
|
|
2599
2700
|
import path2 from "node:path";
|
|
2600
2701
|
function stripSurroundingQuotes(value) {
|
|
2601
2702
|
const t = value.trim();
|
|
@@ -2612,7 +2713,7 @@ function loadEnvFromFile(envFilePath) {
|
|
|
2612
2713
|
return {};
|
|
2613
2714
|
}
|
|
2614
2715
|
const targetPath = path2.resolve(envFilePath);
|
|
2615
|
-
if (!
|
|
2716
|
+
if (!existsSync13(targetPath) || !statSync5(targetPath).isFile()) {
|
|
2616
2717
|
return {};
|
|
2617
2718
|
}
|
|
2618
2719
|
const raw = readFileSync10(targetPath, "utf-8");
|
|
@@ -2786,12 +2887,12 @@ function dockerPushImage(params, cwd) {
|
|
|
2786
2887
|
}
|
|
2787
2888
|
|
|
2788
2889
|
// src/commands/deploy/internal/backend-deploy/resolve-dockerfile.ts
|
|
2789
|
-
import { existsSync as
|
|
2890
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
2790
2891
|
import path3 from "node:path";
|
|
2791
2892
|
function resolveDockerBuildPaths(cwd) {
|
|
2792
2893
|
const dockerfilePath = path3.join(cwd, "Dockerfile");
|
|
2793
2894
|
Logger.info(`\u67E5\u627EDockerfile\u6587\u4EF6\uFF0C\u8DEF\u5F84: ${dockerfilePath}`);
|
|
2794
|
-
if (!
|
|
2895
|
+
if (!existsSync14(dockerfilePath)) {
|
|
2795
2896
|
throw new Error(`Dockerfile \u4E0D\u5B58\u5728\uFF1A${dockerfilePath}`);
|
|
2796
2897
|
}
|
|
2797
2898
|
Logger.info("\u2713 Dockerfile \u5B58\u5728");
|
|
@@ -2920,14 +3021,14 @@ import { copyFile, readdir as readdir2, stat } from "node:fs/promises";
|
|
|
2920
3021
|
import path7 from "node:path";
|
|
2921
3022
|
|
|
2922
3023
|
// src/commands/deploy/internal/minio.ts
|
|
2923
|
-
import { statSync as
|
|
3024
|
+
import { statSync as statSync6 } from "node:fs";
|
|
2924
3025
|
import { readdir, readFile } from "node:fs/promises";
|
|
2925
3026
|
import path6 from "node:path";
|
|
2926
3027
|
import * as Minio from "minio";
|
|
2927
3028
|
var DEFAULT_MAX_FILE_SIZE_MB = 50;
|
|
2928
3029
|
async function isDirectoryPath(dir) {
|
|
2929
3030
|
try {
|
|
2930
|
-
const st =
|
|
3031
|
+
const st = statSync6(dir);
|
|
2931
3032
|
return st.isDirectory();
|
|
2932
3033
|
} catch {
|
|
2933
3034
|
return false;
|
|
@@ -2957,7 +3058,7 @@ async function collectFiles(root) {
|
|
|
2957
3058
|
if (e.isDirectory()) {
|
|
2958
3059
|
await walk(abs, rel);
|
|
2959
3060
|
} else if (e.isFile()) {
|
|
2960
|
-
const st =
|
|
3061
|
+
const st = statSync6(abs);
|
|
2961
3062
|
out.push({
|
|
2962
3063
|
absPath: abs,
|
|
2963
3064
|
relativePath: rel.replace(/\\/g, "/"),
|
|
@@ -3400,7 +3501,9 @@ function buildProgram() {
|
|
|
3400
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) => {
|
|
3401
3502
|
await runLogin(opts);
|
|
3402
3503
|
});
|
|
3403
|
-
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) => {
|
|
3404
3507
|
await runInit(opts.name);
|
|
3405
3508
|
});
|
|
3406
3509
|
program.command("update").description(
|
|
@@ -3413,6 +3516,11 @@ function buildProgram() {
|
|
|
3413
3516
|
).action(async () => {
|
|
3414
3517
|
await runUpdateSkills();
|
|
3415
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
|
+
});
|
|
3416
3524
|
program.command("pull").description(
|
|
3417
3525
|
"\u62C9\u53D6\u6C9F\u901A\u7FA4\u6570\u636E\u5230 .apm/sessions/<sessionId>/\uFF08session.yaml\u3001RULE.md\u3001TASK.md\u3001TODO.md\u3001docs\u3001attachments\uFF09"
|
|
3418
3526
|
).argument("<sessionId>", "\u6C9F\u901A\u7FA4 ID").action(async (sessionId) => {
|