agentfootprint 11.3.0 → 11.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CAPABILITIES.md +4 -1
- package/dist/adapters/mcp/agentcoreRuntime/invoke.js +7 -6
- package/dist/adapters/mcp/agentcoreRuntime/invoke.js.map +1 -1
- package/dist/adapters/mcp/agentcoreRuntime/sessionBusy.js +36 -2
- package/dist/adapters/mcp/agentcoreRuntime/sessionBusy.js.map +1 -1
- package/dist/adapters/mcp/agentcoreRuntime/transport.js +3 -1
- package/dist/adapters/mcp/agentcoreRuntime/transport.js.map +1 -1
- package/dist/answer-account/account.js +15 -3
- package/dist/answer-account/account.js.map +1 -1
- package/dist/answer-account/facts/howSure.js +10 -22
- package/dist/answer-account/facts/howSure.js.map +1 -1
- package/dist/core/Agent.js +26 -3
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/AgentBuilder.js +69 -12
- package/dist/core/agent/AgentBuilder.js.map +1 -1
- package/dist/core/agent/assessment/assess.js +15 -4
- package/dist/core/agent/assessment/assess.js.map +1 -1
- package/dist/core/agent/assessment/compose.js +153 -15
- package/dist/core/agent/assessment/compose.js.map +1 -1
- package/dist/core/agent/assessment/reasons.js +35 -1
- package/dist/core/agent/assessment/reasons.js.map +1 -1
- package/dist/core/agent/assessment/sources.js +205 -0
- package/dist/core/agent/assessment/sources.js.map +1 -0
- package/dist/core/agent/assessment/stage.js +15 -4
- package/dist/core/agent/assessment/stage.js.map +1 -1
- package/dist/core/agent/buildAgentChart.js.map +1 -1
- package/dist/core/agent/buildToolRegistry.js +3 -0
- package/dist/core/agent/buildToolRegistry.js.map +1 -1
- package/dist/core/agent/evidence/numberPrecision.js.map +1 -1
- package/dist/core/agent/honesty/mounts.js.map +1 -1
- package/dist/core/agent/stages/prepareFinal.js +33 -17
- package/dist/core/agent/stages/prepareFinal.js.map +1 -1
- package/dist/esm/adapters/mcp/agentcoreRuntime/invoke.d.ts +7 -6
- package/dist/esm/adapters/mcp/agentcoreRuntime/invoke.js +7 -6
- package/dist/esm/adapters/mcp/agentcoreRuntime/invoke.js.map +1 -1
- package/dist/esm/adapters/mcp/agentcoreRuntime/sessionBusy.d.ts +32 -1
- package/dist/esm/adapters/mcp/agentcoreRuntime/sessionBusy.js +35 -1
- package/dist/esm/adapters/mcp/agentcoreRuntime/sessionBusy.js.map +1 -1
- package/dist/esm/adapters/mcp/agentcoreRuntime/transport.js +4 -2
- package/dist/esm/adapters/mcp/agentcoreRuntime/transport.js.map +1 -1
- package/dist/esm/answer-account/account.js +16 -4
- package/dist/esm/answer-account/account.js.map +1 -1
- package/dist/esm/answer-account/facts/howSure.js +10 -22
- package/dist/esm/answer-account/facts/howSure.js.map +1 -1
- package/dist/esm/core/Agent.d.ts +2 -1
- package/dist/esm/core/Agent.js +26 -3
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/AgentBuilder.d.ts +22 -1
- package/dist/esm/core/agent/AgentBuilder.js +69 -12
- package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
- package/dist/esm/core/agent/assessment/assess.js +15 -4
- package/dist/esm/core/agent/assessment/assess.js.map +1 -1
- package/dist/esm/core/agent/assessment/compose.d.ts +82 -5
- package/dist/esm/core/agent/assessment/compose.js +148 -14
- package/dist/esm/core/agent/assessment/compose.js.map +1 -1
- package/dist/esm/core/agent/assessment/reasons.d.ts +17 -1
- package/dist/esm/core/agent/assessment/reasons.js +35 -1
- package/dist/esm/core/agent/assessment/reasons.js.map +1 -1
- package/dist/esm/core/agent/assessment/sources.d.ts +66 -0
- package/dist/esm/core/agent/assessment/sources.js +201 -0
- package/dist/esm/core/agent/assessment/sources.js.map +1 -0
- package/dist/esm/core/agent/assessment/stage.d.ts +17 -4
- package/dist/esm/core/agent/assessment/stage.js +16 -5
- package/dist/esm/core/agent/assessment/stage.js.map +1 -1
- package/dist/esm/core/agent/assessment/types.d.ts +37 -0
- package/dist/esm/core/agent/buildAgentChart.d.ts +8 -0
- package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
- package/dist/esm/core/agent/buildToolRegistry.js +4 -1
- package/dist/esm/core/agent/buildToolRegistry.js.map +1 -1
- package/dist/esm/core/agent/evidence/numberPrecision.d.ts +3 -2
- package/dist/esm/core/agent/evidence/numberPrecision.js.map +1 -1
- package/dist/esm/core/agent/honesty/mounts.d.ts +11 -2
- package/dist/esm/core/agent/honesty/mounts.js.map +1 -1
- package/dist/esm/core/agent/stages/prepareFinal.d.ts +19 -3
- package/dist/esm/core/agent/stages/prepareFinal.js +33 -17
- package/dist/esm/core/agent/stages/prepareFinal.js.map +1 -1
- package/dist/esm/core/agent/types.d.ts +16 -2
- package/dist/esm/events/payloads.d.ts +137 -27
- package/dist/esm/lib/displayName.d.ts +81 -0
- package/dist/esm/lib/displayName.js +119 -0
- package/dist/esm/lib/displayName.js.map +1 -0
- package/dist/esm/mcp/callLifetime.d.ts +57 -14
- package/dist/esm/mcp/callLifetime.js +67 -19
- package/dist/esm/mcp/callLifetime.js.map +1 -1
- package/dist/esm/mcp/callMarker.d.ts +43 -0
- package/dist/esm/mcp/callMarker.js +69 -0
- package/dist/esm/mcp/callMarker.js.map +1 -0
- package/dist/esm/mcp/connectionRefusals.js +7 -0
- package/dist/esm/mcp/connectionRefusals.js.map +1 -1
- package/dist/esm/mcp/index.d.ts +2 -0
- package/dist/esm/mcp/index.js +3 -0
- package/dist/esm/mcp/index.js.map +1 -1
- package/dist/esm/mcp/mcpClient.js +93 -26
- package/dist/esm/mcp/mcpClient.js.map +1 -1
- package/dist/esm/mcp/replay.d.ts +283 -0
- package/dist/esm/mcp/replay.js +401 -0
- package/dist/esm/mcp/replay.js.map +1 -0
- package/dist/esm/mcp/replayUnavailable.d.ts +55 -0
- package/dist/esm/mcp/replayUnavailable.js +74 -0
- package/dist/esm/mcp/replayUnavailable.js.map +1 -0
- package/dist/esm/mcp/requestLedger.d.ts +115 -32
- package/dist/esm/mcp/requestLedger.js +193 -52
- package/dist/esm/mcp/requestLedger.js.map +1 -1
- package/dist/esm/mcp/seriesEvidence.d.ts +73 -15
- package/dist/esm/mcp/seriesEvidence.js +114 -21
- package/dist/esm/mcp/seriesEvidence.js.map +1 -1
- package/dist/esm/mcp/throttleRetry.d.ts +86 -42
- package/dist/esm/mcp/throttleRetry.js +158 -50
- package/dist/esm/mcp/throttleRetry.js.map +1 -1
- package/dist/esm/mcp/toolResult.d.ts +6 -0
- package/dist/esm/mcp/toolResult.js +15 -0
- package/dist/esm/mcp/toolResult.js.map +1 -1
- package/dist/esm/mcp/types.d.ts +70 -8
- package/dist/esm/redaction/knownStrings.js +14 -0
- package/dist/esm/redaction/knownStrings.js.map +1 -1
- package/dist/esm/semantics/coverage/answer.d.ts +9 -1
- package/dist/esm/semantics/coverage/answer.js +50 -10
- package/dist/esm/semantics/coverage/answer.js.map +1 -1
- package/dist/esm/tool-providers/index.d.ts +2 -2
- package/dist/esm/tool-providers/index.js +4 -0
- package/dist/esm/tool-providers/index.js.map +1 -1
- package/dist/esm/tools/requestEvidence.js +60 -0
- package/dist/esm/tools/requestEvidence.js.map +1 -1
- package/dist/esm/tools/tools.d.ts +30 -0
- package/dist/esm/tools/tools.js +16 -0
- package/dist/esm/tools/tools.js.map +1 -1
- package/dist/lib/displayName.js +125 -0
- package/dist/lib/displayName.js.map +1 -0
- package/dist/mcp/callLifetime.js +66 -18
- package/dist/mcp/callLifetime.js.map +1 -1
- package/dist/mcp/callMarker.js +74 -0
- package/dist/mcp/callMarker.js.map +1 -0
- package/dist/mcp/connectionRefusals.js +7 -0
- package/dist/mcp/connectionRefusals.js.map +1 -1
- package/dist/mcp/index.js +5 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/mcpClient.js +91 -24
- package/dist/mcp/mcpClient.js.map +1 -1
- package/dist/mcp/replay.js +411 -0
- package/dist/mcp/replay.js.map +1 -0
- package/dist/mcp/replayUnavailable.js +79 -0
- package/dist/mcp/replayUnavailable.js.map +1 -0
- package/dist/mcp/requestLedger.js +193 -52
- package/dist/mcp/requestLedger.js.map +1 -1
- package/dist/mcp/seriesEvidence.js +116 -22
- package/dist/mcp/seriesEvidence.js.map +1 -1
- package/dist/mcp/throttleRetry.js +160 -51
- package/dist/mcp/throttleRetry.js.map +1 -1
- package/dist/mcp/toolResult.js +17 -1
- package/dist/mcp/toolResult.js.map +1 -1
- package/dist/redaction/knownStrings.js +14 -0
- package/dist/redaction/knownStrings.js.map +1 -1
- package/dist/semantics/coverage/answer.js +49 -9
- package/dist/semantics/coverage/answer.js.map +1 -1
- package/dist/tool-providers/index.js +5 -1
- package/dist/tool-providers/index.js.map +1 -1
- package/dist/tools/requestEvidence.js +60 -0
- package/dist/tools/requestEvidence.js.map +1 -1
- package/dist/tools/tools.js +18 -1
- package/dist/tools/tools.js.map +1 -1
- package/dist/types/adapters/mcp/agentcoreRuntime/invoke.d.ts +7 -6
- package/dist/types/adapters/mcp/agentcoreRuntime/invoke.d.ts.map +1 -1
- package/dist/types/adapters/mcp/agentcoreRuntime/sessionBusy.d.ts +32 -1
- package/dist/types/adapters/mcp/agentcoreRuntime/sessionBusy.d.ts.map +1 -1
- package/dist/types/adapters/mcp/agentcoreRuntime/transport.d.ts.map +1 -1
- package/dist/types/answer-account/account.d.ts.map +1 -1
- package/dist/types/answer-account/facts/howSure.d.ts.map +1 -1
- package/dist/types/core/Agent.d.ts +2 -1
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/AgentBuilder.d.ts +22 -1
- package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
- package/dist/types/core/agent/assessment/assess.d.ts.map +1 -1
- package/dist/types/core/agent/assessment/compose.d.ts +82 -5
- package/dist/types/core/agent/assessment/compose.d.ts.map +1 -1
- package/dist/types/core/agent/assessment/reasons.d.ts +17 -1
- package/dist/types/core/agent/assessment/reasons.d.ts.map +1 -1
- package/dist/types/core/agent/assessment/sources.d.ts +67 -0
- package/dist/types/core/agent/assessment/sources.d.ts.map +1 -0
- package/dist/types/core/agent/assessment/stage.d.ts +17 -4
- package/dist/types/core/agent/assessment/stage.d.ts.map +1 -1
- package/dist/types/core/agent/assessment/types.d.ts +37 -0
- package/dist/types/core/agent/assessment/types.d.ts.map +1 -1
- package/dist/types/core/agent/buildAgentChart.d.ts +8 -0
- package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/buildToolRegistry.d.ts.map +1 -1
- package/dist/types/core/agent/evidence/numberPrecision.d.ts +3 -2
- package/dist/types/core/agent/evidence/numberPrecision.d.ts.map +1 -1
- package/dist/types/core/agent/honesty/mounts.d.ts +11 -2
- package/dist/types/core/agent/honesty/mounts.d.ts.map +1 -1
- package/dist/types/core/agent/stages/prepareFinal.d.ts +19 -3
- package/dist/types/core/agent/stages/prepareFinal.d.ts.map +1 -1
- package/dist/types/core/agent/types.d.ts +16 -2
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/events/payloads.d.ts +137 -27
- package/dist/types/events/payloads.d.ts.map +1 -1
- package/dist/types/lib/displayName.d.ts +82 -0
- package/dist/types/lib/displayName.d.ts.map +1 -0
- package/dist/types/mcp/callLifetime.d.ts +57 -14
- package/dist/types/mcp/callLifetime.d.ts.map +1 -1
- package/dist/types/mcp/callMarker.d.ts +44 -0
- package/dist/types/mcp/callMarker.d.ts.map +1 -0
- package/dist/types/mcp/index.d.ts +2 -0
- package/dist/types/mcp/index.d.ts.map +1 -1
- package/dist/types/mcp/mcpClient.d.ts.map +1 -1
- package/dist/types/mcp/replay.d.ts +284 -0
- package/dist/types/mcp/replay.d.ts.map +1 -0
- package/dist/types/mcp/replayUnavailable.d.ts +56 -0
- package/dist/types/mcp/replayUnavailable.d.ts.map +1 -0
- package/dist/types/mcp/requestLedger.d.ts +115 -32
- package/dist/types/mcp/requestLedger.d.ts.map +1 -1
- package/dist/types/mcp/seriesEvidence.d.ts +73 -15
- package/dist/types/mcp/seriesEvidence.d.ts.map +1 -1
- package/dist/types/mcp/throttleRetry.d.ts +86 -42
- package/dist/types/mcp/throttleRetry.d.ts.map +1 -1
- package/dist/types/mcp/toolResult.d.ts +6 -0
- package/dist/types/mcp/toolResult.d.ts.map +1 -1
- package/dist/types/mcp/types.d.ts +70 -8
- package/dist/types/mcp/types.d.ts.map +1 -1
- package/dist/types/redaction/knownStrings.d.ts.map +1 -1
- package/dist/types/semantics/coverage/answer.d.ts +9 -1
- package/dist/types/semantics/coverage/answer.d.ts.map +1 -1
- package/dist/types/tool-providers/index.d.ts +2 -2
- package/dist/types/tool-providers/index.d.ts.map +1 -1
- package/dist/types/tools/requestEvidence.d.ts.map +1 -1
- package/dist/types/tools/tools.d.ts +30 -0
- package/dist/types/tools/tools.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,73 +1,146 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* requestLedger — which dispatched tool call an MCP request belongs to, so the
|
|
3
|
-
* retry series that sends it files its attempts into THAT call's run;
|
|
4
|
-
*
|
|
3
|
+
* retry series that sends it files its attempts into THAT call's run; when the
|
|
4
|
+
* MCP SDK cancels a request, so the series sending it stops; and whether the
|
|
5
|
+
* request's JSON-RPC answer arrived.
|
|
5
6
|
*
|
|
6
7
|
* Pattern: a per-connection ledger + the SDK transport's `send`, watched in place.
|
|
7
8
|
* Role: The middle of the evidence seam (`tools/requestEvidence.ts` is its
|
|
8
9
|
* door). The retry series runs inside the transport's `fetch`, which
|
|
9
10
|
* the MCP SDK calls with a serialized body and nothing else — no tool
|
|
10
|
-
* call, no run. Three hops carry the call down to it
|
|
11
|
-
* identity the hop already holds:
|
|
11
|
+
* call, no run. Three hops carry the call down to it:
|
|
12
12
|
*
|
|
13
|
-
* 1. call →
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* 2.
|
|
17
|
-
*
|
|
18
|
-
*
|
|
13
|
+
* 1. call → marker `issue`: the MCP tool gets a library-private marker and
|
|
14
|
+
* puts it in its request's `_meta` (`callMarker.ts`). It
|
|
15
|
+
* survives an SDK that copies the params.
|
|
16
|
+
* 2. marker → id the watched `send` takes the marker out of the message
|
|
17
|
+
* — the server receives the bytes it always did — and
|
|
18
|
+
* keys the call by the JSON-RPC `id` the SDK assigned.
|
|
19
19
|
* 3. id → series `claim`: the series reads the `id` back out of the body
|
|
20
20
|
* it is about to send.
|
|
21
21
|
*
|
|
22
22
|
* CANCELLATION DOES NOT WAIT ON ATTRIBUTION. Every `tools/call` in flight gets
|
|
23
|
-
* an entry,
|
|
24
|
-
* `notifications/cancelled` naming the request's id — on its own
|
|
25
|
-
* when the call's signal fires — through this same `send`. The
|
|
26
|
-
* that request's series there and then, so a request nobody waits
|
|
27
|
-
* asked again, even when
|
|
23
|
+
* an entry, matched or not, and the SDK says when it gives a request up: it
|
|
24
|
+
* sends `notifications/cancelled` naming the request's id — on its own
|
|
25
|
+
* timeout, or when the call's signal fires — through this same `send`. The
|
|
26
|
+
* ledger aborts that request's series there and then, so a request nobody waits
|
|
27
|
+
* for is never asked again, even when it could not be matched to a call.
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
29
|
+
* Under `'app-authorized'` (`strict`), two more things hold:
|
|
30
|
+
* - A `tools/call` that reaches `send` without a marker this ledger issued
|
|
31
|
+
* and has not used is REFUSED there (`replayUnavailable.ts`,
|
|
32
|
+
* `'request-unmatched'`): its answer could not be tied to any call, so it
|
|
33
|
+
* is never sent rather than guessed at.
|
|
34
|
+
* - Each matched request's answer is AWAITED, by its id: the connection's
|
|
35
|
+
* incoming messages are observed for the JSON-RPC response to it. A 202, or
|
|
36
|
+
* a stream, is not that answer. The watch ends when the answer arrives,
|
|
37
|
+
* when the SDK cancels the request, when the call settles (found by its
|
|
38
|
+
* marker, never by its params object) or when the connection closes —
|
|
39
|
+
* never when only the HTTP send finished, since a 202 or a stream can still
|
|
40
|
+
* carry the answer later.
|
|
41
|
+
*
|
|
42
|
+
* Whether the answers are observed at all is established once, at
|
|
43
|
+
* initialization: the `initialize` answer must pass the observer
|
|
44
|
+
* (`answersObserved`). An SDK whose `connect` replaces the transport's
|
|
45
|
+
* `onmessage` instead of keeping it leaves the observer out, and a call under
|
|
46
|
+
* `'app-authorized'` is then refused before it is sent (`replayUnavailable.ts`).
|
|
47
|
+
*
|
|
48
|
+
* Ids are the client's, one ledger per connection, so concurrent calls — and
|
|
49
|
+
* concurrent runs sharing one client — can never claim each other's request. A
|
|
50
|
+
* request that is not a `tools/call` (a `tools/list`, a notification, a
|
|
51
|
+
* response) claims nothing.
|
|
35
52
|
*
|
|
36
53
|
* `send` is installed as an OWN property of the transport instance — the same
|
|
37
54
|
* object, its own `send` bound to it, so a transport class with `#private`
|
|
38
55
|
* fields works as it always did. Assigning `send` again afterwards THROWS: a
|
|
39
56
|
* send that bypassed the ledger would quietly lose every call's attempts.
|
|
40
57
|
*
|
|
58
|
+
* Each matched `tools/call` also gets ONE `RequestReplay` (`replay.ts`), the
|
|
59
|
+
* facts its series, this ledger and its call share: the series' claim hands it
|
|
60
|
+
* over by the request's id, the call reads it from the entry it was issued
|
|
61
|
+
* (`IssuedCall`), which outlives the connection's close. The
|
|
62
|
+
* series writes what HTTP showed; this ledger writes whether the JSON-RPC
|
|
63
|
+
* answer arrived; the call writes how it settled.
|
|
64
|
+
*
|
|
41
65
|
* What it does NOT do: retry, wait, or decide anything. The series is the one
|
|
42
66
|
* retry owner; this only tells it whose attempts it is making, and when the SDK
|
|
43
67
|
* has stopped waiting for them.
|
|
44
68
|
*/
|
|
45
|
-
|
|
69
|
+
import { takeMarker } from './callMarker.js';
|
|
70
|
+
import { RequestReplay } from './replay.js';
|
|
71
|
+
import { McpReplayUnavailableError } from './replayUnavailable.js';
|
|
72
|
+
/** The method whose requests a tool call issues markers for. */
|
|
46
73
|
const TOOLS_CALL = 'tools/call';
|
|
47
74
|
/** The notification the SDK sends when it gives up one of its own requests. */
|
|
48
75
|
const CANCELLED = 'notifications/cancelled';
|
|
49
|
-
/**
|
|
76
|
+
/** The request whose answer proves the observer sees this connection's answers. */
|
|
77
|
+
const INITIALIZE = 'initialize';
|
|
78
|
+
const LENIENT = { server: 'mcp', strict: false };
|
|
79
|
+
/** Per connection: the calls issued and not yet settled, the requests being sent, the answers awaited. */
|
|
50
80
|
export class RequestLedger {
|
|
51
|
-
|
|
52
|
-
issued
|
|
53
|
-
|
|
54
|
-
bound = new WeakSet();
|
|
81
|
+
options;
|
|
82
|
+
/** Every call issued and not yet settled — keyed by its marker. */
|
|
83
|
+
issued = new Map();
|
|
55
84
|
/** Every `tools/call` sent and not yet settled — keyed by its JSON-RPC id. */
|
|
56
85
|
sending = new Map();
|
|
86
|
+
/** Matched requests whose JSON-RPC answer is awaited (`strict` only) — by id. */
|
|
87
|
+
awaiting = new Map();
|
|
88
|
+
initializeId;
|
|
89
|
+
initializeAnswered = false;
|
|
90
|
+
markers = 0;
|
|
57
91
|
calls = 0;
|
|
58
92
|
unboundNamed = false;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
this.issued.set(params, ticket);
|
|
93
|
+
constructor(options = LENIENT) {
|
|
94
|
+
this.options = options;
|
|
62
95
|
}
|
|
63
|
-
/**
|
|
64
|
-
|
|
65
|
-
|
|
96
|
+
/**
|
|
97
|
+
* A call is about to send its request: its entry, whose `marker` the call
|
|
98
|
+
* puts in the request's `_meta` (`callMarker.ts` · `markParams`). `ticket`
|
|
99
|
+
* is where its attempts are filed, when the call carries the run's evidence
|
|
100
|
+
* port.
|
|
101
|
+
*/
|
|
102
|
+
issue(ticket) {
|
|
103
|
+
this.markers += 1;
|
|
104
|
+
const call = {
|
|
105
|
+
marker: `call-${this.markers}`,
|
|
106
|
+
...(ticket !== undefined && { ticket }),
|
|
107
|
+
};
|
|
108
|
+
this.issued.set(call.marker, call);
|
|
109
|
+
return call;
|
|
110
|
+
}
|
|
111
|
+
/** `call` settled: forget it, and stop awaiting its request's answer. */
|
|
112
|
+
settle(call) {
|
|
113
|
+
if (this.issued.get(call.marker) === call)
|
|
114
|
+
this.issued.delete(call.marker);
|
|
115
|
+
const request = call.request;
|
|
116
|
+
if (request !== undefined && this.awaiting.get(request.id) === request.replay) {
|
|
117
|
+
this.awaiting.delete(request.id);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/** The connection closed: nothing it sent is awaited, and no call is pending, any more. */
|
|
121
|
+
close() {
|
|
122
|
+
this.issued.clear();
|
|
123
|
+
this.sending.clear();
|
|
124
|
+
this.awaiting.clear();
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Whether this connection's answers pass the observer: the `initialize`
|
|
128
|
+
* answer did. Read once the connection is initialized.
|
|
129
|
+
*/
|
|
130
|
+
get answersObserved() {
|
|
131
|
+
return this.initializeAnswered;
|
|
66
132
|
}
|
|
67
133
|
/** How many `tools/call` requests the watched transport has sent — matched to a call or not. */
|
|
68
134
|
get toolCallsSent() {
|
|
69
135
|
return this.calls;
|
|
70
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* @internal How many entries the ledger holds: calls issued and not settled,
|
|
139
|
+
* requests being sent, answers awaited. Zero once every call settled.
|
|
140
|
+
*/
|
|
141
|
+
get retained() {
|
|
142
|
+
return this.issued.size + this.sending.size + this.awaiting.size;
|
|
143
|
+
}
|
|
71
144
|
/** `true` the first time it is asked, then never again: an unmatched request is named once per connection. */
|
|
72
145
|
firstUnbound() {
|
|
73
146
|
if (this.unboundNamed)
|
|
@@ -80,6 +153,11 @@ export class RequestLedger {
|
|
|
80
153
|
* original bound to the instance itself. Returns the SAME object — or
|
|
81
154
|
* `undefined` when it has no `send` to watch or refuses the property, and
|
|
82
155
|
* then nothing is watched and no call should expect its attempts filed.
|
|
156
|
+
*
|
|
157
|
+
* Its incoming messages are watched too: an `onmessage` set before the
|
|
158
|
+
* client connects, which the current MCP SDK's `Protocol.connect` keeps and
|
|
159
|
+
* calls before its own dispatch. Whether it was kept is known once the
|
|
160
|
+
* `initialize` answer has, or has not, passed it (`answersObserved`).
|
|
83
161
|
*/
|
|
84
162
|
watch(transport) {
|
|
85
163
|
const send = Reflect.get(transport, 'send');
|
|
@@ -102,8 +180,37 @@ export class RequestLedger {
|
|
|
102
180
|
catch {
|
|
103
181
|
return undefined;
|
|
104
182
|
}
|
|
183
|
+
this.watchMessages(transport);
|
|
105
184
|
return transport;
|
|
106
185
|
}
|
|
186
|
+
/** Observe incoming messages before whatever handled them already — never instead of it. */
|
|
187
|
+
watchMessages(transport) {
|
|
188
|
+
try {
|
|
189
|
+
const before = Reflect.get(transport, 'onmessage');
|
|
190
|
+
const handled = typeof before === 'function' ? before : undefined;
|
|
191
|
+
const observing = (message, extra) => {
|
|
192
|
+
this.observe(message);
|
|
193
|
+
handled?.(message, extra);
|
|
194
|
+
};
|
|
195
|
+
Reflect.set(transport, 'onmessage', observing);
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
// A transport that refuses it is never observed: `answersObserved` stays false.
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/** One incoming message: the `initialize` answer, or the answer to an awaited request. */
|
|
202
|
+
observe(message) {
|
|
203
|
+
const id = responseIdOf(message);
|
|
204
|
+
if (id === undefined)
|
|
205
|
+
return;
|
|
206
|
+
if (id === this.initializeId)
|
|
207
|
+
this.initializeAnswered = true;
|
|
208
|
+
const replay = this.awaiting.get(id);
|
|
209
|
+
if (replay === undefined)
|
|
210
|
+
return;
|
|
211
|
+
this.awaiting.delete(id);
|
|
212
|
+
replay.answered();
|
|
213
|
+
}
|
|
107
214
|
/**
|
|
108
215
|
* The `tools/call` request `body` carries, while its send runs — its ticket
|
|
109
216
|
* when a call issued one, and the signal its cancellation fires. `undefined`
|
|
@@ -126,44 +233,60 @@ export class RequestLedger {
|
|
|
126
233
|
return {
|
|
127
234
|
...(entry.ticket !== undefined && { ticket: entry.ticket }),
|
|
128
235
|
cancelled: entry.cut.signal,
|
|
236
|
+
replay: entry.replay,
|
|
129
237
|
};
|
|
130
238
|
}
|
|
131
239
|
/** One message through the watched transport. */
|
|
132
240
|
send(original, message, options) {
|
|
133
241
|
this.cancelIfAsked(message);
|
|
134
|
-
|
|
242
|
+
this.noteInitialize(message);
|
|
243
|
+
const id = requestIdOf(message);
|
|
135
244
|
if (id === undefined)
|
|
136
245
|
return original(message, options);
|
|
137
|
-
|
|
246
|
+
// The marker comes out before anything else: the server never sees it.
|
|
247
|
+
const taken = takeMarker(message);
|
|
248
|
+
const call = taken.marker === undefined ? undefined : this.issued.get(taken.marker);
|
|
249
|
+
// One request per marker: a second message carrying it is not this call's.
|
|
250
|
+
const matched = call !== undefined && call.request === undefined ? call : undefined;
|
|
251
|
+
if (matched === undefined && this.options.strict) {
|
|
252
|
+
return Promise.reject(new McpReplayUnavailableError('request-unmatched', this.options.server, toolNameOf(message)));
|
|
253
|
+
}
|
|
254
|
+
this.calls += 1;
|
|
255
|
+
const replay = new RequestReplay(id, this.initializeAnswered);
|
|
256
|
+
if (matched !== undefined) {
|
|
257
|
+
matched.request = { id, replay };
|
|
258
|
+
if (this.options.strict)
|
|
259
|
+
this.awaiting.set(id, replay);
|
|
260
|
+
}
|
|
261
|
+
const entry = {
|
|
262
|
+
...(matched?.ticket !== undefined && { ticket: matched.ticket }),
|
|
263
|
+
cut: new AbortController(),
|
|
264
|
+
replay,
|
|
265
|
+
};
|
|
266
|
+
this.sending.set(id, entry);
|
|
138
267
|
const release = () => {
|
|
139
268
|
if (this.sending.get(id) === entry)
|
|
140
269
|
this.sending.delete(id);
|
|
141
270
|
};
|
|
142
271
|
try {
|
|
143
|
-
return Promise.resolve(original(message, options)).finally(release);
|
|
272
|
+
return Promise.resolve(original(taken.message, options)).finally(release);
|
|
144
273
|
}
|
|
145
274
|
catch (err) {
|
|
146
275
|
release();
|
|
147
276
|
throw err;
|
|
148
277
|
}
|
|
149
278
|
}
|
|
150
|
-
/**
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
// One request per ticket: a second message reusing these params is not this call's.
|
|
160
|
-
this.issued.delete(params);
|
|
161
|
-
this.bound.add(ticket);
|
|
162
|
-
}
|
|
163
|
-
this.sending.set(id, { ...(ticket !== undefined && { ticket }), cut: new AbortController() });
|
|
164
|
-
return id;
|
|
279
|
+
/** The `initialize` request: its answer is the one that proves the observer is in place. */
|
|
280
|
+
noteInitialize(message) {
|
|
281
|
+
if (message === null || typeof message !== 'object' || Array.isArray(message))
|
|
282
|
+
return;
|
|
283
|
+
const { method, id } = message;
|
|
284
|
+
if (method !== INITIALIZE || (typeof id !== 'string' && typeof id !== 'number'))
|
|
285
|
+
return;
|
|
286
|
+
this.initializeId = id;
|
|
287
|
+
this.initializeAnswered = false;
|
|
165
288
|
}
|
|
166
|
-
/** The SDK gave a request up: stop the series still sending it. */
|
|
289
|
+
/** The SDK gave a request up: stop the series still sending it, and stop awaiting its answer. */
|
|
167
290
|
cancelIfAsked(message) {
|
|
168
291
|
if (message === null || typeof message !== 'object' || Array.isArray(message))
|
|
169
292
|
return;
|
|
@@ -174,12 +297,30 @@ export class RequestLedger {
|
|
|
174
297
|
if (typeof requestId !== 'string' && typeof requestId !== 'number')
|
|
175
298
|
return;
|
|
176
299
|
this.sending.get(requestId)?.cut.abort(sdkCancelled());
|
|
300
|
+
this.awaiting.delete(requestId);
|
|
177
301
|
}
|
|
178
302
|
}
|
|
179
303
|
/** The reason a series stops when the SDK cancelled its request — a fixed sentence. */
|
|
180
304
|
function sdkCancelled() {
|
|
181
305
|
return Object.assign(new Error('The MCP SDK cancelled this request.'), { name: 'AbortError' });
|
|
182
306
|
}
|
|
307
|
+
/** The tool a `tools/call` names — what a refusal names. Never its arguments. */
|
|
308
|
+
function toolNameOf(message) {
|
|
309
|
+
const params = message.params;
|
|
310
|
+
const name = params !== null && typeof params === 'object'
|
|
311
|
+
? params.name
|
|
312
|
+
: undefined;
|
|
313
|
+
return typeof name === 'string' ? name : 'tools/call';
|
|
314
|
+
}
|
|
315
|
+
/** The id of a JSON-RPC RESPONSE — a result or an error, never a request or a notification. */
|
|
316
|
+
function responseIdOf(message) {
|
|
317
|
+
if (message === null || typeof message !== 'object' || Array.isArray(message))
|
|
318
|
+
return undefined;
|
|
319
|
+
const fields = message;
|
|
320
|
+
if (fields.method !== undefined || !('result' in fields || 'error' in fields))
|
|
321
|
+
return undefined;
|
|
322
|
+
return typeof fields.id === 'string' || typeof fields.id === 'number' ? fields.id : undefined;
|
|
323
|
+
}
|
|
183
324
|
/** The id of a `tools/call` REQUEST — a response or a notification has none to claim. */
|
|
184
325
|
function requestIdOf(message) {
|
|
185
326
|
if (message === null || typeof message !== 'object' || Array.isArray(message))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requestLedger.js","sourceRoot":"","sources":["../../../src/mcp/requestLedger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"requestLedger.js","sourceRoot":"","sources":["../../../src/mcp/requestLedger.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,17 +28,31 @@
|
|
|
28
28
|
* timed out, or failed — was sent, and the server may have received it and run
|
|
29
29
|
* it. Its row says so (`remote: 'unknown'`); nothing here records it as not run.
|
|
30
30
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
31
|
+
* THREE FACTS PER ATTEMPT, NONE READ FROM ANOTHER (`replay.ts`): the failure
|
|
32
|
+
* (footprintjs's category), what is known of its effect (`unknown` for every
|
|
33
|
+
* attempt sent that did not complete — a refusal included; `applied` when the
|
|
34
|
+
* call completed, never proof of a write; `none` only for what was never
|
|
35
|
+
* sent), and — on an attempt the series asked again after — what permitted it.
|
|
36
|
+
* Each row also says how long it took. The end says how many requests were
|
|
37
|
+
* sent and what is known of the whole series' effect; uncertainty survives
|
|
38
|
+
* (`SeriesKnowledge`).
|
|
39
|
+
*
|
|
40
|
+
* WHEN IT FILES. When the call settles — the series has ended by then, and the
|
|
41
|
+
* call's verdict is what says whether an answered attempt completed (a 200 can
|
|
42
|
+
* carry a tool error) — and, for a cancellation, at the moment the signal
|
|
43
|
+
* fires: a cancelled run stops waiting for its stage at once, so a record filed
|
|
44
|
+
* when the series later unwinds would land after the run was saved. The runner
|
|
45
|
+
* makes no record for an attempt it abandons at that moment or for a wait it
|
|
46
|
+
* was cut out of, so those are written here: the cut attempt's row and
|
|
47
|
+
* `during: 'request'`, or `during: 'wait'`. A series ended and waiting for its
|
|
48
|
+
* call files at once if the call is cancelled first, with what it knows.
|
|
49
|
+
* Anything the series reports after it has filed is not part of the request's
|
|
50
|
+
* story any more and is ignored.
|
|
38
51
|
*/
|
|
39
52
|
import type { AttemptRecord } from 'footprintjs';
|
|
40
|
-
import type { ToolRequestAttempt, ToolRequestReason } from '../events/payloads.js';
|
|
53
|
+
import type { ToolRequestAttempt, ToolRequestEffect, ToolRequestPermission, ToolRequestReason } from '../events/payloads.js';
|
|
41
54
|
import { type RequestEvidence, type RequestEvidenceSink } from '../tools/requestEvidence.js';
|
|
55
|
+
import { type RequestReplay } from './replay.js';
|
|
42
56
|
/** Where the request went, as a row may say it: the app's label for it, or its origin. */
|
|
43
57
|
export type RequestWhere = Pick<RequestEvidence, 'endpoint' | 'origin'>;
|
|
44
58
|
/** What the series saw of one attempt that its record does not hold. */
|
|
@@ -52,24 +66,49 @@ export interface AttemptSeen {
|
|
|
52
66
|
};
|
|
53
67
|
}
|
|
54
68
|
/** Why the series' `retryOn` said no — the reasons the runner calls `declined`. */
|
|
55
|
-
export type DeclineReason = Extract<ToolRequestReason, 'exhausted' | 'wait-limit' | 'no-time-left' | 'not-replayable' | 'not-retryable'>;
|
|
69
|
+
export type DeclineReason = Extract<ToolRequestReason, 'exhausted' | 'wait-limit' | 'no-time-left' | 'not-replayable' | 'not-retryable' | 'not-permitted' | 'changes-without-key'>;
|
|
70
|
+
/**
|
|
71
|
+
* What the series knows of one attempt beyond the runner's record (`replay.ts`):
|
|
72
|
+
* its effect — absent for an answered attempt, which the call's verdict decides
|
|
73
|
+
* when the record is filed — what permitted the next attempt, and how long it
|
|
74
|
+
* took.
|
|
75
|
+
*/
|
|
76
|
+
export interface AttemptFacts {
|
|
77
|
+
readonly effect?: ToolRequestEffect;
|
|
78
|
+
readonly permission?: ToolRequestPermission;
|
|
79
|
+
readonly durationMs: number;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Where the record waits for its call: the call's signal (it fires when the
|
|
83
|
+
* call settles or is cancelled), and the facts the call leaves there.
|
|
84
|
+
*/
|
|
85
|
+
export interface Settlement {
|
|
86
|
+
readonly signal: AbortSignal;
|
|
87
|
+
readonly replay: RequestReplay;
|
|
88
|
+
}
|
|
56
89
|
/** One request's evidence, collected as its series runs and filed once. */
|
|
57
90
|
export declare class SeriesEvidence {
|
|
58
91
|
private readonly sink;
|
|
59
92
|
private readonly where;
|
|
93
|
+
private readonly settlement?;
|
|
60
94
|
private readonly rows;
|
|
61
95
|
private omitted;
|
|
62
96
|
private last;
|
|
63
97
|
private filed;
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
|
|
98
|
+
private waiting;
|
|
99
|
+
/** What is known of the series' effect, attempt by attempt — the answer's excepted. */
|
|
100
|
+
private readonly knowledge;
|
|
101
|
+
/** The answered attempt, while its effect waits for the call's verdict. */
|
|
102
|
+
private answer;
|
|
103
|
+
constructor(sink: RequestEvidenceSink, where: RequestWhere, settlement?: Settlement | undefined);
|
|
104
|
+
/** One attempt as the runner recorded it, with what the series knows of it. */
|
|
105
|
+
attempt(record: AttemptRecord, seen: AttemptSeen | undefined, declined?: DeclineReason, facts?: AttemptFacts): void;
|
|
67
106
|
/**
|
|
68
107
|
* The caller's cancellation cut attempt `n` in flight. It was sent — the
|
|
69
108
|
* server may have it, and may have run it — so it is a row, `cut`, with the
|
|
70
109
|
* remote outcome `unknown`; then the request's end says the same.
|
|
71
110
|
*/
|
|
72
|
-
cutInFlight(n: number): void;
|
|
111
|
+
cutInFlight(n: number, durationMs?: number): void;
|
|
73
112
|
/**
|
|
74
113
|
* The caller's cancellation landed with NO request in flight: between two —
|
|
75
114
|
* `during: 'wait'`, the next request never sent — or before the first, when
|
|
@@ -82,7 +121,7 @@ export declare class SeriesEvidence {
|
|
|
82
121
|
* refusal it will not ask again after. A refusal it MEANT to ask again after
|
|
83
122
|
* is delivered when the deadline lands inside the wait: the runner's wait
|
|
84
123
|
* ends early, the series stops, and the end says so (`no-time-left`, during
|
|
85
|
-
* the `wait`).
|
|
124
|
+
* the `wait`). Filed when the call has read it.
|
|
86
125
|
*/
|
|
87
126
|
delivered(): void;
|
|
88
127
|
/**
|
|
@@ -92,11 +131,30 @@ export declare class SeriesEvidence {
|
|
|
92
131
|
* as one: a deadline that had passed before the first request (`timed-out`,
|
|
93
132
|
* no `during`, nothing sent) or one a future runner reports from inside a wait
|
|
94
133
|
* (`during: 'wait'`); anything else is filed as a failure the record cannot
|
|
95
|
-
* account for, so a request is never left unfiled.
|
|
134
|
+
* account for, so a request is never left unfiled. Filed when the call settles.
|
|
96
135
|
*/
|
|
97
136
|
threw(outOfTime: boolean): void;
|
|
98
137
|
private add;
|
|
138
|
+
/**
|
|
139
|
+
* File `end` once the call has settled — its verdict is what says whether an
|
|
140
|
+
* answered attempt completed — or at once, when the call is already settled
|
|
141
|
+
* or cancelled, or there is no call to wait for.
|
|
142
|
+
*/
|
|
143
|
+
private fileWhenSettled;
|
|
99
144
|
private file;
|
|
145
|
+
/**
|
|
146
|
+
* The rows, the answered one given its effect: `applied` when the call
|
|
147
|
+
* completed — the server answered it, and not with an error — else `unknown`
|
|
148
|
+
* (a 5xx, a JSON-RPC error, a tool error, a call cancelled before it read the
|
|
149
|
+
* answer). The answer's effect joins the series' knowledge here.
|
|
150
|
+
*/
|
|
151
|
+
private settleAnswer;
|
|
100
152
|
}
|
|
101
153
|
/** One record as a row — see the module note for what a row may say. */
|
|
102
154
|
export declare function rowOf(record: AttemptRecord, seen: AttemptSeen | undefined, declined?: DeclineReason): ToolRequestAttempt;
|
|
155
|
+
/**
|
|
156
|
+
* `row` with what the series knows of its attempt beyond the record — its
|
|
157
|
+
* effect, what permitted the next attempt, how long it took. Without `facts`,
|
|
158
|
+
* the row as the record alone says it.
|
|
159
|
+
*/
|
|
160
|
+
export declare function withFacts(row: ToolRequestAttempt, facts: AttemptFacts | undefined): ToolRequestAttempt;
|