agentfootprint 11.4.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 +2 -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/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/events/payloads.d.ts +128 -27
- 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 +13 -0
- package/dist/esm/redaction/knownStrings.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/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 +13 -0
- package/dist/redaction/knownStrings.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/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/events/payloads.d.ts +128 -27
- package/dist/types/events/payloads.d.ts.map +1 -1
- 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/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/package.json +1 -1
|
@@ -2270,17 +2270,22 @@ export interface ToolsCodeRunPayload {
|
|
|
2270
2270
|
/**
|
|
2271
2271
|
* What one attempt of an MCP request came to.
|
|
2272
2272
|
*
|
|
2273
|
-
* - `'answered'` —
|
|
2274
|
-
* delivered as it came, WHATEVER its status: a 503 is `answered` with
|
|
2273
|
+
* - `'answered'` — an HTTP response arrived and no retry rule refused it. It
|
|
2274
|
+
* is delivered as it came, WHATEVER its status: a 503 is `answered` with
|
|
2275
2275
|
* `status: 503`. A response received is not an operation that succeeded,
|
|
2276
|
-
* so nothing here is called success; read `status`.
|
|
2276
|
+
* so nothing here is called success; read `status`. Nor is it the MCP
|
|
2277
|
+
* call's answer: it records the HTTP exchange. A `202 Accepted`, or a
|
|
2278
|
+
* stream that closes before the call's result, is `answered`, and the
|
|
2279
|
+
* JSON-RPC answer may still never come — the end's `mayHaveRun` says when
|
|
2280
|
+
* the call failed that way.
|
|
2277
2281
|
* - `'refused'` — a response the retry policy recognises as a refusal
|
|
2278
|
-
* (`kind`): HTTP 429, or AgentCore Runtime's session-busy reply.
|
|
2279
|
-
*
|
|
2280
|
-
*
|
|
2281
|
-
*
|
|
2282
|
+
* (`kind`): HTTP 429, or AgentCore Runtime's session-busy reply. It records
|
|
2283
|
+
* the response the server sent, not proof that nothing ran: a 429 says the
|
|
2284
|
+
* request was rate-limited, nothing more (RFC 6585 §4). `effect` says what
|
|
2285
|
+
* is known; `permission` says what allowed asking again.
|
|
2282
2286
|
* - `'failed'` — the request threw before an answer arrived (a dropped
|
|
2283
|
-
* connection, a DNS failure).
|
|
2287
|
+
* connection, a DNS failure). The server may have run it, so it is asked
|
|
2288
|
+
* again only when the app declared that for this tool (`replay`).
|
|
2284
2289
|
* - `'timed-out'` — the call's deadline (`maxElapsedMs`) cut the request
|
|
2285
2290
|
* while it was in flight.
|
|
2286
2291
|
* - `'cut'` — the call was cancelled while the request was in flight: the
|
|
@@ -2288,7 +2293,7 @@ export interface ToolsCodeRunPayload {
|
|
|
2288
2293
|
* or the call settling first. The request WAS sent; the server may already
|
|
2289
2294
|
* have received it and run it. A cut is never a "not run".
|
|
2290
2295
|
*
|
|
2291
|
-
* The last three never had
|
|
2296
|
+
* The last three never had a response, so they carry `remote: 'unknown'`.
|
|
2292
2297
|
*
|
|
2293
2298
|
* Every request the series sent is a row, or is counted in `omitted`: the rows
|
|
2294
2299
|
* and `omitted` together are the requests the series sent. A request that was
|
|
@@ -2305,7 +2310,7 @@ export type ToolRequestAttemptOutcome = 'answered' | 'refused' | 'failed' | 'tim
|
|
|
2305
2310
|
export type ToolRequestOutcome = ToolRequestAttemptOutcome | 'cancelled';
|
|
2306
2311
|
/**
|
|
2307
2312
|
* Whether the server received and ran a request, when that is not known: the
|
|
2308
|
-
* attempt ended without
|
|
2313
|
+
* attempt ended without a response (`failed`, `timed-out`, `cut`), so the
|
|
2309
2314
|
* request may have reached the server and run there, or not. The library never
|
|
2310
2315
|
* records such a request as not run.
|
|
2311
2316
|
*/
|
|
@@ -2313,24 +2318,81 @@ export type ToolRequestRemote = 'unknown';
|
|
|
2313
2318
|
/**
|
|
2314
2319
|
* Why the request went on after an attempt, or ended with it.
|
|
2315
2320
|
*
|
|
2316
|
-
* - `'retryable'` —
|
|
2317
|
-
* only reason that is not an end.
|
|
2321
|
+
* - `'retryable'` — another attempt follows after `waitMs`; `permission`
|
|
2322
|
+
* says what allowed it. The only reason that is not an end.
|
|
2318
2323
|
* - `'answered'` — answered; the response is delivered.
|
|
2319
|
-
* - `'exhausted'` —
|
|
2320
|
-
* - `'wait-limit'` —
|
|
2321
|
-
*
|
|
2322
|
-
*
|
|
2323
|
-
* - `'no-time-left'` —
|
|
2324
|
-
*
|
|
2325
|
-
* - `'not-replayable'` —
|
|
2326
|
-
* - `'not-retryable'` — the attempt failed
|
|
2327
|
-
*
|
|
2328
|
-
*
|
|
2324
|
+
* - `'exhausted'` — the request has made every attempt it may.
|
|
2325
|
+
* - `'wait-limit'` — the wait would pass the call's total waiting budget
|
|
2326
|
+
* (`maxWaitMs`). A stated `Retry-After` is never shortened to fit: the
|
|
2327
|
+
* refusal is delivered instead.
|
|
2328
|
+
* - `'no-time-left'` — the wait would pass the call's deadline; or the
|
|
2329
|
+
* deadline cut a request or a wait.
|
|
2330
|
+
* - `'not-replayable'` — the request's body cannot be sent twice.
|
|
2331
|
+
* - `'not-retryable'` — the attempt failed without an answer, and nothing
|
|
2332
|
+
* permits asking again after that failure: the app declared no repeat of
|
|
2333
|
+
* this tool on it (`replay`), or it is not a kind the series repeats.
|
|
2334
|
+
* - `'not-permitted'` — refused with a 429, and the policy in force does not
|
|
2335
|
+
* permit asking this tool again on it. Under `'app-authorized'`, only the
|
|
2336
|
+
* app's declaration does: a generic 429 does not prove the server ran
|
|
2337
|
+
* nothing.
|
|
2338
|
+
* - `'changes-without-key'` — the app declared this tool as making changes,
|
|
2339
|
+
* and the call carries no key the server is declared to deduplicate by. It
|
|
2340
|
+
* is never asked again automatically, under any policy.
|
|
2329
2341
|
* - `'cancelled'` — the caller's signal ended the request.
|
|
2330
2342
|
*/
|
|
2331
|
-
export type ToolRequestReason = 'retryable' | 'answered' | 'exhausted' | 'wait-limit' | 'no-time-left' | 'not-replayable' | 'not-retryable' | 'cancelled';
|
|
2343
|
+
export type ToolRequestReason = 'retryable' | 'answered' | 'exhausted' | 'wait-limit' | 'no-time-left' | 'not-replayable' | 'not-retryable' | 'not-permitted' | 'changes-without-key' | 'cancelled';
|
|
2332
2344
|
/** The refusals a retry rule recognises: HTTP 429, and AgentCore Runtime's session-busy reply. */
|
|
2333
2345
|
export type ToolRequestRefusalKind = 'throttle' | 'session-busy';
|
|
2346
|
+
/**
|
|
2347
|
+
* What is known about whether an attempt took effect on the server —
|
|
2348
|
+
* footprintjs's effect law (`AttemptEffect`), read for an MCP request:
|
|
2349
|
+
*
|
|
2350
|
+
* - `'none'` — it ran nothing, and that is established: the request was
|
|
2351
|
+
* never sent (an `end` whose `attempts` is `0`). No reply establishes it.
|
|
2352
|
+
* A 429 says the request was rate-limited, and AgentCore's session-busy
|
|
2353
|
+
* body is matched by its code and words — a server behind the runtime can
|
|
2354
|
+
* answer with the same error after it ran the call.
|
|
2355
|
+
* - `'unknown'` — anything sent that did not complete: a 429, a session-busy
|
|
2356
|
+
* reply, a lost connection or a timeout after the request was sent, a cut,
|
|
2357
|
+
* a 5xx, a JSON-RPC error, a tool error (one can follow a write that
|
|
2358
|
+
* succeeded).
|
|
2359
|
+
* - `'applied'` — the call completed: the server answered it, and not with
|
|
2360
|
+
* an error. It is never proof that anything was written.
|
|
2361
|
+
*/
|
|
2362
|
+
export type ToolRequestEffect = 'none' | 'unknown' | 'applied';
|
|
2363
|
+
/** The failure kinds the app may declare a tool repeatable on (`replay.tools[name].on`). */
|
|
2364
|
+
export type ToolRequestReplayKind = 'throttle' | 'network';
|
|
2365
|
+
/**
|
|
2366
|
+
* What allowed the next attempt — present exactly when `reason` is
|
|
2367
|
+
* `'retryable'`. Permission and effect are separate facts: neither is ever
|
|
2368
|
+
* read from the other.
|
|
2369
|
+
*
|
|
2370
|
+
* - `by: 'declaration'` — the app's entry for this tool names the failure
|
|
2371
|
+
* kind (`on`).
|
|
2372
|
+
* - `by: 'adapter'` — the adapter the app chose retries this refusal as its
|
|
2373
|
+
* own policy: AgentCore Runtime's session-busy reply, which AWS documents
|
|
2374
|
+
* as a retryable conflict while a session starts or stops. It says what
|
|
2375
|
+
* it assumes in doing so (`assumes`).
|
|
2376
|
+
* - `by: 'compatibility'` — the compatibility policy, today's default: it
|
|
2377
|
+
* repeats a 429 for every tool, and says what it assumes in doing so
|
|
2378
|
+
* (`assumes`).
|
|
2379
|
+
*
|
|
2380
|
+
* An assumption is a policy, never evidence: the row's `effect` stays
|
|
2381
|
+
* `'unknown'`.
|
|
2382
|
+
*/
|
|
2383
|
+
export interface ToolRequestPermission {
|
|
2384
|
+
readonly by: 'declaration' | 'adapter' | 'compatibility';
|
|
2385
|
+
/** `declaration` only — the failure kind the app's entry names. */
|
|
2386
|
+
readonly on?: ToolRequestReplayKind;
|
|
2387
|
+
/** `adapter` and `compatibility` only — what the policy assumes of the refusal it repeats. */
|
|
2388
|
+
readonly assumes?: 'refused-before-execution';
|
|
2389
|
+
/**
|
|
2390
|
+
* The app declared this tool as making changes, so it was asked again only
|
|
2391
|
+
* because the server is declared to deduplicate by a key this call carries.
|
|
2392
|
+
* The key protects only if the server uses it.
|
|
2393
|
+
*/
|
|
2394
|
+
readonly deduplicated?: true;
|
|
2395
|
+
}
|
|
2334
2396
|
/**
|
|
2335
2397
|
* footprintjs's failure categories (`AttemptCategory`) — the one fixed set
|
|
2336
2398
|
* every attempt record uses, so a saved request groups with every other.
|
|
@@ -2373,13 +2435,22 @@ export interface ToolRequestAttempt {
|
|
|
2373
2435
|
/** `failed` and `timed-out` only. */
|
|
2374
2436
|
readonly error?: ToolRequestError;
|
|
2375
2437
|
/**
|
|
2376
|
-
* `'unknown'` when the attempt ended without
|
|
2438
|
+
* `'unknown'` when the attempt ended without a response (`failed`,
|
|
2377
2439
|
* `timed-out`, `cut`): it was sent, and whether the server received and ran
|
|
2378
2440
|
* it is not known. Absent when a response arrived: the record keeps what the
|
|
2379
2441
|
* server answered (`status`) — for a `refused` attempt that is the server's
|
|
2380
2442
|
* own refusal, not proof that nothing ran.
|
|
2381
2443
|
*/
|
|
2382
2444
|
readonly remote?: ToolRequestRemote;
|
|
2445
|
+
/**
|
|
2446
|
+
* What is known about whether this attempt took effect (see
|
|
2447
|
+
* {@link ToolRequestEffect}). On every attempt the library files.
|
|
2448
|
+
*/
|
|
2449
|
+
readonly effect?: ToolRequestEffect;
|
|
2450
|
+
/** What allowed the next attempt — present exactly when `reason` is `'retryable'`. */
|
|
2451
|
+
readonly permission?: ToolRequestPermission;
|
|
2452
|
+
/** How long the attempt took, in ms, from sending to its end. On every attempt the library files. */
|
|
2453
|
+
readonly durationMs?: number;
|
|
2383
2454
|
}
|
|
2384
2455
|
/** How an MCP request ended. */
|
|
2385
2456
|
export interface ToolRequestEnd {
|
|
@@ -2406,17 +2477,47 @@ export interface ToolRequestEnd {
|
|
|
2406
2477
|
/** `failed` and `timed-out` only. */
|
|
2407
2478
|
readonly error?: ToolRequestError;
|
|
2408
2479
|
/**
|
|
2409
|
-
* `'unknown'` when the request ended on an attempt with no
|
|
2410
|
-
* `timed-out`, `cut`): whether the server ran that request is not
|
|
2480
|
+
* `'unknown'` when the request ended on an attempt with no response
|
|
2481
|
+
* (`failed`, `timed-out`, `cut`): whether the server ran that request is not
|
|
2482
|
+
* known.
|
|
2411
2483
|
*/
|
|
2412
2484
|
readonly remote?: ToolRequestRemote;
|
|
2485
|
+
/**
|
|
2486
|
+
* How many requests the series sent: `attempts.length + omitted`. On every
|
|
2487
|
+
* end the library files.
|
|
2488
|
+
*/
|
|
2489
|
+
readonly attempts?: number;
|
|
2490
|
+
/**
|
|
2491
|
+
* What is known about the series' effect as a whole. Uncertainty survives:
|
|
2492
|
+
* once any attempt's effect is `'unknown'`, so is the series' — a later
|
|
2493
|
+
* proven refusal does not resolve it, and a later success does not prove the
|
|
2494
|
+
* operation happened only once. `'applied'` only when the call completed and
|
|
2495
|
+
* no attempt's effect is unknown; `'none'` only when every attempt is proven
|
|
2496
|
+
* to have run nothing (or none was sent). On every end the library files.
|
|
2497
|
+
*/
|
|
2498
|
+
readonly effect?: ToolRequestEffect;
|
|
2499
|
+
/**
|
|
2500
|
+
* The call failed as "may have run" (footprintjs's `UnknownEffectError`, its
|
|
2501
|
+
* final error — a later refusal's, or the timeout — as the `cause`): under
|
|
2502
|
+
* the `'app-authorized'` policy, the call genuinely lacked an answer
|
|
2503
|
+
* somewhere and did not complete. Lacking an answer is not an unknown
|
|
2504
|
+
* effect: it is an attempt that got no response at all (`remote:
|
|
2505
|
+
* 'unknown'`), or a request accepted over HTTP (an `answered` 2xx) whose
|
|
2506
|
+
* JSON-RPC answer never came. A received refusal or error IS an answer —
|
|
2507
|
+
* its effect unknown, delivered as the server sent it — so a call whose
|
|
2508
|
+
* every attempt received one has no `mayHaveRun`. Absent under
|
|
2509
|
+
* `'compatibility'`, where the caller sees the error it always did, and
|
|
2510
|
+
* for a call its caller cancelled, which ends with the caller's reason.
|
|
2511
|
+
*/
|
|
2512
|
+
readonly mayHaveRun?: true;
|
|
2413
2513
|
}
|
|
2414
2514
|
/**
|
|
2415
2515
|
* What one MCP request's retry series did: every attempt it made, why it went
|
|
2416
2516
|
* on or stopped after each, how long it waited, and how the request ended.
|
|
2417
2517
|
*
|
|
2418
2518
|
* Filed by `mcpClient`'s retry series for a call the agent dispatched, ONCE per
|
|
2419
|
-
* request, when the
|
|
2519
|
+
* request, when the call settles — so the last attempt's `effect` can say
|
|
2520
|
+
* whether the call completed — and at the moment of a cancellation, so a
|
|
2420
2521
|
* run cancelled during a wait still carries it when it is saved. A call that
|
|
2421
2522
|
* settles before its series (the MCP SDK's own timeout, say) cancels the series
|
|
2422
2523
|
* there and then, inside the call, so it is never filed after its run, and no
|
|
@@ -15,35 +15,78 @@
|
|
|
15
15
|
* the call. The link is undone when the call settles: the SDK keeps its
|
|
16
16
|
* abort listener on the signal it was given, and a link that outlived the
|
|
17
17
|
* call would cancel a request that had already finished.
|
|
18
|
-
* 2. ITS
|
|
19
|
-
* the
|
|
18
|
+
* 2. ITS MARKER is issued when the connection has a ledger, with its ticket
|
|
19
|
+
* when the call carries the run's evidence port: a library-private string
|
|
20
|
+
* in the request's `_meta` (`callMarker.ts`), which ties the request to
|
|
21
|
+
* the call even when the SDK copies the params, and which the transport
|
|
22
|
+
* takes out before anything is sent.
|
|
20
23
|
* 3. ITS SETTLING ENDS ITS SERIES. However `callTool` settles — answered,
|
|
21
24
|
* failed, or given up by the SDK (its own timeout) — a retry series still
|
|
22
25
|
* sending the request is cut there and then, inside the call: it files
|
|
23
26
|
* `cancelled` before the call's result is read, and sends nothing more.
|
|
27
|
+
* 4. ITS VERDICT REACHES ITS RECORD. A series that has ended waits for the
|
|
28
|
+
* call to settle before it files, because only the call can say whether
|
|
29
|
+
* the answer completed — a 200 can carry a tool error. The call leaves its
|
|
30
|
+
* verdict in the request's shared replay facts (`replay.ts` ·
|
|
31
|
+
* `RequestReplay`) before it settles the series' wait.
|
|
32
|
+
* 5. "MAY HAVE RUN" IS RAISED HERE — footprintjs's law, under the
|
|
33
|
+
* `'app-authorized'` policy (`replay.ts` · `RequestReplay`, its
|
|
34
|
+
* `uncertain`). A received refusal or error is preserved: a 429, a 503,
|
|
35
|
+
* a JSON-RPC or tool error — or a chain in which every attempt received
|
|
36
|
+
* one — keeps the server's error as it came, its effect still `unknown`.
|
|
37
|
+
* A call that genuinely lacked an answer somewhere — an attempt with no
|
|
38
|
+
* response at all, or a request the HTTP layer accepted whose JSON-RPC
|
|
39
|
+
* answer never came — and then fails, fails with footprintjs's
|
|
40
|
+
* `UnknownEffectError`, its final error (a later refusal's, or the
|
|
41
|
+
* timeout) as the `cause`: that error alone would read as "failed, try
|
|
42
|
+
* again". A call that completes returns normally. Under `'compatibility'`
|
|
43
|
+
* the caller sees the error it always did; the record still says the
|
|
44
|
+
* effect is unknown. A cancellation never raises it: a call its caller
|
|
45
|
+
* cancelled ends with the caller's reason, as it always did.
|
|
24
46
|
*
|
|
25
|
-
* In dev mode, a ticket that no request was
|
|
26
|
-
* settled, when a `tools/call` request DID go out, is named once per
|
|
27
|
-
* the params, so the call's
|
|
28
|
-
*
|
|
29
|
-
* `notifications/cancelled`).
|
|
47
|
+
* In dev mode, a ticket that no request was matched to by the time the call
|
|
48
|
+
* settled, when a `tools/call` request DID go out, is named once per
|
|
49
|
+
* connection: the SDK rebuilt the params without the marker, so the call's
|
|
50
|
+
* attempts could not be matched to it. Its cancellation still reached the
|
|
51
|
+
* request (1, and the ledger's own watch on `notifications/cancelled`). Under
|
|
52
|
+
* `'app-authorized'` such a request is never sent at all
|
|
53
|
+
* (`replayUnavailable.ts`).
|
|
30
54
|
*/
|
|
55
|
+
import type { CallVerdict } from './replay.js';
|
|
31
56
|
import type { RequestLedger } from './requestLedger.js';
|
|
32
|
-
/** A call that has been opened: the signal its SDK request runs under, and how to close it. */
|
|
33
|
-
export interface OpenCall {
|
|
57
|
+
/** A call that has been opened: the params to send, the signal its SDK request runs under, and how to close it. */
|
|
58
|
+
export interface OpenCall<P extends object = object> {
|
|
59
|
+
/**
|
|
60
|
+
* What to hand the SDK: the call's params, with its private marker in
|
|
61
|
+
* `_meta` when a ledger watches the connection (`callMarker.ts`). The
|
|
62
|
+
* transport takes the marker out again: the server never sees it.
|
|
63
|
+
*/
|
|
64
|
+
readonly params: P;
|
|
34
65
|
/** What cancels the SDK request — absent when nothing can. */
|
|
35
66
|
readonly signal?: AbortSignal;
|
|
36
|
-
/**
|
|
37
|
-
|
|
67
|
+
/**
|
|
68
|
+
* The call failed with `error` (`verdict` says how far it got): the error it
|
|
69
|
+
* fails with — `error` itself, or, under `'app-authorized'`, footprintjs's
|
|
70
|
+
* `UnknownEffectError` with `error` as its `cause` when the call genuinely
|
|
71
|
+
* lacked an answer somewhere (see 5 above).
|
|
72
|
+
*/
|
|
73
|
+
failed(error: unknown, verdict: CallVerdict): unknown;
|
|
74
|
+
/**
|
|
75
|
+
* The call settled with `verdict`: leave it for the record, settle it in the
|
|
76
|
+
* ledger (its answer is no longer awaited), undo the link, cut a series
|
|
77
|
+
* still sending, check its request was matched.
|
|
78
|
+
*/
|
|
79
|
+
close(verdict: CallVerdict): void;
|
|
38
80
|
}
|
|
39
81
|
/**
|
|
40
82
|
* Open one call.
|
|
41
83
|
*
|
|
42
|
-
* @param params the request's params
|
|
43
|
-
* the
|
|
84
|
+
* @param params the request's params. The call sends them marked
|
|
85
|
+
* (`OpenCall.params`): the marker, not the object, is how the ledger knows
|
|
86
|
+
* the request is this call's — it survives an SDK that copies the params.
|
|
44
87
|
* @param ctx the call's context: its signal, and the run's evidence port if any.
|
|
45
88
|
* @param clientSignal the client's own `signal` (`McpClientOptions.signal`).
|
|
46
89
|
* @param ledger the connection's ledger, when the library built its transport.
|
|
47
90
|
* @param server the client's name, for the dev-mode note.
|
|
48
91
|
*/
|
|
49
|
-
export declare function openCall(params:
|
|
92
|
+
export declare function openCall<P extends object>(params: P, ctx: unknown, clientSignal: AbortSignal | undefined, ledger: RequestLedger | undefined, server: string): OpenCall<P>;
|
|
@@ -15,27 +15,53 @@
|
|
|
15
15
|
* the call. The link is undone when the call settles: the SDK keeps its
|
|
16
16
|
* abort listener on the signal it was given, and a link that outlived the
|
|
17
17
|
* call would cancel a request that had already finished.
|
|
18
|
-
* 2. ITS
|
|
19
|
-
* the
|
|
18
|
+
* 2. ITS MARKER is issued when the connection has a ledger, with its ticket
|
|
19
|
+
* when the call carries the run's evidence port: a library-private string
|
|
20
|
+
* in the request's `_meta` (`callMarker.ts`), which ties the request to
|
|
21
|
+
* the call even when the SDK copies the params, and which the transport
|
|
22
|
+
* takes out before anything is sent.
|
|
20
23
|
* 3. ITS SETTLING ENDS ITS SERIES. However `callTool` settles — answered,
|
|
21
24
|
* failed, or given up by the SDK (its own timeout) — a retry series still
|
|
22
25
|
* sending the request is cut there and then, inside the call: it files
|
|
23
26
|
* `cancelled` before the call's result is read, and sends nothing more.
|
|
27
|
+
* 4. ITS VERDICT REACHES ITS RECORD. A series that has ended waits for the
|
|
28
|
+
* call to settle before it files, because only the call can say whether
|
|
29
|
+
* the answer completed — a 200 can carry a tool error. The call leaves its
|
|
30
|
+
* verdict in the request's shared replay facts (`replay.ts` ·
|
|
31
|
+
* `RequestReplay`) before it settles the series' wait.
|
|
32
|
+
* 5. "MAY HAVE RUN" IS RAISED HERE — footprintjs's law, under the
|
|
33
|
+
* `'app-authorized'` policy (`replay.ts` · `RequestReplay`, its
|
|
34
|
+
* `uncertain`). A received refusal or error is preserved: a 429, a 503,
|
|
35
|
+
* a JSON-RPC or tool error — or a chain in which every attempt received
|
|
36
|
+
* one — keeps the server's error as it came, its effect still `unknown`.
|
|
37
|
+
* A call that genuinely lacked an answer somewhere — an attempt with no
|
|
38
|
+
* response at all, or a request the HTTP layer accepted whose JSON-RPC
|
|
39
|
+
* answer never came — and then fails, fails with footprintjs's
|
|
40
|
+
* `UnknownEffectError`, its final error (a later refusal's, or the
|
|
41
|
+
* timeout) as the `cause`: that error alone would read as "failed, try
|
|
42
|
+
* again". A call that completes returns normally. Under `'compatibility'`
|
|
43
|
+
* the caller sees the error it always did; the record still says the
|
|
44
|
+
* effect is unknown. A cancellation never raises it: a call its caller
|
|
45
|
+
* cancelled ends with the caller's reason, as it always did.
|
|
24
46
|
*
|
|
25
|
-
* In dev mode, a ticket that no request was
|
|
26
|
-
* settled, when a `tools/call` request DID go out, is named once per
|
|
27
|
-
* the params, so the call's
|
|
28
|
-
*
|
|
29
|
-
* `notifications/cancelled`).
|
|
47
|
+
* In dev mode, a ticket that no request was matched to by the time the call
|
|
48
|
+
* settled, when a `tools/call` request DID go out, is named once per
|
|
49
|
+
* connection: the SDK rebuilt the params without the marker, so the call's
|
|
50
|
+
* attempts could not be matched to it. Its cancellation still reached the
|
|
51
|
+
* request (1, and the ledger's own watch on `notifications/cancelled`). Under
|
|
52
|
+
* `'app-authorized'` such a request is never sent at all
|
|
53
|
+
* (`replayUnavailable.ts`).
|
|
30
54
|
*/
|
|
31
|
-
import { isDevMode } from 'footprintjs';
|
|
55
|
+
import { isDevMode, UnknownEffectError } from 'footprintjs';
|
|
32
56
|
import { eitherSignal, linkedController } from '../lib/abort.js';
|
|
33
57
|
import { requestEvidenceOf } from '../tools/requestEvidence.js';
|
|
58
|
+
import { markParams } from './callMarker.js';
|
|
34
59
|
/**
|
|
35
60
|
* Open one call.
|
|
36
61
|
*
|
|
37
|
-
* @param params the request's params
|
|
38
|
-
* the
|
|
62
|
+
* @param params the request's params. The call sends them marked
|
|
63
|
+
* (`OpenCall.params`): the marker, not the object, is how the ledger knows
|
|
64
|
+
* the request is this call's — it survives an SDK that copies the params.
|
|
39
65
|
* @param ctx the call's context: its signal, and the run's evidence port if any.
|
|
40
66
|
* @param clientSignal the client's own `signal` (`McpClientOptions.signal`).
|
|
41
67
|
* @param ledger the connection's ledger, when the library built its transport.
|
|
@@ -51,15 +77,37 @@ export function openCall(params, ctx, clientSignal, ledger, server) {
|
|
|
51
77
|
? undefined
|
|
52
78
|
: { sink, signal: eitherSignal(signal, settled?.signal) };
|
|
53
79
|
const sentBefore = ledger?.toolCallsSent ?? 0;
|
|
54
|
-
|
|
55
|
-
|
|
80
|
+
// Every call on a watched connection gets a marker, ticket or not: under
|
|
81
|
+
// 'app-authorized' its request must be matched to it either way. The call
|
|
82
|
+
// holds its entry, so what it reads survives the connection closing.
|
|
83
|
+
const issued = ledger?.issue(ticket);
|
|
84
|
+
let mayHaveRun = false;
|
|
56
85
|
return {
|
|
86
|
+
params: issued === undefined ? params : markParams(params, issued.marker),
|
|
57
87
|
...(signal !== undefined && { signal }),
|
|
58
|
-
|
|
88
|
+
failed: (error, verdict) => {
|
|
89
|
+
// A call its caller cancelled ends with the caller's reason, whatever its
|
|
90
|
+
// series did; the record still says what is known of its effect.
|
|
91
|
+
if (verdict === 'completed' || signal?.aborted === true)
|
|
92
|
+
return error;
|
|
93
|
+
const replay = issued?.request?.replay;
|
|
94
|
+
if (replay === undefined || !replay.uncertain)
|
|
95
|
+
return error;
|
|
96
|
+
mayHaveRun = true;
|
|
97
|
+
// The key, when one was sent, is an argument VALUE: it stays with the
|
|
98
|
+
// caller, who sent it, and never rides an error a run may record.
|
|
99
|
+
return new UnknownEffectError({ system: server, attempts: replay.sent, cause: error });
|
|
100
|
+
},
|
|
101
|
+
close: (verdict) => {
|
|
102
|
+
// The verdict first: settling the series' wait files its record.
|
|
103
|
+
issued?.request?.replay.settle(verdict, mayHaveRun);
|
|
104
|
+
// By its own entry, never the params object: a copy cannot keep a watch alive.
|
|
105
|
+
if (issued !== undefined)
|
|
106
|
+
ledger?.settle(issued);
|
|
59
107
|
settled?.abort(callSettled());
|
|
60
108
|
link?.unlink();
|
|
61
109
|
if (ticket !== undefined && ledger !== undefined) {
|
|
62
|
-
noteUnbound(ledger,
|
|
110
|
+
noteUnbound(ledger, issued?.request !== undefined, sentBefore, server);
|
|
63
111
|
}
|
|
64
112
|
},
|
|
65
113
|
};
|
|
@@ -85,15 +133,15 @@ function callSettled() {
|
|
|
85
133
|
});
|
|
86
134
|
}
|
|
87
135
|
/** Dev mode, once per connection: a request went out for this call, but the ledger never matched it. */
|
|
88
|
-
function noteUnbound(ledger,
|
|
89
|
-
if (!isDevMode() ||
|
|
136
|
+
function noteUnbound(ledger, matched, sentBefore, server) {
|
|
137
|
+
if (!isDevMode() || matched || ledger.toolCallsSent <= sentBefore)
|
|
90
138
|
return;
|
|
91
139
|
if (!ledger.firstUnbound())
|
|
92
140
|
return;
|
|
93
141
|
// eslint-disable-next-line no-console
|
|
94
142
|
console.warn(`[agentfootprint] mcpClient[${server}]: a tool call's request could not be matched to ` +
|
|
95
|
-
'the call, so its retry attempts were not recorded in the run. The MCP SDK
|
|
96
|
-
"request's
|
|
97
|
-
'cancellation still reached the request.');
|
|
143
|
+
'the call, so its retry attempts were not recorded in the run. The MCP SDK sent the ' +
|
|
144
|
+
"request without the call's `_meta` marker: it rebuilt the request's params. The call " +
|
|
145
|
+
'itself is unaffected, and its cancellation still reached the request.');
|
|
98
146
|
}
|
|
99
147
|
//# sourceMappingURL=callLifetime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"callLifetime.js","sourceRoot":"","sources":["../../../src/mcp/callLifetime.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"callLifetime.js","sourceRoot":"","sources":["../../../src/mcp/callLifetime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* callMarker — a library-private marker that ties one MCP tool call to the one
|
|
3
|
+
* request the SDK sends for it, whatever the SDK copies on the way.
|
|
4
|
+
*
|
|
5
|
+
* Pattern: mark at the call, take at the transport.
|
|
6
|
+
* Role: The correlation hop of the request ledger (`requestLedger.ts`). The
|
|
7
|
+
* call puts its marker in the request's own `_meta` bag
|
|
8
|
+
* (`markParams`); the MCP SDK carries `_meta` through to the
|
|
9
|
+
* transport — the very object, or a copy of it (`structuredClone`, a
|
|
10
|
+
* spread) — and the ledger's watched `send` takes the marker out again
|
|
11
|
+
* (`takeMarker`) before the transport serializes the request. The
|
|
12
|
+
* server receives the bytes it always did: the marker never leaves the
|
|
13
|
+
* client.
|
|
14
|
+
*
|
|
15
|
+
* An object's identity does not survive a copy; a string inside it does. So an
|
|
16
|
+
* SDK that copies the params still delivers the marker, and the request is
|
|
17
|
+
* matched to its call by the call's own word, never by guessing from content
|
|
18
|
+
* (two calls with the same arguments are the case content matching gets wrong).
|
|
19
|
+
* An SDK that rebuilds the params and drops `_meta` delivers nothing: the
|
|
20
|
+
* request then matches no call, and the ledger says so (`requestLedger.ts`).
|
|
21
|
+
*/
|
|
22
|
+
/** The `_meta` key the marker rides under. Never sent: `takeMarker` removes it. */
|
|
23
|
+
export declare const CALL_MARKER_KEY = "agentfootprint/call-ref";
|
|
24
|
+
/**
|
|
25
|
+
* `params` with `marker` added to its `_meta` bag: a new object, with every
|
|
26
|
+
* other key in its place; `params` itself is not changed. A `_meta` that was
|
|
27
|
+
* absent is added, after the other keys, so `takeMarker` can remove it whole.
|
|
28
|
+
*/
|
|
29
|
+
export declare function markParams<P extends object>(params: P, marker: string): P;
|
|
30
|
+
/** What `takeMarker` found: the marker, when the message carried one, and the message to send. */
|
|
31
|
+
export interface TakenMarker {
|
|
32
|
+
readonly marker?: string;
|
|
33
|
+
/** The message without the marker, or the message itself when it carried none. */
|
|
34
|
+
readonly message: unknown;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The marker a JSON-RPC message carries in `params._meta`, and the message
|
|
38
|
+
* without it. The message is never changed in place: the SDK's object stays
|
|
39
|
+
* the SDK's. Without the marker, the params are what they were before
|
|
40
|
+
* `markParams`: a `_meta` the marker alone filled is removed, and any other
|
|
41
|
+
* entry, the SDK's own included, keeps its place.
|
|
42
|
+
*/
|
|
43
|
+
export declare function takeMarker(message: unknown): TakenMarker;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* callMarker — a library-private marker that ties one MCP tool call to the one
|
|
3
|
+
* request the SDK sends for it, whatever the SDK copies on the way.
|
|
4
|
+
*
|
|
5
|
+
* Pattern: mark at the call, take at the transport.
|
|
6
|
+
* Role: The correlation hop of the request ledger (`requestLedger.ts`). The
|
|
7
|
+
* call puts its marker in the request's own `_meta` bag
|
|
8
|
+
* (`markParams`); the MCP SDK carries `_meta` through to the
|
|
9
|
+
* transport — the very object, or a copy of it (`structuredClone`, a
|
|
10
|
+
* spread) — and the ledger's watched `send` takes the marker out again
|
|
11
|
+
* (`takeMarker`) before the transport serializes the request. The
|
|
12
|
+
* server receives the bytes it always did: the marker never leaves the
|
|
13
|
+
* client.
|
|
14
|
+
*
|
|
15
|
+
* An object's identity does not survive a copy; a string inside it does. So an
|
|
16
|
+
* SDK that copies the params still delivers the marker, and the request is
|
|
17
|
+
* matched to its call by the call's own word, never by guessing from content
|
|
18
|
+
* (two calls with the same arguments are the case content matching gets wrong).
|
|
19
|
+
* An SDK that rebuilds the params and drops `_meta` delivers nothing: the
|
|
20
|
+
* request then matches no call, and the ledger says so (`requestLedger.ts`).
|
|
21
|
+
*/
|
|
22
|
+
/** The `_meta` key the marker rides under. Never sent: `takeMarker` removes it. */
|
|
23
|
+
export const CALL_MARKER_KEY = 'agentfootprint/call-ref';
|
|
24
|
+
/**
|
|
25
|
+
* `params` with `marker` added to its `_meta` bag: a new object, with every
|
|
26
|
+
* other key in its place; `params` itself is not changed. A `_meta` that was
|
|
27
|
+
* absent is added, after the other keys, so `takeMarker` can remove it whole.
|
|
28
|
+
*/
|
|
29
|
+
export function markParams(params, marker) {
|
|
30
|
+
const meta = recordOf(params._meta) ?? {};
|
|
31
|
+
return { ...params, _meta: { ...meta, [CALL_MARKER_KEY]: marker } };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The marker a JSON-RPC message carries in `params._meta`, and the message
|
|
35
|
+
* without it. The message is never changed in place: the SDK's object stays
|
|
36
|
+
* the SDK's. Without the marker, the params are what they were before
|
|
37
|
+
* `markParams`: a `_meta` the marker alone filled is removed, and any other
|
|
38
|
+
* entry, the SDK's own included, keeps its place.
|
|
39
|
+
*/
|
|
40
|
+
export function takeMarker(message) {
|
|
41
|
+
const fields = recordOf(message);
|
|
42
|
+
const params = recordOf(fields?.['params']);
|
|
43
|
+
const meta = recordOf(params?.['_meta']);
|
|
44
|
+
if (fields === undefined ||
|
|
45
|
+
params === undefined ||
|
|
46
|
+
meta === undefined ||
|
|
47
|
+
!Object.prototype.hasOwnProperty.call(meta, CALL_MARKER_KEY)) {
|
|
48
|
+
return { message };
|
|
49
|
+
}
|
|
50
|
+
const { [CALL_MARKER_KEY]: marker, ...rest } = meta;
|
|
51
|
+
// A copy keeps every key in its place: `_meta` is replaced where it stood, or
|
|
52
|
+
// removed when the marker alone filled it.
|
|
53
|
+
const unmarked = { ...params };
|
|
54
|
+
if (Object.keys(rest).length > 0)
|
|
55
|
+
unmarked['_meta'] = rest;
|
|
56
|
+
else
|
|
57
|
+
delete unmarked['_meta'];
|
|
58
|
+
return {
|
|
59
|
+
...(typeof marker === 'string' && { marker }),
|
|
60
|
+
message: { ...fields, params: unmarked },
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** A plain object's own fields, or `undefined` for anything else. */
|
|
64
|
+
function recordOf(value) {
|
|
65
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
66
|
+
? value
|
|
67
|
+
: undefined;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=callMarker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callMarker.js","sourceRoot":"","sources":["../../../src/mcp/callMarker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,mFAAmF;AACnF,MAAM,CAAC,MAAM,eAAe,GAAG,yBAAyB,CAAC;AAEzD;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAmB,MAAS,EAAE,MAAc;IACpE,MAAM,IAAI,GAAG,QAAQ,CAAE,MAAuC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAC5E,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;AACtE,CAAC;AASD;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,OAAgB;IACzC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACzC,IACE,MAAM,KAAK,SAAS;QACpB,MAAM,KAAK,SAAS;QACpB,IAAI,KAAK,SAAS;QAClB,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,EAC5D,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;IACD,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;IACpD,8EAA8E;IAC9E,2CAA2C;IAC3C,MAAM,QAAQ,GAA4B,EAAE,GAAG,MAAM,EAAE,CAAC;IACxD,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;;QACtD,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO;QACL,GAAG,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,EAAE,MAAM,EAAE,CAAC;QAC7C,OAAO,EAAE,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE;KACzC,CAAC;AACJ,CAAC;AAED,qEAAqE;AACrE,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACzE,CAAC,CAAE,KAA2C;QAC9C,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC"}
|
|
@@ -65,6 +65,13 @@ const BUILT_BY_THE_TRANSPORT = [
|
|
|
65
65
|
'`agentfootprint/providers`) and hand THAT to your transport — it is the same ' +
|
|
66
66
|
'implementation, applied where you build it.',
|
|
67
67
|
],
|
|
68
|
+
[
|
|
69
|
+
'replay',
|
|
70
|
+
'The replay declaration is asked by the retry series inside that transport, and a ' +
|
|
71
|
+
'connection you built has none of ours: `retryingFetch` keeps the compatibility ' +
|
|
72
|
+
'policy (a 429 retried for every tool, the assumption recorded nowhere). Pass ' +
|
|
73
|
+
'`transport` instead to have tool calls sent again only as you declare.',
|
|
74
|
+
],
|
|
68
75
|
[
|
|
69
76
|
'clientInfo',
|
|
70
77
|
'Pass it to the SDK `Client` constructor instead: `new Client(clientInfo, { capabilities: {} })`.',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectionRefusals.js","sourceRoot":"","sources":["../../../src/mcp/connectionRefusals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,0EAA0E;AAC1E,MAAM,kBAAkB,GAAG,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,CAAU,CAAC;AAEvE;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB,CACtC,IAA6C,EAC7C,IAAY;IAEZ,MAAM,EAAE,GAAG,aAAa,IAAI,GAAG,CAAC;IAChC,6EAA6E;IAC7E,6EAA6E;IAC7E,8EAA8E;IAC9E,iCAAiC;IACjC,MAAM,KAAK,GAAG,IAAoD,CAAC;IAEnE,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,SAAS,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,SAAS,EAAE,CAAC;YACvE,MAAM,IAAI,KAAK,CACb,GAAG,EAAE,kFAAkF;gBACrF,oDAAoD,CACvD,CAAC;QACJ,CAAC;QACD,OAAO;IACT,CAAC;IAED,sDAAsD;IACtD,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,sBAAsB,EAAE,CAAC;QACrD,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,GAAG,EAAE,0BAA0B,MAAM,6BAA6B;gBAChE,oEAAoE,MAAM,QAAQ;gBAClF,6DAA6D,KAAK,EAAE,CACvE,CAAC;QACJ,CAAC;IACH,CAAC;IACD,gBAAgB,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,sBAAsB,GAExB;IACF;QACE,iBAAiB;QACjB,gFAAgF;YAC9E,+EAA+E;YAC/E,6CAA6C;KAChD;IACD;QACE,YAAY;QACZ,kGAAkG;KACnG;IACD;QACE,WAAW;QACX,gGAAgG;KACjG;IACD;QACE,KAAK;QACL,+EAA+E;YAC7E,wCAAwC;KAC3C;IACD;QACE,SAAS;QACT,uFAAuF;KACxF;CACF,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,SAAS,gBAAgB,CAAC,UAAmB,EAAE,EAAU;IACvD,MAAM,OAAO,GAAG,CAAC,UAAU,IAAI,EAAE,CAAsC,CAAC;IACxE,KAAK,MAAM,MAAM,IAAI,kBAAkB,EAAE,CAAC;QACxC,IAAI,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,GAAG,EAAE,6BAA6B,MAAM,yCAAyC;gBAC/E,oFAAoF;gBACpF,kFAAkF;gBAClF,uDAAuD,CAC1D,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"connectionRefusals.js","sourceRoot":"","sources":["../../../src/mcp/connectionRefusals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,0EAA0E;AAC1E,MAAM,kBAAkB,GAAG,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,CAAU,CAAC;AAEvE;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB,CACtC,IAA6C,EAC7C,IAAY;IAEZ,MAAM,EAAE,GAAG,aAAa,IAAI,GAAG,CAAC;IAChC,6EAA6E;IAC7E,6EAA6E;IAC7E,8EAA8E;IAC9E,iCAAiC;IACjC,MAAM,KAAK,GAAG,IAAoD,CAAC;IAEnE,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,SAAS,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,SAAS,EAAE,CAAC;YACvE,MAAM,IAAI,KAAK,CACb,GAAG,EAAE,kFAAkF;gBACrF,oDAAoD,CACvD,CAAC;QACJ,CAAC;QACD,OAAO;IACT,CAAC;IAED,sDAAsD;IACtD,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,sBAAsB,EAAE,CAAC;QACrD,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,GAAG,EAAE,0BAA0B,MAAM,6BAA6B;gBAChE,oEAAoE,MAAM,QAAQ;gBAClF,6DAA6D,KAAK,EAAE,CACvE,CAAC;QACJ,CAAC;IACH,CAAC;IACD,gBAAgB,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,sBAAsB,GAExB;IACF;QACE,iBAAiB;QACjB,gFAAgF;YAC9E,+EAA+E;YAC/E,6CAA6C;KAChD;IACD;QACE,QAAQ;QACR,mFAAmF;YACjF,iFAAiF;YACjF,+EAA+E;YAC/E,wEAAwE;KAC3E;IACD;QACE,YAAY;QACZ,kGAAkG;KACnG;IACD;QACE,WAAW;QACX,gGAAgG;KACjG;IACD;QACE,KAAK;QACL,+EAA+E;YAC7E,wCAAwC;KAC3C;IACD;QACE,SAAS;QACT,uFAAuF;KACxF;CACF,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,SAAS,gBAAgB,CAAC,UAAmB,EAAE,EAAU;IACvD,MAAM,OAAO,GAAG,CAAC,UAAU,IAAI,EAAE,CAAsC,CAAC;IACxE,KAAK,MAAM,MAAM,IAAI,kBAAkB,EAAE,CAAC;QACxC,IAAI,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,GAAG,EAAE,6BAA6B,MAAM,yCAAyC;gBAC/E,oFAAoF;gBACpF,kFAAkF;gBAClF,uDAAuD,CAC1D,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/dist/esm/mcp/index.d.ts
CHANGED
|
@@ -11,4 +11,6 @@ export { mockMcpClient, type MockMcpClientOptions, type MockMcpTool } from './mo
|
|
|
11
11
|
export { gatewayTransport, GatewayAuthorizationRequiredError, type GatewayTransportOptions, } from './gatewayTransport.js';
|
|
12
12
|
export { retryingFetch } from './throttleRetry.js';
|
|
13
13
|
export type { RetryOnThrottle, ThrottleFetch, ThrottleRetryInfo, ThrottleRetryOptions, } from './throttleRetry.js';
|
|
14
|
+
export type { McpReplayDeduplication, McpReplayKind, McpReplayOptions, McpReplayPolicy, McpReplayTool, } from './replay.js';
|
|
15
|
+
export { McpReplayUnavailableError, type McpReplayUnavailableReason } from './replayUnavailable.js';
|
|
14
16
|
export type { McpCallToolResult, McpClient, McpClientOptions, McpConnection, McpConnectionOptions, McpSdk, McpGatewayTransport, McpHttpTransport, McpStdioTransport, McpTransport, McpSdkClient, McpServeOptions, McpServeHandle, McpServeTransport, McpHttpServeTransport, McpStdioServeTransport, McpSdkServer, } from './types.js';
|
package/dist/esm/mcp/index.js
CHANGED
|
@@ -15,4 +15,7 @@ export { gatewayTransport, GatewayAuthorizationRequiredError, } from './gatewayT
|
|
|
15
15
|
// 9.81.0 so the `connection` arm, which builds no transport of its own, can
|
|
16
16
|
// apply the SAME implementation instead of silently going without it.
|
|
17
17
|
export { retryingFetch } from './throttleRetry.js';
|
|
18
|
+
// A call under 'app-authorized' that a connection cannot honour is refused
|
|
19
|
+
// before it is sent, with a typed reason.
|
|
20
|
+
export { McpReplayUnavailableError } from './replayUnavailable.js';
|
|
18
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,8EAA8E;AAC9E,0EAA0E;AAC1E,OAAO,EAAE,mBAAmB,EAAsB,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAA+C,MAAM,oBAAoB,CAAC;AAChG,OAAO,EACL,gBAAgB,EAChB,iCAAiC,GAElC,MAAM,uBAAuB,CAAC;AAC/B,6EAA6E;AAC7E,4EAA4E;AAC5E,sEAAsE;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,8EAA8E;AAC9E,0EAA0E;AAC1E,OAAO,EAAE,mBAAmB,EAAsB,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAA+C,MAAM,oBAAoB,CAAC;AAChG,OAAO,EACL,gBAAgB,EAChB,iCAAiC,GAElC,MAAM,uBAAuB,CAAC;AAC/B,6EAA6E;AAC7E,4EAA4E;AAC5E,sEAAsE;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAgBnD,2EAA2E;AAC3E,0CAA0C;AAC1C,OAAO,EAAE,yBAAyB,EAAmC,MAAM,wBAAwB,CAAC"}
|