@hasna/recordings 0.2.14 → 0.3.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.
Files changed (123) hide show
  1. package/Dockerfile.package +4 -5
  2. package/README.md +113 -8
  3. package/bun.lock +2 -2
  4. package/dist/__tests__/helpers/installer-guard-execution.d.ts +22 -0
  5. package/dist/__tests__/helpers/installer-guard-execution.d.ts.map +1 -0
  6. package/dist/__tests__/helpers/installer-preflight.d.ts +22 -0
  7. package/dist/__tests__/helpers/installer-preflight.d.ts.map +1 -0
  8. package/dist/__tests__/helpers/native-fs-guard.d.ts.map +1 -1
  9. package/dist/__tests__/helpers/source-assertions.d.ts +169 -0
  10. package/dist/__tests__/helpers/source-assertions.d.ts.map +1 -0
  11. package/dist/__tests__/preload.d.ts +1 -4
  12. package/dist/__tests__/preload.d.ts.map +1 -1
  13. package/dist/cli/desktop-snapshot.d.ts +20 -0
  14. package/dist/cli/desktop-snapshot.d.ts.map +1 -0
  15. package/dist/cli/index.js +2094 -280
  16. package/dist/cli/macos-permissions.d.ts +72 -0
  17. package/dist/cli/macos-permissions.d.ts.map +1 -1
  18. package/dist/cli/macos-shortcut.d.ts +139 -0
  19. package/dist/cli/macos-shortcut.d.ts.map +1 -0
  20. package/dist/cli/trigger-probe.d.ts +172 -0
  21. package/dist/cli/trigger-probe.d.ts.map +1 -0
  22. package/dist/db/database.d.ts +9 -0
  23. package/dist/db/database.d.ts.map +1 -1
  24. package/dist/http/client.d.ts +19 -7
  25. package/dist/http/client.d.ts.map +1 -1
  26. package/dist/index.d.ts +3 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +635 -50
  29. package/dist/lib/capture-probe.d.ts +216 -0
  30. package/dist/lib/capture-probe.d.ts.map +1 -0
  31. package/dist/lib/config.d.ts.map +1 -1
  32. package/dist/lib/macos-bundle.d.ts +50 -0
  33. package/dist/lib/macos-bundle.d.ts.map +1 -0
  34. package/dist/lib/persistence-probe.d.ts +208 -0
  35. package/dist/lib/persistence-probe.d.ts.map +1 -0
  36. package/dist/lib/recorder.d.ts.map +1 -1
  37. package/dist/lib/retired-deployment-modes.d.ts +24 -0
  38. package/dist/lib/retired-deployment-modes.d.ts.map +1 -0
  39. package/dist/lib/transcriber.d.ts +60 -0
  40. package/dist/lib/transcriber.d.ts.map +1 -1
  41. package/dist/mcp/index.js +141 -57
  42. package/dist/server/cloud-config.d.ts +25 -3
  43. package/dist/server/cloud-config.d.ts.map +1 -1
  44. package/dist/server/cloud-readiness.d.ts.map +1 -1
  45. package/dist/server/cloud.d.ts +8 -7
  46. package/dist/server/cloud.d.ts.map +1 -1
  47. package/dist/server/index.js +188 -80
  48. package/dist/server/migrate-command.d.ts.map +1 -1
  49. package/dist/server/serve.d.ts.map +1 -1
  50. package/dist/storage.d.ts +2 -2
  51. package/dist/storage.d.ts.map +1 -1
  52. package/dist/storage.js +109 -50
  53. package/dist/store.d.ts +1 -1
  54. package/dist/store.d.ts.map +1 -1
  55. package/dist/version.d.ts +1 -1
  56. package/dist/version.d.ts.map +1 -1
  57. package/package.json +25 -6
  58. package/scripts/ci-linux-suite.ts +403 -0
  59. package/scripts/ci-native-build.ts +402 -0
  60. package/scripts/enforce_identity_migration.sh +110 -0
  61. package/scripts/generate-sdk.ts +1 -1
  62. package/scripts/install_macos_app.sh +192 -31
  63. package/scripts/macos_artifact.ts +323 -43
  64. package/scripts/native/realtime-settle-probe/README.md +39 -0
  65. package/scripts/native/realtime-settle-probe/main.swift +135 -0
  66. package/scripts/policy/local-only-approved-targets.txt +21 -0
  67. package/scripts/read_local_only_targets.sh +203 -0
  68. package/scripts/scan-artifact.ts +40 -0
  69. package/scripts/set-version.ts +145 -0
  70. package/scripts/smoke_macos_app.sh +62 -16
  71. package/scripts/vacuity-manifest-gen.ts +96 -0
  72. package/scripts/vacuity-manifests/enhancement-screen-mirror.tsv +44 -0
  73. package/scripts/vacuity-manifests/install-chain.tsv +13 -0
  74. package/scripts/vacuity-manifests/must-survive-controls.tsv +10 -0
  75. package/scripts/vacuity-manifests/reorder.tsv +4 -0
  76. package/scripts/vacuity-manifests/source-side.tsv +15 -0
  77. package/scripts/vacuity-manifests/variable-operands.tsv +16 -0
  78. package/scripts/vacuity-manifests/version-sites.tsv +61 -0
  79. package/scripts/vacuity-mutation-battery.ts +266 -0
  80. package/src/native/Recordings/App/MenuBarStatusView.swift +23 -11
  81. package/src/native/Recordings/App/RecordingsApp.swift +37 -1
  82. package/src/native/Recordings/App/RuntimeSmoke.swift +5 -1
  83. package/src/native/Recordings/App/SidebarView.swift +1 -1
  84. package/src/native/Recordings/Package.swift +24 -5
  85. package/src/native/Recordings/RecordingsLib/EnhancementScreen.swift +91 -0
  86. package/src/native/Recordings/RecordingsLib/FnKeyMonitor.swift +27 -4
  87. package/src/native/Recordings/RecordingsLib/Info.plist +2 -2
  88. package/src/native/Recordings/RecordingsLib/MenuBarPresentation.swift +56 -3
  89. package/src/native/Recordings/RecordingsLib/NativePCMRecorder.swift +13 -0
  90. package/src/native/Recordings/RecordingsLib/PasteDeliveryVerification.swift +460 -0
  91. package/src/native/Recordings/RecordingsLib/PermissionRequestLaunchPlan.swift +21 -1
  92. package/src/native/Recordings/RecordingsLib/RealtimeTranscriptionClient.swift +41 -7
  93. package/src/native/Recordings/RecordingsLib/RecordingAttemptAlert.swift +36 -0
  94. package/src/native/Recordings/RecordingsLib/RecordingEngine.swift +1071 -75
  95. package/src/native/Recordings/RecordingsLib/SettingsView.swift +47 -3
  96. package/src/native/Recordings/RecordingsLib/VoiceShortcuts.swift +11 -6
  97. package/src/native/Recordings/RecordingsTests/BarOnlyLaunchPlanTests.swift +99 -0
  98. package/src/native/Recordings/RecordingsTests/CLIRunnerTests.swift +3 -3
  99. package/src/native/Recordings/RecordingsTests/EnhancementScreenTests.swift +191 -0
  100. package/src/native/Recordings/RecordingsTests/MenuBarPresentationTests.swift +144 -4
  101. package/src/native/Recordings/RecordingsTests/PasteDeliveryVerificationTests.swift +463 -0
  102. package/src/native/Recordings/RecordingsTests/PasteTargetTests.swift +33 -20
  103. package/src/native/Recordings/RecordingsTests/ProjectStoreTests.swift +1 -1
  104. package/src/native/Recordings/RecordingsTests/RealtimeSettleBenchmark.swift +200 -0
  105. package/src/native/Recordings/RecordingsTests/RealtimeSettleBudgetTests.swift +80 -0
  106. package/src/native/Recordings/RecordingsTests/RealtimeTranscriptionTests.swift +22 -4
  107. package/src/native/Recordings/RecordingsTests/RecordingEngineDeliveryTests.swift +12 -6
  108. package/src/native/Recordings/RecordingsTests/RecordingEngineHomeIsolationTests.swift +67 -0
  109. package/src/native/Recordings/RecordingsTests/RecordingStartGateTests.swift +12 -3
  110. package/src/native/Recordings/RecordingsTests/RecordingStartTimingTests.swift +207 -11
  111. package/src/native/Recordings/RecordingsTests/SpeechIntentTests.swift +17 -6
  112. package/src/native/Recordings/RecordingsTests/TestHomeDirectory.swift +23 -0
  113. package/src/native/Recordings/Updater/Broker/ApplicationProcessQuiescence.swift +7 -1
  114. package/src/native/Recordings/Updater/Broker/AtomicActivation.swift +10 -10
  115. package/src/native/Recordings/Updater/Broker/BrokerMain.swift +5 -1
  116. package/src/native/Recordings/Updater/Broker/HostOSProductVersion.swift +1 -0
  117. package/src/native/Recordings/Updater/Broker/PeerIdentity.swift +59 -3
  118. package/src/native/Recordings/Updater/Protocol/UpdateProtocol.swift +21 -2
  119. package/src/native/Recordings/Updater/ProtocolTests/ExpectationIntegrityTests.swift +60 -0
  120. package/src/native/Recordings/Updater/ProtocolTests/UpdateXPCInterfaceTests.swift +113 -0
  121. package/src/native/Recordings/Updater/VerifierLauncher/RecordingsVerifierLauncher.c +106 -5
  122. package/src/native/Recordings/build.sh +226 -20
  123. package/scripts/native/prebuilds/darwin-universal/recordings_fs_guard.node +0 -0
@@ -294,7 +294,10 @@ public final class RealtimeTranscriptionClient: ObservableObject, @unchecked Sen
294
294
  let sessionConfig = Self.transcriptionSessionUpdateEvent(transcription: transcription)
295
295
 
296
296
  do {
297
- try await sendEvent(sessionConfig)
297
+ try await sendEvent(
298
+ sessionConfig,
299
+ timeoutMilliseconds: Self.configureSendTimeoutMilliseconds
300
+ )
298
301
  isConfigured = true
299
302
  flushPendingAudio()
300
303
  } catch {
@@ -369,8 +372,11 @@ public final class RealtimeTranscriptionClient: ObservableObject, @unchecked Sen
369
372
  }
370
373
 
371
374
  /// Commit buffered input, wait briefly for a final completed event, then close.
375
+ /// The settlement budget is the caller's decision (`RecordingEngine` scales it with
376
+ /// captured audio length); there is deliberately no default so a new call site cannot
377
+ /// silently reintroduce the fixed 700 ms budget this parameter replaced.
372
378
  public func finish(
373
- timeoutMilliseconds: UInt64 = 700,
379
+ timeoutMilliseconds: UInt64,
374
380
  pipelineID: String? = nil,
375
381
  pipelineStartedUptimeMilliseconds: UInt64? = nil
376
382
  ) async -> RealtimeFinishResult {
@@ -611,14 +617,42 @@ public final class RealtimeTranscriptionClient: ObservableObject, @unchecked Sen
611
617
  }
612
618
  }
613
619
 
614
- private func sendEvent(_ obj: [String: Any]) async throws {
615
- try await sendEncodedEvent(encodeJSON(obj))
620
+ /// Deadline for the session-configure send. This is the first frame on a
621
+ /// just-resumed socket, so it absorbs DNS + TCP + TLS + WebSocket upgrade on a
622
+ /// cold connection — measured 0.77-1.0 s from a fresh process against the live
623
+ /// endpoint. The old shared 500 ms deadline made a cold morning connection fail
624
+ /// configuration outright, poisoning the whole session and silently demoting
625
+ /// every recording to the batch path. The user is speaking while this runs
626
+ /// (audio buffers locally either way), so the larger budget costs nothing on
627
+ /// the delivery path.
628
+ nonisolated static let configureSendTimeoutMilliseconds: UInt64 = 3_000
629
+ /// Deadline for every send after configuration, riding the established
630
+ /// connection. A single send past this deadline records a transport failure,
631
+ /// which permanently vetoes the realtime fast path for the whole recording —
632
+ /// so the deadline must tolerate ordinary jitter, not just the median. At the
633
+ /// old 500 ms value, 3 of 5 two-minute streaming sessions against the live
634
+ /// endpoint were poisoned by one slow frame and demoted to the batch path.
635
+ /// True connection stalls are still detected structurally: the bounded
636
+ /// outbound queue (262,144 bytes of raw 24 kHz/16-bit PCM ≈ 5.5 s of audio,
637
+ /// 262,144 ÷ 48,000 bytes/s) overflows and fails the transport
638
+ /// if sends stop draining, and the settle budget bounds release latency
639
+ /// regardless of this deadline.
640
+ nonisolated static let outboundSendTimeoutMilliseconds: UInt64 = 2_500
641
+
642
+ private func sendEvent(
643
+ _ obj: [String: Any],
644
+ timeoutMilliseconds: UInt64 = RealtimeTranscriptionClient.outboundSendTimeoutMilliseconds
645
+ ) async throws {
646
+ try await sendEncodedEvent(encodeJSON(obj), timeoutMilliseconds: timeoutMilliseconds)
616
647
  }
617
648
 
618
- private func sendEncodedEvent(_ text: String) async throws {
649
+ private func sendEncodedEvent(
650
+ _ text: String,
651
+ timeoutMilliseconds: UInt64 = RealtimeTranscriptionClient.outboundSendTimeoutMilliseconds
652
+ ) async throws {
619
653
  guard let ws else { throw URLError(.networkConnectionLost) }
620
654
  try await Self.runOutboundOperationWithDeadline(
621
- timeoutMilliseconds: 500,
655
+ timeoutMilliseconds: timeoutMilliseconds,
622
656
  operation: { try await ws.send(.string(text)) },
623
657
  nowMilliseconds: Self.monotonicMilliseconds,
624
658
  sleepMilliseconds: { milliseconds in
@@ -826,7 +860,7 @@ extension RealtimeTranscriptionClient {
826
860
  _ operation: @escaping @MainActor @Sendable () async throws -> Void
827
861
  ) async -> Bool {
828
862
  await enqueueOutboundOperationTestHelper(
829
- timeoutMilliseconds: 500,
863
+ timeoutMilliseconds: Self.outboundSendTimeoutMilliseconds,
830
864
  operation: operation,
831
865
  nowMilliseconds: Self.monotonicMilliseconds,
832
866
  sleepMilliseconds: { milliseconds in
@@ -0,0 +1,36 @@
1
+ import Foundation
2
+
3
+ /// A recording attempt that produced nothing the user can see anywhere else.
4
+ ///
5
+ /// Recordings is an `LSUIElement` app: its only always-on surface is the menu-bar glyph.
6
+ /// `statusMessage` and the Record pane both sit behind a click, so an outcome delivered only
7
+ /// there is invisible to someone who pressed the key while looking at their editor — which is
8
+ /// how a swallowed attempt reads as "the app is still broken" no matter what the log says.
9
+ ///
10
+ /// This is a message vocabulary, not a surface. The engine discloses these through
11
+ /// `setBlockedReason(_:for: .pressConsumed)` — the single published `blockedReason` field, which
12
+ /// `MenuBarPresentation` already renders with its own icon and its own VoiceOver label, and which
13
+ /// `startRecording` already clears. A second published field for the same idea would undo the
14
+ /// collapse that field exists to be.
15
+ public enum RecordingAttemptAlert: Equatable, Sendable {
16
+ /// The trigger was released before the microphone delivered its first sample, so no audio
17
+ /// ever existed to transcribe.
18
+ case releasedBeforeAudio
19
+ /// Capture ran to completion but the microphone produced no audio at all.
20
+ case noAudioCaptured
21
+
22
+ /// Shown on the menu-bar status line and in the Record pane. Kept short enough to fit the
23
+ /// 260 pt popover without wrapping past two lines, and phrased as the corrective action
24
+ /// rather than a diagnosis.
25
+ ///
26
+ /// Deliberately carries no millisecond figure. The hold a user has to manage is the cold
27
+ /// audio engine plus one input buffer period, and the buffer period is a property of
28
+ /// whichever device is selected — so any number printed here would be wrong on some
29
+ /// machines.
30
+ public var message: String {
31
+ switch self {
32
+ case .releasedBeforeAudio: "Released too soon — hold the key a moment longer"
33
+ case .noAudioCaptured: "No audio captured"
34
+ }
35
+ }
36
+ }