@aexol/spectral 0.9.182 → 0.9.184
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/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +1 -6
- package/dist/memory/config.d.ts +2 -12
- package/dist/memory/config.d.ts.map +1 -1
- package/dist/memory/config.js +2 -20
- package/dist/memory/hooks/observer-trigger.d.ts.map +1 -1
- package/dist/memory/hooks/observer-trigger.js +11 -6
- package/dist/memory/tools/compact-context.d.ts +0 -10
- package/dist/memory/tools/compact-context.d.ts.map +1 -1
- package/dist/memory/tools/compact-context.js +6 -230
- package/dist/relay/client.d.ts +40 -4
- package/dist/relay/client.d.ts.map +1 -1
- package/dist/relay/client.js +351 -180
- package/dist/sdk/ai/cache-benchmark/benchmark.d.ts.map +1 -1
- package/dist/sdk/ai/cache-benchmark/benchmark.js +31 -7
- package/dist/sdk/ai/cache-benchmark/strategies.d.ts.map +1 -1
- package/dist/sdk/ai/cache-benchmark/strategies.js +29 -4
- package/dist/sdk/ai/cache-benchmark/types.d.ts +31 -0
- package/dist/sdk/ai/cache-benchmark/types.d.ts.map +1 -1
- package/dist/server/handlers/settings.d.ts +0 -6
- package/dist/server/handlers/settings.d.ts.map +1 -1
- package/dist/server/handlers/settings.js +0 -21
- package/dist/server/session-stream.d.ts +1 -3
- package/dist/server/session-stream.d.ts.map +1 -1
- package/dist/server/session-stream.js +0 -5
- package/dist/server/wire.d.ts +0 -4
- package/dist/server/wire.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAIX,SAAS,EAET,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAIX,SAAS,EAET,MAAM,4BAA4B,CAAC;AASpC,OAAO,EACN,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EACN,KAAK,WAAW,EAKhB,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAQrD,OAAO,KAAK,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AAuG7G;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACxC,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,GAAG,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAC,GACpF,MAAM,CAYR;AA0JD;;;GAGG;AACH,wBAAgB,oCAAoC,CACnD,cAAc,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAChD,IAAI,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,EAAE,WAAW,CAAC,CAK3D;AAoBD,wBAAgB,oBAAoB,CACnC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,gBAAgB,GACnB,SAAS,EAAE,CAoCb;AA6bD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CACxC,GAAG,EAAE,YAAY,EACjB,IAAI,CAAC,EAAE;IACN,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,GACC,IAAI,CAgaN"}
|
package/dist/agent/index.js
CHANGED
|
@@ -25,8 +25,7 @@
|
|
|
25
25
|
* - Access to observational memory via the recall tool
|
|
26
26
|
*/
|
|
27
27
|
import { agentLoop } from "../sdk/agent-core/index.js";
|
|
28
|
-
import { buildIsolatedRequestTimePrunedMessages, COMPACT_CONTEXT_TOOL_NAME,
|
|
29
|
-
import { loadConfig } from "../memory/config.js";
|
|
28
|
+
import { buildIsolatedRequestTimePrunedMessages, COMPACT_CONTEXT_TOOL_NAME, } from "../memory/tools/compact-context.js";
|
|
30
29
|
import { StringEnum } from "../sdk/ai/index.js";
|
|
31
30
|
import { mutateSystemPrompt } from "../sdk/coding-agent/core/system-prompt-mutator.js";
|
|
32
31
|
import { Type } from "typebox";
|
|
@@ -468,10 +467,6 @@ async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, si
|
|
|
468
467
|
const config = {
|
|
469
468
|
model,
|
|
470
469
|
apiKey: auth.apiKey,
|
|
471
|
-
onPayload: createIsolatedDcpNudgePayloadHook({
|
|
472
|
-
config: loadConfig(effectiveCwd),
|
|
473
|
-
policy: ctx.settingsManager?.getCompactionPolicy?.(),
|
|
474
|
-
}),
|
|
475
470
|
headers: auth.headers,
|
|
476
471
|
convertToLlm: (msgs) => msgs.filter((m) => m.role === "user" || m.role === "assistant" || m.role === "toolResult"),
|
|
477
472
|
toolExecution: "parallel",
|
package/dist/memory/config.d.ts
CHANGED
|
@@ -23,18 +23,8 @@ export interface Config {
|
|
|
23
23
|
observerMaxChunkTokens?: number;
|
|
24
24
|
reflectorMaxTurnsPerPass?: number;
|
|
25
25
|
prunerMaxTurnsPerPass?: number;
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
/** Absolute context tokens before adding DCP-lite nudges. Mirrors DCP compress.minContextLimit. */
|
|
29
|
-
dcpNudgeMinContextTokens: number;
|
|
30
|
-
/** Context-window percent before adding DCP-lite nudges. */
|
|
31
|
-
dcpNudgeContextPercent: number;
|
|
32
|
-
/** Minimum turns between repeated DCP-lite nudges. */
|
|
33
|
-
dcpNudgeTurnInterval: number;
|
|
34
|
-
/** Provider requests after a user prompt before adding an in-run DCP-lite nudge. */
|
|
35
|
-
dcpInRunNudgeIterationThreshold: number;
|
|
36
|
-
/** Minimum provider requests between repeated in-run DCP-lite nudges. */
|
|
37
|
-
dcpInRunNudgeFrequency: number;
|
|
26
|
+
/** Absolute context tokens at which DCP-lite auto older-history compaction triggers. Default: 50_000. */
|
|
27
|
+
autoCompactionContextTokens: number;
|
|
38
28
|
/** @deprecated Use reflectorMaxTurnsPerPass and prunerMaxTurnsPerPass. */
|
|
39
29
|
compactionMaxToolCalls?: number;
|
|
40
30
|
interAgent?: InterAgentConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/memory/config.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAChC,yFAAyF;IACzF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,4DAA4D;IAC5D,qBAAqB,CAAC,EAAE,SAAS,CAAC;IAClC,wEAAwE;IACxE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,MAAM;IACtB,0BAA0B,EAAE,MAAM,CAAC;IACnC,yBAAyB,EAAE,MAAM,CAAC;IAClC,yBAAyB,EAAE,MAAM,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/memory/config.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAChC,yFAAyF;IACzF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,4DAA4D;IAC5D,qBAAqB,CAAC,EAAE,SAAS,CAAC;IAClC,wEAAwE;IACxE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,MAAM;IACtB,0BAA0B,EAAE,MAAM,CAAC;IACnC,yBAAyB,EAAE,MAAM,CAAC;IAClC,yBAAyB,EAAE,MAAM,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,yGAAyG;IACzG,2BAA2B,EAAE,MAAM,CAAC;IACpC,0EAA0E;IAC1E,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IACnC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wBAAwB,EAAE,MAAM,CAAC;IACjC,qBAAqB,EAAE,MAAM,CAAC;CAC9B;AAUD,eAAO,MAAM,QAAQ,EAAE,MAQtB,CAAC;AA0DF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAMrE;AAED,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAOnF;AAyBD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAUpF;AAED,gEAAgE;AAChE,wBAAsB,eAAe,CACpC,GAAG,EAAE,MAAM,EACX,GAAG,GAAE,MAAM,CAAC,UAAwB,GAClC,OAAO,CAAC,MAAM,CAAC,CAUjB"}
|
package/dist/memory/config.js
CHANGED
|
@@ -9,12 +9,7 @@ export const DEFAULTS = {
|
|
|
9
9
|
passive: false,
|
|
10
10
|
debugLog: false,
|
|
11
11
|
observerMaxChunkTokens: 30_000,
|
|
12
|
-
|
|
13
|
-
dcpNudgeMinContextTokens: 50_000,
|
|
14
|
-
dcpNudgeContextPercent: 35,
|
|
15
|
-
dcpNudgeTurnInterval: 5,
|
|
16
|
-
dcpInRunNudgeIterationThreshold: 15,
|
|
17
|
-
dcpInRunNudgeFrequency: 5,
|
|
12
|
+
autoCompactionContextTokens: 50_000,
|
|
18
13
|
};
|
|
19
14
|
const SETTINGS_KEY = "observational-memory";
|
|
20
15
|
const PASSIVE_ENV = "PI_OBSERVATIONAL_MEMORY_PASSIVE";
|
|
@@ -33,14 +28,6 @@ function normalizeTurnLimit(normalized, key) {
|
|
|
33
28
|
normalized[key] = value;
|
|
34
29
|
}
|
|
35
30
|
}
|
|
36
|
-
function normalizePercent(normalized, key) {
|
|
37
|
-
if (!(key in normalized))
|
|
38
|
-
return;
|
|
39
|
-
const value = normalized[key];
|
|
40
|
-
if (typeof value === "number" && Number.isFinite(value) && value > 0 && value <= 100)
|
|
41
|
-
return;
|
|
42
|
-
delete normalized[key];
|
|
43
|
-
}
|
|
44
31
|
const RELEVANCE_VALUES = ["low", "medium", "high", "critical"];
|
|
45
32
|
function normalizeInterAgentConfig(value) {
|
|
46
33
|
if (!value || typeof value !== "object")
|
|
@@ -69,12 +56,7 @@ function normalizeSettingsConfig(value) {
|
|
|
69
56
|
normalizeTurnLimit(normalized, "observerMaxChunkTokens");
|
|
70
57
|
normalizeTurnLimit(normalized, "reflectorMaxTurnsPerPass");
|
|
71
58
|
normalizeTurnLimit(normalized, "prunerMaxTurnsPerPass");
|
|
72
|
-
normalizeTurnLimit(normalized, "
|
|
73
|
-
normalizeTurnLimit(normalized, "dcpNudgeMinContextTokens");
|
|
74
|
-
normalizeTurnLimit(normalized, "dcpNudgeTurnInterval");
|
|
75
|
-
normalizeTurnLimit(normalized, "dcpInRunNudgeIterationThreshold");
|
|
76
|
-
normalizeTurnLimit(normalized, "dcpInRunNudgeFrequency");
|
|
77
|
-
normalizePercent(normalized, "dcpNudgeContextPercent");
|
|
59
|
+
normalizeTurnLimit(normalized, "autoCompactionContextTokens");
|
|
78
60
|
normalizeTurnLimit(normalized, "compactionMaxToolCalls");
|
|
79
61
|
if ("interAgent" in normalized) {
|
|
80
62
|
const normalizedInterAgent = normalizeInterAgentConfig(normalized.interAgent);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observer-trigger.d.ts","sourceRoot":"","sources":["../../../src/memory/hooks/observer-trigger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAWpE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"observer-trigger.d.ts","sourceRoot":"","sources":["../../../src/memory/hooks/observer-trigger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAWpE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAY7C,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CA8KjF"}
|
|
@@ -7,23 +7,28 @@ import { estimateEntryTokens, estimateStringTokens } from "../tokens.js";
|
|
|
7
7
|
import { OBSERVATION_CUSTOM_TYPE, reflectionToPromptLine } from "../types.js";
|
|
8
8
|
import { getProjectObsStore } from "../project-observations-store.js";
|
|
9
9
|
import { relayProjectObservations } from "../inter-agent-relay.js";
|
|
10
|
+
/** Write diagnostic lines only when structured debug logging is enabled. */
|
|
11
|
+
function debugStderr(runtime, message) {
|
|
12
|
+
if (runtime.config.debugLog === true)
|
|
13
|
+
process.stderr.write(message);
|
|
14
|
+
}
|
|
10
15
|
export function registerObserverTrigger(ext, runtime) {
|
|
11
16
|
ext.on("turn_end", (_event, ctx) => {
|
|
12
|
-
|
|
17
|
+
debugStderr(runtime, "[obs-mem] turn_end fired\n");
|
|
13
18
|
runtime.ensureConfig(ctx.cwd);
|
|
14
19
|
if (runtime.config.passive === true) {
|
|
15
|
-
|
|
20
|
+
debugStderr(runtime, "[obs-mem] passive=true → skipping\n");
|
|
16
21
|
return;
|
|
17
22
|
}
|
|
18
23
|
if (runtime.observerInFlight) {
|
|
19
|
-
|
|
24
|
+
debugStderr(runtime, "[obs-mem] observer already in flight → skipping\n");
|
|
20
25
|
return;
|
|
21
26
|
}
|
|
22
27
|
const entries = ctx.sessionManager.getBranch();
|
|
23
28
|
const tokens = rawTokensSinceLastBound(entries);
|
|
24
|
-
|
|
29
|
+
debugStderr(runtime, `[obs-mem] tokens since last bound: ${tokens} (threshold: ${runtime.config.observationThresholdTokens})\n`);
|
|
25
30
|
if (tokens < runtime.config.observationThresholdTokens) {
|
|
26
|
-
|
|
31
|
+
debugStderr(runtime, "[obs-mem] below threshold → skipping observer\n");
|
|
27
32
|
return;
|
|
28
33
|
}
|
|
29
34
|
const lastBoundIdx = lastObservationCoverEndIdx(entries);
|
|
@@ -60,7 +65,7 @@ export function registerObserverTrigger(ext, runtime) {
|
|
|
60
65
|
if (capIdx < chunkEntries.length) {
|
|
61
66
|
chunkEntries = chunkEntries.slice(0, capIdx);
|
|
62
67
|
effectiveCoversUpToId = chunkEntries[capIdx - 1]?.id ?? coversUpToId;
|
|
63
|
-
|
|
68
|
+
debugStderr(runtime, `[obs-mem] chunk capped at ~${accumulated.toLocaleString()} tokens ` +
|
|
64
69
|
`(${chunkEntries.length} source entries); remaining unobserved entries deferred\n`);
|
|
65
70
|
debugLog("observer.chunk_capped", {
|
|
66
71
|
originalCount: rawTailEntriesBetween(entries, coversFromId, coversUpToId).length,
|
|
@@ -2,17 +2,7 @@ import type { AgentMessage } from "../../sdk/agent-core/index.js";
|
|
|
2
2
|
import { type CompactionPolicy } from "../../sdk/coding-agent/core/compaction/index.js";
|
|
3
3
|
import { type ExtensionAPI } from "../../sdk/coding-agent/index.js";
|
|
4
4
|
import type { Runtime } from "../runtime.js";
|
|
5
|
-
import { type Config } from "../config.js";
|
|
6
5
|
export declare const COMPACT_CONTEXT_TOOL_NAME = "compact_context";
|
|
7
|
-
/**
|
|
8
|
-
* Creates an invocation-local provider payload hook for isolated agent loops.
|
|
9
|
-
* The values are snapshotted at invocation start; no Runtime, SessionManager, or
|
|
10
|
-
* extension state is retained by the returned hook.
|
|
11
|
-
*/
|
|
12
|
-
export declare function createIsolatedDcpNudgePayloadHook(options?: {
|
|
13
|
-
config?: Pick<Config, "dcpInRunNudgeIterationThreshold" | "dcpInRunNudgeFrequency">;
|
|
14
|
-
policy?: CompactionPolicy;
|
|
15
|
-
}): NonNullable<import("../../sdk/ai/index.js").SimpleStreamOptions["onPayload"]>;
|
|
16
6
|
/** Request-time DCP adapter for isolated loops: it borrows only pure policy helpers. */
|
|
17
7
|
export declare function buildIsolatedRequestTimePrunedMessages(currentMessages: AgentMessage[], policy?: CompactionPolicy, keepRecentTokens?: number): AgentMessage[];
|
|
18
8
|
export declare function registerCompactContextTool(ext: ExtensionAPI, runtime: Runtime): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compact-context.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/compact-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAUN,KAAK,gBAAgB,EACrB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAc,KAAK,YAAY,EAAyB,MAAM,iCAAiC,CAAC;AAKvG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"compact-context.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/compact-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAUN,KAAK,gBAAgB,EACrB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAc,KAAK,YAAY,EAAyB,MAAM,iCAAiC,CAAC;AAKvG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,eAAO,MAAM,yBAAyB,oBAAoB,CAAC;AAkX3D,wFAAwF;AACxF,wBAAgB,sCAAsC,CACrD,eAAe,EAAE,YAAY,EAAE,EAC/B,MAAM,GAAE,gBAA4C,EACpD,gBAAgB,CAAC,EAAE,MAAM,GACvB,YAAY,EAAE,CAchB;AAmRD,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAgPpF"}
|
|
@@ -4,9 +4,7 @@ import { defineTool } from "../../sdk/coding-agent/index.js";
|
|
|
4
4
|
import { buildSessionContext } from "../../sdk/coding-agent/core/session-manager.js";
|
|
5
5
|
import { rawTokensSinceLastCompaction } from "../branch.js";
|
|
6
6
|
import { debugLog, withDebugLogContext } from "../debug-log.js";
|
|
7
|
-
import { DEFAULTS } from "../config.js";
|
|
8
7
|
export const COMPACT_CONTEXT_TOOL_NAME = "compact_context";
|
|
9
|
-
const DCP_NUDGE_HEADING = "## DCP-lite context hygiene";
|
|
10
8
|
const MAX_COMPACT_CONTEXT_TEXT_CHARS = 240;
|
|
11
9
|
const MAX_CUSTOM_INSTRUCTIONS_CHARS = 640;
|
|
12
10
|
const DEFAULT_COMPACT_CONTEXT_SCOPE = "closed_phase";
|
|
@@ -61,11 +59,8 @@ function getState(runtime) {
|
|
|
61
59
|
if (!state) {
|
|
62
60
|
state = {
|
|
63
61
|
request: null,
|
|
64
|
-
|
|
65
|
-
lastNudgeTurn: 0,
|
|
62
|
+
turnCount: 0,
|
|
66
63
|
lastAgentDrivenRequestTurn: null,
|
|
67
|
-
providerRequestCount: 0,
|
|
68
|
-
lastInRunNudgeRequest: 0,
|
|
69
64
|
};
|
|
70
65
|
stateByRuntime.set(runtime, state);
|
|
71
66
|
}
|
|
@@ -100,136 +95,6 @@ function buildCustomInstructions(params) {
|
|
|
100
95
|
function formatTokenCount(tokens) {
|
|
101
96
|
return Math.round(tokens).toLocaleString();
|
|
102
97
|
}
|
|
103
|
-
function formatSignals(rawTokens, contextTokens, percent, providerRequests) {
|
|
104
|
-
const parts = [`~${rawTokens.toLocaleString()} raw tokens since last compaction`];
|
|
105
|
-
if (typeof contextTokens === "number" && Number.isFinite(contextTokens)) {
|
|
106
|
-
parts.push(`~${formatTokenCount(contextTokens)} context tokens in the next request`);
|
|
107
|
-
}
|
|
108
|
-
if (typeof percent === "number" && Number.isFinite(percent)) {
|
|
109
|
-
parts.push(`${Math.round(percent)}% context window used`);
|
|
110
|
-
}
|
|
111
|
-
if (providerRequests !== undefined) {
|
|
112
|
-
parts.push(`${formatTokenCount(providerRequests)} provider requests since the last user prompt`);
|
|
113
|
-
}
|
|
114
|
-
return parts.join(", ");
|
|
115
|
-
}
|
|
116
|
-
function buildDcpNudge(rawTokens, contextTokens, percent, policy, providerRequests) {
|
|
117
|
-
return [
|
|
118
|
-
"",
|
|
119
|
-
DCP_NUDGE_HEADING,
|
|
120
|
-
`Context is accumulating (${formatSignals(rawTokens, contextTokens, percent, providerRequests)}).`,
|
|
121
|
-
"Use `compact_context` once when a safe compaction scope is available. When the agent is still working mid-run, the default is virtual `request_time` pruning that shrinks the next provider request without mutating session history; when the phase is closed or the agent is idle, persisted `after_turn` compaction runs after this run for cache-friendly future requests.",
|
|
122
|
-
"If the user explicitly asks to run/trigger `compact_context`, DCP, DCP-lite, context pruning, or context compression, call `compact_context` in the next step with the safest allowed scope; do not run shell tests, explain it away, or claim DCP was activated without a tool result. If guards reject the call, report that rejection.",
|
|
123
|
-
"When the current topic/phase is done, the user changes threads, or old tool output is no longer needed, call `compact_context({ scope: \"closed_phase\", focus: \"short topic/focus\", phaseComplete: true })` once and continue normally.",
|
|
124
|
-
`If the phase remains active/open, use \`compact_context({ scope: "older_history", keepRecentTokens: ${policy.agentDriven.olderHistoryKeepRecentTokens} })\` to prune older stale history in-flight while a recent raw suffix stays available for the next step.`,
|
|
125
|
-
"Prefer `mode: \"request_time\"` while the phase is active and context is growing (prunes the next request virtually); use `mode: \"after_turn\"` once the phase is closed (persists compaction after the run).",
|
|
126
|
-
].join("\n");
|
|
127
|
-
}
|
|
128
|
-
function isRecord(value) {
|
|
129
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
130
|
-
}
|
|
131
|
-
function contentContainsDcpNudge(content) {
|
|
132
|
-
if (typeof content === "string")
|
|
133
|
-
return content.includes(DCP_NUDGE_HEADING);
|
|
134
|
-
if (!Array.isArray(content))
|
|
135
|
-
return false;
|
|
136
|
-
return content.some((part) => {
|
|
137
|
-
if (typeof part === "string")
|
|
138
|
-
return part.includes(DCP_NUDGE_HEADING);
|
|
139
|
-
return isRecord(part) && typeof part.text === "string" && part.text.includes(DCP_NUDGE_HEADING);
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
function payloadContainsDcpNudge(payload) {
|
|
143
|
-
if (!isRecord(payload))
|
|
144
|
-
return false;
|
|
145
|
-
if (contentContainsDcpNudge(payload.system))
|
|
146
|
-
return true;
|
|
147
|
-
const messages = payload.messages;
|
|
148
|
-
if (!Array.isArray(messages))
|
|
149
|
-
return false;
|
|
150
|
-
return messages.some((message) => isRecord(message) && contentContainsDcpNudge(message.content));
|
|
151
|
-
}
|
|
152
|
-
function appendNudgeToContent(content, nudge) {
|
|
153
|
-
if (typeof content === "string")
|
|
154
|
-
return `${content}${nudge}`;
|
|
155
|
-
if (Array.isArray(content))
|
|
156
|
-
return [...content, { type: "text", text: nudge.trimStart() }];
|
|
157
|
-
return nudge.trimStart();
|
|
158
|
-
}
|
|
159
|
-
function injectDcpNudgeIntoAnthropicPayload(payload, nudge) {
|
|
160
|
-
if (!("system" in payload))
|
|
161
|
-
return undefined;
|
|
162
|
-
const system = payload.system;
|
|
163
|
-
if (typeof system === "string")
|
|
164
|
-
return { ...payload, system: `${system}${nudge}` };
|
|
165
|
-
if (Array.isArray(system))
|
|
166
|
-
return { ...payload, system: [...system, { type: "text", text: nudge.trimStart() }] };
|
|
167
|
-
if (system === undefined || system === null)
|
|
168
|
-
return { ...payload, system: [{ type: "text", text: nudge.trimStart() }] };
|
|
169
|
-
return undefined;
|
|
170
|
-
}
|
|
171
|
-
function injectDcpNudgeIntoOpenAiPayload(payload, nudge) {
|
|
172
|
-
const messages = payload.messages;
|
|
173
|
-
if (!Array.isArray(messages))
|
|
174
|
-
return undefined;
|
|
175
|
-
const targetIndex = messages.findIndex((message) => {
|
|
176
|
-
if (!isRecord(message))
|
|
177
|
-
return false;
|
|
178
|
-
return message.role === "system" || message.role === "developer";
|
|
179
|
-
});
|
|
180
|
-
if (targetIndex === -1) {
|
|
181
|
-
return { ...payload, messages: [{ role: "system", content: nudge.trimStart() }, ...messages] };
|
|
182
|
-
}
|
|
183
|
-
const targetMessage = messages[targetIndex];
|
|
184
|
-
if (!isRecord(targetMessage))
|
|
185
|
-
return undefined;
|
|
186
|
-
const nextMessages = [...messages];
|
|
187
|
-
nextMessages[targetIndex] = {
|
|
188
|
-
...targetMessage,
|
|
189
|
-
content: appendNudgeToContent(targetMessage.content, nudge),
|
|
190
|
-
};
|
|
191
|
-
return { ...payload, messages: nextMessages };
|
|
192
|
-
}
|
|
193
|
-
function injectDcpNudgeIntoProviderPayload(payload, nudge) {
|
|
194
|
-
if (!isRecord(payload) || payloadContainsDcpNudge(payload))
|
|
195
|
-
return undefined;
|
|
196
|
-
return injectDcpNudgeIntoAnthropicPayload(payload, nudge) ?? injectDcpNudgeIntoOpenAiPayload(payload, nudge);
|
|
197
|
-
}
|
|
198
|
-
function describeProviderPayload(payload) {
|
|
199
|
-
if (!isRecord(payload))
|
|
200
|
-
return typeof payload;
|
|
201
|
-
const keys = Object.keys(payload).sort();
|
|
202
|
-
if (Array.isArray(payload.messages))
|
|
203
|
-
return `messages:${keys.join(",")}`;
|
|
204
|
-
if (Array.isArray(payload.system))
|
|
205
|
-
return `anthropic:${keys.join(",")}`;
|
|
206
|
-
return `object:${keys.join(",")}`;
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Creates an invocation-local provider payload hook for isolated agent loops.
|
|
210
|
-
* The values are snapshotted at invocation start; no Runtime, SessionManager, or
|
|
211
|
-
* extension state is retained by the returned hook.
|
|
212
|
-
*/
|
|
213
|
-
export function createIsolatedDcpNudgePayloadHook(options = {}) {
|
|
214
|
-
let providerRequestCount = 0;
|
|
215
|
-
let lastNudgeRequest = 0;
|
|
216
|
-
const config = options.config ?? DEFAULTS;
|
|
217
|
-
const policy = options.policy ?? DEFAULT_COMPACTION_POLICY;
|
|
218
|
-
return (payload) => {
|
|
219
|
-
providerRequestCount += 1;
|
|
220
|
-
const frequency = config.dcpInRunNudgeFrequency;
|
|
221
|
-
const hasSignal = providerRequestCount >= config.dcpInRunNudgeIterationThreshold;
|
|
222
|
-
const frequencyReady = lastNudgeRequest === 0 || providerRequestCount - lastNudgeRequest >= frequency;
|
|
223
|
-
if (!hasSignal || !frequencyReady || payloadContainsDcpNudge(payload))
|
|
224
|
-
return undefined;
|
|
225
|
-
const nudge = buildDcpNudge(0, undefined, undefined, policy, providerRequestCount);
|
|
226
|
-
const nextPayload = injectDcpNudgeIntoProviderPayload(payload, nudge);
|
|
227
|
-
if (nextPayload === undefined)
|
|
228
|
-
return undefined;
|
|
229
|
-
lastNudgeRequest = providerRequestCount;
|
|
230
|
-
return nextPayload;
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
98
|
function rawTokensForContext(ctx) {
|
|
234
99
|
const entries = ctx.sessionManager.getBranch();
|
|
235
100
|
return rawTokensSinceLastCompaction(entries);
|
|
@@ -342,7 +207,7 @@ function decideAutoCompaction(ctx, runtime, state, policy, rawTokens, contextTok
|
|
|
342
207
|
cooldownActive: remainingCooldownTurns(state, policy) > 0,
|
|
343
208
|
hasSufficientMaterial: rawTokens >= requestSettings.minRawTokens,
|
|
344
209
|
contextRatioReached: isContextAtOrAboveRatio(percent, policy.autoOlderHistory.contextLimitRatio),
|
|
345
|
-
absoluteThresholdReached: isContextAtOrAboveTokenLimit(contextTokens, runtime.config.
|
|
210
|
+
absoluteThresholdReached: isContextAtOrAboveTokenLimit(contextTokens, runtime.config.autoCompactionContextTokens),
|
|
346
211
|
rawThresholdReached: rawTokens >= runtime.config.compactionThresholdTokens,
|
|
347
212
|
iterationReached: iterationSignal,
|
|
348
213
|
});
|
|
@@ -352,7 +217,7 @@ function maybeScheduleAutoOlderHistoryCompaction(ctx, runtime, state, policy, ra
|
|
|
352
217
|
if (decision.mode === "none")
|
|
353
218
|
return false;
|
|
354
219
|
const requestSettings = getAutoOlderHistoryRequestSettings(policy);
|
|
355
|
-
state.lastAgentDrivenRequestTurn = state.
|
|
220
|
+
state.lastAgentDrivenRequestTurn = state.turnCount;
|
|
356
221
|
state.request = { source: "auto", mode: decision.mode, ...requestSettings };
|
|
357
222
|
if (decision.mode === "request_time")
|
|
358
223
|
notifyRequestTimeActive(ctx, state.request, rawTokens);
|
|
@@ -363,7 +228,7 @@ function maybeScheduleAutoOlderHistoryCompaction(ctx, runtime, state, policy, ra
|
|
|
363
228
|
function remainingCooldownTurns(state, policy) {
|
|
364
229
|
if (state.lastAgentDrivenRequestTurn === null)
|
|
365
230
|
return 0;
|
|
366
|
-
const elapsed = Math.max(0, state.
|
|
231
|
+
const elapsed = Math.max(0, state.turnCount - state.lastAgentDrivenRequestTurn);
|
|
367
232
|
return Math.max(0, policy.agentDriven.cooldownTurns - elapsed);
|
|
368
233
|
}
|
|
369
234
|
function getRequestTimeCompactionSettings(request, policy) {
|
|
@@ -581,7 +446,7 @@ function registerAgentCompactionTool(ext, runtime, state) {
|
|
|
581
446
|
};
|
|
582
447
|
}
|
|
583
448
|
const customInstructions = buildCustomInstructions(params);
|
|
584
|
-
state.lastAgentDrivenRequestTurn = state.
|
|
449
|
+
state.lastAgentDrivenRequestTurn = state.turnCount;
|
|
585
450
|
state.request = { source: "tool", mode, customInstructions, ...requestSettings };
|
|
586
451
|
if (mode === "request_time")
|
|
587
452
|
notifyRequestTimeActive(ctx, state.request, rawTokens);
|
|
@@ -625,9 +490,7 @@ export function registerCompactContextTool(ext, runtime) {
|
|
|
625
490
|
const policy = getCompactionPolicy(ctx);
|
|
626
491
|
if (!policy.agentDriven.enabled)
|
|
627
492
|
return;
|
|
628
|
-
state.
|
|
629
|
-
state.lastInRunNudgeRequest = 0;
|
|
630
|
-
state.nudgeTurnCount += 1;
|
|
493
|
+
state.turnCount += 1;
|
|
631
494
|
let rawTokens = 0;
|
|
632
495
|
try {
|
|
633
496
|
rawTokens = rawTokensForContext(ctx);
|
|
@@ -638,21 +501,7 @@ export function registerCompactContextTool(ext, runtime) {
|
|
|
638
501
|
const usage = ctx.getContextUsage();
|
|
639
502
|
const contextTokens = usage?.tokens;
|
|
640
503
|
const percent = usage?.percent;
|
|
641
|
-
const minRawTokens = runtime.config.dcpNudgeMinRawTokens;
|
|
642
|
-
const minContextTokens = runtime.config.dcpNudgeMinContextTokens;
|
|
643
|
-
const minPercent = runtime.config.dcpNudgeContextPercent;
|
|
644
|
-
const turnInterval = runtime.config.dcpNudgeTurnInterval;
|
|
645
|
-
const turnsSinceNudge = state.nudgeTurnCount - state.lastNudgeTurn;
|
|
646
|
-
const rawSignal = rawTokens >= minRawTokens;
|
|
647
|
-
const absoluteContextSignal = isContextAtOrAboveTokenLimit(contextTokens, minContextTokens);
|
|
648
|
-
const percentSignal = typeof percent === "number" && Number.isFinite(percent) && percent >= minPercent;
|
|
649
|
-
const intervalSignal = turnsSinceNudge >= turnInterval && rawTokens >= Math.floor(minRawTokens / 2);
|
|
650
504
|
maybeScheduleAutoOlderHistoryCompaction(ctx, runtime, state, policy, rawTokens, contextTokens, percent);
|
|
651
|
-
if (!rawSignal && !absoluteContextSignal && !percentSignal && !intervalSignal)
|
|
652
|
-
return;
|
|
653
|
-
state.lastNudgeTurn = state.nudgeTurnCount;
|
|
654
|
-
const nudge = buildDcpNudge(rawTokens, contextTokens, percent, policy);
|
|
655
|
-
return { systemPrompt: `${_event.systemPrompt}${nudge}` };
|
|
656
505
|
}));
|
|
657
506
|
ext.on("context", withDebug((_event, ctx) => {
|
|
658
507
|
runtime.ensureConfig(ctx.cwd);
|
|
@@ -752,80 +601,7 @@ export function registerCompactContextTool(ext, runtime) {
|
|
|
752
601
|
notifyRequestTimeApplied(ctx, autoPruned, autoRequest);
|
|
753
602
|
return { messages: autoPruned.messages };
|
|
754
603
|
}));
|
|
755
|
-
ext.on("before_provider_request", withDebug((_event, ctx) => {
|
|
756
|
-
runtime.ensureConfig(ctx.cwd);
|
|
757
|
-
if (runtime.config.passive === true)
|
|
758
|
-
return;
|
|
759
|
-
const policy = getCompactionPolicy(ctx);
|
|
760
|
-
if (!policy.agentDriven.enabled)
|
|
761
|
-
return;
|
|
762
|
-
state.providerRequestCount += 1;
|
|
763
|
-
const rawTokens = safeRawTokensForContext(ctx);
|
|
764
|
-
const usage = ctx.getContextUsage();
|
|
765
|
-
const contextTokens = usage?.tokens;
|
|
766
|
-
const percent = usage?.percent;
|
|
767
|
-
const minRawTokens = runtime.config.dcpNudgeMinRawTokens;
|
|
768
|
-
const minContextTokens = runtime.config.dcpNudgeMinContextTokens;
|
|
769
|
-
const minPercent = runtime.config.dcpNudgeContextPercent;
|
|
770
|
-
const iterationThreshold = runtime.config.dcpInRunNudgeIterationThreshold;
|
|
771
|
-
const frequency = runtime.config.dcpInRunNudgeFrequency;
|
|
772
|
-
const rawSignal = rawTokens >= minRawTokens;
|
|
773
|
-
const absoluteContextSignal = isContextAtOrAboveTokenLimit(contextTokens, minContextTokens);
|
|
774
|
-
const percentSignal = typeof percent === "number" && Number.isFinite(percent) && percent >= minPercent;
|
|
775
|
-
const iterationSignal = state.providerRequestCount >= iterationThreshold;
|
|
776
|
-
const frequencyReady = state.lastInRunNudgeRequest === 0 ||
|
|
777
|
-
state.providerRequestCount - state.lastInRunNudgeRequest >= frequency;
|
|
778
|
-
const signalEligible = rawSignal || absoluteContextSignal || percentSignal || iterationSignal;
|
|
779
|
-
const payloadShape = describeProviderPayload(_event.payload);
|
|
780
|
-
const alreadyContainsNudge = payloadContainsDcpNudge(_event.payload);
|
|
781
|
-
debugLog("compact_context.before_provider_request", {
|
|
782
|
-
providerRequestCount: state.providerRequestCount,
|
|
783
|
-
rawTokens,
|
|
784
|
-
contextTokens: contextTokens ?? null,
|
|
785
|
-
percent: percent ?? null,
|
|
786
|
-
rawSignal,
|
|
787
|
-
absoluteContextSignal,
|
|
788
|
-
percentSignal,
|
|
789
|
-
iterationSignal,
|
|
790
|
-
frequencyReady,
|
|
791
|
-
signalEligible,
|
|
792
|
-
payloadShape,
|
|
793
|
-
alreadyContainsNudge,
|
|
794
|
-
});
|
|
795
|
-
// NOTE: maybeScheduleAutoOlderHistoryCompaction is intentionally NOT called
|
|
796
|
-
// here. This event fires AFTER the context event within the same provider
|
|
797
|
-
// request cycle, so any state.request set here would only be visible to
|
|
798
|
-
// the context event on the NEXT request — a one-request lag that lets the
|
|
799
|
-
// oversized request through unpruned. Auto request_time pruning is now
|
|
800
|
-
// decided inline in the context event handler (no lag).
|
|
801
|
-
if (!signalEligible || !frequencyReady) {
|
|
802
|
-
debugLog("compact_context.nudge_skipped", {
|
|
803
|
-
reason: !signalEligible ? "no_signal" : "frequency_cooldown",
|
|
804
|
-
payloadShape,
|
|
805
|
-
});
|
|
806
|
-
return;
|
|
807
|
-
}
|
|
808
|
-
if (alreadyContainsNudge) {
|
|
809
|
-
state.lastInRunNudgeRequest = state.providerRequestCount;
|
|
810
|
-
debugLog("compact_context.nudge_skipped", { reason: "already_present", payloadShape });
|
|
811
|
-
return;
|
|
812
|
-
}
|
|
813
|
-
const nudge = buildDcpNudge(rawTokens, contextTokens, percent, policy, state.providerRequestCount);
|
|
814
|
-
const payload = injectDcpNudgeIntoProviderPayload(_event.payload, nudge);
|
|
815
|
-
if (payload === undefined) {
|
|
816
|
-
debugLog("compact_context.nudge_skipped", { reason: "unsupported_payload_shape", payloadShape });
|
|
817
|
-
return;
|
|
818
|
-
}
|
|
819
|
-
state.lastInRunNudgeRequest = state.providerRequestCount;
|
|
820
|
-
debugLog("compact_context.nudge_injected", {
|
|
821
|
-
providerRequestCount: state.providerRequestCount,
|
|
822
|
-
payloadShape,
|
|
823
|
-
});
|
|
824
|
-
return payload;
|
|
825
|
-
}));
|
|
826
604
|
ext.on("agent_end", withDebug((_event, ctx) => {
|
|
827
|
-
state.providerRequestCount = 0;
|
|
828
|
-
state.lastInRunNudgeRequest = 0;
|
|
829
605
|
const request = state.request;
|
|
830
606
|
if (!request || request.mode !== "after_turn")
|
|
831
607
|
return;
|
package/dist/relay/client.d.ts
CHANGED
|
@@ -7,12 +7,16 @@
|
|
|
7
7
|
* machine JWT via `Authorization: Bearer <jwt>`.
|
|
8
8
|
* - Reply `{kind:"pong"}` to backend `{kind:"ping"}`. Backend closes
|
|
9
9
|
* `4408 heartbeat-timeout` if it doesn't hear from us within 90s; we
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* keep this app-level reply in addition to the protocol-level heartbeat
|
|
11
|
+
* below.
|
|
12
|
+
* - **Client heartbeat:** additionally emits a protocol-level `ws` ping
|
|
13
|
+
* every `HEARTBEAT_INTERVAL_MS` and requires a `pong` within
|
|
14
|
+
* `HEARTBEAT_TIMEOUT_MS`. This detects a half-open send path (e.g. after
|
|
15
|
+
* laptop sleep/wake) where `readyState` still reports `OPEN`.
|
|
12
16
|
* - **Watchdog timer:** tracks `lastActivityMs` on every received frame /
|
|
13
17
|
* ping. Every 15 s, if no activity within `WATCHDOG_MS` (120 s = 2×
|
|
14
|
-
* backend timeout),
|
|
15
|
-
*
|
|
18
|
+
* backend timeout), terminates the socket and triggers a reconnect.
|
|
19
|
+
* Detects silent backend death (Docker OOM
|
|
16
20
|
* kill, network partition without TCP RST) where the socket stays open
|
|
17
21
|
* but no data flows.
|
|
18
22
|
* - **Pre-reconnect health check:** before opening a new WS, does a quick
|
|
@@ -104,11 +108,19 @@ export declare class RelayClient extends EventEmitter {
|
|
|
104
108
|
private tightLoopWindowStart;
|
|
105
109
|
private reconnectTimer;
|
|
106
110
|
private sendQueue;
|
|
111
|
+
/** Wire currently waiting on a `ws.send` callback. Only one in flight to preserve FIFO. */
|
|
112
|
+
private sendInFlight;
|
|
113
|
+
private sendTimer;
|
|
107
114
|
/** Set true when the WS error handler sees an HTTP 401/403 upgrade rejection. */
|
|
108
115
|
private authFailed;
|
|
109
116
|
/** Timestamp of last received frame / ping — drives the watchdog. */
|
|
110
117
|
private lastActivityMs;
|
|
111
118
|
private watchdogTimer;
|
|
119
|
+
private heartbeatTimer;
|
|
120
|
+
private heartbeatPongTimer;
|
|
121
|
+
private heartbeatPending;
|
|
122
|
+
/** Guards the async window of `scheduleReconnect` (health check). */
|
|
123
|
+
private reconnectInFlight;
|
|
112
124
|
constructor(opts: RelayClientOptions);
|
|
113
125
|
/** Open the connection. Idempotent — calling twice is a no-op. */
|
|
114
126
|
connect(): void;
|
|
@@ -129,6 +141,30 @@ export declare class RelayClient extends EventEmitter {
|
|
|
129
141
|
private openSocket;
|
|
130
142
|
private startWatchdog;
|
|
131
143
|
private stopWatchdog;
|
|
144
|
+
private startHeartbeat;
|
|
145
|
+
private stopHeartbeat;
|
|
146
|
+
private enqueueWire;
|
|
147
|
+
private clearSendInFlight;
|
|
148
|
+
/**
|
|
149
|
+
* Drain the FIFO send queue over the current socket. Exactly one frame is
|
|
150
|
+
* in flight at a time so ordering is preserved. If `ws.send` never calls
|
|
151
|
+
* its callback (half-open socket), the frame stays at the front of the
|
|
152
|
+
* queue and the connection is force-reconnected; the next `open` flushes
|
|
153
|
+
* it again.
|
|
154
|
+
*/
|
|
155
|
+
private flushSendQueue;
|
|
156
|
+
private setTcpKeepAlive;
|
|
157
|
+
/**
|
|
158
|
+
* Tear down a suspected-dead socket and schedule a reconnect immediately.
|
|
159
|
+
* Unlike the `close` path, this does not wait for a (possibly never
|
|
160
|
+
* arriving) `close` event — `terminate()` destroys the socket directly.
|
|
161
|
+
*/
|
|
162
|
+
private forceReconnect;
|
|
163
|
+
/**
|
|
164
|
+
* Single disconnect entry point for both real `close` events and forced
|
|
165
|
+
* reconnects. Ignored for sockets that have already been replaced.
|
|
166
|
+
*/
|
|
167
|
+
private handleDisconnect;
|
|
132
168
|
/**
|
|
133
169
|
* Pre-reconnect health check: quick HTTP GET to `<backendUrl>/health`.
|
|
134
170
|
* Returns true when the backend is reachable (or when no backendUrl is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/relay/client.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/relay/client.ts"],"names":[],"mappings":"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"}
|