appduct 0.10.0 → 0.11.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 +122 -52
- package/dist/artifact-inspect.d.ts +0 -1
- package/dist/bin.d.ts +0 -1
- package/dist/bin.js +1250 -2
- package/dist/cli/command-options.d.ts +8 -1
- package/dist/cli/create-cli.d.ts +0 -1
- package/dist/cli/dispatch.d.ts +10 -1
- package/dist/cli/envelope.d.ts +19 -0
- package/dist/cli/global-flags.d.ts +30 -0
- package/dist/cli/open-target.d.ts +25 -8
- package/dist/cli/result-types.d.ts +31 -5
- package/dist/cli/router.d.ts +78 -0
- package/dist/cli/routes/daemon/index.d.ts +9 -0
- package/dist/cli/routes/daemon/index.js +848 -0
- package/dist/cli/routes/daemon/run.d.ts +3 -0
- package/dist/cli/routes/daemon/run.js +3246 -0
- package/dist/cli/routes/daemon/start.d.ts +3 -0
- package/dist/cli/routes/daemon/start.js +1677 -0
- package/dist/cli/routes/daemon/status.d.ts +4 -0
- package/dist/cli/routes/daemon/status.js +1685 -0
- package/dist/cli/routes/daemon/stop.d.ts +4 -0
- package/dist/cli/routes/daemon/stop.js +1655 -0
- package/dist/cli/routes/doctor.d.ts +3 -0
- package/dist/cli/routes/doctor.js +1075 -0
- package/dist/cli/routes/events.d.ts +3 -0
- package/dist/cli/routes/events.js +1915 -0
- package/dist/cli/routes/init.d.ts +3 -0
- package/dist/cli/routes/init.js +1486 -0
- package/dist/cli/routes/invoke.d.ts +3 -0
- package/dist/cli/routes/invoke.js +1893 -0
- package/dist/cli/routes/keygen.d.ts +3 -0
- package/dist/cli/routes/keygen.js +928 -0
- package/dist/cli/routes/link.d.ts +3 -0
- package/dist/cli/routes/link.js +2714 -0
- package/dist/cli/routes/ls.d.ts +3 -0
- package/dist/cli/routes/ls.js +1668 -0
- package/dist/cli/routes/mcp.d.ts +5 -0
- package/dist/cli/routes/mcp.js +3929 -0
- package/dist/cli/routes/revoke.d.ts +3 -0
- package/dist/cli/routes/revoke.js +1684 -0
- package/dist/cli/routes/tools.d.ts +3 -0
- package/dist/cli/routes/tools.js +1860 -0
- package/dist/cli/runner.d.ts +3 -11
- package/dist/cli/types.d.ts +9 -6
- package/dist/cli/version-guard.d.ts +20 -0
- package/dist/cli.d.ts +0 -1
- package/dist/client/app-client.d.ts +4 -4
- package/dist/client/bootstrap.d.ts +4 -4
- package/dist/client/connect.d.ts +0 -1
- package/dist/client/errors.d.ts +0 -1
- package/dist/client/index.d.ts +1 -2
- package/dist/client/index.js +2389 -16
- package/dist/commands/daemon/context.d.ts +14 -0
- package/dist/commands/daemon/run.d.ts +11 -0
- package/dist/commands/daemon/start.d.ts +5 -0
- package/dist/commands/daemon/status.d.ts +5 -0
- package/dist/commands/daemon/stop.d.ts +5 -0
- package/dist/commands/doctor.d.ts +0 -1
- package/dist/commands/events.d.ts +0 -1
- package/dist/commands/init.d.ts +17 -4
- package/dist/commands/invoke.d.ts +0 -1
- package/dist/commands/keygen.d.ts +0 -1
- package/dist/commands/link.d.ts +1 -2
- package/dist/commands/ls.d.ts +0 -1
- package/dist/commands/mcp.d.ts +2 -4
- package/dist/commands/revoke.d.ts +0 -1
- package/dist/commands/tools.d.ts +19 -3
- package/dist/daemon/address.d.ts +0 -1
- package/dist/daemon/audit.d.ts +6 -11
- package/dist/daemon/calls.d.ts +0 -1
- package/dist/daemon/config.d.ts +13 -16
- package/dist/daemon/daemon.d.ts +0 -1
- package/dist/daemon/event-bus.d.ts +0 -1
- package/dist/daemon/links.d.ts +0 -1
- package/dist/daemon/listener.d.ts +0 -1
- package/dist/daemon/log-rotation.d.ts +0 -1
- package/dist/daemon/pidfile.d.ts +14 -8
- package/dist/daemon/policy.d.ts +0 -1
- package/dist/daemon/registry.d.ts +0 -1
- package/dist/daemon/rpc-errors.d.ts +16 -0
- package/dist/daemon/rpc-server.d.ts +0 -11
- package/dist/daemon/sessions.d.ts +0 -1
- package/dist/daemon/socket-probe.d.ts +0 -1
- package/dist/daemon/state-dir.d.ts +0 -1
- package/dist/daemon/timers.d.ts +0 -1
- package/dist/daemon/tls.d.ts +0 -1
- package/dist/errors.d.ts +0 -1
- package/dist/host-certificate.d.ts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1307 -3
- package/dist/key-material.d.ts +0 -1
- package/dist/link.d.ts +8 -7
- package/dist/mcp/app-tools.d.ts +153 -0
- package/dist/mcp/connect-tool.d.ts +14 -8
- package/dist/mcp/daemon-tools.d.ts +2 -11
- package/dist/mcp/events-tool.d.ts +0 -1
- package/dist/mcp/server.d.ts +33 -14
- package/dist/native-scheme.d.ts +0 -1
- package/dist/output.d.ts +8 -11
- package/dist/package-root.d.ts +11 -0
- package/dist/package-version.d.ts +0 -1
- package/dist/qr-terminal.d.ts +0 -1
- package/dist/rpc/client.d.ts +3 -3
- package/dist/scheme.d.ts +60 -2
- package/dist/spki-pin.d.ts +0 -1
- package/package.json +6 -3
- package/dist/artifact-inspect.d.ts.map +0 -1
- package/dist/artifact-inspect.js +0 -334
- package/dist/bin.d.ts.map +0 -1
- package/dist/cli/command-options.d.ts.map +0 -1
- package/dist/cli/command-options.js +0 -95
- package/dist/cli/create-cli.d.ts.map +0 -1
- package/dist/cli/create-cli.js +0 -56
- package/dist/cli/dispatch.d.ts.map +0 -1
- package/dist/cli/dispatch.js +0 -275
- package/dist/cli/open-target.d.ts.map +0 -1
- package/dist/cli/open-target.js +0 -438
- package/dist/cli/result-types.d.ts.map +0 -1
- package/dist/cli/result-types.js +0 -6
- package/dist/cli/runner.d.ts.map +0 -1
- package/dist/cli/runner.js +0 -111
- package/dist/cli/types.d.ts.map +0 -1
- package/dist/cli/types.js +0 -10
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -2
- package/dist/client/app-client.d.ts.map +0 -1
- package/dist/client/app-client.js +0 -223
- package/dist/client/bootstrap.d.ts.map +0 -1
- package/dist/client/bootstrap.js +0 -108
- package/dist/client/connect.d.ts.map +0 -1
- package/dist/client/connect.js +0 -38
- package/dist/client/errors.d.ts.map +0 -1
- package/dist/client/errors.js +0 -40
- package/dist/client/index.d.ts.map +0 -1
- package/dist/commands/daemon.d.ts +0 -22
- package/dist/commands/daemon.d.ts.map +0 -1
- package/dist/commands/daemon.js +0 -128
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js +0 -42
- package/dist/commands/events.d.ts.map +0 -1
- package/dist/commands/events.js +0 -76
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js +0 -231
- package/dist/commands/invoke.d.ts.map +0 -1
- package/dist/commands/invoke.js +0 -54
- package/dist/commands/keygen.d.ts.map +0 -1
- package/dist/commands/keygen.js +0 -46
- package/dist/commands/link.d.ts.map +0 -1
- package/dist/commands/link.js +0 -43
- package/dist/commands/ls.d.ts.map +0 -1
- package/dist/commands/ls.js +0 -7
- package/dist/commands/mcp.d.ts.map +0 -1
- package/dist/commands/mcp.js +0 -98
- package/dist/commands/revoke.d.ts.map +0 -1
- package/dist/commands/revoke.js +0 -7
- package/dist/commands/tools.d.ts.map +0 -1
- package/dist/commands/tools.js +0 -52
- package/dist/daemon/address.d.ts.map +0 -1
- package/dist/daemon/address.js +0 -71
- package/dist/daemon/audit.d.ts.map +0 -1
- package/dist/daemon/audit.js +0 -237
- package/dist/daemon/calls.d.ts.map +0 -1
- package/dist/daemon/calls.js +0 -158
- package/dist/daemon/config.d.ts.map +0 -1
- package/dist/daemon/config.js +0 -170
- package/dist/daemon/daemon.d.ts.map +0 -1
- package/dist/daemon/daemon.js +0 -560
- package/dist/daemon/event-bus.d.ts.map +0 -1
- package/dist/daemon/event-bus.js +0 -111
- package/dist/daemon/links.d.ts.map +0 -1
- package/dist/daemon/links.js +0 -118
- package/dist/daemon/listener.d.ts.map +0 -1
- package/dist/daemon/listener.js +0 -132
- package/dist/daemon/log-rotation.d.ts.map +0 -1
- package/dist/daemon/log-rotation.js +0 -136
- package/dist/daemon/pidfile.d.ts.map +0 -1
- package/dist/daemon/pidfile.js +0 -90
- package/dist/daemon/policy.d.ts.map +0 -1
- package/dist/daemon/policy.js +0 -24
- package/dist/daemon/registry.d.ts.map +0 -1
- package/dist/daemon/registry.js +0 -31
- package/dist/daemon/rpc-server.d.ts.map +0 -1
- package/dist/daemon/rpc-server.js +0 -203
- package/dist/daemon/sessions.d.ts.map +0 -1
- package/dist/daemon/sessions.js +0 -429
- package/dist/daemon/socket-probe.d.ts.map +0 -1
- package/dist/daemon/socket-probe.js +0 -28
- package/dist/daemon/state-dir.d.ts.map +0 -1
- package/dist/daemon/state-dir.js +0 -43
- package/dist/daemon/timers.d.ts.map +0 -1
- package/dist/daemon/timers.js +0 -12
- package/dist/daemon/tls.d.ts.map +0 -1
- package/dist/daemon/tls.js +0 -79
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -162
- package/dist/host-certificate.d.ts.map +0 -1
- package/dist/host-certificate.js +0 -111
- package/dist/index.d.ts.map +0 -1
- package/dist/key-material.d.ts.map +0 -1
- package/dist/key-material.js +0 -42
- package/dist/link.d.ts.map +0 -1
- package/dist/link.js +0 -117
- package/dist/mcp/connect-tool.d.ts.map +0 -1
- package/dist/mcp/connect-tool.js +0 -396
- package/dist/mcp/daemon-tools.d.ts.map +0 -1
- package/dist/mcp/daemon-tools.js +0 -29
- package/dist/mcp/events-tool.d.ts.map +0 -1
- package/dist/mcp/events-tool.js +0 -322
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js +0 -538
- package/dist/mcp/tool-mapping.d.ts +0 -58
- package/dist/mcp/tool-mapping.d.ts.map +0 -1
- package/dist/mcp/tool-mapping.js +0 -143
- package/dist/mcp/tool-namespace.d.ts +0 -40
- package/dist/mcp/tool-namespace.d.ts.map +0 -1
- package/dist/mcp/tool-namespace.js +0 -65
- package/dist/native-scheme.d.ts.map +0 -1
- package/dist/native-scheme.js +0 -465
- package/dist/output.d.ts.map +0 -1
- package/dist/output.js +0 -342
- package/dist/package-version.d.ts.map +0 -1
- package/dist/package-version.js +0 -47
- package/dist/qr-terminal.d.ts.map +0 -1
- package/dist/qr-terminal.js +0 -45
- package/dist/rpc/client.d.ts.map +0 -1
- package/dist/rpc/client.js +0 -819
- package/dist/scheme.d.ts.map +0 -1
- package/dist/scheme.js +0 -321
- package/dist/spki-pin.d.ts.map +0 -1
- package/dist/spki-pin.js +0 -14
package/dist/daemon/daemon.js
DELETED
|
@@ -1,560 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Daemon composition root (ARCHITECTURE.md §4): state dir → config → pidfile → TLS → session
|
|
3
|
-
* engine → listener → RPC server. Implements `daemon.status`/`daemon.shutdown`, the session RPC
|
|
4
|
-
* surface (`link.create`, `sessions.list`, `sessions.describe`, `sessions.revoke`), and the
|
|
5
|
-
* invocation surface (`tools.list`, `tools.call`, `events.subscribe`), and policy + audit
|
|
6
|
-
* (ARCHITECTURE.md §12): every `tools.call` attempt is evaluated against `config.policy` and
|
|
7
|
-
* recorded to the audit log inline in the `tools.call` handler below.
|
|
8
|
-
*/
|
|
9
|
-
import { rm } from "node:fs/promises";
|
|
10
|
-
import { RPC_METHODS, EVENT_KINDS, } from "@appduct/shared";
|
|
11
|
-
import { getDaemonReportedVersion } from "../package-version.js";
|
|
12
|
-
import { detectAdvertisedAddress } from "./address.js";
|
|
13
|
-
import { argsSha256, createAuditLogger } from "./audit.js";
|
|
14
|
-
import { createCallsManager } from "./calls.js";
|
|
15
|
-
import { loadConfig } from "./config.js";
|
|
16
|
-
import { createEventBus } from "./event-bus.js";
|
|
17
|
-
import { startListener } from "./listener.js";
|
|
18
|
-
import { evaluate as evaluatePolicy } from "./policy.js";
|
|
19
|
-
import { acquirePidfile } from "./pidfile.js";
|
|
20
|
-
import { RpcApplicationError, startRpcServer } from "./rpc-server.js";
|
|
21
|
-
import { createSessionManager } from "./sessions.js";
|
|
22
|
-
import { ensureStateDir, getSocketPath, getStateDirPaths } from "./state-dir.js";
|
|
23
|
-
import { systemTimers } from "./timers.js";
|
|
24
|
-
import { createTlsManager, toAgentEndpoint } from "./tls.js";
|
|
25
|
-
/** Used to validate `events.subscribe`/`events.since`'s `kinds` filter. */
|
|
26
|
-
const KNOWN_EVENT_KINDS = new Set(EVENT_KINDS);
|
|
27
|
-
/**
|
|
28
|
-
* What this daemon reports as its version over `daemon.status` and in `daemon_started`. Read per
|
|
29
|
-
* call rather than at module load so `APPDUCT_DAEMON_VERSION_OVERRIDE` (issue #30's test seam)
|
|
30
|
-
* takes effect for an in-process daemon started by a test that set it after import.
|
|
31
|
-
*/
|
|
32
|
-
const packageVersion = () => getDaemonReportedVersion();
|
|
33
|
-
/** How often audit retention runs after the startup prune (ARCHITECTURE.md §3: "once a day"). */
|
|
34
|
-
export const AUDIT_PRUNE_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
35
|
-
const buildStatusResult = async (config, startedAt, tls, sessionManager, auditLogger, auditDir) => {
|
|
36
|
-
// The audit directory footprint is measured on demand rather than tracked incrementally: this
|
|
37
|
-
// handler runs at most once per `appduct daemon status`, and a stat per day file is cheaper
|
|
38
|
-
// and far harder to get wrong than a running total that must survive pruning and restarts.
|
|
39
|
-
const stats = await auditLogger.stats();
|
|
40
|
-
return {
|
|
41
|
-
version: packageVersion(),
|
|
42
|
-
pid: process.pid,
|
|
43
|
-
startedAt: startedAt.toISOString(),
|
|
44
|
-
wssPort: config.wssPort,
|
|
45
|
-
pinnedKeys: tls.pinnedKeys(),
|
|
46
|
-
sessions: sessionManager.list(),
|
|
47
|
-
pendingLinks: sessionManager.pendingLinkCount(),
|
|
48
|
-
policy: config.policy,
|
|
49
|
-
audit: {
|
|
50
|
-
path: auditDir,
|
|
51
|
-
failedWrites: auditLogger.failedWrites(),
|
|
52
|
-
failedPrunes: auditLogger.failedPrunes(),
|
|
53
|
-
retentionDays: config.auditRetentionDays,
|
|
54
|
-
files: stats.files,
|
|
55
|
-
bytes: stats.bytes,
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
|
-
};
|
|
59
|
-
const asSelectorParams = (params) => {
|
|
60
|
-
if (params === undefined || params === null) {
|
|
61
|
-
return {};
|
|
62
|
-
}
|
|
63
|
-
if (typeof params !== "object" || Array.isArray(params)) {
|
|
64
|
-
throw new RpcApplicationError("invalid_request", "Params must be an object.");
|
|
65
|
-
}
|
|
66
|
-
const selector = params.selector;
|
|
67
|
-
if (selector !== undefined && typeof selector !== "string") {
|
|
68
|
-
throw new RpcApplicationError("invalid_request", '"selector" must be a string.');
|
|
69
|
-
}
|
|
70
|
-
return { selector };
|
|
71
|
-
};
|
|
72
|
-
const asRecordParams = (params) => {
|
|
73
|
-
if (params === undefined || params === null) {
|
|
74
|
-
return {};
|
|
75
|
-
}
|
|
76
|
-
if (typeof params !== "object" || Array.isArray(params)) {
|
|
77
|
-
throw new RpcApplicationError("invalid_request", "Params must be an object.");
|
|
78
|
-
}
|
|
79
|
-
return params;
|
|
80
|
-
};
|
|
81
|
-
const asToolsCallParams = (params) => {
|
|
82
|
-
const record = asRecordParams(params);
|
|
83
|
-
const selector = record.selector;
|
|
84
|
-
if (selector !== undefined && typeof selector !== "string") {
|
|
85
|
-
throw new RpcApplicationError("invalid_request", '"selector" must be a string.');
|
|
86
|
-
}
|
|
87
|
-
if (typeof record.name !== "string" || record.name.length === 0) {
|
|
88
|
-
throw new RpcApplicationError("invalid_request", '"name" must be a non-empty string.');
|
|
89
|
-
}
|
|
90
|
-
const args = record.args;
|
|
91
|
-
if (typeof args !== "object" || args === null || Array.isArray(args)) {
|
|
92
|
-
throw new RpcApplicationError("invalid_request", '"args" must be a JSON object.');
|
|
93
|
-
}
|
|
94
|
-
const timeoutMs = record.timeoutMs;
|
|
95
|
-
if (timeoutMs !== undefined && (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs))) {
|
|
96
|
-
throw new RpcApplicationError("invalid_request", '"timeoutMs" must be a number.');
|
|
97
|
-
}
|
|
98
|
-
const caller = record.caller;
|
|
99
|
-
if (caller !== undefined && caller !== "cli" && caller !== "mcp" && caller !== "client") {
|
|
100
|
-
throw new RpcApplicationError("invalid_request", '"caller" must be "cli", "mcp", or "client".');
|
|
101
|
-
}
|
|
102
|
-
const consent = record.consent;
|
|
103
|
-
if (consent !== undefined && consent !== "client" && consent !== "elicitation") {
|
|
104
|
-
throw new RpcApplicationError("invalid_request", '"consent" must be "client" or "elicitation".');
|
|
105
|
-
}
|
|
106
|
-
return {
|
|
107
|
-
selector: selector,
|
|
108
|
-
name: record.name,
|
|
109
|
-
args: args,
|
|
110
|
-
timeoutMs: timeoutMs,
|
|
111
|
-
caller: caller,
|
|
112
|
-
consent: consent,
|
|
113
|
-
};
|
|
114
|
-
};
|
|
115
|
-
const asToolsCancelParams = (params) => {
|
|
116
|
-
const record = asRecordParams(params);
|
|
117
|
-
const selector = record.selector;
|
|
118
|
-
if (selector !== undefined && typeof selector !== "string") {
|
|
119
|
-
throw new RpcApplicationError("invalid_request", '"selector" must be a string.');
|
|
120
|
-
}
|
|
121
|
-
if (typeof record.callId !== "string" || record.callId.length === 0) {
|
|
122
|
-
throw new RpcApplicationError("invalid_request", '"callId" must be a non-empty string.');
|
|
123
|
-
}
|
|
124
|
-
const reason = record.reason;
|
|
125
|
-
if (reason !== undefined && typeof reason !== "string") {
|
|
126
|
-
throw new RpcApplicationError("invalid_request", '"reason" must be a string.');
|
|
127
|
-
}
|
|
128
|
-
return {
|
|
129
|
-
selector: selector,
|
|
130
|
-
callId: record.callId,
|
|
131
|
-
reason: reason,
|
|
132
|
-
};
|
|
133
|
-
};
|
|
134
|
-
const asEventsSubscribeParams = (params) => {
|
|
135
|
-
const record = asRecordParams(params);
|
|
136
|
-
const sessionSelector = record.sessionSelector;
|
|
137
|
-
if (sessionSelector !== undefined && typeof sessionSelector !== "string") {
|
|
138
|
-
throw new RpcApplicationError("invalid_request", '"sessionSelector" must be a string.');
|
|
139
|
-
}
|
|
140
|
-
const kindsRaw = record.kinds;
|
|
141
|
-
let kinds;
|
|
142
|
-
if (kindsRaw !== undefined) {
|
|
143
|
-
if (!Array.isArray(kindsRaw) || !kindsRaw.every((kind) => typeof kind === "string" && KNOWN_EVENT_KINDS.has(kind))) {
|
|
144
|
-
throw new RpcApplicationError("invalid_request", '"kinds" must be an array of known event kinds.');
|
|
145
|
-
}
|
|
146
|
-
kinds = kindsRaw;
|
|
147
|
-
}
|
|
148
|
-
return { sessionSelector: sessionSelector, kinds };
|
|
149
|
-
};
|
|
150
|
-
const asEventsSinceParams = (params) => {
|
|
151
|
-
const record = asRecordParams(params);
|
|
152
|
-
const selector = record.selector;
|
|
153
|
-
if (selector !== undefined && typeof selector !== "string") {
|
|
154
|
-
throw new RpcApplicationError("invalid_request", '"selector" must be a string.');
|
|
155
|
-
}
|
|
156
|
-
const since = record.since;
|
|
157
|
-
if (since !== undefined && (typeof since !== "number" || !Number.isInteger(since) || since < 0)) {
|
|
158
|
-
throw new RpcApplicationError("invalid_request", '"since" must be a non-negative integer.');
|
|
159
|
-
}
|
|
160
|
-
const kindsRaw = record.kinds;
|
|
161
|
-
let kinds;
|
|
162
|
-
if (kindsRaw !== undefined) {
|
|
163
|
-
if (!Array.isArray(kindsRaw) || !kindsRaw.every((kind) => typeof kind === "string" && KNOWN_EVENT_KINDS.has(kind))) {
|
|
164
|
-
throw new RpcApplicationError("invalid_request", '"kinds" must be an array of known event kinds.');
|
|
165
|
-
}
|
|
166
|
-
kinds = kindsRaw;
|
|
167
|
-
}
|
|
168
|
-
const limit = record.limit;
|
|
169
|
-
if (limit !== undefined && (typeof limit !== "number" || !Number.isInteger(limit) || limit <= 0)) {
|
|
170
|
-
throw new RpcApplicationError("invalid_request", '"limit" must be a positive integer.');
|
|
171
|
-
}
|
|
172
|
-
return {
|
|
173
|
-
selector: selector,
|
|
174
|
-
since: since,
|
|
175
|
-
kinds,
|
|
176
|
-
limit: limit,
|
|
177
|
-
};
|
|
178
|
-
};
|
|
179
|
-
const asLinkCreateParams = (params) => {
|
|
180
|
-
if (params === undefined || params === null) {
|
|
181
|
-
return {};
|
|
182
|
-
}
|
|
183
|
-
if (typeof params !== "object" || Array.isArray(params)) {
|
|
184
|
-
throw new RpcApplicationError("invalid_request", "Params must be an object.");
|
|
185
|
-
}
|
|
186
|
-
const record = params;
|
|
187
|
-
const ttlSeconds = record.ttlSeconds;
|
|
188
|
-
if (ttlSeconds !== undefined && (typeof ttlSeconds !== "number" || !Number.isInteger(ttlSeconds) || ttlSeconds <= 0)) {
|
|
189
|
-
throw new RpcApplicationError("invalid_request", '"ttlSeconds" must be a positive integer.');
|
|
190
|
-
}
|
|
191
|
-
const addressOverride = record.addressOverride;
|
|
192
|
-
if (addressOverride !== undefined && (typeof addressOverride !== "string" || addressOverride.length === 0)) {
|
|
193
|
-
throw new RpcApplicationError("invalid_request", '"addressOverride" must be a non-empty string.');
|
|
194
|
-
}
|
|
195
|
-
return { ttlSeconds, addressOverride: addressOverride };
|
|
196
|
-
};
|
|
197
|
-
export const startDaemon = async (options) => {
|
|
198
|
-
const clock = options.clock ?? { now: () => new Date() };
|
|
199
|
-
const timers = options.timers ?? systemTimers;
|
|
200
|
-
const paths = getStateDirPaths(options.stateDir);
|
|
201
|
-
await ensureStateDir(options.stateDir);
|
|
202
|
-
const config = await loadConfig(paths, { warn: options.warn });
|
|
203
|
-
const startedAt = clock.now();
|
|
204
|
-
// Created eagerly (before anything else can fail) so shutdown can always flush it, and so a
|
|
205
|
-
// startup failure before the RPC server exists still gets a chance to record what happened.
|
|
206
|
-
const auditLogger = createAuditLogger({
|
|
207
|
-
auditDir: paths.auditDir,
|
|
208
|
-
clock,
|
|
209
|
-
retentionDays: config.auditRetentionDays,
|
|
210
|
-
warn: options.warn,
|
|
211
|
-
});
|
|
212
|
-
let auditPruneInterval;
|
|
213
|
-
let pidfile;
|
|
214
|
-
let server;
|
|
215
|
-
let listener;
|
|
216
|
-
let sessionManager;
|
|
217
|
-
let callsManager;
|
|
218
|
-
let eventBus;
|
|
219
|
-
let shuttingDown = false;
|
|
220
|
-
let resolveExited;
|
|
221
|
-
const exited = new Promise((resolve) => {
|
|
222
|
-
resolveExited = resolve;
|
|
223
|
-
});
|
|
224
|
-
const shutdown = async () => {
|
|
225
|
-
if (shuttingDown) {
|
|
226
|
-
return exited;
|
|
227
|
-
}
|
|
228
|
-
shuttingDown = true;
|
|
229
|
-
try {
|
|
230
|
-
// Cleared first so a long teardown can't have the daily sweep fire into a half-torn-down
|
|
231
|
-
// daemon, and so nothing keeps the event loop (or a test runner) alive after `exited`.
|
|
232
|
-
if (auditPruneInterval !== undefined) {
|
|
233
|
-
timers.clearInterval(auditPruneInterval);
|
|
234
|
-
auditPruneInterval = undefined;
|
|
235
|
-
}
|
|
236
|
-
// Reject any calls still in flight before the sockets that would have answered them go away.
|
|
237
|
-
callsManager?.disposeAll();
|
|
238
|
-
// ARCHITECTURE.md §4: close all device sockets (1001) before tearing down the control plane.
|
|
239
|
-
sessionManager?.disposeAll(1001, "daemon_shutdown");
|
|
240
|
-
await listener?.close();
|
|
241
|
-
await server?.close();
|
|
242
|
-
await pidfile?.release();
|
|
243
|
-
await rm(getSocketPath(paths), { force: true });
|
|
244
|
-
// Flush the audit queue last: nothing else here writes audit records, but this makes sure a
|
|
245
|
-
// record enqueued by the very last `tools.call` before shutdown actually lands on disk.
|
|
246
|
-
await auditLogger.flush();
|
|
247
|
-
}
|
|
248
|
-
finally {
|
|
249
|
-
resolveExited();
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
try {
|
|
253
|
-
pidfile = await acquirePidfile(paths.pidFilePath, {
|
|
254
|
-
onStaleTakeover: async () => {
|
|
255
|
-
await rm(getSocketPath(paths), { force: true });
|
|
256
|
-
},
|
|
257
|
-
});
|
|
258
|
-
eventBus = createEventBus({ clock, bufferSize: config.eventBufferSize });
|
|
259
|
-
const activeEventBus = eventBus;
|
|
260
|
-
const detectAddress = options.detectAddress ??
|
|
261
|
-
(() => detectAdvertisedAddress({ override: config.advertisedIp }));
|
|
262
|
-
const tls = await createTlsManager({ keyPath: config.keyPath, detectAddress, warn: options.warn });
|
|
263
|
-
sessionManager = createSessionManager({
|
|
264
|
-
graceSeconds: config.graceSeconds,
|
|
265
|
-
keepaliveIntervalSeconds: config.keepaliveIntervalSeconds,
|
|
266
|
-
linkTtlSeconds: config.linkTtlSeconds,
|
|
267
|
-
getEndpoint: () => toAgentEndpoint(tls.current().advertisedAddress, config.wssPort),
|
|
268
|
-
eventBus: activeEventBus,
|
|
269
|
-
clock,
|
|
270
|
-
onToolFrame: (message) => {
|
|
271
|
-
switch (message.type) {
|
|
272
|
-
case "tool_result":
|
|
273
|
-
callsManager?.handleToolResult(message);
|
|
274
|
-
return;
|
|
275
|
-
case "tool_error":
|
|
276
|
-
callsManager?.handleToolError(message);
|
|
277
|
-
return;
|
|
278
|
-
case "tool_call_progress":
|
|
279
|
-
callsManager?.handleToolCallProgress(message);
|
|
280
|
-
}
|
|
281
|
-
},
|
|
282
|
-
onAppEvent: (sessionId, alias, message) => {
|
|
283
|
-
activeEventBus.emit({
|
|
284
|
-
kind: "app_event",
|
|
285
|
-
sessionId,
|
|
286
|
-
alias,
|
|
287
|
-
data: { name: message.name, payload: message.payload, ts: message.ts },
|
|
288
|
-
});
|
|
289
|
-
},
|
|
290
|
-
});
|
|
291
|
-
const activeSessionManager = sessionManager;
|
|
292
|
-
callsManager = createCallsManager({
|
|
293
|
-
send: (sessionId, message) => activeSessionManager.sendToolCall(sessionId, message),
|
|
294
|
-
sendCancel: (sessionId, message) => activeSessionManager.sendToolCancel(sessionId, message),
|
|
295
|
-
eventBus: activeEventBus,
|
|
296
|
-
});
|
|
297
|
-
const activeCallsManager = callsManager;
|
|
298
|
-
listener = await startListener({
|
|
299
|
-
port: config.wssPort,
|
|
300
|
-
tls,
|
|
301
|
-
sessionManager,
|
|
302
|
-
});
|
|
303
|
-
const activeListener = listener;
|
|
304
|
-
// `events.subscribe` fan-out: one global listener pushes matching notifications to every RPC
|
|
305
|
-
// connection currently marked as a subscriber (state stashed by the `events.subscribe` handler
|
|
306
|
-
// below). `RpcServer.notify` itself guards against a slow/dead subscriber backing up the daemon.
|
|
307
|
-
activeEventBus.subscribe((event) => {
|
|
308
|
-
for (const connection of server?.connections() ?? []) {
|
|
309
|
-
const subscription = connection.state.eventSubscription;
|
|
310
|
-
if (!subscription) {
|
|
311
|
-
continue;
|
|
312
|
-
}
|
|
313
|
-
if (subscription.kinds && !subscription.kinds.has(event.kind)) {
|
|
314
|
-
continue;
|
|
315
|
-
}
|
|
316
|
-
if (subscription.sessionSelector !== undefined &&
|
|
317
|
-
event.sessionId !== subscription.sessionSelector &&
|
|
318
|
-
event.alias !== subscription.sessionSelector) {
|
|
319
|
-
continue;
|
|
320
|
-
}
|
|
321
|
-
server?.notify(connection, event);
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
server = await startRpcServer({
|
|
325
|
-
socketPath: getSocketPath(paths),
|
|
326
|
-
dispatch: {
|
|
327
|
-
[RPC_METHODS.daemonStatus]: async () => {
|
|
328
|
-
return buildStatusResult(config, startedAt, tls, activeSessionManager, auditLogger, paths.auditDir);
|
|
329
|
-
},
|
|
330
|
-
[RPC_METHODS.daemonShutdown]: (_params, context) => {
|
|
331
|
-
context.afterSend(() => {
|
|
332
|
-
void shutdown();
|
|
333
|
-
});
|
|
334
|
-
return { ok: true };
|
|
335
|
-
},
|
|
336
|
-
[RPC_METHODS.linkCreate]: async (params) => {
|
|
337
|
-
const { ttlSeconds, addressOverride } = asLinkCreateParams(params);
|
|
338
|
-
// Re-detect the advertised address on every mint (ARCHITECTURE.md §4/§8): a long-lived
|
|
339
|
-
// daemon that changed networks must not keep minting links with a stale address/SAN.
|
|
340
|
-
// `refresh` only re-mints the certificate when the address actually changed; applying the
|
|
341
|
-
// (possibly unchanged) secure context is a cheap no-op the rest of the time, but comparing
|
|
342
|
-
// material identity avoids even that when nothing changed.
|
|
343
|
-
const previousMaterial = tls.current();
|
|
344
|
-
const nextMaterial = await tls.refresh();
|
|
345
|
-
if (nextMaterial !== previousMaterial) {
|
|
346
|
-
activeListener.applyTls(nextMaterial);
|
|
347
|
-
}
|
|
348
|
-
// `tls.refresh()` just ran above, so `pinnedKeys()[0]` reflects the material this link's
|
|
349
|
-
// endpoint will actually serve (opt-in hardening dev-mode: the CLI composes this into the
|
|
350
|
-
// deep link's `pin` query param — see `LinkCreateResult.pin`).
|
|
351
|
-
return { ...activeSessionManager.createLink(ttlSeconds, addressOverride), pin: tls.pinnedKeys()[0] };
|
|
352
|
-
},
|
|
353
|
-
[RPC_METHODS.sessionsList]: () => {
|
|
354
|
-
return activeSessionManager.list();
|
|
355
|
-
},
|
|
356
|
-
[RPC_METHODS.sessionsDescribe]: (params) => {
|
|
357
|
-
const { selector } = asSelectorParams(params);
|
|
358
|
-
return activeSessionManager.describe(selector);
|
|
359
|
-
},
|
|
360
|
-
[RPC_METHODS.sessionsRevoke]: (params) => {
|
|
361
|
-
const { selector } = asSelectorParams(params);
|
|
362
|
-
activeSessionManager.revoke(selector);
|
|
363
|
-
return { ok: true };
|
|
364
|
-
},
|
|
365
|
-
[RPC_METHODS.toolsList]: (params) => {
|
|
366
|
-
const { selector } = asSelectorParams(params);
|
|
367
|
-
// ARCHITECTURE.md §5: tools.list works for ACTIVE and SUSPENDED sessions alike (the
|
|
368
|
-
// retained registry survives suspend); only tools.call requires ACTIVE.
|
|
369
|
-
const resolved = activeSessionManager.resolveForTools(selector);
|
|
370
|
-
// Each entry carries its effective policy decision (ARCHITECTURE.md §12) so the MCP
|
|
371
|
-
// server can emit `_meta["anthropic/requiresUserInteraction"]` for "prompt" tools
|
|
372
|
-
// without a second round trip (issue #14).
|
|
373
|
-
return resolved.registry.list().map((descriptor) => ({
|
|
374
|
-
...descriptor,
|
|
375
|
-
policy: evaluatePolicy(descriptor, { alias: resolved.alias }, config.policy),
|
|
376
|
-
}));
|
|
377
|
-
},
|
|
378
|
-
// This handler is the single seam every `tools.call` passes through: policy (ARCHITECTURE.md
|
|
379
|
-
// §12) is evaluated once the target tool descriptor is known, and one audit record is
|
|
380
|
-
// written for every attempt that reaches a resolved session, across ok/error/denied.
|
|
381
|
-
[RPC_METHODS.toolsCall]: async (params, context) => {
|
|
382
|
-
const { selector, name, args, timeoutMs, caller, consent } = asToolsCallParams(params);
|
|
383
|
-
const effectiveCaller = caller ?? "cli";
|
|
384
|
-
const resolved = activeSessionManager.resolveForTools(selector);
|
|
385
|
-
const auditStartedAt = clock.now().getTime();
|
|
386
|
-
const writeAudit = (outcome, errorType, grantedConsent, deniedReason) => {
|
|
387
|
-
auditLogger.record({
|
|
388
|
-
sessionId: resolved.sessionId,
|
|
389
|
-
alias: resolved.alias,
|
|
390
|
-
tool: name,
|
|
391
|
-
argsSha256: argsSha256(args),
|
|
392
|
-
outcome,
|
|
393
|
-
errorType,
|
|
394
|
-
deniedReason,
|
|
395
|
-
durationMs: clock.now().getTime() - auditStartedAt,
|
|
396
|
-
caller: effectiveCaller,
|
|
397
|
-
consent: grantedConsent,
|
|
398
|
-
});
|
|
399
|
-
};
|
|
400
|
-
if (resolved.state !== "active") {
|
|
401
|
-
const errorType = resolved.state === "suspended" ? "session_suspended" : "session_not_active";
|
|
402
|
-
writeAudit("error", errorType);
|
|
403
|
-
throw new RpcApplicationError(errorType, `Session "${resolved.alias}" is not active.`);
|
|
404
|
-
}
|
|
405
|
-
const tool = resolved.registry.get(name);
|
|
406
|
-
if (!tool) {
|
|
407
|
-
// Deliberately no frame is sent to the app for an unknown tool.
|
|
408
|
-
writeAudit("error", "tool_not_found");
|
|
409
|
-
throw new RpcApplicationError("tool_not_found", `Tool "${name}" is not registered.`);
|
|
410
|
-
}
|
|
411
|
-
const policyDecision = evaluatePolicy(tool, { alias: resolved.alias }, config.policy);
|
|
412
|
-
// "prompt" fails closed (ARCHITECTURE.md §12): it proceeds only when the caller carried
|
|
413
|
-
// `consent: "client"` (issue #14) or `consent: "elicitation"` (issue #10). Either value is
|
|
414
|
-
// trusted verbatim once present — the daemon does not and cannot re-derive whether an MCP
|
|
415
|
-
// client's `_meta` flag was actually honored or its elicitation reply actually came from a
|
|
416
|
-
// human, the same way it doesn't re-verify any other RPC param. `consent` is only ever
|
|
417
|
-
// justified when set by this codebase's own MCP server (mcp/server.ts), which sets
|
|
418
|
-
// `"client"` solely after confirming both that it emitted
|
|
419
|
-
// `_meta["anthropic/requiresUserInteraction"]` for this exact tool on this connection's
|
|
420
|
-
// most recent listing and that the connected client is known to enforce it, and sets
|
|
421
|
-
// `"elicitation"` solely after sending an `elicitation/create` request over this
|
|
422
|
-
// connection and receiving `action: "accept"` back. Any other local process with access to
|
|
423
|
-
// `daemon.sock` — including the CLI, or an agent with shell access, which is the typical
|
|
424
|
-
// setup this feature targets — could send either value directly; that is not a bypass of
|
|
425
|
-
// this feature so much as a restatement of this codebase's existing trust boundary
|
|
426
|
-
// (docs/SECURITY.md: anything that can reach the socket already has full daemon control).
|
|
427
|
-
// "prompt" guards against a compliant MCP client silently auto-approving on the caller's
|
|
428
|
-
// behalf, not against a hostile process on the operator's own machine.
|
|
429
|
-
const grantedConsent = policyDecision === "prompt" && (consent === "client" || consent === "elicitation") ? consent : undefined;
|
|
430
|
-
if (policyDecision === "deny" || (policyDecision === "prompt" && grantedConsent === undefined)) {
|
|
431
|
-
// Denied → no frame reaches the app, and the call never starts.
|
|
432
|
-
activeEventBus.emit({
|
|
433
|
-
kind: "tool_call_finished",
|
|
434
|
-
sessionId: resolved.sessionId,
|
|
435
|
-
alias: resolved.alias,
|
|
436
|
-
data: { name, outcome: "denied" },
|
|
437
|
-
});
|
|
438
|
-
if (policyDecision === "prompt") {
|
|
439
|
-
writeAudit("denied", undefined, undefined, "no_consent_channel");
|
|
440
|
-
throw new RpcApplicationError("policy_denied", `Policy requires prompt consent to call "${name}" on session "${resolved.alias}", but no consent channel confirmed it.`, -32000, {
|
|
441
|
-
reason: "no_consent_channel",
|
|
442
|
-
hint: `This caller did not confirm human consent for "${name}". An MCP client that declares the "elicitation" capability confirms it via an elicitation/create prompt, and Claude Code ≥ v2.1.199 confirms it via the requiresUserInteraction flag, automatically over MCP; every other caller (including the CLI) is denied by design. To change this tool's policy, edit "policy.tools[\"${resolved.alias}/${name}\"]" (or policy.default/policy.destructive) in ${paths.configPath}.`,
|
|
443
|
-
});
|
|
444
|
-
}
|
|
445
|
-
writeAudit("denied", undefined, undefined, "policy");
|
|
446
|
-
throw new RpcApplicationError("policy_denied", `Policy denies calling "${name}" on session "${resolved.alias}".`, -32000, { hint: `Edit "policy" in ${paths.configPath} (policy.default/policy.destructive/policy.tools) to change this.` });
|
|
447
|
-
}
|
|
448
|
-
const startedAt = clock.now().getTime();
|
|
449
|
-
const session = { sessionId: resolved.sessionId, alias: resolved.alias };
|
|
450
|
-
// `callId` is available synchronously (before the app has answered) precisely so it can
|
|
451
|
-
// be exposed to the RPC caller and stamped on every event in this call's lifecycle — the
|
|
452
|
-
// MCP server correlates its own in-flight `tools.call` against `tool_call_progress`
|
|
453
|
-
// notifications by this id, unambiguous under concurrent calls.
|
|
454
|
-
const { callId, result: callResult } = activeCallsManager.call(session, name, args,
|
|
455
|
-
// The caller's explicit `timeoutMs` wins; otherwise the tool's own declared deadline is
|
|
456
|
-
// the default, and only if it declares none does `clampTimeout` fall back to
|
|
457
|
-
// DEFAULT_CALL_TIMEOUT_MS (issue #25).
|
|
458
|
-
timeoutMs ?? tool.timeout_ms);
|
|
459
|
-
// If the connection that issued this tools.call drops while the call is still pending
|
|
460
|
-
// (CLI Ctrl-C, MCP client disconnect), tell the app to stop rather than leaving an
|
|
461
|
-
// orphaned handler running for a caller nobody is waiting on anymore. Unregistered once
|
|
462
|
-
// this call settles either way — otherwise a long-lived connection issuing many calls
|
|
463
|
-
// (e.g. the MCP server's persistent stream) leaks one closure per call for its lifetime.
|
|
464
|
-
const unregisterOnClose = context.onClose(() => {
|
|
465
|
-
activeCallsManager.cancel(resolved.sessionId, callId, "connection_closed");
|
|
466
|
-
});
|
|
467
|
-
activeEventBus.emit({
|
|
468
|
-
kind: "tool_call_started",
|
|
469
|
-
sessionId: resolved.sessionId,
|
|
470
|
-
alias: resolved.alias,
|
|
471
|
-
data: { name, callId },
|
|
472
|
-
});
|
|
473
|
-
try {
|
|
474
|
-
const result = await callResult;
|
|
475
|
-
activeEventBus.emit({
|
|
476
|
-
kind: "tool_call_finished",
|
|
477
|
-
sessionId: resolved.sessionId,
|
|
478
|
-
alias: resolved.alias,
|
|
479
|
-
data: { name, callId, durationMs: clock.now().getTime() - startedAt, outcome: "ok" },
|
|
480
|
-
});
|
|
481
|
-
writeAudit("ok", undefined, grantedConsent);
|
|
482
|
-
return { result, callId };
|
|
483
|
-
}
|
|
484
|
-
catch (error) {
|
|
485
|
-
const errorType = error instanceof RpcApplicationError ? error.type : "tool_execution_error";
|
|
486
|
-
const outcome = errorType === "tool_cancelled" ? "cancelled" : "error";
|
|
487
|
-
activeEventBus.emit({
|
|
488
|
-
kind: "tool_call_finished",
|
|
489
|
-
sessionId: resolved.sessionId,
|
|
490
|
-
alias: resolved.alias,
|
|
491
|
-
data: { name, callId, durationMs: clock.now().getTime() - startedAt, outcome, errorType },
|
|
492
|
-
});
|
|
493
|
-
writeAudit(outcome, errorType, grantedConsent);
|
|
494
|
-
throw error;
|
|
495
|
-
}
|
|
496
|
-
finally {
|
|
497
|
-
unregisterOnClose();
|
|
498
|
-
}
|
|
499
|
-
},
|
|
500
|
-
[RPC_METHODS.toolsCancel]: (params) => {
|
|
501
|
-
const { selector, callId, reason } = asToolsCancelParams(params);
|
|
502
|
-
const resolved = activeSessionManager.resolveForTools(selector);
|
|
503
|
-
const cancelled = activeCallsManager.cancel(resolved.sessionId, callId, reason ?? "client_cancelled");
|
|
504
|
-
return { cancelled };
|
|
505
|
-
},
|
|
506
|
-
[RPC_METHODS.eventsSubscribe]: (params, context) => {
|
|
507
|
-
const { sessionSelector, kinds } = asEventsSubscribeParams(params);
|
|
508
|
-
context.connection.state.eventSubscription = {
|
|
509
|
-
sessionSelector,
|
|
510
|
-
kinds: kinds ? new Set(kinds) : undefined,
|
|
511
|
-
};
|
|
512
|
-
return { ok: true };
|
|
513
|
-
},
|
|
514
|
-
[RPC_METHODS.eventsSince]: (params) => {
|
|
515
|
-
const { selector, since, kinds, limit } = asEventsSinceParams(params);
|
|
516
|
-
// Resolved the same way as every other selector-taking method (`sessions.describe`,
|
|
517
|
-
// `tools.list`): defaults to the sole active/suspended session, errors on ambiguity, and
|
|
518
|
-
// works for a suspended session too — a suspended app's already-retained events are still
|
|
519
|
-
// fair game to drain.
|
|
520
|
-
const resolved = activeSessionManager.describe(selector);
|
|
521
|
-
return activeEventBus.since(resolved.sessionId, { since, kinds, limit });
|
|
522
|
-
},
|
|
523
|
-
},
|
|
524
|
-
});
|
|
525
|
-
// ARCHITECTURE.md §3: audit retention runs once at startup and once a day thereafter. Both are
|
|
526
|
-
// fire-and-forget — `prune` never rejects, and a daemon must start (and keep running) whether
|
|
527
|
-
// or not it can delete an old day file. The interval is cleared in `shutdown` (and in the
|
|
528
|
-
// startup-failure path below) so it never outlives the daemon that scheduled it.
|
|
529
|
-
auditPruneInterval = timers.setInterval(() => {
|
|
530
|
-
void auditLogger.prune();
|
|
531
|
-
}, AUDIT_PRUNE_INTERVAL_MS);
|
|
532
|
-
void auditLogger.prune();
|
|
533
|
-
}
|
|
534
|
-
catch (error) {
|
|
535
|
-
// Never leave a half-acquired pidfile/listener/socket behind when startup fails partway through.
|
|
536
|
-
if (auditPruneInterval !== undefined) {
|
|
537
|
-
timers.clearInterval(auditPruneInterval);
|
|
538
|
-
auditPruneInterval = undefined;
|
|
539
|
-
}
|
|
540
|
-
callsManager?.disposeAll();
|
|
541
|
-
sessionManager?.disposeAll(1001, "daemon_startup_failed");
|
|
542
|
-
await listener?.close();
|
|
543
|
-
await pidfile?.release();
|
|
544
|
-
throw error;
|
|
545
|
-
}
|
|
546
|
-
// ARCHITECTURE.md §5 lists `daemon_started` among the real event kinds; emitted once startup has
|
|
547
|
-
// fully succeeded (pidfile/TLS/listener/RPC server all up) so a subscriber never sees it followed
|
|
548
|
-
// by a startup failure.
|
|
549
|
-
eventBus.emit({ kind: "daemon_started", data: { version: packageVersion(), pid: process.pid } });
|
|
550
|
-
return {
|
|
551
|
-
paths,
|
|
552
|
-
config,
|
|
553
|
-
startedAt,
|
|
554
|
-
server,
|
|
555
|
-
listener,
|
|
556
|
-
eventBus,
|
|
557
|
-
exited,
|
|
558
|
-
shutdown,
|
|
559
|
-
};
|
|
560
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/daemon/event-bus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,EAAE,IAAI,GAAG,KAAK,CAAC,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzG,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAYlE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACzC,SAAS,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,MAAM,IAAI,CAAC;IACtD;iGAC6F;IAC7F,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,gBAAgB,KAAK,sBAAsB,CAAC;IAC/E;;oGAEgG;IAChG,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,6FAA6F;IAC7F,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,UAAS,qBAA0B,KAAG,QAqGpE,CAAC"}
|