cohvu 1.0.23 → 2.0.1
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/auth.d.ts +3 -0
- package/dist/auth.js +25 -0
- package/dist/auth.js.map +1 -1
- package/dist/proxy.js +121 -278
- package/dist/proxy.js.map +1 -1
- package/package.json +1 -1
package/dist/auth.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ interface StoredTokens {
|
|
|
4
4
|
expires_at: string;
|
|
5
5
|
base_url: string;
|
|
6
6
|
}
|
|
7
|
+
/** Read the long-lived API key for proxy use. Returns null if not stored. */
|
|
8
|
+
export declare function getApiKey(): string | null;
|
|
9
|
+
export declare function storeApiKey(key: string): void;
|
|
7
10
|
export declare function deviceAuthFlow(baseUrl: string): Promise<StoredTokens>;
|
|
8
11
|
export declare function getAuthToken(baseUrl: string): Promise<{
|
|
9
12
|
accessToken: string;
|
package/dist/auth.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// Device auth flow + token storage for the Cohvu CLI.
|
|
3
3
|
// Stores tokens in ~/.cohvu/tokens.json.
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.getApiKey = getApiKey;
|
|
6
|
+
exports.storeApiKey = storeApiKey;
|
|
5
7
|
exports.deviceAuthFlow = deviceAuthFlow;
|
|
6
8
|
exports.getAuthToken = getAuthToken;
|
|
7
9
|
const fs_1 = require("fs");
|
|
@@ -10,6 +12,7 @@ const path_1 = require("path");
|
|
|
10
12
|
const child_process_1 = require("child_process");
|
|
11
13
|
const CONFIG_DIR = (0, path_1.join)((0, os_1.homedir)(), ".cohvu");
|
|
12
14
|
const TOKENS_FILE = (0, path_1.join)(CONFIG_DIR, "tokens.json");
|
|
15
|
+
const API_KEY_FILE = (0, path_1.join)(CONFIG_DIR, "credentials");
|
|
13
16
|
const POLL_INTERVAL_MS = 5000;
|
|
14
17
|
function ensureConfigDir() {
|
|
15
18
|
if (!(0, fs_1.existsSync)(CONFIG_DIR)) {
|
|
@@ -26,6 +29,24 @@ function loadStoredTokens() {
|
|
|
26
29
|
return null;
|
|
27
30
|
}
|
|
28
31
|
}
|
|
32
|
+
/** Read the long-lived API key for proxy use. Returns null if not stored. */
|
|
33
|
+
function getApiKey() {
|
|
34
|
+
if (!(0, fs_1.existsSync)(API_KEY_FILE))
|
|
35
|
+
return null;
|
|
36
|
+
try {
|
|
37
|
+
const key = (0, fs_1.readFileSync)(API_KEY_FILE, "utf-8").trim();
|
|
38
|
+
return key.startsWith("chv_") ? key : null;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function storeApiKey(key) {
|
|
45
|
+
ensureConfigDir();
|
|
46
|
+
const tmp = `${API_KEY_FILE}.${process.pid}.tmp`;
|
|
47
|
+
(0, fs_1.writeFileSync)(tmp, key, { mode: 0o600 });
|
|
48
|
+
(0, fs_1.renameSync)(tmp, API_KEY_FILE);
|
|
49
|
+
}
|
|
29
50
|
function storeTokens(tokens) {
|
|
30
51
|
ensureConfigDir();
|
|
31
52
|
const tmp = `${TOKENS_FILE}.${process.pid}.tmp`;
|
|
@@ -102,6 +123,10 @@ async function deviceAuthFlow(baseUrl) {
|
|
|
102
123
|
base_url: baseUrl,
|
|
103
124
|
};
|
|
104
125
|
storeTokens(tokens);
|
|
126
|
+
// Store long-lived API key for proxy use
|
|
127
|
+
if (tokenData.api_key) {
|
|
128
|
+
storeApiKey(tokenData.api_key);
|
|
129
|
+
}
|
|
105
130
|
process.stderr.write("Authenticated.\n\n");
|
|
106
131
|
return tokens;
|
|
107
132
|
}
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,yCAAyC;;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/proxy.js
CHANGED
|
@@ -1,40 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// MCP proxy —
|
|
3
|
-
// When an agent spawns `npx cohvu` (non-TTY stdin), this bridges
|
|
4
|
-
// stdio MCP ↔ Streamable HTTP transport to the Cohvu API.
|
|
2
|
+
// MCP proxy — thin stateless translator.
|
|
5
3
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
4
|
+
// Agent speaks MCP on stdin. Proxy speaks REST to the backend.
|
|
5
|
+
// No sessions. No state. No reconnection. Each tool call is
|
|
6
|
+
// an independent HTTP request.
|
|
9
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
8
|
exports.proxy = proxy;
|
|
11
9
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
12
|
-
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
13
10
|
const auth_1 = require("./auth");
|
|
14
11
|
const setup_1 = require("./setup");
|
|
15
12
|
async function proxy() {
|
|
16
13
|
const baseUrl = process.env.COHVU_API_URL ?? "https://api.cohvu.com";
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
// Resolve auth — prefer API key (long-lived), fall back to JWT
|
|
15
|
+
let authHeader;
|
|
16
|
+
const apiKey = (0, auth_1.getApiKey)();
|
|
17
|
+
if (apiKey) {
|
|
18
|
+
authHeader = `Bearer ${apiKey}`;
|
|
21
19
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
stdioTransport.send({
|
|
20
|
+
else {
|
|
21
|
+
try {
|
|
22
|
+
const auth = await (0, auth_1.getAuthToken)(baseUrl);
|
|
23
|
+
authHeader = `Bearer ${auth.accessToken}`;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// Not logged in — respond to every message with auth error
|
|
27
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
28
|
+
transport.onmessage = async (message) => {
|
|
29
|
+
const msg = message;
|
|
30
|
+
if (msg.id === undefined)
|
|
31
|
+
return;
|
|
32
|
+
transport.send({
|
|
38
33
|
jsonrpc: "2.0",
|
|
39
34
|
id: msg.id,
|
|
40
35
|
error: {
|
|
@@ -42,274 +37,122 @@ async function proxy() {
|
|
|
42
37
|
message: "Cohvu is not connected. Run `npx cohvu` in your terminal to sign in.",
|
|
43
38
|
},
|
|
44
39
|
}).catch(() => { });
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
// Silently update instruction files if content has changed since last login
|
|
51
|
-
(0, setup_1.refreshInstructions)();
|
|
52
|
-
const stdioTransport = new stdio_js_1.StdioServerTransport();
|
|
53
|
-
const headers = {
|
|
54
|
-
Authorization: `Bearer ${accessToken}`,
|
|
55
|
-
};
|
|
56
|
-
// ---------------------------------------------------------------------------
|
|
57
|
-
// Token refresh — deduplicates concurrent attempts with backoff
|
|
58
|
-
// ---------------------------------------------------------------------------
|
|
59
|
-
let refreshing = null;
|
|
60
|
-
let refreshFailures = 0;
|
|
61
|
-
let refreshBackoffUntil = 0;
|
|
62
|
-
async function refreshTokenNow() {
|
|
63
|
-
if (Date.now() < refreshBackoffUntil)
|
|
64
|
-
return false;
|
|
65
|
-
if (refreshing) {
|
|
66
|
-
await refreshing;
|
|
67
|
-
return refreshFailures === 0;
|
|
40
|
+
};
|
|
41
|
+
await transport.start();
|
|
42
|
+
return;
|
|
68
43
|
}
|
|
69
|
-
let ok = false;
|
|
70
|
-
refreshing = (async () => {
|
|
71
|
-
try {
|
|
72
|
-
const auth = await (0, auth_1.getAuthToken)(baseUrl);
|
|
73
|
-
headers.Authorization = `Bearer ${auth.accessToken}`;
|
|
74
|
-
refreshFailures = 0;
|
|
75
|
-
ok = true;
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
refreshFailures++;
|
|
79
|
-
if (refreshFailures >= 3) {
|
|
80
|
-
refreshBackoffUntil = Date.now() + 30_000;
|
|
81
|
-
process.stderr.write("Token refresh failed 3 times. Backing off 30s.\n");
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
process.stderr.write("Token refresh failed.\n");
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
finally {
|
|
88
|
-
refreshing = null;
|
|
89
|
-
}
|
|
90
|
-
})();
|
|
91
|
-
await refreshing;
|
|
92
|
-
return ok;
|
|
93
44
|
}
|
|
94
|
-
//
|
|
95
|
-
|
|
45
|
+
// Silently update instruction files
|
|
46
|
+
(0, setup_1.refreshInstructions)();
|
|
47
|
+
// Fetch manifest (tool list + instructions) — keep retrying until we get it
|
|
48
|
+
let manifest = null;
|
|
49
|
+
async function fetchManifest() {
|
|
96
50
|
try {
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
catch {
|
|
101
|
-
await new Promise((r) => setTimeout(r, 5000));
|
|
102
|
-
try {
|
|
103
|
-
const auth = await (0, auth_1.getAuthToken)(baseUrl);
|
|
104
|
-
headers.Authorization = `Bearer ${auth.accessToken}`;
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
process.stderr.write("Token refresh failed. Session may expire.\n");
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}, 50 * 60 * 1000);
|
|
111
|
-
// ---------------------------------------------------------------------------
|
|
112
|
-
// Resilient fetch: timeouts, network retry, 401 refresh, session loss detect
|
|
113
|
-
// ---------------------------------------------------------------------------
|
|
114
|
-
let sessionLost = false;
|
|
115
|
-
const resilientFetch = async (url, init) => {
|
|
116
|
-
const applyTimeout = (opts) => {
|
|
117
|
-
const ms = opts?.method === 'POST' ? 300_000 : 60_000;
|
|
118
|
-
const timeout = AbortSignal.timeout(ms);
|
|
119
|
-
if (!opts)
|
|
120
|
-
return { signal: timeout };
|
|
121
|
-
const combined = opts.signal
|
|
122
|
-
? AbortSignal.any([opts.signal, timeout])
|
|
123
|
-
: timeout;
|
|
124
|
-
return { ...opts, signal: combined };
|
|
125
|
-
};
|
|
126
|
-
async function attempt(opts) {
|
|
127
|
-
try {
|
|
128
|
-
return await fetch(url, applyTimeout(opts));
|
|
129
|
-
}
|
|
130
|
-
catch (err) {
|
|
131
|
-
await new Promise((r) => setTimeout(r, 1000));
|
|
132
|
-
try {
|
|
133
|
-
return await fetch(url, applyTimeout(opts));
|
|
134
|
-
}
|
|
135
|
-
catch {
|
|
136
|
-
throw err;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
const res = await attempt(init);
|
|
141
|
-
if (res.status === 401) {
|
|
142
|
-
const ok = await refreshTokenNow();
|
|
143
|
-
if (!ok)
|
|
144
|
-
return res;
|
|
145
|
-
const retryInit = init ? { ...init, headers: { ...init.headers, ...headers } } : { headers };
|
|
146
|
-
return attempt(retryInit);
|
|
147
|
-
}
|
|
148
|
-
// Session expired or lost — signal reconnect
|
|
149
|
-
if (res.status === 410 || res.status === 404) {
|
|
150
|
-
sessionLost = true;
|
|
151
|
-
}
|
|
152
|
-
return res;
|
|
153
|
-
};
|
|
154
|
-
// ---------------------------------------------------------------------------
|
|
155
|
-
// Transport lifecycle — create, connect, reconnect
|
|
156
|
-
// ---------------------------------------------------------------------------
|
|
157
|
-
let httpTransport = null;
|
|
158
|
-
let reconnecting = false;
|
|
159
|
-
let reconnectAttempts = 0;
|
|
160
|
-
function createTransport() {
|
|
161
|
-
const transport = new streamableHttp_js_1.StreamableHTTPClientTransport(new URL(`${baseUrl}/v1/mcp`), { requestInit: { headers }, fetch: resilientFetch });
|
|
162
|
-
transport.onmessage = (message) => {
|
|
163
|
-
reconnectAttempts = 0;
|
|
164
|
-
stdioTransport.send(message).catch((error) => {
|
|
165
|
-
process.stderr.write(`Error forwarding to client: ${error}\n`);
|
|
51
|
+
const res = await fetch(`${baseUrl}/v1/tools/manifest`, {
|
|
52
|
+
headers: { Authorization: authHeader },
|
|
53
|
+
signal: AbortSignal.timeout(10_000),
|
|
166
54
|
});
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
// Don't exit — reconnect
|
|
170
|
-
if (!reconnecting) {
|
|
171
|
-
process.stderr.write("Transport closed. Reconnecting...\n");
|
|
172
|
-
reconnect();
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
transport.onerror = (error) => {
|
|
176
|
-
process.stderr.write(`Transport error: ${error}\n`);
|
|
177
|
-
};
|
|
178
|
-
return transport;
|
|
179
|
-
}
|
|
180
|
-
async function connect() {
|
|
181
|
-
try {
|
|
182
|
-
const transport = createTransport();
|
|
183
|
-
await transport.start();
|
|
184
|
-
httpTransport = transport;
|
|
185
|
-
sessionLost = false;
|
|
186
|
-
reconnecting = false;
|
|
187
|
-
reconnectAttempts = 0;
|
|
188
|
-
return true;
|
|
189
|
-
}
|
|
190
|
-
catch (error) {
|
|
191
|
-
process.stderr.write(`Connection failed: ${error}\n`);
|
|
192
|
-
return false;
|
|
55
|
+
if (res.ok)
|
|
56
|
+
return (await res.json());
|
|
193
57
|
}
|
|
58
|
+
catch { }
|
|
59
|
+
return null;
|
|
194
60
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const old = httpTransport;
|
|
201
|
-
httpTransport = null;
|
|
202
|
-
if (old) {
|
|
203
|
-
old.onclose = () => { };
|
|
204
|
-
old.onerror = () => { };
|
|
205
|
-
old.close().catch(() => { });
|
|
206
|
-
}
|
|
207
|
-
// Retry with exponential backoff
|
|
208
|
-
while (reconnecting) {
|
|
209
|
-
const delay = Math.min(1000 * Math.pow(2, Math.min(reconnectAttempts, 5)), 30_000);
|
|
210
|
-
reconnectAttempts++;
|
|
211
|
-
if (reconnectAttempts > 1) {
|
|
212
|
-
process.stderr.write(`Reconnecting (attempt ${reconnectAttempts}, ${delay}ms delay)...\n`);
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
process.stderr.write("Reconnecting...\n");
|
|
216
|
-
}
|
|
217
|
-
await new Promise((r) => setTimeout(r, delay));
|
|
218
|
-
// Refresh token before reconnecting in case it expired
|
|
219
|
-
try {
|
|
220
|
-
const auth = await (0, auth_1.getAuthToken)(baseUrl);
|
|
221
|
-
headers.Authorization = `Bearer ${auth.accessToken}`;
|
|
222
|
-
}
|
|
223
|
-
catch { }
|
|
224
|
-
if (await connect()) {
|
|
225
|
-
process.stderr.write("Reconnected.\n");
|
|
226
|
-
// Flush any queued messages
|
|
227
|
-
flushPending();
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
61
|
+
for (let attempt = 0; attempt < 10; attempt++) {
|
|
62
|
+
manifest = await fetchManifest();
|
|
63
|
+
if (manifest)
|
|
64
|
+
break;
|
|
65
|
+
await new Promise((r) => setTimeout(r, 1000 * Math.min(attempt + 1, 5)));
|
|
231
66
|
}
|
|
232
|
-
//
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
67
|
+
// Build MCP protocol responses (or error responses if manifest unavailable)
|
|
68
|
+
const initializeResult = manifest
|
|
69
|
+
? {
|
|
70
|
+
protocolVersion: "2025-03-26",
|
|
71
|
+
capabilities: { tools: {} },
|
|
72
|
+
serverInfo: manifest.serverInfo,
|
|
73
|
+
instructions: manifest.instructions,
|
|
74
|
+
}
|
|
75
|
+
: {
|
|
76
|
+
protocolVersion: "2025-03-26",
|
|
77
|
+
capabilities: { tools: {} },
|
|
78
|
+
serverInfo: { name: "cohvu", version: "0.1.0" },
|
|
79
|
+
instructions: "Cohvu is temporarily unavailable. Tool calls will be retried.",
|
|
80
|
+
};
|
|
81
|
+
const toolsListResult = manifest
|
|
82
|
+
? {
|
|
83
|
+
tools: manifest.tools.map((t) => ({
|
|
84
|
+
name: t.name,
|
|
85
|
+
description: t.description,
|
|
86
|
+
inputSchema: t.inputSchema,
|
|
87
|
+
})),
|
|
88
|
+
}
|
|
89
|
+
: { tools: [] };
|
|
90
|
+
// Call backend tool endpoint
|
|
91
|
+
async function callTool(name, args) {
|
|
92
|
+
const res = await fetch(`${baseUrl}/v1/tools/call`, {
|
|
93
|
+
method: "POST",
|
|
94
|
+
headers: {
|
|
95
|
+
"Content-Type": "application/json",
|
|
96
|
+
Authorization: authHeader,
|
|
97
|
+
},
|
|
98
|
+
body: JSON.stringify({ tool: name, arguments: args }),
|
|
99
|
+
signal: AbortSignal.timeout(30_000),
|
|
100
|
+
});
|
|
101
|
+
if (!res.ok) {
|
|
102
|
+
const body = await res.text().catch(() => "Unknown error");
|
|
103
|
+
return {
|
|
104
|
+
content: [{ type: "text", text: body }],
|
|
105
|
+
isError: true,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return await res.json();
|
|
253
109
|
}
|
|
254
|
-
//
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
stdioTransport.onmessage = async (message) => {
|
|
110
|
+
// Start stdio transport and handle MCP messages
|
|
111
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
112
|
+
transport.onmessage = async (message) => {
|
|
258
113
|
const msg = message;
|
|
259
|
-
//
|
|
260
|
-
if (
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
114
|
+
// Notifications (no id) — acknowledge silently
|
|
115
|
+
if (msg.id === undefined)
|
|
116
|
+
return;
|
|
117
|
+
try {
|
|
118
|
+
switch (msg.method) {
|
|
119
|
+
case "initialize":
|
|
120
|
+
await transport.send({ jsonrpc: "2.0", id: msg.id, result: initializeResult });
|
|
121
|
+
break;
|
|
122
|
+
case "tools/list":
|
|
123
|
+
await transport.send({ jsonrpc: "2.0", id: msg.id, result: toolsListResult });
|
|
124
|
+
break;
|
|
125
|
+
case "ping":
|
|
126
|
+
await transport.send({ jsonrpc: "2.0", id: msg.id, result: {} });
|
|
127
|
+
break;
|
|
128
|
+
case "tools/call": {
|
|
129
|
+
const params = msg.params;
|
|
130
|
+
const result = await callTool(params.name, params.arguments ?? {});
|
|
131
|
+
await transport.send({ jsonrpc: "2.0", id: msg.id, result: result });
|
|
132
|
+
break;
|
|
268
133
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
stdioTransport.send({
|
|
134
|
+
default:
|
|
135
|
+
await transport.send({
|
|
272
136
|
jsonrpc: "2.0",
|
|
273
137
|
id: msg.id,
|
|
274
|
-
error: {
|
|
275
|
-
|
|
276
|
-
message: "Cohvu is reconnecting. Please try again in a moment.",
|
|
277
|
-
},
|
|
278
|
-
}).catch(() => { });
|
|
279
|
-
}
|
|
138
|
+
error: { code: -32601, message: `Method not found: ${msg.method}` },
|
|
139
|
+
});
|
|
280
140
|
}
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
try {
|
|
284
|
-
await httpTransport.send(message);
|
|
285
141
|
}
|
|
286
|
-
catch (
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
142
|
+
catch (err) {
|
|
143
|
+
await transport.send({
|
|
144
|
+
jsonrpc: "2.0",
|
|
145
|
+
id: msg.id,
|
|
146
|
+
error: {
|
|
147
|
+
code: -32603,
|
|
148
|
+
message: err instanceof Error ? err.message : "Internal error",
|
|
149
|
+
},
|
|
150
|
+
}).catch(() => { });
|
|
293
151
|
}
|
|
294
152
|
};
|
|
295
|
-
|
|
296
|
-
// Agent disconnected — clean up and exit
|
|
297
|
-
reconnecting = false;
|
|
298
|
-
if (httpTransport) {
|
|
299
|
-
httpTransport.onclose = () => { };
|
|
300
|
-
httpTransport.close().catch(() => { });
|
|
301
|
-
}
|
|
153
|
+
transport.onclose = () => {
|
|
302
154
|
process.exit(0);
|
|
303
155
|
};
|
|
304
|
-
|
|
305
|
-
process.stderr.write(`Stdio transport error: ${error}\n`);
|
|
306
|
-
};
|
|
307
|
-
// ---------------------------------------------------------------------------
|
|
308
|
-
// Start
|
|
309
|
-
// ---------------------------------------------------------------------------
|
|
310
|
-
await stdioTransport.start();
|
|
311
|
-
if (!await connect()) {
|
|
312
|
-
reconnect();
|
|
313
|
-
}
|
|
156
|
+
await transport.start();
|
|
314
157
|
}
|
|
315
158
|
//# sourceMappingURL=proxy.js.map
|
package/dist/proxy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":";AAAA,
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"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"}
|