@glassly/engine 0.4.0-dev.1037 → 0.4.0-dev.1039
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/build/engine.d.ts +1 -1
- package/build/engine.d.ts.map +1 -1
- package/build/engine.js +1 -1
- package/build/engine.js.map +1 -1
- package/build/facades/glasses.js +1 -1
- package/build/facades/glasses.js.map +1 -1
- package/build/facades/providerKeys.d.ts +1 -1
- package/build/facades/providerKeys.js +1 -1
- package/build/facades/providerKeys.js.map +1 -1
- package/build/generated/releaseMetadata.js +3 -3
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/react/useMentraLiveOta.d.ts.map +1 -1
- package/build/react/useMentraLiveOta.js.map +1 -1
- package/build/runtime/config.d.ts.map +1 -1
- package/build/runtime/config.js.map +1 -1
- package/build/services/AiTierResolution.d.ts +1 -1
- package/build/services/AiTierResolution.d.ts.map +1 -1
- package/build/services/AiTierResolution.js.map +1 -1
- package/build/services/AutomaticReportResult.d.ts.map +1 -1
- package/build/services/AutomaticReportResult.js.map +1 -1
- package/build/services/GestureDotsService.js +1 -1
- package/build/services/GestureDotsService.js.map +1 -1
- package/build/services/HotspotOtaTransport.d.ts.map +1 -1
- package/build/services/HotspotOtaTransport.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts +5 -2
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +53 -22
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
- package/build/services/NativeNavigationService.d.ts.map +1 -1
- package/build/services/NativeNavigationService.js.map +1 -1
- package/build/services/NavigationHandlers.d.ts +1 -1
- package/build/services/NavigationHandlers.js +2 -2
- package/build/services/NavigationHandlers.js.map +1 -1
- package/build/services/NavigationService.d.ts +2 -2
- package/build/services/NavigationService.d.ts.map +1 -1
- package/build/services/NavigationService.js +11 -11
- package/build/services/NavigationService.js.map +1 -1
- package/build/services/PairingIdentity.d.ts.map +1 -1
- package/build/services/PairingIdentity.js.map +1 -1
- package/build/services/PhoneCalendarService.d.ts.map +1 -1
- package/build/services/PhoneCalendarService.js.map +1 -1
- package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
- package/build/services/PhoneNotificationsSync.js +2 -1
- package/build/services/PhoneNotificationsSync.js.map +1 -1
- package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
- package/build/services/PhoneStreamCoordinator.js.map +1 -1
- package/build/services/ProviderKeyValidation.d.ts +1 -1
- package/build/services/ProviderKeyValidation.js +1 -1
- package/build/services/ProviderKeyValidation.js.map +1 -1
- package/build/services/STTModelManager.d.ts.map +1 -1
- package/build/services/STTModelManager.js +1 -6
- package/build/services/STTModelManager.js.map +1 -1
- package/build/services/TranscriptionRouting.d.ts +3 -0
- package/build/services/TranscriptionRouting.d.ts.map +1 -1
- package/build/services/TranscriptionRouting.js +14 -0
- package/build/services/TranscriptionRouting.js.map +1 -1
- package/build/services/UIRouter.d.ts.map +1 -1
- package/build/services/UIRouter.js.map +1 -1
- package/build/services/gestureDotGlyphs.d.ts.map +1 -1
- package/build/services/gestureDotGlyphs.js.map +1 -1
- package/build/services/manifestActions.d.ts.map +1 -1
- package/build/services/manifestActions.js.map +1 -1
- package/build/services/notificationAppPayload.d.ts +14 -0
- package/build/services/notificationAppPayload.d.ts.map +1 -0
- package/build/services/notificationAppPayload.js +15 -0
- package/build/services/notificationAppPayload.js.map +1 -0
- package/build/services/settingsBridge.d.ts.map +1 -1
- package/build/services/settingsBridge.js.map +1 -1
- package/build/stores/appVisibility.d.ts.map +1 -1
- package/build/stores/appVisibility.js.map +1 -1
- package/build/stores/gallerySync.d.ts.map +1 -1
- package/build/stores/gallerySync.js.map +1 -1
- package/build/stores/settings.js +1 -1
- package/build/stores/settings.js.map +1 -1
- package/build/utils/display/scene/svgPath.js.map +1 -1
- package/build/utils/memory/search.d.ts.map +1 -1
- package/build/utils/memory/search.js +17 -7
- package/build/utils/memory/search.js.map +1 -1
- package/package.json +7 -7
- package/src/engine.ts +1 -1
- package/src/facades/glasses.ts +1 -1
- package/src/facades/providerKeys.ts +1 -1
- package/src/generated/releaseMetadata.ts +3 -3
- package/src/react/useMentraLiveOta.ts +1 -4
- package/src/runtime/config.ts +1 -6
- package/src/services/AiTierResolution.ts +1 -1
- package/src/services/AutomaticReportResult.ts +1 -3
- package/src/services/GestureDotsService.ts +1 -1
- package/src/services/HotspotOtaTransport.ts +1 -4
- package/src/services/LocalMiniappRuntime.ts +65 -23
- package/src/services/LocalSttFallbackCoordinator.ts +1 -5
- package/src/services/NativeNavigationService.ts +1 -2
- package/src/services/NavigationHandlers.ts +2 -2
- package/src/services/NavigationService.ts +12 -11
- package/src/services/PairingIdentity.ts +1 -3
- package/src/services/PhoneCalendarService.ts +1 -3
- package/src/services/PhoneNotificationsSync.ts +2 -1
- package/src/services/PhoneStreamCoordinator.ts +1 -2
- package/src/services/ProviderKeyValidation.ts +1 -1
- package/src/services/STTModelManager.ts +1 -6
- package/src/services/TranscriptionRouting.ts +18 -0
- package/src/services/UIRouter.ts +3 -9
- package/src/services/gestureDotGlyphs.ts +10 -5
- package/src/services/manifestActions.ts +2 -1
- package/src/services/notificationAppPayload.ts +15 -0
- package/src/services/settingsBridge.ts +1 -2
- package/src/stores/appVisibility.ts +2 -5
- package/src/stores/gallerySync.ts +1 -7
- package/src/stores/settings.ts +1 -1
- package/src/utils/display/scene/svgPath.ts +1 -1
- package/src/utils/memory/search.ts +17 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"svgPath.js","sourceRoot":"","sources":["../../../../src/utils/display/scene/svgPath.ts"],"names":[],"mappings":"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","sourcesContent":["/** SVG path compiler shared by scene validation and native wire encoding.\n * Ported from g2flash revision 21; no DOM, Node or mobile-platform dependencies. */\nconst u16 = (v: number) => [v & 255, (v >>> 8) & 255]\nfunction integer(v: number, min: number, max: number, name: string): number {\n if (!Number.isInteger(v) || v < min || v > max) throw new Error(`${name} outside ${min}..${max}: ${v}`)\n return v\n}\n/** SVG d subset: absolute/relative M L H V Q C S T Z; implicit repetitions.\n * Unsupported syntax is rejected. Each filled contour must explicitly close. */\nexport function svgPath(d: string): number[] {\n const tokens = d.match(/[a-zA-Z]|[-+]?(?:\\d*\\.\\d+|\\d+\\.?\\d*)(?:[eE][-+]?\\d+)?/g) ?? []\n const residue = d.replace(/[a-zA-Z]|[-+]?(?:\\d*\\.\\d+|\\d+\\.?\\d*)(?:[eE][-+]?\\d+)?/g, \"\")\n if (/[^\\s,]/.test(residue)) throw new Error(\"Invalid SVG path syntax\")\n let i = 0,\n cmd = \"\",\n x = 0,\n y = 0,\n sx = 0,\n sy = 0,\n open = false,\n previous = \"\"\n let cx = 0,\n cy = 0\n const out: number[] = []\n const emit = (op: number, ...coords: number[]) => {\n out.push(op, ...coords.flatMap((v) => u16(integer(Math.round(v * 16), -32768, 32767, \"Q4 coordinate\"))))\n }\n const number = () => {\n if (i >= tokens.length || /^[a-z]$/i.test(tokens[i])) throw new Error(\"Missing SVG coordinate\")\n const v = Number(tokens[i++])\n if (!Number.isFinite(v)) throw new Error(\"Invalid number\")\n return v\n }\n while (i < tokens.length) {\n if (/^[a-z]$/i.test(tokens[i])) cmd = tokens[i++]\n if (!cmd || !/^[MLHVQCSTZ]$/i.test(cmd)) throw new Error(`Unsupported SVG command: ${cmd}`)\n const op = cmd.toUpperCase(),\n rel = cmd !== op\n const pair = (): [number, number] => [number() + (rel ? x : 0), number() + (rel ? y : 0)]\n if (op === \"Z\") {\n if (!open) throw new Error(\"Z without an open contour\")\n emit(4)\n x = sx\n y = sy\n open = false\n previous = \"Z\"\n cmd = \"\"\n continue\n }\n if (op !== \"M\" && !open) throw new Error(\"Path must start with M\")\n if (op === \"M\") {\n if (open) throw new Error(\"Filled contours must close with Z before another M\")\n ;[x, y] = pair()\n sx = x\n sy = y\n open = true\n emit(0, x, y)\n cmd = rel ? \"l\" : \"L\"\n } else if (op === \"L\" || op === \"H\" || op === \"V\") {\n if (op === \"L\") [x, y] = pair()\n else if (op === \"H\") x = number() + (rel ? x : 0)\n else y = number() + (rel ? y : 0)\n emit(1, x, y)\n } else if (op === \"Q\" || op === \"T\") {\n const c = op === \"Q\" ? pair() : previous === \"Q\" || previous === \"T\" ? [2 * x - cx, 2 * y - cy] : [x, y]\n const end = pair()\n emit(2, ...c, ...end)\n ;[cx, cy] = c\n ;[x, y] = end\n } else {\n const a = op === \"C\" ? pair() : previous === \"C\" || previous === \"S\" ? [2 * x - cx, 2 * y - cy] : [x, y]\n const b = pair(),\n end = pair()\n emit(3, ...a, ...b, ...end)\n ;[cx, cy] = b\n ;[x, y] = end\n }\n previous = op\n }\n if (open || !out.length) throw new Error(\"Expected explicitly closed filled path\")\n return out\n}\n\n/** Check the same fixed-point subdivision and budgets as revision 21 firmware. */\nexport function compileSvgPath(d: string): {commands: number[]; edges: number} {\n if (typeof d !== \"string\" || d.length > 65536) throw new Error(\"Invalid SVG path data\")\n const commands = svgPath(d)\n if (commands.length > 8192) throw new Error(\"SVG path exceeds 8192 command bytes\")\n let edges = 0,\n count = 0,\n x = 0,\n y = 0,\n sx = 0,\n sy = 0\n const edge = (ax: number, ay: number, bx: number, by: number) => {\n if ((ax !== bx || ay !== by) && ++edges > 512) throw new Error(\"SVG path exceeds 512 compiled edges\")\n }\n const curve = (p: number[], depth: number): void => {\n const u = [\n 3 * p[2] - 2 * p[0] - p[6],\n 3 * p[3] - 2 * p[1] - p[7],\n 3 * p[4] - 2 * p[6] - p[0],\n 3 * p[5] - 2 * p[7] - p[1],\n ]\n if (u.every((v) => Math.abs(v) <= 16)) {\n edge(p[0], p[1], p[6], p[7])\n return\n }\n if (depth === 8) throw new Error(\"SVG curve exceeds subdivision limit\")\n const a = new Array<number>(8),\n b = new Array<number>(8)\n for (let k = 0; k < 2; k++) {\n const ab = Math.trunc((p[k] + p[k + 2]) / 2),\n bc = Math.trunc((p[k + 2] + p[k + 4]) / 2),\n cd = Math.trunc((p[k + 4] + p[k + 6]) / 2)\n const abc = Math.trunc((ab + bc) / 2),\n bcd = Math.trunc((bc + cd) / 2),\n mid = Math.trunc((abc + bcd) / 2)\n a[k] = p[k]\n a[k + 2] = ab\n a[k + 4] = abc\n a[k + 6] = mid\n b[k] = mid\n b[k + 2] = bcd\n b[k + 4] = cd\n b[k + 6] = p[k + 6]\n }\n curve(a, depth + 1)\n curve(b, depth + 1)\n }\n for (let i = 0; i < commands.length; ) {\n const op = commands[i++],\n pairs = op === 4 ? 0 : op === 3 ? 3 : op === 2 ? 2 : 1\n if (++count > 1024) throw new Error(\"SVG path exceeds 1024 commands\")\n const p = [x, y]\n for (let k = 0; k < pairs * 2; k++, i += 2) p.push(((commands[i] | (commands[i + 1] << 8)) << 16) >> 16)\n if (op === 0) {\n x = sx = p[2]\n y = sy = p[3]\n } else if (op === 4) {\n edge(x, y, sx, sy)\n x = sx\n y = sy\n } else if (op === 1) {\n edge(x, y, p[2], p[3])\n x = p[2]\n y = p[3]\n } else {\n if (op === 2) {\n p[6] = p[4]\n p[7] = p[5]\n for (let k = 0; k < 2; k++) {\n p[k + 4] = Math.trunc((p[k + 6] + 2 * p[k + 2]) / 3)\n p[k + 2] = Math.trunc((p[k] + 2 * p[k + 2]) / 3)\n }\n }\n curve(p, 0)\n x = p[6]\n y = p[7]\n }\n }\n return {commands, edges}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"svgPath.js","sourceRoot":"","sources":["../../../../src/utils/display/scene/svgPath.ts"],"names":[],"mappings":"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","sourcesContent":["/** SVG path compiler shared by scene validation and native wire encoding.\n * Ported from g2flash revision 21; no DOM, Node or mobile-platform dependencies. */\nconst u16 = (v: number) => [v & 255, (v >>> 8) & 255]\nfunction integer(v: number, min: number, max: number, name: string): number {\n if (!Number.isInteger(v) || v < min || v > max) throw new Error(`${name} outside ${min}..${max}: ${v}`)\n return v\n}\n/** SVG d subset: absolute/relative M L H V Q C S T Z; implicit repetitions.\n * Unsupported syntax is rejected. Each filled contour must explicitly close. */\nexport function svgPath(d: string): number[] {\n const tokens = d.match(/[a-zA-Z]|[-+]?(?:\\d*\\.\\d+|\\d+\\.?\\d*)(?:[eE][-+]?\\d+)?/g) ?? []\n const residue = d.replace(/[a-zA-Z]|[-+]?(?:\\d*\\.\\d+|\\d+\\.?\\d*)(?:[eE][-+]?\\d+)?/g, \"\")\n if (/[^\\s,]/.test(residue)) throw new Error(\"Invalid SVG path syntax\")\n let i = 0,\n cmd = \"\",\n x = 0,\n y = 0,\n sx = 0,\n sy = 0,\n open = false,\n previous = \"\"\n let cx = 0,\n cy = 0\n const out: number[] = []\n const emit = (op: number, ...coords: number[]) => {\n out.push(op, ...coords.flatMap((v) => u16(integer(Math.round(v * 16), -32768, 32767, \"Q4 coordinate\"))))\n }\n const number = () => {\n if (i >= tokens.length || /^[a-z]$/i.test(tokens[i])) throw new Error(\"Missing SVG coordinate\")\n const v = Number(tokens[i++])\n if (!Number.isFinite(v)) throw new Error(\"Invalid number\")\n return v\n }\n while (i < tokens.length) {\n if (/^[a-z]$/i.test(tokens[i])) cmd = tokens[i++]\n if (!cmd || !/^[MLHVQCSTZ]$/i.test(cmd)) throw new Error(`Unsupported SVG command: ${cmd}`)\n const op = cmd.toUpperCase(),\n rel = cmd !== op\n const pair = (): [number, number] => [number() + (rel ? x : 0), number() + (rel ? y : 0)]\n if (op === \"Z\") {\n if (!open) throw new Error(\"Z without an open contour\")\n emit(4)\n x = sx\n y = sy\n open = false\n previous = \"Z\"\n cmd = \"\"\n continue\n }\n if (op !== \"M\" && !open) throw new Error(\"Path must start with M\")\n if (op === \"M\") {\n if (open) throw new Error(\"Filled contours must close with Z before another M\")\n ;[x, y] = pair()\n sx = x\n sy = y\n open = true\n emit(0, x, y)\n cmd = rel ? \"l\" : \"L\"\n } else if (op === \"L\" || op === \"H\" || op === \"V\") {\n if (op === \"L\") [x, y] = pair()\n else if (op === \"H\") x = number() + (rel ? x : 0)\n else y = number() + (rel ? y : 0)\n emit(1, x, y)\n } else if (op === \"Q\" || op === \"T\") {\n const c = op === \"Q\" ? pair() : previous === \"Q\" || previous === \"T\" ? [2 * x - cx, 2 * y - cy] : [x, y]\n const end = pair()\n emit(2, ...c, ...end)\n ;[cx, cy] = c\n ;[x, y] = end\n } else {\n const a = op === \"C\" ? pair() : previous === \"C\" || previous === \"S\" ? [2 * x - cx, 2 * y - cy] : [x, y]\n const b = pair(),\n end = pair()\n emit(3, ...a, ...b, ...end)\n ;[cx, cy] = b\n ;[x, y] = end\n }\n previous = op\n }\n if (open || !out.length) throw new Error(\"Expected explicitly closed filled path\")\n return out\n}\n\n/** Check the same fixed-point subdivision and budgets as revision 21 firmware. */\nexport function compileSvgPath(d: string): {commands: number[]; edges: number} {\n if (typeof d !== \"string\" || d.length > 65536) throw new Error(\"Invalid SVG path data\")\n const commands = svgPath(d)\n if (commands.length > 8192) throw new Error(\"SVG path exceeds 8192 command bytes\")\n let edges = 0,\n count = 0,\n x = 0,\n y = 0,\n sx = 0,\n sy = 0\n const edge = (ax: number, ay: number, bx: number, by: number) => {\n if ((ax !== bx || ay !== by) && ++edges > 512) throw new Error(\"SVG path exceeds 512 compiled edges\")\n }\n const curve = (p: number[], depth: number): void => {\n const u = [\n 3 * p[2] - 2 * p[0] - p[6],\n 3 * p[3] - 2 * p[1] - p[7],\n 3 * p[4] - 2 * p[6] - p[0],\n 3 * p[5] - 2 * p[7] - p[1],\n ]\n if (u.every((v) => Math.abs(v) <= 16)) {\n edge(p[0], p[1], p[6], p[7])\n return\n }\n if (depth === 8) throw new Error(\"SVG curve exceeds subdivision limit\")\n const a = new Array<number>(8),\n b = new Array<number>(8)\n for (let k = 0; k < 2; k++) {\n const ab = Math.trunc((p[k] + p[k + 2]) / 2),\n bc = Math.trunc((p[k + 2] + p[k + 4]) / 2),\n cd = Math.trunc((p[k + 4] + p[k + 6]) / 2)\n const abc = Math.trunc((ab + bc) / 2),\n bcd = Math.trunc((bc + cd) / 2),\n mid = Math.trunc((abc + bcd) / 2)\n a[k] = p[k]\n a[k + 2] = ab\n a[k + 4] = abc\n a[k + 6] = mid\n b[k] = mid\n b[k + 2] = bcd\n b[k + 4] = cd\n b[k + 6] = p[k + 6]\n }\n curve(a, depth + 1)\n curve(b, depth + 1)\n }\n for (let i = 0; i < commands.length;) {\n const op = commands[i++],\n pairs = op === 4 ? 0 : op === 3 ? 3 : op === 2 ? 2 : 1\n if (++count > 1024) throw new Error(\"SVG path exceeds 1024 commands\")\n const p = [x, y]\n for (let k = 0; k < pairs * 2; k++, i += 2) p.push(((commands[i] | (commands[i + 1] << 8)) << 16) >> 16)\n if (op === 0) {\n x = sx = p[2]\n y = sy = p[3]\n } else if (op === 4) {\n edge(x, y, sx, sy)\n x = sx\n y = sy\n } else if (op === 1) {\n edge(x, y, p[2], p[3])\n x = p[2]\n y = p[3]\n } else {\n if (op === 2) {\n p[6] = p[4]\n p[7] = p[5]\n for (let k = 0; k < 2; k++) {\n p[k + 4] = Math.trunc((p[k + 6] + 2 * p[k + 2]) / 3)\n p[k + 2] = Math.trunc((p[k] + 2 * p[k + 2]) / 3)\n }\n }\n curve(p, 0)\n x = p[6]\n y = p[7]\n }\n }\n return {commands, edges}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/utils/memory/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,qEAAqE;IACrE,OAAO,EAAE,CAAC,EAAE,CAAA;IACZ;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAA;CACpB;AAKD,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,qBAAqB,EACjE,OAAO,EAAE,SAAS,CAAC,EAAE,EACrB,CAAC,EAAE,iBAAiB,GACnB,kBAAkB,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/utils/memory/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,qEAAqE;IACrE,OAAO,EAAE,CAAC,EAAE,CAAA;IACZ;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAA;CACpB;AAKD,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,qBAAqB,EACjE,OAAO,EAAE,SAAS,CAAC,EAAE,EACrB,CAAC,EAAE,iBAAiB,GACnB,kBAAkB,CAAC,CAAC,CAAC,CAmBvB;AAkBD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAO5D;AAED,+DAA+D;AAC/D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAO/C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAqB7E;AAuBD,+CAA+C;AAC/C,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAc5C"}
|
|
@@ -31,9 +31,7 @@ export function searchMemoryEntries(entries, q) {
|
|
|
31
31
|
const hi = upperBound(entries, until); // exclusive
|
|
32
32
|
const windowCount = Math.max(0, hi - lo);
|
|
33
33
|
const needle = q.contains?.trim().toLowerCase() || null;
|
|
34
|
-
const termWords = (q.terms ?? [])
|
|
35
|
-
.map((t) => tokenize(t))
|
|
36
|
-
.filter((words) => words.length > 0);
|
|
34
|
+
const termWords = (q.terms ?? []).map((t) => tokenize(t)).filter((words) => words.length > 0);
|
|
37
35
|
const picked = [];
|
|
38
36
|
for (let i = hi - 1; i >= lo && picked.length < q.limit; i--) {
|
|
39
37
|
const e = entries[i];
|
|
@@ -123,11 +121,23 @@ export function editDistanceAtMost(a, b, max) {
|
|
|
123
121
|
return prev[b.length] <= max;
|
|
124
122
|
}
|
|
125
123
|
const SOUNDEX_CODES = {
|
|
126
|
-
b: "1",
|
|
127
|
-
|
|
128
|
-
|
|
124
|
+
b: "1",
|
|
125
|
+
f: "1",
|
|
126
|
+
p: "1",
|
|
127
|
+
v: "1",
|
|
128
|
+
c: "2",
|
|
129
|
+
g: "2",
|
|
130
|
+
j: "2",
|
|
131
|
+
k: "2",
|
|
132
|
+
q: "2",
|
|
133
|
+
s: "2",
|
|
134
|
+
x: "2",
|
|
135
|
+
z: "2",
|
|
136
|
+
d: "3",
|
|
137
|
+
t: "3",
|
|
129
138
|
l: "4",
|
|
130
|
-
m: "5",
|
|
139
|
+
m: "5",
|
|
140
|
+
n: "5",
|
|
131
141
|
r: "6",
|
|
132
142
|
};
|
|
133
143
|
/** Classic Soundex. Empty input returns "". */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/utils/memory/search.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure memory-timeline search — the matching engine behind MemoryStore.query\n * and the assistant's get_transcripts tool.\n *\n * Lives outside MemoryStore so it is unit-testable and importable by the\n * assistant's eval harness (which replays the exact host semantics against a\n * mock corpus). Keep it dependency-free and runtime-neutral: it also runs\n * under bun for tests.\n *\n * TWO MATCH MODES, deliberately different:\n * - `contains`: exact case-insensitive substring — the pre-existing contract,\n * kept verbatim for callers that need precision (codes, URLs, exact phrases).\n * - `terms`: ANY-of term matching with per-word fuzziness. Speech-to-text\n * mangles proper nouns (\"Sompo\" for \"Sampo\", \"Korwin\" for \"Corwin\"), so a\n * term word matches a transcript token on exact/substring, small edit\n * distance, OR same Soundex key. A multi-word term (\"ring size\") requires\n * all of its words to match somewhere in the entry.\n *\n * The scan walks BACKWARDS from the newest in-window entry and stops at\n * `limit` matches: the caller keeps the most recent matches anyway, and the\n * common \"last 90 minutes\" query then touches dozens of entries instead of\n * the full 4000-entry timeline. Window bounds are found by binary search on\n * `at` (the timeline is maintained time-sorted).\n */\n\nexport interface MemorySearchableEntry {\n text: string\n at: number\n}\n\nexport interface MemorySearchQuery {\n /** Epoch ms lower bound (inclusive). */\n sinceMs?: number\n /** Epoch ms upper bound (inclusive). */\n untilMs?: number\n /** Exact case-insensitive substring filter. */\n contains?: string\n /** Fuzzy any-of terms (see file header). Combined with `contains` as AND. */\n terms?: string[]\n /** Max matches kept (newest win). Caller enforces its own cap. */\n limit: number\n}\n\nexport interface MemorySearchResult<T> {\n /** Matches in chronological order (newest last), at most `limit`. */\n entries: T[]\n /**\n * Entries inside the TIME window before keyword filtering. Lets the caller\n * tell \"keyword matched nothing\" apart from \"window itself is empty\" — the\n * distinction that saves an LLM a blind retry round.\n */\n windowCount: number\n}\n\n/** Tokenized lowercase text per entry, cached for the entry object's lifetime. */\nconst tokenCache = new WeakMap<object, string[]>()\n\nexport function searchMemoryEntries<T extends MemorySearchableEntry>(\n entries: readonly T[],\n q: MemorySearchQuery,\n): MemorySearchResult<T> {\n const since = q.sinceMs ?? 0\n const until = q.untilMs ?? Number.MAX_SAFE_INTEGER\n const lo = lowerBound(entries, since)\n const hi = upperBound(entries, until) // exclusive\n const windowCount = Math.max(0, hi - lo)\n\n const needle = q.contains?.trim().toLowerCase() || null\n const termWords = (q.terms ?? [])\n .map((t) => tokenize(t))\n .filter((words) => words.length > 0)\n\n const picked: T[] = []\n for (let i = hi - 1; i >= lo && picked.length < q.limit; i--) {\n const e = entries[i]\n if (needle && !e.text.toLowerCase().includes(needle)) continue\n if (termWords.length > 0 && !matchesAnyTerm(e, termWords)) continue\n picked.push(e)\n }\n picked.reverse()\n return {entries: picked, windowCount}\n}\n\n/** True when any term matches — a term matches iff ALL its words match a token. */\nfunction matchesAnyTerm(entry: MemorySearchableEntry, termWords: string[][]): boolean {\n let tokens = tokenCache.get(entry)\n if (!tokens) {\n tokens = tokenize(entry.text)\n tokenCache.set(entry, tokens)\n }\n outer: for (const words of termWords) {\n for (const word of words) {\n if (!tokens.some((tok) => fuzzyWordMatch(word, tok))) continue outer\n }\n return true\n }\n return false\n}\n\n/**\n * Does query word `w` match transcript token `t`?\n * - exact, or substring for w of 3+ chars (\"kestrel\" in \"kestrels\")\n * - for words of 5+ chars: bounded edit distance (1, or 2 for 7+ chars)\n * — catches one-vowel STT swaps (\"sompo\"/\"sampo\", \"korwin\"/\"corwin\").\n * 5 is the floor because at 4 chars a one-edit radius swallows unrelated\n * common words (\"code\"→\"mode\"); mistranscribed NAMES are almost always 5+.\n * - same Soundex key with similar length — catches phonetic respellings that\n * edit distance misses (\"warryn\"/\"warren\" style doublings)\n */\nexport function fuzzyWordMatch(w: string, t: string): boolean {\n if (w === t) return true\n if (w.length >= 3 && t.includes(w)) return true\n if (w.length < 5 || t.length < 4) return false\n const maxDist = w.length >= 7 ? 2 : 1\n if (Math.abs(w.length - t.length) <= maxDist && editDistanceAtMost(w, t, maxDist)) return true\n return Math.abs(w.length - t.length) <= 2 && soundex(w) === soundex(t)\n}\n\n/** Lowercase, strip diacritics, split on non-alphanumerics. */\nexport function tokenize(text: string): string[] {\n return text\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 0)\n}\n\n/**\n * Optimal-string-alignment edit distance, early-exited: returns whether\n * dist(a, b) <= max. Transpositions count as one edit (common in STT output).\n */\nexport function editDistanceAtMost(a: string, b: string, max: number): boolean {\n if (Math.abs(a.length - b.length) > max) return false\n let prev2: number[] | null = null\n let prev = Array.from({length: b.length + 1}, (_, j) => j)\n for (let i = 1; i <= a.length; i++) {\n const cur = [i]\n let rowMin = i\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1\n let v = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + cost)\n if (prev2 && i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {\n v = Math.min(v, prev2[j - 2] + 1)\n }\n cur.push(v)\n if (v < rowMin) rowMin = v\n }\n if (rowMin > max) return false\n prev2 = prev\n prev = cur\n }\n return prev[b.length] <= max\n}\n\nconst SOUNDEX_CODES: Record<string, string> = {\n b: \"1\", f: \"1\", p: \"1\", v: \"1\",\n c: \"2\", g: \"2\", j: \"2\", k: \"2\", q: \"2\", s: \"2\", x: \"2\", z: \"2\",\n d: \"3\", t: \"3\",\n l: \"4\",\n m: \"5\", n: \"5\",\n r: \"6\",\n}\n\n/** Classic Soundex. Empty input returns \"\". */\nexport function soundex(word: string): string {\n const w = word.toLowerCase().replace(/[^a-z]/g, \"\")\n if (!w) return \"\"\n let out = w[0].toUpperCase()\n let lastCode = SOUNDEX_CODES[w[0]] ?? \"\"\n for (let i = 1; i < w.length && out.length < 4; i++) {\n const ch = w[i]\n const code = SOUNDEX_CODES[ch] ?? \"\"\n // h/w are transparent: they don't reset the adjacent-duplicate rule.\n if (ch === \"h\" || ch === \"w\") continue\n if (code && code !== lastCode) out += code\n lastCode = code\n }\n return out.padEnd(4, \"0\")\n}\n\n/** First index with at >= value (entries time-sorted ascending). */\nfunction lowerBound(entries: readonly MemorySearchableEntry[], value: number): number {\n let lo = 0\n let hi = entries.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (entries[mid].at < value) lo = mid + 1\n else hi = mid\n }\n return lo\n}\n\n/** First index with at > value (i.e. exclusive end for an inclusive bound). */\nfunction upperBound(entries: readonly MemorySearchableEntry[], value: number): number {\n let lo = 0\n let hi = entries.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (entries[mid].at <= value) lo = mid + 1\n else hi = mid\n }\n return lo\n}\n"]}
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/utils/memory/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA+BH,kFAAkF;AAClF,MAAM,UAAU,GAAG,IAAI,OAAO,EAAoB,CAAA;AAElD,MAAM,UAAU,mBAAmB,CACjC,OAAqB,EACrB,CAAoB;IAEpB,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAA;IAC5B,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,gBAAgB,CAAA;IAClD,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IACrC,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA,CAAC,YAAY;IAClD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;IAExC,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,IAAI,CAAA;IACvD,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAE7F,MAAM,MAAM,GAAQ,EAAE,CAAA;IACtB,KAAK,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7D,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;QACpB,IAAI,MAAM,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,SAAQ;QAC9D,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,SAAS,CAAC;YAAE,SAAQ;QACnE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAChB,CAAC;IACD,MAAM,CAAC,OAAO,EAAE,CAAA;IAChB,OAAO,EAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAC,CAAA;AACvC,CAAC;AAED,mFAAmF;AACnF,SAAS,cAAc,CAAC,KAA4B,EAAE,SAAqB;IACzE,IAAI,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC7B,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAC/B,CAAC;IACD,KAAK,EAAE,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBAAE,SAAS,KAAK,CAAA;QACtE,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,CAAS,EAAE,CAAS;IACjD,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACxB,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAA;IAC/C,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAA;IAC9C,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACrC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,OAAO,IAAI,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IAC9F,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AACxE,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,IAAI;SACR,WAAW,EAAE;SACb,SAAS,CAAC,KAAK,CAAC;SAChB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,KAAK,CAAC,YAAY,CAAC;SACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAS,EAAE,CAAS,EAAE,GAAW;IAClE,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG;QAAE,OAAO,KAAK,CAAA;IACrD,IAAI,KAAK,GAAoB,IAAI,CAAA;IACjC,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAC,MAAM,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,EAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;IAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAA;QACf,IAAI,MAAM,GAAG,CAAC,CAAA;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;YAC1C,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;YACjE,IAAI,KAAK,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBAC9E,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YACnC,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACX,IAAI,CAAC,GAAG,MAAM;gBAAE,MAAM,GAAG,CAAC,CAAA;QAC5B,CAAC;QACD,IAAI,MAAM,GAAG,GAAG;YAAE,OAAO,KAAK,CAAA;QAC9B,KAAK,GAAG,IAAI,CAAA;QACZ,IAAI,GAAG,GAAG,CAAA;IACZ,CAAC;IACD,OAAO,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAA;AAC9B,CAAC;AAED,MAAM,aAAa,GAA2B;IAC5C,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;CACP,CAAA;AAED,+CAA+C;AAC/C,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;IACnD,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAA;IACjB,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;IAC5B,IAAI,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACpD,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QACf,MAAM,IAAI,GAAG,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,CAAA;QACpC,qEAAqE;QACrE,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG;YAAE,SAAQ;QACtC,IAAI,IAAI,IAAI,IAAI,KAAK,QAAQ;YAAE,GAAG,IAAI,IAAI,CAAA;QAC1C,QAAQ,GAAG,IAAI,CAAA;IACjB,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AAC3B,CAAC;AAED,oEAAoE;AACpE,SAAS,UAAU,CAAC,OAAyC,EAAE,KAAa;IAC1E,IAAI,EAAE,GAAG,CAAC,CAAA;IACV,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAA;IACvB,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;QAC1B,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,KAAK;YAAE,EAAE,GAAG,GAAG,GAAG,CAAC,CAAA;;YACpC,EAAE,GAAG,GAAG,CAAA;IACf,CAAC;IACD,OAAO,EAAE,CAAA;AACX,CAAC;AAED,+EAA+E;AAC/E,SAAS,UAAU,CAAC,OAAyC,EAAE,KAAa;IAC1E,IAAI,EAAE,GAAG,CAAC,CAAA;IACV,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAA;IACvB,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;QAC1B,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,KAAK;YAAE,EAAE,GAAG,GAAG,GAAG,CAAC,CAAA;;YACrC,EAAE,GAAG,GAAG,CAAA;IACf,CAAC;IACD,OAAO,EAAE,CAAA;AACX,CAAC","sourcesContent":["/**\n * Pure memory-timeline search — the matching engine behind MemoryStore.query\n * and the assistant's get_transcripts tool.\n *\n * Lives outside MemoryStore so it is unit-testable and importable by the\n * assistant's eval harness (which replays the exact host semantics against a\n * mock corpus). Keep it dependency-free and runtime-neutral: it also runs\n * under bun for tests.\n *\n * TWO MATCH MODES, deliberately different:\n * - `contains`: exact case-insensitive substring — the pre-existing contract,\n * kept verbatim for callers that need precision (codes, URLs, exact phrases).\n * - `terms`: ANY-of term matching with per-word fuzziness. Speech-to-text\n * mangles proper nouns (\"Sompo\" for \"Sampo\", \"Korwin\" for \"Corwin\"), so a\n * term word matches a transcript token on exact/substring, small edit\n * distance, OR same Soundex key. A multi-word term (\"ring size\") requires\n * all of its words to match somewhere in the entry.\n *\n * The scan walks BACKWARDS from the newest in-window entry and stops at\n * `limit` matches: the caller keeps the most recent matches anyway, and the\n * common \"last 90 minutes\" query then touches dozens of entries instead of\n * the full 4000-entry timeline. Window bounds are found by binary search on\n * `at` (the timeline is maintained time-sorted).\n */\n\nexport interface MemorySearchableEntry {\n text: string\n at: number\n}\n\nexport interface MemorySearchQuery {\n /** Epoch ms lower bound (inclusive). */\n sinceMs?: number\n /** Epoch ms upper bound (inclusive). */\n untilMs?: number\n /** Exact case-insensitive substring filter. */\n contains?: string\n /** Fuzzy any-of terms (see file header). Combined with `contains` as AND. */\n terms?: string[]\n /** Max matches kept (newest win). Caller enforces its own cap. */\n limit: number\n}\n\nexport interface MemorySearchResult<T> {\n /** Matches in chronological order (newest last), at most `limit`. */\n entries: T[]\n /**\n * Entries inside the TIME window before keyword filtering. Lets the caller\n * tell \"keyword matched nothing\" apart from \"window itself is empty\" — the\n * distinction that saves an LLM a blind retry round.\n */\n windowCount: number\n}\n\n/** Tokenized lowercase text per entry, cached for the entry object's lifetime. */\nconst tokenCache = new WeakMap<object, string[]>()\n\nexport function searchMemoryEntries<T extends MemorySearchableEntry>(\n entries: readonly T[],\n q: MemorySearchQuery,\n): MemorySearchResult<T> {\n const since = q.sinceMs ?? 0\n const until = q.untilMs ?? Number.MAX_SAFE_INTEGER\n const lo = lowerBound(entries, since)\n const hi = upperBound(entries, until) // exclusive\n const windowCount = Math.max(0, hi - lo)\n\n const needle = q.contains?.trim().toLowerCase() || null\n const termWords = (q.terms ?? []).map((t) => tokenize(t)).filter((words) => words.length > 0)\n\n const picked: T[] = []\n for (let i = hi - 1; i >= lo && picked.length < q.limit; i--) {\n const e = entries[i]\n if (needle && !e.text.toLowerCase().includes(needle)) continue\n if (termWords.length > 0 && !matchesAnyTerm(e, termWords)) continue\n picked.push(e)\n }\n picked.reverse()\n return {entries: picked, windowCount}\n}\n\n/** True when any term matches — a term matches iff ALL its words match a token. */\nfunction matchesAnyTerm(entry: MemorySearchableEntry, termWords: string[][]): boolean {\n let tokens = tokenCache.get(entry)\n if (!tokens) {\n tokens = tokenize(entry.text)\n tokenCache.set(entry, tokens)\n }\n outer: for (const words of termWords) {\n for (const word of words) {\n if (!tokens.some((tok) => fuzzyWordMatch(word, tok))) continue outer\n }\n return true\n }\n return false\n}\n\n/**\n * Does query word `w` match transcript token `t`?\n * - exact, or substring for w of 3+ chars (\"kestrel\" in \"kestrels\")\n * - for words of 5+ chars: bounded edit distance (1, or 2 for 7+ chars)\n * — catches one-vowel STT swaps (\"sompo\"/\"sampo\", \"korwin\"/\"corwin\").\n * 5 is the floor because at 4 chars a one-edit radius swallows unrelated\n * common words (\"code\"→\"mode\"); mistranscribed NAMES are almost always 5+.\n * - same Soundex key with similar length — catches phonetic respellings that\n * edit distance misses (\"warryn\"/\"warren\" style doublings)\n */\nexport function fuzzyWordMatch(w: string, t: string): boolean {\n if (w === t) return true\n if (w.length >= 3 && t.includes(w)) return true\n if (w.length < 5 || t.length < 4) return false\n const maxDist = w.length >= 7 ? 2 : 1\n if (Math.abs(w.length - t.length) <= maxDist && editDistanceAtMost(w, t, maxDist)) return true\n return Math.abs(w.length - t.length) <= 2 && soundex(w) === soundex(t)\n}\n\n/** Lowercase, strip diacritics, split on non-alphanumerics. */\nexport function tokenize(text: string): string[] {\n return text\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 0)\n}\n\n/**\n * Optimal-string-alignment edit distance, early-exited: returns whether\n * dist(a, b) <= max. Transpositions count as one edit (common in STT output).\n */\nexport function editDistanceAtMost(a: string, b: string, max: number): boolean {\n if (Math.abs(a.length - b.length) > max) return false\n let prev2: number[] | null = null\n let prev = Array.from({length: b.length + 1}, (_, j) => j)\n for (let i = 1; i <= a.length; i++) {\n const cur = [i]\n let rowMin = i\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1\n let v = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + cost)\n if (prev2 && i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {\n v = Math.min(v, prev2[j - 2] + 1)\n }\n cur.push(v)\n if (v < rowMin) rowMin = v\n }\n if (rowMin > max) return false\n prev2 = prev\n prev = cur\n }\n return prev[b.length] <= max\n}\n\nconst SOUNDEX_CODES: Record<string, string> = {\n b: \"1\",\n f: \"1\",\n p: \"1\",\n v: \"1\",\n c: \"2\",\n g: \"2\",\n j: \"2\",\n k: \"2\",\n q: \"2\",\n s: \"2\",\n x: \"2\",\n z: \"2\",\n d: \"3\",\n t: \"3\",\n l: \"4\",\n m: \"5\",\n n: \"5\",\n r: \"6\",\n}\n\n/** Classic Soundex. Empty input returns \"\". */\nexport function soundex(word: string): string {\n const w = word.toLowerCase().replace(/[^a-z]/g, \"\")\n if (!w) return \"\"\n let out = w[0].toUpperCase()\n let lastCode = SOUNDEX_CODES[w[0]] ?? \"\"\n for (let i = 1; i < w.length && out.length < 4; i++) {\n const ch = w[i]\n const code = SOUNDEX_CODES[ch] ?? \"\"\n // h/w are transparent: they don't reset the adjacent-duplicate rule.\n if (ch === \"h\" || ch === \"w\") continue\n if (code && code !== lastCode) out += code\n lastCode = code\n }\n return out.padEnd(4, \"0\")\n}\n\n/** First index with at >= value (entries time-sorted ascending). */\nfunction lowerBound(entries: readonly MemorySearchableEntry[], value: number): number {\n let lo = 0\n let hi = entries.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (entries[mid].at < value) lo = mid + 1\n else hi = mid\n }\n return lo\n}\n\n/** First index with at > value (i.e. exclusive end for an inclusive bound). */\nfunction upperBound(entries: readonly MemorySearchableEntry[], value: number): number {\n let lo = 0\n let hi = entries.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (entries[mid].at <= value) lo = mid + 1\n else hi = mid\n }\n return lo\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glassly/engine",
|
|
3
|
-
"version": "0.4.0-dev.
|
|
3
|
+
"version": "0.4.0-dev.1039",
|
|
4
4
|
"description": "Glassly Engine — miniapp registry, WebView bridge, and miniapp store",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -97,17 +97,17 @@
|
|
|
97
97
|
"registry": "https://registry.npmjs.org/"
|
|
98
98
|
},
|
|
99
99
|
"dependencies": {
|
|
100
|
-
"@glassly/bluetooth-sdk": "0.4.0-dev.
|
|
101
|
-
"@glassly/cloud-client": "0.4.0-dev.
|
|
102
|
-
"@glassly/cloud-protocol": "0.4.0-dev.
|
|
103
|
-
"@glassly/crust": "0.4.0-dev.
|
|
104
|
-
"@glassly/miniapp": "0.4.0-dev.
|
|
100
|
+
"@glassly/bluetooth-sdk": "0.4.0-dev.1039",
|
|
101
|
+
"@glassly/cloud-client": "0.4.0-dev.1039",
|
|
102
|
+
"@glassly/cloud-protocol": "0.4.0-dev.1039",
|
|
103
|
+
"@glassly/crust": "0.4.0-dev.1039",
|
|
104
|
+
"@glassly/miniapp": "0.4.0-dev.1039",
|
|
105
105
|
"buffer": "^6.0.3",
|
|
106
106
|
"events": "^3.3.0",
|
|
107
107
|
"react-native-marked": "8.3.2",
|
|
108
108
|
"semver": "^7.7.4",
|
|
109
109
|
"typesafe-ts": "^1.7.1",
|
|
110
|
-
"@glassly/llm-providers": "0.4.0-dev.
|
|
110
|
+
"@glassly/llm-providers": "0.4.0-dev.1039",
|
|
111
111
|
"@huggingface/jinja": "^0.5.9",
|
|
112
112
|
"jsonrepair": "^3.12.0"
|
|
113
113
|
},
|
package/src/engine.ts
CHANGED
|
@@ -239,7 +239,7 @@ export const engine = {
|
|
|
239
239
|
backup,
|
|
240
240
|
/** Device-local voice profiles for on-device speaker ID (Settings > Speakers). */
|
|
241
241
|
speakers,
|
|
242
|
-
/** AI/voice provider key validation — user-supplied keys (Settings > API Keys). */
|
|
242
|
+
/** AI/voice provider key validation — user-supplied keys (Settings > Privacy > API Keys). */
|
|
243
243
|
providerKeys,
|
|
244
244
|
display,
|
|
245
245
|
}
|
package/src/facades/glasses.ts
CHANGED
|
@@ -114,7 +114,7 @@ function projectKeyboardStatus() {
|
|
|
114
114
|
const s = useGlassesStore.getState()
|
|
115
115
|
return {
|
|
116
116
|
/** Connected glasses run a firmware that can host a keyboard (G2 Glassly CFW 39+). */
|
|
117
|
-
available: s.keyboardBridge === true,
|
|
117
|
+
available: isGlassesReady(s.connection) && s.keyboardBridge === true,
|
|
118
118
|
connected: s.keyboardConnected === true,
|
|
119
119
|
name: s.keyboardName ?? "",
|
|
120
120
|
/** A keyboard is remembered and reconnects automatically. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* providerKeys facade — `engine.providerKeys.{anthropic,gemini,openai,deepseek,elevenlabs}`:
|
|
3
3
|
* validate-before-save probes for the user-supplied AI/voice provider keys
|
|
4
|
-
* (Settings > API Keys). Same per-provider shape as `engine.maps.mapbox` /
|
|
4
|
+
* (Settings > Privacy > API Keys). Same per-provider shape as `engine.maps.mapbox` /
|
|
5
5
|
* `engine.speech.sonioxDirect` so the Keys screen treats providers uniformly.
|
|
6
6
|
*/
|
|
7
7
|
import {
|
|
@@ -12,9 +12,9 @@ export interface EngineReleaseMetadata {
|
|
|
12
12
|
export const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({
|
|
13
13
|
"schemaVersion": 1,
|
|
14
14
|
"familyBaseVersion": "0.4.0",
|
|
15
|
-
"releaseIdentity": "0.4.0-dev.
|
|
16
|
-
"releaseSetId": "glassly-0.4.0-dev.
|
|
17
|
-
"sourceCommit": "
|
|
15
|
+
"releaseIdentity": "0.4.0-dev.1039",
|
|
16
|
+
"releaseSetId": "glassly-0.4.0-dev.1039",
|
|
17
|
+
"sourceCommit": "daea71d3a5f3ab0c53c092cb2484c28b2b8d8493",
|
|
18
18
|
"otaManifestUrl": null,
|
|
19
19
|
"otaManifestSha256": null
|
|
20
20
|
})
|
|
@@ -48,10 +48,7 @@ export type MentraLiveOtaScreen =
|
|
|
48
48
|
| "disconnected"
|
|
49
49
|
|
|
50
50
|
export type MentraLiveOtaErrorCode =
|
|
51
|
-
| "
|
|
52
|
-
| "update_info_unavailable"
|
|
53
|
-
| "install_failed"
|
|
54
|
-
| "bes_restart_required"
|
|
51
|
+
"check_failed" | "update_info_unavailable" | "install_failed" | "bes_restart_required"
|
|
55
52
|
|
|
56
53
|
export type MentraLiveOtaError = {
|
|
57
54
|
code: MentraLiveOtaErrorCode
|
package/src/runtime/config.ts
CHANGED
|
@@ -66,12 +66,7 @@ export type NavErrorEvent = {kind: "error"; message: string}
|
|
|
66
66
|
/** Synthesized by the host when the trip is cancelled outside the miniapp (e.g. wearer exited nav mode on the glasses). */
|
|
67
67
|
export type NavCancelledEvent = {kind: "cancelled"; reason?: string}
|
|
68
68
|
export type NavUpdate =
|
|
69
|
-
|
|
|
70
|
-
| NavOffRouteEvent
|
|
71
|
-
| NavReroutingEvent
|
|
72
|
-
| NavArrivedEvent
|
|
73
|
-
| NavErrorEvent
|
|
74
|
-
| NavCancelledEvent
|
|
69
|
+
NavManeuverEvent | NavOffRouteEvent | NavReroutingEvent | NavArrivedEvent | NavErrorEvent | NavCancelledEvent
|
|
75
70
|
|
|
76
71
|
export type NavLocation = {
|
|
77
72
|
lat: number
|
|
@@ -51,7 +51,7 @@ export const TIER_MODEL_OPTIONS: Record<AiTier, TierModelOption[]> = {
|
|
|
51
51
|
],
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
/** Which providers currently have a user key saved (Settings > API Keys). */
|
|
54
|
+
/** Which providers currently have a user key saved (Settings > Privacy > API Keys). */
|
|
55
55
|
export type SavedLlmKeys = Record<AiTierProvider, boolean>
|
|
56
56
|
|
|
57
57
|
/**
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type {ReportSubmitResult} from "../facades/reports"
|
|
2
2
|
|
|
3
3
|
export type AutomaticReportSubmissionStatus =
|
|
4
|
-
|
|
5
|
-
| {status: "skipped"; reason: string}
|
|
6
|
-
| {status: "failed"; error: string}
|
|
4
|
+
{status: "filed"; reportId: string} | {status: "skipped"; reason: string} | {status: "failed"; error: string}
|
|
7
5
|
|
|
8
6
|
export function toAutomaticReportSubmissionStatus(result: ReportSubmitResult): AutomaticReportSubmissionStatus {
|
|
9
7
|
if (result.status === "submitted") {
|
|
@@ -50,7 +50,7 @@ const MIDDLE_FINGER_GLYPHS: Partial<Record<GestureDotGlyph, GestureDotGlyph>> =
|
|
|
50
50
|
|
|
51
51
|
/** `glyph` as `finger` draws it: the middle finger's shapes are hollow. */
|
|
52
52
|
function fingerGlyph(glyph: GestureDotGlyph, finger: number): GestureDotGlyph {
|
|
53
|
-
return finger === 1 ? MIDDLE_FINGER_GLYPHS[glyph] ?? glyph : glyph
|
|
53
|
+
return finger === 1 ? (MIDDLE_FINGER_GLYPHS[glyph] ?? glyph) : glyph
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
function fingerKey(controllerId: string | undefined, finger: number): string {
|
|
@@ -24,10 +24,7 @@ export type HotspotOtaProgress = {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export type HotspotOtaErrorCode =
|
|
27
|
-
| "
|
|
28
|
-
| "hotspot_start_failed"
|
|
29
|
-
| "hotspot_join_failed"
|
|
30
|
-
| "hotspot_server_failed"
|
|
27
|
+
"hotspot_wifi_permission_denied" | "hotspot_start_failed" | "hotspot_join_failed" | "hotspot_server_failed"
|
|
31
28
|
|
|
32
29
|
export class HotspotOtaTransportError extends Error {
|
|
33
30
|
constructor(
|
|
@@ -141,6 +141,7 @@ import {phoneStreamCoordinator} from "./PhoneStreamCoordinator"
|
|
|
141
141
|
import {phoneVideoCoordinator} from "./PhoneVideoCoordinator"
|
|
142
142
|
import {runSentenceTtsPipeline} from "./SentenceTtsPipeline"
|
|
143
143
|
import {
|
|
144
|
+
matchesTranscriptionSubscription,
|
|
144
145
|
summarizeTranscriptionRoutes,
|
|
145
146
|
transcriptionDeliveryRoute,
|
|
146
147
|
type TranscriptionDeliveryRoute,
|
|
@@ -433,7 +434,7 @@ const PERMISSION_TYPE_TO_CANONICAL: Record<string, string> = {
|
|
|
433
434
|
}
|
|
434
435
|
|
|
435
436
|
/**
|
|
436
|
-
* User API keys (Settings > API Keys) a miniapp may read via
|
|
437
|
+
* User API keys (Settings > Privacy > API Keys) a miniapp may read via
|
|
437
438
|
* session.keys.get(), mapped provider → settings-store key. Explicit
|
|
438
439
|
* allowlist: the Soniox key is deliberately absent — it gates the
|
|
439
440
|
* phone→Soniox direct transcription path and is not exposed to miniapps.
|
|
@@ -477,9 +478,9 @@ function directLlmProvider(name: AiTierProvider): LlmProviderImpl {
|
|
|
477
478
|
}
|
|
478
479
|
|
|
479
480
|
const QUOTA_EXCEEDED_MESSAGE =
|
|
480
|
-
"AI credits are used up. Get more in Settings > Membership, or add your own API key in Settings > API Keys."
|
|
481
|
+
"AI credits are used up. Get more in Settings > Membership, or add your own API key in Settings > Privacy > API Keys."
|
|
481
482
|
|
|
482
|
-
/** The user's saved key (Settings > API Keys) for an LLM provider, "" if none. */
|
|
483
|
+
/** The user's saved key (Settings > Privacy > API Keys) for an LLM provider, "" if none. */
|
|
483
484
|
function userLlmKey(provider: AiTierProvider): string {
|
|
484
485
|
const raw = useSettingsStore.getState().getSetting(MINIAPP_READABLE_API_KEYS[provider])
|
|
485
486
|
return typeof raw === "string" ? raw.trim() : ""
|
|
@@ -4149,7 +4150,7 @@ class LocalMiniappRuntime {
|
|
|
4149
4150
|
}
|
|
4150
4151
|
|
|
4151
4152
|
// ---------------------------------------------------------------------------
|
|
4152
|
-
// User API keys (Settings > API Keys)
|
|
4153
|
+
// User API keys (Settings > Privacy > API Keys)
|
|
4153
4154
|
// ---------------------------------------------------------------------------
|
|
4154
4155
|
|
|
4155
4156
|
/**
|
|
@@ -4217,7 +4218,7 @@ class LocalMiniappRuntime {
|
|
|
4217
4218
|
* The request names a TIER; this handler resolves it to a provider+model
|
|
4218
4219
|
* (Settings > AI Models dropdowns, or auto from saved keys) and then picks
|
|
4219
4220
|
* one of two transport paths, decided by whether the user saved a key for
|
|
4220
|
-
* the resolved provider (Settings > API Keys) — the phone is where both
|
|
4221
|
+
* the resolved provider (Settings > Privacy > API Keys) — the phone is where both
|
|
4221
4222
|
* settings live, so this is the only place the choice can be made:
|
|
4222
4223
|
*
|
|
4223
4224
|
* - User key saved → the phone calls the vendor DIRECTLY via
|
|
@@ -4490,7 +4491,7 @@ class LocalMiniappRuntime {
|
|
|
4490
4491
|
this.sendResult(packageName, requestId, false, undefined, {
|
|
4491
4492
|
code: MiniappErrorCode.QUOTA_EXCEEDED,
|
|
4492
4493
|
message:
|
|
4493
|
-
"AI credits are used up. Get more in Settings > Membership, or add your own API key in Settings > API Keys.",
|
|
4494
|
+
"AI credits are used up. Get more in Settings > Membership, or add your own API key in Settings > Privacy > API Keys.",
|
|
4494
4495
|
})
|
|
4495
4496
|
return
|
|
4496
4497
|
}
|
|
@@ -4744,7 +4745,11 @@ class LocalMiniappRuntime {
|
|
|
4744
4745
|
* session.system.webLogin — host in-app browser sheet. Same contract as
|
|
4745
4746
|
* scanQr: the seam presents a Modal and never clears miniapp foreground.
|
|
4746
4747
|
*/
|
|
4747
|
-
private async handleWebLogin(
|
|
4748
|
+
private async handleWebLogin(
|
|
4749
|
+
packageName: string,
|
|
4750
|
+
payload: Record<string, unknown>,
|
|
4751
|
+
requestId?: string,
|
|
4752
|
+
): Promise<void> {
|
|
4748
4753
|
try {
|
|
4749
4754
|
const result = await invokeWebLoginSeam(getUiSeams().webLogin, payload, packageName)
|
|
4750
4755
|
this.sendResult(packageName, requestId, true, result)
|
|
@@ -5385,6 +5390,9 @@ class LocalMiniappRuntime {
|
|
|
5385
5390
|
*/
|
|
5386
5391
|
private buildCloudAudioSubscriptions(cloudStreams: Set<string>): AudioSubscription[] {
|
|
5387
5392
|
const subs: AudioSubscription[] = []
|
|
5393
|
+
// One auto recognizer serves every transcription listener. Explicit-language
|
|
5394
|
+
// listeners are filtered at delivery; translations still need their own jobs.
|
|
5395
|
+
const hasAutoTranscription = cloudStreams.has("transcription:auto")
|
|
5388
5396
|
// Union of every connected app's TRANSCRIPTION_CONFIG hints. Hints only
|
|
5389
5397
|
// apply to the auto-mode TRANSCRIPTION subscription (the wire schema has
|
|
5390
5398
|
// no hints field on specific-language sources — the language IS the hint
|
|
@@ -5395,6 +5403,7 @@ class LocalMiniappRuntime {
|
|
|
5395
5403
|
for (const stream of cloudStreams) {
|
|
5396
5404
|
if (stream.startsWith("transcription:")) {
|
|
5397
5405
|
const lang = stream.substring("transcription:".length)
|
|
5406
|
+
if (hasAutoTranscription && lang !== "auto") continue
|
|
5398
5407
|
const source = langSource(lang)
|
|
5399
5408
|
subs.push({
|
|
5400
5409
|
kind: "transcription",
|
|
@@ -5527,6 +5536,12 @@ class LocalMiniappRuntime {
|
|
|
5527
5536
|
}
|
|
5528
5537
|
|
|
5529
5538
|
private handleTranscriptionData(d: TranscriptionData): void {
|
|
5539
|
+
const expectsAuto = [...(this.streamSubscribers.get("transcription:auto") ?? [])].some(
|
|
5540
|
+
(packageName) => this.appTranscriptionRoutesForSubscription(packageName, "transcription:auto").cloud,
|
|
5541
|
+
)
|
|
5542
|
+
// Subscription replacement is asynchronous. Ignore late results from the
|
|
5543
|
+
// old pipeline while switching between auto and language-specific jobs.
|
|
5544
|
+
if ((d.subscription.language.mode === "auto") !== expectsAuto) return
|
|
5530
5545
|
const receivedAt = Date.now()
|
|
5531
5546
|
if (TRANSCRIPT_TIMING_TELEMETRY) {
|
|
5532
5547
|
console.log(
|
|
@@ -5565,6 +5580,8 @@ class LocalMiniappRuntime {
|
|
|
5565
5580
|
__hostReceivedAt: receivedAt,
|
|
5566
5581
|
},
|
|
5567
5582
|
"cloud",
|
|
5583
|
+
undefined,
|
|
5584
|
+
d.subscription,
|
|
5568
5585
|
)
|
|
5569
5586
|
}
|
|
5570
5587
|
|
|
@@ -5642,8 +5659,7 @@ class LocalMiniappRuntime {
|
|
|
5642
5659
|
/** Model profile + runtime overrides (the G2 CFW scene canvas) for the default wearable. */
|
|
5643
5660
|
private currentCapabilities(): Capabilities {
|
|
5644
5661
|
const defaultWearable = useSettingsStore.getState().getSetting(ISLAND_SETTINGS_KEYS.defaultWearable) as
|
|
5645
|
-
|
|
|
5646
|
-
| undefined
|
|
5662
|
+
DeviceTypes | undefined
|
|
5647
5663
|
return getEffectiveCapabilities(defaultWearable || DeviceTypes.NONE)
|
|
5648
5664
|
}
|
|
5649
5665
|
|
|
@@ -5790,6 +5806,8 @@ class LocalMiniappRuntime {
|
|
|
5790
5806
|
transcriptionSource?: TranscriptionEventSource,
|
|
5791
5807
|
/** Deliver to this subscriber alone (the designated dashboard app's gestures while it shows). */
|
|
5792
5808
|
only?: string,
|
|
5809
|
+
/** Producing cloud/direct subscription; auto results also serve matching language listeners. */
|
|
5810
|
+
transcriptionSubscription?: TranscriptionData["subscription"],
|
|
5793
5811
|
): void {
|
|
5794
5812
|
// Paused miniapps (glasses disconnected) hear no streams. The resume push
|
|
5795
5813
|
// lands before the reconnect's own glasses_connection event, so nothing
|
|
@@ -5801,6 +5819,12 @@ class LocalMiniappRuntime {
|
|
|
5801
5819
|
if (transcriptionSource === "local") markTranscriptSourceRecent("local")
|
|
5802
5820
|
// Translate cloud event names to miniapp protocol stream types
|
|
5803
5821
|
const normalizedStream = this.normalizeStreamType(streamType)
|
|
5822
|
+
const transcriptionStreams =
|
|
5823
|
+
transcriptionSource === "cloud" && transcriptionSubscription
|
|
5824
|
+
? [...this.streamSubscribers.keys()].filter((stream) =>
|
|
5825
|
+
matchesTranscriptionSubscription(stream, normalizedStream, transcriptionSubscription),
|
|
5826
|
+
)
|
|
5827
|
+
: undefined
|
|
5804
5828
|
|
|
5805
5829
|
// Passive memory capture happens HERE, before subscriber fan-out, so the
|
|
5806
5830
|
// timeline reflects what was said around the user regardless of which
|
|
@@ -5809,10 +5833,10 @@ class LocalMiniappRuntime {
|
|
|
5809
5833
|
// recorded while it was open.)
|
|
5810
5834
|
this.captureTranscriptToMemory(normalizedStream, data)
|
|
5811
5835
|
|
|
5812
|
-
//
|
|
5813
|
-
//
|
|
5814
|
-
//
|
|
5815
|
-
//
|
|
5836
|
+
// Auto cloud/direct results serve auto listeners and listeners requesting
|
|
5837
|
+
// the detected language. Specific jobs serve only their own subscription.
|
|
5838
|
+
// Local/legacy events have no producing subscription and retain wildcard
|
|
5839
|
+
// matching so one on-device recognizer can serve auto and explicit listeners.
|
|
5816
5840
|
//
|
|
5817
5841
|
// Translation streams support cloud v3's wildcard patterns. Incoming
|
|
5818
5842
|
// events are keyed `translation:<source>:<target>` and we match against
|
|
@@ -5824,11 +5848,13 @@ class LocalMiniappRuntime {
|
|
|
5824
5848
|
// translation:auto — back-compat alias for *:*
|
|
5825
5849
|
const matchedSubs = new Set<string>()
|
|
5826
5850
|
let translationPatterns: string[] = []
|
|
5827
|
-
const
|
|
5828
|
-
|
|
5851
|
+
for (const stream of transcriptionStreams ?? [normalizedStream]) {
|
|
5852
|
+
const exact = this.streamSubscribers.get(stream)
|
|
5853
|
+
if (exact) for (const p of exact) matchedSubs.add(p)
|
|
5854
|
+
}
|
|
5829
5855
|
|
|
5830
5856
|
if (normalizedStream.startsWith("transcription:")) {
|
|
5831
|
-
const autoSubs = this.streamSubscribers.get("transcription:auto")
|
|
5857
|
+
const autoSubs = transcriptionStreams ? undefined : this.streamSubscribers.get("transcription:auto")
|
|
5832
5858
|
if (autoSubs) for (const p of autoSubs) matchedSubs.add(p)
|
|
5833
5859
|
} else if (normalizedStream.startsWith("translation:")) {
|
|
5834
5860
|
// translation:<source>:<target> — match each wildcard variant.
|
|
@@ -5907,8 +5933,18 @@ class LocalMiniappRuntime {
|
|
|
5907
5933
|
// The wearer's touches reach a widget-only app through its host's widget events alone.
|
|
5908
5934
|
if (normalizedStream === MiniappStreamType.TOUCH_EVENT && miniappWidgetMode.isWidgetOnly(packageName)) continue
|
|
5909
5935
|
let transcriptionRoute: TranscriptionDeliveryRoute | undefined
|
|
5936
|
+
let outboundStream = normalizedStream
|
|
5910
5937
|
if (normalizedStream.startsWith("transcription:") && transcriptionSource) {
|
|
5911
|
-
const
|
|
5938
|
+
const cloudStreams = transcriptionStreams?.filter(
|
|
5939
|
+
(stream) => this.appTranscriptionRoutesForSubscription(packageName, stream).cloud,
|
|
5940
|
+
)
|
|
5941
|
+
const routes = cloudStreams
|
|
5942
|
+
? {cloud: cloudStreams.length > 0, forceLocal: false}
|
|
5943
|
+
: this.appTranscriptionRoutesForEvent(packageName, normalizedStream)
|
|
5944
|
+
// Existing miniapp bundles dispatch explicit listeners by their BCP-47
|
|
5945
|
+
// subscription key, while providers detect bare codes (es vs es-ES).
|
|
5946
|
+
// Send one envelope per app, even when it also subscribes to auto.
|
|
5947
|
+
outboundStream = cloudStreams?.find((stream) => stream !== "transcription:auto") ?? normalizedStream
|
|
5912
5948
|
transcriptionRoute =
|
|
5913
5949
|
transcriptionDeliveryRoute(transcriptionSource, routes, this.transcriptionPrimaryUp()) ?? undefined
|
|
5914
5950
|
if (!transcriptionRoute) continue
|
|
@@ -5937,7 +5973,7 @@ class LocalMiniappRuntime {
|
|
|
5937
5973
|
}
|
|
5938
5974
|
this.sendToMiniapp(packageName, {
|
|
5939
5975
|
type: MiniappResponseType.EVENT,
|
|
5940
|
-
streamType:
|
|
5976
|
+
streamType: outboundStream,
|
|
5941
5977
|
data: outboundData,
|
|
5942
5978
|
...(transcriptionRoute ? {transcriptionRoute} : {}),
|
|
5943
5979
|
})
|
|
@@ -6538,7 +6574,12 @@ class LocalMiniappRuntime {
|
|
|
6538
6574
|
// and an unplace racing it cannot stop the provider early. A provider the
|
|
6539
6575
|
// store already runs (a wearer's launch still spawning, say) stays a
|
|
6540
6576
|
// normal run; the registry alone lags that launch.
|
|
6541
|
-
this.widgetPlacements = placeWidget(this.widgetPlacements, {
|
|
6577
|
+
this.widgetPlacements = placeWidget(this.widgetPlacements, {
|
|
6578
|
+
hostPackageName,
|
|
6579
|
+
providerPackageName: provider,
|
|
6580
|
+
widgetId,
|
|
6581
|
+
box,
|
|
6582
|
+
})
|
|
6542
6583
|
miniappWidgetMode.setPlaced(provider, true)
|
|
6543
6584
|
if (!app.running && !miniappRunningRegistry.has(provider)) miniappWidgetMode.setWidgetOnly(provider, true)
|
|
6544
6585
|
try {
|
|
@@ -6575,7 +6616,10 @@ class LocalMiniappRuntime {
|
|
|
6575
6616
|
this.widgetPlacements = unplaceWidget(this.widgetPlacements, hostPackageName, provider, target.widgetId)
|
|
6576
6617
|
this.sendResult(hostPackageName, requestId, true)
|
|
6577
6618
|
if (!had) return
|
|
6578
|
-
if (
|
|
6619
|
+
if (
|
|
6620
|
+
this.connectedApps.has(provider) &&
|
|
6621
|
+
widgetHostsOf(this.widgetPlacements, provider, target.widgetId).length === 0
|
|
6622
|
+
) {
|
|
6579
6623
|
this.sendWidgetCall(provider, target.widgetId, {kind: "box", box: null})
|
|
6580
6624
|
}
|
|
6581
6625
|
await this.settleWidgetProvider(provider)
|
|
@@ -6706,9 +6750,7 @@ class LocalMiniappRuntime {
|
|
|
6706
6750
|
if (!widget) return
|
|
6707
6751
|
const view: WidgetView = payload.view === "expanded" ? "expanded" : "card"
|
|
6708
6752
|
if (view === "expanded" && !widget.expandable) {
|
|
6709
|
-
console.warn(
|
|
6710
|
-
`${LOG_TAG}: dropping expanded frame from ${providerPackageName}/${widgetId}: it does not list EX`,
|
|
6711
|
-
)
|
|
6753
|
+
console.warn(`${LOG_TAG}: dropping expanded frame from ${providerPackageName}/${widgetId}: it does not list EX`)
|
|
6712
6754
|
return
|
|
6713
6755
|
}
|
|
6714
6756
|
const cap =
|
|
@@ -28,11 +28,7 @@ import sttModelManager from "./STTModelManager"
|
|
|
28
28
|
* `force_local` (a forced subscription would keep local STT on either way).
|
|
29
29
|
*/
|
|
30
30
|
export type LocalSttFallbackReason =
|
|
31
|
-
| "
|
|
32
|
-
| "cloud_disconnected"
|
|
33
|
-
| "cloud_disabled"
|
|
34
|
-
| "stt_quota"
|
|
35
|
-
| "provider_unreachable"
|
|
31
|
+
"force_local" | "cloud_disconnected" | "cloud_disabled" | "stt_quota" | "provider_unreachable"
|
|
36
32
|
|
|
37
33
|
class LocalSttFallbackCoordinator {
|
|
38
34
|
private static instance: LocalSttFallbackCoordinator
|
|
@@ -61,8 +61,7 @@ class NativeNavigationService {
|
|
|
61
61
|
*/
|
|
62
62
|
public isSupported(): boolean {
|
|
63
63
|
const defaultWearable = useSettingsStore.getState().getSetting(ISLAND_SETTINGS_KEYS.defaultWearable) as
|
|
64
|
-
|
|
|
65
|
-
| undefined
|
|
64
|
+
DeviceTypes | undefined
|
|
66
65
|
// Effective, not model: custom firmware drops hasNativeNavigation so the
|
|
67
66
|
// miniapp's scene HUD owns the display (see effectiveCapabilities).
|
|
68
67
|
const capabilities = getEffectiveCapabilities(defaultWearable || DeviceTypes.NONE)
|
|
@@ -364,7 +364,7 @@ export class NavigationHandlers {
|
|
|
364
364
|
|
|
365
365
|
async handleComputeRoute(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {
|
|
366
366
|
try {
|
|
367
|
-
// With the user's own Mapbox key (Settings > API Keys), compute
|
|
367
|
+
// With the user's own Mapbox key (Settings > Privacy > API Keys), compute
|
|
368
368
|
// on-device so routing works without the cloud and bills their account.
|
|
369
369
|
// Without one, go through the v2 cloud maps proxy — org-token Mapbox
|
|
370
370
|
// usage only ever happens cloud-side.
|
|
@@ -437,7 +437,7 @@ export class NavigationHandlers {
|
|
|
437
437
|
|
|
438
438
|
/**
|
|
439
439
|
* Type-ahead place search. Runs on-device against Mapbox Search Box when the
|
|
440
|
-
* user saved their own key (Settings > API Keys) — that key exists precisely
|
|
440
|
+
* user saved their own key (Settings > Privacy > API Keys) — that key exists precisely
|
|
441
441
|
* so search works without the cloud — and falls back to the v2 cloud maps
|
|
442
442
|
* service otherwise. Resolves `{ok: true, suggestions}` — an empty query or no
|
|
443
443
|
* matches is `{ok: true, suggestions: []}`, not an error.
|