@threadbase-sh/streamer 1.65.0 → 1.67.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/api/routes/misc.routes.d.ts.map +1 -1
- package/dist/api/types/api-deps.d.ts +2 -0
- package/dist/api/types/api-deps.d.ts.map +1 -1
- package/dist/cli.cjs +259 -14
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +259 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +247 -2
- package/dist/index.js.map +1 -1
- package/dist/server-wiring.d.ts +3 -0
- package/dist/server-wiring.d.ts.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/services/host-pressure/hostPressure.d.ts +83 -0
- package/dist/services/host-pressure/hostPressure.d.ts.map +1 -0
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4136,7 +4136,7 @@ var import_events = require("events");
|
|
|
4136
4136
|
var import_fs28 = require("fs");
|
|
4137
4137
|
var import_promises7 = require("fs/promises");
|
|
4138
4138
|
var import_http = require("http");
|
|
4139
|
-
var
|
|
4139
|
+
var import_os15 = require("os");
|
|
4140
4140
|
var import_path24 = require("path");
|
|
4141
4141
|
|
|
4142
4142
|
// src/api/app.ts
|
|
@@ -4979,7 +4979,7 @@ function redactPath(path) {
|
|
|
4979
4979
|
function worstStatus(checks) {
|
|
4980
4980
|
const rank = { ok: 0, unknown: 1, degraded: 2, failed: 3 };
|
|
4981
4981
|
return checks.reduce(
|
|
4982
|
-
(
|
|
4982
|
+
(worst2, c) => rank[c.status] > rank[worst2] ? c.status : worst2,
|
|
4983
4983
|
"ok"
|
|
4984
4984
|
);
|
|
4985
4985
|
}
|
|
@@ -5994,7 +5994,12 @@ var createMiscRoutes = (deps) => {
|
|
|
5994
5994
|
// Whether to encrypt to this server. Additive, same contract as `push`:
|
|
5995
5995
|
// absent means an older server, which a client must read as "unknown" and
|
|
5996
5996
|
// resolve as today's plaintext path — never as a reason to fail.
|
|
5997
|
-
e2ee: describeE2eeCapability(deps.featureFlagsConfig().values.e2ee)
|
|
5997
|
+
e2ee: describeE2eeCapability(deps.featureFlagsConfig().values.e2ee),
|
|
5998
|
+
// This build samples cheap host signals and pushes `host_pressure` when
|
|
5999
|
+
// the box is starved. Additive capability flag only — live readings stay
|
|
6000
|
+
// off this polled endpoint. Absent means an older server that never
|
|
6001
|
+
// samples. Informational: pressure never holds, kills, or refuses sessions.
|
|
6002
|
+
hostPressure: true
|
|
5998
6003
|
});
|
|
5999
6004
|
});
|
|
6000
6005
|
app.get("/api/profiles", (c) => c.json([]));
|
|
@@ -12880,6 +12885,7 @@ function createApiDeps(deps) {
|
|
|
12880
12885
|
wsHub: deps.wsHub,
|
|
12881
12886
|
cache: () => deps.cache(),
|
|
12882
12887
|
cacheMonitor: () => deps.cacheMonitor(),
|
|
12888
|
+
hostPressureMonitor: () => deps.hostPressureMonitor(),
|
|
12883
12889
|
pushRepo: () => deps.pushRepo(),
|
|
12884
12890
|
liveActivityPushEnabled: () => deps.liveActivityPushEnabled(),
|
|
12885
12891
|
devicesRepo: () => deps.devicesRepo(),
|
|
@@ -12930,6 +12936,8 @@ function createApiDeps(deps) {
|
|
|
12930
12936
|
}
|
|
12931
12937
|
const alertMsg = deps.cacheMonitor()?.wsMessage();
|
|
12932
12938
|
if (alertMsg) deps.wsHub.unicast(ws, alertMsg);
|
|
12939
|
+
const pressureMsg = deps.hostPressureMonitor()?.wsMessage();
|
|
12940
|
+
if (pressureMsg) deps.wsHub.unicast(ws, pressureMsg);
|
|
12933
12941
|
},
|
|
12934
12942
|
handleWsMessage: async (ws, raw, principal) => {
|
|
12935
12943
|
const deny = (type, required) => {
|
|
@@ -13000,6 +13008,13 @@ function createApiDeps(deps) {
|
|
|
13000
13008
|
);
|
|
13001
13009
|
}
|
|
13002
13010
|
}
|
|
13011
|
+
if (msg.type === "unsubscribe_session" && typeof msg.sessionId === "string") {
|
|
13012
|
+
if (!wsAllows(principal, "history:read")) {
|
|
13013
|
+
deny(msg.type, "history:read");
|
|
13014
|
+
return;
|
|
13015
|
+
}
|
|
13016
|
+
deps.removeSessionSubscriber(msg.sessionId, ws);
|
|
13017
|
+
}
|
|
13003
13018
|
if (msg.type === "hold_session" && typeof msg.sessionId === "string") {
|
|
13004
13019
|
if (!wsAllows(principal, "session:control")) {
|
|
13005
13020
|
deny(msg.type, "session:control");
|
|
@@ -13555,6 +13570,221 @@ function pruneAgentConversations(cache) {
|
|
|
13555
13570
|
return { scanned: rows.length, pruned, missing };
|
|
13556
13571
|
}
|
|
13557
13572
|
|
|
13573
|
+
// src/services/host-pressure/hostPressure.ts
|
|
13574
|
+
var import_os13 = require("os");
|
|
13575
|
+
var import_perf_hooks = require("perf_hooks");
|
|
13576
|
+
var HOST_PRESSURE_SAMPLE_MS = 5e3;
|
|
13577
|
+
var HOST_PRESSURE_BARS = {
|
|
13578
|
+
memFreeRatio: {
|
|
13579
|
+
enterElevated: 0.15,
|
|
13580
|
+
leaveElevated: 0.17,
|
|
13581
|
+
enterCritical: 0.08,
|
|
13582
|
+
leaveCritical: 0.15
|
|
13583
|
+
},
|
|
13584
|
+
eventLoopP99Ms: {
|
|
13585
|
+
enterElevated: 100,
|
|
13586
|
+
leaveElevated: 80,
|
|
13587
|
+
enterCritical: 250,
|
|
13588
|
+
leaveCritical: 100
|
|
13589
|
+
},
|
|
13590
|
+
loadPerCpu: {
|
|
13591
|
+
enterElevated: 1.25,
|
|
13592
|
+
leaveElevated: 1.05,
|
|
13593
|
+
enterCritical: 2,
|
|
13594
|
+
leaveCritical: 1.25
|
|
13595
|
+
},
|
|
13596
|
+
// win32 has no loadavg. Busy ratio from os.cpus()[].times deltas is 0–1, so
|
|
13597
|
+
// it cannot reuse loadPerCpu's 2.0 critical bar. Reason on the wire stays `load`.
|
|
13598
|
+
cpuBusy: {
|
|
13599
|
+
enterElevated: 0.85,
|
|
13600
|
+
leaveElevated: 0.7,
|
|
13601
|
+
enterCritical: 0.97,
|
|
13602
|
+
leaveCritical: 0.85
|
|
13603
|
+
},
|
|
13604
|
+
liveAgentsPair: 4
|
|
13605
|
+
};
|
|
13606
|
+
var REASON_ORDER = ["memory", "event_loop", "load", "agents"];
|
|
13607
|
+
var RANK = { ok: 0, elevated: 1, critical: 2 };
|
|
13608
|
+
function worst(levels) {
|
|
13609
|
+
return levels.reduce(
|
|
13610
|
+
(acc, level) => RANK[level] > RANK[acc] ? level : acc,
|
|
13611
|
+
"ok"
|
|
13612
|
+
);
|
|
13613
|
+
}
|
|
13614
|
+
function schmittLowIsWorse(value, previous, enterElevated, leaveElevated, enterCritical, leaveCritical) {
|
|
13615
|
+
if (previous === "critical") {
|
|
13616
|
+
if (value < leaveCritical) return "critical";
|
|
13617
|
+
if (value < leaveElevated) return "elevated";
|
|
13618
|
+
return "ok";
|
|
13619
|
+
}
|
|
13620
|
+
if (previous === "elevated") {
|
|
13621
|
+
if (value < enterCritical) return "critical";
|
|
13622
|
+
if (value < leaveElevated) return "elevated";
|
|
13623
|
+
return "ok";
|
|
13624
|
+
}
|
|
13625
|
+
if (value < enterCritical) return "critical";
|
|
13626
|
+
if (value < enterElevated) return "elevated";
|
|
13627
|
+
return "ok";
|
|
13628
|
+
}
|
|
13629
|
+
function schmittHighIsWorse(value, previous, enterElevated, leaveElevated, enterCritical, leaveCritical) {
|
|
13630
|
+
if (previous === "critical") {
|
|
13631
|
+
if (value > leaveCritical) return "critical";
|
|
13632
|
+
if (value > leaveElevated) return "elevated";
|
|
13633
|
+
return "ok";
|
|
13634
|
+
}
|
|
13635
|
+
if (previous === "elevated") {
|
|
13636
|
+
if (value > enterCritical) return "critical";
|
|
13637
|
+
if (value > leaveElevated) return "elevated";
|
|
13638
|
+
return "ok";
|
|
13639
|
+
}
|
|
13640
|
+
if (value > enterCritical) return "critical";
|
|
13641
|
+
if (value > enterElevated) return "elevated";
|
|
13642
|
+
return "ok";
|
|
13643
|
+
}
|
|
13644
|
+
function timesTotal(times) {
|
|
13645
|
+
return times.user + times.nice + times.sys + times.idle + times.irq;
|
|
13646
|
+
}
|
|
13647
|
+
function hostPressureOs(platform3) {
|
|
13648
|
+
if (platform3 === "darwin" || platform3 === "linux" || platform3 === "win32") return platform3;
|
|
13649
|
+
return void 0;
|
|
13650
|
+
}
|
|
13651
|
+
function cpuBusyRatio(previous, next) {
|
|
13652
|
+
if (!previous || previous.length === 0 || next.length === 0 || previous.length !== next.length) {
|
|
13653
|
+
return 0;
|
|
13654
|
+
}
|
|
13655
|
+
let idle = 0;
|
|
13656
|
+
let total = 0;
|
|
13657
|
+
for (let i = 0; i < next.length; i++) {
|
|
13658
|
+
const dt = timesTotal(next[i]) - timesTotal(previous[i]);
|
|
13659
|
+
if (dt <= 0) continue;
|
|
13660
|
+
total += dt;
|
|
13661
|
+
idle += Math.max(0, next[i].idle - previous[i].idle);
|
|
13662
|
+
}
|
|
13663
|
+
if (total <= 0) return 0;
|
|
13664
|
+
return 1 - idle / total;
|
|
13665
|
+
}
|
|
13666
|
+
function classifyHostPressure(sample, previous, platform3) {
|
|
13667
|
+
const memRaw = schmittLowIsWorse(
|
|
13668
|
+
sample.memFreeRatio,
|
|
13669
|
+
previous,
|
|
13670
|
+
HOST_PRESSURE_BARS.memFreeRatio.enterElevated,
|
|
13671
|
+
HOST_PRESSURE_BARS.memFreeRatio.leaveElevated,
|
|
13672
|
+
HOST_PRESSURE_BARS.memFreeRatio.enterCritical,
|
|
13673
|
+
HOST_PRESSURE_BARS.memFreeRatio.leaveCritical
|
|
13674
|
+
);
|
|
13675
|
+
const mem = platform3 === "darwin" && memRaw === "critical" ? "elevated" : memRaw;
|
|
13676
|
+
const eventLoop = schmittHighIsWorse(
|
|
13677
|
+
sample.eventLoopP99Ms,
|
|
13678
|
+
previous,
|
|
13679
|
+
HOST_PRESSURE_BARS.eventLoopP99Ms.enterElevated,
|
|
13680
|
+
HOST_PRESSURE_BARS.eventLoopP99Ms.leaveElevated,
|
|
13681
|
+
HOST_PRESSURE_BARS.eventLoopP99Ms.enterCritical,
|
|
13682
|
+
HOST_PRESSURE_BARS.eventLoopP99Ms.leaveCritical
|
|
13683
|
+
);
|
|
13684
|
+
const ncpu = sample.ncpu > 0 ? sample.ncpu : 1;
|
|
13685
|
+
const windows = platform3 === "win32";
|
|
13686
|
+
const loadValue = windows ? sample.cpuBusyRatio ?? 0 : sample.load1 / ncpu;
|
|
13687
|
+
const loadBars = windows ? HOST_PRESSURE_BARS.cpuBusy : HOST_PRESSURE_BARS.loadPerCpu;
|
|
13688
|
+
const load = schmittHighIsWorse(
|
|
13689
|
+
loadValue,
|
|
13690
|
+
previous,
|
|
13691
|
+
loadBars.enterElevated,
|
|
13692
|
+
loadBars.leaveElevated,
|
|
13693
|
+
loadBars.enterCritical,
|
|
13694
|
+
loadBars.leaveCritical
|
|
13695
|
+
);
|
|
13696
|
+
const resourceLevel = worst([mem, eventLoop, load]);
|
|
13697
|
+
const agentsPair = sample.liveAgents >= HOST_PRESSURE_BARS.liveAgentsPair && resourceLevel !== "ok";
|
|
13698
|
+
const level = resourceLevel;
|
|
13699
|
+
const firing = [];
|
|
13700
|
+
if (mem !== "ok") firing.push("memory");
|
|
13701
|
+
if (eventLoop !== "ok") firing.push("event_loop");
|
|
13702
|
+
if (load !== "ok") firing.push("load");
|
|
13703
|
+
if (agentsPair) firing.push("agents");
|
|
13704
|
+
const reasons = REASON_ORDER.filter((reason) => firing.includes(reason));
|
|
13705
|
+
return { level, reasons };
|
|
13706
|
+
}
|
|
13707
|
+
var HostPressureMonitor = class {
|
|
13708
|
+
constructor(opts) {
|
|
13709
|
+
this.opts = opts;
|
|
13710
|
+
}
|
|
13711
|
+
opts;
|
|
13712
|
+
timer = null;
|
|
13713
|
+
level = "ok";
|
|
13714
|
+
lastWarning = null;
|
|
13715
|
+
start() {
|
|
13716
|
+
this.opts.histogram?.enable();
|
|
13717
|
+
if (this.timer) return;
|
|
13718
|
+
const intervalMs = this.opts.intervalMs ?? HOST_PRESSURE_SAMPLE_MS;
|
|
13719
|
+
this.timer = setInterval(() => this.tick(), intervalMs);
|
|
13720
|
+
this.timer.unref?.();
|
|
13721
|
+
}
|
|
13722
|
+
tick() {
|
|
13723
|
+
const sample = this.opts.readSample();
|
|
13724
|
+
const platform3 = this.opts.platform ?? process.platform;
|
|
13725
|
+
const classified = classifyHostPressure(sample, this.level, platform3);
|
|
13726
|
+
if (classified.level === this.level) return;
|
|
13727
|
+
this.level = classified.level;
|
|
13728
|
+
const updatedAt = (this.opts.now ?? (() => /* @__PURE__ */ new Date()))().toISOString();
|
|
13729
|
+
if (classified.level === "ok") {
|
|
13730
|
+
this.lastWarning = null;
|
|
13731
|
+
this.opts.wsHub.broadcast({ type: "host_pressure_cleared", updatedAt });
|
|
13732
|
+
return;
|
|
13733
|
+
}
|
|
13734
|
+
const os2 = hostPressureOs(platform3);
|
|
13735
|
+
const message = {
|
|
13736
|
+
type: "host_pressure",
|
|
13737
|
+
level: classified.level,
|
|
13738
|
+
reasons: classified.reasons,
|
|
13739
|
+
liveAgents: sample.liveAgents,
|
|
13740
|
+
updatedAt,
|
|
13741
|
+
...os2 ? { os: os2 } : {}
|
|
13742
|
+
};
|
|
13743
|
+
this.lastWarning = message;
|
|
13744
|
+
this.opts.wsHub.broadcast(message);
|
|
13745
|
+
}
|
|
13746
|
+
wsMessage() {
|
|
13747
|
+
return this.lastWarning;
|
|
13748
|
+
}
|
|
13749
|
+
dispose() {
|
|
13750
|
+
if (this.timer) {
|
|
13751
|
+
clearInterval(this.timer);
|
|
13752
|
+
this.timer = null;
|
|
13753
|
+
}
|
|
13754
|
+
this.opts.histogram?.disable();
|
|
13755
|
+
}
|
|
13756
|
+
};
|
|
13757
|
+
function createHostPressureMonitor(wsHub, liveAgents) {
|
|
13758
|
+
const histogram = (0, import_perf_hooks.monitorEventLoopDelay)({ resolution: 20 });
|
|
13759
|
+
const windows = process.platform === "win32";
|
|
13760
|
+
let prevCpuTimes = null;
|
|
13761
|
+
const monitor = new HostPressureMonitor({
|
|
13762
|
+
wsHub,
|
|
13763
|
+
histogram,
|
|
13764
|
+
readSample: () => {
|
|
13765
|
+
const eventLoopP99Ms = histogram.percentile(99) / 1e6;
|
|
13766
|
+
histogram.reset();
|
|
13767
|
+
const total = (0, import_os13.totalmem)();
|
|
13768
|
+
const cpuList = (0, import_os13.cpus)();
|
|
13769
|
+
const sample = {
|
|
13770
|
+
liveAgents: liveAgents(),
|
|
13771
|
+
memFreeRatio: total > 0 ? (0, import_os13.freemem)() / total : 1,
|
|
13772
|
+
eventLoopP99Ms,
|
|
13773
|
+
load1: (0, import_os13.loadavg)()[0],
|
|
13774
|
+
ncpu: cpuList.length
|
|
13775
|
+
};
|
|
13776
|
+
if (windows) {
|
|
13777
|
+
const cpuTimes = cpuList.map((cpu) => cpu.times);
|
|
13778
|
+
sample.cpuBusyRatio = cpuBusyRatio(prevCpuTimes, cpuTimes);
|
|
13779
|
+
prevCpuTimes = cpuTimes;
|
|
13780
|
+
}
|
|
13781
|
+
return sample;
|
|
13782
|
+
}
|
|
13783
|
+
});
|
|
13784
|
+
monitor.start();
|
|
13785
|
+
return monitor;
|
|
13786
|
+
}
|
|
13787
|
+
|
|
13558
13788
|
// src/services/push/expoPushSender.ts
|
|
13559
13789
|
var log5 = getLogger("expo-push");
|
|
13560
13790
|
var EXPO_PUSH_ENDPOINT = "https://exp.host/--/api/v2/push/send";
|
|
@@ -15054,7 +15284,7 @@ function discoveredToResponse(d, conversationId) {
|
|
|
15054
15284
|
|
|
15055
15285
|
// src/session-watchers.ts
|
|
15056
15286
|
var import_fs27 = require("fs");
|
|
15057
|
-
var
|
|
15287
|
+
var import_os14 = require("os");
|
|
15058
15288
|
var import_path23 = require("path");
|
|
15059
15289
|
var SessionWatchers = class {
|
|
15060
15290
|
constructor(deps) {
|
|
@@ -15136,7 +15366,7 @@ var SessionWatchers = class {
|
|
|
15136
15366
|
// was passed to Claude via --session-id so the filename matches from the start.
|
|
15137
15367
|
watchForJsonl(sessionId, projectPath) {
|
|
15138
15368
|
const encoded = projectPath.replace(/[/\\:.]/g, "-");
|
|
15139
|
-
const projectsDir = (0, import_path23.join)((0,
|
|
15369
|
+
const projectsDir = (0, import_path23.join)((0, import_os14.homedir)(), ".claude", "projects", encoded);
|
|
15140
15370
|
const expectedFile = `${sessionId}.jsonl`;
|
|
15141
15371
|
const filePath = (0, import_path23.join)(projectsDir, expectedFile);
|
|
15142
15372
|
const deadline = Date.now() + 12e4;
|
|
@@ -15603,6 +15833,7 @@ var StreamerServer = class {
|
|
|
15603
15833
|
wsToClientId = /* @__PURE__ */ new Map();
|
|
15604
15834
|
cache = null;
|
|
15605
15835
|
cacheMonitor = null;
|
|
15836
|
+
hostPressureMonitor = null;
|
|
15606
15837
|
projectsRepo = null;
|
|
15607
15838
|
conversationsRepo = null;
|
|
15608
15839
|
sessionsRepo = null;
|
|
@@ -15667,7 +15898,7 @@ var StreamerServer = class {
|
|
|
15667
15898
|
this.skipStartupWarmup = config.skipStartupWarmup ?? false;
|
|
15668
15899
|
this.autoResumeOnBoot = config.autoResumeOnBoot ?? false;
|
|
15669
15900
|
this.scanProfiles = config.scanProfiles;
|
|
15670
|
-
this.codexRoots = config.codexRoots ?? [(0, import_path24.join)((0,
|
|
15901
|
+
this.codexRoots = config.codexRoots ?? [(0, import_path24.join)((0, import_os15.homedir)(), ".codex", "sessions")];
|
|
15671
15902
|
this.ptyGracePeriodMs = config.ptyGracePeriodMs ?? DEFAULT_PTY_GRACE_PERIOD_MS;
|
|
15672
15903
|
this.defaultSystemPrompt = config.defaultSystemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
15673
15904
|
const flagResolution = resolveFeatureFlags({
|
|
@@ -15684,7 +15915,7 @@ var StreamerServer = class {
|
|
|
15684
15915
|
this.claudeFlagsPersistable = config.claudeFlags === void 0;
|
|
15685
15916
|
this.claudeFlags = config.claudeFlags ?? loadClaudeFlags();
|
|
15686
15917
|
this.claudeExtraArgs = config.claudeExtraArgs ?? loadClaudeExtraArgs();
|
|
15687
|
-
this.cacheDir = config.cacheDir ?? loadCacheDir() ?? (0, import_path24.join)((0,
|
|
15918
|
+
this.cacheDir = config.cacheDir ?? loadCacheDir() ?? (0, import_path24.join)((0, import_os15.homedir)(), ".threadbase", "cache");
|
|
15688
15919
|
this.runtimeDbPath = resolveRuntimeDbPath(config.runtimeDbPath);
|
|
15689
15920
|
this.tailSize = config.tailSize ?? loadTailSize() ?? 10;
|
|
15690
15921
|
this.directoryDebounceMs = parseDirScanDebounceEnv(process.env.THREADBASE_DIR_SCAN_DEBOUNCE_MS) ?? config.directoryScanDebounceMs ?? 1e3;
|
|
@@ -15953,6 +16184,7 @@ var StreamerServer = class {
|
|
|
15953
16184
|
// reset-and-rescan, and tests swap methods on the server instance.
|
|
15954
16185
|
cache: () => this.cache,
|
|
15955
16186
|
cacheMonitor: () => this.cacheMonitor,
|
|
16187
|
+
hostPressureMonitor: () => this.hostPressureMonitor,
|
|
15956
16188
|
pushRepo: () => this.pushRepo,
|
|
15957
16189
|
liveActivityPushEnabled: () => this.liveActivityNotifier !== null,
|
|
15958
16190
|
devicesRepo: () => this.devicesRepo,
|
|
@@ -15968,6 +16200,7 @@ var StreamerServer = class {
|
|
|
15968
16200
|
withReconciledLifecycle: (sessions) => this.withReconciledLifecycle(sessions),
|
|
15969
16201
|
currentWarmupState: () => this.currentWarmupState(),
|
|
15970
16202
|
addSessionSubscriber: (sessionId, ws) => this.addSessionSubscriber(sessionId, ws),
|
|
16203
|
+
removeSessionSubscriber: (sessionId, ws) => this.removeSessionSubscriber(sessionId, ws),
|
|
15971
16204
|
startGraceTimer: (sessionId, delayMs) => this.startGraceTimer(sessionId, delayMs),
|
|
15972
16205
|
armHoldWhenIdle: (sessionId) => this.armHoldWhenIdle(sessionId),
|
|
15973
16206
|
handleSessionsCount: (res) => this.handleSessionsCount(res),
|
|
@@ -16097,6 +16330,12 @@ var StreamerServer = class {
|
|
|
16097
16330
|
);
|
|
16098
16331
|
}
|
|
16099
16332
|
}
|
|
16333
|
+
removeSessionSubscriber(sessionId, ws) {
|
|
16334
|
+
const subs = this.sessionSubscribers.get(sessionId);
|
|
16335
|
+
if (!subs) return;
|
|
16336
|
+
subs.delete(ws);
|
|
16337
|
+
if (subs.size === 0) this.sessionSubscribers.delete(sessionId);
|
|
16338
|
+
}
|
|
16100
16339
|
/**
|
|
16101
16340
|
* Bring up Live Activity push, if credentials are present (Feature 12).
|
|
16102
16341
|
*
|
|
@@ -16123,14 +16362,14 @@ var StreamerServer = class {
|
|
|
16123
16362
|
}
|
|
16124
16363
|
this.apnsClient = new ApnsClient(creds);
|
|
16125
16364
|
const sender = new LiveActivitySender(this.apnsClient, pushRepo);
|
|
16126
|
-
const serverId = process.env.THREADBASE_INSTANCE_ID ?? (0,
|
|
16127
|
-
this.liveActivityNotifier = new LiveActivityNotifier(sender, serverId, (0,
|
|
16365
|
+
const serverId = process.env.THREADBASE_INSTANCE_ID ?? (0, import_os15.hostname)();
|
|
16366
|
+
this.liveActivityNotifier = new LiveActivityNotifier(sender, serverId, (0, import_os15.hostname)());
|
|
16128
16367
|
this.liveActivityRenewal = new LiveActivityRenewalScheduler({
|
|
16129
16368
|
repo: pushRepo,
|
|
16130
16369
|
sender,
|
|
16131
16370
|
sessionStore: this.sessionStore,
|
|
16132
16371
|
serverId,
|
|
16133
|
-
serverLabel: (0,
|
|
16372
|
+
serverLabel: (0, import_os15.hostname)()
|
|
16134
16373
|
});
|
|
16135
16374
|
this.liveActivityRenewal.start();
|
|
16136
16375
|
this.log.info("Live Activity push enabled", {
|
|
@@ -16150,7 +16389,7 @@ var StreamerServer = class {
|
|
|
16150
16389
|
*/
|
|
16151
16390
|
initWaitingInputPush(pushRepo) {
|
|
16152
16391
|
const sender = new ExpoPushSender(pushRepo, process.env.THREADBASE_EXPO_ACCESS_TOKEN);
|
|
16153
|
-
const serverId = process.env.THREADBASE_INSTANCE_ID ?? (0,
|
|
16392
|
+
const serverId = process.env.THREADBASE_INSTANCE_ID ?? (0, import_os15.hostname)();
|
|
16154
16393
|
this.waitingInputNotifier = new WaitingInputNotifier(
|
|
16155
16394
|
sender,
|
|
16156
16395
|
serverId,
|
|
@@ -16380,7 +16619,7 @@ var StreamerServer = class {
|
|
|
16380
16619
|
let sessions = null;
|
|
16381
16620
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
16382
16621
|
const transport = await connectOrSpawnHost({
|
|
16383
|
-
instanceId: process.env.THREADBASE_INSTANCE_ID ?? (0,
|
|
16622
|
+
instanceId: process.env.THREADBASE_INSTANCE_ID ?? (0, import_os15.hostname)()
|
|
16384
16623
|
});
|
|
16385
16624
|
try {
|
|
16386
16625
|
sessions = await this.ptyManager.useRemoteRunner(transport);
|
|
@@ -16427,6 +16666,10 @@ var StreamerServer = class {
|
|
|
16427
16666
|
this.idleReaperTimer = setInterval(() => this.reapIdleSessions(), IDLE_REAP_SWEEP_MS);
|
|
16428
16667
|
this.idleReaperTimer.unref?.();
|
|
16429
16668
|
}
|
|
16669
|
+
this.hostPressureMonitor = createHostPressureMonitor(
|
|
16670
|
+
this.wsHub,
|
|
16671
|
+
() => this.ptyAttachedIds().size
|
|
16672
|
+
);
|
|
16430
16673
|
const warmUp = new Promise((resolveWarm) => {
|
|
16431
16674
|
{
|
|
16432
16675
|
this.log.info(`Streamer server listening on port ${port}`, {
|
|
@@ -16739,6 +16982,8 @@ var StreamerServer = class {
|
|
|
16739
16982
|
clearInterval(this.idleReaperTimer);
|
|
16740
16983
|
this.idleReaperTimer = null;
|
|
16741
16984
|
}
|
|
16985
|
+
this.hostPressureMonitor?.dispose();
|
|
16986
|
+
this.hostPressureMonitor = null;
|
|
16742
16987
|
this.lastAgentChunkAt.clear();
|
|
16743
16988
|
this.terminalSeq.clear();
|
|
16744
16989
|
if (this.ptyManager.isRemote()) this.ptyManager.dispose();
|
|
@@ -16932,7 +17177,7 @@ var StreamerServer = class {
|
|
|
16932
17177
|
deviceToken: device.deviceToken,
|
|
16933
17178
|
capabilities: device.capabilities,
|
|
16934
17179
|
publicUrl: this.publicUrl,
|
|
16935
|
-
machineName: (0,
|
|
17180
|
+
machineName: (0, import_os15.hostname)(),
|
|
16936
17181
|
serverVersion: getVersion()
|
|
16937
17182
|
})
|
|
16938
17183
|
);
|
|
@@ -16966,7 +17211,7 @@ var StreamerServer = class {
|
|
|
16966
17211
|
// Released builds that predate that fix DO still adopt it, so changing
|
|
16967
17212
|
// this value moves where old devices talk. It is not a free field.
|
|
16968
17213
|
publicUrl: this.publicUrl,
|
|
16969
|
-
machineName: (0,
|
|
17214
|
+
machineName: (0, import_os15.hostname)(),
|
|
16970
17215
|
...device && {
|
|
16971
17216
|
deviceId: device.deviceId,
|
|
16972
17217
|
deviceToken: device.deviceToken,
|