@agent-deck/cli 1.8.2 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/agent-harness.d.ts +5 -2
  2. package/dist/agent-harness.d.ts.map +1 -1
  3. package/dist/agent-harness.js +18 -7
  4. package/dist/agent-harness.js.map +1 -1
  5. package/dist/debug-mcp.d.ts +25 -0
  6. package/dist/debug-mcp.d.ts.map +1 -1
  7. package/dist/debug-mcp.js +93 -25
  8. package/dist/debug-mcp.js.map +1 -1
  9. package/dist/grant-issue.d.ts +0 -5
  10. package/dist/grant-issue.d.ts.map +1 -1
  11. package/dist/grant-issue.js +19 -70
  12. package/dist/grant-issue.js.map +1 -1
  13. package/dist/index.js +1 -1
  14. package/dist/mcp-bridge.d.ts +182 -0
  15. package/dist/mcp-bridge.d.ts.map +1 -0
  16. package/dist/mcp-bridge.js +856 -0
  17. package/dist/mcp-bridge.js.map +1 -0
  18. package/dist/mcp-config.d.ts.map +1 -1
  19. package/dist/mcp-config.js +8 -5
  20. package/dist/mcp-config.js.map +1 -1
  21. package/dist/mcp-launcher.d.ts +9 -0
  22. package/dist/mcp-launcher.d.ts.map +1 -1
  23. package/dist/mcp-launcher.js +47 -0
  24. package/dist/mcp-launcher.js.map +1 -1
  25. package/dist/ports.d.ts +38 -0
  26. package/dist/ports.d.ts.map +1 -1
  27. package/dist/ports.js +63 -0
  28. package/dist/ports.js.map +1 -1
  29. package/dist/setup.d.ts +6 -4
  30. package/dist/setup.d.ts.map +1 -1
  31. package/dist/setup.js +51 -26
  32. package/dist/setup.js.map +1 -1
  33. package/dist/start.d.ts +1 -0
  34. package/dist/start.d.ts.map +1 -1
  35. package/dist/start.js +6 -2
  36. package/dist/start.js.map +1 -1
  37. package/dist/status.d.ts.map +1 -1
  38. package/dist/status.js +3 -0
  39. package/dist/status.js.map +1 -1
  40. package/package.json +3 -3
  41. package/dist/coordinator.d.ts +0 -2
  42. package/dist/coordinator.d.ts.map +0 -1
  43. package/dist/coordinator.js +0 -153
  44. package/dist/coordinator.js.map +0 -1
@@ -0,0 +1,182 @@
1
+ import type { Readable, Writable } from 'node:stream';
2
+ /** JSON-RPC message as it crosses the bridge — we route on shape, not on schema. */
3
+ type JsonRpcMessage = {
4
+ jsonrpc?: string;
5
+ id?: string | number | null;
6
+ method?: string;
7
+ params?: unknown;
8
+ result?: unknown;
9
+ error?: unknown;
10
+ };
11
+ export type McpBridgeOptions = {
12
+ url: string;
13
+ /** Sent on every request — the server re-validates the launch deck each call. */
14
+ headers: Record<string, string>;
15
+ /**
16
+ * Re-read the folder assignment before replaying a handshake. It can have moved
17
+ * to another deck — or another endpoint — while we were connected
18
+ * (`switch_bound_deck`, `agent-deck use`), and the values we launched with would
19
+ * otherwise reconnect us to the deck and server we started on.
20
+ */
21
+ resolveTarget?: () => Promise<{
22
+ url?: string;
23
+ headers?: Record<string, string>;
24
+ } | undefined>;
25
+ stdin: Readable;
26
+ stdout: Writable;
27
+ /** Diagnostics only; never stdout, which carries the protocol. */
28
+ log?: (message: string) => void;
29
+ /** Backoff between failed server→client stream reconnects. */
30
+ streamRetryDelayMs?: number;
31
+ /** How long `run()` waits for in-flight requests after the host closes stdin. */
32
+ drainTimeoutMs?: number;
33
+ fetchImpl?: typeof fetch;
34
+ };
35
+ export declare function isSessionInvalidResponse(status: number, body: string): boolean;
36
+ /**
37
+ * Deck id out of an MCP tool result — the binding tools answer with one JSON
38
+ * document in a text content block.
39
+ */
40
+ export declare function readDeckIdFromToolResult(result: unknown): string | undefined;
41
+ /** Pull JSON-RPC payloads out of an SSE body (`data:` lines, blank-line delimited). */
42
+ export declare function parseSseMessages(chunk: string): JsonRpcMessage[];
43
+ export declare class McpStdioHttpBridge {
44
+ private readonly options;
45
+ private readonly fetchImpl;
46
+ private readonly log;
47
+ private sessionId;
48
+ /**
49
+ * Bumped every time the session id changes — including to `undefined`. A reply
50
+ * is only about the session it was sent on, and after a recovery the id alone
51
+ * cannot say that (the replacement may reuse a value we once held).
52
+ */
53
+ private sessionGeneration;
54
+ /** MCP endpoint as it stands now — re-read from the assignment on recovery. */
55
+ private url;
56
+ /** Launch headers as they stand now — re-read from the assignment on recovery. */
57
+ private launchHeaders;
58
+ /** The deck the client is working against: launch deck, or whatever it bound to. */
59
+ private boundDeckId;
60
+ /**
61
+ * In-flight `bind_workspace` / `switch_bound_deck` calls: request id → the session
62
+ * generation the call went out on. A binding result only describes the session that
63
+ * answered it, so one that arrives after a restart must not be read as the deck the
64
+ * replacement session is on.
65
+ */
66
+ private readonly pendingDeckRebinds;
67
+ /**
68
+ * The deck the *client* asked for, if it ever did. Only a client that bound a deck
69
+ * itself can be surprised by a reconnect landing somewhere else — a client that
70
+ * simply took the folder assignment gets whatever that assignment says now.
71
+ */
72
+ private clientChosenDeckId;
73
+ /**
74
+ * Set when a recovery moved the session off the deck the client chose. Held until
75
+ * it binds again: reporting the gap on the one request that happened to be in
76
+ * flight is not enough, because the call the client sends next would go to the
77
+ * new deck with nothing to show for it.
78
+ */
79
+ private deckAwaitingRebind;
80
+ /**
81
+ * A session lost to a restart that the server still counts as stranded. Held
82
+ * across failed recovery attempts so the handshake that finally lands can name
83
+ * it — dropping it would leave that client unresolved on the server forever.
84
+ */
85
+ private unresolvedSessionId;
86
+ private bindingProbeSeq;
87
+ /** The client's own handshake, replayed verbatim when a session disappears. */
88
+ private cachedInitialize;
89
+ private cachedInitialized;
90
+ private streamAbort;
91
+ private closed;
92
+ private recovering;
93
+ /** The in-flight `initialize` exchange; later messages wait for it, not for each other. */
94
+ private handshake;
95
+ /** Every dispatched client message, so stdin closing can drain instead of cutting them off. */
96
+ private readonly inFlight;
97
+ /** How many times we re-initialized after a restart — otherwise invisible, so the tests read it. */
98
+ private recoveryCount;
99
+ constructor(options: McpBridgeOptions);
100
+ getSessionId(): string | undefined;
101
+ getRecoveryCount(): number;
102
+ /** The deck this bridge believes its session acts on — diagnostics and tests. */
103
+ getBoundDeckId(): string | undefined;
104
+ /** Resolves when stdin ends (the host closed the server). */
105
+ run(): Promise<void>;
106
+ /**
107
+ * Start one client message and keep it tracked. Nothing here may reject: an
108
+ * escaping error would tear down `run()` and, with it, the whole bridge process
109
+ * — the exact failure mode a restart is supposed to be recoverable from.
110
+ */
111
+ private dispatch;
112
+ /** Give in-flight exchanges a bounded chance to finish once stdin is gone. */
113
+ private drain;
114
+ close(): void;
115
+ /**
116
+ * Hand a message to the client. `sentOnGeneration` is the session generation the
117
+ * response came back on — absent for anything the bridge writes itself.
118
+ */
119
+ private writeToClient;
120
+ /**
121
+ * Follow the client's own binding calls. `bind_workspace` moves the session to a
122
+ * deck the launch headers know nothing about, so this is the only place the
123
+ * bridge can learn which deck a later request expects to act on.
124
+ *
125
+ * Returns a replacement message when the binding answer belongs to a session a
126
+ * restart has since taken away: the deck it names is not where the bridge is now,
127
+ * and letting the success through would leave the client acting on the wrong deck
128
+ * believing it had bound.
129
+ */
130
+ private noteDeckRebinding;
131
+ private requestHeaders;
132
+ private post;
133
+ private forwardFromClient;
134
+ /**
135
+ * Refuse a deck-scoped call while the session sits on a deck the client never
136
+ * chose. The binding tools themselves go through — they are how it gets out.
137
+ */
138
+ private refuseUntilRebound;
139
+ /**
140
+ * Hold a message only for the two exchanges that own the session id — the
141
+ * handshake and a restart recovery. Everything else goes out concurrently, so
142
+ * one long tool call cannot block the cancellation that would end it.
143
+ */
144
+ private awaitSession;
145
+ /** POST one client message, recovering once if the session went away. */
146
+ private deliver;
147
+ /** Every session change goes through here, so the generation cannot drift. */
148
+ private setSessionId;
149
+ private captureSessionId;
150
+ private emitResponseBody;
151
+ /**
152
+ * Recover the session a request was sent on — once, no matter how many of its
153
+ * siblings come back stale. A second handshake for the same invalidation would
154
+ * discard a session that is already working and leave the first one orphaned on
155
+ * the server, where it shows up as another stranded client.
156
+ */
157
+ private ensureRecovered;
158
+ /**
159
+ * Replay the cached handshake against the restarted server. Its responses are
160
+ * swallowed — the client already completed its handshake and would reject a
161
+ * second `initialize` result for an id it no longer has outstanding.
162
+ */
163
+ private recover;
164
+ private runRecovery;
165
+ private refreshLaunchTarget;
166
+ /**
167
+ * Ask the recovered session which deck it actually acts on. A session deck
168
+ * override is gone after a restart, so this is the answer to compare a pending
169
+ * request against — and the launch header is only the fallback for a server
170
+ * that does not expose the binding tool.
171
+ */
172
+ private resolveSessionDeck;
173
+ private failRequest;
174
+ /**
175
+ * Server→client stream (`GET /mcp`). Reconnects on drop; a 404 here is the same
176
+ * restart signal as on POST, so it recovers through the same path.
177
+ */
178
+ private startServerStream;
179
+ private consumeServerStream;
180
+ }
181
+ export {};
182
+ //# sourceMappingURL=mcp-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-bridge.d.ts","sourceRoot":"","sources":["../src/mcp-bridge.ts"],"names":[],"mappings":"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"}