ai-project-manage-cli 8.1.7 → 8.1.9
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/README.md +1 -1
- package/dist/index.js +209 -222
- package/dist/worker-script.js +157 -261
- package/package.json +1 -1
- package/template/AGENTS.webide.md +0 -28
- package/template/rules/webide_git_commit.md +0 -16
- package/template/rules/webide_merge.md +0 -24
- package/template/rules/webide_package.md +0 -70
- package/template/rules/webide_reply.md +0 -18
- package/template/rules/webide_sql_change.md +0 -28
- package/template/rules/webide_sql_execute.md +0 -29
- package/template/rules/webide_terminal.md +0 -45
- package/template/rules/webide_testcase.md +0 -47
package/dist/worker-script.js
CHANGED
|
@@ -14,6 +14,10 @@ var requestConfig = {
|
|
|
14
14
|
path: "/cli/me"
|
|
15
15
|
}
|
|
16
16
|
),
|
|
17
|
+
webideAgentConfig: defineEndpoint({
|
|
18
|
+
method: "GET",
|
|
19
|
+
path: "/cli/webide/agent-config"
|
|
20
|
+
}),
|
|
17
21
|
webideAppendMessageContent: defineEndpoint({
|
|
18
22
|
method: "PUT",
|
|
19
23
|
path: "/cli/webide/messages/content"
|
|
@@ -325,11 +329,8 @@ function requireRemoteWorkdir(workdir) {
|
|
|
325
329
|
}
|
|
326
330
|
|
|
327
331
|
// src/utils/workspace.ts
|
|
328
|
-
import {
|
|
329
|
-
import {
|
|
330
|
-
import { fileURLToPath } from "url";
|
|
331
|
-
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
332
|
-
var CLI_TEMPLATE_DIR = resolve2(__dirname, "../template");
|
|
332
|
+
import { existsSync, mkdirSync as mkdirSync2, readdirSync, statSync } from "fs";
|
|
333
|
+
import { join as join2, resolve as resolve2 } from "path";
|
|
333
334
|
function workspaceApmDir(cwd = resolveWorkdirPath()) {
|
|
334
335
|
return resolve2(resolve2(cwd), ".apm");
|
|
335
336
|
}
|
|
@@ -380,90 +381,6 @@ async function ensureWorkspaceApmDirForInit(cwd = resolveWorkdirPath()) {
|
|
|
380
381
|
}
|
|
381
382
|
mkdirSync2(fsDir, { recursive: true });
|
|
382
383
|
}
|
|
383
|
-
var WEBIDE_AGENTS_TEMPLATE_NAME = "AGENTS.webide.md";
|
|
384
|
-
function shouldSkipTemplateEntry(name) {
|
|
385
|
-
return name === ".DS_Store" || name === "Thumbs.db";
|
|
386
|
-
}
|
|
387
|
-
function isWebIdeRuleFileName(name) {
|
|
388
|
-
return name.startsWith("webide");
|
|
389
|
-
}
|
|
390
|
-
function copyTemplateEntry(src, dest) {
|
|
391
|
-
const fsSrc = toFsPath(src);
|
|
392
|
-
const fsDest = toFsPath(dest);
|
|
393
|
-
const st = statSync(fsSrc);
|
|
394
|
-
if (st.isDirectory()) {
|
|
395
|
-
mkdirSync2(fsDest, { recursive: true });
|
|
396
|
-
for (const name of readdirSync(fsSrc)) {
|
|
397
|
-
if (shouldSkipTemplateEntry(name)) continue;
|
|
398
|
-
copyTemplateEntry(join2(src, name), join2(dest, name));
|
|
399
|
-
}
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
if (!st.isFile()) return;
|
|
403
|
-
mkdirSync2(toFsPath(dirname(dest)), { recursive: true });
|
|
404
|
-
copyFileSync(fsSrc, fsDest);
|
|
405
|
-
}
|
|
406
|
-
function listWebIdeRuleFileNames(rulesDir) {
|
|
407
|
-
const fsRulesDir = toFsPath(rulesDir);
|
|
408
|
-
if (!existsSync(fsRulesDir) || !statSync(fsRulesDir).isDirectory()) {
|
|
409
|
-
return [];
|
|
410
|
-
}
|
|
411
|
-
return readdirSync(fsRulesDir).filter((name) => {
|
|
412
|
-
if (shouldSkipTemplateEntry(name) || !isWebIdeRuleFileName(name)) {
|
|
413
|
-
return false;
|
|
414
|
-
}
|
|
415
|
-
return statSync(toFsPath(join2(rulesDir, name))).isFile();
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
function assertWebIdeTemplateCopiedToApm(apmDir, workdir) {
|
|
419
|
-
const required = ["AGENTS.md", "rules"];
|
|
420
|
-
for (const item of required) {
|
|
421
|
-
const path3 = join2(apmDir, item);
|
|
422
|
-
if (!existsSync(toFsPath(path3))) {
|
|
423
|
-
throw new Error(`[apm] WebIDE \u521D\u59CB\u5316\u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5C11: ${path3}`);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
const rulesDir = join2(apmDir, "rules");
|
|
427
|
-
const ruleNames = listWebIdeRuleFileNames(rulesDir);
|
|
428
|
-
if (ruleNames.length === 0) {
|
|
429
|
-
throw new Error(`[apm] WebIDE \u521D\u59CB\u5316\u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5C11 webide \u89C4\u5219: ${rulesDir}`);
|
|
430
|
-
}
|
|
431
|
-
const leakedRules = join2(workdir, "rules");
|
|
432
|
-
const apmRules = join2(apmDir, "rules");
|
|
433
|
-
if (existsSync(toFsPath(leakedRules)) && !existsSync(toFsPath(join2(apmRules, "webide_reply.md")))) {
|
|
434
|
-
throw new Error(
|
|
435
|
-
`[apm] \u6A21\u677F\u88AB\u590D\u5236\u5230\u9519\u8BEF\u4F4D\u7F6E: ${leakedRules}\uFF08\u5E94\u5728 ${apmRules}\uFF09`
|
|
436
|
-
);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
async function copyWebIdeTemplateFiles(targetDir, workdir = resolveWorkdirPath()) {
|
|
440
|
-
const resolvedTarget = resolve2(targetDir);
|
|
441
|
-
const templateDir = resolve2(CLI_TEMPLATE_DIR);
|
|
442
|
-
const fsTemplateDir = toFsPath(templateDir);
|
|
443
|
-
if (!existsSync(fsTemplateDir) || !statSync(fsTemplateDir).isDirectory()) {
|
|
444
|
-
throw new Error(`[apm] \u672A\u627E\u5230 CLI \u6A21\u677F\u76EE\u5F55: ${templateDir}`);
|
|
445
|
-
}
|
|
446
|
-
const agentsSrc = join2(templateDir, WEBIDE_AGENTS_TEMPLATE_NAME);
|
|
447
|
-
if (!existsSync(toFsPath(agentsSrc))) {
|
|
448
|
-
throw new Error(`[apm] \u672A\u627E\u5230 WebIDE \u6307\u5357: ${agentsSrc}`);
|
|
449
|
-
}
|
|
450
|
-
const rulesSrc = join2(templateDir, "rules");
|
|
451
|
-
const ruleNames = listWebIdeRuleFileNames(rulesSrc);
|
|
452
|
-
if (ruleNames.length === 0) {
|
|
453
|
-
throw new Error(`[apm] CLI \u6A21\u677F\u4E2D\u6CA1\u6709 webide \u89C4\u5219: ${rulesSrc}`);
|
|
454
|
-
}
|
|
455
|
-
mkdirSync2(toFsPath(resolvedTarget), { recursive: true });
|
|
456
|
-
copyFileSync(
|
|
457
|
-
toFsPath(agentsSrc),
|
|
458
|
-
toFsPath(join2(resolvedTarget, "AGENTS.md"))
|
|
459
|
-
);
|
|
460
|
-
const rulesDest = join2(resolvedTarget, "rules");
|
|
461
|
-
mkdirSync2(toFsPath(rulesDest), { recursive: true });
|
|
462
|
-
for (const name of ruleNames) {
|
|
463
|
-
copyTemplateEntry(join2(rulesSrc, name), join2(rulesDest, name));
|
|
464
|
-
}
|
|
465
|
-
assertWebIdeTemplateCopiedToApm(resolvedTarget, resolve2(workdir));
|
|
466
|
-
}
|
|
467
384
|
|
|
468
385
|
// src/utils/git.ts
|
|
469
386
|
import { execFile as execFile2 } from "child_process";
|
|
@@ -664,7 +581,7 @@ import {
|
|
|
664
581
|
statSync as statSync2,
|
|
665
582
|
writeFileSync as writeFileSync2
|
|
666
583
|
} from "fs";
|
|
667
|
-
import { basename, dirname
|
|
584
|
+
import { basename, dirname, join as join3, relative, resolve as resolve3 } from "path";
|
|
668
585
|
var WORKSPACE_REPOS_MANIFEST = "workspace-repos.json";
|
|
669
586
|
var WORKSPACE_REPOS_VERSION = 1;
|
|
670
587
|
var SKIP_DIR_NAMES = /* @__PURE__ */ new Set([".apm", "node_modules"]);
|
|
@@ -3220,14 +3137,75 @@ function createThrottledWebIdeMessageLogSync(cfg2, ctx, onError, options) {
|
|
|
3220
3137
|
};
|
|
3221
3138
|
}
|
|
3222
3139
|
|
|
3223
|
-
// src/commands/
|
|
3224
|
-
|
|
3225
|
-
|
|
3140
|
+
// src/commands/sync-webide-agent.ts
|
|
3141
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
3142
|
+
import { join as join4 } from "path";
|
|
3143
|
+
var REVISION_FILE = ".webide-agent.json";
|
|
3144
|
+
var RULE_KEY = /^webide_[a-z0-9_]+$/;
|
|
3145
|
+
function withTrailingNewline(text) {
|
|
3146
|
+
return text.endsWith("\n") ? text : `${text}
|
|
3147
|
+
`;
|
|
3148
|
+
}
|
|
3149
|
+
function readRevision(apmDir) {
|
|
3150
|
+
const path3 = toFsPath(join4(apmDir, REVISION_FILE));
|
|
3151
|
+
if (!existsSync5(path3)) return null;
|
|
3152
|
+
try {
|
|
3153
|
+
const parsed = JSON.parse(readFileSync4(path3, "utf8"));
|
|
3154
|
+
if (parsed?.version === 1 && parsed.revision?.trim()) {
|
|
3155
|
+
return parsed.revision.trim();
|
|
3156
|
+
}
|
|
3157
|
+
} catch {
|
|
3158
|
+
return null;
|
|
3159
|
+
}
|
|
3160
|
+
return null;
|
|
3161
|
+
}
|
|
3162
|
+
function writeRevision(apmDir, revision) {
|
|
3163
|
+
writeFileSync3(
|
|
3164
|
+
toFsPath(join4(apmDir, REVISION_FILE)),
|
|
3165
|
+
`${JSON.stringify({ version: 1, revision }, null, 2)}
|
|
3166
|
+
`,
|
|
3167
|
+
"utf8"
|
|
3168
|
+
);
|
|
3169
|
+
}
|
|
3170
|
+
async function syncWebIdeAgentFiles(workdir, cfg2) {
|
|
3171
|
+
const api = createApmApiClient(cfg2);
|
|
3172
|
+
const bundle = await api.cli.webideAgentConfig();
|
|
3173
|
+
const revision = bundle.revision?.trim();
|
|
3174
|
+
if (!revision) {
|
|
3175
|
+
throw new Error("[apm] \u5E73\u53F0\u672A\u8FD4\u56DE WebIDE \u89C4\u5219\u7248\u672C");
|
|
3176
|
+
}
|
|
3226
3177
|
const apmDir = workspaceApmDir(workdir);
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3178
|
+
mkdirSync4(toFsPath(apmDir), { recursive: true });
|
|
3179
|
+
if (readRevision(apmDir) === revision) {
|
|
3180
|
+
return { revision, wrote: false, ruleCount: bundle.rules?.length ?? 0 };
|
|
3181
|
+
}
|
|
3182
|
+
const rulesDir = join4(apmDir, "rules");
|
|
3183
|
+
mkdirSync4(toFsPath(rulesDir), { recursive: true });
|
|
3184
|
+
writeFileSync3(
|
|
3185
|
+
toFsPath(join4(apmDir, "AGENTS.md")),
|
|
3186
|
+
withTrailingNewline(bundle.guide ?? ""),
|
|
3187
|
+
"utf8"
|
|
3188
|
+
);
|
|
3189
|
+
for (const rule of bundle.rules ?? []) {
|
|
3190
|
+
const key = rule.key?.trim() ?? "";
|
|
3191
|
+
if (!RULE_KEY.test(key)) {
|
|
3192
|
+
throw new Error(`[apm] \u975E\u6CD5\u89C4\u5219\u540D: ${key || "(\u7A7A)"}`);
|
|
3193
|
+
}
|
|
3194
|
+
writeFileSync3(
|
|
3195
|
+
toFsPath(join4(rulesDir, `${key}.md`)),
|
|
3196
|
+
withTrailingNewline(rule.body ?? ""),
|
|
3197
|
+
"utf8"
|
|
3198
|
+
);
|
|
3199
|
+
}
|
|
3200
|
+
writeRevision(apmDir, revision);
|
|
3201
|
+
return {
|
|
3202
|
+
revision,
|
|
3203
|
+
wrote: true,
|
|
3204
|
+
ruleCount: bundle.rules?.length ?? 0
|
|
3205
|
+
};
|
|
3230
3206
|
}
|
|
3207
|
+
|
|
3208
|
+
// src/commands/init.ts
|
|
3231
3209
|
async function ensureWorkspaceInitialized(workdir) {
|
|
3232
3210
|
if (isWorkspaceApmInitialized(workdir)) {
|
|
3233
3211
|
return { didInit: false };
|
|
@@ -3235,19 +3213,21 @@ async function ensureWorkspaceInitialized(workdir) {
|
|
|
3235
3213
|
console.log(
|
|
3236
3214
|
`[apm] \u5DE5\u4F5C\u76EE\u5F55 ${workdir} \u672A\u68C0\u6D4B\u5230\u5DF2\u521D\u59CB\u5316\u7684 .apm\uFF0C\u6B63\u5728\u6309 WebIDE \u81EA\u52A8\u521D\u59CB\u5316\u2026`
|
|
3237
3215
|
);
|
|
3238
|
-
|
|
3216
|
+
await ensureWorkspaceApmDirForInit(workdir);
|
|
3217
|
+
console.log(`[apm] \u5DF2\u521B\u5EFA\u5DE5\u4F5C\u533A\u76EE\u5F55\uFF1A${workspaceApmDir(workdir)}`);
|
|
3218
|
+
return { didInit: true };
|
|
3239
3219
|
}
|
|
3240
3220
|
|
|
3241
3221
|
// src/utils/project-documents.ts
|
|
3242
3222
|
import {
|
|
3243
|
-
existsSync as
|
|
3223
|
+
existsSync as existsSync6,
|
|
3244
3224
|
readdirSync as readdirSync3,
|
|
3245
|
-
readFileSync as
|
|
3225
|
+
readFileSync as readFileSync5,
|
|
3246
3226
|
rmSync,
|
|
3247
|
-
writeFileSync as
|
|
3227
|
+
writeFileSync as writeFileSync4
|
|
3248
3228
|
} from "fs";
|
|
3249
3229
|
import { createHash as createHash2 } from "crypto";
|
|
3250
|
-
import { dirname as
|
|
3230
|
+
import { dirname as dirname2, join as join5, relative as relative4, sep } from "path";
|
|
3251
3231
|
var MANIFEST_FILE = "manifest.json";
|
|
3252
3232
|
function normalizeProjectIdForPath(projectId) {
|
|
3253
3233
|
const id = projectId.trim();
|
|
@@ -3261,11 +3241,11 @@ function normalizeProjectIdForPath(projectId) {
|
|
|
3261
3241
|
}
|
|
3262
3242
|
function projectDocumentsDir(apmRoot, projectId) {
|
|
3263
3243
|
const id = normalizeProjectIdForPath(projectId);
|
|
3264
|
-
return
|
|
3244
|
+
return join5(apmRoot ?? workspaceApmDir(), "project", id);
|
|
3265
3245
|
}
|
|
3266
3246
|
function projectDocumentLocalPath(apmRoot, projectId, documentPath) {
|
|
3267
3247
|
const normalized = normalizeLocalDocumentPath(documentPath);
|
|
3268
|
-
return
|
|
3248
|
+
return join5(
|
|
3269
3249
|
projectDocumentsDir(apmRoot, projectId),
|
|
3270
3250
|
...normalized.split("/")
|
|
3271
3251
|
);
|
|
@@ -3285,16 +3265,16 @@ function hashLocalFileContent(content) {
|
|
|
3285
3265
|
return createHash2("sha256").update(content, "utf8").digest("hex");
|
|
3286
3266
|
}
|
|
3287
3267
|
function readLocalManifest(apmRoot, projectId) {
|
|
3288
|
-
const
|
|
3268
|
+
const manifestPath2 = join5(
|
|
3289
3269
|
projectDocumentsDir(apmRoot, projectId),
|
|
3290
3270
|
MANIFEST_FILE
|
|
3291
3271
|
);
|
|
3292
|
-
if (!
|
|
3272
|
+
if (!existsSync6(manifestPath2)) {
|
|
3293
3273
|
return null;
|
|
3294
3274
|
}
|
|
3295
3275
|
try {
|
|
3296
3276
|
return JSON.parse(
|
|
3297
|
-
|
|
3277
|
+
readFileSync5(manifestPath2, "utf8")
|
|
3298
3278
|
);
|
|
3299
3279
|
} catch {
|
|
3300
3280
|
return null;
|
|
@@ -3302,13 +3282,13 @@ function readLocalManifest(apmRoot, projectId) {
|
|
|
3302
3282
|
}
|
|
3303
3283
|
function listLocalDocumentPaths(apmRoot, projectId) {
|
|
3304
3284
|
const root = projectDocumentsDir(apmRoot, projectId);
|
|
3305
|
-
if (!
|
|
3285
|
+
if (!existsSync6(root)) {
|
|
3306
3286
|
return [];
|
|
3307
3287
|
}
|
|
3308
3288
|
const paths = [];
|
|
3309
3289
|
const walk = (dir) => {
|
|
3310
3290
|
for (const entry of readdirSync3(dir, { withFileTypes: true })) {
|
|
3311
|
-
const abs =
|
|
3291
|
+
const abs = join5(dir, entry.name);
|
|
3312
3292
|
if (entry.isDirectory()) {
|
|
3313
3293
|
walk(abs);
|
|
3314
3294
|
continue;
|
|
@@ -3427,8 +3407,8 @@ ${diagnostic ?? ""}`);
|
|
|
3427
3407
|
const absPath = toFsPath(
|
|
3428
3408
|
projectDocumentLocalPath(targetApmDir, projectId, doc.path)
|
|
3429
3409
|
);
|
|
3430
|
-
await ensureDirExists(
|
|
3431
|
-
|
|
3410
|
+
await ensureDirExists(dirname2(absPath));
|
|
3411
|
+
writeFileSync4(absPath, doc.content, "utf8");
|
|
3432
3412
|
downloaded += 1;
|
|
3433
3413
|
}
|
|
3434
3414
|
}
|
|
@@ -3437,13 +3417,13 @@ ${diagnostic ?? ""}`);
|
|
|
3437
3417
|
const absPath = toFsPath(
|
|
3438
3418
|
projectDocumentLocalPath(targetApmDir, projectId, path3)
|
|
3439
3419
|
);
|
|
3440
|
-
if (
|
|
3420
|
+
if (existsSync6(absPath)) {
|
|
3441
3421
|
rmSync(absPath, { force: true });
|
|
3442
3422
|
deleted += 1;
|
|
3443
3423
|
}
|
|
3444
3424
|
}
|
|
3445
|
-
|
|
3446
|
-
toFsPath(
|
|
3425
|
+
writeFileSync4(
|
|
3426
|
+
toFsPath(join5(docsDir, MANIFEST_FILE)),
|
|
3447
3427
|
`${JSON.stringify(remoteManifest, null, 2)}
|
|
3448
3428
|
`,
|
|
3449
3429
|
"utf8"
|
|
@@ -3486,7 +3466,7 @@ async function syncProjectDocumentsPush(cfg2, workdirPath, apmRoot, options) {
|
|
|
3486
3466
|
const absPath = toFsPath(
|
|
3487
3467
|
projectDocumentLocalPath(targetApmDir, projectId, path3)
|
|
3488
3468
|
);
|
|
3489
|
-
const content =
|
|
3469
|
+
const content = readFileSync5(absPath, "utf8");
|
|
3490
3470
|
const contentHash = hashLocalFileContent(content);
|
|
3491
3471
|
if (remoteHashByPath.get(path3) === contentHash) {
|
|
3492
3472
|
continue;
|
|
@@ -3506,71 +3486,6 @@ async function syncProjectDocumentsPush(cfg2, workdirPath, apmRoot, options) {
|
|
|
3506
3486
|
return synced;
|
|
3507
3487
|
}
|
|
3508
3488
|
|
|
3509
|
-
// src/version.ts
|
|
3510
|
-
import { readFileSync as readFileSync5 } from "fs";
|
|
3511
|
-
import { dirname as dirname4, join as join5 } from "path";
|
|
3512
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3513
|
-
function readCliVersion() {
|
|
3514
|
-
try {
|
|
3515
|
-
const dir = dirname4(fileURLToPath2(import.meta.url));
|
|
3516
|
-
const pkgPath = join5(dir, "..", "package.json");
|
|
3517
|
-
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
|
|
3518
|
-
return pkg.version ?? "0.0.0";
|
|
3519
|
-
} catch {
|
|
3520
|
-
return "0.0.0";
|
|
3521
|
-
}
|
|
3522
|
-
}
|
|
3523
|
-
|
|
3524
|
-
// src/commands/connect/cli-version-sync.ts
|
|
3525
|
-
import { existsSync as existsSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
3526
|
-
import { join as join6 } from "path";
|
|
3527
|
-
var CLI_VERSION_FILE = ".cli-version.json";
|
|
3528
|
-
function manifestPath2(apmDir) {
|
|
3529
|
-
return join6(apmDir, CLI_VERSION_FILE);
|
|
3530
|
-
}
|
|
3531
|
-
function loadManifest(apmDir) {
|
|
3532
|
-
const path3 = toFsPath(manifestPath2(apmDir));
|
|
3533
|
-
if (!existsSync6(path3)) {
|
|
3534
|
-
return null;
|
|
3535
|
-
}
|
|
3536
|
-
try {
|
|
3537
|
-
const parsed = JSON.parse(
|
|
3538
|
-
readFileSync6(path3, "utf8")
|
|
3539
|
-
);
|
|
3540
|
-
if (parsed?.version === 1 && typeof parsed.cliVersion === "string" && parsed.cliVersion.trim()) {
|
|
3541
|
-
return parsed;
|
|
3542
|
-
}
|
|
3543
|
-
} catch {
|
|
3544
|
-
}
|
|
3545
|
-
return null;
|
|
3546
|
-
}
|
|
3547
|
-
function saveManifest(apmDir, cliVersion) {
|
|
3548
|
-
const manifest = { version: 1, cliVersion };
|
|
3549
|
-
writeFileSync4(
|
|
3550
|
-
toFsPath(manifestPath2(apmDir)),
|
|
3551
|
-
`${JSON.stringify(manifest, null, 2)}
|
|
3552
|
-
`,
|
|
3553
|
-
"utf8"
|
|
3554
|
-
);
|
|
3555
|
-
}
|
|
3556
|
-
var syncedInSession = /* @__PURE__ */ new Map();
|
|
3557
|
-
function shouldSyncSkillsForCliVersion(workdir, currentVersion) {
|
|
3558
|
-
const cached = syncedInSession.get(workdir);
|
|
3559
|
-
if (cached === currentVersion) {
|
|
3560
|
-
return false;
|
|
3561
|
-
}
|
|
3562
|
-
const stored = loadManifest(workspaceApmDir(workdir));
|
|
3563
|
-
if (stored?.cliVersion === currentVersion) {
|
|
3564
|
-
syncedInSession.set(workdir, currentVersion);
|
|
3565
|
-
return false;
|
|
3566
|
-
}
|
|
3567
|
-
return true;
|
|
3568
|
-
}
|
|
3569
|
-
function markSkillsSyncedForCliVersion(workdir, cliVersion) {
|
|
3570
|
-
saveManifest(workspaceApmDir(workdir), cliVersion);
|
|
3571
|
-
syncedInSession.set(workdir, cliVersion);
|
|
3572
|
-
}
|
|
3573
|
-
|
|
3574
3489
|
// src/commands/connect/upload-package-artifact.ts
|
|
3575
3490
|
import fs2 from "node:fs";
|
|
3576
3491
|
import path2 from "node:path";
|
|
@@ -3690,26 +3605,12 @@ async function handleWebIdePackage(cfg2, msg2, signal) {
|
|
|
3690
3605
|
},
|
|
3691
3606
|
(didInit) => didInit ? "\u5DF2\u521D\u59CB\u5316\u5DE5\u4F5C\u533A" : "\u5DE5\u4F5C\u533A\u5DF2\u5C31\u7EEA"
|
|
3692
3607
|
);
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
await copyWebIdeTemplateFiles(workspaceApmDir(workdir), workdir);
|
|
3700
|
-
markSkillsSyncedForCliVersion(workdir, cliVersion);
|
|
3701
|
-
return cliVersion;
|
|
3702
|
-
},
|
|
3703
|
-
(version) => `\u5DF2\u540C\u6B65\u81F3 CLI ${version}`
|
|
3704
|
-
);
|
|
3705
|
-
} else {
|
|
3706
|
-
eventSession.addCliStep(
|
|
3707
|
-
"\u540C\u6B65 WebIDE \u89C4\u5219",
|
|
3708
|
-
`\u7248\u672C\u4E00\u81F4\uFF08${cliVersion}\uFF09\uFF0C\u8DF3\u8FC7`,
|
|
3709
|
-
"skip"
|
|
3710
|
-
);
|
|
3711
|
-
await syncPrepLog();
|
|
3712
|
-
}
|
|
3608
|
+
if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
|
|
3609
|
+
await runPrepStep(
|
|
3610
|
+
"\u540C\u6B65 WebIDE \u89C4\u5219",
|
|
3611
|
+
async () => syncWebIdeAgentFiles(workdir, cfg2),
|
|
3612
|
+
(result) => result.wrote ? `\u5DF2\u5199\u5165 ${result.ruleCount} \u6761\u89C4\u5219` : "\u89C4\u5219\u672A\u53D8\u5316\uFF0C\u8DF3\u8FC7"
|
|
3613
|
+
);
|
|
3713
3614
|
await runPrepStep(
|
|
3714
3615
|
"\u5DE5\u4F5C\u533A\u4ED3\u5E93\u6E05\u5355",
|
|
3715
3616
|
async () => {
|
|
@@ -3938,6 +3839,7 @@ async function handleStartProject(cfg2, msg2, signal) {
|
|
|
3938
3839
|
try {
|
|
3939
3840
|
if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
|
|
3940
3841
|
await ensureWorkspaceInitialized(workdir);
|
|
3842
|
+
await syncWebIdeAgentFiles(workdir, cfg2);
|
|
3941
3843
|
const api = createApmApiClient(cfg2);
|
|
3942
3844
|
const outcome = await runCursorAgent(
|
|
3943
3845
|
cfg2,
|
|
@@ -4049,8 +3951,8 @@ async function handleStartProject(cfg2, msg2, signal) {
|
|
|
4049
3951
|
}
|
|
4050
3952
|
|
|
4051
3953
|
// src/commands/connect/webide-agent-registry.ts
|
|
4052
|
-
import { existsSync as existsSync7, mkdirSync as
|
|
4053
|
-
import { dirname as
|
|
3954
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
|
|
3955
|
+
import { dirname as dirname3, resolve as resolve6 } from "node:path";
|
|
4054
3956
|
function registryPath(workdir, taskId, fileName = "cursor-agent.json") {
|
|
4055
3957
|
return resolve6(workdir, ".apm", "webide", taskId, fileName);
|
|
4056
3958
|
}
|
|
@@ -4060,7 +3962,7 @@ function readRegistry(path3) {
|
|
|
4060
3962
|
return {};
|
|
4061
3963
|
}
|
|
4062
3964
|
try {
|
|
4063
|
-
const parsed = JSON.parse(
|
|
3965
|
+
const parsed = JSON.parse(readFileSync6(path3, "utf8"));
|
|
4064
3966
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
4065
3967
|
const raw = parsed;
|
|
4066
3968
|
const state = {};
|
|
@@ -4089,7 +3991,7 @@ function readRegistry(path3) {
|
|
|
4089
3991
|
return {};
|
|
4090
3992
|
}
|
|
4091
3993
|
function writeRegistry(path3, registry) {
|
|
4092
|
-
|
|
3994
|
+
mkdirSync5(dirname3(path3), { recursive: true });
|
|
4093
3995
|
writeFileSync5(path3, `${JSON.stringify(registry, null, 2)}
|
|
4094
3996
|
`, "utf8");
|
|
4095
3997
|
}
|
|
@@ -4541,8 +4443,8 @@ async function ensureWebIdePullRequests(cfg2, taskId, workdir) {
|
|
|
4541
4443
|
}
|
|
4542
4444
|
|
|
4543
4445
|
// src/commands/sync-webide-attachments.ts
|
|
4544
|
-
import { existsSync as existsSync9, readFileSync as
|
|
4545
|
-
import { join as
|
|
4446
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
4447
|
+
import { join as join6 } from "path";
|
|
4546
4448
|
var MANIFEST_FILE2 = ".sync-manifest.json";
|
|
4547
4449
|
async function downloadAttachment(cfg2, attachmentId) {
|
|
4548
4450
|
const base = cfg2.baseUrl.trim().replace(/\/+$/, "");
|
|
@@ -4557,14 +4459,14 @@ async function downloadAttachment(cfg2, attachmentId) {
|
|
|
4557
4459
|
}
|
|
4558
4460
|
return Buffer.from(await res.arrayBuffer());
|
|
4559
4461
|
}
|
|
4560
|
-
function
|
|
4561
|
-
const path3 =
|
|
4462
|
+
function loadManifest(dir) {
|
|
4463
|
+
const path3 = join6(dir, MANIFEST_FILE2);
|
|
4562
4464
|
if (!existsSync9(path3)) {
|
|
4563
4465
|
return { version: 1, attachments: {} };
|
|
4564
4466
|
}
|
|
4565
4467
|
try {
|
|
4566
4468
|
const parsed = JSON.parse(
|
|
4567
|
-
|
|
4469
|
+
readFileSync7(path3, "utf8")
|
|
4568
4470
|
);
|
|
4569
4471
|
if (parsed?.version === 1 && parsed.attachments && typeof parsed.attachments === "object") {
|
|
4570
4472
|
return parsed;
|
|
@@ -4573,9 +4475,9 @@ function loadManifest2(dir) {
|
|
|
4573
4475
|
}
|
|
4574
4476
|
return { version: 1, attachments: {} };
|
|
4575
4477
|
}
|
|
4576
|
-
function
|
|
4478
|
+
function saveManifest(dir, manifest) {
|
|
4577
4479
|
writeFileSync6(
|
|
4578
|
-
|
|
4480
|
+
join6(dir, MANIFEST_FILE2),
|
|
4579
4481
|
`${JSON.stringify(manifest, null, 2)}
|
|
4580
4482
|
`,
|
|
4581
4483
|
"utf8"
|
|
@@ -4590,14 +4492,14 @@ function isAttachmentUpToDate(entry, item, dest) {
|
|
|
4590
4492
|
async function syncAttachmentsToDirectory(cfg2, attachments, dir, logLabel) {
|
|
4591
4493
|
await ensureDirExists(dir);
|
|
4592
4494
|
if (attachments.length === 0) {
|
|
4593
|
-
|
|
4495
|
+
saveManifest(dir, { version: 1, attachments: {} });
|
|
4594
4496
|
return [];
|
|
4595
4497
|
}
|
|
4596
|
-
const manifest =
|
|
4498
|
+
const manifest = loadManifest(dir);
|
|
4597
4499
|
const nextManifest = { version: 1, attachments: {} };
|
|
4598
4500
|
const names = [];
|
|
4599
4501
|
for (const item of attachments) {
|
|
4600
|
-
const dest =
|
|
4502
|
+
const dest = join6(dir, item.name);
|
|
4601
4503
|
const entry = manifest.attachments[item.id];
|
|
4602
4504
|
const createdAt = item.createdAt ?? "";
|
|
4603
4505
|
names.push(item.name);
|
|
@@ -4614,7 +4516,7 @@ async function syncAttachmentsToDirectory(cfg2, attachments, dir, logLabel) {
|
|
|
4614
4516
|
};
|
|
4615
4517
|
console.log(`[apm] \u5DF2\u4E0B\u8F7D\u9644\u4EF6: ${logLabel}/${item.name}`);
|
|
4616
4518
|
}
|
|
4617
|
-
|
|
4519
|
+
saveManifest(dir, nextManifest);
|
|
4618
4520
|
return names;
|
|
4619
4521
|
}
|
|
4620
4522
|
async function syncWebIdeAttachments(cfg2, taskId, workdir, attachments) {
|
|
@@ -4629,19 +4531,34 @@ async function syncWebIdeAttachments(cfg2, taskId, workdir, attachments) {
|
|
|
4629
4531
|
|
|
4630
4532
|
// src/commands/sync-webide-design.ts
|
|
4631
4533
|
import { createHash as createHash3 } from "crypto";
|
|
4632
|
-
import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as
|
|
4633
|
-
import { join as
|
|
4534
|
+
import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync5, writeFileSync as writeFileSync7 } from "fs";
|
|
4535
|
+
import { join as join7 } from "path";
|
|
4536
|
+
|
|
4537
|
+
// src/opc-shared-types.ts
|
|
4538
|
+
function webIdeDesignObjectKey(taskId, fileName) {
|
|
4539
|
+
const safe = fileName.replace(/[/\\:*?"<>|]/g, "_").trim() || "index.html";
|
|
4540
|
+
return `tasks/${taskId.trim()}/design/${safe}`;
|
|
4541
|
+
}
|
|
4542
|
+
function isWebIdeDesignArtifactName(name) {
|
|
4543
|
+
const lower = name.trim().toLowerCase();
|
|
4544
|
+
return lower.endsWith(".html") || lower.endsWith(".css");
|
|
4545
|
+
}
|
|
4546
|
+
function webIdeDesignArtifactContentType(name) {
|
|
4547
|
+
return name.trim().toLowerCase().endsWith(".css") ? "text/css; charset=utf-8" : "text/html; charset=utf-8";
|
|
4548
|
+
}
|
|
4549
|
+
|
|
4550
|
+
// src/commands/sync-webide-design.ts
|
|
4634
4551
|
var MANIFEST_FILE3 = ".sync-manifest.json";
|
|
4635
4552
|
function hashBuffer(buf) {
|
|
4636
4553
|
return createHash3("sha256").update(buf).digest("hex");
|
|
4637
4554
|
}
|
|
4638
|
-
function
|
|
4639
|
-
const path3 =
|
|
4555
|
+
function loadManifest2(dir) {
|
|
4556
|
+
const path3 = join7(dir, MANIFEST_FILE3);
|
|
4640
4557
|
if (!existsSync10(path3)) {
|
|
4641
4558
|
return { version: 1, files: {} };
|
|
4642
4559
|
}
|
|
4643
4560
|
try {
|
|
4644
|
-
const parsed = JSON.parse(
|
|
4561
|
+
const parsed = JSON.parse(readFileSync8(path3, "utf8"));
|
|
4645
4562
|
if (parsed?.version === 1 && parsed.files && typeof parsed.files === "object") {
|
|
4646
4563
|
return parsed;
|
|
4647
4564
|
}
|
|
@@ -4649,9 +4566,9 @@ function loadManifest3(dir) {
|
|
|
4649
4566
|
}
|
|
4650
4567
|
return { version: 1, files: {} };
|
|
4651
4568
|
}
|
|
4652
|
-
function
|
|
4569
|
+
function saveManifest2(dir, manifest) {
|
|
4653
4570
|
writeFileSync7(
|
|
4654
|
-
|
|
4571
|
+
join7(dir, MANIFEST_FILE3),
|
|
4655
4572
|
`${JSON.stringify(manifest, null, 2)}
|
|
4656
4573
|
`,
|
|
4657
4574
|
"utf8"
|
|
@@ -4674,12 +4591,12 @@ async function downloadDesignFile(cfg2, taskId, name) {
|
|
|
4674
4591
|
async function syncWebIdeDesign(cfg2, taskId, workdir, artifacts) {
|
|
4675
4592
|
const dir = webideDesignDir(taskId, workdir);
|
|
4676
4593
|
await ensureDirExists(dir);
|
|
4677
|
-
const manifest =
|
|
4594
|
+
const manifest = loadManifest2(dir);
|
|
4678
4595
|
const synced = [];
|
|
4679
4596
|
for (const art of artifacts) {
|
|
4680
4597
|
const name = art.name?.trim();
|
|
4681
|
-
if (!name || !name
|
|
4682
|
-
const localPath =
|
|
4598
|
+
if (!name || !isWebIdeDesignArtifactName(name)) continue;
|
|
4599
|
+
const localPath = join7(dir, name);
|
|
4683
4600
|
const entry = manifest.files[name];
|
|
4684
4601
|
if (entry?.contentHash === art.contentHash && existsSync10(localPath)) {
|
|
4685
4602
|
continue;
|
|
@@ -4689,42 +4606,35 @@ async function syncWebIdeDesign(cfg2, taskId, workdir, artifacts) {
|
|
|
4689
4606
|
manifest.files[name] = { contentHash: hashBuffer(buf) };
|
|
4690
4607
|
synced.push(name);
|
|
4691
4608
|
}
|
|
4692
|
-
|
|
4609
|
+
saveManifest2(dir, manifest);
|
|
4693
4610
|
return synced;
|
|
4694
4611
|
}
|
|
4695
|
-
function
|
|
4612
|
+
function listLocalDesignArtifactFiles(taskId, workdir) {
|
|
4696
4613
|
const dir = webideDesignDir(taskId, workdir);
|
|
4697
4614
|
if (!existsSync10(dir)) return [];
|
|
4698
4615
|
const out = [];
|
|
4699
4616
|
for (const name of readdirSync4(dir)) {
|
|
4700
|
-
if (!name
|
|
4701
|
-
const absPath =
|
|
4702
|
-
|
|
4617
|
+
if (!isWebIdeDesignArtifactName(name)) continue;
|
|
4618
|
+
const absPath = join7(dir, name);
|
|
4619
|
+
if (!statSync5(absPath).isFile()) continue;
|
|
4620
|
+
const buf = readFileSync8(absPath);
|
|
4703
4621
|
if (buf.length === 0) continue;
|
|
4704
4622
|
out.push({ name, absPath, contentHash: hashBuffer(buf) });
|
|
4705
4623
|
}
|
|
4706
4624
|
return out;
|
|
4707
4625
|
}
|
|
4708
4626
|
|
|
4709
|
-
// src/opc-shared-types.ts
|
|
4710
|
-
function webIdeDesignObjectKey(taskId, fileName) {
|
|
4711
|
-
const safe = fileName.replace(/[/\\:*?"<>|]/g, "_").trim() || "index.html";
|
|
4712
|
-
return `tasks/${taskId.trim()}/design/${safe}`;
|
|
4713
|
-
}
|
|
4714
|
-
|
|
4715
4627
|
// src/commands/connect/upload-webide-design.ts
|
|
4716
4628
|
async function uploadWebIdeDesignArtifacts(cfg2, taskId, workdir) {
|
|
4717
|
-
const locals =
|
|
4718
|
-
if (locals.
|
|
4629
|
+
const locals = listLocalDesignArtifactFiles(taskId, workdir);
|
|
4630
|
+
if (!locals.some((file) => file.name.toLowerCase().endsWith(".html"))) {
|
|
4719
4631
|
throw new Error(
|
|
4720
4632
|
`\u8BBE\u8BA1\u76EE\u5F55\u65E0 HTML \u4EA7\u7269\uFF1A.apm/webide/${taskId}/design/\uFF08\u8BF7\u5199\u5165\u81F3\u5C11\u4E00\u4EFD .html\uFF09`
|
|
4721
4633
|
);
|
|
4722
4634
|
}
|
|
4723
4635
|
const api = createApmApiClient(cfg2);
|
|
4724
4636
|
const remote = await api.cli.webideListDesignArtifacts({ taskId }) ?? [];
|
|
4725
|
-
const remoteByName = new Map(
|
|
4726
|
-
remote.map((r) => [r.name, r])
|
|
4727
|
-
);
|
|
4637
|
+
const remoteByName = new Map(remote.map((r) => [r.name, r]));
|
|
4728
4638
|
const { client, bucket } = await createApmLogMinioClient(cfg2);
|
|
4729
4639
|
await client.ensureBucket(bucket);
|
|
4730
4640
|
let uploaded = 0;
|
|
@@ -4743,7 +4653,7 @@ async function uploadWebIdeDesignArtifacts(cfg2, taskId, workdir) {
|
|
|
4743
4653
|
continue;
|
|
4744
4654
|
}
|
|
4745
4655
|
await client.fPutObject(bucket, objectKey, file.absPath, {
|
|
4746
|
-
"Content-Type":
|
|
4656
|
+
"Content-Type": webIdeDesignArtifactContentType(file.name)
|
|
4747
4657
|
});
|
|
4748
4658
|
uploaded += 1;
|
|
4749
4659
|
artifacts.push({
|
|
@@ -4982,26 +4892,12 @@ async function handleWebIdeInboundMessage(cfg2, msg2, signal) {
|
|
|
4982
4892
|
},
|
|
4983
4893
|
(didInit) => didInit ? "\u5DF2\u521D\u59CB\u5316\u5DE5\u4F5C\u533A" : "\u5DE5\u4F5C\u533A\u5DF2\u5C31\u7EEA"
|
|
4984
4894
|
);
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
await copyWebIdeTemplateFiles(workspaceApmDir(workdir), workdir);
|
|
4992
|
-
markSkillsSyncedForCliVersion(workdir, cliVersion);
|
|
4993
|
-
return cliVersion;
|
|
4994
|
-
},
|
|
4995
|
-
(version) => `\u5DF2\u540C\u6B65\u81F3 CLI ${version}`
|
|
4996
|
-
);
|
|
4997
|
-
} else {
|
|
4998
|
-
eventSession.addCliStep(
|
|
4999
|
-
"\u540C\u6B65 WebIDE \u89C4\u5219",
|
|
5000
|
-
`\u7248\u672C\u4E00\u81F4\uFF08${cliVersion}\uFF09\uFF0C\u8DF3\u8FC7`,
|
|
5001
|
-
"skip"
|
|
5002
|
-
);
|
|
5003
|
-
await syncPrepLog();
|
|
5004
|
-
}
|
|
4895
|
+
if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
|
|
4896
|
+
await runPrepStep(
|
|
4897
|
+
"\u540C\u6B65 WebIDE \u89C4\u5219",
|
|
4898
|
+
async () => syncWebIdeAgentFiles(workdir, cfg2),
|
|
4899
|
+
(result) => result.wrote ? `\u5DF2\u5199\u5165 ${result.ruleCount} \u6761\u89C4\u5219` : "\u89C4\u5219\u672A\u53D8\u5316\uFF0C\u8DF3\u8FC7"
|
|
4900
|
+
);
|
|
5005
4901
|
await runPrepStep(
|
|
5006
4902
|
"\u5DE5\u4F5C\u533A\u4ED3\u5E93\u6E05\u5355",
|
|
5007
4903
|
async () => {
|