@animalabs/agent-framework 0.32.0 → 0.34.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/README.md +340 -22
- package/dist/src/admission/admit.d.ts +18 -0
- package/dist/src/admission/admit.d.ts.map +1 -1
- package/dist/src/admission/admit.js +16 -3
- package/dist/src/admission/admit.js.map +1 -1
- package/dist/src/agent.d.ts +208 -80
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +345 -113
- package/dist/src/agent.js.map +1 -1
- package/dist/src/api/mcp-server-core.d.ts.map +1 -1
- package/dist/src/api/mcp-server-core.js +50 -12
- package/dist/src/api/mcp-server-core.js.map +1 -1
- package/dist/src/api/server.d.ts.map +1 -1
- package/dist/src/api/server.js +4 -20
- package/dist/src/api/server.js.map +1 -1
- package/dist/src/append-all.d.ts +5 -0
- package/dist/src/append-all.d.ts.map +1 -0
- package/dist/src/append-all.js +8 -0
- package/dist/src/append-all.js.map +1 -0
- package/dist/src/code-execution/isolate/scripts.d.ts +12 -8
- package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -1
- package/dist/src/code-execution/isolate/scripts.js +24 -0
- package/dist/src/code-execution/isolate/scripts.js.map +1 -1
- package/dist/src/config-checks.d.ts +7 -0
- package/dist/src/config-checks.d.ts.map +1 -1
- package/dist/src/config-checks.js +14 -0
- package/dist/src/config-checks.js.map +1 -1
- package/dist/src/context-manager-errors.d.ts +25 -0
- package/dist/src/context-manager-errors.d.ts.map +1 -0
- package/dist/src/context-manager-errors.js +31 -0
- package/dist/src/context-manager-errors.js.map +1 -0
- package/dist/src/context-options.d.ts +70 -0
- package/dist/src/context-options.d.ts.map +1 -0
- package/dist/src/context-options.js +90 -0
- package/dist/src/context-options.js.map +1 -0
- package/dist/src/cut-off-round.js +4 -4
- package/dist/src/deferred-import.d.ts +93 -0
- package/dist/src/deferred-import.d.ts.map +1 -0
- package/dist/src/deferred-import.js +177 -0
- package/dist/src/deferred-import.js.map +1 -0
- package/dist/src/dendrite/audience.d.ts +223 -0
- package/dist/src/dendrite/audience.d.ts.map +1 -0
- package/dist/src/dendrite/audience.js +202 -0
- package/dist/src/dendrite/audience.js.map +1 -0
- package/dist/src/dendrite/index.d.ts +5 -3
- package/dist/src/dendrite/index.d.ts.map +1 -1
- package/dist/src/dendrite/index.js +2 -1
- package/dist/src/dendrite/index.js.map +1 -1
- package/dist/src/dendrite/presets.d.ts +10 -5
- package/dist/src/dendrite/presets.d.ts.map +1 -1
- package/dist/src/dendrite/presets.js +17 -5
- package/dist/src/dendrite/presets.js.map +1 -1
- package/dist/src/dendrite/registry.d.ts +62 -7
- package/dist/src/dendrite/registry.d.ts.map +1 -1
- package/dist/src/dendrite/registry.js +183 -12
- package/dist/src/dendrite/registry.js.map +1 -1
- package/dist/src/dendrite/types.d.ts +91 -8
- package/dist/src/dendrite/types.d.ts.map +1 -1
- package/dist/src/failure-text.d.ts +36 -0
- package/dist/src/failure-text.d.ts.map +1 -0
- package/dist/src/failure-text.js +89 -0
- package/dist/src/failure-text.js.map +1 -0
- package/dist/src/foreign-rounds.d.ts +69 -0
- package/dist/src/foreign-rounds.d.ts.map +1 -0
- package/dist/src/foreign-rounds.js +152 -0
- package/dist/src/foreign-rounds.js.map +1 -0
- package/dist/src/framework.d.ts +2064 -842
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +8586 -3739
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts +125 -21
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +487 -72
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/gate/index.d.ts +1 -1
- package/dist/src/gate/index.d.ts.map +1 -1
- package/dist/src/gate/index.js.map +1 -1
- package/dist/src/gate/reply-judge.d.ts +4 -0
- package/dist/src/gate/reply-judge.d.ts.map +1 -1
- package/dist/src/gate/reply-judge.js +12 -3
- package/dist/src/gate/reply-judge.js.map +1 -1
- package/dist/src/gate/rule-scope.d.ts +30 -0
- package/dist/src/gate/rule-scope.d.ts.map +1 -0
- package/dist/src/gate/rule-scope.js +41 -0
- package/dist/src/gate/rule-scope.js.map +1 -0
- package/dist/src/gate/suppress-script-worker.d.ts +2 -0
- package/dist/src/gate/suppress-script-worker.d.ts.map +1 -0
- package/dist/src/gate/suppress-script-worker.js +103 -0
- package/dist/src/gate/suppress-script-worker.js.map +1 -0
- package/dist/src/gate/suppress-scripts.d.ts +105 -0
- package/dist/src/gate/suppress-scripts.d.ts.map +1 -0
- package/dist/src/gate/suppress-scripts.js +403 -0
- package/dist/src/gate/suppress-scripts.js.map +1 -0
- package/dist/src/gate/suppression-review.d.ts +143 -0
- package/dist/src/gate/suppression-review.d.ts.map +1 -0
- package/dist/src/gate/suppression-review.js +463 -0
- package/dist/src/gate/suppression-review.js.map +1 -0
- package/dist/src/gate/suppression-stats.d.ts +125 -0
- package/dist/src/gate/suppression-stats.d.ts.map +1 -0
- package/dist/src/gate/suppression-stats.js +214 -0
- package/dist/src/gate/suppression-stats.js.map +1 -0
- package/dist/src/gate/types.d.ts +142 -7
- package/dist/src/gate/types.d.ts.map +1 -1
- package/dist/src/gate/wake-onboarding.d.ts +119 -0
- package/dist/src/gate/wake-onboarding.d.ts.map +1 -0
- package/dist/src/gate/wake-onboarding.js +277 -0
- package/dist/src/gate/wake-onboarding.js.map +1 -0
- package/dist/src/heartbeat/heartbeat.js +1 -1
- package/dist/src/heartbeat/heartbeat.js.map +1 -1
- package/dist/src/held-writes.d.ts +31 -23
- package/dist/src/held-writes.d.ts.map +1 -1
- package/dist/src/held-writes.js +44 -59
- package/dist/src/held-writes.js.map +1 -1
- package/dist/src/index.d.ts +6 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/inference-bounds.d.ts +2 -1
- package/dist/src/inference-bounds.d.ts.map +1 -1
- package/dist/src/inference-bounds.js +9 -6
- package/dist/src/inference-bounds.js.map +1 -1
- package/dist/src/jsonrpc-envelope.d.ts +69 -0
- package/dist/src/jsonrpc-envelope.d.ts.map +1 -0
- package/dist/src/jsonrpc-envelope.js +66 -0
- package/dist/src/jsonrpc-envelope.js.map +1 -0
- package/dist/src/mcpl/channel-registry.d.ts +188 -28
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +426 -70
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/checkpoint-manager.d.ts +2 -4
- package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
- package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
- package/dist/src/mcpl/feature-set-manager.d.ts +2 -4
- package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -1
- package/dist/src/mcpl/feature-set-manager.js.map +1 -1
- package/dist/src/mcpl/inbound-source.d.ts +2 -1
- package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
- package/dist/src/mcpl/inbound-source.js +2 -1
- package/dist/src/mcpl/inbound-source.js.map +1 -1
- package/dist/src/mcpl/inference-router.d.ts +6 -6
- package/dist/src/mcpl/inference-router.d.ts.map +1 -1
- package/dist/src/mcpl/inference-router.js.map +1 -1
- package/dist/src/mcpl/modern-connection.d.ts +109 -15
- package/dist/src/mcpl/modern-connection.d.ts.map +1 -1
- package/dist/src/mcpl/modern-connection.js +593 -86
- package/dist/src/mcpl/modern-connection.js.map +1 -1
- package/dist/src/mcpl/protocol-family.d.ts +3 -1
- package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
- package/dist/src/mcpl/protocol-family.js +15 -9
- package/dist/src/mcpl/protocol-family.js.map +1 -1
- package/dist/src/mcpl/push-coalescer.d.ts +132 -22
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
- package/dist/src/mcpl/push-coalescer.js +105 -15
- package/dist/src/mcpl/push-coalescer.js.map +1 -1
- package/dist/src/mcpl/push-handler.d.ts +9 -7
- package/dist/src/mcpl/push-handler.d.ts.map +1 -1
- package/dist/src/mcpl/push-handler.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +50 -28
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +165 -72
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/tool-classes.d.ts.map +1 -1
- package/dist/src/mcpl/tool-classes.js +3 -0
- package/dist/src/mcpl/tool-classes.js.map +1 -1
- package/dist/src/mcpl/tool-presence.d.ts.map +1 -1
- package/dist/src/mcpl/tool-presence.js +10 -6
- package/dist/src/mcpl/tool-presence.js.map +1 -1
- package/dist/src/mcpl/toolset-host.d.ts.map +1 -1
- package/dist/src/mcpl/toolset-host.js +7 -6
- package/dist/src/mcpl/toolset-host.js.map +1 -1
- package/dist/src/mcpl/toolsets-module.d.ts.map +1 -1
- package/dist/src/mcpl/toolsets-module.js +2 -1
- package/dist/src/mcpl/toolsets-module.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +33 -6
- package/dist/src/mcpl/types.d.ts.map +1 -1
- package/dist/src/mcpl/types.js.map +1 -1
- package/dist/src/module-registry.d.ts +24 -1
- package/dist/src/module-registry.d.ts.map +1 -1
- package/dist/src/module-registry.js +68 -18
- package/dist/src/module-registry.js.map +1 -1
- package/dist/src/modules/discord/index.d.ts +45 -8
- package/dist/src/modules/discord/index.d.ts.map +1 -1
- package/dist/src/modules/discord/index.js +238 -87
- package/dist/src/modules/discord/index.js.map +1 -1
- package/dist/src/modules/health/index.js +2 -2
- package/dist/src/modules/health/index.js.map +1 -1
- package/dist/src/modules/history/index.d.ts +59 -0
- package/dist/src/modules/history/index.d.ts.map +1 -1
- package/dist/src/modules/history/index.js +432 -67
- package/dist/src/modules/history/index.js.map +1 -1
- package/dist/src/modules/history/semantic.d.ts +6 -5
- package/dist/src/modules/history/semantic.d.ts.map +1 -1
- package/dist/src/modules/history/semantic.js +18 -25
- package/dist/src/modules/history/semantic.js.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.d.ts +1 -1
- package/dist/src/modules/workspace/disk-agreement.js +1 -1
- package/dist/src/modules/workspace/index.d.ts +28 -7
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +80 -25
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/observe.d.ts.map +1 -1
- package/dist/src/modules/workspace/observe.js +2 -1
- package/dist/src/modules/workspace/observe.js.map +1 -1
- package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
- package/dist/src/modules/workspace/reconcile.js +3 -2
- package/dist/src/modules/workspace/reconcile.js.map +1 -1
- package/dist/src/notice-tags.d.ts +20 -9
- package/dist/src/notice-tags.d.ts.map +1 -1
- package/dist/src/notice-tags.js +20 -9
- package/dist/src/notice-tags.js.map +1 -1
- package/dist/src/operator-log.d.ts +36 -3
- package/dist/src/operator-log.d.ts.map +1 -1
- package/dist/src/operator-log.js +2 -2
- package/dist/src/operator-log.js.map +1 -1
- package/dist/src/presentation.d.ts +747 -0
- package/dist/src/presentation.d.ts.map +1 -0
- package/dist/src/presentation.js +1437 -0
- package/dist/src/presentation.js.map +1 -0
- package/dist/src/prose-drafts.d.ts +15 -11
- package/dist/src/prose-drafts.d.ts.map +1 -1
- package/dist/src/prose-drafts.js +16 -12
- package/dist/src/prose-drafts.js.map +1 -1
- package/dist/src/read-marks.d.ts +192 -0
- package/dist/src/read-marks.d.ts.map +1 -0
- package/dist/src/read-marks.js +242 -0
- package/dist/src/read-marks.js.map +1 -0
- package/dist/src/reasoning-loss.d.ts +5 -0
- package/dist/src/reasoning-loss.d.ts.map +1 -0
- package/dist/src/reasoning-loss.js +8 -0
- package/dist/src/reasoning-loss.js.map +1 -0
- package/dist/src/recovery/offline-branch.d.ts +91 -6
- package/dist/src/recovery/offline-branch.d.ts.map +1 -1
- package/dist/src/recovery/offline-branch.js +277 -32
- package/dist/src/recovery/offline-branch.js.map +1 -1
- package/dist/src/recovery/recover-cli.js +24 -4
- package/dist/src/recovery/recover-cli.js.map +1 -1
- package/dist/src/send-tools.d.ts +5 -9
- package/dist/src/send-tools.d.ts.map +1 -1
- package/dist/src/send-tools.js +40 -7
- package/dist/src/send-tools.js.map +1 -1
- package/dist/src/sent-rows.js +1 -1
- package/dist/src/stored-injections.d.ts +2 -2
- package/dist/src/stored-injections.js +2 -2
- package/dist/src/stored-removal.d.ts +17 -4
- package/dist/src/stored-removal.d.ts.map +1 -1
- package/dist/src/stored-removal.js +29 -5
- package/dist/src/stored-removal.js.map +1 -1
- package/dist/src/supplied-text.d.ts +1 -1
- package/dist/src/supplied-text.js +3 -3
- package/dist/src/supplied-text.js.map +1 -1
- package/dist/src/thinking-drops.d.ts +2 -0
- package/dist/src/thinking-drops.d.ts.map +1 -1
- package/dist/src/thinking-drops.js.map +1 -1
- package/dist/src/tool-presentation.d.ts.map +1 -1
- package/dist/src/tool-presentation.js +38 -9
- package/dist/src/tool-presentation.js.map +1 -1
- package/dist/src/tool-result-guard.d.ts +12 -1
- package/dist/src/tool-result-guard.d.ts.map +1 -1
- package/dist/src/tool-result-guard.js +42 -8
- package/dist/src/tool-result-guard.js.map +1 -1
- package/dist/src/tune-out/coordinator.d.ts +1170 -81
- package/dist/src/tune-out/coordinator.d.ts.map +1 -1
- package/dist/src/tune-out/coordinator.js +3732 -369
- package/dist/src/tune-out/coordinator.js.map +1 -1
- package/dist/src/tune-out/tools.d.ts +114 -17
- package/dist/src/tune-out/tools.d.ts.map +1 -1
- package/dist/src/tune-out/tools.js +89 -28
- package/dist/src/tune-out/tools.js.map +1 -1
- package/dist/src/tune-out/window-anchor.d.ts +143 -0
- package/dist/src/tune-out/window-anchor.d.ts.map +1 -0
- package/dist/src/tune-out/window-anchor.js +202 -0
- package/dist/src/tune-out/window-anchor.js.map +1 -0
- package/dist/src/types/agent.d.ts +121 -25
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/events.d.ts +2 -0
- package/dist/src/types/events.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +72 -17
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/inference-log.d.ts +1 -0
- package/dist/src/types/inference-log.d.ts.map +1 -1
- package/dist/src/types/module.d.ts +180 -69
- package/dist/src/types/module.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +573 -39
- package/dist/src/types/trace.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/admission/admit.ts +32 -3
- package/src/agent.ts +392 -132
- package/src/api/mcp-server-core.ts +54 -17
- package/src/api/server.ts +4 -23
- package/src/append-all.ts +6 -0
- package/src/code-execution/isolate/scripts.ts +28 -3
- package/src/config-checks.ts +14 -0
- package/src/context-manager-errors.ts +37 -0
- package/src/context-options.ts +106 -0
- package/src/cut-off-round.ts +4 -4
- package/src/deferred-import.ts +239 -0
- package/src/dendrite/audience.ts +315 -0
- package/src/dendrite/index.ts +14 -2
- package/src/dendrite/presets.ts +18 -6
- package/src/dendrite/registry.ts +213 -14
- package/src/dendrite/types.ts +92 -8
- package/src/failure-text.ts +88 -0
- package/src/foreign-rounds.ts +199 -0
- package/src/framework.ts +8796 -3813
- package/src/gate/event-gate.ts +518 -91
- package/src/gate/index.ts +3 -0
- package/src/gate/reply-judge.ts +12 -3
- package/src/gate/rule-scope.ts +45 -0
- package/src/gate/suppress-script-worker.ts +89 -0
- package/src/gate/suppress-scripts.ts +414 -0
- package/src/gate/suppression-review.ts +517 -0
- package/src/gate/suppression-stats.ts +314 -0
- package/src/gate/types.ts +148 -7
- package/src/gate/wake-onboarding.ts +309 -0
- package/src/heartbeat/heartbeat.ts +1 -1
- package/src/held-writes.ts +49 -60
- package/src/index.ts +10 -2
- package/src/inference-bounds.ts +11 -6
- package/src/jsonrpc-envelope.ts +81 -0
- package/src/mcpl/channel-registry.ts +513 -116
- package/src/mcpl/checkpoint-manager.ts +3 -2
- package/src/mcpl/feature-set-manager.ts +2 -1
- package/src/mcpl/inbound-source.ts +2 -1
- package/src/mcpl/inference-router.ts +7 -4
- package/src/mcpl/modern-connection.ts +629 -91
- package/src/mcpl/protocol-family.ts +15 -9
- package/src/mcpl/push-coalescer.ts +193 -34
- package/src/mcpl/push-handler.ts +10 -5
- package/src/mcpl/server-connection.ts +169 -75
- package/src/mcpl/tool-classes.ts +3 -0
- package/src/mcpl/tool-presence.ts +10 -5
- package/src/mcpl/toolset-host.ts +7 -6
- package/src/mcpl/toolsets-module.ts +2 -1
- package/src/mcpl/types.ts +33 -6
- package/src/module-registry.ts +73 -17
- package/src/modules/discord/index.ts +230 -82
- package/src/modules/health/index.ts +2 -2
- package/src/modules/history/index.ts +439 -70
- package/src/modules/history/semantic.ts +18 -24
- package/src/modules/workspace/disk-agreement.ts +1 -1
- package/src/modules/workspace/index.ts +89 -26
- package/src/modules/workspace/observe.ts +2 -1
- package/src/modules/workspace/reconcile.ts +3 -2
- package/src/notice-tags.ts +21 -9
- package/src/operator-log.ts +36 -3
- package/src/presentation.ts +1678 -0
- package/src/prose-drafts.ts +16 -12
- package/src/read-marks.ts +328 -0
- package/src/reasoning-loss.ts +7 -0
- package/src/recovery/offline-branch.ts +350 -35
- package/src/recovery/recover-cli.ts +23 -4
- package/src/send-tools.ts +40 -7
- package/src/sent-rows.ts +1 -1
- package/src/stored-injections.ts +2 -2
- package/src/stored-removal.ts +31 -7
- package/src/supplied-text.ts +3 -3
- package/src/thinking-drops.ts +2 -0
- package/src/tool-presentation.ts +34 -9
- package/src/tool-result-guard.ts +41 -7
- package/src/tune-out/coordinator.ts +4121 -472
- package/src/tune-out/tools.ts +162 -44
- package/src/tune-out/window-anchor.ts +277 -0
- package/src/types/agent.ts +122 -25
- package/src/types/events.ts +2 -0
- package/src/types/framework.ts +73 -17
- package/src/types/inference-log.ts +1 -0
- package/src/types/module.ts +181 -68
- package/src/types/trace.ts +607 -43
|
@@ -14,6 +14,7 @@ import { maskNegotiatedCapabilities } from './capability-mask.js';
|
|
|
14
14
|
import { CapabilityGrant, expandAdvertisementShorthand } from './capability-grant.js';
|
|
15
15
|
import { CAPABILITY_DISABLED, boundedForLog, describeCause } from './errors.js';
|
|
16
16
|
import { logDetail, logValue, logValueRedacted, loggedCode } from './log-value.js';
|
|
17
|
+
import { jsonKind, readEnvelope } from '../jsonrpc-envelope.js';
|
|
17
18
|
import { LEGACY_MCP_PROTOCOL_VERSION, MODERN_MCP_PROTOCOL_VERSION, checkServerConfig, logDroppedLine, redactServerText, redactedData, serverTextRedactor, } from './protocol-family.js';
|
|
18
19
|
import { McplMethod } from './types.js';
|
|
19
20
|
/** Timeout for the initialize handshake in milliseconds.
|
|
@@ -79,20 +80,27 @@ const UNSUPPORTED_PROTOCOL_VERSION_CODE = -32022;
|
|
|
79
80
|
* end. Generous: real inventories fit in a handful of pages. */
|
|
80
81
|
const MAX_TOOL_LIST_PAGES = 100;
|
|
81
82
|
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* revision
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
83
|
+
* This engine and the server could not negotiate a protocol revision, so the
|
|
84
|
+
* connect that throws it established no connection. Usually they share none. Over HTTP it
|
|
85
|
+
* can also be the SDK's own refusal: after a -32022 whose list names a
|
|
86
|
+
* revision from 2026-07-28 on that this client doesn't speak, the SDK
|
|
87
|
+
* negotiates no further, even when the list also names a 2025 revision both
|
|
88
|
+
* speak. This is a protocol-negotiation fact, not a request outcome.
|
|
89
|
+
* Retrying cannot change it: each engine offers the same revisions every
|
|
90
|
+
* time (`offeredRevisions`), and only configuration, or the server's
|
|
91
|
+
* operator, can fix the mismatch. A connection that gets this error does not
|
|
92
|
+
* schedule reconnects. The legacy engine and the modern one
|
|
93
|
+
* (ModernMcpConnection) both throw it, so its readers treat them alike.
|
|
89
94
|
*
|
|
90
|
-
* - `rejected`: the server refused the offered
|
|
91
|
-
* `initialize` answered with error -32022
|
|
92
|
-
* or error
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
95
|
+
* - `rejected`: the server refused the revision offered. The legacy
|
|
96
|
+
* engine's `initialize` was answered with error -32022. A modern server's
|
|
97
|
+
* discovery or -32022 error named no revision in common (over HTTP, a
|
|
98
|
+
* discovery's list counts once the server has refused the `initialize`
|
|
99
|
+
* tried after it too), or, over HTTP, named one this client doesn't speak,
|
|
100
|
+
* as above. `supported` is the server's own list, when it gave one.
|
|
101
|
+
* - `mismatch`: the server answered `initialize` with a revision that
|
|
102
|
+
* handshake doesn't accept, or with none: the legacy engine's, or a modern
|
|
103
|
+
* connection's 2025 handshake over HTTP.
|
|
96
104
|
*/
|
|
97
105
|
export class McplProtocolVersionError extends Error {
|
|
98
106
|
kind;
|
|
@@ -101,6 +109,7 @@ export class McplProtocolVersionError extends Error {
|
|
|
101
109
|
code;
|
|
102
110
|
data;
|
|
103
111
|
offered;
|
|
112
|
+
offeredRevisions;
|
|
104
113
|
constructor(message, kind,
|
|
105
114
|
/** Revision the server answered with (`mismatch`; null when it gave
|
|
106
115
|
* none), redacted as the server's words are. */
|
|
@@ -110,9 +119,15 @@ export class McplProtocolVersionError extends Error {
|
|
|
110
119
|
/** The JSON-RPC error's code, and its data with each string in it
|
|
111
120
|
* redacted (`rejected`). */
|
|
112
121
|
code, data,
|
|
113
|
-
/** The revision this client offered
|
|
114
|
-
* modern connection's
|
|
115
|
-
|
|
122
|
+
/** The revision this client offered first, in its order of preference:
|
|
123
|
+
* the legacy engine's (2024-11-05), a modern connection's over stdio
|
|
124
|
+
* (2026-07-28), or over HTTP 2026-07-28, the first of
|
|
125
|
+
* `offeredRevisions`. */
|
|
126
|
+
offered = MCP_PROTOCOL_VERSION,
|
|
127
|
+
/** Every revision this client offered, in its order of preference: the
|
|
128
|
+
* legacy engine's one, a modern connection's one over stdio, or its
|
|
129
|
+
* list over HTTP. */
|
|
130
|
+
offeredRevisions = [offered]) {
|
|
116
131
|
super(message);
|
|
117
132
|
this.kind = kind;
|
|
118
133
|
this.returned = returned;
|
|
@@ -120,6 +135,7 @@ export class McplProtocolVersionError extends Error {
|
|
|
120
135
|
this.code = code;
|
|
121
136
|
this.data = data;
|
|
122
137
|
this.offered = offered;
|
|
138
|
+
this.offeredRevisions = offeredRevisions;
|
|
123
139
|
this.name = 'McplProtocolVersionError';
|
|
124
140
|
}
|
|
125
141
|
}
|
|
@@ -239,11 +255,27 @@ export class McplRequestError extends Error {
|
|
|
239
255
|
this.name = 'McplRequestError';
|
|
240
256
|
}
|
|
241
257
|
}
|
|
242
|
-
/**
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
258
|
+
/** Whether a response that can't be matched to a request of ours, its id
|
|
259
|
+
* being neither a string nor a number or missing, is logged: only a
|
|
260
|
+
* JSON-RPC 2.0 error is, since that's how a server says it couldn't read a
|
|
261
|
+
* message of ours (JSON-RPC 2.0 §5). Anything else id-less, such as a
|
|
262
|
+
* server's own JSON log line with `"id": null`, is ignored silently, as it
|
|
263
|
+
* was before #475, so a server's log output can't fill the host's. */
|
|
264
|
+
function isJsonRpcError(response) {
|
|
265
|
+
return response.jsonrpc === '2.0' && Object.hasOwn(response, 'error');
|
|
266
|
+
}
|
|
267
|
+
/** The log line for such an error. The host's own request ids are numbers,
|
|
268
|
+
* so it can't be matched to one. Once connected it may be the answer to a
|
|
269
|
+
* request of ours, which gets nothing from it and ends as any unanswered
|
|
270
|
+
* request does, by its timeout where it has one. (During the handshake an
|
|
271
|
+
* error with id null or no id answers initialize.) Its error member is the
|
|
272
|
+
* server's text, whatever JSON value it is, so it's printed redacted with
|
|
273
|
+
* `redact`, the server's redaction (logValueRedacted), as handleResponse
|
|
274
|
+
* prints a matched error's code and message. */
|
|
275
|
+
function unmatchedResponse(serverId, response, redact) {
|
|
276
|
+
const which = Object.hasOwn(response, 'id') ? `whose id is ${jsonKind(response.id)}` : 'with no id';
|
|
277
|
+
return `[mcpl] ${serverId}: ignored a response ${which}, which can't be matched to a request of ours; ` +
|
|
278
|
+
`its error: ${logValueRedacted(response.error, redact)}`;
|
|
247
279
|
}
|
|
248
280
|
/**
|
|
249
281
|
* McplServerConnection manages a single JSON-RPC 2.0 connection to an
|
|
@@ -542,13 +574,14 @@ export class McplServerConnection extends EventEmitter {
|
|
|
542
574
|
// Reconnect state (adapted from Anarchid/agent-framework@mcpl-module-proto)
|
|
543
575
|
config = null;
|
|
544
576
|
/** The redactor of the server's text for `config`, made at its first error
|
|
545
|
-
* answer, by when `config`
|
|
546
|
-
*
|
|
547
|
-
*
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
* something new
|
|
577
|
+
* answer or response it can't match (handleResponse), by when `config`
|
|
578
|
+
* is set, and kept: a framework-launched child's `env` is a getter that
|
|
579
|
+
* reads the awareness ledger, so a redactor built per answer would read
|
|
580
|
+
* it per answer (#540's review, R1-2). An answer takes one build of it
|
|
581
|
+
* for its words, data and log line (`now()`), so it reads the ledger at
|
|
582
|
+
* most once. It builds again only after a build that failed, which
|
|
583
|
+
* withholds that answer's text, or once a dial notes something new
|
|
584
|
+
* (serverTextRedactor). */
|
|
552
585
|
redactor = null;
|
|
553
586
|
hostCapabilities = null;
|
|
554
587
|
reconnectEnabled = false;
|
|
@@ -1154,16 +1187,36 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1154
1187
|
// initialize response, whatever its id: a server's own ids can start
|
|
1155
1188
|
// at 0, this handshake's. MCP lets a server ping before
|
|
1156
1189
|
// initialization completes, and the ping gets its empty result, as
|
|
1157
|
-
// on a connected transport
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1190
|
+
// on a connected transport, `"id": null` included
|
|
1191
|
+
// (src/jsonrpc-envelope.ts). Anything else it sends now is ignored,
|
|
1192
|
+
// an invalid request included. Of its responses, the one with
|
|
1193
|
+
// initialize's id answers it, and so does a JSON-RPC 2.0 error with
|
|
1194
|
+
// id null or with no id: a peer answers a request it couldn't read
|
|
1195
|
+
// that way (JSON-RPC 2.0 §5; MCP 2025-11-25, Basic), initialize is
|
|
1196
|
+
// the only request this host has out, and a peer never answers a
|
|
1197
|
+
// response. Such an error means the server can't read this host's
|
|
1198
|
+
// messages, so the handshake fails at once, with the error's message.
|
|
1199
|
+
// `"jsonrpc": "2.0"` keeps a server's own JSON log line with an
|
|
1200
|
+
// error key and id null, or no id, from failing it; one with
|
|
1201
|
+
// initialize's id is taken for the answer, whatever its jsonrpc. Of
|
|
1202
|
+
// the other responses, a JSON-RPC 2.0 error whose id is neither a
|
|
1203
|
+
// string nor a number is logged, as on a connected transport, and
|
|
1204
|
+
// any other is ignored.
|
|
1205
|
+
const envelope = readEnvelope(msg);
|
|
1206
|
+
if (envelope.kind === 'request' && envelope.method === 'ping') {
|
|
1207
|
+
transport.writeLine(JSON.stringify({ jsonrpc: '2.0', id: envelope.id, result: {} }));
|
|
1163
1208
|
return;
|
|
1164
1209
|
}
|
|
1165
|
-
if (
|
|
1210
|
+
if (envelope.kind !== 'response')
|
|
1166
1211
|
return;
|
|
1212
|
+
const namesNoRequest = msg.id === null || !Object.hasOwn(msg, 'id');
|
|
1213
|
+
const answersInitialize = msg.id === initId || (namesNoRequest && msg.jsonrpc === '2.0' && Boolean(msg.error));
|
|
1214
|
+
if (!answersInitialize) {
|
|
1215
|
+
if (typeof msg.id !== 'string' && typeof msg.id !== 'number' && isJsonRpcError(msg)) {
|
|
1216
|
+
console.error(unmatchedResponse(config.id, msg, (text) => redactServerText(text, config)));
|
|
1217
|
+
}
|
|
1218
|
+
return;
|
|
1219
|
+
}
|
|
1167
1220
|
cleanup();
|
|
1168
1221
|
if (msg.error) {
|
|
1169
1222
|
// describeCause rather than the template's own conversion: the
|
|
@@ -1486,8 +1539,9 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1486
1539
|
* following `nextCursor` across pages (2024-11-05 pagination). Cursors are
|
|
1487
1540
|
* opaque strings, `''` included: only an absent or null `nextCursor` ends
|
|
1488
1541
|
* the inventory (a null one is how some servers say "no more", and main
|
|
1489
|
-
* read it as a complete page). A page that isn't well formed (no `tools` array,
|
|
1490
|
-
* that isn't a string
|
|
1542
|
+
* read it as a complete page). A page that isn't well formed (no `tools` array, an entry
|
|
1543
|
+
* that isn't an object with a string `name`, a cursor that isn't a string), or cursors
|
|
1544
|
+
* that don't terminate (a repeat, or more
|
|
1491
1545
|
* than {@link MAX_TOOL_LIST_PAGES} pages), are errors, never a partial or
|
|
1492
1546
|
* empty inventory published as complete. The read tap (RFC-014) is handed
|
|
1493
1547
|
* the complete inventory once, with the last page's `_meta`, as the last
|
|
@@ -1502,10 +1556,13 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1502
1556
|
let first;
|
|
1503
1557
|
const read = [];
|
|
1504
1558
|
const revs = new Set();
|
|
1559
|
+
const isTool = (entry) => !!entry && typeof entry === 'object' && typeof entry.name === 'string';
|
|
1505
1560
|
const onRead = (result) => {
|
|
1506
1561
|
if (!result || typeof result !== 'object' || !Array.isArray(result.tools))
|
|
1507
1562
|
return;
|
|
1508
1563
|
const r = result;
|
|
1564
|
+
if (!r.tools.every(isTool))
|
|
1565
|
+
return;
|
|
1509
1566
|
for (const t of r.tools)
|
|
1510
1567
|
read.push(t);
|
|
1511
1568
|
const rev = r._meta?.['mcpl/rev'];
|
|
@@ -1524,6 +1581,9 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1524
1581
|
if (!result || typeof result !== 'object' || !Array.isArray(result.tools)) {
|
|
1525
1582
|
throw malformed('no tools array');
|
|
1526
1583
|
}
|
|
1584
|
+
const unreadable = result.tools.findIndex((entry) => !isTool(entry));
|
|
1585
|
+
if (unreadable !== -1)
|
|
1586
|
+
throw malformed(`entry ${unreadable + 1} isn't an object with a string name`);
|
|
1527
1587
|
first ??= result;
|
|
1528
1588
|
for (const t of result.tools)
|
|
1529
1589
|
tools.push(t);
|
|
@@ -2103,23 +2163,46 @@ export class McplServerConnection extends EventEmitter {
|
|
|
2103
2163
|
}
|
|
2104
2164
|
/** Contain synchronous dispatch failures; async RPC handlers own their promises. */
|
|
2105
2165
|
dispatchMessage(msg, epoch) {
|
|
2106
|
-
//
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
this.
|
|
2114
|
-
|
|
2115
|
-
|
|
2166
|
+
// The envelope is read once, here (src/jsonrpc-envelope.ts says how).
|
|
2167
|
+
const envelope = readEnvelope(msg);
|
|
2168
|
+
switch (envelope.kind) {
|
|
2169
|
+
case 'response': {
|
|
2170
|
+
// Never answered, so a server that answers what it can't read, with
|
|
2171
|
+
// id null, can't start an exchange of errors with us. One read after
|
|
2172
|
+
// its transport's boundary is late (handleResponse).
|
|
2173
|
+
const late = epoch !== this.transportEpoch;
|
|
2174
|
+
// RFC-014: its hints apply as it's read, whether or not anyone still
|
|
2175
|
+
// waits for it. A dead transport's revs are its own, so a response
|
|
2176
|
+
// read after its boundary is never tapped.
|
|
2177
|
+
if (!late)
|
|
2178
|
+
this.tapResponse(msg);
|
|
2179
|
+
this.handleResponse(msg, late);
|
|
2180
|
+
return;
|
|
2181
|
+
}
|
|
2182
|
+
case 'neither':
|
|
2183
|
+
// Not JSON-RPC: ignored like the server's other unrelated output.
|
|
2184
|
+
return;
|
|
2185
|
+
case 'invalid': {
|
|
2186
|
+
// Answered on the transport it came on, as every request is. One
|
|
2187
|
+
// read after that transport's boundary is the dead process's and
|
|
2188
|
+
// isn't answered: sendErrorResponse logs the answer it didn't send.
|
|
2189
|
+
this.sendErrorResponse(envelope.id, envelope.error.code, envelope.error.message, undefined, epoch);
|
|
2190
|
+
if (epoch !== this.transportEpoch)
|
|
2191
|
+
return;
|
|
2192
|
+
const forMethod = envelope.method !== undefined ? ` for method ${logValue(envelope.method)}` : '';
|
|
2193
|
+
console.error(`[mcpl] ${this.id}: answered -32600 to an invalid request${forMethod}: ${envelope.problems}`);
|
|
2194
|
+
return;
|
|
2195
|
+
}
|
|
2116
2196
|
}
|
|
2117
|
-
// It is an inbound request or notification from the server
|
|
2197
|
+
// It is an inbound request or notification from the server, its method
|
|
2198
|
+
// a string. A request's id is a string, a number or null, and `"id": null`
|
|
2199
|
+
// is answered with id null; a notification has none.
|
|
2118
2200
|
const request = msg;
|
|
2201
|
+
const requestId = envelope.kind === 'request' ? envelope.id : undefined;
|
|
2119
2202
|
// Read after its transport's boundary, it is the dead process's: the
|
|
2120
2203
|
// boundary's rule applies (afterBoundary).
|
|
2121
2204
|
if (epoch !== this.transportEpoch) {
|
|
2122
|
-
this.afterBoundary(request, epoch);
|
|
2205
|
+
this.afterBoundary(request, requestId, epoch);
|
|
2123
2206
|
return;
|
|
2124
2207
|
}
|
|
2125
2208
|
// MCP's ping, which either side may send: its receiver answers promptly
|
|
@@ -2128,8 +2211,8 @@ export class McplServerConnection extends EventEmitter {
|
|
|
2128
2211
|
// paused plane mustn't hold that answer. A ping sent as a notification
|
|
2129
2212
|
// has nothing to answer. The handshake answers one too.
|
|
2130
2213
|
if (request.method === 'ping') {
|
|
2131
|
-
if (
|
|
2132
|
-
this.sendResponse(
|
|
2214
|
+
if (requestId !== undefined)
|
|
2215
|
+
this.sendResponse(requestId, {});
|
|
2133
2216
|
return;
|
|
2134
2217
|
}
|
|
2135
2218
|
// RFC-014 §6.1: a push's hints apply as it's read, before the plane gate
|
|
@@ -2140,11 +2223,11 @@ export class McplServerConnection extends EventEmitter {
|
|
|
2140
2223
|
this.tap({ kind: 'push', params: request.params });
|
|
2141
2224
|
else if (request.method === 'tools/hints' && this.readTap) {
|
|
2142
2225
|
this.tap({ kind: 'hints', params: request.params });
|
|
2143
|
-
if (
|
|
2144
|
-
this.sendResponse(
|
|
2226
|
+
if (requestId !== undefined)
|
|
2227
|
+
this.sendResponse(requestId, {});
|
|
2145
2228
|
return;
|
|
2146
2229
|
}
|
|
2147
|
-
const eventName =
|
|
2230
|
+
const eventName = Object.hasOwn(McplServerConnection.METHOD_TO_EVENT, request.method)
|
|
2148
2231
|
? McplServerConnection.METHOD_TO_EVENT[request.method] : undefined;
|
|
2149
2232
|
// §7 is removed in 0.5.0: scope/elevate is no longer a method. Answer
|
|
2150
2233
|
// rather than hang (§6.6 — a method that will never be answered MUST
|
|
@@ -2155,8 +2238,8 @@ export class McplServerConnection extends EventEmitter {
|
|
|
2155
2238
|
// routed, control-plane classified, and mutating declarations — a
|
|
2156
2239
|
// live ungated self-attestation path (PR #79 review blocker 4).
|
|
2157
2240
|
if (request.method === McplMethod.FeatureSetsChanged) {
|
|
2158
|
-
if (
|
|
2159
|
-
this.sendErrorResponse(
|
|
2241
|
+
if (requestId !== undefined) {
|
|
2242
|
+
this.sendErrorResponse(requestId, -32601, 'featureSets/changed removed in MCPL 0.5.0 (superseded by mcpl/manifestChanged, SPEC §17)');
|
|
2160
2243
|
}
|
|
2161
2244
|
else {
|
|
2162
2245
|
console.error(`[mcpl] ${this.id}: discarded featureSets/changed — removed in 0.5.0 (§6.7/§17)`);
|
|
@@ -2164,8 +2247,8 @@ export class McplServerConnection extends EventEmitter {
|
|
|
2164
2247
|
return;
|
|
2165
2248
|
}
|
|
2166
2249
|
if (request.method === McplMethod.ScopeElevate) {
|
|
2167
|
-
if (
|
|
2168
|
-
this.sendErrorResponse(
|
|
2250
|
+
if (requestId !== undefined) {
|
|
2251
|
+
this.sendErrorResponse(requestId, -32601, 'scope/elevate removed in MCPL 0.5.0 (SPEC §7)');
|
|
2169
2252
|
}
|
|
2170
2253
|
return;
|
|
2171
2254
|
}
|
|
@@ -2175,19 +2258,18 @@ export class McplServerConnection extends EventEmitter {
|
|
|
2175
2258
|
// rejecting here, at line receipt, was wrong for staged connections.
|
|
2176
2259
|
if (!eventName) {
|
|
2177
2260
|
// §6.6: a request that will never be answered MUST get an error, so a
|
|
2178
|
-
// request
|
|
2179
|
-
//
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
console.error(`[mcpl] ${this.id}: answered -32601 to a request for ${describeMethod(request.method)}, which this host doesn't handle`);
|
|
2261
|
+
// request whose method isn't one this host handles is answered -32601.
|
|
2262
|
+
// A notification nobody handles is ignored, as JSON-RPC asks.
|
|
2263
|
+
if (requestId !== undefined) {
|
|
2264
|
+
this.sendErrorResponse(requestId, -32601, 'Method not found');
|
|
2265
|
+
console.error(`[mcpl] ${this.id}: answered -32601 to a request for method ${logValue(request.method)}, which this host doesn't handle`);
|
|
2184
2266
|
}
|
|
2185
2267
|
return;
|
|
2186
2268
|
}
|
|
2187
2269
|
// Emit the typed event with params and (for requests) a respond callback
|
|
2188
|
-
if (
|
|
2270
|
+
if (requestId !== undefined) {
|
|
2189
2271
|
// Server expects a response — provide a respond helper
|
|
2190
|
-
this.dispatchInboundEvent(eventName, request.params, this.responderFor(
|
|
2272
|
+
this.dispatchInboundEvent(eventName, request.params, this.responderFor(requestId, epoch));
|
|
2191
2273
|
}
|
|
2192
2274
|
else {
|
|
2193
2275
|
// Notification — no response expected
|
|
@@ -2197,7 +2279,8 @@ export class McplServerConnection extends EventEmitter {
|
|
|
2197
2279
|
/**
|
|
2198
2280
|
* A request's responder, bound to the transport it came on (`epoch`): an
|
|
2199
2281
|
* answer, or a streamed inference's chunk, sent after that transport has
|
|
2200
|
-
* closed reaches nothing, never a server that didn't ask it.
|
|
2282
|
+
* closed reaches nothing, never a server that didn't ask it. A request
|
|
2283
|
+
* sent with id null is answered with id null.
|
|
2201
2284
|
*/
|
|
2202
2285
|
responderFor(id, epoch) {
|
|
2203
2286
|
return {
|
|
@@ -2222,15 +2305,15 @@ export class McplServerConnection extends EventEmitter {
|
|
|
2222
2305
|
* it while its writer lives, with no grant to come, so it drops and logs
|
|
2223
2306
|
* all of it; hold's bounds cap what any other keeps.
|
|
2224
2307
|
*/
|
|
2225
|
-
afterBoundary(request, epoch) {
|
|
2226
|
-
const event =
|
|
2308
|
+
afterBoundary(request, requestId, epoch) {
|
|
2309
|
+
const event = Object.hasOwn(McplServerConnection.METHOD_TO_EVENT, request.method)
|
|
2227
2310
|
? McplServerConnection.METHOD_TO_EVENT[request.method] : undefined;
|
|
2228
2311
|
if (this.closedForGood || event === undefined || !McplServerConnection.WORLD_EVENTS.has(event)) {
|
|
2229
2312
|
console.error(`[mcpl] ${this.id}: dropped a message read after its transport closed` +
|
|
2230
|
-
`${this.closedForGood ? ', with no transport to come' : ''}: ${
|
|
2313
|
+
`${this.closedForGood ? ', with no transport to come' : ''}: method ${logValue(request.method)}`);
|
|
2231
2314
|
return;
|
|
2232
2315
|
}
|
|
2233
|
-
this.hold(event,
|
|
2316
|
+
this.hold(event, requestId !== undefined ? [request.params, this.responderFor(requestId, epoch)] : [request.params], true);
|
|
2234
2317
|
}
|
|
2235
2318
|
/** Live delivery and delayed plane flushes share the same containment boundary. */
|
|
2236
2319
|
dispatchInboundEvent(event, ...args) {
|
|
@@ -2283,7 +2366,7 @@ export class McplServerConnection extends EventEmitter {
|
|
|
2283
2366
|
/** Tap a response to a hinted request (RFC-014): its result's hints, or a
|
|
2284
2367
|
* list's statement, apply now, awaited or not. */
|
|
2285
2368
|
tapResponse(response) {
|
|
2286
|
-
if (!this.readTap)
|
|
2369
|
+
if (!this.readTap || response.id === null)
|
|
2287
2370
|
return;
|
|
2288
2371
|
const sent = this.hintedRequests.get(response.id);
|
|
2289
2372
|
if (!sent)
|
|
@@ -2298,6 +2381,16 @@ export class McplServerConnection extends EventEmitter {
|
|
|
2298
2381
|
* Handle a JSON-RPC response by resolving/rejecting the corresponding pending request.
|
|
2299
2382
|
*/
|
|
2300
2383
|
handleResponse(response, late = false) {
|
|
2384
|
+
// A response whose id is neither a string nor a number, or that has
|
|
2385
|
+
// none, can't be matched to a request of ours, on this transport or an
|
|
2386
|
+
// earlier one. It isn't an orphan, which is a late answer to one, so
|
|
2387
|
+
// it's ignored, and logged when it's a JSON-RPC 2.0 error.
|
|
2388
|
+
if (typeof response.id !== 'string' && typeof response.id !== 'number') {
|
|
2389
|
+
if (isJsonRpcError(response)) {
|
|
2390
|
+
console.error(unmatchedResponse(this.id, response, (this.redactor ??= serverTextRedactor(this.config ?? {})).now()));
|
|
2391
|
+
}
|
|
2392
|
+
return;
|
|
2393
|
+
}
|
|
2301
2394
|
// One read after its transport's boundary answers a request the close
|
|
2302
2395
|
// ended. It's matched against none of this connection's request records,
|
|
2303
2396
|
// since the next transport numbers its requests afresh, and goes the way
|