@yeaft/webchat-agent 1.0.61 → 1.0.63
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.
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const DEFAULT_AGENT_HEARTBEAT_TIMEOUT_MS = 180000;
|
|
2
|
+
|
|
3
|
+
function parsePositiveInt(value, fallback) {
|
|
4
|
+
const n = Number(value);
|
|
5
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const AGENT_HEARTBEAT_TIMEOUT_MS = parsePositiveInt(
|
|
9
|
+
process.env.YEAFT_AGENT_HEARTBEAT_TIMEOUT_MS || process.env.AGENT_HEARTBEAT_TIMEOUT_MS,
|
|
10
|
+
DEFAULT_AGENT_HEARTBEAT_TIMEOUT_MS,
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
export function shouldReconnectForHeartbeat(lastPongAt, now = Date.now(), timeoutMs = AGENT_HEARTBEAT_TIMEOUT_MS) {
|
|
14
|
+
return Number.isFinite(lastPongAt) && lastPongAt > 0 && (now - lastPongAt) > timeoutMs;
|
|
15
|
+
}
|
package/connection/heartbeat.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import WebSocket from 'ws';
|
|
2
2
|
import ctx from '../context.js';
|
|
3
|
+
import { shouldReconnectForHeartbeat } from './heartbeat-policy.js';
|
|
3
4
|
|
|
4
5
|
export function startAgentHeartbeat() {
|
|
5
6
|
stopAgentHeartbeat();
|
|
@@ -16,8 +17,9 @@ export function startAgentHeartbeat() {
|
|
|
16
17
|
if (!ctx.ws || ctx.ws.readyState !== WebSocket.OPEN) return;
|
|
17
18
|
|
|
18
19
|
// 检查上次 pong 是否超时
|
|
19
|
-
const
|
|
20
|
-
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
const sincePong = now - ctx.lastPongAt;
|
|
22
|
+
if (shouldReconnectForHeartbeat(ctx.lastPongAt, now)) {
|
|
21
23
|
console.warn(`[Heartbeat] No pong for ${Math.round(sincePong / 1000)}s, reconnecting...`);
|
|
22
24
|
ctx.ws.terminate();
|
|
23
25
|
return;
|
package/package.json
CHANGED
|
@@ -266,15 +266,18 @@ export function buildRelevantScopes({ sessionId, chatId, vpId, extra } = {}) {
|
|
|
266
266
|
scopes.push(`chat/${chatId}`);
|
|
267
267
|
if (vpId) scopes.push(`chat/${chatId}/vp/${vpId}`);
|
|
268
268
|
} else if (sessionId) {
|
|
269
|
-
// Read
|
|
270
|
-
//
|
|
271
|
-
//
|
|
272
|
-
//
|
|
269
|
+
// Read every persisted Session spelling that can exist on disk. Current
|
|
270
|
+
// Dream writers use `sessions/<id>`; older readers/writers used singular
|
|
271
|
+
// `session/<id>` or legacy `group/<id>`. SQLite FTS is scope-filtered, so
|
|
272
|
+
// omitting any spelling makes valid indexed memory invisible.
|
|
273
|
+
scopes.push(`sessions/${sessionId}`);
|
|
274
|
+
scopes.push(`sessions/${sessionId}/user`);
|
|
273
275
|
scopes.push(`session/${sessionId}`);
|
|
274
276
|
scopes.push(`session/${sessionId}/user`);
|
|
275
277
|
scopes.push(`group/${sessionId}`);
|
|
276
278
|
scopes.push(`group/${sessionId}/user`);
|
|
277
279
|
if (vpId) {
|
|
280
|
+
scopes.push(`sessions/${sessionId}/vp/${vpId}`);
|
|
278
281
|
scopes.push(`session/${sessionId}/vp/${vpId}`);
|
|
279
282
|
scopes.push(`group/${sessionId}/vp/${vpId}`);
|
|
280
283
|
}
|
package/yeaft/web-bridge.js
CHANGED
|
@@ -4821,6 +4821,12 @@ export function __testAppendTurnToSessionHistory(...args) {
|
|
|
4821
4821
|
* Backwards-compat: when neither field is set, defaults to `vpId='default'`
|
|
4822
4822
|
* which matches the pre-v0.1.754 behavior.
|
|
4823
4823
|
*/
|
|
4824
|
+
function resolveDreamTriggerSessionId(msg = {}) {
|
|
4825
|
+
return typeof msg.sessionId === 'string' && msg.sessionId
|
|
4826
|
+
? msg.sessionId
|
|
4827
|
+
: (typeof msg.groupId === 'string' && msg.groupId ? msg.groupId : null);
|
|
4828
|
+
}
|
|
4829
|
+
|
|
4824
4830
|
export function normalizeDreamResult(result) {
|
|
4825
4831
|
const sessions = Array.isArray(result?.sessions) ? result.sessions : [];
|
|
4826
4832
|
const targets = Array.isArray(result?.targets) ? result.targets : [];
|
|
@@ -4869,7 +4875,7 @@ export async function handleYeaftDreamTrigger(msg = {}) {
|
|
|
4869
4875
|
// route the error event back to the right row and the per-group
|
|
4870
4876
|
// "Run dream now" button would stay stuck on "Running…" forever
|
|
4871
4877
|
// (review feedback from PR #757).
|
|
4872
|
-
const sessionId =
|
|
4878
|
+
const sessionId = resolveDreamTriggerSessionId(msg);
|
|
4873
4879
|
const vpId = !sessionId ? (msg.vpId || 'default') : null;
|
|
4874
4880
|
const tag = sessionId ? { sessionId } : { vpId };
|
|
4875
4881
|
|
|
@@ -5924,6 +5930,7 @@ export const __testHooks = {
|
|
|
5924
5930
|
return getVpStatusBroker().transition(status);
|
|
5925
5931
|
},
|
|
5926
5932
|
decorateSessionsWithRuntimeState,
|
|
5933
|
+
resolveDreamTriggerSessionId,
|
|
5927
5934
|
async loadProjectRuntime(workDir) {
|
|
5928
5935
|
return loadProjectRuntime(workDir);
|
|
5929
5936
|
},
|