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