ai-project-manage-cli 6.0.64 → 6.0.65
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 +149 -403
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -473,33 +473,19 @@ var requestConfig = {
|
|
|
473
473
|
method: "DELETE",
|
|
474
474
|
path: "/cli/repository-project-documents"
|
|
475
475
|
}),
|
|
476
|
-
|
|
476
|
+
updateTaskDeploymentStatus: defineEndpoint({
|
|
477
477
|
method: "PUT",
|
|
478
|
-
path: "/cli/
|
|
478
|
+
path: "/cli/task-deployments/status"
|
|
479
479
|
}),
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}),
|
|
488
|
-
updateCoordinatorDispatchStatus: defineEndpoint({
|
|
489
|
-
method: "PUT",
|
|
490
|
-
path: "/cli/coordinator-dispatches/status"
|
|
491
|
-
}),
|
|
492
|
-
appendCoordinatorDispatchResponse: defineEndpoint({
|
|
493
|
-
method: "PUT",
|
|
494
|
-
path: "/cli/coordinator-dispatches/append-response"
|
|
495
|
-
}),
|
|
496
|
-
completeCoordinatorDispatch: defineEndpoint({
|
|
480
|
+
syncTaskDeploymentLog: defineEndpoint(
|
|
481
|
+
{
|
|
482
|
+
method: "PUT",
|
|
483
|
+
path: "/cli/task-deployments/log"
|
|
484
|
+
}
|
|
485
|
+
),
|
|
486
|
+
completeTaskDeployment: defineEndpoint({
|
|
497
487
|
method: "PUT",
|
|
498
|
-
path: "/cli/
|
|
499
|
-
}),
|
|
500
|
-
createCoordinatorDispatchQuestions: defineEndpoint({
|
|
501
|
-
method: "POST",
|
|
502
|
-
path: "/cli/coordinator-dispatches/questions"
|
|
488
|
+
path: "/cli/task-deployments/complete"
|
|
503
489
|
})
|
|
504
490
|
}
|
|
505
491
|
};
|
|
@@ -1760,8 +1746,12 @@ function registryBaseUrl() {
|
|
|
1760
1746
|
const fromEnv = process.env.npm_config_registry?.trim() || process.env.NPM_CONFIG_REGISTRY?.trim();
|
|
1761
1747
|
return (fromEnv || "https://registry.npmjs.org").replace(/\/+$/, "");
|
|
1762
1748
|
}
|
|
1763
|
-
|
|
1764
|
-
const
|
|
1749
|
+
function parseMajorVersion(version) {
|
|
1750
|
+
const m = /^(\d+)/.exec(version.trim());
|
|
1751
|
+
return m ? Number(m[1]) : 0;
|
|
1752
|
+
}
|
|
1753
|
+
async function fetchPublishedVersion(spec) {
|
|
1754
|
+
const url = `${registryBaseUrl()}/${CLI_PACKAGE_NAME}/${spec}`;
|
|
1765
1755
|
try {
|
|
1766
1756
|
const res = await fetch(url);
|
|
1767
1757
|
if (!res.ok) return null;
|
|
@@ -1771,28 +1761,73 @@ async function fetchLatestPublishedVersion() {
|
|
|
1771
1761
|
return null;
|
|
1772
1762
|
}
|
|
1773
1763
|
}
|
|
1764
|
+
async function fetchLatestPublishedVersion() {
|
|
1765
|
+
return fetchPublishedVersion("latest");
|
|
1766
|
+
}
|
|
1767
|
+
async function fetchLatestPublishedVersionInMajor(major) {
|
|
1768
|
+
return fetchPublishedVersion(String(major));
|
|
1769
|
+
}
|
|
1770
|
+
function resolveUpdateTarget(input) {
|
|
1771
|
+
const { current, allowMajorUpgrade, latestInMajor, globalLatest } = input;
|
|
1772
|
+
const currentMajor = parseMajorVersion(current);
|
|
1773
|
+
if (allowMajorUpgrade) {
|
|
1774
|
+
if (globalLatest && globalLatest === current) {
|
|
1775
|
+
return { action: "skip" };
|
|
1776
|
+
}
|
|
1777
|
+
return {
|
|
1778
|
+
action: "install",
|
|
1779
|
+
installSpec: `${CLI_PACKAGE_NAME}@latest`,
|
|
1780
|
+
targetLabel: globalLatest ?? "latest",
|
|
1781
|
+
expectedVersion: globalLatest,
|
|
1782
|
+
majorUpgradeAvailable: null
|
|
1783
|
+
};
|
|
1784
|
+
}
|
|
1785
|
+
if (latestInMajor && latestInMajor === current) {
|
|
1786
|
+
return { action: "skip" };
|
|
1787
|
+
}
|
|
1788
|
+
const majorUpgradeAvailable = globalLatest && parseMajorVersion(globalLatest) > currentMajor ? globalLatest : null;
|
|
1789
|
+
return {
|
|
1790
|
+
action: "install",
|
|
1791
|
+
installSpec: `${CLI_PACKAGE_NAME}@${currentMajor}`,
|
|
1792
|
+
targetLabel: latestInMajor ?? String(currentMajor),
|
|
1793
|
+
expectedVersion: latestInMajor,
|
|
1794
|
+
majorUpgradeAvailable
|
|
1795
|
+
};
|
|
1796
|
+
}
|
|
1774
1797
|
function npmAvailable() {
|
|
1775
1798
|
const r = runNpm(["--version"], { encoding: "utf8" });
|
|
1776
1799
|
return !r.error && r.status === 0;
|
|
1777
1800
|
}
|
|
1778
|
-
async function runUpdate() {
|
|
1801
|
+
async function runUpdate(options = {}) {
|
|
1779
1802
|
const current = readCliVersion();
|
|
1780
|
-
const
|
|
1781
|
-
|
|
1803
|
+
const currentMajor = parseMajorVersion(current);
|
|
1804
|
+
const globalLatest = await fetchLatestPublishedVersion();
|
|
1805
|
+
const latestInMajor = options.allowMajorUpgrade ? null : await fetchLatestPublishedVersionInMajor(currentMajor);
|
|
1806
|
+
const resolved = resolveUpdateTarget({
|
|
1807
|
+
current,
|
|
1808
|
+
allowMajorUpgrade: options.allowMajorUpgrade,
|
|
1809
|
+
latestInMajor,
|
|
1810
|
+
globalLatest
|
|
1811
|
+
});
|
|
1812
|
+
if (resolved.action === "skip") {
|
|
1782
1813
|
console.log(`[apm] \u5DF2\u662F\u6700\u65B0\u7248\u672C ${current}`);
|
|
1783
1814
|
return { didUpdate: false };
|
|
1784
1815
|
}
|
|
1816
|
+
if (resolved.majorUpgradeAvailable) {
|
|
1817
|
+
console.log(
|
|
1818
|
+
`[apm] registry \u6700\u65B0\u4E3A ${resolved.majorUpgradeAvailable}\uFF08\u5927\u7248\u672C\u5347\u7EA7\uFF09\uFF0C\u672C\u6B21\u4EC5\u66F4\u65B0\u5230 ${currentMajor}.x\uFF1B\u4F7F\u7528 apm update --major \u53EF\u8DE8\u5927\u7248\u672C\u5347\u7EA7`
|
|
1819
|
+
);
|
|
1820
|
+
}
|
|
1785
1821
|
if (!npmAvailable()) {
|
|
1786
1822
|
console.error(
|
|
1787
|
-
`[apm] \u672A\u627E\u5230 npm\u3002\u8BF7\u5B89\u88C5 Node.js \u540E\u6267\u884C\uFF1Anpm install -g ${
|
|
1823
|
+
`[apm] \u672A\u627E\u5230 npm\u3002\u8BF7\u5B89\u88C5 Node.js \u540E\u6267\u884C\uFF1Anpm install -g ${resolved.installSpec}`
|
|
1788
1824
|
);
|
|
1789
1825
|
process.exit(1);
|
|
1790
1826
|
}
|
|
1791
|
-
const targetLabel = latest ?? "latest";
|
|
1792
1827
|
console.error(
|
|
1793
|
-
`[apm] \u5F53\u524D\u7248\u672C ${current}\uFF0C\u6B63\u5728\u5B89\u88C5 ${
|
|
1828
|
+
`[apm] \u5F53\u524D\u7248\u672C ${current}\uFF0C\u6B63\u5728\u5B89\u88C5 ${resolved.installSpec} \u2026` + (resolved.targetLabel !== current ? `\uFF08\u76EE\u6807 ${resolved.targetLabel}\uFF09` : "")
|
|
1794
1829
|
);
|
|
1795
|
-
const install = runNpm(["install", "-g",
|
|
1830
|
+
const install = runNpm(["install", "-g", resolved.installSpec], {
|
|
1796
1831
|
stdio: "inherit"
|
|
1797
1832
|
});
|
|
1798
1833
|
if (install.error) {
|
|
@@ -1803,7 +1838,7 @@ async function runUpdate() {
|
|
|
1803
1838
|
process.exit(install.status ?? 1);
|
|
1804
1839
|
}
|
|
1805
1840
|
const after = readCliVersion();
|
|
1806
|
-
if (
|
|
1841
|
+
if (resolved.expectedVersion && after === resolved.expectedVersion) {
|
|
1807
1842
|
console.log(`[apm] \u5DF2\u66F4\u65B0\u5230 ${after}`);
|
|
1808
1843
|
} else {
|
|
1809
1844
|
console.log(
|
|
@@ -2168,113 +2203,13 @@ function validateDeployPush(o) {
|
|
|
2168
2203
|
}
|
|
2169
2204
|
};
|
|
2170
2205
|
}
|
|
2171
|
-
function validateCoordinatorDispatchMode(mode) {
|
|
2172
|
-
return mode === "plan" || mode === "agent";
|
|
2173
|
-
}
|
|
2174
|
-
function validateCoordinatorDispatchPush(o) {
|
|
2175
|
-
if (o.type !== "coordinator_dispatch") {
|
|
2176
|
-
return { ok: false, reason: "\u671F\u671B coordinator_dispatch" };
|
|
2177
|
-
}
|
|
2178
|
-
if (!nonEmptyString(o.dispatchId)) {
|
|
2179
|
-
return { ok: false, reason: "coordinator_dispatch \u7F3A\u5C11 dispatchId" };
|
|
2180
|
-
}
|
|
2181
|
-
if (!nonEmptyString(o.dispatchSessionId)) {
|
|
2182
|
-
return { ok: false, reason: "coordinator_dispatch \u7F3A\u5C11 dispatchSessionId" };
|
|
2183
|
-
}
|
|
2184
|
-
if (!validateCoordinatorDispatchMode(o.mode)) {
|
|
2185
|
-
return { ok: false, reason: "coordinator_dispatch.mode \u65E0\u6548" };
|
|
2186
|
-
}
|
|
2187
|
-
if (!nonEmptyString(o.content)) {
|
|
2188
|
-
return { ok: false, reason: "coordinator_dispatch \u7F3A\u5C11 content" };
|
|
2189
|
-
}
|
|
2190
|
-
if (!nonEmptyString(o.model)) {
|
|
2191
|
-
return { ok: false, reason: "coordinator_dispatch \u7F3A\u5C11 model" };
|
|
2192
|
-
}
|
|
2193
|
-
if (!nonEmptyString(o.apiKey)) {
|
|
2194
|
-
return { ok: false, reason: "coordinator_dispatch \u7F3A\u5C11 apiKey" };
|
|
2195
|
-
}
|
|
2196
|
-
if (!nonEmptyString(o.workdir)) {
|
|
2197
|
-
return { ok: false, reason: "coordinator_dispatch \u7F3A\u5C11 workdir" };
|
|
2198
|
-
}
|
|
2199
|
-
if (!nonEmptyString(o.user)) {
|
|
2200
|
-
return { ok: false, reason: "coordinator_dispatch \u7F3A\u5C11 user" };
|
|
2201
|
-
}
|
|
2202
|
-
const data = {
|
|
2203
|
-
type: "coordinator_dispatch",
|
|
2204
|
-
dispatchId: o.dispatchId.trim(),
|
|
2205
|
-
dispatchSessionId: o.dispatchSessionId.trim(),
|
|
2206
|
-
mode: o.mode,
|
|
2207
|
-
content: o.content,
|
|
2208
|
-
model: o.model.trim(),
|
|
2209
|
-
apiKey: o.apiKey.trim(),
|
|
2210
|
-
workdir: o.workdir.trim(),
|
|
2211
|
-
user: o.user.trim()
|
|
2212
|
-
};
|
|
2213
|
-
if (nonEmptyString(o.resumeAgentId)) {
|
|
2214
|
-
data.resumeAgentId = o.resumeAgentId.trim();
|
|
2215
|
-
}
|
|
2216
|
-
return { ok: true, data };
|
|
2217
|
-
}
|
|
2218
|
-
function validateCoordinatorDispatchResumePush(o) {
|
|
2219
|
-
if (o.type !== "coordinator_dispatch_resume") {
|
|
2220
|
-
return { ok: false, reason: "\u671F\u671B coordinator_dispatch_resume" };
|
|
2221
|
-
}
|
|
2222
|
-
if (!nonEmptyString(o.dispatchId)) {
|
|
2223
|
-
return { ok: false, reason: "coordinator_dispatch_resume \u7F3A\u5C11 dispatchId" };
|
|
2224
|
-
}
|
|
2225
|
-
if (!nonEmptyString(o.dispatchSessionId)) {
|
|
2226
|
-
return {
|
|
2227
|
-
ok: false,
|
|
2228
|
-
reason: "coordinator_dispatch_resume \u7F3A\u5C11 dispatchSessionId"
|
|
2229
|
-
};
|
|
2230
|
-
}
|
|
2231
|
-
if (!validateCoordinatorDispatchMode(o.mode)) {
|
|
2232
|
-
return { ok: false, reason: "coordinator_dispatch_resume.mode \u65E0\u6548" };
|
|
2233
|
-
}
|
|
2234
|
-
if (!nonEmptyString(o.content)) {
|
|
2235
|
-
return { ok: false, reason: "coordinator_dispatch_resume \u7F3A\u5C11 content" };
|
|
2236
|
-
}
|
|
2237
|
-
if (!nonEmptyString(o.resumeAgentId)) {
|
|
2238
|
-
return {
|
|
2239
|
-
ok: false,
|
|
2240
|
-
reason: "coordinator_dispatch_resume \u7F3A\u5C11 resumeAgentId"
|
|
2241
|
-
};
|
|
2242
|
-
}
|
|
2243
|
-
if (!nonEmptyString(o.model)) {
|
|
2244
|
-
return { ok: false, reason: "coordinator_dispatch_resume \u7F3A\u5C11 model" };
|
|
2245
|
-
}
|
|
2246
|
-
if (!nonEmptyString(o.apiKey)) {
|
|
2247
|
-
return { ok: false, reason: "coordinator_dispatch_resume \u7F3A\u5C11 apiKey" };
|
|
2248
|
-
}
|
|
2249
|
-
if (!nonEmptyString(o.workdir)) {
|
|
2250
|
-
return { ok: false, reason: "coordinator_dispatch_resume \u7F3A\u5C11 workdir" };
|
|
2251
|
-
}
|
|
2252
|
-
if (!nonEmptyString(o.user)) {
|
|
2253
|
-
return { ok: false, reason: "coordinator_dispatch_resume \u7F3A\u5C11 user" };
|
|
2254
|
-
}
|
|
2255
|
-
return {
|
|
2256
|
-
ok: true,
|
|
2257
|
-
data: {
|
|
2258
|
-
type: "coordinator_dispatch_resume",
|
|
2259
|
-
dispatchId: o.dispatchId.trim(),
|
|
2260
|
-
dispatchSessionId: o.dispatchSessionId.trim(),
|
|
2261
|
-
mode: o.mode,
|
|
2262
|
-
content: o.content,
|
|
2263
|
-
resumeAgentId: o.resumeAgentId.trim(),
|
|
2264
|
-
model: o.model.trim(),
|
|
2265
|
-
apiKey: o.apiKey.trim(),
|
|
2266
|
-
workdir: o.workdir.trim(),
|
|
2267
|
-
user: o.user.trim()
|
|
2268
|
-
}
|
|
2269
|
-
};
|
|
2270
|
-
}
|
|
2271
2206
|
function validateAgentWsMessage(value, kind) {
|
|
2272
2207
|
if (typeof value !== "object" || value === null) {
|
|
2273
2208
|
return { ok: false, reason: "\u6D88\u606F\u4F53\u4E0D\u662F JSON \u5BF9\u8C61" };
|
|
2274
2209
|
}
|
|
2275
2210
|
const o = value;
|
|
2276
2211
|
const type = o.type;
|
|
2277
|
-
if (type !== "heartbeat" && type !== "message" && type !== "cancel" && type !== "deploy"
|
|
2212
|
+
if (type !== "heartbeat" && type !== "message" && type !== "cancel" && type !== "deploy") {
|
|
2278
2213
|
return { ok: false, reason: `\u672A\u77E5 type: ${String(type)}` };
|
|
2279
2214
|
}
|
|
2280
2215
|
if (kind === "heartbeat" || type === "heartbeat") {
|
|
@@ -2286,12 +2221,6 @@ function validateAgentWsMessage(value, kind) {
|
|
|
2286
2221
|
if (type === "deploy") {
|
|
2287
2222
|
return validateDeployPush(o);
|
|
2288
2223
|
}
|
|
2289
|
-
if (type === "coordinator_dispatch") {
|
|
2290
|
-
return validateCoordinatorDispatchPush(o);
|
|
2291
|
-
}
|
|
2292
|
-
if (type === "coordinator_dispatch_resume") {
|
|
2293
|
-
return validateCoordinatorDispatchResumePush(o);
|
|
2294
|
-
}
|
|
2295
2224
|
return validateMessagePush(o);
|
|
2296
2225
|
}
|
|
2297
2226
|
|
|
@@ -2378,7 +2307,7 @@ function createDeployLogSyncer(api, deploymentRunId) {
|
|
|
2378
2307
|
if (!latestLog || latestLog === lastSyncedLog) {
|
|
2379
2308
|
return;
|
|
2380
2309
|
}
|
|
2381
|
-
await api.cli.
|
|
2310
|
+
await api.cli.syncTaskDeploymentLog({
|
|
2382
2311
|
id: deploymentRunId,
|
|
2383
2312
|
log: latestLog
|
|
2384
2313
|
});
|
|
@@ -2409,7 +2338,7 @@ async function handleInboundDeploy(cfg, msg, signal) {
|
|
|
2409
2338
|
const api = createApmApiClient(cfg);
|
|
2410
2339
|
const deploymentRunId = msg.deploymentRunId;
|
|
2411
2340
|
if (signal.aborted) return;
|
|
2412
|
-
await api.cli.
|
|
2341
|
+
await api.cli.updateTaskDeploymentStatus({
|
|
2413
2342
|
id: deploymentRunId,
|
|
2414
2343
|
status: "DEPLOYING"
|
|
2415
2344
|
});
|
|
@@ -2418,7 +2347,7 @@ async function handleInboundDeploy(cfg, msg, signal) {
|
|
|
2418
2347
|
if (!command) {
|
|
2419
2348
|
const error = missingDeployCommandMessage(msg.environment);
|
|
2420
2349
|
console.error(`[apm] ${error}`);
|
|
2421
|
-
await api.cli.
|
|
2350
|
+
await api.cli.completeTaskDeployment({
|
|
2422
2351
|
id: deploymentRunId,
|
|
2423
2352
|
status: "FAILED",
|
|
2424
2353
|
log: error,
|
|
@@ -2440,7 +2369,7 @@ async function handleInboundDeploy(cfg, msg, signal) {
|
|
|
2440
2369
|
latestLog = log;
|
|
2441
2370
|
logSyncer.updateLog(log);
|
|
2442
2371
|
await logSyncer.flush();
|
|
2443
|
-
await api.cli.
|
|
2372
|
+
await api.cli.completeTaskDeployment({
|
|
2444
2373
|
id: deploymentRunId,
|
|
2445
2374
|
status: "SUCCESS",
|
|
2446
2375
|
log
|
|
@@ -2451,7 +2380,7 @@ async function handleInboundDeploy(cfg, msg, signal) {
|
|
|
2451
2380
|
const log = error && typeof error === "object" && "log" in error ? String(error.log ?? latestLog) : latestLog;
|
|
2452
2381
|
logSyncer.updateLog(log);
|
|
2453
2382
|
await logSyncer.flush();
|
|
2454
|
-
await api.cli.
|
|
2383
|
+
await api.cli.completeTaskDeployment({
|
|
2455
2384
|
id: deploymentRunId,
|
|
2456
2385
|
status: "FAILED",
|
|
2457
2386
|
log,
|
|
@@ -2463,6 +2392,69 @@ async function handleInboundDeploy(cfg, msg, signal) {
|
|
|
2463
2392
|
}
|
|
2464
2393
|
}
|
|
2465
2394
|
|
|
2395
|
+
// src/commands/connect/abort-signal-debug.ts
|
|
2396
|
+
import {
|
|
2397
|
+
getEventListeners,
|
|
2398
|
+
getMaxListeners,
|
|
2399
|
+
setMaxListeners
|
|
2400
|
+
} from "node:events";
|
|
2401
|
+
function isAbortSignalDebugEnabled() {
|
|
2402
|
+
const v = process.env.APM_DEBUG_ABORT_SIGNAL?.trim().toLowerCase();
|
|
2403
|
+
return v === "1" || v === "true" || v === "yes";
|
|
2404
|
+
}
|
|
2405
|
+
function formatAbortSignalStats(signal, label) {
|
|
2406
|
+
if (!signal) {
|
|
2407
|
+
return `[apm:abort-debug] ${label}: (no signal)`;
|
|
2408
|
+
}
|
|
2409
|
+
const listeners = getEventListeners(signal, "abort");
|
|
2410
|
+
const max = getMaxListeners(signal);
|
|
2411
|
+
return `[apm:abort-debug] ${label}: abortListeners=${listeners.length} maxListeners=${max} aborted=${signal.aborted}`;
|
|
2412
|
+
}
|
|
2413
|
+
function logAbortSignalStats(signal, label) {
|
|
2414
|
+
if (!isAbortSignalDebugEnabled()) return;
|
|
2415
|
+
console.log(formatAbortSignalStats(signal, label));
|
|
2416
|
+
}
|
|
2417
|
+
var installed = false;
|
|
2418
|
+
function installAbortSignalDebug() {
|
|
2419
|
+
if (!isAbortSignalDebugEnabled() || installed) return;
|
|
2420
|
+
installed = true;
|
|
2421
|
+
const maxFromEnv = Number.parseInt(
|
|
2422
|
+
process.env.APM_ABORT_SIGNAL_MAX_LISTENERS ?? "",
|
|
2423
|
+
10
|
|
2424
|
+
);
|
|
2425
|
+
if (Number.isFinite(maxFromEnv) && maxFromEnv > 0) {
|
|
2426
|
+
setMaxListeners(maxFromEnv);
|
|
2427
|
+
console.log(
|
|
2428
|
+
`[apm:abort-debug] setMaxListeners(${maxFromEnv}) via APM_ABORT_SIGNAL_MAX_LISTENERS`
|
|
2429
|
+
);
|
|
2430
|
+
}
|
|
2431
|
+
process.on("warning", (warning) => {
|
|
2432
|
+
if (warning.name !== "MaxListenersExceededWarning") return;
|
|
2433
|
+
console.warn(`[apm:abort-debug] ${warning.name}: ${warning.message}`);
|
|
2434
|
+
if (warning.stack) {
|
|
2435
|
+
console.warn(warning.stack);
|
|
2436
|
+
}
|
|
2437
|
+
});
|
|
2438
|
+
const proto = AbortSignal.prototype;
|
|
2439
|
+
const original = proto.addEventListener;
|
|
2440
|
+
proto.addEventListener = function(type, listener, options) {
|
|
2441
|
+
if (type === "abort") {
|
|
2442
|
+
const sig = this;
|
|
2443
|
+
const before = getEventListeners(sig, "abort").length;
|
|
2444
|
+
const max = getMaxListeners(sig);
|
|
2445
|
+
const stack = new Error("[apm:abort-debug] addEventListener stack").stack?.split("\n").slice(2, 8).join("\n") ?? "";
|
|
2446
|
+
console.log(
|
|
2447
|
+
`[apm:abort-debug] addEventListener("abort") before=${before} max=${max}
|
|
2448
|
+
${stack}`
|
|
2449
|
+
);
|
|
2450
|
+
}
|
|
2451
|
+
return original.call(this, type, listener, options);
|
|
2452
|
+
};
|
|
2453
|
+
console.log(
|
|
2454
|
+
"[apm:abort-debug] \u5DF2\u542F\u7528 AbortSignal \u8C03\u8BD5\uFF08APM_DEBUG_ABORT_SIGNAL\uFF09"
|
|
2455
|
+
);
|
|
2456
|
+
}
|
|
2457
|
+
|
|
2466
2458
|
// src/commands/connect/cursor-agent.ts
|
|
2467
2459
|
import {
|
|
2468
2460
|
Agent,
|
|
@@ -2792,97 +2784,6 @@ async function syncCursorMessageLog(cfg, ctx, events) {
|
|
|
2792
2784
|
});
|
|
2793
2785
|
}
|
|
2794
2786
|
|
|
2795
|
-
// src/commands/connect/abort-signal-debug.ts
|
|
2796
|
-
import {
|
|
2797
|
-
getEventListeners,
|
|
2798
|
-
getMaxListeners,
|
|
2799
|
-
setMaxListeners
|
|
2800
|
-
} from "node:events";
|
|
2801
|
-
function isAbortSignalDebugEnabled() {
|
|
2802
|
-
const v = process.env.APM_DEBUG_ABORT_SIGNAL?.trim().toLowerCase();
|
|
2803
|
-
return v === "1" || v === "true" || v === "yes";
|
|
2804
|
-
}
|
|
2805
|
-
function formatAbortSignalStats(signal, label) {
|
|
2806
|
-
if (!signal) {
|
|
2807
|
-
return `[apm:abort-debug] ${label}: (no signal)`;
|
|
2808
|
-
}
|
|
2809
|
-
const listeners = getEventListeners(signal, "abort");
|
|
2810
|
-
const max = getMaxListeners(signal);
|
|
2811
|
-
return `[apm:abort-debug] ${label}: abortListeners=${listeners.length} maxListeners=${max} aborted=${signal.aborted}`;
|
|
2812
|
-
}
|
|
2813
|
-
function logAbortSignalStats(signal, label) {
|
|
2814
|
-
if (!isAbortSignalDebugEnabled()) return;
|
|
2815
|
-
console.log(formatAbortSignalStats(signal, label));
|
|
2816
|
-
}
|
|
2817
|
-
var installed = false;
|
|
2818
|
-
function installAbortSignalDebug() {
|
|
2819
|
-
if (!isAbortSignalDebugEnabled() || installed) return;
|
|
2820
|
-
installed = true;
|
|
2821
|
-
const maxFromEnv = Number.parseInt(
|
|
2822
|
-
process.env.APM_ABORT_SIGNAL_MAX_LISTENERS ?? "",
|
|
2823
|
-
10
|
|
2824
|
-
);
|
|
2825
|
-
if (Number.isFinite(maxFromEnv) && maxFromEnv > 0) {
|
|
2826
|
-
setMaxListeners(maxFromEnv);
|
|
2827
|
-
console.log(
|
|
2828
|
-
`[apm:abort-debug] setMaxListeners(${maxFromEnv}) via APM_ABORT_SIGNAL_MAX_LISTENERS`
|
|
2829
|
-
);
|
|
2830
|
-
}
|
|
2831
|
-
process.on("warning", (warning) => {
|
|
2832
|
-
if (warning.name !== "MaxListenersExceededWarning") return;
|
|
2833
|
-
console.warn(`[apm:abort-debug] ${warning.name}: ${warning.message}`);
|
|
2834
|
-
if (warning.stack) {
|
|
2835
|
-
console.warn(warning.stack);
|
|
2836
|
-
}
|
|
2837
|
-
});
|
|
2838
|
-
const proto = AbortSignal.prototype;
|
|
2839
|
-
const original = proto.addEventListener;
|
|
2840
|
-
proto.addEventListener = function(type, listener, options) {
|
|
2841
|
-
if (type === "abort") {
|
|
2842
|
-
const sig = this;
|
|
2843
|
-
const before = getEventListeners(sig, "abort").length;
|
|
2844
|
-
const max = getMaxListeners(sig);
|
|
2845
|
-
const stack = new Error("[apm:abort-debug] addEventListener stack").stack?.split("\n").slice(2, 8).join("\n") ?? "";
|
|
2846
|
-
console.log(
|
|
2847
|
-
`[apm:abort-debug] addEventListener("abort") before=${before} max=${max}
|
|
2848
|
-
${stack}`
|
|
2849
|
-
);
|
|
2850
|
-
}
|
|
2851
|
-
return original.call(this, type, listener, options);
|
|
2852
|
-
};
|
|
2853
|
-
console.log(
|
|
2854
|
-
"[apm:abort-debug] \u5DF2\u542F\u7528 AbortSignal \u8C03\u8BD5\uFF08APM_DEBUG_ABORT_SIGNAL\uFF09"
|
|
2855
|
-
);
|
|
2856
|
-
}
|
|
2857
|
-
|
|
2858
|
-
// src/commands/connect/append-dispatch-response-tool.ts
|
|
2859
|
-
function createAppendDispatchResponseTools(cfg, dispatchId) {
|
|
2860
|
-
return {
|
|
2861
|
-
append_dispatch_response: {
|
|
2862
|
-
description: "Append content to the coordinator member dispatch response for the coordinator Agent to read.",
|
|
2863
|
-
inputSchema: {
|
|
2864
|
-
type: "object",
|
|
2865
|
-
properties: {
|
|
2866
|
-
content: { type: "string", description: "Response text to append" }
|
|
2867
|
-
},
|
|
2868
|
-
required: ["content"]
|
|
2869
|
-
},
|
|
2870
|
-
execute: async (args) => {
|
|
2871
|
-
const content = String(args.content ?? "").trim();
|
|
2872
|
-
if (!content) {
|
|
2873
|
-
return "content \u4E0D\u80FD\u4E3A\u7A7A";
|
|
2874
|
-
}
|
|
2875
|
-
const api = createApmApiClient(cfg);
|
|
2876
|
-
await api.cli.appendCoordinatorDispatchResponse({
|
|
2877
|
-
id: dispatchId,
|
|
2878
|
-
content
|
|
2879
|
-
});
|
|
2880
|
-
return `\u5DF2\u8FFD\u52A0\u6D3E\u53D1\u54CD\u5E94\uFF08${content.length} \u5B57\u7B26\uFF09`;
|
|
2881
|
-
}
|
|
2882
|
-
}
|
|
2883
|
-
};
|
|
2884
|
-
}
|
|
2885
|
-
|
|
2886
2787
|
// src/commands/connect/append-message-tool.ts
|
|
2887
2788
|
function createAppendMessageCustomTools(cfg, messageId) {
|
|
2888
2789
|
return {
|
|
@@ -2923,8 +2824,7 @@ function createAppendMessageCustomTools(cfg, messageId) {
|
|
|
2923
2824
|
}
|
|
2924
2825
|
|
|
2925
2826
|
// src/commands/connect/ask-question-tool.ts
|
|
2926
|
-
|
|
2927
|
-
function createAskQuestionTool(options) {
|
|
2827
|
+
function createAskQuestionMockTool(options) {
|
|
2928
2828
|
return {
|
|
2929
2829
|
description: "Collect structured multiple-choice answers from the user. Use when blocked on a decision that is genuinely the user's to make.",
|
|
2930
2830
|
inputSchema: {
|
|
@@ -2962,61 +2862,6 @@ function createAskQuestionTool(options) {
|
|
|
2962
2862
|
},
|
|
2963
2863
|
required: ["questions"]
|
|
2964
2864
|
},
|
|
2965
|
-
execute: async (args) => {
|
|
2966
|
-
const record = args;
|
|
2967
|
-
const questions = record.questions;
|
|
2968
|
-
if (!Array.isArray(questions) || questions.length === 0) {
|
|
2969
|
-
return "questions \u4E0D\u80FD\u4E3A\u7A7A";
|
|
2970
|
-
}
|
|
2971
|
-
const api = createApmApiClient(options.cfg);
|
|
2972
|
-
await api.cli.createCoordinatorDispatchQuestions({
|
|
2973
|
-
dispatchId: options.dispatchId,
|
|
2974
|
-
batchId: randomUUID(),
|
|
2975
|
-
title: typeof record.title === "string" ? record.title : void 0,
|
|
2976
|
-
questions
|
|
2977
|
-
});
|
|
2978
|
-
options.onSubmitted?.();
|
|
2979
|
-
return "\u5DF2\u5411\u7528\u6237\u63D0\u4EA4\u95EE\u9898\uFF0C\u8BF7\u7ED3\u675F\u672C\u8F6E run\uFF0C\u7B49\u5F85\u7528\u6237\u5728\u534F\u8C03\u4F1A\u8BDD\u9875\u56DE\u7B54\u540E\u7EE7\u7EED\u3002";
|
|
2980
|
-
}
|
|
2981
|
-
};
|
|
2982
|
-
}
|
|
2983
|
-
|
|
2984
|
-
// src/commands/connect/ask-question-tool.mock.ts
|
|
2985
|
-
function createAskQuestionMockTool(options) {
|
|
2986
|
-
return {
|
|
2987
|
-
description: "Collect structured multiple-choice answers from the user. Use when blocked on a decision that is genuinely the user's to make.",
|
|
2988
|
-
inputSchema: {
|
|
2989
|
-
type: "object",
|
|
2990
|
-
properties: {
|
|
2991
|
-
title: { type: "string" },
|
|
2992
|
-
questions: {
|
|
2993
|
-
type: "array",
|
|
2994
|
-
minItems: 1,
|
|
2995
|
-
items: {
|
|
2996
|
-
type: "object",
|
|
2997
|
-
properties: {
|
|
2998
|
-
id: { type: "string" },
|
|
2999
|
-
prompt: { type: "string" },
|
|
3000
|
-
allow_multiple: { type: "boolean" },
|
|
3001
|
-
options: {
|
|
3002
|
-
type: "array",
|
|
3003
|
-
minItems: 2,
|
|
3004
|
-
items: {
|
|
3005
|
-
type: "object",
|
|
3006
|
-
properties: {
|
|
3007
|
-
id: { type: "string" },
|
|
3008
|
-
label: { type: "string" }
|
|
3009
|
-
},
|
|
3010
|
-
required: ["id", "label"]
|
|
3011
|
-
}
|
|
3012
|
-
}
|
|
3013
|
-
},
|
|
3014
|
-
required: ["id", "prompt", "options"]
|
|
3015
|
-
}
|
|
3016
|
-
}
|
|
3017
|
-
},
|
|
3018
|
-
required: ["questions"]
|
|
3019
|
-
},
|
|
3020
2865
|
execute: async (args) => {
|
|
3021
2866
|
const payload = JSON.stringify(args, null, 2);
|
|
3022
2867
|
console.log(`[apm] AskQuestion mock \u8C03\u7528:
|
|
@@ -3041,16 +2886,6 @@ function createCursorCustomTools(cfg, messageId, options) {
|
|
|
3041
2886
|
})
|
|
3042
2887
|
};
|
|
3043
2888
|
}
|
|
3044
|
-
function createCursorDispatchCustomTools(cfg, options) {
|
|
3045
|
-
return {
|
|
3046
|
-
...createAppendDispatchResponseTools(cfg, options.dispatchId),
|
|
3047
|
-
AskQuestion: createAskQuestionTool({
|
|
3048
|
-
cfg,
|
|
3049
|
-
dispatchId: options.dispatchId,
|
|
3050
|
-
onSubmitted: options.onAskQuestionSubmitted
|
|
3051
|
-
})
|
|
3052
|
-
};
|
|
3053
|
-
}
|
|
3054
2889
|
function withPlanModeToolHint(prompt, mode) {
|
|
3055
2890
|
if (mode !== "plan") {
|
|
3056
2891
|
return prompt;
|
|
@@ -3137,7 +2972,7 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
3137
2972
|
throw new Error("\u7F3A\u5C11 apiKey\uFF0C\u65E0\u6CD5\u8C03\u7528 Cursor SDK");
|
|
3138
2973
|
}
|
|
3139
2974
|
const workdir = resolveWorkdirPath(ctx.workdir);
|
|
3140
|
-
const customTools =
|
|
2975
|
+
const customTools = createCursorCustomTools(cfg, ctx.messageId, {
|
|
3141
2976
|
onAskQuestion: options?.onAskQuestion
|
|
3142
2977
|
});
|
|
3143
2978
|
const prompt = withPlanModeToolHint(ctx.prompt, ctx.mode);
|
|
@@ -3265,79 +3100,6 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
3265
3100
|
}
|
|
3266
3101
|
}
|
|
3267
3102
|
|
|
3268
|
-
// src/commands/connect/coordinator-dispatch-handler.ts
|
|
3269
|
-
async function handleInboundCoordinatorDispatch(cfg, msg, signal) {
|
|
3270
|
-
const workdir = requireRemoteWorkdir(msg.workdir);
|
|
3271
|
-
assertApmGitignoredInRepo(workdir);
|
|
3272
|
-
await ensureWorkspaceInitialized(workdir);
|
|
3273
|
-
const api = createApmApiClient(cfg);
|
|
3274
|
-
let askQuestionSubmitted = false;
|
|
3275
|
-
try {
|
|
3276
|
-
await api.cli.updateCoordinatorDispatchStatus({
|
|
3277
|
-
id: msg.dispatchId,
|
|
3278
|
-
status: "DISPATCHING"
|
|
3279
|
-
});
|
|
3280
|
-
const result = await runCursorAgent(
|
|
3281
|
-
cfg,
|
|
3282
|
-
{
|
|
3283
|
-
messageId: msg.dispatchId,
|
|
3284
|
-
sessionId: msg.dispatchSessionId,
|
|
3285
|
-
prompt: msg.content,
|
|
3286
|
-
model: msg.model,
|
|
3287
|
-
apiKey: msg.apiKey,
|
|
3288
|
-
workdir: msg.workdir,
|
|
3289
|
-
user: msg.user,
|
|
3290
|
-
mode: msg.mode,
|
|
3291
|
-
resumeAgentId: msg.type === "coordinator_dispatch_resume" ? msg.resumeAgentId : msg.resumeAgentId
|
|
3292
|
-
},
|
|
3293
|
-
{
|
|
3294
|
-
signal,
|
|
3295
|
-
forceSend: true,
|
|
3296
|
-
skipRemoteLogSync: true,
|
|
3297
|
-
customTools: createCursorDispatchCustomTools(cfg, {
|
|
3298
|
-
dispatchId: msg.dispatchId,
|
|
3299
|
-
onAskQuestionSubmitted: () => {
|
|
3300
|
-
askQuestionSubmitted = true;
|
|
3301
|
-
}
|
|
3302
|
-
})
|
|
3303
|
-
}
|
|
3304
|
-
);
|
|
3305
|
-
if (askQuestionSubmitted) {
|
|
3306
|
-
if (result.agentId) {
|
|
3307
|
-
await api.cli.completeCoordinatorDispatch({
|
|
3308
|
-
id: msg.dispatchId,
|
|
3309
|
-
agentId: result.agentId
|
|
3310
|
-
});
|
|
3311
|
-
}
|
|
3312
|
-
console.log(
|
|
3313
|
-
`[apm] \u534F\u8C03\u6D3E\u53D1 ${msg.dispatchId} \u5DF2\u63D0\u4EA4 AskQuestion\uFF0C\u7B49\u5F85\u7528\u6237\u7B54\u9898`
|
|
3314
|
-
);
|
|
3315
|
-
return;
|
|
3316
|
-
}
|
|
3317
|
-
await api.cli.completeCoordinatorDispatch({
|
|
3318
|
-
id: msg.dispatchId,
|
|
3319
|
-
agentId: result.agentId,
|
|
3320
|
-
createPlan: result.createPlan,
|
|
3321
|
-
artifacts: result.artifactDocuments.map((doc) => ({
|
|
3322
|
-
name: doc.path.split("/").pop() ?? doc.path,
|
|
3323
|
-
content: doc.content
|
|
3324
|
-
})),
|
|
3325
|
-
status: "SUCCESS"
|
|
3326
|
-
});
|
|
3327
|
-
console.log(`[apm] \u534F\u8C03\u6D3E\u53D1\u5B8C\u6210 dispatchId=${msg.dispatchId}`);
|
|
3328
|
-
} catch (error) {
|
|
3329
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
3330
|
-
console.error(`[apm] \u534F\u8C03\u6D3E\u53D1\u5931\u8D25 dispatchId=${msg.dispatchId}:`, message);
|
|
3331
|
-
if (!askQuestionSubmitted) {
|
|
3332
|
-
await api.cli.completeCoordinatorDispatch({
|
|
3333
|
-
id: msg.dispatchId,
|
|
3334
|
-
status: "FAILED",
|
|
3335
|
-
error: message
|
|
3336
|
-
});
|
|
3337
|
-
}
|
|
3338
|
-
}
|
|
3339
|
-
}
|
|
3340
|
-
|
|
3341
3103
|
// src/commands/connect/cli-version-sync.ts
|
|
3342
3104
|
import { existsSync as existsSync12, readFileSync as readFileSync11, writeFileSync as writeFileSync11 } from "fs";
|
|
3343
3105
|
import { join as join14 } from "path";
|
|
@@ -3713,27 +3475,6 @@ async function runConnect(options) {
|
|
|
3713
3475
|
});
|
|
3714
3476
|
return;
|
|
3715
3477
|
}
|
|
3716
|
-
if (validated.data.type === "coordinator_dispatch" || validated.data.type === "coordinator_dispatch_resume") {
|
|
3717
|
-
const msg2 = validated.data;
|
|
3718
|
-
const perDispatchController = new AbortController();
|
|
3719
|
-
const signal2 = AbortSignal.any([
|
|
3720
|
-
shutdownAbort.signal,
|
|
3721
|
-
perDispatchController.signal
|
|
3722
|
-
]);
|
|
3723
|
-
const task2 = (async () => {
|
|
3724
|
-
await runSlots.acquire();
|
|
3725
|
-
try {
|
|
3726
|
-
await handleInboundCoordinatorDispatch(cfg, msg2, signal2);
|
|
3727
|
-
} finally {
|
|
3728
|
-
runSlots.release();
|
|
3729
|
-
}
|
|
3730
|
-
})();
|
|
3731
|
-
activeTasks.add(task2);
|
|
3732
|
-
void task2.finally(() => {
|
|
3733
|
-
activeTasks.delete(task2);
|
|
3734
|
-
});
|
|
3735
|
-
return;
|
|
3736
|
-
}
|
|
3737
3478
|
if (validated.data.type !== "message") {
|
|
3738
3479
|
return;
|
|
3739
3480
|
}
|
|
@@ -5007,9 +4748,14 @@ function buildProgram() {
|
|
|
5007
4748
|
await runInit(opts.name);
|
|
5008
4749
|
});
|
|
5009
4750
|
program.command("update").description(
|
|
5010
|
-
`\u901A\u8FC7 npm \u5168\u5C40\u5B89\u88C5 ${CLI_PACKAGE_NAME}
|
|
5011
|
-
|
|
5012
|
-
|
|
4751
|
+
`\u901A\u8FC7 npm \u5168\u5C40\u5B89\u88C5 ${CLI_PACKAGE_NAME}\uFF0C\u9ED8\u8BA4\u66F4\u65B0\u5230\u5F53\u524D\u5927\u7248\u672C\uFF08${parseMajorVersion(
|
|
4752
|
+
readCliVersion()
|
|
4753
|
+
)}.x\uFF09\u6700\u65B0\u7248`
|
|
4754
|
+
).option(
|
|
4755
|
+
"--major",
|
|
4756
|
+
"\u5141\u8BB8\u8DE8\u5927\u7248\u672C\u66F4\u65B0\u5230 registry \u5168\u5C40 latest\uFF08\u9ED8\u8BA4\u4EC5\u8DDF\u968F\u5F53\u524D\u5927\u7248\u672C\uFF09"
|
|
4757
|
+
).action(async (opts) => {
|
|
4758
|
+
await runUpdate({ allowMajorUpgrade: opts.major === true });
|
|
5013
4759
|
});
|
|
5014
4760
|
program.command("update-skills").description(
|
|
5015
4761
|
"\u540C\u6B65 .apm/ \u4E0B\u7684\u89C4\u5219\u4E0E\u6280\u80FD\uFF1A\u57FA\u7840\u5185\u5BB9\u6765\u81EA CLI \u6A21\u677F\uFF0C\u8865\u5145\u6280\u80FD\u6765\u81EA\u5E73\u53F0"
|
|
@@ -5047,7 +4793,7 @@ function buildProgram() {
|
|
|
5047
4793
|
await runUpdateMessageStatus(opts);
|
|
5048
4794
|
});
|
|
5049
4795
|
program.command("connect").description(
|
|
5050
|
-
"\u8FDE\u63A5\u5E73\u53F0 WebSocket\uFF08/ws/agent\uFF09\uFF0C\u7EF4\u6301\u5FC3\u8DF3\u5E76\u5904\u7406\u4E0B\u884C message\uFF08TYPING \u2192 Cursor \u2192 SUCCESS/FAILED\uFF09\uFF1B\u542F\u52A8\u524D\u81EA\u52A8 apm update \u5230\u6700\u65B0\u7248"
|
|
4796
|
+
"\u8FDE\u63A5\u5E73\u53F0 WebSocket\uFF08/ws/agent\uFF09\uFF0C\u7EF4\u6301\u5FC3\u8DF3\u5E76\u5904\u7406\u4E0B\u884C message\uFF08TYPING \u2192 Cursor \u2192 SUCCESS/FAILED\uFF09\uFF1B\u542F\u52A8\u524D\u81EA\u52A8 apm update \u5230\u5F53\u524D\u5927\u7248\u672C\u6700\u65B0\u7248"
|
|
5051
4797
|
).option("--server <url>", "API \u6839\u5730\u5740\uFF0C\u8986\u76D6 config \u4E2D\u7684 baseUrl").action(async (opts) => {
|
|
5052
4798
|
await runConnect(opts);
|
|
5053
4799
|
});
|