@gotcos/glasses-server 6.21.4 → 6.21.5

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 CHANGED
@@ -1,3 +1,12 @@
1
+ ## 6.21.5
2
+
3
+ - Drop the narrow Large-v3 stock-caption artifact family beginning with
4
+ “closed captioning provided by” from prompt dictation.
5
+ - When that exact HQ artifact occurs, retain the already-validated Fast
6
+ transcript for the same audio and report the result as degraded instead of
7
+ saving either the caption credit or an empty gap. All other HQ and no-speech
8
+ paths are unchanged.
9
+
1
10
  ## 6.21.4
2
11
 
3
12
  - Preserve validated phone-photo references on Claude and Codex conversation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gotcos/glasses-server",
3
- "version": "6.21.4",
3
+ "version": "6.21.5",
4
4
  "description": "COS Glasses — 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": {
@@ -14,8 +14,11 @@
14
14
  import { getNegativeRules, getVocabulary, getOwnerName, getWhisperCorrections } from './profile.js'
15
15
 
16
16
  // ── Whole-chunk silence hallucinations ─────────────────────────────────────
17
+ const CAPTION_CREDIT_HALLUCINATION = /^\s*(?:closed\s+)?caption(?:ing|s)?\s+(?:is\s+)?provided\s+by\b/i
18
+
17
19
  const KNOWN_HALLUCINATIONS = [
18
20
  /^subtitles?\s+by\b/i,
21
+ CAPTION_CREDIT_HALLUCINATION,
19
22
  /\blike\s+and\s+subscribe\b/i,
20
23
  /\bthanks?\s+for\s+watching\b/i,
21
24
  /\bplease\s+subscribe\b/i,
@@ -27,6 +30,13 @@ const KNOWN_HALLUCINATIONS = [
27
30
  /^\s*♪+\s*[^♪\n]{0,40}\s*♪+\s*$/,
28
31
  ]
29
32
 
33
+ /** Narrow stock-caption detector used to retain a valid Fast draft when an HQ
34
+ * decode leaks a caption credit. It intentionally requires the phrase to begin
35
+ * the chunk so normal questions about closed captioning remain untouched. */
36
+ export function isCaptionCreditHallucination(text: string): boolean {
37
+ return CAPTION_CREDIT_HALLUCINATION.test(text)
38
+ }
39
+
30
40
  // ── Inline "Name:" detector (session-aware in streaming, static in one-shot) ──
31
41
  const INLINE_HALLUCINATION_THRESHOLD = 3
32
42
  // Seed list of known Whisper "Name:" training artifacts. Empty by default — the
@@ -29,6 +29,7 @@ import {
29
29
  stripInlineHallucinations,
30
30
  stripPromptDictationArtifacts,
31
31
  isFullHallucination,
32
+ isCaptionCreditHallucination,
32
33
  isBrandUrlOnly,
33
34
  clearSessionHallucinationState,
34
35
  applyNegativeRules,
@@ -250,6 +251,35 @@ async function transcribeChunk(draftId: string, chunkIndex: number, audio: Buffe
250
251
  return text
251
252
  } catch (err) {
252
253
  if (err instanceof NoSpeechDetectedError) {
254
+ // Large-v3 can rarely replace a clipped but valid phrase with a stock
255
+ // caption credit. Keep the already-decoded Fast text for this one
256
+ // recognized failure shape instead of persisting either the artifact
257
+ // or an empty gap. Other no-speech results retain existing behavior.
258
+ if (mode === 'hq' && isCaptionCreditHallucination(err.rawText)) {
259
+ const fastJob = modeQualityJobs.get(modeQualityKey(draftId, chunkIndex, 'fast', hash))
260
+ if (fastJob) {
261
+ try { await fastJob } catch { /* normal no-speech path below */ }
262
+ }
263
+ const fast = loadPromptDraftMeta(draftId)?.warmTranscripts?.[String(chunkIndex)]
264
+ if (
265
+ fast
266
+ && fast.hash === hash
267
+ && fast.requestedMode === 'fast'
268
+ && fast.actualQuality === 'fast'
269
+ && fast.text.trim()
270
+ ) {
271
+ if (purpose === 'final') {
272
+ await markPromptDraftChunkTranscript(draftId, chunkIndex, {
273
+ ...fast,
274
+ requestedMode: 'hq',
275
+ degraded: true,
276
+ degradationReason: 'hq_caption_credit_hallucination',
277
+ }, 'final')
278
+ }
279
+ console.warn(`[prompt-draft] dropped HQ caption-credit hallucination ${draftId}/${chunkIndex}; retained Fast text`)
280
+ return fast.text
281
+ }
282
+ }
253
283
  await markPromptDraftChunkTranscript(draftId, chunkIndex, {
254
284
  text: '', hash, requestedMode: mode, actualQuality: mode, backend: 'no-speech', degraded: false,
255
285
  }, purpose)