@gotcos/glasses-server 6.24.1 → 6.24.2
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/CHANGELOG.md +26 -0
- package/package.json +1 -1
- package/server/routes/transcribe-stream.ts +26 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
## 6.24.2
|
|
2
|
+
|
|
3
|
+
The empty-recording restart lock, split out of 6.24.1.
|
|
4
|
+
|
|
5
|
+
**Correction to 6.24.1's own entry.** These bullets were written under 6.24.1 while it
|
|
6
|
+
was still unpublished, but it had already gone to the registry by then, so that heading
|
|
7
|
+
described a published artifact that does not contain this code. Verified by downloading
|
|
8
|
+
the published tarball: 6.24.1 carries the `project` field and has no
|
|
9
|
+
`EMPTY_SESSION_STALE_MS`. Moved here rather than left standing.
|
|
10
|
+
|
|
11
|
+
- **A 6-second aborted recording no longer locks the restart for 30 minutes.**
|
|
12
|
+
`getTranscriptionSessionLiveness` gated purely on elapsed time. The 30-minute grace
|
|
13
|
+
exists to protect a real recording that has gone briefly quiet — a backgrounded phone
|
|
14
|
+
buffering to IndexedDB — but a session with NO canonical text has nothing to protect.
|
|
15
|
+
Observed 2026-08-10: `meeting_1786393815060_tp693w` started, received one 5.6s chunk
|
|
16
|
+
that transcribed to empty, stopped 6.2 seconds later, and then blocked Update Server.
|
|
17
|
+
A session idle past `EMPTY_SESSION_STALE_MS` (2 minutes) with zero canonical chunks
|
|
18
|
+
now stops blocking a restart.
|
|
19
|
+
- **Why that cannot reap a live recording.** `lastActivityAt` is bumped on chunk
|
|
20
|
+
ARRIVAL, before any text filtering, so a live recording in a silent room keeps
|
|
21
|
+
arriving every ~10s and never goes idle at all; its silent chunks land in
|
|
22
|
+
`emptyCompletions`, not `chunks`. Gating on emptiness ALONE would kill exactly that
|
|
23
|
+
session, which is why the rule requires emptiness AND idleness. Counted on canonical
|
|
24
|
+
text rather than array length, because the array is sparse and a silent chunk carries
|
|
25
|
+
no text — the precise shape an aborted recording leaves behind.
|
|
26
|
+
|
|
1
27
|
## 6.24.1
|
|
2
28
|
|
|
3
29
|
Surfaces `project` on session rows, so the list can group the way Claude Code's own
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gotcos/glasses-server",
|
|
3
|
-
"version": "6.24.
|
|
3
|
+
"version": "6.24.2",
|
|
4
4
|
"description": "COS Glasses \u2014 self-hosted AI heads-up-display server for Even G2 smart glasses, powered by Claude Code, Codex, or Cursor Agent CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -387,6 +387,26 @@ export function getActiveTranscriptionSessionCount(): number {
|
|
|
387
387
|
*/
|
|
388
388
|
export const RECORDING_SESSION_STALE_MS = STRANDED_STALE_MS
|
|
389
389
|
|
|
390
|
+
/**
|
|
391
|
+
* How long an EMPTY session may hold the restart lock.
|
|
392
|
+
*
|
|
393
|
+
* The 30-minute grace above protects a real recording that has gone briefly quiet — a
|
|
394
|
+
* backgrounded phone buffering to IndexedDB, a network drop, a long pause. A session
|
|
395
|
+
* that has produced NO canonical text has nothing to protect, so it must not lock
|
|
396
|
+
* Install, Repair, Restart and Update Server for half an hour.
|
|
397
|
+
*
|
|
398
|
+
* Observed 2026-08-10: meeting_1786393815060_tp693w started, took ONE 5.6s chunk that
|
|
399
|
+
* transcribed to empty, stopped 6.2s later, then blocked every restart for 30 minutes.
|
|
400
|
+
*
|
|
401
|
+
* WHY THIS CANNOT REAP A LIVE RECORDING. `lastActivityAt` is bumped on chunk ARRIVAL
|
|
402
|
+
* in processStreamChunk, before any text filtering, so a live recording in a silent
|
|
403
|
+
* room keeps arriving every ~10s and never goes idle — its silent chunks land in
|
|
404
|
+
* `emptyCompletions`, not `chunks`. Gating on emptiness ALONE would kill exactly that
|
|
405
|
+
* session; gating on emptiness AND idleness cannot. Two minutes is comfortably more
|
|
406
|
+
* than one chunk interval, so a recording that has just started is safe.
|
|
407
|
+
*/
|
|
408
|
+
export const EMPTY_SESSION_STALE_MS = 2 * 60_000
|
|
409
|
+
|
|
390
410
|
export interface TranscriptionSessionLiveness {
|
|
391
411
|
/** Sessions still plausibly recording. These block a restart. */
|
|
392
412
|
live: number
|
|
@@ -479,8 +499,12 @@ export function getTranscriptionSessionLiveness(now = Date.now()): Transcription
|
|
|
479
499
|
const staleSessions: TranscriptionSessionLiveness['staleSessions'] = []
|
|
480
500
|
for (const [sessionId, session] of sessions) {
|
|
481
501
|
const silentForMs = now - session.lastActivityAt
|
|
482
|
-
|
|
483
|
-
|
|
502
|
+
// Canonical text, not array length: the array is sparse and silent chunks carry no
|
|
503
|
+
// text, which is exactly the shape an aborted recording leaves behind.
|
|
504
|
+
const canonicalChunks = session.chunks.filter(chunk => chunk && chunk.text).length
|
|
505
|
+
const emptyAndIdle = canonicalChunks === 0 && silentForMs >= EMPTY_SESSION_STALE_MS
|
|
506
|
+
if (silentForMs >= RECORDING_SESSION_STALE_MS || emptyAndIdle) {
|
|
507
|
+
staleSessions.push({ sessionId, silentForMs, chunks: canonicalChunks })
|
|
484
508
|
} else {
|
|
485
509
|
live++
|
|
486
510
|
}
|