@agentconnect.md/daemon 1.0.0-rc.46 → 1.0.0-rc.48
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/agent-list-CZbaXHPF.js +21 -0
- package/dist/agent-list-CZbaXHPF.js.map +1 -0
- package/dist/{bridge-hZMpl3k6.js → bridge-NDvTO1zB.js} +2 -2
- package/dist/{bridge-hZMpl3k6.js.map → bridge-NDvTO1zB.js.map} +1 -1
- package/dist/index.js +220 -47
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,12 +4,12 @@ import { EventEmitter } from "node:events";
|
|
|
4
4
|
import childProcess, { execFile, spawn } from "node:child_process";
|
|
5
5
|
import * as sp from "node:path";
|
|
6
6
|
import path, { delimiter, dirname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
7
|
-
import fs, { accessSync, chmodSync, constants, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, stat, unlinkSync, unwatchFile, watch, watchFile, writeFileSync } from "node:fs";
|
|
7
|
+
import fs, { accessSync, chmodSync, constants, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, stat, unlinkSync, unwatchFile, watch, watchFile, writeFileSync } from "node:fs";
|
|
8
8
|
import process$1 from "node:process";
|
|
9
9
|
import { stripVTControlCharacters } from "node:util";
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
11
11
|
import { createInterface } from "node:readline";
|
|
12
|
-
import { cpus, freemem, homedir, hostname, totalmem, type } from "node:os";
|
|
12
|
+
import { cpus, freemem, homedir, hostname, tmpdir, totalmem, type } from "node:os";
|
|
13
13
|
import { spawn as spawn$1 } from "child_process";
|
|
14
14
|
import { Readable, Writable } from "node:stream";
|
|
15
15
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
@@ -3045,7 +3045,7 @@ var $ZodEncodeError = class extends Error {
|
|
|
3045
3045
|
};
|
|
3046
3046
|
(_a$2 = globalThis).__zod_globalConfig ?? (_a$2.__zod_globalConfig = {});
|
|
3047
3047
|
const globalConfig = globalThis.__zod_globalConfig;
|
|
3048
|
-
function config
|
|
3048
|
+
function config(newConfig) {
|
|
3049
3049
|
if (newConfig) Object.assign(globalConfig, newConfig);
|
|
3050
3050
|
return globalConfig;
|
|
3051
3051
|
}
|
|
@@ -3437,7 +3437,7 @@ const _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
|
3437
3437
|
}, ctx);
|
|
3438
3438
|
if (result instanceof Promise) throw new $ZodAsyncError();
|
|
3439
3439
|
if (result.issues.length) {
|
|
3440
|
-
const e = new ((_params?.Err) ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
3440
|
+
const e = new ((_params?.Err) ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
3441
3441
|
captureStackTrace(e, _params?.callee);
|
|
3442
3442
|
throw e;
|
|
3443
3443
|
}
|
|
@@ -3454,7 +3454,7 @@ const _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
|
|
3454
3454
|
}, ctx);
|
|
3455
3455
|
if (result instanceof Promise) result = await result;
|
|
3456
3456
|
if (result.issues.length) {
|
|
3457
|
-
const e = new ((params?.Err) ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
3457
|
+
const e = new ((params?.Err) ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
3458
3458
|
captureStackTrace(e, params?.callee);
|
|
3459
3459
|
throw e;
|
|
3460
3460
|
}
|
|
@@ -3472,7 +3472,7 @@ const _safeParse = (_Err) => (schema, value, _ctx) => {
|
|
|
3472
3472
|
if (result instanceof Promise) throw new $ZodAsyncError();
|
|
3473
3473
|
return result.issues.length ? {
|
|
3474
3474
|
success: false,
|
|
3475
|
-
error: new (_Err ?? $ZodError)(result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
3475
|
+
error: new (_Err ?? $ZodError)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
3476
3476
|
} : {
|
|
3477
3477
|
success: true,
|
|
3478
3478
|
data: result.value
|
|
@@ -3491,7 +3491,7 @@ const _safeParseAsync = (_Err) => async (schema, value, _ctx) => {
|
|
|
3491
3491
|
if (result instanceof Promise) result = await result;
|
|
3492
3492
|
return result.issues.length ? {
|
|
3493
3493
|
success: false,
|
|
3494
|
-
error: new _Err(result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
3494
|
+
error: new _Err(result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
3495
3495
|
} : {
|
|
3496
3496
|
success: true,
|
|
3497
3497
|
data: result.value
|
|
@@ -4732,7 +4732,7 @@ function handleUnionResults(results, final, inst, ctx) {
|
|
|
4732
4732
|
code: "invalid_union",
|
|
4733
4733
|
input: final.value,
|
|
4734
4734
|
inst,
|
|
4735
|
-
errors: results.map((result) => result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
4735
|
+
errors: results.map((result) => result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
4736
4736
|
});
|
|
4737
4737
|
return final;
|
|
4738
4738
|
}
|
|
@@ -4957,7 +4957,7 @@ const $ZodRecord = /*@__PURE__*/ $constructor("$ZodRecord", (inst, def) => {
|
|
|
4957
4957
|
payload.issues.push({
|
|
4958
4958
|
code: "invalid_key",
|
|
4959
4959
|
origin: "record",
|
|
4960
|
-
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
4960
|
+
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
4961
4961
|
input: key,
|
|
4962
4962
|
path: [key],
|
|
4963
4963
|
inst
|
|
@@ -5012,7 +5012,7 @@ const $ZodRecord = /*@__PURE__*/ $constructor("$ZodRecord", (inst, def) => {
|
|
|
5012
5012
|
else payload.issues.push({
|
|
5013
5013
|
code: "invalid_key",
|
|
5014
5014
|
origin: "record",
|
|
5015
|
-
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
5015
|
+
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
5016
5016
|
input: key,
|
|
5017
5017
|
path: [key],
|
|
5018
5018
|
inst
|
|
@@ -5209,7 +5209,7 @@ const $ZodCatch = /*@__PURE__*/ $constructor("$ZodCatch", (inst, def) => {
|
|
|
5209
5209
|
if (result.issues.length) {
|
|
5210
5210
|
payload.value = def.catchValue({
|
|
5211
5211
|
...payload,
|
|
5212
|
-
error: { issues: result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
5212
|
+
error: { issues: result.issues.map((iss) => finalizeIssue(iss, ctx, config())) },
|
|
5213
5213
|
input: payload.value
|
|
5214
5214
|
});
|
|
5215
5215
|
payload.issues = [];
|
|
@@ -5221,7 +5221,7 @@ const $ZodCatch = /*@__PURE__*/ $constructor("$ZodCatch", (inst, def) => {
|
|
|
5221
5221
|
if (result.issues.length) {
|
|
5222
5222
|
payload.value = def.catchValue({
|
|
5223
5223
|
...payload,
|
|
5224
|
-
error: { issues: result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
5224
|
+
error: { issues: result.issues.map((iss) => finalizeIssue(iss, ctx, config())) },
|
|
5225
5225
|
input: payload.value
|
|
5226
5226
|
});
|
|
5227
5227
|
payload.issues = [];
|
|
@@ -7529,7 +7529,7 @@ function toRuntimeDef(entry) {
|
|
|
7529
7529
|
return null;
|
|
7530
7530
|
}
|
|
7531
7531
|
const REGISTRY_URL = "https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json";
|
|
7532
|
-
const DEFAULT_TIMEOUT_MS = 4500;
|
|
7532
|
+
const DEFAULT_TIMEOUT_MS$1 = 4500;
|
|
7533
7533
|
function readCachedDoc(root) {
|
|
7534
7534
|
const file = registryPath(root);
|
|
7535
7535
|
if (!existsSync(file)) return null;
|
|
@@ -7555,7 +7555,7 @@ async function fetchRegistry(root, opts = {}) {
|
|
|
7555
7555
|
if (meta.etag) headers["If-None-Match"] = meta.etag;
|
|
7556
7556
|
if (meta.lastModified) headers["If-Modified-Since"] = meta.lastModified;
|
|
7557
7557
|
const ac = new AbortController();
|
|
7558
|
-
const timer = setTimeout(() => ac.abort(), opts.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
7558
|
+
const timer = setTimeout(() => ac.abort(), opts.timeoutMs ?? DEFAULT_TIMEOUT_MS$1);
|
|
7559
7559
|
try {
|
|
7560
7560
|
const res = await doFetch(REGISTRY_URL, {
|
|
7561
7561
|
headers,
|
|
@@ -16891,6 +16891,21 @@ CLIENT_METHODS.session_update, CLIENT_METHODS.elicitation_complete;
|
|
|
16891
16891
|
//#endregion
|
|
16892
16892
|
//#region src/acp/acp-host.ts
|
|
16893
16893
|
const PROTOCOL_VERSION = 1;
|
|
16894
|
+
/**
|
|
16895
|
+
* Extract the model selector from a session's `configOptions`. ACP models are an
|
|
16896
|
+
* (experimental) session config option tagged `category: "model"`, `type:
|
|
16897
|
+
* "select"`; the selectable values (optionally grouped) are the model list.
|
|
16898
|
+
* Returns null when the agent advertises no model selector.
|
|
16899
|
+
*/
|
|
16900
|
+
function modelOptionsFrom(configOptions) {
|
|
16901
|
+
const model = configOptions?.find((o) => o.category === "model" && o.type === "select");
|
|
16902
|
+
if (!model || model.type !== "select") return null;
|
|
16903
|
+
const models = model.options.flatMap((o) => "group" in o ? o.options : [o]).map((o) => o.value);
|
|
16904
|
+
return {
|
|
16905
|
+
current: model.currentValue,
|
|
16906
|
+
models
|
|
16907
|
+
};
|
|
16908
|
+
}
|
|
16894
16909
|
var AcpHost = class {
|
|
16895
16910
|
runtime;
|
|
16896
16911
|
opts;
|
|
@@ -16900,6 +16915,7 @@ var AcpHost = class {
|
|
|
16900
16915
|
loadingSessions = /* @__PURE__ */ new Set();
|
|
16901
16916
|
canLoad = false;
|
|
16902
16917
|
promptCaps = {};
|
|
16918
|
+
lastModelOptions = null;
|
|
16903
16919
|
constructor(runtime, opts) {
|
|
16904
16920
|
this.runtime = runtime;
|
|
16905
16921
|
this.opts = opts;
|
|
@@ -16953,9 +16969,15 @@ var AcpHost = class {
|
|
|
16953
16969
|
cwd,
|
|
16954
16970
|
mcpServers
|
|
16955
16971
|
});
|
|
16972
|
+
this.lastModelOptions = modelOptionsFrom(res.configOptions);
|
|
16956
16973
|
this.live.add(res.sessionId);
|
|
16957
16974
|
return res.sessionId;
|
|
16958
16975
|
}
|
|
16976
|
+
/** The model selector advertised by the most recent session/new, or null if the
|
|
16977
|
+
* agent exposed none. Used by the runtime probe to report available models. */
|
|
16978
|
+
modelOptions() {
|
|
16979
|
+
return this.lastModelOptions;
|
|
16980
|
+
}
|
|
16959
16981
|
/** True iff THIS agent process created or loaded `sessionId` in its current lifetime. */
|
|
16960
16982
|
hasSession(sessionId) {
|
|
16961
16983
|
return this.live.has(sessionId);
|
|
@@ -81439,13 +81461,18 @@ var Scheduler = class {
|
|
|
81439
81461
|
* only advertises genuinely-installed runtimes in `RegisterReq.capabilities`.
|
|
81440
81462
|
*
|
|
81441
81463
|
* Two layers:
|
|
81442
|
-
* 1. A generic launcher check — is the runtime's `command` resolvable?
|
|
81443
|
-
*
|
|
81444
|
-
*
|
|
81445
|
-
*
|
|
81446
|
-
*
|
|
81447
|
-
*
|
|
81448
|
-
*
|
|
81464
|
+
* 1. A generic launcher check — is the runtime's `command` resolvable? For a
|
|
81465
|
+
* runtime distributed as a real binary (`command` is the tool's own
|
|
81466
|
+
* executable) this is a meaningful signal: the binary on `$PATH` means it's
|
|
81467
|
+
* installed.
|
|
81468
|
+
* 2. For runtimes distributed via a package launcher (`npx`/`uvx`), (1) is
|
|
81469
|
+
* meaningless — the launcher fetches on demand, so "npx exists" is true on
|
|
81470
|
+
* virtually every dev host and tells us nothing about the wrapped agent. For
|
|
81471
|
+
* those we REQUIRE a per-runtime custom probe (`CUSTOM_PROBES`) that looks for
|
|
81472
|
+
* the wrapped CLI's own config/state dir, which appears once the user has
|
|
81473
|
+
* installed and run/initialized it. A launcher-distributed runtime with no
|
|
81474
|
+
* probe is treated as NOT installed — otherwise every npx/uvx agent in the
|
|
81475
|
+
* ACP registry would be falsely advertised just because `npx` is on `$PATH`.
|
|
81449
81476
|
*
|
|
81450
81477
|
* The custom probes test for the config *directory* (the "installed & initialized
|
|
81451
81478
|
* on this host" signal). A stricter "is logged in" check would look for the auth
|
|
@@ -81511,11 +81538,18 @@ const CUSTOM_PROBES = {
|
|
|
81511
81538
|
"factory-droid": (env) => pathExists(join(home(env), ".factory")),
|
|
81512
81539
|
devin: (env) => anyExists(join(xdgConfigHome(env), "devin"), join(xdgDataHome(env), "devin"))
|
|
81513
81540
|
};
|
|
81541
|
+
/**
|
|
81542
|
+
* Package launchers that fetch-and-run on demand. When a runtime is launched via
|
|
81543
|
+
* one of these, the launcher being on `$PATH` says nothing about whether the
|
|
81544
|
+
* wrapped agent is installed, so such runtimes require a custom probe to count.
|
|
81545
|
+
*/
|
|
81546
|
+
const PACKAGE_LAUNCHERS = /* @__PURE__ */ new Set(["npx", "uvx"]);
|
|
81514
81547
|
/** Is this runtime actually usable on this host? */
|
|
81515
81548
|
function isRuntimeAvailable(id, rt, env = process.env) {
|
|
81516
81549
|
if (!isCommandAvailable(rt.command, env)) return false;
|
|
81517
81550
|
const custom = CUSTOM_PROBES[id];
|
|
81518
|
-
|
|
81551
|
+
if (custom) return custom(env);
|
|
81552
|
+
return !PACKAGE_LAUNCHERS.has(rt.command);
|
|
81519
81553
|
}
|
|
81520
81554
|
/**
|
|
81521
81555
|
* Filter a runtime map down to those installed on this host — what the daemon
|
|
@@ -81527,6 +81561,89 @@ function installedRuntimes(runtimes, env = process.env) {
|
|
|
81527
81561
|
return out;
|
|
81528
81562
|
}
|
|
81529
81563
|
//#endregion
|
|
81564
|
+
//#region src/runtimes/runtime-prober.ts
|
|
81565
|
+
const DEFAULT_TIMEOUT_MS = 3e4;
|
|
81566
|
+
const DEFAULT_CONCURRENCY = 3;
|
|
81567
|
+
function makeHost(rt, log) {
|
|
81568
|
+
return new AcpHost(rt, {
|
|
81569
|
+
onUpdate: () => {},
|
|
81570
|
+
log
|
|
81571
|
+
});
|
|
81572
|
+
}
|
|
81573
|
+
/**
|
|
81574
|
+
* Probe one runtime. Never throws: any failure (spawn error, handshake failure,
|
|
81575
|
+
* timeout) is captured in `{ ok: false, error }`. On success, `models` reflects
|
|
81576
|
+
* whatever the agent advertised — an empty list is normal for agents that expose
|
|
81577
|
+
* no model selector, and is not a failure.
|
|
81578
|
+
*/
|
|
81579
|
+
async function probeRuntime(id, rt, cwd, opts = {}) {
|
|
81580
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
81581
|
+
const host = (opts.hostFactory ?? ((r) => makeHost(r, opts.log)))(rt);
|
|
81582
|
+
let timer;
|
|
81583
|
+
const timeout = new Promise((_, reject) => {
|
|
81584
|
+
timer = setTimeout(() => reject(/* @__PURE__ */ new Error(`probe timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
81585
|
+
});
|
|
81586
|
+
const run = async () => {
|
|
81587
|
+
await host.start();
|
|
81588
|
+
await host.newSession(cwd);
|
|
81589
|
+
return host.modelOptions();
|
|
81590
|
+
};
|
|
81591
|
+
try {
|
|
81592
|
+
const models = await Promise.race([run(), timeout]);
|
|
81593
|
+
opts.log?.info(`probe: ${id} ok (models: ${models?.models.length ? models.models.join(", ") : "none advertised"})`);
|
|
81594
|
+
return {
|
|
81595
|
+
runtime: id,
|
|
81596
|
+
ok: true,
|
|
81597
|
+
models: models?.models ?? [],
|
|
81598
|
+
currentModel: models?.current
|
|
81599
|
+
};
|
|
81600
|
+
} catch (err) {
|
|
81601
|
+
const error = err.message;
|
|
81602
|
+
opts.log?.warn(`probe: ${id} failed — ${error}`);
|
|
81603
|
+
return {
|
|
81604
|
+
runtime: id,
|
|
81605
|
+
ok: false,
|
|
81606
|
+
models: [],
|
|
81607
|
+
error
|
|
81608
|
+
};
|
|
81609
|
+
} finally {
|
|
81610
|
+
if (timer) clearTimeout(timer);
|
|
81611
|
+
await host.stop().catch(() => {});
|
|
81612
|
+
}
|
|
81613
|
+
}
|
|
81614
|
+
/**
|
|
81615
|
+
* Probe every runtime with bounded concurrency. All probes share one temp cwd
|
|
81616
|
+
* (removed afterward). Result order is not meaningful — callers key by
|
|
81617
|
+
* `result.runtime`.
|
|
81618
|
+
*/
|
|
81619
|
+
async function probeAllRuntimes(runtimes, opts = {}) {
|
|
81620
|
+
const ids = Object.keys(runtimes);
|
|
81621
|
+
if (ids.length === 0) return [];
|
|
81622
|
+
const cwd = mkdtempSync(join(tmpdir(), "ac-probe-"));
|
|
81623
|
+
const limit = Math.max(1, opts.concurrency ?? DEFAULT_CONCURRENCY);
|
|
81624
|
+
const results = [];
|
|
81625
|
+
let next = 0;
|
|
81626
|
+
const worker = async () => {
|
|
81627
|
+
for (let i = next++; i < ids.length; i = next++) {
|
|
81628
|
+
const id = ids[i];
|
|
81629
|
+
results.push(await probeRuntime(id, runtimes[id], cwd, opts));
|
|
81630
|
+
}
|
|
81631
|
+
};
|
|
81632
|
+
try {
|
|
81633
|
+
await Promise.all(Array.from({ length: Math.min(limit, ids.length) }, () => worker()));
|
|
81634
|
+
} finally {
|
|
81635
|
+
try {
|
|
81636
|
+
rmSync(cwd, {
|
|
81637
|
+
recursive: true,
|
|
81638
|
+
force: true
|
|
81639
|
+
});
|
|
81640
|
+
} catch (err) {
|
|
81641
|
+
opts.log?.debug(`probe: temp cwd cleanup failed for ${cwd}: ${err.message}`);
|
|
81642
|
+
}
|
|
81643
|
+
}
|
|
81644
|
+
return results;
|
|
81645
|
+
}
|
|
81646
|
+
//#endregion
|
|
81530
81647
|
//#region src/log.ts
|
|
81531
81648
|
const ORDER = {
|
|
81532
81649
|
trace: 10,
|
|
@@ -81728,7 +81845,17 @@ var CpClient = class {
|
|
|
81728
81845
|
this.heartbeatMs = ok.heartbeatSec > 0 ? ok.heartbeatSec * 1e3 : this.deps.heartbeatDefaultMs;
|
|
81729
81846
|
this.armHeartbeat();
|
|
81730
81847
|
this.deps.log.info(`cp: READY (epoch=${this.sessionEpoch}, routingEpoch=${this.routingEpoch})`);
|
|
81731
|
-
for (const profile of this.deps.runtimeProfiles()) this.
|
|
81848
|
+
for (const profile of this.deps.runtimeProfiles()) this.emitRuntimeProfile(profile);
|
|
81849
|
+
this.deps.onReady?.();
|
|
81850
|
+
}
|
|
81851
|
+
/**
|
|
81852
|
+
* Push a single runtime profile mid-session (D→C EVT, fire-and-forget). No-op
|
|
81853
|
+
* unless connected and READY/DRAINING — the CP only accepts control frames
|
|
81854
|
+
* there, and a reconnect's handshake re-emits the latest profiles anyway.
|
|
81855
|
+
*/
|
|
81856
|
+
emitRuntimeProfile(profile) {
|
|
81857
|
+
if (this.state !== "READY" && this.state !== "DRAINING") return;
|
|
81858
|
+
this.transport?.send(encode(buildEnvelope("facts/runtime-profile", profile)));
|
|
81732
81859
|
}
|
|
81733
81860
|
request(type, payload) {
|
|
81734
81861
|
const frame = buildEnvelope(type, payload);
|
|
@@ -82244,7 +82371,7 @@ function cpuTotals() {
|
|
|
82244
82371
|
busy
|
|
82245
82372
|
};
|
|
82246
82373
|
}
|
|
82247
|
-
var Daemon = class {
|
|
82374
|
+
var Daemon = class Daemon {
|
|
82248
82375
|
opts;
|
|
82249
82376
|
store;
|
|
82250
82377
|
mcp;
|
|
@@ -82266,6 +82393,9 @@ var Daemon = class {
|
|
|
82266
82393
|
runtimes = {};
|
|
82267
82394
|
runtimeNames = {};
|
|
82268
82395
|
runtimeVersions = {};
|
|
82396
|
+
runtimeModels = /* @__PURE__ */ new Map();
|
|
82397
|
+
probing = false;
|
|
82398
|
+
lastProbeAtMs = 0;
|
|
82269
82399
|
cpClient;
|
|
82270
82400
|
cpCrons;
|
|
82271
82401
|
cpAgents;
|
|
@@ -83216,13 +83346,8 @@ var Daemon = class {
|
|
|
83216
83346
|
acp: true,
|
|
83217
83347
|
features: []
|
|
83218
83348
|
}),
|
|
83219
|
-
runtimeProfiles: () => Object.keys(this.runtimes).map((id) => (
|
|
83220
|
-
|
|
83221
|
-
version: this.runtimeVersions[id] ?? "",
|
|
83222
|
-
models: [],
|
|
83223
|
-
acpSupport: "full",
|
|
83224
|
-
toolCalling: true
|
|
83225
|
-
})),
|
|
83349
|
+
runtimeProfiles: () => Object.keys(this.runtimes).map((id) => this.runtimeProfileFor(id)),
|
|
83350
|
+
onReady: () => void this.probeRuntimesAndEmit(),
|
|
83226
83351
|
localState: () => ({
|
|
83227
83352
|
assignments: [],
|
|
83228
83353
|
crons: this.cpCrons?.ids() ?? [],
|
|
@@ -83244,6 +83369,54 @@ var Daemon = class {
|
|
|
83244
83369
|
this.cpClient.start();
|
|
83245
83370
|
this.log.info(`cp: connecting to ${url}…`);
|
|
83246
83371
|
}
|
|
83372
|
+
/** Build the current `facts/runtime-profile` for a runtime, folding in any
|
|
83373
|
+
* models learned by the probe sweep. */
|
|
83374
|
+
runtimeProfileFor(id) {
|
|
83375
|
+
return {
|
|
83376
|
+
runtime: id,
|
|
83377
|
+
version: this.runtimeVersions[id] ?? "",
|
|
83378
|
+
models: this.runtimeModels.get(id) ?? [],
|
|
83379
|
+
acpSupport: "full",
|
|
83380
|
+
toolCalling: true
|
|
83381
|
+
};
|
|
83382
|
+
}
|
|
83383
|
+
/** How long a completed probe sweep stays fresh — reconnects within this window
|
|
83384
|
+
* re-emit the cached profiles instead of re-spawning every agent. */
|
|
83385
|
+
static PROBE_TTL_MS = 5 * 6e4;
|
|
83386
|
+
/**
|
|
83387
|
+
* Probe every installed runtime in the background (launch → initialize →
|
|
83388
|
+
* session/new → read models → tear down), then emit a refreshed
|
|
83389
|
+
* `facts/runtime-profile` per runtime once the whole sweep completes.
|
|
83390
|
+
*
|
|
83391
|
+
* Triggered on each CP (re)connect. Deduped while in flight; skipped (with a
|
|
83392
|
+
* cached re-emit) when the last sweep is still fresh, so a reconnect storm can't
|
|
83393
|
+
* spawn a fleet of agent subprocesses. Never throws — probing is best-effort and
|
|
83394
|
+
* must not affect the CP connection.
|
|
83395
|
+
*/
|
|
83396
|
+
async probeRuntimesAndEmit() {
|
|
83397
|
+
if (this.opts.hostFactory && !this.opts.probeRuntimes) return;
|
|
83398
|
+
const ids = Object.keys(this.runtimes);
|
|
83399
|
+
if (ids.length === 0) return;
|
|
83400
|
+
if (this.probing) return;
|
|
83401
|
+
if (this.lastProbeAtMs > 0 && Date.now() - this.lastProbeAtMs < Daemon.PROBE_TTL_MS) {
|
|
83402
|
+
for (const id of ids) this.cpClient?.emitRuntimeProfile(this.runtimeProfileFor(id));
|
|
83403
|
+
return;
|
|
83404
|
+
}
|
|
83405
|
+
this.probing = true;
|
|
83406
|
+
this.log.info(`probe: sweeping ${ids.length} runtime(s): ${ids.join(", ")}`);
|
|
83407
|
+
try {
|
|
83408
|
+
const results = await (this.opts.probeRuntimes ?? probeAllRuntimes)(this.runtimes, { log: this.log });
|
|
83409
|
+
for (const r of results) this.runtimeModels.set(r.runtime, r.ok ? r.models : []);
|
|
83410
|
+
this.lastProbeAtMs = Date.now();
|
|
83411
|
+
const okCount = results.filter((r) => r.ok).length;
|
|
83412
|
+
this.log.info(`probe: sweep complete — ${okCount}/${results.length} runtime(s) reachable`);
|
|
83413
|
+
for (const id of ids) this.cpClient?.emitRuntimeProfile(this.runtimeProfileFor(id));
|
|
83414
|
+
} catch (err) {
|
|
83415
|
+
this.log.warn(`probe: sweep failed: ${formatErr(err)}`);
|
|
83416
|
+
} finally {
|
|
83417
|
+
this.probing = false;
|
|
83418
|
+
}
|
|
83419
|
+
}
|
|
83247
83420
|
async stop() {
|
|
83248
83421
|
this.draining = true;
|
|
83249
83422
|
clearTimeout(this.debounceTimer);
|
|
@@ -83527,7 +83700,7 @@ program.command("run").description("Run the daemon in the foreground").action(as
|
|
|
83527
83700
|
}
|
|
83528
83701
|
});
|
|
83529
83702
|
program.command("mcp-bridge", { hidden: true }).description("internal: stdio MCP bridge to the running daemon").action(async () => {
|
|
83530
|
-
const { runBridge } = await import("./bridge-
|
|
83703
|
+
const { runBridge } = await import("./bridge-NDvTO1zB.js");
|
|
83531
83704
|
await runBridge();
|
|
83532
83705
|
});
|
|
83533
83706
|
const controller = () => resolveController({ root: program.opts().root });
|
|
@@ -83629,20 +83802,20 @@ program.command("login").description("Interactive onboarding: test the Control P
|
|
|
83629
83802
|
process.exit(1);
|
|
83630
83803
|
}
|
|
83631
83804
|
});
|
|
83632
|
-
|
|
83633
|
-
const
|
|
83634
|
-
|
|
83635
|
-
};
|
|
83636
|
-
|
|
83637
|
-
|
|
83638
|
-
|
|
83639
|
-
|
|
83640
|
-
|
|
83641
|
-
|
|
83642
|
-
|
|
83643
|
-
|
|
83644
|
-
|
|
83645
|
-
|
|
83805
|
+
program.command("agent").description("Inspect local agent directories").command("list").description("List agents discovered under --agents-dir (id, status, runtime, name, dir)").action(async () => {
|
|
83806
|
+
const opts = program.opts();
|
|
83807
|
+
try {
|
|
83808
|
+
const { runAgentList } = await import("./agent-list-CZbaXHPF.js");
|
|
83809
|
+
await runAgentList({
|
|
83810
|
+
agentsDir: opts.agentsDir,
|
|
83811
|
+
configPath: opts.config,
|
|
83812
|
+
root: opts.root
|
|
83813
|
+
});
|
|
83814
|
+
} catch (err) {
|
|
83815
|
+
console.error(`agentconnect agent list: ${err.message}`);
|
|
83816
|
+
process.exit(1);
|
|
83817
|
+
}
|
|
83818
|
+
});
|
|
83646
83819
|
program.command("chat [message]").description("Discover an agent under --agents-dir (or --agent <name>) and chat over ACP").action(async (message) => {
|
|
83647
83820
|
const opts = program.opts();
|
|
83648
83821
|
try {
|
|
@@ -83661,6 +83834,6 @@ program.command("chat [message]").description("Discover an agent under --agents-
|
|
|
83661
83834
|
});
|
|
83662
83835
|
program.parse();
|
|
83663
83836
|
//#endregion
|
|
83664
|
-
export {
|
|
83837
|
+
export { datetime as C, __toESM as E, unknown as S, __commonJSMin as T, optional as _, loadConfig as a, string as b, array as c, discriminatedUnion as d, intersection as f, object as g, number as h, discoverAgents as i, boolean as l, looseObject as m, encodeFrame as n, _enum as o, literal as p, DAEMON_VERSION as r, _null as s, decodeFrames as t, custom as u, preprocess as v, safeParse$1 as w, union as x, record as y };
|
|
83665
83838
|
|
|
83666
83839
|
//# sourceMappingURL=index.js.map
|