@automatalabs/workflows 0.49.0 → 0.50.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/mcp-server.js +388 -114
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -578,7 +578,8 @@ await runner.dispose();
|
|
|
578
578
|
**Event names.** The ACP `sessionUpdate` discriminants verbatim — `user_message_chunk`,
|
|
579
579
|
`agent_message_chunk`, `agent_thought_chunk`, `tool_call`, `tool_call_update`, `plan`,
|
|
580
580
|
`plan_update`, `plan_removed`, `available_commands_update`, `current_mode_update`,
|
|
581
|
-
`config_option_update`, `session_info_update`, `usage_update
|
|
581
|
+
`config_option_update`, `session_info_update`, `usage_update`, and (ACP schema 1.21.0, UNSTABLE)
|
|
582
|
+
`compaction_update`, `compaction_summary_chunk` — plus a few cross-cutting events:
|
|
582
583
|
|
|
583
584
|
| event | payload |
|
|
584
585
|
|-------|---------|
|
package/dist/index.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export { AGENTPRISM_PERSISTENCE_ROOT_ENV, WORKFLOW_PROJECTS_SUBDIR, workflowHome
|
|
|
17
17
|
export { withRunEvents, RunEventLogError, RUN_EVENT_READ_LIMIT_DEFAULT, RUN_EVENT_READ_LIMIT_MAX, RUN_EVENT_MAX_RECORD_BYTES, } from "@automatalabs/workflow-engine";
|
|
18
18
|
export type { RunEventPersistence, RunEventStream, AppendRunEventInput, ReadRunEventsOptions, ReadRunEventsResult, WatchRunEventsOptions, RunEventLogErrorCode, } from "@automatalabs/workflow-engine";
|
|
19
19
|
export { createAcpRunner, AcpAgentRunner, InteractiveSession, selectBackend, ClaudeBackend, CodexBackend, CustomAcpBackend, AGENT_METHODS, CLIENT_METHODS, AGENT_METHOD_COVERAGE, CLIENT_METHOD_COVERAGE, ACP_AUTH_REQUIRED_ERROR_CODE, clientCapabilitiesFor, adaptPromptContent, resolveBackendRegistry, BACKENDS_ENV, toJsonSchema, toStrictJsonSchema, } from "@automatalabs/acp-agents";
|
|
20
|
-
export type { AcpPoolOptions, AcpRunnerOptions, AuthenticateOptions, AuthMethodsOptions, DisableProviderOptions, DeleteSessionOptions, InteractiveSessionOptions, InteractiveTurn, SteeringOutcome, ListProvidersOptions, ListSessionsOptions, LogoutOptions, ProbeConfigOptionsOptions, ProbedConfigOptions, ReattachSessionOptions, SetProviderOptions, BackendRegistry, CustomBackendConfig, RegisteredBackend, ClientCapabilityOptions, ClientHandlers, FsHandlers, McpHandlers, TerminalHandlers, AcpSessionContext, NegotiatedCapabilities, PermissionResolver, AgentAuthCapabilities, AgentRequestMethod, AgentRequestParamsByMethod, AgentRequestResponsesByMethod, AuthCapabilities,
|
|
20
|
+
export type { AcpPoolOptions, AcpRunnerOptions, AuthenticateOptions, AuthMethodsOptions, DisableProviderOptions, DeleteSessionOptions, InteractiveSessionOptions, InteractiveTurn, SteeringOutcome, ListProvidersOptions, ListSessionsOptions, LogoutOptions, ProbeConfigOptionsOptions, ProbedConfigOptions, ReattachSessionOptions, SetProviderOptions, BackendRegistry, CustomBackendConfig, RegisteredBackend, ClientCapabilityOptions, ClientHandlers, FsHandlers, McpHandlers, TerminalHandlers, AcpSessionContext, NegotiatedCapabilities, PermissionResolver, AgentAuthCapabilities, AgentRequestMethod, AgentRequestParamsByMethod, AgentRequestResponsesByMethod, AuthCapabilities, AuthenticateRequest, AuthenticateResponse, AuthMethod, AuthMethodAgent, AuthMethodId, AuthMethodTerminal, ConnectMcpRequest, ConnectMcpResponse, DeleteSessionRequest, DeleteSessionResponse, DisableProviderRequest, DisableProviderResponse, DisconnectMcpRequest, DisconnectMcpResponse, ListProvidersRequest, ListProvidersResponse, ListSessionsRequest, ListSessionsResponse, LlmProtocol, LoadSessionRequest, LoadSessionResponse, LogoutCapabilities, LogoutRequest, LogoutResponse, McpConnectionId, McpServerAcp, McpServerAcpId, MessageMcpNotification, MessageMcpRequest, MessageMcpResponse, ProviderCurrentConfig, ProviderId, ProviderInfo, ProvidersCapabilities, ResumeSessionRequest, ResumeSessionResponse, SetProviderRequest, SetProviderResponse, AgentNotificationMethod, AgentNotificationParamsByMethod, CompleteElicitationNotification, CreateElicitationRequest, CreateElicitationResponse, ElicitationAcceptAction, ElicitationCapabilities, ElicitationContentValue, ElicitationFormCapabilities, ElicitationFormMode, ElicitationId, ElicitationPropertySchema, ElicitationRequestScope, ElicitationResolver, ElicitationSchema, ElicitationSchemaType, ElicitationSessionScope, ElicitationUrlCapabilities, ElicitationUrlMode, SessionMode, SessionModeState, SessionConfigOption, SessionInfo, SendRequestOptions, AgentMethodCoverage, ClientMethodCoverage, } from "@automatalabs/acp-agents";
|
|
21
21
|
export type { AuthResolver, AuthContext, AuthResolution, AuthMethodDescriptor, CompleteAuthOptions, AuthOutcome, AuthController, AuthStatusSnapshot, AuthCapableRunner, ProviderCapableRunner, } from "@automatalabs/acp-agents";
|
|
22
22
|
export type { ProviderUsageLimitContext, AuthErrorContext, CheckpointContext, } from "@automatalabs/shared-types";
|
|
23
23
|
export { TypedEventEmitter } from "@automatalabs/acp-agents";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp-server.js
CHANGED
|
@@ -26205,6 +26205,7 @@ var JSONRPCErrorResponseSchema = object2({
|
|
|
26205
26205
|
})
|
|
26206
26206
|
}).strict();
|
|
26207
26207
|
var isJSONRPCErrorResponse = (value) => JSONRPCErrorResponseSchema.safeParse(value).success;
|
|
26208
|
+
var isJSONRPCError = isJSONRPCErrorResponse;
|
|
26208
26209
|
var JSONRPCMessageSchema = union([
|
|
26209
26210
|
JSONRPCRequestSchema,
|
|
26210
26211
|
JSONRPCNotificationSchema,
|
|
@@ -32487,7 +32488,7 @@ var workflowRunLimitsSchema = external_exports.object({
|
|
|
32487
32488
|
var authContextSchema = external_exports.object({
|
|
32488
32489
|
backendId: external_exports.string().optional(),
|
|
32489
32490
|
methods: external_exports.array(
|
|
32490
|
-
external_exports.object({ id: external_exports.string(), type: external_exports.enum(["agent", "terminal"
|
|
32491
|
+
external_exports.object({ id: external_exports.string(), type: external_exports.enum(["agent", "terminal"]), name: external_exports.string().optional() })
|
|
32491
32492
|
)
|
|
32492
32493
|
});
|
|
32493
32494
|
var checkpointContextSchema = external_exports.object({
|
|
@@ -33556,6 +33557,19 @@ var ReplPresenceLedger = class {
|
|
|
33556
33557
|
drainingCount() {
|
|
33557
33558
|
return this.draining.size;
|
|
33558
33559
|
}
|
|
33560
|
+
/**
|
|
33561
|
+
* True when any workspace the session has affinity with has a subagent turn running. The
|
|
33562
|
+
* lame-duck migration keeps such sessions: closing one would drain the workspace here while
|
|
33563
|
+
* the migrated client re-opens it on the successor — a workspace split across two daemons.
|
|
33564
|
+
*/
|
|
33565
|
+
sessionHasBusyWorkspace(clientId) {
|
|
33566
|
+
const projects = this.bySession.get(clientId);
|
|
33567
|
+
if (projects === void 0) return false;
|
|
33568
|
+
for (const state of projects) {
|
|
33569
|
+
if (state.broker !== null && state.broker.busySessionCount() > 0) return true;
|
|
33570
|
+
}
|
|
33571
|
+
return false;
|
|
33572
|
+
}
|
|
33559
33573
|
/** Drop every session's presence (daemon shutdown): the scheduled
|
|
33560
33574
|
* drains see the projects' client sets emptied and run to completion
|
|
33561
33575
|
* on the already-disposed brokers — a no-op there, cleared here. */
|
|
@@ -33581,8 +33595,10 @@ var DAEMON_PORT_ENV = "AGENTPRISM_DAEMON_PORT";
|
|
|
33581
33595
|
var DAEMON_ALLOWED_ORIGINS_ENV = "AGENTPRISM_DAEMON_ALLOWED_ORIGINS";
|
|
33582
33596
|
var DAEMON_IDLE_TTL_MS = 15 * 6e4;
|
|
33583
33597
|
var DAEMON_IDLE_TTL_ENV = "AGENTPRISM_DAEMON_IDLE_TTL_MS";
|
|
33584
|
-
var SESSION_IDLE_TTL_MS =
|
|
33598
|
+
var SESSION_IDLE_TTL_MS = 5 * 6e4;
|
|
33585
33599
|
var SESSION_IDLE_TTL_ENV = "AGENTPRISM_SESSION_TTL_MS";
|
|
33600
|
+
var REPL_DRAIN_BOUND_MS = 2 * 60 * 6e4;
|
|
33601
|
+
var REPL_DRAIN_BOUND_ENV = "AGENTPRISM_REPL_DRAIN_BOUND_MS";
|
|
33586
33602
|
var REAPER_INTERVAL_MS = 6e4;
|
|
33587
33603
|
var EVENT_STORE_MAX_EVENTS_PER_STREAM = 1e3;
|
|
33588
33604
|
var EVENT_STORE_MAX_TOTAL_EVENTS = 1e4;
|
|
@@ -34066,7 +34082,7 @@ var WorkflowScriptResources = class {
|
|
|
34066
34082
|
// ../mcp-server/src/server.ts
|
|
34067
34083
|
var SERVER_NAME = "agentprism-workflow";
|
|
34068
34084
|
var require2 = createRequire(import.meta.url);
|
|
34069
|
-
var SERVER_VERSION = require2("../package.json").version;
|
|
34085
|
+
var SERVER_VERSION = true ? "0.30.1" : require2("../package.json").version;
|
|
34070
34086
|
var SERVER_INSTRUCTIONS = [
|
|
34071
34087
|
"This server exposes two model-facing tools for orchestrating multi-agent work. Both spawn subagents over the same ACP backends \u2014 the registry built-ins Claude, Codex, OpenCode, and pi, plus any registered custom agents \u2014 and key their durable state by an absolute projectDir (required on the shared daemon; defaults to the server's own project in single-project mode). Backend credentials come from each agent's own login (claude, codex, opencode, pi), so there is nothing auth-shaped to configure here.",
|
|
34072
34088
|
'\u2022 workflow \u2014 DETERMINISTIC BATCH orchestration. Supply a JavaScript workflow script (inline or by absolute scriptPath) that fans out agent() subagents and optional checkpoint() gates; it runs to completion in the foreground, or background:true returns a durable runId for bounded action:"await"/"inspect"/"stop" calls, with journaling, replay, and resumeFromRunId. Reach for it when the orchestration is known up front and you want it repeatable and resumable. The user-invocable author-workflow prompt helps write scripts.',
|
|
@@ -34884,7 +34900,7 @@ function createWorkflowServer(runner, options = {}) {
|
|
|
34884
34900
|
const defaultContext = requireProjectDir ? void 0 : projects.adopt(options.manager ?? new WorkflowManager3({ agent: runner }), options.backgroundRuns);
|
|
34885
34901
|
const scriptResources = new WorkflowScriptResources(mcp, { router: projects });
|
|
34886
34902
|
const backendApprovals = /* @__PURE__ */ new Set();
|
|
34887
|
-
const replPresence = options.replPresence ?? new ReplPresenceLedger(options.replDrainBoundMs ??
|
|
34903
|
+
const replPresence = options.replPresence ?? new ReplPresenceLedger(options.replDrainBoundMs ?? REPL_DRAIN_BOUND_MS);
|
|
34888
34904
|
const resolveContext2 = (input) => {
|
|
34889
34905
|
if (input.action === "inspect" || input.action === "await" || input.action === "stop") {
|
|
34890
34906
|
return projects.storeFor(input.runId) ?? defaultContext;
|
|
@@ -35418,6 +35434,7 @@ import { createHash } from "node:crypto";
|
|
|
35418
35434
|
import {
|
|
35419
35435
|
chmodSync,
|
|
35420
35436
|
mkdirSync,
|
|
35437
|
+
readdirSync as readdirSync2,
|
|
35421
35438
|
readFileSync as readFileSync3,
|
|
35422
35439
|
renameSync as renameSync2,
|
|
35423
35440
|
rmSync,
|
|
@@ -35438,11 +35455,20 @@ async function probeHealthz(port, timeoutMs = 2e3) {
|
|
|
35438
35455
|
return void 0;
|
|
35439
35456
|
}
|
|
35440
35457
|
}
|
|
35441
|
-
function
|
|
35442
|
-
return join2(workflowHomeDir2(), "
|
|
35458
|
+
function daemonsDir() {
|
|
35459
|
+
return join2(workflowHomeDir2(), "daemons");
|
|
35443
35460
|
}
|
|
35444
|
-
function
|
|
35445
|
-
return join2(
|
|
35461
|
+
function daemonInfoPath(fingerprint = envFingerprint()) {
|
|
35462
|
+
return join2(daemonsDir(), `${fingerprint}.json`);
|
|
35463
|
+
}
|
|
35464
|
+
function daemonLockPath(fingerprint = envFingerprint()) {
|
|
35465
|
+
return join2(daemonsDir(), `${fingerprint}.lock`);
|
|
35466
|
+
}
|
|
35467
|
+
function daemonInstancePath(pid) {
|
|
35468
|
+
return join2(daemonsDir(), "instances", `${pid}.json`);
|
|
35469
|
+
}
|
|
35470
|
+
function legacyDaemonInfoPath() {
|
|
35471
|
+
return join2(workflowHomeDir2(), "daemon.json");
|
|
35446
35472
|
}
|
|
35447
35473
|
function daemonLogPath() {
|
|
35448
35474
|
return join2(workflowHomeDir2(), "logs", "daemon.log");
|
|
@@ -35457,9 +35483,9 @@ function pidIsAlive(pid) {
|
|
|
35457
35483
|
return false;
|
|
35458
35484
|
}
|
|
35459
35485
|
}
|
|
35460
|
-
function
|
|
35486
|
+
function readInfoFile(path) {
|
|
35461
35487
|
try {
|
|
35462
|
-
const parsed = JSON.parse(readFileSync3(
|
|
35488
|
+
const parsed = JSON.parse(readFileSync3(path, "utf-8"));
|
|
35463
35489
|
if (parsed.name !== DAEMON_NAME || typeof parsed.pid !== "number" || typeof parsed.port !== "number" || typeof parsed.url !== "string" || typeof parsed.version !== "string") {
|
|
35464
35490
|
return void 0;
|
|
35465
35491
|
}
|
|
@@ -35468,34 +35494,97 @@ function readDaemonInfo() {
|
|
|
35468
35494
|
return void 0;
|
|
35469
35495
|
}
|
|
35470
35496
|
}
|
|
35471
|
-
function
|
|
35472
|
-
|
|
35497
|
+
function readDaemonInfo(fingerprint = envFingerprint()) {
|
|
35498
|
+
return readInfoFile(daemonInfoPath(fingerprint));
|
|
35499
|
+
}
|
|
35500
|
+
function writeInfoFile(path, info) {
|
|
35473
35501
|
mkdirSync(dirname(path), { recursive: true });
|
|
35474
|
-
const tmp = `${path}.${info.pid}.tmp`;
|
|
35502
|
+
const tmp = `${path}.${info.pid}.${randomUUID().slice(0, 8)}.tmp`;
|
|
35475
35503
|
writeFileSync(tmp, `${JSON.stringify(info, null, 2)}
|
|
35476
35504
|
`, { mode: 384 });
|
|
35477
35505
|
chmodSync(tmp, 384);
|
|
35478
35506
|
renameSync2(tmp, path);
|
|
35479
35507
|
}
|
|
35508
|
+
function writeDaemonInfo(info) {
|
|
35509
|
+
writeInfoFile(daemonInfoPath(info.envFingerprint), info);
|
|
35510
|
+
writeInfoFile(daemonInstancePath(info.pid), info);
|
|
35511
|
+
}
|
|
35480
35512
|
function clearDaemonInfo(pid) {
|
|
35481
|
-
const
|
|
35482
|
-
|
|
35513
|
+
const instance = readInfoFile(daemonInstancePath(pid));
|
|
35514
|
+
const fingerprint = instance?.envFingerprint ?? envFingerprint();
|
|
35515
|
+
const current = readDaemonInfo(fingerprint);
|
|
35516
|
+
try {
|
|
35517
|
+
if (current !== void 0 && current.pid === pid) rmSync(daemonInfoPath(fingerprint), { force: true });
|
|
35518
|
+
} catch {
|
|
35519
|
+
}
|
|
35483
35520
|
try {
|
|
35484
|
-
rmSync(
|
|
35521
|
+
rmSync(daemonInstancePath(pid), { force: true });
|
|
35485
35522
|
} catch {
|
|
35486
35523
|
}
|
|
35487
35524
|
}
|
|
35488
|
-
function isSupersededBy(ownPid) {
|
|
35489
|
-
const info = readDaemonInfo();
|
|
35525
|
+
function isSupersededBy(ownPid, fingerprint = envFingerprint()) {
|
|
35526
|
+
const info = readDaemonInfo(fingerprint);
|
|
35490
35527
|
return info !== void 0 && info.pid !== ownPid;
|
|
35491
35528
|
}
|
|
35529
|
+
function listDaemonInstances() {
|
|
35530
|
+
const instances = [];
|
|
35531
|
+
const seen = /* @__PURE__ */ new Set();
|
|
35532
|
+
const dir = join2(daemonsDir(), "instances");
|
|
35533
|
+
let files = [];
|
|
35534
|
+
try {
|
|
35535
|
+
files = readdirSync2(dir);
|
|
35536
|
+
} catch {
|
|
35537
|
+
files = [];
|
|
35538
|
+
}
|
|
35539
|
+
for (const file2 of files) {
|
|
35540
|
+
if (!file2.endsWith(".json")) continue;
|
|
35541
|
+
const path = join2(dir, file2);
|
|
35542
|
+
const info = readInfoFile(path);
|
|
35543
|
+
if (info === void 0 || !pidIsAlive(info.pid)) {
|
|
35544
|
+
try {
|
|
35545
|
+
rmSync(path, { force: true });
|
|
35546
|
+
} catch {
|
|
35547
|
+
}
|
|
35548
|
+
continue;
|
|
35549
|
+
}
|
|
35550
|
+
if (seen.has(info.pid)) continue;
|
|
35551
|
+
seen.add(info.pid);
|
|
35552
|
+
instances.push({ info, legacy: false });
|
|
35553
|
+
}
|
|
35554
|
+
const legacy = readInfoFile(legacyDaemonInfoPath());
|
|
35555
|
+
if (legacy !== void 0 && pidIsAlive(legacy.pid) && !seen.has(legacy.pid)) {
|
|
35556
|
+
instances.push({ info: legacy, legacy: true });
|
|
35557
|
+
}
|
|
35558
|
+
return instances;
|
|
35559
|
+
}
|
|
35560
|
+
function findDaemonInstanceOnPort(port) {
|
|
35561
|
+
return listDaemonInstances().find((instance) => instance.info.port === port);
|
|
35562
|
+
}
|
|
35492
35563
|
var ENV_FINGERPRINT_PREFIXES = ["AGENTPRISM_", "OPENCODE_ACP_", "PI_ACP_", "CODEX_ACP_"];
|
|
35564
|
+
var ENV_FINGERPRINT_EXCLUDED = /* @__PURE__ */ new Set([DAEMON_IDLE_TTL_ENV, SESSION_IDLE_TTL_ENV, REPL_DRAIN_BOUND_ENV]);
|
|
35493
35565
|
function envFingerprint(env = process.env) {
|
|
35494
|
-
const relevant = Object.entries(env).filter(([key, value]) => value !== void 0 && ENV_FINGERPRINT_PREFIXES.some((p2) => key.startsWith(p2))).filter(([key]) => key
|
|
35566
|
+
const relevant = Object.entries(env).filter(([key, value]) => value !== void 0 && ENV_FINGERPRINT_PREFIXES.some((p2) => key.startsWith(p2))).filter(([key]) => !ENV_FINGERPRINT_EXCLUDED.has(key)).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, value]) => `${key}=${value}`).join("\n");
|
|
35495
35567
|
return createHash("sha256").update(relevant).digest("hex").slice(0, 16);
|
|
35496
35568
|
}
|
|
35497
|
-
function
|
|
35498
|
-
const
|
|
35569
|
+
function compareVersions(a, b) {
|
|
35570
|
+
const parse3 = (value) => {
|
|
35571
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(value.trim());
|
|
35572
|
+
if (match === null) return void 0;
|
|
35573
|
+
return { nums: [Number(match[1]), Number(match[2]), Number(match[3])], pre: match[4] };
|
|
35574
|
+
};
|
|
35575
|
+
const pa = parse3(a);
|
|
35576
|
+
const pb = parse3(b);
|
|
35577
|
+
if (pa === void 0 || pb === void 0) return a < b ? -1 : a > b ? 1 : 0;
|
|
35578
|
+
for (let i = 0; i < 3; i++) {
|
|
35579
|
+
if (pa.nums[i] !== pb.nums[i]) return pa.nums[i] - pb.nums[i];
|
|
35580
|
+
}
|
|
35581
|
+
if (pa.pre === void 0 && pb.pre === void 0) return 0;
|
|
35582
|
+
if (pa.pre === void 0) return 1;
|
|
35583
|
+
if (pb.pre === void 0) return -1;
|
|
35584
|
+
return pa.pre < pb.pre ? -1 : pa.pre > pb.pre ? 1 : 0;
|
|
35585
|
+
}
|
|
35586
|
+
function claimSpawnLock(fingerprint = envFingerprint()) {
|
|
35587
|
+
const path = daemonLockPath(fingerprint);
|
|
35499
35588
|
mkdirSync(dirname(path), { recursive: true });
|
|
35500
35589
|
const lock = { pid: process.pid, startedAt: (/* @__PURE__ */ new Date()).toISOString(), token: randomUUID() };
|
|
35501
35590
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
@@ -35520,8 +35609,8 @@ function claimSpawnLock() {
|
|
|
35520
35609
|
}
|
|
35521
35610
|
return null;
|
|
35522
35611
|
}
|
|
35523
|
-
function releaseSpawnLock(lock) {
|
|
35524
|
-
const path = daemonLockPath();
|
|
35612
|
+
function releaseSpawnLock(lock, fingerprint = envFingerprint()) {
|
|
35613
|
+
const path = daemonLockPath(fingerprint);
|
|
35525
35614
|
try {
|
|
35526
35615
|
const holder = JSON.parse(readFileSync3(path, "utf-8"));
|
|
35527
35616
|
if (holder.token !== lock.token) return;
|
|
@@ -35531,27 +35620,21 @@ function releaseSpawnLock(lock) {
|
|
|
35531
35620
|
}
|
|
35532
35621
|
|
|
35533
35622
|
// ../mcp-server/src/shim/ensure-daemon.ts
|
|
35534
|
-
function
|
|
35535
|
-
return live.version
|
|
35623
|
+
function isStale(live) {
|
|
35624
|
+
return compareVersions(live.version, SERVER_VERSION) < 0;
|
|
35536
35625
|
}
|
|
35537
|
-
async function probeLiveDaemon() {
|
|
35538
|
-
const info = readDaemonInfo();
|
|
35626
|
+
async function probeLiveDaemon(fingerprint) {
|
|
35627
|
+
const info = readDaemonInfo(fingerprint);
|
|
35539
35628
|
if (info === void 0 || !pidIsAlive(info.pid)) return void 0;
|
|
35540
35629
|
const health = await probeHealthz(info.port);
|
|
35541
35630
|
if (health === void 0 || health.pid !== info.pid) return void 0;
|
|
35542
|
-
return {
|
|
35543
|
-
info,
|
|
35544
|
-
sessions: health.sessions,
|
|
35545
|
-
activeRuns: health.activeRuns,
|
|
35546
|
-
version: health.version,
|
|
35547
|
-
envFingerprint: health.envFingerprint
|
|
35548
|
-
};
|
|
35631
|
+
return { info, sessions: health.sessions, activeRuns: health.activeRuns, version: health.version };
|
|
35549
35632
|
}
|
|
35550
35633
|
async function waitForCurrentDaemon(fingerprint, timeoutMs) {
|
|
35551
35634
|
const start = Date.now();
|
|
35552
35635
|
while (Date.now() - start < timeoutMs) {
|
|
35553
|
-
const live = await probeLiveDaemon();
|
|
35554
|
-
if (live !== void 0 && !
|
|
35636
|
+
const live = await probeLiveDaemon(fingerprint);
|
|
35637
|
+
if (live !== void 0 && !isStale(live)) return live.info;
|
|
35555
35638
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
35556
35639
|
}
|
|
35557
35640
|
return void 0;
|
|
@@ -35588,29 +35671,32 @@ function spawnDetachedDaemon(args) {
|
|
|
35588
35671
|
async function ensureDaemonRunning(options) {
|
|
35589
35672
|
const fingerprint = envFingerprint();
|
|
35590
35673
|
const spawnDaemon = options.spawn ?? ((args) => spawnDetachedDaemon(args));
|
|
35591
|
-
const
|
|
35592
|
-
|
|
35593
|
-
|
|
35594
|
-
|
|
35595
|
-
|
|
35596
|
-
if (live.envFingerprint !== fingerprint) {
|
|
35597
|
-
reasons.push(`env fingerprint ${live.envFingerprint} \u2192 ${fingerprint}`);
|
|
35674
|
+
const adopt = (live2) => {
|
|
35675
|
+
if (compareVersions(live2.version, SERVER_VERSION) > 0) {
|
|
35676
|
+
options.log(
|
|
35677
|
+
`[${DAEMON_NAME}] adopting daemon v${live2.version} (pid ${live2.info.pid}), newer than this client v${SERVER_VERSION}`
|
|
35678
|
+
);
|
|
35598
35679
|
}
|
|
35680
|
+
return live2.info;
|
|
35681
|
+
};
|
|
35682
|
+
const live = await probeLiveDaemon(fingerprint);
|
|
35683
|
+
if (live !== void 0 && !isStale(live)) return adopt(live);
|
|
35684
|
+
if (live !== void 0) {
|
|
35599
35685
|
options.log(
|
|
35600
|
-
`[${DAEMON_NAME}] superseding stale daemon (pid ${live.info.pid}, ${live.sessions} session(s), ${live.activeRuns} run(s)): ${
|
|
35686
|
+
`[${DAEMON_NAME}] superseding stale daemon (pid ${live.info.pid}, ${live.sessions} session(s), ${live.activeRuns} run(s)): version v${live.version} \u2192 v${SERVER_VERSION} \u2014 spawning a successor and repointing discovery`
|
|
35601
35687
|
);
|
|
35602
35688
|
}
|
|
35603
|
-
const lock = claimSpawnLock();
|
|
35689
|
+
const lock = claimSpawnLock(fingerprint);
|
|
35604
35690
|
if (lock === null) {
|
|
35605
35691
|
const info = await waitForCurrentDaemon(fingerprint, SPAWN_HEALTH_TIMEOUT_MS);
|
|
35606
35692
|
if (info !== void 0) return info;
|
|
35607
35693
|
throw new Error(
|
|
35608
|
-
`[${DAEMON_NAME}] another process is starting the daemon but no current
|
|
35694
|
+
`[${DAEMON_NAME}] another process is starting the daemon but no current daemon became healthy; see ${daemonLogPath()}`
|
|
35609
35695
|
);
|
|
35610
35696
|
}
|
|
35611
35697
|
try {
|
|
35612
|
-
const raced = await probeLiveDaemon();
|
|
35613
|
-
if (raced !== void 0 && !
|
|
35698
|
+
const raced = await probeLiveDaemon(fingerprint);
|
|
35699
|
+
if (raced !== void 0 && !isStale(raced)) return adopt(raced);
|
|
35614
35700
|
const superseding = raced !== void 0;
|
|
35615
35701
|
spawnDaemon({ bundlePath: options.bundlePath, port: options.port, supersede: superseding });
|
|
35616
35702
|
const info = await waitForCurrentDaemon(fingerprint, SPAWN_HEALTH_TIMEOUT_MS);
|
|
@@ -35621,12 +35707,12 @@ async function ensureDaemonRunning(options) {
|
|
|
35621
35707
|
}
|
|
35622
35708
|
if (superseding) {
|
|
35623
35709
|
options.log(
|
|
35624
|
-
`[${DAEMON_NAME}] succession complete: connected to v${info.version} daemon (pid ${info.pid}) at ${info.url}; the superseded daemon will finish its work and exit`
|
|
35710
|
+
`[${DAEMON_NAME}] succession complete: connected to v${info.version} daemon (pid ${info.pid}) at ${info.url}; the superseded daemon will migrate its sessions, finish its work, and exit`
|
|
35625
35711
|
);
|
|
35626
35712
|
}
|
|
35627
35713
|
return info;
|
|
35628
35714
|
} finally {
|
|
35629
|
-
releaseSpawnLock(lock);
|
|
35715
|
+
releaseSpawnLock(lock, fingerprint);
|
|
35630
35716
|
}
|
|
35631
35717
|
}
|
|
35632
35718
|
|
|
@@ -35644,19 +35730,43 @@ function installDaemonLifecycle(options) {
|
|
|
35644
35730
|
const log = options.log ?? ((line) => console.error(line));
|
|
35645
35731
|
let shutdownPromise;
|
|
35646
35732
|
let idleSince;
|
|
35733
|
+
let supersessionAnnounced = false;
|
|
35647
35734
|
const onSigint = () => void lifecycle.shutdown("SIGINT");
|
|
35648
35735
|
const onSigterm = () => void lifecycle.shutdown("SIGTERM");
|
|
35649
35736
|
const reaper = setInterval(() => {
|
|
35650
|
-
const
|
|
35651
|
-
|
|
35652
|
-
|
|
35737
|
+
const daemon = options.daemon;
|
|
35738
|
+
const superseded = daemon.isSuperseded();
|
|
35739
|
+
if (superseded) {
|
|
35740
|
+
if (!supersessionAnnounced) {
|
|
35741
|
+
supersessionAnnounced = true;
|
|
35742
|
+
log(
|
|
35743
|
+
`[agentprism-daemon] superseded by a newer daemon; draining \u2014 ${daemon.sessions.size} session(s), ${daemon.activeRunCount()} run(s), ${daemon.inflightRequestCount()} request(s) in flight`
|
|
35744
|
+
);
|
|
35745
|
+
}
|
|
35746
|
+
if (daemon.activeRunCount() === 0) {
|
|
35747
|
+
const migrated = daemon.evictDrainableSessions();
|
|
35748
|
+
if (migrated.length > 0) {
|
|
35749
|
+
log(`[agentprism-daemon] migrated ${migrated.length} idle session(s) to the successor: ${migrated.join(", ")}`);
|
|
35750
|
+
}
|
|
35751
|
+
}
|
|
35752
|
+
} else {
|
|
35753
|
+
supersessionAnnounced = false;
|
|
35754
|
+
const evicted = daemon.sessions.evictIdle(options.sessionTtlMs);
|
|
35755
|
+
if (evicted.length > 0) {
|
|
35756
|
+
log(`[agentprism-daemon] evicted ${evicted.length} idle session(s): ${evicted.join(", ")}`);
|
|
35757
|
+
}
|
|
35653
35758
|
}
|
|
35654
|
-
|
|
35655
|
-
const busy = options.daemon.sessions.size > 0 || options.daemon.activeRunCount() > 0 || options.daemon.activeReplDrainCount() > 0;
|
|
35759
|
+
const busy = daemon.sessions.size > 0 || daemon.activeRunCount() > 0 || daemon.activeReplDrainCount() > 0;
|
|
35656
35760
|
if (busy) {
|
|
35657
35761
|
idleSince = void 0;
|
|
35658
35762
|
return;
|
|
35659
35763
|
}
|
|
35764
|
+
if (superseded) {
|
|
35765
|
+
log("[agentprism-daemon] superseded and nothing in flight; exiting");
|
|
35766
|
+
void lifecycle.shutdown("superseded");
|
|
35767
|
+
return;
|
|
35768
|
+
}
|
|
35769
|
+
if (options.idleTtlMs <= 0) return;
|
|
35660
35770
|
idleSince ??= Date.now();
|
|
35661
35771
|
if (Date.now() - idleSince >= options.idleTtlMs) {
|
|
35662
35772
|
log(`[agentprism-daemon] idle for ${options.idleTtlMs}ms with no sessions, runs, or repl drains; shutting down`);
|
|
@@ -37174,7 +37284,7 @@ var SessionRegistry = class {
|
|
|
37174
37284
|
*/
|
|
37175
37285
|
onSessionDeleted;
|
|
37176
37286
|
add(record2) {
|
|
37177
|
-
this.sessions.set(record2.sessionId, record2);
|
|
37287
|
+
this.sessions.set(record2.sessionId, { ...record2, inflightRequests: record2.inflightRequests ?? 0 });
|
|
37178
37288
|
}
|
|
37179
37289
|
get(sessionId) {
|
|
37180
37290
|
return this.sessions.get(sessionId);
|
|
@@ -37204,6 +37314,22 @@ var SessionRegistry = class {
|
|
|
37204
37314
|
this.onLastConnectionClosed?.(sessionId);
|
|
37205
37315
|
}
|
|
37206
37316
|
}
|
|
37317
|
+
/** A request (POST) started being processed on the session. */
|
|
37318
|
+
requestStarted(sessionId) {
|
|
37319
|
+
const record2 = this.sessions.get(sessionId);
|
|
37320
|
+
if (record2 !== void 0) record2.inflightRequests++;
|
|
37321
|
+
}
|
|
37322
|
+
/** The request's response finished (or its connection closed). */
|
|
37323
|
+
requestFinished(sessionId) {
|
|
37324
|
+
const record2 = this.sessions.get(sessionId);
|
|
37325
|
+
if (record2 !== void 0) record2.inflightRequests = Math.max(0, record2.inflightRequests - 1);
|
|
37326
|
+
}
|
|
37327
|
+
/** Requests being processed right now, across every session. */
|
|
37328
|
+
inflightCount() {
|
|
37329
|
+
let total = 0;
|
|
37330
|
+
for (const record2 of this.sessions.values()) total += record2.inflightRequests;
|
|
37331
|
+
return total;
|
|
37332
|
+
}
|
|
37207
37333
|
get size() {
|
|
37208
37334
|
return this.sessions.size;
|
|
37209
37335
|
}
|
|
@@ -37221,6 +37347,21 @@ var SessionRegistry = class {
|
|
|
37221
37347
|
}
|
|
37222
37348
|
return evicted;
|
|
37223
37349
|
}
|
|
37350
|
+
/**
|
|
37351
|
+
* Close every session with NO request in flight — the lame-duck migration: the client's
|
|
37352
|
+
* next frame (or its standalone GET stream ending) makes it re-initialize on the successor.
|
|
37353
|
+
* `keep` can veto a session (the daemon keeps sessions whose REPL workspace is mid-turn).
|
|
37354
|
+
*/
|
|
37355
|
+
evictDrainable(keep = () => false) {
|
|
37356
|
+
const evicted = [];
|
|
37357
|
+
for (const record2 of this.sessions.values()) {
|
|
37358
|
+
if (record2.inflightRequests > 0) continue;
|
|
37359
|
+
if (keep(record2.sessionId)) continue;
|
|
37360
|
+
evicted.push(record2.sessionId);
|
|
37361
|
+
void record2.transport.close().catch(() => void 0);
|
|
37362
|
+
}
|
|
37363
|
+
return evicted;
|
|
37364
|
+
}
|
|
37224
37365
|
async closeAll() {
|
|
37225
37366
|
const records = [...this.sessions.values()];
|
|
37226
37367
|
await Promise.allSettled(records.map((record2) => record2.transport.close()));
|
|
@@ -37251,7 +37392,8 @@ async function createDaemon(options) {
|
|
|
37251
37392
|
const isSuperseded = options.isSuperseded ?? (() => isSupersededBy(ownPid));
|
|
37252
37393
|
const sessions = new SessionRegistry();
|
|
37253
37394
|
const projects = new WorkflowProjectRegistry(options.runner);
|
|
37254
|
-
const
|
|
37395
|
+
const replDrainBoundMs = options.replDrainBoundMs ?? options.sessionTtlMs ?? REPL_DRAIN_BOUND_MS;
|
|
37396
|
+
const replPresence = new ReplPresenceLedger(replDrainBoundMs);
|
|
37255
37397
|
sessions.onConnectionOpened = (sessionId) => replPresence.reconnect(sessionId);
|
|
37256
37398
|
sessions.onLastConnectionClosed = (sessionId) => replPresence.disconnect(sessionId);
|
|
37257
37399
|
sessions.onSessionDeleted = (sessionId) => replPresence.forget(sessionId);
|
|
@@ -37266,7 +37408,12 @@ async function createDaemon(options) {
|
|
|
37266
37408
|
return;
|
|
37267
37409
|
}
|
|
37268
37410
|
sessions.connectionOpened(sessionId);
|
|
37269
|
-
|
|
37411
|
+
const isRequest = req.method === "POST";
|
|
37412
|
+
if (isRequest) sessions.requestStarted(sessionId);
|
|
37413
|
+
res.on("close", () => {
|
|
37414
|
+
if (isRequest) sessions.requestFinished(sessionId);
|
|
37415
|
+
sessions.connectionClosed(sessionId);
|
|
37416
|
+
});
|
|
37270
37417
|
await record2.transport.handleRequest(req, res);
|
|
37271
37418
|
return;
|
|
37272
37419
|
}
|
|
@@ -37300,7 +37447,7 @@ async function createDaemon(options) {
|
|
|
37300
37447
|
replRunner: options.replRunner,
|
|
37301
37448
|
replPresence,
|
|
37302
37449
|
replClientId: () => transport.sessionId,
|
|
37303
|
-
replDrainBoundMs
|
|
37450
|
+
replDrainBoundMs,
|
|
37304
37451
|
replEvalBreakChannel: options.evalBreakChannel
|
|
37305
37452
|
});
|
|
37306
37453
|
await server.connect(transport);
|
|
@@ -37341,7 +37488,8 @@ async function createDaemon(options) {
|
|
|
37341
37488
|
activeRuns: projects.activeRunCount(),
|
|
37342
37489
|
envFingerprint: envFingerprint(env),
|
|
37343
37490
|
projects: projects.snapshot(),
|
|
37344
|
-
lameDuck: isSuperseded()
|
|
37491
|
+
lameDuck: isSuperseded(),
|
|
37492
|
+
inflightRequests: sessions.inflightCount()
|
|
37345
37493
|
})
|
|
37346
37494
|
);
|
|
37347
37495
|
return;
|
|
@@ -37376,6 +37524,9 @@ async function createDaemon(options) {
|
|
|
37376
37524
|
projects,
|
|
37377
37525
|
activeRunCount: () => projects.activeRunCount(),
|
|
37378
37526
|
activeReplDrainCount: () => replPresence.drainingCount(),
|
|
37527
|
+
inflightRequestCount: () => sessions.inflightCount(),
|
|
37528
|
+
isSuperseded,
|
|
37529
|
+
evictDrainableSessions: () => sessions.evictDrainable((sessionId) => replPresence.sessionHasBusyWorkspace(sessionId)),
|
|
37379
37530
|
async close() {
|
|
37380
37531
|
const closed = new Promise((resolvePromise) => {
|
|
37381
37532
|
httpServer.close(() => resolvePromise());
|
|
@@ -37412,22 +37563,37 @@ async function runDaemon(options = {}) {
|
|
|
37412
37563
|
const supersede = options.supersede ?? false;
|
|
37413
37564
|
let daemon;
|
|
37414
37565
|
const sessionTtlMs = envInt(SESSION_IDLE_TTL_ENV, SESSION_IDLE_TTL_MS);
|
|
37566
|
+
const replDrainBoundMs = envInt(REPL_DRAIN_BOUND_ENV, REPL_DRAIN_BOUND_MS);
|
|
37567
|
+
const describePortHolder = (port) => {
|
|
37568
|
+
const holder = findDaemonInstanceOnPort(port);
|
|
37569
|
+
if (holder === void 0) return `port ${port} is taken by another process`;
|
|
37570
|
+
return `port ${port} is still held by ${holder.legacy ? "a legacy " : ""}daemon pid ${holder.info.pid} (v${holder.info.version}, started ${holder.info.startedAt})`;
|
|
37571
|
+
};
|
|
37415
37572
|
const evalBreakChannel = createEvalBreakChannel2();
|
|
37573
|
+
const daemonOptions = { runner, log, replDrainBoundMs, evalBreakChannel };
|
|
37416
37574
|
if (supersede) {
|
|
37417
|
-
|
|
37418
|
-
|
|
37575
|
+
let port = options.port ?? 0;
|
|
37576
|
+
try {
|
|
37577
|
+
daemon = await createDaemon({ ...daemonOptions, port });
|
|
37578
|
+
} catch (error51) {
|
|
37579
|
+
if (!(error51 instanceof DaemonPortInUseError) || port === 0) throw error51;
|
|
37580
|
+
log(`[${DAEMON_NAME}] ${describePortHolder(port)}; successor falling back to an ephemeral port`);
|
|
37581
|
+
port = 0;
|
|
37582
|
+
daemon = await createDaemon({ ...daemonOptions, port });
|
|
37583
|
+
}
|
|
37584
|
+
log(`[${DAEMON_NAME}] starting as a successor to a superseded daemon (port ${daemon.port})`);
|
|
37419
37585
|
} else {
|
|
37420
37586
|
const port = resolveDaemonPort(options.port);
|
|
37421
37587
|
try {
|
|
37422
|
-
daemon = await createDaemon({
|
|
37588
|
+
daemon = await createDaemon({ ...daemonOptions, port });
|
|
37423
37589
|
} catch (error51) {
|
|
37424
37590
|
if (!(error51 instanceof DaemonPortInUseError)) throw error51;
|
|
37425
37591
|
if (await ownDaemonAlreadyRunning()) {
|
|
37426
37592
|
log(`[${DAEMON_NAME}] already running (port ${port}); nothing to do`);
|
|
37427
37593
|
return "already-running";
|
|
37428
37594
|
}
|
|
37429
|
-
log(`[${DAEMON_NAME}]
|
|
37430
|
-
daemon = await createDaemon({
|
|
37595
|
+
log(`[${DAEMON_NAME}] ${describePortHolder(port)}; falling back to an ephemeral port`);
|
|
37596
|
+
daemon = await createDaemon({ ...daemonOptions, port: 0 });
|
|
37431
37597
|
}
|
|
37432
37598
|
}
|
|
37433
37599
|
writeDaemonInfo({
|
|
@@ -37445,7 +37611,7 @@ async function runDaemon(options = {}) {
|
|
|
37445
37611
|
runner,
|
|
37446
37612
|
ownPid: process.pid,
|
|
37447
37613
|
idleTtlMs: envInt(DAEMON_IDLE_TTL_ENV, DAEMON_IDLE_TTL_MS),
|
|
37448
|
-
sessionTtlMs
|
|
37614
|
+
sessionTtlMs,
|
|
37449
37615
|
log
|
|
37450
37616
|
});
|
|
37451
37617
|
log(
|
|
@@ -37459,8 +37625,9 @@ var DAEMON_USAGE = `Usage: daemon <command>
|
|
|
37459
37625
|
|
|
37460
37626
|
Commands:
|
|
37461
37627
|
start Start the daemon in the background (no-op when already running)
|
|
37462
|
-
stop
|
|
37463
|
-
|
|
37628
|
+
stop [--all] Stop this env's daemon (SIGTERM, waits for exit); --all stops every daemon
|
|
37629
|
+
on this machine, including draining (superseded) and legacy ones
|
|
37630
|
+
status Show every daemon: pid, port, version, uptime, sessions, active runs
|
|
37464
37631
|
url Print the MCP endpoint URL and client registration snippets
|
|
37465
37632
|
run Run the daemon in the foreground (logs to stderr)
|
|
37466
37633
|
logs [-n LINES] Print the tail of the daemon log
|
|
@@ -37478,9 +37645,53 @@ function formatUrlSnippets(url2) {
|
|
|
37478
37645
|
"",
|
|
37479
37646
|
"One registration serves every project: each workflow run names its project via the",
|
|
37480
37647
|
"required `projectDir` tool argument (inspect/await/stop locate a runId automatically).",
|
|
37481
|
-
"Stdio clients need no registration changes: the default stdio command proxies to this daemon automatically."
|
|
37648
|
+
"Stdio clients need no registration changes: the default stdio command proxies to this daemon automatically.",
|
|
37649
|
+
"Note: a direct HTTP registration pins this daemon's port; after a version upgrade the current",
|
|
37650
|
+
"daemon may listen elsewhere \u2014 re-run `daemon url`. The stdio command follows upgrades automatically."
|
|
37482
37651
|
].join("\n");
|
|
37483
37652
|
}
|
|
37653
|
+
async function probeAll() {
|
|
37654
|
+
const instances = listDaemonInstances();
|
|
37655
|
+
return Promise.all(
|
|
37656
|
+
instances.map(async (instance) => {
|
|
37657
|
+
const health = await probeHealthz(instance.info.port);
|
|
37658
|
+
return { ...instance, health: health !== void 0 && health.pid === instance.info.pid ? health : void 0 };
|
|
37659
|
+
})
|
|
37660
|
+
);
|
|
37661
|
+
}
|
|
37662
|
+
function formatInstance(instance, currentPid) {
|
|
37663
|
+
const { info, health } = instance;
|
|
37664
|
+
const role = instance.legacy ? "legacy (pre-family daemon; stop it with `daemon stop --all`)" : info.pid === currentPid ? "current for this env" : health?.lameDuck ? "draining (superseded by a newer daemon; admits no new sessions)" : "other env family";
|
|
37665
|
+
const lines = [
|
|
37666
|
+
`${DAEMON_NAME} v${health?.version ?? info.version}`,
|
|
37667
|
+
` pid: ${info.pid}`,
|
|
37668
|
+
` url: ${info.url}`,
|
|
37669
|
+
` role: ${role}`
|
|
37670
|
+
];
|
|
37671
|
+
if (health === void 0) {
|
|
37672
|
+
lines.push(" health: not responding (pid alive, /healthz unreachable)");
|
|
37673
|
+
return lines;
|
|
37674
|
+
}
|
|
37675
|
+
const uptimeMs = Date.now() - Date.parse(health.startedAt);
|
|
37676
|
+
lines.push(
|
|
37677
|
+
` uptime: ${Math.round(uptimeMs / 1e3)}s`,
|
|
37678
|
+
` sessions: ${health.sessions}`,
|
|
37679
|
+
` active runs: ${health.activeRuns}`,
|
|
37680
|
+
...health.inflightRequests !== void 0 ? [` in flight: ${health.inflightRequests} request(s)`] : [],
|
|
37681
|
+
...health.projects.map((p2) => ` ${p2.projectDir}: ${p2.activeRuns} active run(s)`)
|
|
37682
|
+
);
|
|
37683
|
+
return lines;
|
|
37684
|
+
}
|
|
37685
|
+
async function stopInstance(instance, timeoutMs) {
|
|
37686
|
+
const stopped = await stopDaemon(instance.info.pid, timeoutMs);
|
|
37687
|
+
if (stopped) {
|
|
37688
|
+
if (!instance.legacy) clearDaemonInfo(instance.info.pid);
|
|
37689
|
+
console.log(`${DAEMON_NAME} (pid ${instance.info.pid}, v${instance.info.version}) stopped`);
|
|
37690
|
+
} else {
|
|
37691
|
+
console.error(`${DAEMON_NAME} (pid ${instance.info.pid}) did not exit within ${Math.round(timeoutMs / 1e3)}s`);
|
|
37692
|
+
}
|
|
37693
|
+
return stopped;
|
|
37694
|
+
}
|
|
37484
37695
|
async function runDaemonCommand(args, options) {
|
|
37485
37696
|
const [command, ...rest] = args;
|
|
37486
37697
|
switch (command) {
|
|
@@ -37498,41 +37709,44 @@ async function runDaemonCommand(args, options) {
|
|
|
37498
37709
|
return 0;
|
|
37499
37710
|
}
|
|
37500
37711
|
case "stop": {
|
|
37712
|
+
if (rest.includes("--all")) {
|
|
37713
|
+
const instances = listDaemonInstances();
|
|
37714
|
+
if (instances.length === 0) {
|
|
37715
|
+
console.log(`${DAEMON_NAME} is not running`);
|
|
37716
|
+
return 0;
|
|
37717
|
+
}
|
|
37718
|
+
const results = await Promise.all(instances.map((instance) => stopInstance(instance, 7e3)));
|
|
37719
|
+
return results.every(Boolean) ? 0 : 1;
|
|
37720
|
+
}
|
|
37501
37721
|
const info = readDaemonInfo();
|
|
37502
37722
|
if (info === void 0 || !pidIsAlive(info.pid)) {
|
|
37503
37723
|
if (info !== void 0) clearDaemonInfo(info.pid);
|
|
37504
|
-
|
|
37724
|
+
const others = listDaemonInstances();
|
|
37725
|
+
console.log(
|
|
37726
|
+
`${DAEMON_NAME} is not running for this env` + (others.length > 0 ? ` (${others.length} other daemon(s) alive \u2014 see \`daemon status\`, stop with \`daemon stop --all\`)` : "")
|
|
37727
|
+
);
|
|
37505
37728
|
return 0;
|
|
37506
37729
|
}
|
|
37507
|
-
const stopped = await
|
|
37508
|
-
|
|
37509
|
-
console.error(`${DAEMON_NAME} (pid ${info.pid}) did not exit within 7s`);
|
|
37510
|
-
return 1;
|
|
37511
|
-
}
|
|
37512
|
-
console.log(`${DAEMON_NAME} (pid ${info.pid}) stopped`);
|
|
37513
|
-
return 0;
|
|
37730
|
+
const stopped = await stopInstance({ info, legacy: false }, 7e3);
|
|
37731
|
+
return stopped ? 0 : 1;
|
|
37514
37732
|
}
|
|
37515
37733
|
case "status": {
|
|
37516
|
-
const
|
|
37517
|
-
const
|
|
37518
|
-
|
|
37519
|
-
|
|
37734
|
+
const current = readDaemonInfo();
|
|
37735
|
+
const currentPid = current !== void 0 && pidIsAlive(current.pid) ? current.pid : void 0;
|
|
37736
|
+
const instances = await probeAll();
|
|
37737
|
+
if (instances.length === 0) {
|
|
37738
|
+
console.log(
|
|
37739
|
+
`${DAEMON_NAME}: not running (client v${SERVER_VERSION}, env family ${envFingerprint()}, default port ${resolveDaemonPort()})`
|
|
37740
|
+
);
|
|
37520
37741
|
return 1;
|
|
37521
37742
|
}
|
|
37522
|
-
const
|
|
37523
|
-
console.log(
|
|
37524
|
-
|
|
37525
|
-
|
|
37526
|
-
|
|
37527
|
-
|
|
37528
|
-
|
|
37529
|
-
` sessions: ${health.sessions}`,
|
|
37530
|
-
` active runs: ${health.activeRuns}`,
|
|
37531
|
-
...health.lameDuck ? [" lame duck: yes (superseded by a newer daemon \u2014 draining, admits no new sessions)"] : [],
|
|
37532
|
-
...health.projects.map((p2) => ` ${p2.projectDir}: ${p2.activeRuns} active run(s)`)
|
|
37533
|
-
].join("\n")
|
|
37534
|
-
);
|
|
37535
|
-
return 0;
|
|
37743
|
+
const blocks = instances.sort((a, b) => a.info.pid === currentPid ? -1 : b.info.pid === currentPid ? 1 : 0).map((instance) => formatInstance(instance, currentPid).join("\n"));
|
|
37744
|
+
console.log(blocks.join("\n\n"));
|
|
37745
|
+
if (currentPid === void 0) {
|
|
37746
|
+
console.log(`
|
|
37747
|
+
(no current daemon for this env \u2014 client v${SERVER_VERSION}, env family ${envFingerprint()})`);
|
|
37748
|
+
}
|
|
37749
|
+
return currentPid === void 0 ? 1 : 0;
|
|
37536
37750
|
}
|
|
37537
37751
|
case "url": {
|
|
37538
37752
|
const info = readDaemonInfo();
|
|
@@ -39131,15 +39345,26 @@ var StreamableHTTPClientTransport = class {
|
|
|
39131
39345
|
};
|
|
39132
39346
|
|
|
39133
39347
|
// ../mcp-server/src/shim/shim.ts
|
|
39348
|
+
var RECOVERY_WINDOW_MS = 6e4;
|
|
39349
|
+
var RECOVERY_MAX_PER_WINDOW = 6;
|
|
39134
39350
|
function initializeResultProtocolVersion(message) {
|
|
39135
39351
|
if (!isJSONRPCResponse(message)) return void 0;
|
|
39136
39352
|
const version2 = message.result.protocolVersion;
|
|
39137
39353
|
return typeof version2 === "string" ? version2 : void 0;
|
|
39138
39354
|
}
|
|
39355
|
+
function isRecoverableError(error51) {
|
|
39356
|
+
if (error51 instanceof StreamableHTTPError) return error51.code === 404 || error51.code === 503;
|
|
39357
|
+
if (error51 instanceof TypeError) return true;
|
|
39358
|
+
if (error51 instanceof Error) {
|
|
39359
|
+
return /Maximum reconnection attempts|Failed to reconnect|Failed to open SSE stream/.test(error51.message);
|
|
39360
|
+
}
|
|
39361
|
+
return false;
|
|
39362
|
+
}
|
|
39139
39363
|
async function runShim(options) {
|
|
39140
39364
|
const log = (line) => console.error(line);
|
|
39141
39365
|
const info = await ensureDaemonRunning({ bundlePath: options.bundlePath, port: options.port, log });
|
|
39142
39366
|
let replBreakUrl = info.replBreakUrl;
|
|
39367
|
+
let exiting = false;
|
|
39143
39368
|
function fireOutOfBandBreak(projectDir) {
|
|
39144
39369
|
if (typeof projectDir !== "string" || replBreakUrl === void 0) return;
|
|
39145
39370
|
let key;
|
|
@@ -39166,14 +39391,56 @@ async function runShim(options) {
|
|
|
39166
39391
|
const queue = [];
|
|
39167
39392
|
const subscribedUris = /* @__PURE__ */ new Set();
|
|
39168
39393
|
const swallowedIds = /* @__PURE__ */ new Set();
|
|
39394
|
+
const pending = /* @__PURE__ */ new Map();
|
|
39395
|
+
const keyOf = (id) => `${typeof id}:${String(id)}`;
|
|
39396
|
+
const retired = /* @__PURE__ */ new WeakSet();
|
|
39397
|
+
const recoveryTimes = [];
|
|
39398
|
+
function recoveryAllowed(now = Date.now()) {
|
|
39399
|
+
while (recoveryTimes.length > 0 && now - recoveryTimes[0] > RECOVERY_WINDOW_MS) recoveryTimes.shift();
|
|
39400
|
+
return recoveryTimes.length < RECOVERY_MAX_PER_WINDOW;
|
|
39401
|
+
}
|
|
39169
39402
|
const makeHttpTransport = (url2) => {
|
|
39170
39403
|
const transport = new StreamableHTTPClientTransport(new URL(url2));
|
|
39171
|
-
transport.onmessage = onDaemonMessage;
|
|
39172
|
-
transport.onerror = (error51) =>
|
|
39404
|
+
transport.onmessage = (message) => onDaemonMessage(message, transport);
|
|
39405
|
+
transport.onerror = (error51) => onTransportError(transport, error51);
|
|
39173
39406
|
return transport;
|
|
39174
39407
|
};
|
|
39175
39408
|
let http2 = makeHttpTransport(info.url);
|
|
39176
|
-
function
|
|
39409
|
+
function failPendingOn(transport, reason) {
|
|
39410
|
+
let failed = 0;
|
|
39411
|
+
for (const [key, entry] of [...pending.entries()]) {
|
|
39412
|
+
if (entry.transport !== transport) continue;
|
|
39413
|
+
pending.delete(key);
|
|
39414
|
+
failed++;
|
|
39415
|
+
void stdio.send({
|
|
39416
|
+
jsonrpc: "2.0",
|
|
39417
|
+
id: entry.message.id,
|
|
39418
|
+
error: {
|
|
39419
|
+
code: -32603,
|
|
39420
|
+
message: `workflow daemon session lost before the response arrived (${reason}); the request may or may not have completed \u2014 inspect before retrying`
|
|
39421
|
+
}
|
|
39422
|
+
}).catch(() => void 0);
|
|
39423
|
+
}
|
|
39424
|
+
return failed;
|
|
39425
|
+
}
|
|
39426
|
+
function retireTransport(transport, reason) {
|
|
39427
|
+
retired.add(transport);
|
|
39428
|
+
void transport.close().catch(() => void 0);
|
|
39429
|
+
setImmediate(() => {
|
|
39430
|
+
const failed = failPendingOn(transport, reason);
|
|
39431
|
+
if (failed > 0) log(`[${DAEMON_NAME} shim] ${failed} in-flight request(s) failed with the lost session (${reason})`);
|
|
39432
|
+
});
|
|
39433
|
+
}
|
|
39434
|
+
function onTransportError(transport, error51) {
|
|
39435
|
+
if (retired.has(transport) || exiting) return;
|
|
39436
|
+
log(`[${DAEMON_NAME} shim] http transport error: ${String(error51)}`);
|
|
39437
|
+
if (isRecoverableError(error51)) void startReinitialize(`stream error: ${String(error51)}`);
|
|
39438
|
+
}
|
|
39439
|
+
function onDaemonMessage(message, transport) {
|
|
39440
|
+
if ((isJSONRPCResponse(message) || isJSONRPCError(message)) && message.id !== null && message.id !== void 0) {
|
|
39441
|
+
pending.delete(keyOf(message.id));
|
|
39442
|
+
}
|
|
39443
|
+
if (retired.has(transport)) return;
|
|
39177
39444
|
if (pendingReinitId !== void 0 && isJSONRPCResponse(message) && message.id === pendingReinitId) {
|
|
39178
39445
|
pendingReinitId = void 0;
|
|
39179
39446
|
const version2 = initializeResultProtocolVersion(message);
|
|
@@ -39193,7 +39460,7 @@ async function runShim(options) {
|
|
|
39193
39460
|
}).catch((error51) => failPump(`re-initialize handshake failed: ${String(error51)}`));
|
|
39194
39461
|
return;
|
|
39195
39462
|
}
|
|
39196
|
-
if (isJSONRPCResponse(message) && typeof message.id === "string" && swallowedIds.delete(message.id)) {
|
|
39463
|
+
if ((isJSONRPCResponse(message) || isJSONRPCError(message)) && typeof message.id === "string" && swallowedIds.delete(message.id)) {
|
|
39197
39464
|
return;
|
|
39198
39465
|
}
|
|
39199
39466
|
if (clientInitializeId !== void 0 && isJSONRPCResponse(message) && message.id === clientInitializeId) {
|
|
@@ -39211,15 +39478,21 @@ async function runShim(options) {
|
|
|
39211
39478
|
log(`[${DAEMON_NAME} shim] fatal: ${reason}`);
|
|
39212
39479
|
void shutdown(1);
|
|
39213
39480
|
}
|
|
39214
|
-
async function startReinitialize() {
|
|
39215
|
-
if (reinitializing) return;
|
|
39481
|
+
async function startReinitialize(reason) {
|
|
39482
|
+
if (reinitializing || exiting) return;
|
|
39483
|
+
if (!recoveryAllowed()) {
|
|
39484
|
+
failPump(`daemon session recovery is looping (${RECOVERY_MAX_PER_WINDOW} attempts within ${RECOVERY_WINDOW_MS}ms; last: ${reason})`);
|
|
39485
|
+
return;
|
|
39486
|
+
}
|
|
39487
|
+
recoveryTimes.push(Date.now());
|
|
39216
39488
|
reinitializing = true;
|
|
39217
39489
|
if (cachedInitialize === void 0) {
|
|
39218
39490
|
failPump("daemon session lost before the client ever initialized");
|
|
39219
39491
|
return;
|
|
39220
39492
|
}
|
|
39493
|
+
log(`[${DAEMON_NAME} shim] recovering the daemon session (${reason})`);
|
|
39221
39494
|
try {
|
|
39222
|
-
|
|
39495
|
+
retireTransport(http2, reason);
|
|
39223
39496
|
const fresh = await ensureDaemonRunning({ bundlePath: options.bundlePath, port: options.port, log });
|
|
39224
39497
|
replBreakUrl = fresh.replBreakUrl;
|
|
39225
39498
|
http2 = makeHttpTransport(fresh.url);
|
|
@@ -39228,28 +39501,29 @@ async function runShim(options) {
|
|
|
39228
39501
|
const reinit = { ...cachedInitialize, id: pendingReinitId };
|
|
39229
39502
|
await http2.send(reinit);
|
|
39230
39503
|
} catch (error51) {
|
|
39504
|
+
if (isRecoverableError(error51) && recoveryAllowed()) {
|
|
39505
|
+
reinitializing = false;
|
|
39506
|
+
pendingReinitId = void 0;
|
|
39507
|
+
setTimeout(() => void startReinitialize(`retry after: ${String(error51)}`), 250);
|
|
39508
|
+
return;
|
|
39509
|
+
}
|
|
39231
39510
|
failPump(`could not re-establish a daemon session: ${String(error51)}`);
|
|
39232
39511
|
}
|
|
39233
39512
|
}
|
|
39234
|
-
let recoveryStreak = 0;
|
|
39235
|
-
function isRecoverableSendError(error51) {
|
|
39236
|
-
if (error51 instanceof StreamableHTTPError && error51.code === 404) return true;
|
|
39237
|
-
return error51 instanceof TypeError;
|
|
39238
|
-
}
|
|
39239
|
-
let sendChain = Promise.resolve();
|
|
39240
39513
|
async function pumpSend(message) {
|
|
39241
39514
|
if (reinitializing) {
|
|
39242
39515
|
queue.push(message);
|
|
39243
39516
|
return;
|
|
39244
39517
|
}
|
|
39518
|
+
const transport = http2;
|
|
39519
|
+
if (isJSONRPCRequest(message)) pending.set(keyOf(message.id), { transport, message });
|
|
39245
39520
|
try {
|
|
39246
|
-
await
|
|
39247
|
-
recoveryStreak = 0;
|
|
39521
|
+
await transport.send(message);
|
|
39248
39522
|
} catch (error51) {
|
|
39249
|
-
if (
|
|
39250
|
-
|
|
39523
|
+
if (isJSONRPCRequest(message)) pending.delete(keyOf(message.id));
|
|
39524
|
+
if (isRecoverableError(error51)) {
|
|
39251
39525
|
queue.push(message);
|
|
39252
|
-
void startReinitialize();
|
|
39526
|
+
void startReinitialize(`send failed: ${String(error51)}`);
|
|
39253
39527
|
return;
|
|
39254
39528
|
}
|
|
39255
39529
|
log(`[${DAEMON_NAME} shim] send failed: ${String(error51)}`);
|
|
@@ -39262,6 +39536,7 @@ async function runShim(options) {
|
|
|
39262
39536
|
}
|
|
39263
39537
|
}
|
|
39264
39538
|
}
|
|
39539
|
+
let sendChain = Promise.resolve();
|
|
39265
39540
|
stdio.onmessage = (message) => {
|
|
39266
39541
|
if (isJSONRPCRequest(message)) {
|
|
39267
39542
|
if (message.method === "initialize") {
|
|
@@ -39285,7 +39560,6 @@ async function runShim(options) {
|
|
|
39285
39560
|
}
|
|
39286
39561
|
sendChain = sendChain.then(() => pumpSend(message)).catch(() => void 0);
|
|
39287
39562
|
};
|
|
39288
|
-
let exiting = false;
|
|
39289
39563
|
async function shutdown(code) {
|
|
39290
39564
|
if (exiting) return;
|
|
39291
39565
|
exiting = true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automatalabs/workflows",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.50.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22"
|
|
@@ -31,16 +31,16 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"typebox": "1.3.2",
|
|
34
|
-
"@automatalabs/repl-engine": "0.3.
|
|
35
|
-
"@automatalabs/shared-types": "0.
|
|
36
|
-
"@automatalabs/workflow-engine": "0.36.
|
|
37
|
-
"@automatalabs/acp-agents": "0.
|
|
34
|
+
"@automatalabs/repl-engine": "0.3.4",
|
|
35
|
+
"@automatalabs/shared-types": "0.31.0",
|
|
36
|
+
"@automatalabs/workflow-engine": "0.36.1",
|
|
37
|
+
"@automatalabs/acp-agents": "0.38.1"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"esbuild": "^0.28.1"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
|
-
"build": "node ../../scripts/ensure-run-monitor-html.mjs && tsc -b &&
|
|
43
|
+
"build": "node ../../scripts/ensure-run-monitor-html.mjs && tsc -b && node scripts/bundle-mcp-server.mjs && node ../../scripts/check-workflows-bundle-deps.mjs",
|
|
44
44
|
"typecheck": "tsc -p tsconfig.test.json --noEmit",
|
|
45
45
|
"test": "tsx --test \"test/**/*.test.ts\""
|
|
46
46
|
}
|