ai-project-manage-cli 7.1.15 → 7.1.16
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 +29 -12
- package/dist/webide-message-worker.js +135 -14
- package/package.json +1 -1
- package/template/AGENTS.md +4 -0
package/dist/index.js
CHANGED
|
@@ -184,6 +184,10 @@ var init_request_config = __esm({
|
|
|
184
184
|
method: "GET",
|
|
185
185
|
path: "/cli/webide/assumptions"
|
|
186
186
|
}),
|
|
187
|
+
webideListAttachments: defineEndpoint({
|
|
188
|
+
method: "GET",
|
|
189
|
+
path: "/cli/webide/attachments"
|
|
190
|
+
}),
|
|
187
191
|
webideRecommendPlan: defineEndpoint({
|
|
188
192
|
method: "PUT",
|
|
189
193
|
path: "/cli/webide/plan-recommendation"
|
|
@@ -220,10 +224,12 @@ var init_request_config = __esm({
|
|
|
220
224
|
method: "GET",
|
|
221
225
|
path: "/cli/tasks/branch-baseline"
|
|
222
226
|
}),
|
|
223
|
-
projectBaseBranch: defineEndpoint(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
+
projectBaseBranch: defineEndpoint(
|
|
228
|
+
{
|
|
229
|
+
method: "GET",
|
|
230
|
+
path: "/cli/tasks/project-base-branch"
|
|
231
|
+
}
|
|
232
|
+
),
|
|
227
233
|
listSessionsForBranchCleanup: defineEndpoint({
|
|
228
234
|
method: "GET",
|
|
229
235
|
path: "/cli/sessions/branch-cleanup"
|
|
@@ -2498,7 +2504,9 @@ import { join as join6 } from "path";
|
|
|
2498
2504
|
var MANIFEST_FILE2 = ".sync-manifest.json";
|
|
2499
2505
|
async function downloadAttachment(cfg, attachmentId) {
|
|
2500
2506
|
const base = cfg.baseUrl.trim().replace(/\/+$/, "");
|
|
2501
|
-
const url = `${base}/api/v1/tasks/attachments/file?${new URLSearchParams({
|
|
2507
|
+
const url = `${base}/api/v1/tasks/attachments/file?${new URLSearchParams({
|
|
2508
|
+
attachmentId
|
|
2509
|
+
})}`;
|
|
2502
2510
|
const res = await fetch(url);
|
|
2503
2511
|
if (!res.ok) {
|
|
2504
2512
|
throw new Error(
|
|
@@ -2537,24 +2545,23 @@ function isAttachmentUpToDate(entry, item, dest) {
|
|
|
2537
2545
|
const createdAt = item.createdAt ?? "";
|
|
2538
2546
|
return entry.createdAt === createdAt;
|
|
2539
2547
|
}
|
|
2540
|
-
async function
|
|
2541
|
-
const dir = join6(sessionDir(sessionId, apmRoot), SESSION_ATTACHMENTS_SUBDIR);
|
|
2548
|
+
async function syncAttachmentsToDirectory(cfg, attachments, dir, logLabel) {
|
|
2542
2549
|
await ensureDirExists(dir);
|
|
2543
2550
|
if (attachments.length === 0) {
|
|
2544
2551
|
saveManifest(dir, { version: 1, attachments: {} });
|
|
2545
|
-
return;
|
|
2552
|
+
return [];
|
|
2546
2553
|
}
|
|
2547
2554
|
const manifest = loadManifest(dir);
|
|
2548
2555
|
const nextManifest = { version: 1, attachments: {} };
|
|
2556
|
+
const names = [];
|
|
2549
2557
|
for (const item of attachments) {
|
|
2550
2558
|
const dest = join6(dir, item.name);
|
|
2551
2559
|
const entry = manifest.attachments[item.id];
|
|
2552
2560
|
const createdAt = item.createdAt ?? "";
|
|
2561
|
+
names.push(item.name);
|
|
2553
2562
|
if (isAttachmentUpToDate(entry, item, dest)) {
|
|
2554
2563
|
nextManifest.attachments[item.id] = entry;
|
|
2555
|
-
console.log(
|
|
2556
|
-
`[apm] \u9644\u4EF6\u65E0\u53D8\u5316\uFF0C\u5DF2\u8DF3\u8FC7: ${SESSION_ATTACHMENTS_SUBDIR}/${item.name}`
|
|
2557
|
-
);
|
|
2564
|
+
console.log(`[apm] \u9644\u4EF6\u65E0\u53D8\u5316\uFF0C\u5DF2\u8DF3\u8FC7: ${logLabel}/${item.name}`);
|
|
2558
2565
|
continue;
|
|
2559
2566
|
}
|
|
2560
2567
|
const buffer = await downloadAttachment(cfg, item.id);
|
|
@@ -2563,9 +2570,19 @@ async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
|
|
|
2563
2570
|
name: item.name,
|
|
2564
2571
|
createdAt
|
|
2565
2572
|
};
|
|
2566
|
-
console.log(`[apm] \u5DF2\u4E0B\u8F7D\u9644\u4EF6: ${
|
|
2573
|
+
console.log(`[apm] \u5DF2\u4E0B\u8F7D\u9644\u4EF6: ${logLabel}/${item.name}`);
|
|
2567
2574
|
}
|
|
2568
2575
|
saveManifest(dir, nextManifest);
|
|
2576
|
+
return names;
|
|
2577
|
+
}
|
|
2578
|
+
async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
|
|
2579
|
+
const dir = join6(sessionDir(sessionId, apmRoot), SESSION_ATTACHMENTS_SUBDIR);
|
|
2580
|
+
return syncAttachmentsToDirectory(
|
|
2581
|
+
cfg,
|
|
2582
|
+
attachments,
|
|
2583
|
+
dir,
|
|
2584
|
+
SESSION_ATTACHMENTS_SUBDIR
|
|
2585
|
+
);
|
|
2569
2586
|
}
|
|
2570
2587
|
|
|
2571
2588
|
// src/rules-sync.ts
|
|
@@ -88,6 +88,10 @@ var requestConfig = {
|
|
|
88
88
|
method: "GET",
|
|
89
89
|
path: "/cli/webide/assumptions"
|
|
90
90
|
}),
|
|
91
|
+
webideListAttachments: defineEndpoint({
|
|
92
|
+
method: "GET",
|
|
93
|
+
path: "/cli/webide/attachments"
|
|
94
|
+
}),
|
|
91
95
|
webideRecommendPlan: defineEndpoint({
|
|
92
96
|
method: "PUT",
|
|
93
97
|
path: "/cli/webide/plan-recommendation"
|
|
@@ -124,10 +128,12 @@ var requestConfig = {
|
|
|
124
128
|
method: "GET",
|
|
125
129
|
path: "/cli/tasks/branch-baseline"
|
|
126
130
|
}),
|
|
127
|
-
projectBaseBranch: defineEndpoint(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
+
projectBaseBranch: defineEndpoint(
|
|
132
|
+
{
|
|
133
|
+
method: "GET",
|
|
134
|
+
path: "/cli/tasks/project-base-branch"
|
|
135
|
+
}
|
|
136
|
+
),
|
|
131
137
|
listSessionsForBranchCleanup: defineEndpoint({
|
|
132
138
|
method: "GET",
|
|
133
139
|
path: "/cli/sessions/branch-cleanup"
|
|
@@ -591,6 +597,14 @@ function assertApmGitignoredInRepo(workdir) {
|
|
|
591
597
|
);
|
|
592
598
|
}
|
|
593
599
|
}
|
|
600
|
+
var SESSION_ATTACHMENTS_SUBDIR = "attachments";
|
|
601
|
+
var WEBIDE_SUBDIR = "webide";
|
|
602
|
+
function webideTaskDir(taskId, workdir) {
|
|
603
|
+
return join2(workdir, ".apm", WEBIDE_SUBDIR, taskId);
|
|
604
|
+
}
|
|
605
|
+
function webideAttachmentsDir(taskId, workdir) {
|
|
606
|
+
return join2(webideTaskDir(taskId, workdir), SESSION_ATTACHMENTS_SUBDIR);
|
|
607
|
+
}
|
|
594
608
|
async function ensureLoggedConfig() {
|
|
595
609
|
const cfg = await ensureApmConfig();
|
|
596
610
|
if (!resolveApiKey(cfg)) {
|
|
@@ -3087,21 +3101,108 @@ async function syncWorkspaceSkills(cfg, workdir) {
|
|
|
3087
3101
|
);
|
|
3088
3102
|
}
|
|
3089
3103
|
|
|
3090
|
-
// src/commands/
|
|
3104
|
+
// src/commands/sync-session-attachments.ts
|
|
3091
3105
|
import { existsSync as existsSync8, readFileSync as readFileSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
3092
3106
|
import { join as join11 } from "path";
|
|
3107
|
+
var MANIFEST_FILE2 = ".sync-manifest.json";
|
|
3108
|
+
async function downloadAttachment(cfg, attachmentId) {
|
|
3109
|
+
const base = cfg.baseUrl.trim().replace(/\/+$/, "");
|
|
3110
|
+
const url = `${base}/api/v1/tasks/attachments/file?${new URLSearchParams({
|
|
3111
|
+
attachmentId
|
|
3112
|
+
})}`;
|
|
3113
|
+
const res = await fetch(url);
|
|
3114
|
+
if (!res.ok) {
|
|
3115
|
+
throw new Error(
|
|
3116
|
+
`[apm] \u4E0B\u8F7D\u9644\u4EF6\u5931\u8D25 (${res.status}): attachmentId=${attachmentId}`
|
|
3117
|
+
);
|
|
3118
|
+
}
|
|
3119
|
+
return Buffer.from(await res.arrayBuffer());
|
|
3120
|
+
}
|
|
3121
|
+
function loadManifest(dir) {
|
|
3122
|
+
const path = join11(dir, MANIFEST_FILE2);
|
|
3123
|
+
if (!existsSync8(path)) {
|
|
3124
|
+
return { version: 1, attachments: {} };
|
|
3125
|
+
}
|
|
3126
|
+
try {
|
|
3127
|
+
const parsed = JSON.parse(
|
|
3128
|
+
readFileSync9(path, "utf8")
|
|
3129
|
+
);
|
|
3130
|
+
if (parsed?.version === 1 && parsed.attachments && typeof parsed.attachments === "object") {
|
|
3131
|
+
return parsed;
|
|
3132
|
+
}
|
|
3133
|
+
} catch {
|
|
3134
|
+
}
|
|
3135
|
+
return { version: 1, attachments: {} };
|
|
3136
|
+
}
|
|
3137
|
+
function saveManifest(dir, manifest) {
|
|
3138
|
+
writeFileSync10(
|
|
3139
|
+
join11(dir, MANIFEST_FILE2),
|
|
3140
|
+
`${JSON.stringify(manifest, null, 2)}
|
|
3141
|
+
`,
|
|
3142
|
+
"utf8"
|
|
3143
|
+
);
|
|
3144
|
+
}
|
|
3145
|
+
function isAttachmentUpToDate(entry, item, dest) {
|
|
3146
|
+
if (!entry || !existsSync8(dest)) return false;
|
|
3147
|
+
if (entry.name !== item.name) return false;
|
|
3148
|
+
const createdAt = item.createdAt ?? "";
|
|
3149
|
+
return entry.createdAt === createdAt;
|
|
3150
|
+
}
|
|
3151
|
+
async function syncAttachmentsToDirectory(cfg, attachments, dir, logLabel) {
|
|
3152
|
+
await ensureDirExists(dir);
|
|
3153
|
+
if (attachments.length === 0) {
|
|
3154
|
+
saveManifest(dir, { version: 1, attachments: {} });
|
|
3155
|
+
return [];
|
|
3156
|
+
}
|
|
3157
|
+
const manifest = loadManifest(dir);
|
|
3158
|
+
const nextManifest = { version: 1, attachments: {} };
|
|
3159
|
+
const names = [];
|
|
3160
|
+
for (const item of attachments) {
|
|
3161
|
+
const dest = join11(dir, item.name);
|
|
3162
|
+
const entry = manifest.attachments[item.id];
|
|
3163
|
+
const createdAt = item.createdAt ?? "";
|
|
3164
|
+
names.push(item.name);
|
|
3165
|
+
if (isAttachmentUpToDate(entry, item, dest)) {
|
|
3166
|
+
nextManifest.attachments[item.id] = entry;
|
|
3167
|
+
console.log(`[apm] \u9644\u4EF6\u65E0\u53D8\u5316\uFF0C\u5DF2\u8DF3\u8FC7: ${logLabel}/${item.name}`);
|
|
3168
|
+
continue;
|
|
3169
|
+
}
|
|
3170
|
+
const buffer = await downloadAttachment(cfg, item.id);
|
|
3171
|
+
writeFileSync10(dest, buffer);
|
|
3172
|
+
nextManifest.attachments[item.id] = {
|
|
3173
|
+
name: item.name,
|
|
3174
|
+
createdAt
|
|
3175
|
+
};
|
|
3176
|
+
console.log(`[apm] \u5DF2\u4E0B\u8F7D\u9644\u4EF6: ${logLabel}/${item.name}`);
|
|
3177
|
+
}
|
|
3178
|
+
saveManifest(dir, nextManifest);
|
|
3179
|
+
return names;
|
|
3180
|
+
}
|
|
3181
|
+
async function syncWebIdeAttachments(cfg, taskId, workdir, attachments) {
|
|
3182
|
+
const dir = webideAttachmentsDir(taskId, workdir);
|
|
3183
|
+
return syncAttachmentsToDirectory(
|
|
3184
|
+
cfg,
|
|
3185
|
+
attachments,
|
|
3186
|
+
dir,
|
|
3187
|
+
`.apm/webide/${taskId}/attachments`
|
|
3188
|
+
);
|
|
3189
|
+
}
|
|
3190
|
+
|
|
3191
|
+
// src/commands/connect/cli-version-sync.ts
|
|
3192
|
+
import { existsSync as existsSync9, readFileSync as readFileSync10, writeFileSync as writeFileSync11 } from "fs";
|
|
3193
|
+
import { join as join12 } from "path";
|
|
3093
3194
|
var CLI_VERSION_FILE = ".cli-version.json";
|
|
3094
3195
|
function manifestPath2(apmDir) {
|
|
3095
|
-
return
|
|
3196
|
+
return join12(apmDir, CLI_VERSION_FILE);
|
|
3096
3197
|
}
|
|
3097
|
-
function
|
|
3198
|
+
function loadManifest2(apmDir) {
|
|
3098
3199
|
const path = toFsPath(manifestPath2(apmDir));
|
|
3099
|
-
if (!
|
|
3200
|
+
if (!existsSync9(path)) {
|
|
3100
3201
|
return null;
|
|
3101
3202
|
}
|
|
3102
3203
|
try {
|
|
3103
3204
|
const parsed = JSON.parse(
|
|
3104
|
-
|
|
3205
|
+
readFileSync10(path, "utf8")
|
|
3105
3206
|
);
|
|
3106
3207
|
if (parsed?.version === 1 && typeof parsed.cliVersion === "string" && parsed.cliVersion.trim()) {
|
|
3107
3208
|
return parsed;
|
|
@@ -3110,9 +3211,9 @@ function loadManifest(apmDir) {
|
|
|
3110
3211
|
}
|
|
3111
3212
|
return null;
|
|
3112
3213
|
}
|
|
3113
|
-
function
|
|
3214
|
+
function saveManifest2(apmDir, cliVersion) {
|
|
3114
3215
|
const manifest = { version: 1, cliVersion };
|
|
3115
|
-
|
|
3216
|
+
writeFileSync11(
|
|
3116
3217
|
toFsPath(manifestPath2(apmDir)),
|
|
3117
3218
|
`${JSON.stringify(manifest, null, 2)}
|
|
3118
3219
|
`,
|
|
@@ -3125,7 +3226,7 @@ function shouldSyncSkillsForCliVersion(workdir, currentVersion) {
|
|
|
3125
3226
|
if (cached === currentVersion) {
|
|
3126
3227
|
return false;
|
|
3127
3228
|
}
|
|
3128
|
-
const stored =
|
|
3229
|
+
const stored = loadManifest2(workspaceApmDir(workdir));
|
|
3129
3230
|
if (stored?.cliVersion === currentVersion) {
|
|
3130
3231
|
syncedInSession.set(workdir, currentVersion);
|
|
3131
3232
|
return false;
|
|
@@ -3133,7 +3234,7 @@ function shouldSyncSkillsForCliVersion(workdir, currentVersion) {
|
|
|
3133
3234
|
return true;
|
|
3134
3235
|
}
|
|
3135
3236
|
function markSkillsSyncedForCliVersion(workdir, cliVersion) {
|
|
3136
|
-
|
|
3237
|
+
saveManifest2(workspaceApmDir(workdir), cliVersion);
|
|
3137
3238
|
syncedInSession.set(workdir, cliVersion);
|
|
3138
3239
|
}
|
|
3139
3240
|
|
|
@@ -3206,6 +3307,27 @@ async function handleWebIdeInboundMessage(cfg, msg, signal, options) {
|
|
|
3206
3307
|
if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
|
|
3207
3308
|
await ensureWebIdePullRequests(cfg, taskId, workdir);
|
|
3208
3309
|
}
|
|
3310
|
+
if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
|
|
3311
|
+
const api = createApmApiClient(cfg);
|
|
3312
|
+
try {
|
|
3313
|
+
const attachments = await api.cli.webideListAttachments({ taskId });
|
|
3314
|
+
const names = await syncWebIdeAttachments(
|
|
3315
|
+
cfg,
|
|
3316
|
+
taskId,
|
|
3317
|
+
workdir,
|
|
3318
|
+
attachments ?? []
|
|
3319
|
+
);
|
|
3320
|
+
if (names.length > 0) {
|
|
3321
|
+
console.log(
|
|
3322
|
+
`[apm] webide \u9644\u4EF6\u5DF2\u5C31\u7EEA count=${names.length} dir=.apm/webide/${taskId}/attachments`
|
|
3323
|
+
);
|
|
3324
|
+
}
|
|
3325
|
+
} catch (err) {
|
|
3326
|
+
console.warn(
|
|
3327
|
+
"[apm] WebIDE \u9644\u4EF6\u540C\u6B65\u5931\u8D25:",
|
|
3328
|
+
err instanceof Error ? err.message : err
|
|
3329
|
+
);
|
|
3330
|
+
}
|
|
3209
3331
|
const savedAgentId = loadWebIdeAgentId(workdir, taskId);
|
|
3210
3332
|
const logSyncRef = { current: null };
|
|
3211
3333
|
const outcome = await runCursorAgent(
|
|
@@ -3272,7 +3394,6 @@ async function handleWebIdeInboundMessage(cfg, msg, signal, options) {
|
|
|
3272
3394
|
result: outcome.result,
|
|
3273
3395
|
createPlan: outcome.createPlan
|
|
3274
3396
|
});
|
|
3275
|
-
const api = createApmApiClient(cfg);
|
|
3276
3397
|
await api.cli.webideEnsureMessageContent({
|
|
3277
3398
|
id: messageId,
|
|
3278
3399
|
content: fallback
|
package/package.json
CHANGED
package/template/AGENTS.md
CHANGED
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
- 任务涉及菜单名、路由、业务术语等时,**先 Read manifest 与相关文档**,禁止猜测路径
|
|
41
41
|
|
|
42
42
|
- 本轮任务需要关注的文档指引(.apm/sessions/<会话 ID>/\*):
|
|
43
|
+
|
|
43
44
|
- 本轮会话状态: `session.yaml`,从这里可以看到每个成员的信息,找到可以协助你一起解决问题的人,可以结合 `RULE.md`一起看
|
|
44
45
|
- 群文档: `docs/xxxx.md`,当需要相关上下文可以在这里查找,按需阅读
|
|
45
46
|
- 附件列表: `attachments/*`,当有文档中提及附件时,从这里查找
|
|
@@ -47,3 +48,6 @@
|
|
|
47
48
|
- 协作 TODO: `TODO.md`,跨轮次任务清单(待办与已完成项),按需阅读
|
|
48
49
|
- 历史消息记录: `messages.xml`,历史消息列表,数据量很大,按需阅读
|
|
49
50
|
- 初始目标: `TASK.md`,最初的目标,不一定具体,团队成员会有人负责让这个任务变得具体,仅供参考。如果你是相关的角色,则你需要先读取这个目标,然后规划接下来的动作。
|
|
51
|
+
|
|
52
|
+
- WebIDE 任务附件(`.apm/webide/<taskId>/attachments/`):
|
|
53
|
+
- `apm connect` 处理 webide-message 时会自动同步;prompt 中若出现「任务附件」指引,请按路径查看相关文件
|