ai-project-manage-cli 6.0.36 → 6.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +148 -39
- package/package.json +1 -1
- package/template/apm.config.json +1 -1
- package/template/deploy/README.md +15 -0
- package/template/sessions/.gitkeep +0 -0
package/dist/index.js
CHANGED
|
@@ -84,13 +84,55 @@ import { join as join3 } from "path";
|
|
|
84
84
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
85
85
|
|
|
86
86
|
// src/command-utils.ts
|
|
87
|
-
import {
|
|
88
|
-
import { basename, dirname, extname, join as join2, resolve } from "path";
|
|
87
|
+
import { copyFileSync, existsSync, mkdirSync as mkdirSync2, readdirSync, statSync } from "fs";
|
|
88
|
+
import { basename, dirname, extname, join as join2, resolve as resolve2 } from "path";
|
|
89
89
|
import { fileURLToPath } from "url";
|
|
90
|
+
|
|
91
|
+
// src/workdir-path.ts
|
|
92
|
+
import { realpathSync } from "fs";
|
|
93
|
+
import { platform } from "os";
|
|
94
|
+
import { resolve } from "path";
|
|
95
|
+
function toFsPath(inputPath) {
|
|
96
|
+
const absolute = resolve(inputPath);
|
|
97
|
+
if (platform() !== "win32") return absolute;
|
|
98
|
+
if (absolute.startsWith("\\\\?\\")) return absolute;
|
|
99
|
+
const normalized = absolute.replace(/\//g, "\\");
|
|
100
|
+
if (normalized.startsWith("\\\\")) {
|
|
101
|
+
return `\\\\?\\UNC\\${normalized.slice(2)}`;
|
|
102
|
+
}
|
|
103
|
+
return `\\\\?\\${normalized}`;
|
|
104
|
+
}
|
|
105
|
+
function normalizeWorkdirPath(path10) {
|
|
106
|
+
let normalized = path10.trim().replace(/\\/g, "/").normalize("NFC");
|
|
107
|
+
if (normalized.startsWith("//?/")) {
|
|
108
|
+
normalized = normalized.slice(4);
|
|
109
|
+
}
|
|
110
|
+
const windowsDrive = /^([A-Za-z]:)\/*(.*)$/.exec(normalized);
|
|
111
|
+
if (windowsDrive) {
|
|
112
|
+
const drive = windowsDrive[1].toLowerCase();
|
|
113
|
+
const rest = windowsDrive[2].replace(/\/+/g, "/").replace(/\/$/, "");
|
|
114
|
+
return rest ? `${drive}/${rest}` : drive;
|
|
115
|
+
}
|
|
116
|
+
normalized = normalized.replace(/\/+/g, "/");
|
|
117
|
+
if (normalized.length > 1 && normalized.endsWith("/")) {
|
|
118
|
+
normalized = normalized.slice(0, -1);
|
|
119
|
+
}
|
|
120
|
+
return normalized;
|
|
121
|
+
}
|
|
122
|
+
function resolveWorkdirPath(cwd = process.cwd()) {
|
|
123
|
+
const absolute = resolve(cwd);
|
|
124
|
+
try {
|
|
125
|
+
return normalizeWorkdirPath(realpathSync.native(absolute));
|
|
126
|
+
} catch {
|
|
127
|
+
return normalizeWorkdirPath(absolute);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/command-utils.ts
|
|
90
132
|
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
91
|
-
var CLI_TEMPLATE_DIR =
|
|
92
|
-
function workspaceApmDir(cwd =
|
|
93
|
-
return
|
|
133
|
+
var CLI_TEMPLATE_DIR = resolve2(__dirname, "../template");
|
|
134
|
+
function workspaceApmDir(cwd = resolveWorkdirPath()) {
|
|
135
|
+
return resolve2(resolve2(cwd), ".apm");
|
|
94
136
|
}
|
|
95
137
|
var SESSIONS_SUBDIR = "sessions";
|
|
96
138
|
var SESSION_DOCS_SUBDIR = "docs";
|
|
@@ -147,51 +189,119 @@ async function ensureLoggedConfig() {
|
|
|
147
189
|
async function ensureDirExists(dir) {
|
|
148
190
|
mkdirSync2(dir, { recursive: true });
|
|
149
191
|
}
|
|
150
|
-
async function ensureWorkspaceApmDirForInit() {
|
|
151
|
-
const dir = workspaceApmDir();
|
|
152
|
-
|
|
153
|
-
|
|
192
|
+
async function ensureWorkspaceApmDirForInit(cwd = resolveWorkdirPath()) {
|
|
193
|
+
const dir = workspaceApmDir(cwd);
|
|
194
|
+
const fsDir = toFsPath(dir);
|
|
195
|
+
if (!existsSync(fsDir)) {
|
|
196
|
+
mkdirSync2(fsDir, { recursive: true });
|
|
154
197
|
return;
|
|
155
198
|
}
|
|
156
|
-
const st = statSync(
|
|
199
|
+
const st = statSync(fsDir);
|
|
157
200
|
if (!st.isDirectory()) {
|
|
158
201
|
throw new Error(`[apm] \u8DEF\u5F84\u5DF2\u5B58\u5728\u4F46\u4E0D\u662F\u76EE\u5F55: ${dir}`);
|
|
159
202
|
}
|
|
160
|
-
if (readdirSync(
|
|
203
|
+
if (readdirSync(fsDir).length > 0) {
|
|
161
204
|
throw new Error(
|
|
162
205
|
"[apm] .apm \u76EE\u5F55\u5DF2\u5B58\u5728\u4E14\u975E\u7A7A\uFF0C\u8BF7\u5148\u5907\u4EFD\u3001\u6E05\u7A7A\u6216\u5220\u9664\u540E\u518D\u6267\u884C init"
|
|
163
206
|
);
|
|
164
207
|
}
|
|
165
208
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
209
|
+
var WORKSPACE_TEMPLATE_SUBDIRS = [
|
|
210
|
+
"sessions",
|
|
211
|
+
"skills",
|
|
212
|
+
"rules",
|
|
213
|
+
"deploy"
|
|
214
|
+
];
|
|
215
|
+
function shouldSkipTemplateEntry(name) {
|
|
216
|
+
return name === ".DS_Store" || name === "Thumbs.db";
|
|
217
|
+
}
|
|
218
|
+
function copyTemplateEntry(src, dest) {
|
|
219
|
+
const fsSrc = toFsPath(src);
|
|
220
|
+
const fsDest = toFsPath(dest);
|
|
221
|
+
const st = statSync(fsSrc);
|
|
222
|
+
if (st.isDirectory()) {
|
|
223
|
+
mkdirSync2(fsDest, { recursive: true });
|
|
224
|
+
for (const name of readdirSync(fsSrc)) {
|
|
225
|
+
if (shouldSkipTemplateEntry(name)) continue;
|
|
226
|
+
copyTemplateEntry(join2(src, name), join2(dest, name));
|
|
227
|
+
}
|
|
171
228
|
return;
|
|
172
229
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
230
|
+
if (!st.isFile()) return;
|
|
231
|
+
mkdirSync2(toFsPath(dirname(dest)), { recursive: true });
|
|
232
|
+
copyFileSync(fsSrc, fsDest);
|
|
233
|
+
}
|
|
234
|
+
function assertTemplateCopiedToApm(apmDir, workdir) {
|
|
235
|
+
const required = [
|
|
236
|
+
"AGENTS.md",
|
|
237
|
+
"apm.config.json",
|
|
238
|
+
"rules",
|
|
239
|
+
"skills",
|
|
240
|
+
"sessions"
|
|
241
|
+
];
|
|
242
|
+
for (const item of required) {
|
|
243
|
+
const path10 = join2(apmDir, item);
|
|
244
|
+
if (!existsSync(toFsPath(path10))) {
|
|
245
|
+
throw new Error(`[apm] \u521D\u59CB\u5316\u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5C11: ${path10}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const leakedRules = join2(workdir, "rules");
|
|
249
|
+
const apmRules = join2(apmDir, "rules");
|
|
250
|
+
if (existsSync(toFsPath(leakedRules)) && !existsSync(toFsPath(join2(apmRules, "reply.md")))) {
|
|
251
|
+
throw new Error(
|
|
252
|
+
`[apm] \u6A21\u677F\u88AB\u590D\u5236\u5230\u9519\u8BEF\u4F4D\u7F6E: ${leakedRules}\uFF08\u5E94\u5728 ${apmRules}\uFF09`
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
async function copyTemplateFiles(targetDir, workdir = resolveWorkdirPath()) {
|
|
257
|
+
const resolvedTarget = resolve2(targetDir);
|
|
258
|
+
const templateDir = resolve2(CLI_TEMPLATE_DIR);
|
|
259
|
+
const fsTemplateDir = toFsPath(templateDir);
|
|
260
|
+
if (!existsSync(fsTemplateDir)) {
|
|
261
|
+
throw new Error(`[apm] \u672A\u627E\u5230 CLI \u6A21\u677F\u76EE\u5F55: ${templateDir}`);
|
|
262
|
+
}
|
|
263
|
+
const dirStat = statSync(fsTemplateDir);
|
|
264
|
+
if (!dirStat.isDirectory()) {
|
|
265
|
+
throw new Error(`[apm] CLI \u6A21\u677F\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${templateDir}`);
|
|
266
|
+
}
|
|
267
|
+
const entries = readdirSync(fsTemplateDir).filter(
|
|
268
|
+
(name) => !shouldSkipTemplateEntry(name)
|
|
180
269
|
);
|
|
270
|
+
if (entries.length === 0) {
|
|
271
|
+
throw new Error(`[apm] CLI \u6A21\u677F\u76EE\u5F55\u4E3A\u7A7A: ${templateDir}`);
|
|
272
|
+
}
|
|
273
|
+
mkdirSync2(toFsPath(resolvedTarget), { recursive: true });
|
|
274
|
+
for (const name of entries) {
|
|
275
|
+
copyTemplateEntry(join2(templateDir, name), join2(resolvedTarget, name));
|
|
276
|
+
}
|
|
277
|
+
for (const subdir of WORKSPACE_TEMPLATE_SUBDIRS) {
|
|
278
|
+
mkdirSync2(toFsPath(join2(resolvedTarget, subdir)), { recursive: true });
|
|
279
|
+
}
|
|
280
|
+
assertTemplateCopiedToApm(resolvedTarget, resolve2(workdir));
|
|
181
281
|
}
|
|
182
282
|
|
|
183
283
|
// src/commands/init.ts
|
|
184
284
|
async function runInit(name) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
285
|
+
const workdir = resolveWorkdirPath();
|
|
286
|
+
await ensureWorkspaceApmDirForInit(workdir);
|
|
287
|
+
const apmDir = workspaceApmDir(workdir);
|
|
288
|
+
await copyTemplateFiles(apmDir, workdir);
|
|
289
|
+
const trimmedName = name?.trim();
|
|
290
|
+
if (trimmedName) {
|
|
291
|
+
const apmConfigPath = toFsPath(join3(apmDir, "apm.config.json"));
|
|
190
292
|
const config = readFileSync2(apmConfigPath, "utf8");
|
|
191
293
|
const configJson = JSON.parse(config);
|
|
192
|
-
configJson.name =
|
|
193
|
-
writeFileSync2(
|
|
294
|
+
configJson.name = trimmedName;
|
|
295
|
+
writeFileSync2(
|
|
296
|
+
apmConfigPath,
|
|
297
|
+
`${JSON.stringify(configJson, null, 2)}
|
|
298
|
+
`,
|
|
299
|
+
"utf8"
|
|
300
|
+
);
|
|
194
301
|
}
|
|
302
|
+
console.log(`[apm] \u5DF2\u521D\u59CB\u5316\u5DE5\u4F5C\u533A\uFF1A${apmDir}`);
|
|
303
|
+
console.log(`[apm] \u5DE5\u4F5C\u76EE\u5F55\u8DEF\u5F84\uFF1A${workdir}`);
|
|
304
|
+
console.log("[apm] \u8BF7\u5728\u5E73\u53F0\u300C\u5BA2\u6237\u673A\u7BA1\u7406 \u2192 \u5DE5\u4F5C\u7A7A\u95F4\u300D\u767B\u8BB0\u4E0A\u8FF0\u76EE\u5F55\u8DEF\u5F84");
|
|
195
305
|
}
|
|
196
306
|
|
|
197
307
|
// src/commands/login.ts
|
|
@@ -328,7 +438,6 @@ async function runLogin(opts) {
|
|
|
328
438
|
|
|
329
439
|
// src/commands/branch.ts
|
|
330
440
|
import { execFile } from "child_process";
|
|
331
|
-
import { resolve as resolve2 } from "path";
|
|
332
441
|
import { promisify } from "util";
|
|
333
442
|
var execFileAsync = promisify(execFile);
|
|
334
443
|
function branchNameForSession(sessionId) {
|
|
@@ -476,7 +585,7 @@ async function runBranch(sessionId, options = {}) {
|
|
|
476
585
|
const cfg = await ensureLoggedConfig();
|
|
477
586
|
const api = createApmApiClient(cfg);
|
|
478
587
|
const cwd = options.cwd ?? process.cwd();
|
|
479
|
-
const workdirPath =
|
|
588
|
+
const workdirPath = resolveWorkdirPath(cwd);
|
|
480
589
|
const baseline = await api.cli.branchBaseline({
|
|
481
590
|
sessionId: trimmedSessionId,
|
|
482
591
|
workdirPath
|
|
@@ -755,8 +864,8 @@ import { join as join8 } from "path";
|
|
|
755
864
|
|
|
756
865
|
// src/skills-sync.ts
|
|
757
866
|
import {
|
|
758
|
-
copyFileSync,
|
|
759
|
-
cpSync
|
|
867
|
+
copyFileSync as copyFileSync2,
|
|
868
|
+
cpSync,
|
|
760
869
|
existsSync as existsSync3,
|
|
761
870
|
mkdirSync as mkdirSync3,
|
|
762
871
|
readdirSync as readdirSync2,
|
|
@@ -783,7 +892,7 @@ function listBaseSkillDirNames() {
|
|
|
783
892
|
function syncAgentsGuide(apmDir) {
|
|
784
893
|
if (!existsSync3(AGENTS_TEMPLATE_PATH)) return false;
|
|
785
894
|
mkdirSync3(apmDir, { recursive: true });
|
|
786
|
-
|
|
895
|
+
copyFileSync2(AGENTS_TEMPLATE_PATH, join7(apmDir, "AGENTS.md"));
|
|
787
896
|
return true;
|
|
788
897
|
}
|
|
789
898
|
function listBaseRuleFileNames() {
|
|
@@ -799,7 +908,7 @@ function syncBaseRules(rulesDir) {
|
|
|
799
908
|
for (const name of names) {
|
|
800
909
|
const src = join7(BASE_RULES_TEMPLATE_DIR, name);
|
|
801
910
|
const dest = join7(rulesDir, name);
|
|
802
|
-
|
|
911
|
+
copyFileSync2(src, dest);
|
|
803
912
|
}
|
|
804
913
|
return names;
|
|
805
914
|
}
|
|
@@ -809,7 +918,7 @@ function syncBaseSkills(skillsDir) {
|
|
|
809
918
|
for (const name of names) {
|
|
810
919
|
const src = join7(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
811
920
|
const dest = join7(skillsDir, name);
|
|
812
|
-
|
|
921
|
+
cpSync(src, dest, { recursive: true, force: true });
|
|
813
922
|
}
|
|
814
923
|
return names;
|
|
815
924
|
}
|
|
@@ -2306,7 +2415,7 @@ function assertDeployImageTag(tag) {
|
|
|
2306
2415
|
}
|
|
2307
2416
|
|
|
2308
2417
|
// src/commands/deploy/internal/backend-deploy/local-docker-build.ts
|
|
2309
|
-
import { platform } from "node:os";
|
|
2418
|
+
import { platform as platform2 } from "node:os";
|
|
2310
2419
|
|
|
2311
2420
|
// src/commands/deploy/internal/backend-deploy/command-runner.ts
|
|
2312
2421
|
import { execSync } from "child_process";
|
|
@@ -2366,7 +2475,7 @@ var CommandRunner = class {
|
|
|
2366
2475
|
|
|
2367
2476
|
// src/commands/deploy/internal/backend-deploy/local-docker-build.ts
|
|
2368
2477
|
function dockerBuildPlatformFlags() {
|
|
2369
|
-
return
|
|
2478
|
+
return platform2() === "darwin" ? ["--platform", "linux/amd64"] : [];
|
|
2370
2479
|
}
|
|
2371
2480
|
function buildDockerImageLocally(params, cwd) {
|
|
2372
2481
|
const platformFlags = dockerBuildPlatformFlags();
|
package/package.json
CHANGED
package/template/apm.config.json
CHANGED
|
File without changes
|