@pwrdrvr/agent-acp 0.14.0 → 0.15.0
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.d.ts +35 -4
- package/dist/index.js +116 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,10 @@ interface AcpAgentConnection {
|
|
|
27
27
|
request(method: string, params: Record<string, unknown>): Promise<unknown>;
|
|
28
28
|
notify(method: string, params: Record<string, unknown>): Promise<void>;
|
|
29
29
|
}
|
|
30
|
+
/** Prefix on the rejection when a request outlived its budget. Lets a caller
|
|
31
|
+
* tell "the agent did not answer in time" apart from "the agent answered with
|
|
32
|
+
* an error" — the two want different recovery (retry / restart vs. surface). */
|
|
33
|
+
declare const ACP_REQUEST_TIMEOUT_MESSAGE_PREFIX = "acp request timed out";
|
|
30
34
|
/** Built connection + a teardown handle (kills the child / closes streams). */
|
|
31
35
|
type AcpAgentConnectionHandle = {
|
|
32
36
|
connection: AcpAgentConnection;
|
|
@@ -55,7 +59,8 @@ declare class AcpConnection implements AcpJsonRpcTransport {
|
|
|
55
59
|
private ensureConnected;
|
|
56
60
|
private connect;
|
|
57
61
|
private defaultCreateConnection;
|
|
58
|
-
request(method: string, params?: Record<string, unknown>,
|
|
62
|
+
request(method: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<unknown>;
|
|
63
|
+
private dispatch;
|
|
59
64
|
notify(method: string, params?: Record<string, unknown>): Promise<void>;
|
|
60
65
|
close(): Promise<void>;
|
|
61
66
|
onNotification(listener: (method: string, params: Record<string, unknown>) => void): () => void;
|
|
@@ -66,7 +71,14 @@ type LocalAcpProbeResult = {
|
|
|
66
71
|
stdout?: string | Buffer;
|
|
67
72
|
stderr?: string | Buffer;
|
|
68
73
|
};
|
|
69
|
-
type
|
|
74
|
+
type LocalAcpProbeOptions = {
|
|
75
|
+
/** Budget for this probe spawn. An injected probe should honor it so a slow
|
|
76
|
+
* CLI is reported as "did not answer in time", not as "not installed". */
|
|
77
|
+
timeoutMs?: number | undefined;
|
|
78
|
+
/** Fires when discovery is abandoned mid-probe. */
|
|
79
|
+
signal?: AbortSignal | undefined;
|
|
80
|
+
};
|
|
81
|
+
type LocalAcpAgentProbe = (command: string, args: string[], options?: LocalAcpProbeOptions) => Promise<LocalAcpProbeResult>;
|
|
70
82
|
/** How a strategy decides it is installed + ACP-capable on this machine. */
|
|
71
83
|
type AcpDiscoveryProbe = {
|
|
72
84
|
/** Args that print a version (probed first; failure = not installed). */
|
|
@@ -707,7 +719,10 @@ type RejectedAcpAgentInstance = {
|
|
|
707
719
|
/** Parsed from successful `--version` output when available. */
|
|
708
720
|
version?: string;
|
|
709
721
|
source: AcpAgentInstanceSource;
|
|
710
|
-
|
|
722
|
+
/** `probe-timed-out` means the CLI did not answer within the probe budget —
|
|
723
|
+
* UNLIKE the other reasons it is not a verdict on the CLI, and a host may
|
|
724
|
+
* re-probe on a larger `probeTimeoutMs` instead of reporting it unusable. */
|
|
725
|
+
reason: "version-probe-failed" | "acp-probe-failed" | "acp-help-mismatch" | "probe-timed-out";
|
|
711
726
|
};
|
|
712
727
|
/** Every installed instance of one agent found on this machine. */
|
|
713
728
|
type DiscoveredAcpAgentGroup = {
|
|
@@ -755,7 +770,23 @@ type LocalAcpDiscoveryOptions = {
|
|
|
755
770
|
/** Include candidates known to exist but rejected by a discovery probe.
|
|
756
771
|
* Defaults false to preserve the legacy installed-only result. */
|
|
757
772
|
includeRejectedCandidates?: boolean;
|
|
773
|
+
/** Budget for ONE probe spawn (the default probe only — an injected `probe`
|
|
774
|
+
* owns its own timing). Defaults to `DEFAULT_ACP_PROBE_TIMEOUT_MS`. */
|
|
775
|
+
probeTimeoutMs?: number;
|
|
776
|
+
/** Abandon discovery in flight (re-triggered discovery, app quitting).
|
|
777
|
+
* Already-probed groups are still returned. */
|
|
778
|
+
signal?: AbortSignal;
|
|
758
779
|
};
|
|
780
|
+
/**
|
|
781
|
+
* Budget for one ACP discovery probe spawn, in ms.
|
|
782
|
+
*
|
|
783
|
+
* Unchanged from the value this module has always used. Kept lower than
|
|
784
|
+
* codex-discovery's version-probe budget on purpose: `discoverStrategyInstances`
|
|
785
|
+
* walks its candidates SERIALLY, so the worst case here is (candidates x
|
|
786
|
+
* budget) rather than a single budget. Hosts that scan machines with many
|
|
787
|
+
* installed copies can raise it knowingly via `probeTimeoutMs`.
|
|
788
|
+
*/
|
|
789
|
+
declare const DEFAULT_ACP_PROBE_TIMEOUT_MS = 5000;
|
|
759
790
|
/**
|
|
760
791
|
* Discover every installed instance of each agent (all `PATH` matches +
|
|
761
792
|
* fallbacks + override that pass the probe), grouped per strategy. Groups with
|
|
@@ -890,4 +921,4 @@ declare class AcpRegistryService {
|
|
|
890
921
|
declare function evaluateAcpDistributionPolicy(distribution: AcpRegistryDistribution, allowlist: AcpAllowlistDecision): AcpDistributionPolicy;
|
|
891
922
|
declare function normalizeRegistry(raw: unknown): AcpRegistryAgent[];
|
|
892
923
|
|
|
893
|
-
export { ACP_REGISTRY_URL, AcpAgentAllowlist, type AcpAgentAllowlistRule, AcpAgentClient, type AcpAgentClientFactory, type AcpAgentClientOptions, AcpAgentClientPool, type AcpAgentClientPoolOptions, type AcpAgentConnection, type AcpAgentConnectionHandle, type AcpAgentInstanceSource, type AcpAgentQuirks, type AcpAgentStrategy, type AcpAllowlistDecision, type AcpApplyContext, type AcpBinaryPlatformDistribution, AcpConnection, type AcpConnectionOptions, type AcpDiscoveryProbe, type AcpDistributionKind, type AcpDistributionPolicy, type AcpHttpMcpServerConfig, type AcpJsonRpcTransport, type AcpLoadThreadOptions, type AcpMcpKeyValue, type AcpMcpKeyValueCollection, type AcpMcpServerConfig, type AcpMcpServerWireConfig, type AcpNormalizeResult, type AcpNormalizerOptions, AcpOneShotClient, type AcpOneShotClientOptions, type AcpOneShotRequest, type AcpOneShotResponse, type AcpPackageDistribution, type AcpPathExecutableLister, type AcpPromptContentBlock, type AcpRegistryAgent, type AcpRegistryAgentWithPolicy, type AcpRegistryAuthDescriptor, type AcpRegistryAuthMethod, type AcpRegistryDistribution, type AcpRegistryFetch, AcpRegistryService, type AcpRegistryServiceOptions, type AcpRegistrySnapshot, type AcpRuntimeAgentCapabilities, type AcpRuntimeAgentInfo, type AcpRuntimeCapabilities, type AcpRuntimeCapabilitiesHandler, type AcpRuntimeCapabilitiesSource, type AcpRuntimeConfigOption, type AcpRuntimeConfigOptionValue, type AcpRuntimeMcpCapabilities, type AcpRuntimeMode, type AcpRuntimeModel, type AcpRuntimeModels, type AcpRuntimeModes, type AcpRuntimeOptionSource, AcpSessionNormalizer, type AcpSessionRuntimeState, type AcpSpawnSpec, type AcpSseMcpServerConfig, type AcpStartThreadOptions, type AcpStartTurnOptions, type AcpStdioMcpServerConfig, type AcpTitleHandler, type AcpVerificationStatus, BANNED_ACP_REGISTRY_IDS, BUILT_IN_ACP_STRATEGIES, DEFAULT_ACP_AGENT_ALLOWLIST, type DiscoveredAcpAgent, type DiscoveredAcpAgentGroup, type DiscoveredAcpAgentInstance, type LocalAcpAgentProbe, type LocalAcpDiscoveryOptions, type LocalAcpProbeResult, type RejectedAcpAgentInstance, acpRuntimeSupportsHttpMcp, acpRuntimeSupportsSessionLoad, acpRuntimeSupportsSseMcp, acpSessionRuntimeStateFromCapabilities, acpSessionRuntimeStateFromUpdate, asRecord, buildAcpBackendId, buildStrategyTable, defaultAcpAgentAllowlist, defaultQuirks, discoverLocalAcpAgentInstances, discoverLocalAcpAgents, evaluateAcpDistributionPolicy, geminiStrategy, grokStrategy, isBannedAcpRegistryId, kimiStrategy, mergeAcpRuntimeState, modeLabelFor, modelConfigOption, modelIdFromCapabilities, modelsFromCapabilities, normalizeAcpMcpServerConfig, normalizeAcpMcpServerConfigs, normalizeAcpRuntimeCapabilities, normalizeRegistry, qwenStrategy, readAcpContentText, readBoolean, readContentText, readFirstLocationPath, readFirstString, readKind, readNonEmptyString, readNumber, readPromptText, readString, readToolCallId, readToolContentText, readToolOutput, readUpdateText, reasoningValueForThoughtLevel, strategyByBackendId, strategyById, toolCallFromUpdate, wellKnownAgentBinDirs };
|
|
924
|
+
export { ACP_REGISTRY_URL, ACP_REQUEST_TIMEOUT_MESSAGE_PREFIX, AcpAgentAllowlist, type AcpAgentAllowlistRule, AcpAgentClient, type AcpAgentClientFactory, type AcpAgentClientOptions, AcpAgentClientPool, type AcpAgentClientPoolOptions, type AcpAgentConnection, type AcpAgentConnectionHandle, type AcpAgentInstanceSource, type AcpAgentQuirks, type AcpAgentStrategy, type AcpAllowlistDecision, type AcpApplyContext, type AcpBinaryPlatformDistribution, AcpConnection, type AcpConnectionOptions, type AcpDiscoveryProbe, type AcpDistributionKind, type AcpDistributionPolicy, type AcpHttpMcpServerConfig, type AcpJsonRpcTransport, type AcpLoadThreadOptions, type AcpMcpKeyValue, type AcpMcpKeyValueCollection, type AcpMcpServerConfig, type AcpMcpServerWireConfig, type AcpNormalizeResult, type AcpNormalizerOptions, AcpOneShotClient, type AcpOneShotClientOptions, type AcpOneShotRequest, type AcpOneShotResponse, type AcpPackageDistribution, type AcpPathExecutableLister, type AcpPromptContentBlock, type AcpRegistryAgent, type AcpRegistryAgentWithPolicy, type AcpRegistryAuthDescriptor, type AcpRegistryAuthMethod, type AcpRegistryDistribution, type AcpRegistryFetch, AcpRegistryService, type AcpRegistryServiceOptions, type AcpRegistrySnapshot, type AcpRuntimeAgentCapabilities, type AcpRuntimeAgentInfo, type AcpRuntimeCapabilities, type AcpRuntimeCapabilitiesHandler, type AcpRuntimeCapabilitiesSource, type AcpRuntimeConfigOption, type AcpRuntimeConfigOptionValue, type AcpRuntimeMcpCapabilities, type AcpRuntimeMode, type AcpRuntimeModel, type AcpRuntimeModels, type AcpRuntimeModes, type AcpRuntimeOptionSource, AcpSessionNormalizer, type AcpSessionRuntimeState, type AcpSpawnSpec, type AcpSseMcpServerConfig, type AcpStartThreadOptions, type AcpStartTurnOptions, type AcpStdioMcpServerConfig, type AcpTitleHandler, type AcpVerificationStatus, BANNED_ACP_REGISTRY_IDS, BUILT_IN_ACP_STRATEGIES, DEFAULT_ACP_AGENT_ALLOWLIST, DEFAULT_ACP_PROBE_TIMEOUT_MS, type DiscoveredAcpAgent, type DiscoveredAcpAgentGroup, type DiscoveredAcpAgentInstance, type LocalAcpAgentProbe, type LocalAcpDiscoveryOptions, type LocalAcpProbeOptions, type LocalAcpProbeResult, type RejectedAcpAgentInstance, acpRuntimeSupportsHttpMcp, acpRuntimeSupportsSessionLoad, acpRuntimeSupportsSseMcp, acpSessionRuntimeStateFromCapabilities, acpSessionRuntimeStateFromUpdate, asRecord, buildAcpBackendId, buildStrategyTable, defaultAcpAgentAllowlist, defaultQuirks, discoverLocalAcpAgentInstances, discoverLocalAcpAgents, evaluateAcpDistributionPolicy, geminiStrategy, grokStrategy, isBannedAcpRegistryId, kimiStrategy, mergeAcpRuntimeState, modeLabelFor, modelConfigOption, modelIdFromCapabilities, modelsFromCapabilities, normalizeAcpMcpServerConfig, normalizeAcpMcpServerConfigs, normalizeAcpRuntimeCapabilities, normalizeRegistry, qwenStrategy, readAcpContentText, readBoolean, readContentText, readFirstLocationPath, readFirstString, readKind, readNonEmptyString, readNumber, readPromptText, readString, readToolCallId, readToolContentText, readToolOutput, readUpdateText, reasoningValueForThoughtLevel, strategyByBackendId, strategyById, toolCallFromUpdate, wellKnownAgentBinDirs };
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,27 @@ import {
|
|
|
10
10
|
createCommandInvocation,
|
|
11
11
|
prependCommandDirToPath
|
|
12
12
|
} from "@pwrdrvr/agent-transport";
|
|
13
|
+
var ACP_REQUEST_TIMEOUT_MESSAGE_PREFIX = "acp request timed out";
|
|
14
|
+
function withAcpRequestTimeout(method, timeoutMs, run) {
|
|
15
|
+
if (timeoutMs === void 0 || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
16
|
+
return run();
|
|
17
|
+
}
|
|
18
|
+
const budget = Math.max(1, Math.floor(timeoutMs));
|
|
19
|
+
const call = run();
|
|
20
|
+
void call.catch(() => void 0);
|
|
21
|
+
let timer;
|
|
22
|
+
const expiry = new Promise((_, reject) => {
|
|
23
|
+
timer = setTimeout(
|
|
24
|
+
() => reject(
|
|
25
|
+
new Error(`${ACP_REQUEST_TIMEOUT_MESSAGE_PREFIX} after ${budget}ms: ${method}`)
|
|
26
|
+
),
|
|
27
|
+
budget
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
return Promise.race([call, expiry]).finally(() => {
|
|
31
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
13
34
|
var AcpConnection = class {
|
|
14
35
|
constructor(options) {
|
|
15
36
|
this.options = options;
|
|
@@ -101,10 +122,17 @@ var AcpConnection = class {
|
|
|
101
122
|
};
|
|
102
123
|
};
|
|
103
124
|
}
|
|
104
|
-
async request(method, params = {},
|
|
125
|
+
async request(method, params = {}, timeoutMs) {
|
|
105
126
|
await this.ensureConnected();
|
|
106
127
|
const conn = this.connection;
|
|
107
128
|
if (!conn) throw new Error("acp connection unavailable");
|
|
129
|
+
return await withAcpRequestTimeout(
|
|
130
|
+
method,
|
|
131
|
+
timeoutMs,
|
|
132
|
+
() => this.dispatch(conn, method, params)
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
async dispatch(conn, method, params) {
|
|
108
136
|
switch (method) {
|
|
109
137
|
case "initialize":
|
|
110
138
|
return await conn.initialize(params);
|
|
@@ -1436,6 +1464,8 @@ var AcpAgentClient = class {
|
|
|
1436
1464
|
}
|
|
1437
1465
|
async initialize() {
|
|
1438
1466
|
if (this.initialized) return;
|
|
1467
|
+
this.unsubscribeNotification?.();
|
|
1468
|
+
this.unsubscribeRequest?.();
|
|
1439
1469
|
this.unsubscribeNotification = this.transport.onNotification((method, params) => {
|
|
1440
1470
|
this.handleNotification(method, params);
|
|
1441
1471
|
});
|
|
@@ -2314,12 +2344,17 @@ import {
|
|
|
2314
2344
|
prependCommandDirToPath as prependCommandDirToPath2
|
|
2315
2345
|
} from "@pwrdrvr/agent-transport";
|
|
2316
2346
|
var execFile = promisify(execFileCallback);
|
|
2347
|
+
var DEFAULT_ACP_PROBE_TIMEOUT_MS = 5e3;
|
|
2317
2348
|
async function discoverLocalAcpAgentInstances(options = {}) {
|
|
2318
2349
|
const strategies = options.strategies ?? BUILT_IN_ACP_STRATEGIES;
|
|
2319
2350
|
const env = options.env ?? process.env;
|
|
2320
2351
|
const probe = options.probe ?? makeDefaultProbe(env);
|
|
2321
2352
|
const listExecutables = options.listExecutables ?? defaultListExecutables;
|
|
2322
2353
|
const now = options.now ?? Date.now;
|
|
2354
|
+
const probeOptions = {
|
|
2355
|
+
timeoutMs: options.probeTimeoutMs ?? DEFAULT_ACP_PROBE_TIMEOUT_MS,
|
|
2356
|
+
signal: options.signal
|
|
2357
|
+
};
|
|
2323
2358
|
const groups = await Promise.all(
|
|
2324
2359
|
strategies.map(
|
|
2325
2360
|
(strategy) => discoverStrategyInstances(
|
|
@@ -2329,7 +2364,8 @@ async function discoverLocalAcpAgentInstances(options = {}) {
|
|
|
2329
2364
|
env,
|
|
2330
2365
|
listExecutables,
|
|
2331
2366
|
options.overrides?.[strategy.id],
|
|
2332
|
-
options.includeRejectedCandidates === true
|
|
2367
|
+
options.includeRejectedCandidates === true,
|
|
2368
|
+
probeOptions
|
|
2333
2369
|
)
|
|
2334
2370
|
)
|
|
2335
2371
|
);
|
|
@@ -2353,22 +2389,27 @@ async function discoverLocalAcpAgents(options = {}) {
|
|
|
2353
2389
|
return [agent];
|
|
2354
2390
|
});
|
|
2355
2391
|
}
|
|
2356
|
-
async function discoverStrategyInstances(strategy, probe, now, env, listExecutables, override, includeRejectedCandidates = false) {
|
|
2392
|
+
async function discoverStrategyInstances(strategy, probe, now, env, listExecutables, override, includeRejectedCandidates = false, probeOptions = {}) {
|
|
2357
2393
|
const candidates = candidateCommands(strategy, env, listExecutables, override);
|
|
2358
2394
|
const instances = [];
|
|
2359
2395
|
const rejectedInstances = [];
|
|
2360
2396
|
for (const candidate of candidates) {
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
runProbe(probe, candidate.command, strategy.discoveryProbe.
|
|
2397
|
+
if (probeOptions.signal?.aborted) break;
|
|
2398
|
+
const [versionAttempt, helpAttempt] = await Promise.all([
|
|
2399
|
+
runProbe(probe, candidate.command, strategy.discoveryProbe.versionArgs, probeOptions),
|
|
2400
|
+
runProbe(probe, candidate.command, strategy.discoveryProbe.helpArgs, probeOptions)
|
|
2364
2401
|
]);
|
|
2402
|
+
if (probeOptions.signal?.aborted) break;
|
|
2403
|
+
const versionResult = versionAttempt.ok ? versionAttempt.result : void 0;
|
|
2404
|
+
const helpResult = helpAttempt.ok ? helpAttempt.result : void 0;
|
|
2365
2405
|
const version = versionResult ? parseCliVersion(resultText(versionResult)) : void 0;
|
|
2366
2406
|
if (!versionResult || !helpResult) {
|
|
2367
|
-
|
|
2407
|
+
const timedOut = !versionAttempt.ok && versionAttempt.timedOut || !helpAttempt.ok && helpAttempt.timedOut;
|
|
2408
|
+
if (candidate.detected && (timedOut || includeRejectedCandidates)) {
|
|
2368
2409
|
const rejected = {
|
|
2369
2410
|
command: candidate.command,
|
|
2370
2411
|
source: candidate.source,
|
|
2371
|
-
reason: versionResult ? "acp-probe-failed" : "version-probe-failed"
|
|
2412
|
+
reason: timedOut ? "probe-timed-out" : versionResult ? "acp-probe-failed" : "version-probe-failed"
|
|
2372
2413
|
};
|
|
2373
2414
|
if (version !== void 0) rejected.version = version;
|
|
2374
2415
|
rejectedInstances.push(rejected);
|
|
@@ -2531,25 +2572,78 @@ function ensureArgs(args, ensure) {
|
|
|
2531
2572
|
}
|
|
2532
2573
|
return result;
|
|
2533
2574
|
}
|
|
2575
|
+
var AcpProbeTimeoutError = class extends Error {
|
|
2576
|
+
constructor(command, timeoutMs) {
|
|
2577
|
+
super(`acp probe did not answer within ${timeoutMs}ms: ${command}`);
|
|
2578
|
+
this.name = "AcpProbeTimeoutError";
|
|
2579
|
+
}
|
|
2580
|
+
};
|
|
2581
|
+
function isProbeTimeout(error) {
|
|
2582
|
+
if (error instanceof AcpProbeTimeoutError) return true;
|
|
2583
|
+
const name = error?.name;
|
|
2584
|
+
return error?.killed === true || name === "AbortError" || name === "TimeoutError";
|
|
2585
|
+
}
|
|
2586
|
+
function normalizeProbeTimeoutMs(timeoutMs) {
|
|
2587
|
+
if (timeoutMs === void 0 || !Number.isFinite(timeoutMs)) {
|
|
2588
|
+
return DEFAULT_ACP_PROBE_TIMEOUT_MS;
|
|
2589
|
+
}
|
|
2590
|
+
return Math.max(1, Math.floor(timeoutMs));
|
|
2591
|
+
}
|
|
2534
2592
|
function makeDefaultProbe(env) {
|
|
2535
|
-
return async (command, args) => {
|
|
2593
|
+
return async (command, args, options = {}) => {
|
|
2594
|
+
const timeoutMs = normalizeProbeTimeoutMs(options.timeoutMs);
|
|
2536
2595
|
const launchEnv = prependCommandDirToPath2(command, env);
|
|
2537
2596
|
const invocation = createCommandInvocation2({ command, args, env: launchEnv });
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2597
|
+
const controller = new AbortController();
|
|
2598
|
+
let timedOut = false;
|
|
2599
|
+
const onAbort = () => controller.abort();
|
|
2600
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
2601
|
+
const timer = setTimeout(() => {
|
|
2602
|
+
timedOut = true;
|
|
2603
|
+
controller.abort();
|
|
2604
|
+
}, timeoutMs);
|
|
2605
|
+
const expired = new Promise((resolve) => {
|
|
2606
|
+
controller.signal.addEventListener("abort", () => resolve("expired"), {
|
|
2607
|
+
once: true
|
|
2608
|
+
});
|
|
2545
2609
|
});
|
|
2610
|
+
try {
|
|
2611
|
+
const execution = execFile(invocation.command, invocation.args, {
|
|
2612
|
+
timeout: timeoutMs,
|
|
2613
|
+
signal: controller.signal,
|
|
2614
|
+
maxBuffer: 1024 * 1024,
|
|
2615
|
+
// A Windows `.cmd` shim runs through `cmd.exe`; without this every
|
|
2616
|
+
// discovery pass flashes console windows over the host app.
|
|
2617
|
+
windowsHide: true,
|
|
2618
|
+
// Prepend the candidate's own dir so a node-script CLI (e.g. an nvm-
|
|
2619
|
+
// installed `qwen`) finds its sibling `node` during the probe.
|
|
2620
|
+
env: launchEnv,
|
|
2621
|
+
windowsVerbatimArguments: invocation.windowsVerbatimArguments
|
|
2622
|
+
}).then(
|
|
2623
|
+
(result) => ({ ok: true, result }),
|
|
2624
|
+
(error) => ({ ok: false, error })
|
|
2625
|
+
);
|
|
2626
|
+
const settled = await Promise.race([execution, expired]);
|
|
2627
|
+
if (settled === "expired") {
|
|
2628
|
+
if (timedOut) throw new AcpProbeTimeoutError(command, timeoutMs);
|
|
2629
|
+
throw new Error(`acp probe aborted: ${command}`);
|
|
2630
|
+
}
|
|
2631
|
+
if (!settled.ok) {
|
|
2632
|
+
if (timedOut) throw new AcpProbeTimeoutError(command, timeoutMs);
|
|
2633
|
+
throw settled.error;
|
|
2634
|
+
}
|
|
2635
|
+
return settled.result;
|
|
2636
|
+
} finally {
|
|
2637
|
+
clearTimeout(timer);
|
|
2638
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
2639
|
+
}
|
|
2546
2640
|
};
|
|
2547
2641
|
}
|
|
2548
|
-
async function runProbe(probe, command, args) {
|
|
2642
|
+
async function runProbe(probe, command, args, options) {
|
|
2549
2643
|
try {
|
|
2550
|
-
return await probe(command, args);
|
|
2551
|
-
} catch {
|
|
2552
|
-
return
|
|
2644
|
+
return { ok: true, result: await probe(command, args, options) };
|
|
2645
|
+
} catch (error) {
|
|
2646
|
+
return { ok: false, timedOut: isProbeTimeout(error) };
|
|
2553
2647
|
}
|
|
2554
2648
|
}
|
|
2555
2649
|
function resultText(result) {
|
|
@@ -2894,6 +2988,7 @@ function stringRecord(value) {
|
|
|
2894
2988
|
}
|
|
2895
2989
|
export {
|
|
2896
2990
|
ACP_REGISTRY_URL,
|
|
2991
|
+
ACP_REQUEST_TIMEOUT_MESSAGE_PREFIX,
|
|
2897
2992
|
AcpAgentAllowlist,
|
|
2898
2993
|
AcpAgentClient,
|
|
2899
2994
|
AcpAgentClientPool,
|
|
@@ -2904,6 +2999,7 @@ export {
|
|
|
2904
2999
|
BANNED_ACP_REGISTRY_IDS,
|
|
2905
3000
|
BUILT_IN_ACP_STRATEGIES,
|
|
2906
3001
|
DEFAULT_ACP_AGENT_ALLOWLIST,
|
|
3002
|
+
DEFAULT_ACP_PROBE_TIMEOUT_MS,
|
|
2907
3003
|
acpRuntimeSupportsHttpMcp,
|
|
2908
3004
|
acpRuntimeSupportsSessionLoad,
|
|
2909
3005
|
acpRuntimeSupportsSseMcp,
|