@clawchatsai/connector 0.0.18 → 0.0.20
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-handler.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -2
- package/dist/shim.d.ts +5 -0
- package/dist/shim.js +39 -2
- package/package.json +1 -1
package/dist/auth-handler.js
CHANGED
|
@@ -25,7 +25,7 @@ const blockedConnections = new Map(); // connectionId → unblock timestamp
|
|
|
25
25
|
let lastUsedTotpStep = 0;
|
|
26
26
|
/** Max nonces to prevent memory leaks from connection storms */
|
|
27
27
|
const MAX_PENDING_NONCES = 10;
|
|
28
|
-
const AUTH_TIMEOUT_MS =
|
|
28
|
+
const AUTH_TIMEOUT_MS = 60_000; // 60s — enough time to open authenticator app and enter code
|
|
29
29
|
const MAX_FAILURES = 5;
|
|
30
30
|
const BLOCK_DURATION_MS = 60_000;
|
|
31
31
|
// ---------------------------------------------------------------------------
|
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* Spec: specs/multitenant-p2p.md sections 6.1-6.2
|
|
11
11
|
*/
|
|
12
12
|
export declare const PLUGIN_ID = "connector";
|
|
13
|
-
export declare const PLUGIN_VERSION = "0.0.
|
|
13
|
+
export declare const PLUGIN_VERSION = "0.0.20";
|
|
14
14
|
interface PluginServiceContext {
|
|
15
15
|
stateDir: string;
|
|
16
16
|
logger: {
|
package/dist/index.js
CHANGED
|
@@ -22,7 +22,7 @@ import { generateSessionSecret } from './session-token.js';
|
|
|
22
22
|
// Inline from shared/api-version.ts to avoid rootDir conflict
|
|
23
23
|
const CURRENT_API_VERSION = 1;
|
|
24
24
|
export const PLUGIN_ID = 'connector';
|
|
25
|
-
export const PLUGIN_VERSION = '0.0.
|
|
25
|
+
export const PLUGIN_VERSION = '0.0.20';
|
|
26
26
|
/** Max DataChannel message size (~256KB, leave room for envelope) */
|
|
27
27
|
const MAX_DC_MESSAGE_SIZE = 256 * 1024;
|
|
28
28
|
/** Active DataChannel connections: connectionId → send function */
|
|
@@ -327,7 +327,15 @@ function setupDataChannelHandler(dc, connectionId, ctx) {
|
|
|
327
327
|
// Pre-auth non-auth message — drop silently
|
|
328
328
|
return;
|
|
329
329
|
case 'pass':
|
|
330
|
-
// Already authenticated —
|
|
330
|
+
// Already authenticated — but verify this connection is actually
|
|
331
|
+
// in connectedClients. If auth_timeout deleted the session but the
|
|
332
|
+
// DC is still open, we'd get 'pass' for an un-authed connection.
|
|
333
|
+
// Re-initiate auth instead of processing the message.
|
|
334
|
+
if (!connectedClients.has(connectionId)) {
|
|
335
|
+
ctx.logger.warn(`Stale connection ${connectionId} — re-initiating auth`);
|
|
336
|
+
initAuth(dc, connectionId);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
331
339
|
break;
|
|
332
340
|
}
|
|
333
341
|
// Authenticated message processing
|
package/dist/shim.d.ts
CHANGED
|
@@ -56,6 +56,11 @@ declare class FakeRes extends Writable {
|
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
58
58
|
* Dispatch an RPC request through handleRequest and return the response.
|
|
59
|
+
*
|
|
60
|
+
* Safety nets:
|
|
61
|
+
* 1. If handleRequest() throws, we return a 500 with the error message.
|
|
62
|
+
* 2. If res.finished never resolves (handleRequest forgot to call res.end()),
|
|
63
|
+
* we time out after RPC_TIMEOUT_MS and return a 504.
|
|
59
64
|
*/
|
|
60
65
|
export declare function dispatchRpc(rpc: RpcRequest, handleRequest: HandleRequestFn): Promise<RpcResponse>;
|
|
61
66
|
export {};
|
package/dist/shim.js
CHANGED
|
@@ -137,14 +137,51 @@ function tryJsonParse(buf) {
|
|
|
137
137
|
return buf.toString('base64');
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
+
/** RPC dispatch timeout — if handleRequest doesn't call res.end() within
|
|
141
|
+
* this window, we return a 504 so the browser isn't left hanging. */
|
|
142
|
+
const RPC_TIMEOUT_MS = 30_000;
|
|
140
143
|
/**
|
|
141
144
|
* Dispatch an RPC request through handleRequest and return the response.
|
|
145
|
+
*
|
|
146
|
+
* Safety nets:
|
|
147
|
+
* 1. If handleRequest() throws, we return a 500 with the error message.
|
|
148
|
+
* 2. If res.finished never resolves (handleRequest forgot to call res.end()),
|
|
149
|
+
* we time out after RPC_TIMEOUT_MS and return a 504.
|
|
142
150
|
*/
|
|
143
151
|
export async function dispatchRpc(rpc, handleRequest) {
|
|
144
152
|
const req = new FakeReq(rpc);
|
|
145
153
|
const res = new FakeRes();
|
|
146
|
-
|
|
147
|
-
|
|
154
|
+
try {
|
|
155
|
+
await handleRequest(req, res);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
159
|
+
const stack = err instanceof Error ? err.stack : undefined;
|
|
160
|
+
console.error(`[RPC] handleRequest threw for ${rpc.method} ${rpc.url}: ${message}`);
|
|
161
|
+
if (stack)
|
|
162
|
+
console.error(stack);
|
|
163
|
+
return {
|
|
164
|
+
id: rpc.id,
|
|
165
|
+
status: 500,
|
|
166
|
+
headers: {},
|
|
167
|
+
body: JSON.stringify({ error: 'Internal server error', detail: message }),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
// Wait for res.finished, but give up after RPC_TIMEOUT_MS
|
|
171
|
+
const result = await Promise.race([
|
|
172
|
+
res.finished,
|
|
173
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('RPC_TIMEOUT')), RPC_TIMEOUT_MS)),
|
|
174
|
+
]).catch((err) => {
|
|
175
|
+
console.error(`[RPC] Response never completed for ${rpc.method} ${rpc.url}: ${err.message}`);
|
|
176
|
+
return {
|
|
177
|
+
status: 504,
|
|
178
|
+
headers: {},
|
|
179
|
+
body: Buffer.from(JSON.stringify({
|
|
180
|
+
error: 'Gateway timeout',
|
|
181
|
+
detail: `Plugin did not respond within ${RPC_TIMEOUT_MS / 1000}s for ${rpc.method} ${rpc.url}`,
|
|
182
|
+
})),
|
|
183
|
+
};
|
|
184
|
+
});
|
|
148
185
|
return {
|
|
149
186
|
id: rpc.id,
|
|
150
187
|
status: result.status,
|