@apnex/network-adapter 0.1.1 → 0.1.5
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/dist/build-info.json +6 -0
- package/dist/file-logger.d.ts +42 -0
- package/dist/file-logger.js +122 -0
- package/dist/file-logger.js.map +1 -0
- package/dist/index.d.ts +37 -13
- package/dist/index.js +42 -15
- package/dist/index.js.map +1 -1
- package/dist/kernel/adapter-config.d.ts +47 -0
- package/dist/kernel/adapter-config.js +90 -0
- package/dist/kernel/adapter-config.js.map +1 -0
- package/dist/kernel/agent-client.d.ts +25 -20
- package/dist/kernel/build-identity.d.ts +24 -0
- package/dist/kernel/build-identity.js +45 -0
- package/dist/kernel/build-identity.js.map +1 -0
- package/dist/kernel/event-router.d.ts +22 -1
- package/dist/kernel/event-router.js +45 -7
- package/dist/kernel/event-router.js.map +1 -1
- package/dist/kernel/handshake.d.ts +40 -4
- package/dist/kernel/handshake.js +46 -7
- package/dist/kernel/handshake.js.map +1 -1
- package/dist/kernel/harness-manifest.d.ts +51 -0
- package/dist/kernel/harness-manifest.js +96 -0
- package/dist/kernel/harness-manifest.js.map +1 -0
- package/dist/kernel/liveness-signal.d.ts +35 -0
- package/dist/kernel/liveness-signal.js +61 -0
- package/dist/kernel/liveness-signal.js.map +1 -0
- package/dist/kernel/liveness-watchdog.d.ts +78 -0
- package/dist/kernel/liveness-watchdog.js +115 -0
- package/dist/kernel/liveness-watchdog.js.map +1 -0
- package/dist/kernel/mcp-agent-client.d.ts +2 -2
- package/dist/kernel/mcp-agent-client.js +49 -3
- package/dist/kernel/mcp-agent-client.js.map +1 -1
- package/dist/kernel/poll-backstop.d.ts +93 -4
- package/dist/kernel/poll-backstop.js +193 -25
- package/dist/kernel/poll-backstop.js.map +1 -1
- package/dist/kernel/state-sync.d.ts +2 -13
- package/dist/kernel/state-sync.js.map +1 -1
- package/dist/notification-log.d.ts +8 -0
- package/dist/notification-log.js +10 -0
- package/dist/notification-log.js.map +1 -1
- package/dist/observability.d.ts +24 -0
- package/dist/observability.js +52 -0
- package/dist/observability.js.map +1 -0
- package/dist/prompt-format.js +82 -9
- package/dist/prompt-format.js.map +1 -1
- package/dist/tool-manager/catalog/health-revision.d.ts +43 -0
- package/dist/tool-manager/catalog/health-revision.js +61 -0
- package/dist/tool-manager/catalog/health-revision.js.map +1 -0
- package/dist/tool-manager/{tool-catalog-cache.d.ts → catalog/tool-catalog-cache.d.ts} +39 -19
- package/dist/tool-manager/{tool-catalog-cache.js → catalog/tool-catalog-cache.js} +53 -26
- package/dist/tool-manager/catalog/tool-catalog-cache.js.map +1 -0
- package/dist/tool-manager/catalog/tool-surface-reconciler.d.ts +93 -0
- package/dist/tool-manager/catalog/tool-surface-reconciler.js +101 -0
- package/dist/tool-manager/catalog/tool-surface-reconciler.js.map +1 -0
- package/dist/tool-manager/contracts.d.ts +91 -0
- package/dist/tool-manager/contracts.js +20 -0
- package/dist/tool-manager/contracts.js.map +1 -0
- package/dist/tool-manager/dispatch/dispatch.d.ts +77 -0
- package/dist/tool-manager/dispatch/dispatch.js +170 -0
- package/dist/tool-manager/dispatch/dispatch.js.map +1 -0
- package/dist/tool-manager/dispatch/tool-call-policy.d.ts +32 -0
- package/dist/tool-manager/dispatch/tool-call-policy.js +56 -0
- package/dist/tool-manager/dispatch/tool-call-policy.js.map +1 -0
- package/dist/tool-manager/{dispatcher.d.ts → orchestrator/dispatcher.d.ts} +110 -31
- package/dist/tool-manager/orchestrator/dispatcher.js +559 -0
- package/dist/tool-manager/orchestrator/dispatcher.js.map +1 -0
- package/dist/tool-manager/work-protocol/claimable-digest-tracker.d.ts +60 -0
- package/dist/tool-manager/work-protocol/claimable-digest-tracker.js +66 -0
- package/dist/tool-manager/work-protocol/claimable-digest-tracker.js.map +1 -0
- package/dist/tool-manager/work-protocol/work-lease-tracker.d.ts +59 -0
- package/dist/tool-manager/work-protocol/work-lease-tracker.js +134 -0
- package/dist/tool-manager/work-protocol/work-lease-tracker.js.map +1 -0
- package/dist/wire/mcp-transport.d.ts +1 -1
- package/dist/wire/mcp-transport.js +31 -7
- package/dist/wire/mcp-transport.js.map +1 -1
- package/dist/wire/slot-gate.d.ts +40 -0
- package/dist/wire/slot-gate.js +61 -0
- package/dist/wire/slot-gate.js.map +1 -0
- package/dist/wire/transport.d.ts +18 -0
- package/package.json +6 -3
- package/dist/kernel/instance.d.ts +0 -40
- package/dist/kernel/instance.js +0 -79
- package/dist/kernel/instance.js.map +0 -1
- package/dist/tool-manager/dispatcher.js +0 -379
- package/dist/tool-manager/dispatcher.js.map +0 -1
- package/dist/tool-manager/tool-catalog-cache.js.map +0 -1
|
@@ -19,11 +19,13 @@
|
|
|
19
19
|
* "dispatcher".
|
|
20
20
|
*/
|
|
21
21
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
22
|
-
import type { AgentClientCallbacks, AgentEvent, SessionState, SessionReconnectReason } from "
|
|
23
|
-
import type { McpAgentClient } from "
|
|
24
|
-
import { PollBackstop, type PollBackstopOptions } from "
|
|
25
|
-
import type { DrainedPendingAction } from "
|
|
26
|
-
import type { CachedCatalog } from "
|
|
22
|
+
import type { AgentClientCallbacks, AgentEvent, SessionState, SessionReconnectReason } from "../../kernel/agent-client.js";
|
|
23
|
+
import type { McpAgentClient } from "../../kernel/mcp-agent-client.js";
|
|
24
|
+
import { PollBackstop, type PollBackstopOptions } from "../../kernel/poll-backstop.js";
|
|
25
|
+
import type { DrainedPendingAction } from "../../kernel/state-sync.js";
|
|
26
|
+
import type { CachedCatalog } from "../catalog/tool-catalog-cache.js";
|
|
27
|
+
import { WorkLeaseTracker } from "../work-protocol/work-lease-tracker.js";
|
|
28
|
+
import { TOOL_CALL_SIGNAL_SKIP, pendingKey, injectQueueItemId } from "../dispatch/tool-call-policy.js";
|
|
27
29
|
export interface DispatcherClientInfo {
|
|
28
30
|
name: string;
|
|
29
31
|
version: string;
|
|
@@ -47,8 +49,11 @@ export interface SharedDispatcherOptions {
|
|
|
47
49
|
* Late-binding agent accessor. Some hosts (opencode) construct the
|
|
48
50
|
* dispatcher before the McpAgentClient connection is established.
|
|
49
51
|
* Returning `null` means "not connected yet" — the dispatcher
|
|
50
|
-
* surfaces a "Hub not connected" error envelope on CallTool and
|
|
51
|
-
*
|
|
52
|
+
* surfaces a "Hub not connected" error envelope on CallTool and a
|
|
53
|
+
* structured MCP error on ListTools after a bounded retry window
|
|
54
|
+
* (bug-114 fallback-gap fix). Silent empty-tool-list response was
|
|
55
|
+
* retired 2026-05-26 — host MCP clients (e.g. Claude Code) cached
|
|
56
|
+
* the empty list as the authoritative surface, masking comms-loss.
|
|
52
57
|
*/
|
|
53
58
|
getAgent: () => McpAgentClient | null;
|
|
54
59
|
/** Adapter version reported in MCP serverInfo. */
|
|
@@ -64,10 +69,19 @@ export interface SharedDispatcherOptions {
|
|
|
64
69
|
/** Diagnostic logger. No-op default. */
|
|
65
70
|
log?: (msg: string) => void;
|
|
66
71
|
/**
|
|
67
|
-
* Resolves when the underlying McpAgentClient
|
|
68
|
-
* (transport connected + identity asserted
|
|
69
|
-
*
|
|
70
|
-
*
|
|
72
|
+
* Resolves when the underlying McpAgentClient is fully usable
|
|
73
|
+
* (transport connected + identity asserted + streaming-state
|
|
74
|
+
* reached, i.e. `agent.start()` returned). Gates the ListTools
|
|
75
|
+
* handler's bootstrap path; on probe-path (`!identityReady`) the
|
|
76
|
+
* cache fallback runs without awaiting this gate.
|
|
77
|
+
*
|
|
78
|
+
* bug-141 pass-2 (2026-05-28): docs updated from "handshake
|
|
79
|
+
* completes" → "fully usable". The earlier wording prompted host
|
|
80
|
+
* shims to gate on `identityReady`, which opened the gate ~1.3s
|
|
81
|
+
* before `agent.isConnected` flipped true (during the synchronizing
|
|
82
|
+
* → streaming transition) — surfacing the bug-141 race. Hosts MUST
|
|
83
|
+
* gate on a Promise that resolves only after the agent is in
|
|
84
|
+
* streaming state (claude-plugin: `syncReady`).
|
|
71
85
|
*
|
|
72
86
|
* Was: `handshakeComplete` (per-plugin dispatchers). Renamed in
|
|
73
87
|
* mission-55 cleanup per Design v1.2 Q5: name what is gated, not
|
|
@@ -84,22 +98,47 @@ export interface SharedDispatcherOptions {
|
|
|
84
98
|
* cleanup per Design v1.2 Q5.
|
|
85
99
|
*/
|
|
86
100
|
callToolGate?: Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* mission-88 W10 (bug-126 fix): timeout in ms for `await callToolGate`.
|
|
103
|
+
* If the gate Promise neither resolves nor rejects within this budget,
|
|
104
|
+
* the dispatcher emits a structured `gate-timeout` log line + returns
|
|
105
|
+
* isError to host (instead of hanging indefinitely as the bug-126
|
|
106
|
+
* incident exhibited). Default 30000ms; set to 0 to disable.
|
|
107
|
+
*
|
|
108
|
+
* Defense against pending-forever sessionReady Promises (W10 Design §3
|
|
109
|
+
* H1+H3 hypotheses). The timeout is a fail-safe — production-correct
|
|
110
|
+
* handshake flow should never hit it.
|
|
111
|
+
*/
|
|
112
|
+
callToolGateTimeoutMs?: number;
|
|
87
113
|
getCachedCatalog?: () => CachedCatalog | null;
|
|
88
114
|
getIsIdentityReady?: () => boolean;
|
|
89
|
-
|
|
115
|
+
/**
|
|
116
|
+
* bug-114 — current Hub tool-surface revision (`/health`
|
|
117
|
+
* `toolSurfaceRevision`). The cache-validity key; `null` when the
|
|
118
|
+
* /health fetch hasn't resolved yet (probe-friendly trust-cache).
|
|
119
|
+
*/
|
|
120
|
+
getCurrentToolSurfaceRevision?: () => string | null;
|
|
90
121
|
persistCatalog?: (catalog: unknown[]) => void;
|
|
91
122
|
/**
|
|
92
123
|
* Optional cache-validity check. When omitted, cache-fallback
|
|
93
124
|
* conservatively treats every cached entry as invalid (live-fetch
|
|
94
125
|
* dominates). Wire `isCacheValid` from `./tool-catalog-cache.js`
|
|
95
|
-
* to enable
|
|
126
|
+
* to enable tool-surface-revision-keyed validity.
|
|
96
127
|
*/
|
|
97
|
-
isCacheValid?: (cached: CachedCatalog,
|
|
128
|
+
isCacheValid?: (cached: CachedCatalog, currentRevision: string | null | undefined) => boolean;
|
|
98
129
|
/**
|
|
99
130
|
* Universal Adapter notification contract. Host shim attaches its
|
|
100
131
|
* render-surface bindings here.
|
|
101
132
|
*/
|
|
102
133
|
notificationHooks?: DispatcherNotificationHooks;
|
|
134
|
+
/**
|
|
135
|
+
* idea-353 W2: observe each host-driven CallTool's (method, args, result)
|
|
136
|
+
* after it returns. The host wires this to a WorkLeaseTracker so the
|
|
137
|
+
* outbound stall-prompt can track this agent's own held leases locally
|
|
138
|
+
* (claim/renew/complete/abandon) with no Hub round-trip. Best-effort —
|
|
139
|
+
* a throw is caught + logged and never affects the tool-call return.
|
|
140
|
+
*/
|
|
141
|
+
onToolCallResult?: (method: string, args: Record<string, unknown>, result: unknown) => void;
|
|
103
142
|
/**
|
|
104
143
|
* Mission-56 W3.3: opt-in adapter-side hybrid poll backstop. When
|
|
105
144
|
* supplied, the dispatcher constructs a PollBackstop (Design v1.2
|
|
@@ -113,6 +152,24 @@ export interface SharedDispatcherOptions {
|
|
|
113
152
|
* Omit to disable polling (push-only mode).
|
|
114
153
|
*/
|
|
115
154
|
pollBackstop?: Omit<PollBackstopOptions, "onPolledMessage">;
|
|
155
|
+
/**
|
|
156
|
+
* Slice D (pi native binding) — external idle probe. A NATIVE host (pi) drives
|
|
157
|
+
* tool calls through `runToolDispatch` directly, NOT through this dispatcher's
|
|
158
|
+
* MCP `CallTool` handler, so the internal `activeCallCount` never sees them.
|
|
159
|
+
* Supply the host's own idle signal (e.g. pi's `ctx.isIdle()`) and the
|
|
160
|
+
* wake/stall reconcile gates on THAT instead of the (always-zero) internal
|
|
161
|
+
* counter. When omitted, the internal `activeCallCount` is authoritative
|
|
162
|
+
* (MCP hosts — unchanged).
|
|
163
|
+
*/
|
|
164
|
+
externalIdle?: () => boolean;
|
|
165
|
+
/**
|
|
166
|
+
* Slice D (pi native binding) — shared WorkLeaseTracker. A native host's
|
|
167
|
+
* `ToolDispatchContext.workLeases` must be the SAME tracker the reconcile
|
|
168
|
+
* reads for stall-prompts. Inject it here so the native binding's
|
|
169
|
+
* `workLeases.observe(...)` populates the tracker the heartbeat tick consumes.
|
|
170
|
+
* When omitted, the dispatcher constructs its own (MCP hosts — unchanged).
|
|
171
|
+
*/
|
|
172
|
+
sharedWorkLeases?: WorkLeaseTracker;
|
|
116
173
|
}
|
|
117
174
|
export interface SharedDispatcher {
|
|
118
175
|
/** ADR-017 queueItemId tracking map. Keyed by `${dispatchType}:${entityRef}`. */
|
|
@@ -157,24 +214,46 @@ export interface SharedDispatcher {
|
|
|
157
214
|
* re-render it.
|
|
158
215
|
*/
|
|
159
216
|
ackMessage: (messageId: string) => Promise<void>;
|
|
217
|
+
/**
|
|
218
|
+
* idea-353 W1 idle-gate: number of host-driven CallTool requests currently
|
|
219
|
+
* in flight. The wake/stall reconciler reads this on the heartbeat tick to
|
|
220
|
+
* skip surfacing while the agent is mid-task (AC4). The tick's own internal
|
|
221
|
+
* `agent.call`s do not pass through the CallTool handler, so they are not
|
|
222
|
+
* counted (an idle poll never self-gates).
|
|
223
|
+
*/
|
|
224
|
+
getActiveCallCount: () => number;
|
|
225
|
+
/** idea-353 W1 idle-gate convenience: `getActiveCallCount() === 0`. */
|
|
226
|
+
isIdle: () => boolean;
|
|
227
|
+
/**
|
|
228
|
+
* Slice D (pi native binding) — the WorkLeaseTracker the reconcile reads. A
|
|
229
|
+
* native host builds its `ToolDispatchContext.workLeases` from THIS instance
|
|
230
|
+
* so its `runToolDispatch` lease observations feed the stall-prompt path.
|
|
231
|
+
* (Same object as `opts.sharedWorkLeases` when injected.)
|
|
232
|
+
*/
|
|
233
|
+
workLeases: WorkLeaseTracker;
|
|
160
234
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
* Mission-62 W3: tools that should NOT trigger signal_working_*
|
|
164
|
-
* wrapping. The signal_* tools themselves would recurse infinitely;
|
|
165
|
-
* register_role + claim_session + drain_pending_actions are lifecycle
|
|
166
|
-
* tools, not semantic tool-call-work.
|
|
167
|
-
*/
|
|
168
|
-
export declare const TOOL_CALL_SIGNAL_SKIP: ReadonlySet<string>;
|
|
169
|
-
export declare function pendingKey(dispatchType: string, entityRef: string): string;
|
|
235
|
+
export { TOOL_CALL_SIGNAL_SKIP, pendingKey, injectQueueItemId };
|
|
236
|
+
export declare function createSharedDispatcher(opts: SharedDispatcherOptions): SharedDispatcher;
|
|
170
237
|
/**
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
238
|
+
* bug-53 boot-time fail-fast: assert host adapter has opted into
|
|
239
|
+
* pollBackstop wiring (transport_heartbeat periodic timer). Throws if
|
|
240
|
+
* `dispatcher.pollBackstop === undefined` UNLESS `TRANSPORT_HEARTBEAT_ENABLED=false`
|
|
241
|
+
* is set explicitly (opt-out path).
|
|
242
|
+
*
|
|
243
|
+
* Class: substrate-runtime-gap (sister to bug-49/50/51). Mission-75 §3.3
|
|
244
|
+
* substrate (PollBackstop heartbeat-second-timer) shipped at thread-472 with
|
|
245
|
+
* unit tests green, but the host integration was never written — both
|
|
246
|
+
* adapters call `createSharedDispatcher({...})` without supplying
|
|
247
|
+
* `opts.pollBackstop`, so the dispatcher's pollBackstop field stayed
|
|
248
|
+
* `undefined` and neither the poll-timer nor the heartbeat-timer ever
|
|
249
|
+
* scheduled. ZERO `transport_heartbeat` MCP tool calls fired in 96 minutes
|
|
250
|
+
* post Hub-restart (5127-line shim.log + 1789-event ndjson confirmed).
|
|
175
251
|
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
252
|
+
* This assertion is a §6.4-equivalent gate: each host MUST call
|
|
253
|
+
* `assertHostWiringComplete(dispatcher)` post-startup so the bug-53 class
|
|
254
|
+
* cannot recur silently. Misconfiguration fails fast at boot, not invisibly
|
|
255
|
+
* after 96 minutes of clinical observability degradation.
|
|
178
256
|
*/
|
|
179
|
-
export declare function
|
|
180
|
-
|
|
257
|
+
export declare function assertHostWiringComplete(dispatcher: {
|
|
258
|
+
pollBackstop?: PollBackstop;
|
|
259
|
+
}, log?: (msg: string) => void): void;
|