@clawchatsai/connector 0.1.5 → 0.1.7
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/index.js +21 -2
- package/package.json +1 -1
- package/server/gateway.js +27 -0
- package/server/index.js +1 -0
package/dist/index.js
CHANGED
|
@@ -564,6 +564,7 @@ function setupDataChannelHandler(dc, connectionId, ctx) {
|
|
|
564
564
|
dc.onClosed(() => {
|
|
565
565
|
connectedClients.delete(connectionId);
|
|
566
566
|
cleanupAuth(connectionId);
|
|
567
|
+
app?.debugLogger.handleClientDisconnect(dc);
|
|
567
568
|
});
|
|
568
569
|
}
|
|
569
570
|
/**
|
|
@@ -661,6 +662,24 @@ function processAuthenticatedMessage(dc, connectionId, msg, ctx) {
|
|
|
661
662
|
case 'ping':
|
|
662
663
|
dc.send(JSON.stringify({ type: 'pong' }));
|
|
663
664
|
break;
|
|
665
|
+
case 'clawchats':
|
|
666
|
+
case 'shellchat': {
|
|
667
|
+
if (!app)
|
|
668
|
+
break;
|
|
669
|
+
const action = msg['action'];
|
|
670
|
+
if (action === 'debug-start') {
|
|
671
|
+
const ts = typeof msg['ts'] === 'string' ? msg['ts'] : new Date().toISOString();
|
|
672
|
+
const r = app.debugLogger.start(ts, dc);
|
|
673
|
+
dc.send(JSON.stringify(r.error === 'already-active'
|
|
674
|
+
? { type: 'clawchats', event: 'debug-error', error: 'Recording already active in another tab', sessionId: r.sessionId }
|
|
675
|
+
: { type: 'clawchats', event: 'debug-started', sessionId: r.sessionId }));
|
|
676
|
+
}
|
|
677
|
+
else if (action === 'debug-dump') {
|
|
678
|
+
const r = app.debugLogger.saveDump(msg);
|
|
679
|
+
dc.send(JSON.stringify({ type: 'clawchats', event: 'debug-saved', sessionId: r.sessionId, files: r.files }));
|
|
680
|
+
}
|
|
681
|
+
break;
|
|
682
|
+
}
|
|
664
683
|
default:
|
|
665
684
|
// Unknown message type — ignore silently.
|
|
666
685
|
// (Sending an error response would break heartbeat backward-compat
|
|
@@ -1055,13 +1074,13 @@ async function handleSetupTotp() {
|
|
|
1055
1074
|
}
|
|
1056
1075
|
else {
|
|
1057
1076
|
// Expired — generate a fresh one
|
|
1058
|
-
totpSecret = generateTotpSecret();
|
|
1077
|
+
totpSecret = process.env.CLAWCHATS_DEV_TOTP_SECRET || generateTotpSecret();
|
|
1059
1078
|
config.totpPending = { secret: totpSecret, generatedAt: new Date().toISOString() };
|
|
1060
1079
|
saveConfig(config);
|
|
1061
1080
|
}
|
|
1062
1081
|
}
|
|
1063
1082
|
else {
|
|
1064
|
-
totpSecret = generateTotpSecret();
|
|
1083
|
+
totpSecret = process.env.CLAWCHATS_DEV_TOTP_SECRET || generateTotpSecret();
|
|
1065
1084
|
config.totpPending = { secret: totpSecret, generatedAt: new Date().toISOString() };
|
|
1066
1085
|
saveConfig(config);
|
|
1067
1086
|
}
|
package/package.json
CHANGED
package/server/gateway.js
CHANGED
|
@@ -22,6 +22,10 @@ export class GatewayClient {
|
|
|
22
22
|
this.streamState = new Map();
|
|
23
23
|
this.activityLogs = new Map();
|
|
24
24
|
this._pendingTitleGens = new Map();
|
|
25
|
+
// Runs we've already synthesized a streaming-end{reason:'error'} for
|
|
26
|
+
// (agent lifecycle:error emitted but no chat state:error ever will). Prevents
|
|
27
|
+
// double-fires across retries and cross-path dedup with handleChatEvent.
|
|
28
|
+
this._syntheticErrorRuns = new Set();
|
|
25
29
|
|
|
26
30
|
// On startup: mark any pending activity log messages from previous crashed/restarted sessions
|
|
27
31
|
// as interrupted. Without this, stale pending=true rows survive gateway restarts and cause
|
|
@@ -402,6 +406,29 @@ export class GatewayClient {
|
|
|
402
406
|
log.finalSteps = cleanSteps;
|
|
403
407
|
log.finalSummary = generateActivitySummary(log.steps);
|
|
404
408
|
// Note: activityLogs entry is kept until _popActivityLogForSession cleans it up
|
|
409
|
+
//
|
|
410
|
+
// Fallback: if the gateway never emitted any chat.* events for this session
|
|
411
|
+
// (e.g. pre-reply provider error on a non-webchat surface where the chat
|
|
412
|
+
// broadcast is gated off upstream), handleChatEvent won't fire a
|
|
413
|
+
// streaming-end and the UI stays locked on "thinking…" forever. Synthesize
|
|
414
|
+
// one here so the frontend's existing error path (`reason: 'error'`) runs.
|
|
415
|
+
if (data?.phase === 'error' && !this.streamState.has(sessionKey) && !this._syntheticErrorRuns.has(runId)) {
|
|
416
|
+
this._syntheticErrorRuns.add(runId);
|
|
417
|
+
const parsed = parseSessionKey(sessionKey);
|
|
418
|
+
if (parsed) {
|
|
419
|
+
this.broadcastToBrowsers(JSON.stringify({
|
|
420
|
+
type: 'clawchats',
|
|
421
|
+
event: 'streaming-end',
|
|
422
|
+
threadId: parsed.threadId,
|
|
423
|
+
workspace: parsed.workspace,
|
|
424
|
+
reason: 'error',
|
|
425
|
+
errorMessage: data?.error || 'Agent failed before reply',
|
|
426
|
+
}));
|
|
427
|
+
}
|
|
428
|
+
// Bound the set — auto-evict after the retry window so long-lived
|
|
429
|
+
// processes don't leak. 5 min is far longer than any retry chain.
|
|
430
|
+
setTimeout(() => this._syntheticErrorRuns.delete(runId), 5 * 60 * 1000);
|
|
431
|
+
}
|
|
405
432
|
}
|
|
406
433
|
}
|
|
407
434
|
|