cohvu 1.0.23 → 2.0.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/dist/auth.d.ts +3 -0
- package/dist/auth.js +25 -0
- package/dist/auth.js.map +1 -1
- package/dist/proxy.js +127 -277
- 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,129 @@ 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) — retry until we get it
|
|
48
|
+
let manifest = null;
|
|
49
|
+
for (let attempt = 0; attempt < 5; attempt++) {
|
|
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
|
-
|
|
170
|
-
if (!reconnecting) {
|
|
171
|
-
process.stderr.write("Transport closed. Reconnecting...\n");
|
|
172
|
-
reconnect();
|
|
55
|
+
if (res.ok) {
|
|
56
|
+
manifest = (await res.json());
|
|
57
|
+
break;
|
|
173
58
|
}
|
|
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;
|
|
193
59
|
}
|
|
60
|
+
catch { }
|
|
61
|
+
if (attempt < 4)
|
|
62
|
+
await new Promise((r) => setTimeout(r, 1000 * (attempt + 1)));
|
|
194
63
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
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
|
-
}
|
|
64
|
+
if (!manifest) {
|
|
65
|
+
// Couldn't reach backend — use hardcoded fallback
|
|
66
|
+
manifest = {
|
|
67
|
+
serverInfo: { name: "cohvu", version: "0.1.0" },
|
|
68
|
+
instructions: "",
|
|
69
|
+
tools: [
|
|
70
|
+
{
|
|
71
|
+
name: "read",
|
|
72
|
+
description: "Read from project memory. Be specific — it helps get relevant results.",
|
|
73
|
+
inputSchema: { type: "object", properties: { query: { type: "string" } }, required: ["query"] },
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: "contribute",
|
|
77
|
+
description: "Contribute to project memory. Contribute what helps understand the project.",
|
|
78
|
+
inputSchema: { type: "object", properties: { text: { type: "string" } }, required: ["text"] },
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
};
|
|
231
82
|
}
|
|
232
|
-
//
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
83
|
+
// Build MCP protocol responses
|
|
84
|
+
const initializeResult = {
|
|
85
|
+
protocolVersion: "2025-03-26",
|
|
86
|
+
capabilities: { tools: {} },
|
|
87
|
+
serverInfo: manifest.serverInfo,
|
|
88
|
+
instructions: manifest.instructions,
|
|
89
|
+
};
|
|
90
|
+
const toolsListResult = {
|
|
91
|
+
tools: manifest.tools.map((t) => ({
|
|
92
|
+
name: t.name,
|
|
93
|
+
description: t.description,
|
|
94
|
+
inputSchema: t.inputSchema,
|
|
95
|
+
})),
|
|
96
|
+
};
|
|
97
|
+
// Call backend tool endpoint
|
|
98
|
+
async function callTool(name, args) {
|
|
99
|
+
const res = await fetch(`${baseUrl}/v1/tools/call`, {
|
|
100
|
+
method: "POST",
|
|
101
|
+
headers: {
|
|
102
|
+
"Content-Type": "application/json",
|
|
103
|
+
Authorization: authHeader,
|
|
104
|
+
},
|
|
105
|
+
body: JSON.stringify({ tool: name, arguments: args }),
|
|
106
|
+
signal: AbortSignal.timeout(30_000),
|
|
107
|
+
});
|
|
108
|
+
if (!res.ok) {
|
|
109
|
+
const body = await res.text().catch(() => "Unknown error");
|
|
110
|
+
return {
|
|
111
|
+
content: [{ type: "text", text: body }],
|
|
112
|
+
isError: true,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return await res.json();
|
|
253
116
|
}
|
|
254
|
-
//
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
stdioTransport.onmessage = async (message) => {
|
|
117
|
+
// Start stdio transport and handle MCP messages
|
|
118
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
119
|
+
transport.onmessage = async (message) => {
|
|
258
120
|
const msg = message;
|
|
259
|
-
//
|
|
260
|
-
if (
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
121
|
+
// Notifications (no id) — acknowledge silently
|
|
122
|
+
if (msg.id === undefined)
|
|
123
|
+
return;
|
|
124
|
+
try {
|
|
125
|
+
switch (msg.method) {
|
|
126
|
+
case "initialize":
|
|
127
|
+
await transport.send({ jsonrpc: "2.0", id: msg.id, result: initializeResult });
|
|
128
|
+
break;
|
|
129
|
+
case "tools/list":
|
|
130
|
+
await transport.send({ jsonrpc: "2.0", id: msg.id, result: toolsListResult });
|
|
131
|
+
break;
|
|
132
|
+
case "ping":
|
|
133
|
+
await transport.send({ jsonrpc: "2.0", id: msg.id, result: {} });
|
|
134
|
+
break;
|
|
135
|
+
case "tools/call": {
|
|
136
|
+
const params = msg.params;
|
|
137
|
+
const result = await callTool(params.name, params.arguments ?? {});
|
|
138
|
+
await transport.send({ jsonrpc: "2.0", id: msg.id, result: result });
|
|
139
|
+
break;
|
|
268
140
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
stdioTransport.send({
|
|
141
|
+
default:
|
|
142
|
+
await transport.send({
|
|
272
143
|
jsonrpc: "2.0",
|
|
273
144
|
id: msg.id,
|
|
274
|
-
error: {
|
|
275
|
-
|
|
276
|
-
message: "Cohvu is reconnecting. Please try again in a moment.",
|
|
277
|
-
},
|
|
278
|
-
}).catch(() => { });
|
|
279
|
-
}
|
|
145
|
+
error: { code: -32601, message: `Method not found: ${msg.method}` },
|
|
146
|
+
});
|
|
280
147
|
}
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
try {
|
|
284
|
-
await httpTransport.send(message);
|
|
285
148
|
}
|
|
286
|
-
catch (
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
149
|
+
catch (err) {
|
|
150
|
+
await transport.send({
|
|
151
|
+
jsonrpc: "2.0",
|
|
152
|
+
id: msg.id,
|
|
153
|
+
error: {
|
|
154
|
+
code: -32603,
|
|
155
|
+
message: err instanceof Error ? err.message : "Internal error",
|
|
156
|
+
},
|
|
157
|
+
}).catch(() => { });
|
|
293
158
|
}
|
|
294
159
|
};
|
|
295
|
-
|
|
296
|
-
// Agent disconnected — clean up and exit
|
|
297
|
-
reconnecting = false;
|
|
298
|
-
if (httpTransport) {
|
|
299
|
-
httpTransport.onclose = () => { };
|
|
300
|
-
httpTransport.close().catch(() => { });
|
|
301
|
-
}
|
|
160
|
+
transport.onclose = () => {
|
|
302
161
|
process.exit(0);
|
|
303
162
|
};
|
|
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
|
-
}
|
|
163
|
+
await transport.start();
|
|
314
164
|
}
|
|
315
165
|
//# 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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"}
|