@threadbase-sh/streamer 1.38.0 → 1.39.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/cli.cjs +183 -19
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +180 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +44 -3
- package/dist/index.d.ts +44 -3
- package/dist/index.js +180 -15
- package/dist/index.js.map +1 -1
- package/dist/migrations/014_add_conversation_meta_file_path_index.sql +5 -0
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -1490,6 +1490,9 @@ function isPermissionMode(value) {
|
|
|
1490
1490
|
function isDangerousPermissionMode(mode) {
|
|
1491
1491
|
return DANGEROUS_PERMISSION_MODES.includes(mode);
|
|
1492
1492
|
}
|
|
1493
|
+
function isEffortLevel(value) {
|
|
1494
|
+
return typeof value === "string" && EFFORT_LEVELS.includes(value);
|
|
1495
|
+
}
|
|
1493
1496
|
function findFlag(id) {
|
|
1494
1497
|
return CLAUDE_FLAGS.find((f2) => f2.id === id);
|
|
1495
1498
|
}
|
|
@@ -1554,7 +1557,7 @@ function buildFlagArgs(values, extraArgs) {
|
|
|
1554
1557
|
const args = [];
|
|
1555
1558
|
const safe = validateFlagValues(values ?? {});
|
|
1556
1559
|
for (const def of CLAUDE_FLAGS) {
|
|
1557
|
-
if (def.id
|
|
1560
|
+
if (SPAWN_POSITIONAL_FLAG_IDS.has(def.id)) continue;
|
|
1558
1561
|
const value = safe[def.id];
|
|
1559
1562
|
if (value === void 0) continue;
|
|
1560
1563
|
if (def.valueType === "boolean") {
|
|
@@ -1577,7 +1580,7 @@ function buildSettingsJson(permissionMode) {
|
|
|
1577
1580
|
}
|
|
1578
1581
|
return JSON.stringify(settings);
|
|
1579
1582
|
}
|
|
1580
|
-
var PERMISSION_MODES, DANGEROUS_PERMISSION_MODES, CLAUDE_FLAGS;
|
|
1583
|
+
var PERMISSION_MODES, DANGEROUS_PERMISSION_MODES, EFFORT_LEVELS, CLAUDE_FLAGS, SPAWN_POSITIONAL_FLAG_IDS;
|
|
1581
1584
|
var init_claude_flags = __esm({
|
|
1582
1585
|
"src/claude-flags.ts"() {
|
|
1583
1586
|
"use strict";
|
|
@@ -1593,6 +1596,7 @@ var init_claude_flags = __esm({
|
|
|
1593
1596
|
"bypassPermissions",
|
|
1594
1597
|
"dontAsk"
|
|
1595
1598
|
];
|
|
1599
|
+
EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
|
|
1596
1600
|
CLAUDE_FLAGS = [
|
|
1597
1601
|
{
|
|
1598
1602
|
id: "permissionMode",
|
|
@@ -1604,9 +1608,10 @@ var init_claude_flags = __esm({
|
|
|
1604
1608
|
{ id: "addDir", flag: "--add-dir", valueType: "list", risk: "elevated" },
|
|
1605
1609
|
{ id: "allowedTools", flag: "--allowedTools", valueType: "list", risk: "elevated" },
|
|
1606
1610
|
{ id: "disallowedTools", flag: "--disallowedTools", valueType: "list", risk: "low" },
|
|
1607
|
-
{ id: "
|
|
1608
|
-
{ id: "
|
|
1611
|
+
{ id: "model", flag: "--model", valueType: "string", risk: "low" },
|
|
1612
|
+
{ id: "effort", flag: "--effort", valueType: "enum", enumValues: EFFORT_LEVELS, risk: "low" }
|
|
1609
1613
|
];
|
|
1614
|
+
SPAWN_POSITIONAL_FLAG_IDS = /* @__PURE__ */ new Set(["permissionMode", "model", "effort"]);
|
|
1610
1615
|
}
|
|
1611
1616
|
});
|
|
1612
1617
|
|
|
@@ -139499,6 +139504,14 @@ var createSessionRoutes = (deps) => {
|
|
|
139499
139504
|
await deps.handleSetSessionName(c.req.param("id"), c.env.incoming, c.env.outgoing);
|
|
139500
139505
|
return alreadyHandled6();
|
|
139501
139506
|
});
|
|
139507
|
+
app.patch("/:id/model", async (c) => {
|
|
139508
|
+
await deps.handleSetSessionModel(c.req.param("id"), c.env.incoming, c.env.outgoing);
|
|
139509
|
+
return alreadyHandled6();
|
|
139510
|
+
});
|
|
139511
|
+
app.patch("/:id/effort", async (c) => {
|
|
139512
|
+
await deps.handleSetSessionEffort(c.req.param("id"), c.env.incoming, c.env.outgoing);
|
|
139513
|
+
return alreadyHandled6();
|
|
139514
|
+
});
|
|
139502
139515
|
app.post("/:id/adopt", async (c) => {
|
|
139503
139516
|
await deps.handleAdopt(c.req.param("id"), c.env.outgoing);
|
|
139504
139517
|
return alreadyHandled6();
|
|
@@ -139838,6 +139851,7 @@ CREATE TABLE IF NOT EXISTS conversation_meta (
|
|
|
139838
139851
|
);
|
|
139839
139852
|
CREATE INDEX IF NOT EXISTS idx_meta_last_activity ON conversation_meta(last_activity DESC);
|
|
139840
139853
|
CREATE INDEX IF NOT EXISTS idx_meta_project ON conversation_meta(project_path);
|
|
139854
|
+
CREATE INDEX IF NOT EXISTS idx_meta_file_path ON conversation_meta(file_path);
|
|
139841
139855
|
|
|
139842
139856
|
CREATE TABLE IF NOT EXISTS conversation_tail (
|
|
139843
139857
|
conversation_id TEXT PRIMARY KEY REFERENCES conversation_meta(id) ON DELETE CASCADE,
|
|
@@ -145915,6 +145929,24 @@ var WSHub = class {
|
|
|
145915
145929
|
this.clients.delete(client);
|
|
145916
145930
|
}
|
|
145917
145931
|
}
|
|
145932
|
+
// Scoped broadcast for high-frequency per-session messages (terminal_output,
|
|
145933
|
+
// user_message). Sending to every connected client for every PTY output
|
|
145934
|
+
// chunk made broadcast() cost scale with connections x active sessions;
|
|
145935
|
+
// this bounds it to only that session's subscribers.
|
|
145936
|
+
broadcastToClients(clients, message) {
|
|
145937
|
+
const data = JSON.stringify(message);
|
|
145938
|
+
for (const client of clients) {
|
|
145939
|
+
try {
|
|
145940
|
+
if (client.readyState === client.OPEN) {
|
|
145941
|
+
client.send(data);
|
|
145942
|
+
} else {
|
|
145943
|
+
this.clients.delete(client);
|
|
145944
|
+
}
|
|
145945
|
+
} catch {
|
|
145946
|
+
this.clients.delete(client);
|
|
145947
|
+
}
|
|
145948
|
+
}
|
|
145949
|
+
}
|
|
145918
145950
|
unicast(ws2, message) {
|
|
145919
145951
|
try {
|
|
145920
145952
|
if (ws2.readyState === ws2.OPEN) {
|
|
@@ -145977,6 +146009,7 @@ var ADOPT_KILL_TIMEOUT_MS = 5e3;
|
|
|
145977
146009
|
var ADOPT_KILL_POLL_MS = 100;
|
|
145978
146010
|
var REFRESH_TTL_MS = 2e3;
|
|
145979
146011
|
var START_READY_TIMEOUT_MS = 1e4;
|
|
146012
|
+
var MODEL_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
145980
146013
|
var EXTERNAL_TAIL_RECENCY_MS = RESUME_BUSY_WINDOW_MS;
|
|
145981
146014
|
var EXTERNAL_TAIL_MAX = 32;
|
|
145982
146015
|
var EXTERNAL_TAIL_IDLE_MS = 3e5;
|
|
@@ -146080,6 +146113,8 @@ var StreamerServer = class {
|
|
|
146080
146113
|
dbPool = null;
|
|
146081
146114
|
dbInstanceId = null;
|
|
146082
146115
|
disableDb = false;
|
|
146116
|
+
// Skip the startup warm-up scan (test hook; see ServerConfig.skipStartupWarmup).
|
|
146117
|
+
skipStartupWarmup;
|
|
146083
146118
|
browseRoot = null;
|
|
146084
146119
|
publicUrl = null;
|
|
146085
146120
|
browserCors;
|
|
@@ -146119,6 +146154,11 @@ var StreamerServer = class {
|
|
|
146119
146154
|
// every provider; read only by the idle reaper. Entries are dropped when the
|
|
146120
146155
|
// session leaves the runner (reap/exit/hold).
|
|
146121
146156
|
lastAgentChunkAt = /* @__PURE__ */ new Map();
|
|
146157
|
+
// sessionId → last terminal_output seq broadcast (starts at 1, per session).
|
|
146158
|
+
// Stamped on every terminal_output/terminal_replay so a client can detect a
|
|
146159
|
+
// stale chunk delivered after a reconnect race instead of trusting raw WS
|
|
146160
|
+
// arrival order. Entries dropped alongside lastAgentChunkAt.
|
|
146161
|
+
terminalSeq = /* @__PURE__ */ new Map();
|
|
146122
146162
|
// Recently accepted input idempotency keys (C4). A retried POST replays its
|
|
146123
146163
|
// original outcome instead of submitting the prompt to the agent twice.
|
|
146124
146164
|
idempotency = new IdempotencyStore();
|
|
@@ -146186,6 +146226,7 @@ var StreamerServer = class {
|
|
|
146186
146226
|
}
|
|
146187
146227
|
this.verbose = config2.verbose ?? false;
|
|
146188
146228
|
this.disableDb = config2.disableDb ?? false;
|
|
146229
|
+
this.skipStartupWarmup = config2.skipStartupWarmup ?? false;
|
|
146189
146230
|
this.scannerPersistenceDisabled = config2.scannerPersistent === false;
|
|
146190
146231
|
this.scanProfiles = config2.scanProfiles;
|
|
146191
146232
|
this.codexRoots = config2.codexRoots ?? [(0, import_path29.join)((0, import_os12.homedir)(), ".codex", "sessions")];
|
|
@@ -146334,10 +146375,22 @@ var StreamerServer = class {
|
|
|
146334
146375
|
logger: getLogger("pty"),
|
|
146335
146376
|
onOutput: (sessionId, data) => {
|
|
146336
146377
|
this.lastAgentChunkAt.set(sessionId, Date.now());
|
|
146337
|
-
this.
|
|
146378
|
+
const seq = (this.terminalSeq.get(sessionId) ?? 0) + 1;
|
|
146379
|
+
this.terminalSeq.set(sessionId, seq);
|
|
146380
|
+
this.wsHub.broadcastToClients(this.sessionSubscribers.get(sessionId) ?? [], {
|
|
146381
|
+
type: "terminal_output",
|
|
146382
|
+
sessionId,
|
|
146383
|
+
data,
|
|
146384
|
+
seq
|
|
146385
|
+
});
|
|
146338
146386
|
},
|
|
146339
146387
|
onUserMessage: (sessionId, text, ts2) => {
|
|
146340
|
-
this.wsHub.
|
|
146388
|
+
this.wsHub.broadcastToClients(this.sessionSubscribers.get(sessionId) ?? [], {
|
|
146389
|
+
type: "user_message",
|
|
146390
|
+
sessionId,
|
|
146391
|
+
text,
|
|
146392
|
+
ts: ts2
|
|
146393
|
+
});
|
|
146341
146394
|
},
|
|
146342
146395
|
onPermissionChange: (sessionId, gate) => {
|
|
146343
146396
|
this.handlePermissionChange(sessionId, gate);
|
|
@@ -146474,6 +146527,8 @@ var StreamerServer = class {
|
|
|
146474
146527
|
handleCancel: (id, res) => this.handleCancel(id, res),
|
|
146475
146528
|
handleStopSession: (id, res) => this.handleStopSession(id, res),
|
|
146476
146529
|
handleSetSessionName: (id, req, res) => this.handleSetSessionName(id, req, res),
|
|
146530
|
+
handleSetSessionModel: (id, req, res) => this.applyLiveSessionSetting(id, req, res, "model"),
|
|
146531
|
+
handleSetSessionEffort: (id, req, res) => this.applyLiveSessionSetting(id, req, res, "effort"),
|
|
146477
146532
|
handleUploadFile: (id, req, res) => this.handleUploadFile(id, req, res),
|
|
146478
146533
|
handleAdopt: (id, res) => this.handleAdopt(id, res),
|
|
146479
146534
|
handleResume: (req, res) => this.handleResume(req, res),
|
|
@@ -146520,7 +146575,8 @@ var StreamerServer = class {
|
|
|
146520
146575
|
type: "terminal_replay",
|
|
146521
146576
|
sessionId: msg.sessionId,
|
|
146522
146577
|
lines,
|
|
146523
|
-
userMessages
|
|
146578
|
+
userMessages,
|
|
146579
|
+
seq: this.terminalSeq.get(msg.sessionId)
|
|
146524
146580
|
})
|
|
146525
146581
|
);
|
|
146526
146582
|
}
|
|
@@ -146880,6 +146936,7 @@ var StreamerServer = class {
|
|
|
146880
146936
|
);
|
|
146881
146937
|
this.ptyManager.putOnHold(session.id);
|
|
146882
146938
|
this.lastAgentChunkAt.delete(session.id);
|
|
146939
|
+
this.terminalSeq.delete(session.id);
|
|
146883
146940
|
this.idempotency.clear(session.id);
|
|
146884
146941
|
this.sessionSubscribers.delete(session.id);
|
|
146885
146942
|
reaped.push(session.id);
|
|
@@ -147054,6 +147111,14 @@ var StreamerServer = class {
|
|
|
147054
147111
|
);
|
|
147055
147112
|
this.scannerPersistenceDisabled = true;
|
|
147056
147113
|
}
|
|
147114
|
+
if (this.skipStartupWarmup) {
|
|
147115
|
+
this.log.debug?.("startup warm-up scan skipped (skipStartupWarmup)", {
|
|
147116
|
+
event: "cache.warmup_skipped"
|
|
147117
|
+
});
|
|
147118
|
+
this.finishWarmup(0);
|
|
147119
|
+
resolveWarm();
|
|
147120
|
+
return;
|
|
147121
|
+
}
|
|
147057
147122
|
const warmupStatCache = this.buildStatCache(null);
|
|
147058
147123
|
const warmupScanner = this.newScanner(warmupStatCache ? { persistent: false } : void 0);
|
|
147059
147124
|
this.allScanners.add(warmupScanner);
|
|
@@ -147245,6 +147310,7 @@ var StreamerServer = class {
|
|
|
147245
147310
|
this.idleReaperTimer = null;
|
|
147246
147311
|
}
|
|
147247
147312
|
this.lastAgentChunkAt.clear();
|
|
147313
|
+
this.terminalSeq.clear();
|
|
147248
147314
|
this.recordShutdownState();
|
|
147249
147315
|
this.markScannerStaleDebounced.cancel();
|
|
147250
147316
|
await Promise.all([...this.inFlightCacheWrites]);
|
|
@@ -147426,6 +147492,30 @@ var StreamerServer = class {
|
|
|
147426
147492
|
persisted: this.claudeFlagsPersistable
|
|
147427
147493
|
};
|
|
147428
147494
|
}
|
|
147495
|
+
/**
|
|
147496
|
+
* The three spawn options that a configured claude-flag can override, with
|
|
147497
|
+
* the boot-time CLI/yaml default as the fallback. Spread into every
|
|
147498
|
+
* start/resume/adopt call so all three paths agree.
|
|
147499
|
+
*
|
|
147500
|
+
* These ids are excluded from buildFlagArgs (SPAWN_POSITIONAL_FLAG_IDS)
|
|
147501
|
+
* precisely because they arrive here instead — the PTY spawn paths pass them
|
|
147502
|
+
* as explicit positionals, so emitting them from the allowlist too would
|
|
147503
|
+
* duplicate the flag.
|
|
147504
|
+
*
|
|
147505
|
+
* Narrowed with the type guards rather than cast: ClaudeFlagValues is a loose
|
|
147506
|
+
* Record by design, and while validateFlagValues already guarantees the shape
|
|
147507
|
+
* on the way in, TypeScript cannot see that through the record.
|
|
147508
|
+
*/
|
|
147509
|
+
spawnFlagOverrides() {
|
|
147510
|
+
const mode = this.claudeFlags.permissionMode;
|
|
147511
|
+
const model = this.claudeFlags.model;
|
|
147512
|
+
const effort = this.claudeFlags.effort;
|
|
147513
|
+
return {
|
|
147514
|
+
permissionMode: isPermissionMode(mode) ? mode : this.defaultPermissionMode,
|
|
147515
|
+
model: typeof model === "string" ? model : this.defaultModel,
|
|
147516
|
+
effort: isEffortLevel(effort) ? effort : this.defaultEffort
|
|
147517
|
+
};
|
|
147518
|
+
}
|
|
147429
147519
|
checkRateLimit(map2, key, limit, windowMs) {
|
|
147430
147520
|
const now = Date.now();
|
|
147431
147521
|
const arr = (map2.get(key) ?? []).filter((t) => now - t < windowMs);
|
|
@@ -148575,11 +148665,9 @@ var StreamerServer = class {
|
|
|
148575
148665
|
projectPath,
|
|
148576
148666
|
projectName: body.projectName,
|
|
148577
148667
|
branch: body.branch,
|
|
148578
|
-
permissionMode: this.defaultPermissionMode,
|
|
148579
148668
|
claudeFlags: this.claudeFlags,
|
|
148580
148669
|
claudeExtraArgs: this.claudeExtraArgs,
|
|
148581
|
-
|
|
148582
|
-
effort: this.defaultEffort
|
|
148670
|
+
...this.spawnFlagOverrides()
|
|
148583
148671
|
});
|
|
148584
148672
|
this.sessionStore.addManaged(session);
|
|
148585
148673
|
this.recordSessionSpawn(session);
|
|
@@ -149026,11 +149114,9 @@ var StreamerServer = class {
|
|
|
149026
149114
|
projectPath,
|
|
149027
149115
|
projectName,
|
|
149028
149116
|
branch,
|
|
149029
|
-
permissionMode: this.defaultPermissionMode,
|
|
149030
149117
|
claudeFlags: this.claudeFlags,
|
|
149031
149118
|
claudeExtraArgs: this.claudeExtraArgs,
|
|
149032
|
-
|
|
149033
|
-
effort: this.defaultEffort
|
|
149119
|
+
...this.spawnFlagOverrides()
|
|
149034
149120
|
});
|
|
149035
149121
|
this.sessionStore.addManaged(session);
|
|
149036
149122
|
this.recordSessionSpawn(session);
|
|
@@ -149103,11 +149189,9 @@ var StreamerServer = class {
|
|
|
149103
149189
|
projectPath: resolvedPath,
|
|
149104
149190
|
projectName: body.projectName,
|
|
149105
149191
|
...includeSystemPrompt && { systemPrompt: systemPromptParts.join("\n") },
|
|
149106
|
-
permissionMode: this.defaultPermissionMode,
|
|
149107
149192
|
claudeFlags: this.claudeFlags,
|
|
149108
149193
|
claudeExtraArgs: this.claudeExtraArgs,
|
|
149109
|
-
|
|
149110
|
-
effort: this.defaultEffort
|
|
149194
|
+
...this.spawnFlagOverrides()
|
|
149111
149195
|
});
|
|
149112
149196
|
this.sessionStore.addManaged(session);
|
|
149113
149197
|
this.recordSessionSpawn(session);
|
|
@@ -149467,6 +149551,87 @@ var StreamerServer = class {
|
|
|
149467
149551
|
this.cache.upsertSessionName(sessionId, name);
|
|
149468
149552
|
json2(res, 200, { ok: true });
|
|
149469
149553
|
}
|
|
149554
|
+
/**
|
|
149555
|
+
* Retarget a LIVE session's model or effort by typing the corresponding
|
|
149556
|
+
* Claude Code slash command into its PTY.
|
|
149557
|
+
*
|
|
149558
|
+
* There is no CLI or IPC channel for this — `--model`/`--effort` are spawn
|
|
149559
|
+
* arguments — so the interactive `/model <x>` / `/effort <y>` commands are the
|
|
149560
|
+
* only way to change a session already running. Both accept an argument and
|
|
149561
|
+
* apply it without opening the picker (verified against Claude Code v2.1.220).
|
|
149562
|
+
*
|
|
149563
|
+
* Answers 202, not 200: the value is applied by the TUI on its next render, so
|
|
149564
|
+
* there is nothing truthful to echo back synchronously. Clients confirm with
|
|
149565
|
+
* `GET /api/sessions/:id`, which scrapes the applied value off the live status
|
|
149566
|
+
* line.
|
|
149567
|
+
*/
|
|
149568
|
+
async applyLiveSessionSetting(sessionId, req, res, setting) {
|
|
149569
|
+
const session = this.ptyManager.getSession(sessionId);
|
|
149570
|
+
if (!session) {
|
|
149571
|
+
const known = this.sessionStore.getManaged(sessionId);
|
|
149572
|
+
if (known) {
|
|
149573
|
+
json2(res, 409, {
|
|
149574
|
+
error: "Session has no live PTY; resume it first",
|
|
149575
|
+
code: "SESSION_IDLE"
|
|
149576
|
+
});
|
|
149577
|
+
return;
|
|
149578
|
+
}
|
|
149579
|
+
json2(res, 404, { error: "Session not found" });
|
|
149580
|
+
return;
|
|
149581
|
+
}
|
|
149582
|
+
if ((session.provider ?? CLAUDE_CODE_PROVIDER2) !== CLAUDE_CODE_PROVIDER2) {
|
|
149583
|
+
json2(res, 501, {
|
|
149584
|
+
error: `Setting ${setting} on a ${session.provider} session is not supported`,
|
|
149585
|
+
code: "UNSUPPORTED_PROVIDER"
|
|
149586
|
+
});
|
|
149587
|
+
return;
|
|
149588
|
+
}
|
|
149589
|
+
if (session.status === "running") {
|
|
149590
|
+
json2(res, 409, {
|
|
149591
|
+
error: "Session is mid-turn; retry once it is waiting for input",
|
|
149592
|
+
code: "SESSION_BUSY"
|
|
149593
|
+
});
|
|
149594
|
+
return;
|
|
149595
|
+
}
|
|
149596
|
+
let parsed;
|
|
149597
|
+
try {
|
|
149598
|
+
parsed = await readBody(req);
|
|
149599
|
+
} catch {
|
|
149600
|
+
json2(res, 400, { error: "Invalid JSON" });
|
|
149601
|
+
return;
|
|
149602
|
+
}
|
|
149603
|
+
let value;
|
|
149604
|
+
if (setting === "effort") {
|
|
149605
|
+
if (!isEffortLevel(parsed.effort)) {
|
|
149606
|
+
json2(res, 400, {
|
|
149607
|
+
error: `effort must be one of ${EFFORT_LEVELS.join(", ")}`
|
|
149608
|
+
});
|
|
149609
|
+
return;
|
|
149610
|
+
}
|
|
149611
|
+
value = parsed.effort;
|
|
149612
|
+
} else {
|
|
149613
|
+
if (typeof parsed.model !== "string" || !MODEL_NAME_RE.test(parsed.model)) {
|
|
149614
|
+
json2(res, 400, {
|
|
149615
|
+
error: "model must be an alias or full model name (letters, digits, dot, dash, underscore)"
|
|
149616
|
+
});
|
|
149617
|
+
return;
|
|
149618
|
+
}
|
|
149619
|
+
value = parsed.model;
|
|
149620
|
+
}
|
|
149621
|
+
try {
|
|
149622
|
+
this.ptyManager.sendKeys(sessionId, `/${setting} ${value}\r`);
|
|
149623
|
+
} catch (err) {
|
|
149624
|
+
json2(res, 400, { error: err instanceof Error ? err.message : "Failed to write to session" });
|
|
149625
|
+
return;
|
|
149626
|
+
}
|
|
149627
|
+
this.log.info(`Live session ${setting} set to ${value}`, {
|
|
149628
|
+
event: "session.setting_applied",
|
|
149629
|
+
sessionId,
|
|
149630
|
+
setting,
|
|
149631
|
+
value
|
|
149632
|
+
});
|
|
149633
|
+
json2(res, 202, { id: sessionId, [setting]: value });
|
|
149634
|
+
}
|
|
149470
149635
|
handleGetSessionNames(res) {
|
|
149471
149636
|
if (!this.cache) {
|
|
149472
149637
|
json2(res, 200, {});
|
|
@@ -153557,10 +153722,9 @@ program2.command("serve").description("Start the streamer server").option("-p, -
|
|
|
153557
153722
|
}
|
|
153558
153723
|
featureFlags = parsed.values;
|
|
153559
153724
|
}
|
|
153560
|
-
|
|
153561
|
-
if (opts.defaultEffort !== void 0 && !validEfforts.includes(opts.defaultEffort)) {
|
|
153725
|
+
if (opts.defaultEffort !== void 0 && !isEffortLevel(opts.defaultEffort)) {
|
|
153562
153726
|
log11.error(
|
|
153563
|
-
`Invalid --default-effort: ${opts.defaultEffort} (expected one of ${
|
|
153727
|
+
`Invalid --default-effort: ${opts.defaultEffort} (expected one of ${EFFORT_LEVELS.join(", ")})`,
|
|
153564
153728
|
void 0,
|
|
153565
153729
|
"console"
|
|
153566
153730
|
);
|