@aristanetworks/eos-mcp-server 0.8.0-beta → 0.9.0-beta
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/CHANGELOG.md +13 -0
- package/README.md +19 -42
- package/dist/cli.d.ts +1 -4
- package/dist/cli.js +4 -63
- package/dist/cli.js.map +1 -1
- package/dist/commands/probe.js +2 -1
- package/dist/commands/probe.js.map +1 -1
- package/dist/config/diagnostics.d.ts +15 -5
- package/dist/config/diagnostics.js +8 -3
- package/dist/config/diagnostics.js.map +1 -1
- package/dist/config/loadConfig.js +2 -5
- package/dist/config/loadConfig.js.map +1 -1
- package/dist/config/schema.d.ts +123 -15
- package/dist/config/schema.js +14 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/connection/eosDeviceReader.d.ts +6 -1
- package/dist/connection/eosDeviceReader.js +14 -3
- package/dist/connection/eosDeviceReader.js.map +1 -1
- package/dist/diagnostics/eapiRunner.js +7 -1
- package/dist/diagnostics/eapiRunner.js.map +1 -1
- package/dist/diagnostics/executor.d.ts +7 -4
- package/dist/diagnostics/executor.js +16 -14
- package/dist/diagnostics/executor.js.map +1 -1
- package/dist/diagnostics/types.d.ts +22 -6
- package/dist/eapi/client.js +5 -4
- package/dist/eapi/client.js.map +1 -1
- package/dist/eapi/types.d.ts +3 -0
- package/dist/eapi/types.js.map +1 -1
- package/dist/index.js +0 -10
- package/dist/index.js.map +1 -1
- package/dist/mcp/createServer.js +21 -21
- package/dist/mcp/createServer.js.map +1 -1
- package/dist/mcp/tools/ping.d.ts +2 -9
- package/dist/mcp/tools/ping.js +13 -26
- package/dist/mcp/tools/ping.js.map +1 -1
- package/dist/operations/eapiSlots.d.ts +68 -0
- package/dist/operations/eapiSlots.js +237 -0
- package/dist/operations/eapiSlots.js.map +1 -0
- package/dist/operations/readExecution.js +1 -1
- package/dist/operations/readExecution.js.map +1 -1
- package/dist/serverInfo/buildServerInfo.js +4 -1
- package/dist/serverInfo/buildServerInfo.js.map +1 -1
- package/dist/serverInfo/types.d.ts +3 -0
- package/docs/CHECKPOINT.md +3 -6
- package/docs/CODE_WALKTHROUGH.md +6 -11
- package/docs/DEMO_SKILLS_YOUTUBE.md +346 -0
- package/docs/DESIGN.md +4 -4
- package/docs/DIAGNOSTICS.md +26 -74
- package/docs/IMPLEMENTATION_PLAN.md +2 -2
- package/docs/adr/0002-fail-closed-diagnostic-reservations.md +2 -0
- package/docs/adr/0003-durable-diagnostic-ledger.md +2 -0
- package/docs/adr/0004-offline-operator-attested-release.md +2 -0
- package/docs/adr/0005-multi-destination-ping.md +5 -1
- package/docs/adr/0006-in-memory-timed-diagnostic-capacity.md +23 -0
- package/docs/adr/0007-per-device-diagnostic-concurrency.md +16 -0
- package/docs/adr/0008-read-only-tool-annotations.md +16 -0
- package/docs/adr/0009-shared-per-device-eapi-slots.md +40 -0
- package/docs/research/eos-diagnostic-lifecycle.md +2 -0
- package/docs/research/eos-linter-integration.md +70 -0
- package/package.json +1 -1
- package/dist/commands/inspectDiagnostics.d.ts +0 -3
- package/dist/commands/inspectDiagnostics.js +0 -35
- package/dist/commands/inspectDiagnostics.js.map +0 -1
- package/dist/commands/releaseDiagnostics.d.ts +0 -9
- package/dist/commands/releaseDiagnostics.js +0 -87
- package/dist/commands/releaseDiagnostics.js.map +0 -1
- package/dist/diagnostics/concurrency.d.ts +0 -33
- package/dist/diagnostics/concurrency.js +0 -157
- package/dist/diagnostics/concurrency.js.map +0 -1
- package/dist/diagnostics/journal.d.ts +0 -14
- package/dist/diagnostics/journal.js +0 -317
- package/dist/diagnostics/journal.js.map +0 -1
- package/dist/diagnostics/journalTypes.d.ts +0 -8
- package/dist/diagnostics/journalTypes.js +0 -2
- package/dist/diagnostics/journalTypes.js.map +0 -1
- package/dist/diagnostics/releaseEvidence.d.ts +0 -502
- package/dist/diagnostics/releaseEvidence.js +0 -115
- package/dist/diagnostics/releaseEvidence.js.map +0 -1
- package/dist/diagnostics/reservationSchema.d.ts +0 -49
- package/dist/diagnostics/reservationSchema.js +0 -18
- package/dist/diagnostics/reservationSchema.js.map +0 -1
- package/dist/diagnostics/statePath.d.ts +0 -4
- package/dist/diagnostics/statePath.js +0 -25
- package/dist/diagnostics/statePath.js.map +0 -1
- package/dist/utils/privateFile.d.ts +0 -3
- package/dist/utils/privateFile.js +0 -7
- package/dist/utils/privateFile.js.map +0 -1
- package/docs/examples/diagnostic-release-evidence.template.json +0 -26
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { AppError } from "../core/errors.js";
|
|
3
|
+
/** One instance per server process, shared by every eAPI request (ADR 0009). A slot is granted only
|
|
4
|
+
* while its device has room and, for a diagnostic, its device's diagnostic share and the server-wide
|
|
5
|
+
* diagnostic ceiling have room; waiters are served oldest first, skipping those that cannot run yet
|
|
6
|
+
* (ADR 0007). A read frees its slot when its request settles. A diagnostic slot with unknown remote
|
|
7
|
+
* completion stays held for the execution budget, then frees itself; a late confirmed response frees
|
|
8
|
+
* it sooner (ADR 0006).
|
|
9
|
+
*/
|
|
10
|
+
export class EapiSlots {
|
|
11
|
+
limits;
|
|
12
|
+
uncertainHoldMs;
|
|
13
|
+
/** Held diagnostic slots; an uncertain slot carries the timer that frees it. */
|
|
14
|
+
reservations = new Map();
|
|
15
|
+
readsHeldByDevice = new Map();
|
|
16
|
+
waiting = [];
|
|
17
|
+
closed = false;
|
|
18
|
+
constructor(limits, uncertainHoldMs) {
|
|
19
|
+
this.limits = limits;
|
|
20
|
+
this.uncertainHoldMs = uncertainHoldMs;
|
|
21
|
+
}
|
|
22
|
+
close() {
|
|
23
|
+
if (this.closed)
|
|
24
|
+
return;
|
|
25
|
+
this.closed = true;
|
|
26
|
+
for (const timer of this.reservations.values())
|
|
27
|
+
clearTimeout(timer);
|
|
28
|
+
const error = closedError();
|
|
29
|
+
for (const waiter of this.waiting.splice(0))
|
|
30
|
+
waiter.reject(error);
|
|
31
|
+
}
|
|
32
|
+
/** Top-level counts cover diagnostics; `devices` also shows each host's read slots. */
|
|
33
|
+
snapshot() {
|
|
34
|
+
const reservations = Array.from(this.reservations.keys(), (reservation) => ({ ...reservation }));
|
|
35
|
+
const uncertain = reservations.filter((reservation) => reservation.state === "uncertain").length;
|
|
36
|
+
const serverAvailable = this.closed ? 0 : Math.max(0, this.limits.diagnosticServerLimit - reservations.length);
|
|
37
|
+
const queuedDiagnostics = this.waiting.filter((waiter) => waiter.kind === "diagnostic").length;
|
|
38
|
+
return {
|
|
39
|
+
limit: this.limits.diagnosticServerLimit,
|
|
40
|
+
device_limit: this.limits.diagnosticDeviceLimit,
|
|
41
|
+
eapi_device_limit: this.limits.deviceLimit,
|
|
42
|
+
available_count: serverAvailable,
|
|
43
|
+
active_count: reservations.length - uncertain,
|
|
44
|
+
uncertain_count: uncertain,
|
|
45
|
+
queued_count: queuedDiagnostics,
|
|
46
|
+
devices: this.deviceBreakdown(reservations, serverAvailable),
|
|
47
|
+
reservations
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Per-host counts for every host holding or awaiting a slot, sorted by hostname. */
|
|
51
|
+
deviceBreakdown(reservations, serverAvailable) {
|
|
52
|
+
const devices = new Map();
|
|
53
|
+
const deviceEntry = (inventoryHostname) => {
|
|
54
|
+
let entry = devices.get(inventoryHostname);
|
|
55
|
+
if (entry === undefined) {
|
|
56
|
+
entry = {
|
|
57
|
+
inventory_hostname: inventoryHostname,
|
|
58
|
+
available_count: 0, active_count: 0, uncertain_count: 0, queued_count: 0,
|
|
59
|
+
read_active_count: 0, read_queued_count: 0
|
|
60
|
+
};
|
|
61
|
+
devices.set(inventoryHostname, entry);
|
|
62
|
+
}
|
|
63
|
+
return entry;
|
|
64
|
+
};
|
|
65
|
+
for (const reservation of reservations) {
|
|
66
|
+
const entry = deviceEntry(reservation.inventory_hostname);
|
|
67
|
+
if (reservation.state === "uncertain")
|
|
68
|
+
entry.uncertain_count += 1;
|
|
69
|
+
else
|
|
70
|
+
entry.active_count += 1;
|
|
71
|
+
}
|
|
72
|
+
for (const [inventoryHostname, readsHeld] of this.readsHeldByDevice)
|
|
73
|
+
deviceEntry(inventoryHostname).read_active_count = readsHeld;
|
|
74
|
+
for (const waiter of this.waiting) {
|
|
75
|
+
const entry = deviceEntry(waiter.inventoryHostname);
|
|
76
|
+
if (waiter.kind === "diagnostic")
|
|
77
|
+
entry.queued_count += 1;
|
|
78
|
+
else
|
|
79
|
+
entry.read_queued_count += 1;
|
|
80
|
+
}
|
|
81
|
+
for (const entry of devices.values()) {
|
|
82
|
+
entry.available_count = this.diagnosticHeadroom(entry.active_count + entry.uncertain_count, entry.read_active_count, serverAvailable);
|
|
83
|
+
}
|
|
84
|
+
return Array.from(devices.values()).sort((left, right) => left.inventory_hostname.localeCompare(right.inventory_hostname));
|
|
85
|
+
}
|
|
86
|
+
/** Waits for a read slot on the host; the returned function frees it. */
|
|
87
|
+
acquireRead(signal, inventoryHostname) {
|
|
88
|
+
return this.enqueue(signal, inventoryHostname, "read", () => this.reserveRead(inventoryHostname));
|
|
89
|
+
}
|
|
90
|
+
acquireDiagnostic(signal, intent) {
|
|
91
|
+
return this.enqueue(signal, intent.inventoryHostname, "diagnostic", () => this.reserveDiagnostic(intent));
|
|
92
|
+
}
|
|
93
|
+
enqueue(signal, inventoryHostname, kind, reserve) {
|
|
94
|
+
return new Promise((resolve, reject) => {
|
|
95
|
+
if (signal?.aborted === true) {
|
|
96
|
+
reject(abortedError());
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (this.closed) {
|
|
100
|
+
reject(closedError());
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const cancelled = () => {
|
|
104
|
+
const index = this.waiting.indexOf(waiter);
|
|
105
|
+
if (index >= 0)
|
|
106
|
+
this.waiting.splice(index, 1);
|
|
107
|
+
waiter.reject(abortedError());
|
|
108
|
+
};
|
|
109
|
+
const stopListening = () => signal?.removeEventListener("abort", cancelled);
|
|
110
|
+
const waiter = {
|
|
111
|
+
inventoryHostname,
|
|
112
|
+
kind,
|
|
113
|
+
reject: (error) => {
|
|
114
|
+
stopListening();
|
|
115
|
+
reject(error);
|
|
116
|
+
},
|
|
117
|
+
grant: () => {
|
|
118
|
+
stopListening();
|
|
119
|
+
resolve(reserve());
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
if (this.hasRoom(waiter)) {
|
|
123
|
+
waiter.grant();
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
this.waiting.push(waiter);
|
|
127
|
+
signal?.addEventListener("abort", cancelled, { once: true });
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
hasRoom(waiter) {
|
|
132
|
+
const diagnosticsHeld = this.diagnosticSlotsHeldBy(waiter.inventoryHostname);
|
|
133
|
+
const readsHeld = this.readsHeldByDevice.get(waiter.inventoryHostname) ?? 0;
|
|
134
|
+
if (waiter.kind === "read")
|
|
135
|
+
return diagnosticsHeld + readsHeld < this.limits.deviceLimit;
|
|
136
|
+
return this.diagnosticHeadroom(diagnosticsHeld, readsHeld, this.limits.diagnosticServerLimit - this.reservations.size) > 0;
|
|
137
|
+
}
|
|
138
|
+
/** Diagnostic slots a host could take now: the tightest of its diagnostic share, its shared device
|
|
139
|
+
* slots, and the server-wide diagnostic slots still free. Admission and the snapshot both use it.
|
|
140
|
+
*/
|
|
141
|
+
diagnosticHeadroom(diagnosticsHeld, readsHeld, serverAvailable) {
|
|
142
|
+
const diagnosticShareLeft = this.limits.diagnosticDeviceLimit - diagnosticsHeld;
|
|
143
|
+
const deviceSlotsLeft = this.limits.deviceLimit - diagnosticsHeld - readsHeld;
|
|
144
|
+
return Math.max(0, Math.min(diagnosticShareLeft, deviceSlotsLeft, serverAvailable));
|
|
145
|
+
}
|
|
146
|
+
/** Counted from the held reservations, which never exceed the server-wide diagnostic limit. */
|
|
147
|
+
diagnosticSlotsHeldBy(inventoryHostname) {
|
|
148
|
+
let held = 0;
|
|
149
|
+
for (const reservation of this.reservations.keys()) {
|
|
150
|
+
if (reservation.inventory_hostname === inventoryHostname)
|
|
151
|
+
held += 1;
|
|
152
|
+
}
|
|
153
|
+
return held;
|
|
154
|
+
}
|
|
155
|
+
reserveRead(inventoryHostname) {
|
|
156
|
+
this.adjustReadsHeld(inventoryHostname, 1);
|
|
157
|
+
let released = false;
|
|
158
|
+
return () => {
|
|
159
|
+
if (released)
|
|
160
|
+
return;
|
|
161
|
+
released = true;
|
|
162
|
+
this.adjustReadsHeld(inventoryHostname, -1);
|
|
163
|
+
this.grantWaiting();
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/** Keeps only hosts that hold reads, so the snapshot lists no idle hosts. */
|
|
167
|
+
adjustReadsHeld(inventoryHostname, change) {
|
|
168
|
+
const readsHeld = (this.readsHeldByDevice.get(inventoryHostname) ?? 0) + change;
|
|
169
|
+
if (readsHeld > 0)
|
|
170
|
+
this.readsHeldByDevice.set(inventoryHostname, readsHeld);
|
|
171
|
+
else
|
|
172
|
+
this.readsHeldByDevice.delete(inventoryHostname);
|
|
173
|
+
}
|
|
174
|
+
reserveDiagnostic(intent) {
|
|
175
|
+
const requestId = randomUUID();
|
|
176
|
+
const state = {
|
|
177
|
+
reservation_id: requestId,
|
|
178
|
+
inventory_hostname: intent.inventoryHostname,
|
|
179
|
+
diagnostic: intent.diagnostic,
|
|
180
|
+
state: "active",
|
|
181
|
+
reserved_at: new Date().toISOString()
|
|
182
|
+
};
|
|
183
|
+
this.reservations.set(state, undefined);
|
|
184
|
+
return {
|
|
185
|
+
requestId,
|
|
186
|
+
complete: () => this.freeDiagnostic(state),
|
|
187
|
+
markUncertain: (reasonCode) => this.markUncertain(state, reasonCode)
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
freeDiagnostic(state) {
|
|
191
|
+
if (!this.reservations.has(state))
|
|
192
|
+
return;
|
|
193
|
+
clearTimeout(this.reservations.get(state));
|
|
194
|
+
this.reservations.delete(state);
|
|
195
|
+
this.grantWaiting();
|
|
196
|
+
}
|
|
197
|
+
/** Grant the oldest waiters that can run now; a waiter that cannot run yet keeps its place. */
|
|
198
|
+
grantWaiting() {
|
|
199
|
+
let index = 0;
|
|
200
|
+
while (index < this.waiting.length) {
|
|
201
|
+
const waiter = this.waiting[index];
|
|
202
|
+
if (waiter !== undefined && this.hasRoom(waiter)) {
|
|
203
|
+
this.waiting.splice(index, 1);
|
|
204
|
+
waiter.grant();
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
index += 1;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
markUncertain(state, reasonCode) {
|
|
212
|
+
if (this.closed || !this.reservations.has(state) || state.state === "uncertain")
|
|
213
|
+
return;
|
|
214
|
+
const now = Date.now();
|
|
215
|
+
state.state = "uncertain";
|
|
216
|
+
state.uncertain_since = new Date(now).toISOString();
|
|
217
|
+
state.releases_at = new Date(now + this.uncertainHoldMs).toISOString();
|
|
218
|
+
state.reason_code = reasonCode;
|
|
219
|
+
// Unref so a held slot never keeps a stopping server alive.
|
|
220
|
+
this.reservations.set(state, setTimeout(() => this.freeDiagnostic(state), this.uncertainHoldMs).unref());
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/** Limits from config: top-level `deviceConcurrency` per device, `diagnostics.*` for the diagnostic share. */
|
|
224
|
+
export function eapiSlotLimits(config) {
|
|
225
|
+
return {
|
|
226
|
+
deviceLimit: config.deviceConcurrency,
|
|
227
|
+
diagnosticDeviceLimit: config.diagnostics.deviceConcurrency,
|
|
228
|
+
diagnosticServerLimit: config.diagnostics.maxConcurrentDiagnostics
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function closedError() {
|
|
232
|
+
return new AppError("diagnostic_server_stopping", "eAPI execution is shutting down");
|
|
233
|
+
}
|
|
234
|
+
function abortedError() {
|
|
235
|
+
return new AppError("operation_aborted", "Request was cancelled while waiting for device capacity");
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=eapiSlots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eapiSlots.js","sourceRoot":"","sources":["../../src/operations/eapiSlots.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ export async function executeReadOperation(model, config, options) {
|
|
|
4
4
|
const resolvedTarget = resolveInventoryTarget(model, { target: options.target });
|
|
5
5
|
enforceReadTargetLimit(config, resolvedTarget.resolvedHosts.length);
|
|
6
6
|
options.validateTarget?.(resolvedTarget);
|
|
7
|
-
const results = await runWithOperationTimeout(config, options.operationName, (signal) => mapWithConcurrency(resolvedTarget.resolvedHosts, config.
|
|
7
|
+
const results = await runWithOperationTimeout(config, options.operationName, (signal) => mapWithConcurrency(resolvedTarget.resolvedHosts, config.readFanOut, async (host) => {
|
|
8
8
|
try {
|
|
9
9
|
return await options.run(host, signal);
|
|
10
10
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readExecution.js","sourceRoot":"","sources":["../../src/operations/readExecution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE1E,OAAO,EAAE,sBAAsB,EAAgC,MAAM,+BAA+B,CAAC;AA0CrG,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAAqB,EACrB,MAA4B,EAC5B,OAOC;IAED,MAAM,cAAc,GAAG,sBAAsB,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACjF,sBAAsB,CAAC,MAAM,EAAE,cAAc,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACpE,OAAO,CAAC,cAAc,EAAE,CAAC,cAAc,CAAC,CAAC;IAEzC,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAC3C,MAAM,EACN,OAAO,CAAC,aAAa,EACrB,CAAC,MAAM,EAAE,EAAE,CACT,kBAAkB,CAAC,cAAc,CAAC,aAAa,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"readExecution.js","sourceRoot":"","sources":["../../src/operations/readExecution.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,6 +26,7 @@ export function buildServerInfo(context, diagnosticCapacity) {
|
|
|
26
26
|
read_timeout_ms: context.config.readTimeoutMs,
|
|
27
27
|
overall_operation_timeout_ms: context.config.overallOperationTimeoutMs ?? null,
|
|
28
28
|
device_concurrency: context.config.deviceConcurrency,
|
|
29
|
+
read_fan_out: context.config.readFanOut,
|
|
29
30
|
max_read_targets: context.config.maxReadTargets,
|
|
30
31
|
max_show_commands_per_request: context.config.maxShowCommandsPerRequest,
|
|
31
32
|
max_logging_messages_per_request: context.config.maxLoggingMessagesPerRequest,
|
|
@@ -36,10 +37,12 @@ export function buildServerInfo(context, diagnosticCapacity) {
|
|
|
36
37
|
max_probes_per_request: context.config.diagnostics.maxProbesPerRequest,
|
|
37
38
|
max_destinations_per_request: context.config.diagnostics.maxDestinationsPerRequest,
|
|
38
39
|
device_concurrency: context.config.diagnostics.deviceConcurrency,
|
|
40
|
+
max_concurrent_diagnostics: context.config.diagnostics.maxConcurrentDiagnostics,
|
|
39
41
|
ping_reply_timeout_ms: context.config.diagnostics.pingReplyTimeoutMs,
|
|
40
42
|
command_timeout_ms: context.config.diagnostics.commandTimeoutMs,
|
|
41
43
|
http_timeout_ms: context.config.diagnostics.httpTimeoutMs,
|
|
42
|
-
overall_operation_timeout_ms: context.config.diagnostics.overallOperationTimeoutMs
|
|
44
|
+
overall_operation_timeout_ms: context.config.diagnostics.overallOperationTimeoutMs,
|
|
45
|
+
native_request_timeout: context.config.diagnostics.nativeRequestTimeout
|
|
43
46
|
}
|
|
44
47
|
},
|
|
45
48
|
diagnostics: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildServerInfo.js","sourceRoot":"","sources":["../../src/serverInfo/buildServerInfo.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAI3D,MAAM,UAAU,eAAe,CAAC,OAA6B,EAAE,kBAA+C;IAC5G,MAAM,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAEzC,OAAO;QACL,WAAW,EAAE,QAAQ;QACrB,cAAc,EAAE,WAAW;QAC3B,WAAW,EAAE,OAAO,CAAC,UAAU;QAC/B,UAAU,EAAE,OAAO,CAAC,SAAS;QAC7B,YAAY,EAAE,WAAW;QACzB,SAAS,EAAE;YACT,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC;YAC7E,WAAW,EAAE,OAAO,EAAE,UAAU,IAAI,IAAI;YACxC,WAAW,EAAE,OAAO,EAAE,cAAc,IAAI,IAAI;YAC5C,YAAY,EAAE,OAAO,EAAE,eAAe,IAAI,IAAI;YAC9C,kBAAkB,EAAE,OAAO,EAAE,oBAAoB,IAAI,IAAI;YACzD,kBAAkB,EAAE,OAAO,EAAE,oBAAoB,IAAI,IAAI;SAC1D;QACD,YAAY,EAAE;YACZ,WAAW,EAAE,MAAM;YACnB,2BAA2B,EAAE,CAAC,wBAAwB,EAAE,iBAAiB,CAAC;YAC1E,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YACtC,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW;SACzC;QACD,MAAM,EAAE;YACN,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa;YAC7C,4BAA4B,EAAE,OAAO,CAAC,MAAM,CAAC,yBAAyB,IAAI,IAAI;YAC9E,kBAAkB,EAAE,OAAO,CAAC,MAAM,CAAC,iBAAiB;YACpD,gBAAgB,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc;YAC/C,6BAA6B,EAAE,OAAO,CAAC,MAAM,CAAC,yBAAyB;YACvE,gCAAgC,EAAE,OAAO,CAAC,MAAM,CAAC,4BAA4B;YAC7E,uBAAuB,EAAE,OAAO,CAAC,MAAM,CAAC,oBAAoB;YAC5D,WAAW,EAAE;gBACX,kBAAkB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,gBAAgB;gBAC/D,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY;gBACvD,sBAAsB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,mBAAmB;gBACtE,4BAA4B,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,yBAAyB;gBAClF,kBAAkB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,iBAAiB;gBAChE,qBAAqB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,kBAAkB;gBACpE,kBAAkB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,gBAAgB;gBAC/D,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,aAAa;gBACzD,4BAA4B,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,yBAAyB;
|
|
1
|
+
{"version":3,"file":"buildServerInfo.js","sourceRoot":"","sources":["../../src/serverInfo/buildServerInfo.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,6 +32,7 @@ export interface ServerInfo {
|
|
|
32
32
|
read_timeout_ms: number;
|
|
33
33
|
overall_operation_timeout_ms: number | null;
|
|
34
34
|
device_concurrency: number;
|
|
35
|
+
read_fan_out: number;
|
|
35
36
|
max_read_targets: number;
|
|
36
37
|
max_show_commands_per_request: number;
|
|
37
38
|
max_logging_messages_per_request: number;
|
|
@@ -42,10 +43,12 @@ export interface ServerInfo {
|
|
|
42
43
|
max_probes_per_request: number;
|
|
43
44
|
max_destinations_per_request: number;
|
|
44
45
|
device_concurrency: number;
|
|
46
|
+
max_concurrent_diagnostics: number;
|
|
45
47
|
ping_reply_timeout_ms: number;
|
|
46
48
|
command_timeout_ms: number;
|
|
47
49
|
http_timeout_ms: number;
|
|
48
50
|
overall_operation_timeout_ms: number;
|
|
51
|
+
native_request_timeout: boolean;
|
|
49
52
|
};
|
|
50
53
|
};
|
|
51
54
|
diagnostics: {
|
package/docs/CHECKPOINT.md
CHANGED
|
@@ -23,8 +23,6 @@ The server is a test-backed, read-only MCP service for Arista EOS eAPI. The prod
|
|
|
23
23
|
- `validate-inventory`
|
|
24
24
|
- `print-server-info`
|
|
25
25
|
- `probe`
|
|
26
|
-
- `inspect-diagnostics` (read-only persisted state and audit, no device access)
|
|
27
|
-
- `release-diagnostics` (offline operator attestation, explicit scope and atomic audit)
|
|
28
26
|
|
|
29
27
|
## Safety and operational controls
|
|
30
28
|
|
|
@@ -35,10 +33,9 @@ The server is a test-backed, read-only MCP service for Arista EOS eAPI. The prod
|
|
|
35
33
|
- HTTPS with certificate validation by default and optional custom CA support.
|
|
36
34
|
- Validated show commands and bounded logging/running-configuration queries.
|
|
37
35
|
- Read-operation concurrency, target, response-size, and timeout controls.
|
|
38
|
-
- Configurable diagnostic budgets,
|
|
39
|
-
- Write-ahead SQLite reservations, exact wire-ID persistence/correlation, exclusive crash-released ownership, restoration of unfinished work as uncertain, and fail-closed storage errors.
|
|
36
|
+
- Configurable diagnostic budgets, in-memory per-server admission, independent timeouts, and uncertain reservations held for the command budget after unknown remote completion (ADR 0006).
|
|
40
37
|
- JSON-RPC version/ID and result/error exclusivity validation precedes output interpretation or read-only fallback; unrelated acknowledgements cannot free diagnostic capacity.
|
|
41
|
-
- Live sanitized capacity/reservation visibility in server info
|
|
38
|
+
- Live sanitized capacity/reservation visibility in server info, including when each uncertain slot frees. A qualified native remote kill/deadline mechanism remains unimplemented; installed EOS requestTimeout is not an end-to-end termination guarantee.
|
|
42
39
|
- No retries or shell/SSH fallback for ping. Non-configuring diagnostics are not passive reads; traceroute and capture are not implemented.
|
|
43
40
|
- Sanitized result envelopes with stable machine-readable errors.
|
|
44
41
|
|
|
@@ -53,4 +50,4 @@ The server is a test-backed, read-only MCP service for Arista EOS eAPI. The prod
|
|
|
53
50
|
|
|
54
51
|
Run `npm test`, `npm run typecheck`, `npm run lint`, and `npm run build` after changes. Optional integration tests require the configured cEOS environment. Ping's module and MCP stdio integration suites are qualified on cEOS 4.34.3M; see [DIAGNOSTICS.md](DIAGNOSTICS.md).
|
|
55
52
|
|
|
56
|
-
Latest
|
|
53
|
+
Latest verification (in-memory capacity, ADR 0006): unit suite, typecheck, static policy and build pass; `INTEGRATION=1` was run against the cEOS lab, including a second server pinging the same inventory while the first held an uncertain slot.
|
package/docs/CODE_WALKTHROUGH.md
CHANGED
|
@@ -20,8 +20,6 @@ Execution starts at `src/index.ts`. It parses CLI args, loads config, then dispa
|
|
|
20
20
|
- `validate-inventory`: validate inventory and print the result.
|
|
21
21
|
- `print-server-info`: print sanitized server metadata.
|
|
22
22
|
- `probe`: run the same probe logic as the MCP probe tool.
|
|
23
|
-
- `inspect-diagnostics`: read existing reservations and release audit without device access, ownership takeover, or reset.
|
|
24
|
-
- `release-diagnostics`: offline, exact-scope operator release with explicit fencing attestation and atomic audit; no device calls or MCP exposure.
|
|
25
23
|
|
|
26
24
|
CLI parsing lives in `src/cli.ts`. The app name and version are read from `package.json` at runtime via `src/core/version.ts`. Shared error handling lives in `src/core/errors.ts`, which defines `AppError` and the stable machine-readable error codes used across the CLI and MCP layers.
|
|
27
25
|
|
|
@@ -53,7 +51,7 @@ eAPI protocol and transport are split:
|
|
|
53
51
|
|
|
54
52
|
- `src/eapi/client.ts`: builds JSON-RPC `runCmds` requests using the connection's `eapiVersion` (`"latest"` by default, `1` when pinned in config), handles HTTP errors, invalid JSON, protocol version/response-ID correlation, exclusive result/error envelopes, JSON-RPC errors, and unexpected result counts. Supports opt-in enable mode (`{ enable: true }`) for privileged commands by prepending `enable` to the wire commands and stripping the extra result entry transparently. Per-request timeout and caller cancellation are combined with `AbortSignal`.
|
|
55
53
|
- `src/eapi/transport.ts`: production HTTPS transport and test-friendly fetch transport. The production transport enforces `maxResponseSizeBytes` while chunks are received, before buffering an oversized device response.
|
|
56
|
-
- `src/eapi/client.ts` also exposes single-execution text commands for active diagnostics, without JSON fallback retries, using the
|
|
54
|
+
- `src/eapi/client.ts` also exposes single-execution text commands for active diagnostics, without JSON fallback retries, using the reserved request identity supplied by the diagnostic execution context.
|
|
57
55
|
- `src/eapi/types.ts`: shared eAPI types, the low-level `EosCommandRunner` interface used by `EapiDeviceReader`, `EapiCommandOptions`, and helpers for validating/drilling into eAPI JSON-RPC response payloads.
|
|
58
56
|
|
|
59
57
|
## Read Tool Services
|
|
@@ -77,17 +75,15 @@ Shared type-narrowing utilities (`isObject`, `readString`, `readBoolean`, `readN
|
|
|
77
75
|
## Diagnostic Execution
|
|
78
76
|
|
|
79
77
|
- `src/diagnostics/executor.ts`: typed diagnostic orchestration, inventory opt-in and probe-budget checks, existing result envelopes, and cancellation. One executor is created per server instance.
|
|
80
|
-
- `src/
|
|
78
|
+
- `src/operations/eapiSlots.ts`: in-memory admission shared by every eAPI request in one server process. Reads and diagnostics share each device's slots; diagnostics also have a per-device share and a server-wide ceiling. `EapiDeviceReader` holds a read slot per request. Waiters are served oldest first, skipping those that cannot run yet. Unknown completion holds a slot for `commandTimeoutMs`, then a timer frees it; a late confirmed response frees it sooner. Shutdown rejects queued work; cancelled waiters are removed.
|
|
81
79
|
- `src/diagnostics/eapiRunner.ts`: connection resolution followed by one text eAPI attempt in enable mode. Separate error paths distinguish local rejection before dispatch from uncertain RPC, transport, or malformed-result failures after dispatch; there is no mutable dispatch flag or retry.
|
|
82
80
|
- `src/diagnostics/executionError.ts`: typed `AppError` classification (`not_dispatched`, `completed`, or `unknown`). Only explicitly settled errors permit capacity reuse; ordinary errors remain uncertain.
|
|
83
81
|
- `src/diagnostics/ping.ts`: literal-address/VRF/source/count validation, finite ping command construction, and loss/RTT interpretation. A no-reply finding is not an execution failure.
|
|
84
82
|
- `src/diagnostics/types.ts`: request, prepared intent, observation, and finding types discriminated by diagnostic kind, plus the `DiagnosticDeviceRunner` seam. Only ping is implemented; capture sessions are not pre-modeled.
|
|
85
83
|
|
|
86
|
-
Diagnostic execution reuses read-operation orchestration with independent settings and
|
|
84
|
+
Diagnostic execution reuses read-operation orchestration with independent settings and per-device admission under a server-wide ceiling. Unknown completion holds capacity for the command budget; HTTP abort is not a remote kill signal. Each server-info call reads `DiagnosticExecutor.getCapacity()` afresh; the standalone CLI reports no live snapshot.
|
|
87
85
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
`releaseEvidence.ts` validates attestation scope/consistency and uses shared JSON SHA-256 hashing for evidence and audit checksums; it does not verify external fencing. `reservationSchema.ts` validates and normalizes both unresolved records and audit snapshots, including absent legacy RPC IDs. The refactor preserves serialized records, checksum computation, and schema versions. Schema-1 migration, audit insertion, and selected deletions share the release transaction; ordinary server migration preserves occupied capacity. See [DIAGNOSTICS.md](DIAGNOSTICS.md).
|
|
86
|
+
Capacity lives in memory per server process, so several servers can run against one inventory. See [DIAGNOSTICS.md](DIAGNOSTICS.md) [ADR 0006](adr/0006-in-memory-timed-diagnostic-capacity.md), and [ADR 0007](adr/0007-per-device-diagnostic-concurrency.md).
|
|
91
87
|
|
|
92
88
|
## MCP Layer
|
|
93
89
|
|
|
@@ -126,11 +122,10 @@ Tests mirror the source layout:
|
|
|
126
122
|
- Inventory and target behavior: `inventory.test.ts`, `targetResolution.test.ts`
|
|
127
123
|
- eAPI and connection behavior: `eapiClient.test.ts`, `eosDeviceReader.test.ts`, `startupValidation.test.ts`, `responseSize.test.ts`
|
|
128
124
|
- Read services and orchestration: `probeDevices.test.ts`, `runShow.test.ts`, `loggingQuery.test.ts`, `showLogging.test.ts`, `getFacts.test.ts`, `getRunningConfig.test.ts`, `readExecution.test.ts`
|
|
129
|
-
- Diagnostics: `ping.test.ts`, `diagnosticConfig.test.ts`, `diagnostics.test.ts`, `diagnosticEapi.test.ts`, `diagnosticReservations.test.ts` (
|
|
130
|
-
-
|
|
125
|
+
- Diagnostics: `ping.test.ts`, `diagnosticConfig.test.ts`, `diagnostics.test.ts`, `diagnosticEapi.test.ts`, `diagnosticReservations.test.ts` (timed release, cancellation, late responses and visibility)
|
|
126
|
+
- Response correlation: `eapiCorrelation.test.ts`
|
|
131
127
|
- Server info and errors: `buildServerInfo.test.ts`, `errors.test.ts`, `errorTaxonomy.test.ts`
|
|
132
128
|
- MCP adapters and stdio: `readToolsMcp.test.ts`, `probeDevicesTool.test.ts`, `listInventoryTool.test.ts`, `mcpStdioSmoke.test.ts`
|
|
133
129
|
- Package/static policy: `packagePolicy.test.ts`, `packageSmoke.test.ts`
|
|
134
130
|
- Optional cEOS integration (requires a configured lab): `integration.test.ts`, `pingIntegration.test.ts`, `pingMcpIntegration.test.ts`
|
|
135
|
-
- Offline attested release and CLI: `diagnosticRelease.test.ts`, `releaseDiagnosticsCli.test.ts` (synthetic evidence only; no live EOS releases)
|
|
136
131
|
- Shared test helpers: `test/helpers.ts`
|