urma-mcp 0.1.0-rc.1

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 (229) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +389 -0
  3. package/assets/urma-banner.png +0 -0
  4. package/assets/urma-logo.png +0 -0
  5. package/dist/src/acquisition/frame-panel.d.ts +22 -0
  6. package/dist/src/acquisition/frame-panel.js +110 -0
  7. package/dist/src/acquisition/frame-panel.js.map +1 -0
  8. package/dist/src/acquisition/frames.d.ts +37 -0
  9. package/dist/src/acquisition/frames.js +463 -0
  10. package/dist/src/acquisition/frames.js.map +1 -0
  11. package/dist/src/acquisition/media.d.ts +59 -0
  12. package/dist/src/acquisition/media.js +946 -0
  13. package/dist/src/acquisition/media.js.map +1 -0
  14. package/dist/src/acquisition/overview.d.ts +31 -0
  15. package/dist/src/acquisition/overview.js +335 -0
  16. package/dist/src/acquisition/overview.js.map +1 -0
  17. package/dist/src/acquisition/panel.d.ts +16 -0
  18. package/dist/src/acquisition/panel.js +125 -0
  19. package/dist/src/acquisition/panel.js.map +1 -0
  20. package/dist/src/acquisition/records.d.ts +24 -0
  21. package/dist/src/acquisition/records.js +127 -0
  22. package/dist/src/acquisition/records.js.map +1 -0
  23. package/dist/src/acquisition/remote-budget.d.ts +4 -0
  24. package/dist/src/acquisition/remote-budget.js +121 -0
  25. package/dist/src/acquisition/remote-budget.js.map +1 -0
  26. package/dist/src/acquisition/singleflight.d.ts +10 -0
  27. package/dist/src/acquisition/singleflight.js +75 -0
  28. package/dist/src/acquisition/singleflight.js.map +1 -0
  29. package/dist/src/acquisition/storyboard.d.ts +36 -0
  30. package/dist/src/acquisition/storyboard.js +324 -0
  31. package/dist/src/acquisition/storyboard.js.map +1 -0
  32. package/dist/src/acquisition/transcript.d.ts +25 -0
  33. package/dist/src/acquisition/transcript.js +367 -0
  34. package/dist/src/acquisition/transcript.js.map +1 -0
  35. package/dist/src/acquisition/transport-policy.d.ts +7 -0
  36. package/dist/src/acquisition/transport-policy.js +22 -0
  37. package/dist/src/acquisition/transport-policy.js.map +1 -0
  38. package/dist/src/acquisition/video-timing.d.ts +24 -0
  39. package/dist/src/acquisition/video-timing.js +249 -0
  40. package/dist/src/acquisition/video-timing.js.map +1 -0
  41. package/dist/src/app.d.ts +49 -0
  42. package/dist/src/app.js +31 -0
  43. package/dist/src/app.js.map +1 -0
  44. package/dist/src/cli/doctor.d.ts +24 -0
  45. package/dist/src/cli/doctor.js +368 -0
  46. package/dist/src/cli/doctor.js.map +1 -0
  47. package/dist/src/cli/main.d.ts +2 -0
  48. package/dist/src/cli/main.js +79 -0
  49. package/dist/src/cli/main.js.map +1 -0
  50. package/dist/src/config.d.ts +36 -0
  51. package/dist/src/config.js +110 -0
  52. package/dist/src/config.js.map +1 -0
  53. package/dist/src/core/coverage.d.ts +20 -0
  54. package/dist/src/core/coverage.js +89 -0
  55. package/dist/src/core/coverage.js.map +1 -0
  56. package/dist/src/core/diagnostics.d.ts +58 -0
  57. package/dist/src/core/diagnostics.js +451 -0
  58. package/dist/src/core/diagnostics.js.map +1 -0
  59. package/dist/src/core/errors.d.ts +13 -0
  60. package/dist/src/core/errors.js +57 -0
  61. package/dist/src/core/errors.js.map +1 -0
  62. package/dist/src/core/frame-schedule.d.ts +16 -0
  63. package/dist/src/core/frame-schedule.js +52 -0
  64. package/dist/src/core/frame-schedule.js.map +1 -0
  65. package/dist/src/core/ids.d.ts +48 -0
  66. package/dist/src/core/ids.js +122 -0
  67. package/dist/src/core/ids.js.map +1 -0
  68. package/dist/src/core/model.d.ts +216 -0
  69. package/dist/src/core/model.js +2 -0
  70. package/dist/src/core/model.js.map +1 -0
  71. package/dist/src/core/request-key.d.ts +1 -0
  72. package/dist/src/core/request-key.js +8 -0
  73. package/dist/src/core/request-key.js.map +1 -0
  74. package/dist/src/core/search-limits.d.ts +11 -0
  75. package/dist/src/core/search-limits.js +13 -0
  76. package/dist/src/core/search-limits.js.map +1 -0
  77. package/dist/src/distribution/active.d.ts +20 -0
  78. package/dist/src/distribution/active.js +169 -0
  79. package/dist/src/distribution/active.js.map +1 -0
  80. package/dist/src/distribution/archive.d.ts +8 -0
  81. package/dist/src/distribution/archive.js +368 -0
  82. package/dist/src/distribution/archive.js.map +1 -0
  83. package/dist/src/distribution/download.d.ts +8 -0
  84. package/dist/src/distribution/download.js +93 -0
  85. package/dist/src/distribution/download.js.map +1 -0
  86. package/dist/src/distribution/host-registration.d.ts +7 -0
  87. package/dist/src/distribution/host-registration.js +64 -0
  88. package/dist/src/distribution/host-registration.js.map +1 -0
  89. package/dist/src/distribution/installer.d.ts +38 -0
  90. package/dist/src/distribution/installer.js +445 -0
  91. package/dist/src/distribution/installer.js.map +1 -0
  92. package/dist/src/distribution/integrity.d.ts +8 -0
  93. package/dist/src/distribution/integrity.js +131 -0
  94. package/dist/src/distribution/integrity.js.map +1 -0
  95. package/dist/src/distribution/lock.d.ts +14 -0
  96. package/dist/src/distribution/lock.js +136 -0
  97. package/dist/src/distribution/lock.js.map +1 -0
  98. package/dist/src/distribution/manifest.d.ts +46 -0
  99. package/dist/src/distribution/manifest.js +202 -0
  100. package/dist/src/distribution/manifest.js.map +1 -0
  101. package/dist/src/distribution/paths.d.ts +30 -0
  102. package/dist/src/distribution/paths.js +154 -0
  103. package/dist/src/distribution/paths.js.map +1 -0
  104. package/dist/src/distribution/platform.d.ts +15 -0
  105. package/dist/src/distribution/platform.js +76 -0
  106. package/dist/src/distribution/platform.js.map +1 -0
  107. package/dist/src/distribution/qualification.d.ts +26 -0
  108. package/dist/src/distribution/qualification.js +265 -0
  109. package/dist/src/distribution/qualification.js.map +1 -0
  110. package/dist/src/distribution/receipt.d.ts +52 -0
  111. package/dist/src/distribution/receipt.js +142 -0
  112. package/dist/src/distribution/receipt.js.map +1 -0
  113. package/dist/src/distribution/runtime.d.ts +8 -0
  114. package/dist/src/distribution/runtime.js +173 -0
  115. package/dist/src/distribution/runtime.js.map +1 -0
  116. package/dist/src/evidence/service.d.ts +959 -0
  117. package/dist/src/evidence/service.js +1455 -0
  118. package/dist/src/evidence/service.js.map +1 -0
  119. package/dist/src/evidence/state.d.ts +52 -0
  120. package/dist/src/evidence/state.js +362 -0
  121. package/dist/src/evidence/state.js.map +1 -0
  122. package/dist/src/index.d.ts +5 -0
  123. package/dist/src/index.js +6 -0
  124. package/dist/src/index.js.map +1 -0
  125. package/dist/src/mcp/logo.d.ts +5 -0
  126. package/dist/src/mcp/logo.js +11 -0
  127. package/dist/src/mcp/logo.js.map +1 -0
  128. package/dist/src/mcp/projection.d.ts +4 -0
  129. package/dist/src/mcp/projection.js +144 -0
  130. package/dist/src/mcp/projection.js.map +1 -0
  131. package/dist/src/mcp/schemas.d.ts +1744 -0
  132. package/dist/src/mcp/schemas.js +662 -0
  133. package/dist/src/mcp/schemas.js.map +1 -0
  134. package/dist/src/mcp/server.d.ts +6 -0
  135. package/dist/src/mcp/server.js +470 -0
  136. package/dist/src/mcp/server.js.map +1 -0
  137. package/dist/src/mcp/stdio.d.ts +1 -0
  138. package/dist/src/mcp/stdio.js +36 -0
  139. package/dist/src/mcp/stdio.js.map +1 -0
  140. package/dist/src/remote/egress.d.ts +42 -0
  141. package/dist/src/remote/egress.js +611 -0
  142. package/dist/src/remote/egress.js.map +1 -0
  143. package/dist/src/remote/formats.d.ts +5 -0
  144. package/dist/src/remote/formats.js +30 -0
  145. package/dist/src/remote/formats.js.map +1 -0
  146. package/dist/src/remote/lease.d.ts +15 -0
  147. package/dist/src/remote/lease.js +2 -0
  148. package/dist/src/remote/lease.js.map +1 -0
  149. package/dist/src/remote/normalize.d.ts +14 -0
  150. package/dist/src/remote/normalize.js +243 -0
  151. package/dist/src/remote/normalize.js.map +1 -0
  152. package/dist/src/remote/policy.d.ts +13 -0
  153. package/dist/src/remote/policy.js +107 -0
  154. package/dist/src/remote/policy.js.map +1 -0
  155. package/dist/src/remote/worker.d.ts +14 -0
  156. package/dist/src/remote/worker.js +40 -0
  157. package/dist/src/remote/worker.js.map +1 -0
  158. package/dist/src/sources/candidates.d.ts +18 -0
  159. package/dist/src/sources/candidates.js +23 -0
  160. package/dist/src/sources/candidates.js.map +1 -0
  161. package/dist/src/sources/caption-tracks.d.ts +12 -0
  162. package/dist/src/sources/caption-tracks.js +75 -0
  163. package/dist/src/sources/caption-tracks.js.map +1 -0
  164. package/dist/src/sources/local.d.ts +42 -0
  165. package/dist/src/sources/local.js +203 -0
  166. package/dist/src/sources/local.js.map +1 -0
  167. package/dist/src/sources/metadata.d.ts +15 -0
  168. package/dist/src/sources/metadata.js +513 -0
  169. package/dist/src/sources/metadata.js.map +1 -0
  170. package/dist/src/sources/resolver.d.ts +22 -0
  171. package/dist/src/sources/resolver.js +363 -0
  172. package/dist/src/sources/resolver.js.map +1 -0
  173. package/dist/src/sources/timeline.d.ts +23 -0
  174. package/dist/src/sources/timeline.js +145 -0
  175. package/dist/src/sources/timeline.js.map +1 -0
  176. package/dist/src/sources/types.d.ts +67 -0
  177. package/dist/src/sources/types.js +2 -0
  178. package/dist/src/sources/types.js.map +1 -0
  179. package/dist/src/sources/youtube.d.ts +10 -0
  180. package/dist/src/sources/youtube.js +59 -0
  181. package/dist/src/sources/youtube.js.map +1 -0
  182. package/dist/src/store/blob-store.d.ts +20 -0
  183. package/dist/src/store/blob-store.js +156 -0
  184. package/dist/src/store/blob-store.js.map +1 -0
  185. package/dist/src/store/schema.d.ts +4 -0
  186. package/dist/src/store/schema.js +169 -0
  187. package/dist/src/store/schema.js.map +1 -0
  188. package/dist/src/store/sqlite-store.d.ts +47 -0
  189. package/dist/src/store/sqlite-store.js +545 -0
  190. package/dist/src/store/sqlite-store.js.map +1 -0
  191. package/dist/src/store/store.d.ts +138 -0
  192. package/dist/src/store/store.js +2 -0
  193. package/dist/src/store/store.js.map +1 -0
  194. package/dist/src/subprocess/ffmpeg.d.ts +18 -0
  195. package/dist/src/subprocess/ffmpeg.js +117 -0
  196. package/dist/src/subprocess/ffmpeg.js.map +1 -0
  197. package/dist/src/subprocess/ffprobe.d.ts +11 -0
  198. package/dist/src/subprocess/ffprobe.js +62 -0
  199. package/dist/src/subprocess/ffprobe.js.map +1 -0
  200. package/dist/src/subprocess/redaction.d.ts +3 -0
  201. package/dist/src/subprocess/redaction.js +31 -0
  202. package/dist/src/subprocess/redaction.js.map +1 -0
  203. package/dist/src/subprocess/remote-media.d.ts +3 -0
  204. package/dist/src/subprocess/remote-media.js +27 -0
  205. package/dist/src/subprocess/remote-media.js.map +1 -0
  206. package/dist/src/subprocess/runner.d.ts +23 -0
  207. package/dist/src/subprocess/runner.js +197 -0
  208. package/dist/src/subprocess/runner.js.map +1 -0
  209. package/dist/src/subprocess/versions.d.ts +8 -0
  210. package/dist/src/subprocess/versions.js +46 -0
  211. package/dist/src/subprocess/versions.js.map +1 -0
  212. package/dist/src/subprocess/ytdlp.d.ts +39 -0
  213. package/dist/src/subprocess/ytdlp.js +326 -0
  214. package/dist/src/subprocess/ytdlp.js.map +1 -0
  215. package/dist/src/version.d.ts +8 -0
  216. package/dist/src/version.js +44 -0
  217. package/dist/src/version.js.map +1 -0
  218. package/docs/ARCHITECTURE.md +273 -0
  219. package/docs/CONTRIBUTING.md +101 -0
  220. package/docs/EVIDENCE_MODEL.md +292 -0
  221. package/docs/PRODUCT_SCOPE.md +115 -0
  222. package/docs/SECURITY.md +182 -0
  223. package/docs/assets/architecture.png +0 -0
  224. package/docs/assets/contribution.png +0 -0
  225. package/docs/assets/evidence-model.png +0 -0
  226. package/docs/assets/product-scope.png +0 -0
  227. package/docs/assets/security.png +0 -0
  228. package/launcher-v1.mjs +430 -0
  229. package/package.json +45 -0
@@ -0,0 +1,110 @@
1
+ import { mkdtemp, rm } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { diagnosticLog } from "../core/diagnostics.js";
4
+ import { deterministicRequestKey } from "../core/request-key.js";
5
+ import { Ffmpeg } from "../subprocess/ffmpeg.js";
6
+ import { collectBinaryVersions } from "../subprocess/versions.js";
7
+ import { BlobStore } from "../store/blob-store.js";
8
+ import { URMA_VERSION } from "../version.js";
9
+ import { createPanel, framePanelDimensions, } from "./panel.js";
10
+ function sameStrings(value, expected) {
11
+ return (Array.isArray(value) &&
12
+ value.length === expected.length &&
13
+ value.every((item, index) => item === expected[index]));
14
+ }
15
+ function sameNumbers(value, expected) {
16
+ return (Array.isArray(value) &&
17
+ value.length === expected.length &&
18
+ value.every((item, index) => item === expected[index]));
19
+ }
20
+ export class FramePanelAcquirer {
21
+ config;
22
+ store;
23
+ blobs;
24
+ constructor(config, store, blobs) {
25
+ this.config = config;
26
+ this.store = store;
27
+ this.blobs = blobs;
28
+ }
29
+ async get(source, frames, signal) {
30
+ const timesMs = frames.map((frame) => frame.atMs);
31
+ const artifactIds = frames.map((frame) => frame.artifact.artifactId);
32
+ const dimensions = framePanelDimensions(frames.length);
33
+ const requestKey = deterministicRequestKey(source.revision, "frame-panel", { timesMs, artifactIds }, "frame-panel");
34
+ const cached = this.store.getArtifactByRequest(requestKey);
35
+ if (cached?.kind === "frame_panel" &&
36
+ cached.role === "locator" &&
37
+ cached.mimeType === "image/jpeg" &&
38
+ cached.params.canonical === false &&
39
+ sameNumbers(cached.params.pointsMs, timesMs) &&
40
+ sameStrings(cached.params.artifactIds, artifactIds)) {
41
+ try {
42
+ await this.blobs.verify(cached.artifactId, cached.blobPath);
43
+ diagnosticLog(this.config.debug, "frame-panel", {
44
+ status: "cache-hit",
45
+ cellCount: frames.length,
46
+ canvasWidth: dimensions.width,
47
+ canvasHeight: dimensions.height,
48
+ imageBytes: cached.byteSize,
49
+ });
50
+ return { artifact: cached, dimensions, cacheHit: true };
51
+ }
52
+ catch {
53
+ }
54
+ }
55
+ const working = await mkdtemp(path.join(this.config.dataDir, "tmp-frame-panel-"));
56
+ try {
57
+ const paths = [];
58
+ for (const frame of frames) {
59
+ paths.push(await this.blobs.verify(frame.artifact.artifactId, frame.artifact.blobPath));
60
+ }
61
+ const output = path.join(working, "panel.jpg");
62
+ await createPanel(this.config, paths, timesMs, output, signal, {
63
+ presentation: "exact-frames",
64
+ });
65
+ const blob = await this.blobs.putFile(output, (file) => new Ffmpeg(this.config).validateJpeg(file));
66
+ const versions = await collectBinaryVersions(this.config, ["ffmpeg"], signal);
67
+ const artifact = {
68
+ artifactId: blob.artifactId,
69
+ sourceRef: source.sourceRef,
70
+ sourceRevision: source.revision,
71
+ kind: "frame_panel",
72
+ role: "locator",
73
+ mimeType: "image/jpeg",
74
+ sha256: blob.sha256,
75
+ byteSize: blob.byteSize,
76
+ blobPath: blob.relativePath,
77
+ startMs: Math.min(...timesMs),
78
+ endMs: Math.max(...timesMs),
79
+ params: {
80
+ presentation: "panel",
81
+ canonical: false,
82
+ pointsMs: timesMs,
83
+ artifactIds,
84
+ count: frames.length,
85
+ },
86
+ producer: {
87
+ version: "frame-panel",
88
+ urmaVersion: URMA_VERSION,
89
+ ...versions,
90
+ ...dimensions,
91
+ deterministic: true,
92
+ },
93
+ createdAt: new Date().toISOString(),
94
+ };
95
+ this.store.putArtifact(artifact, { requestKey, operation: "frame-panel" }, artifactIds);
96
+ diagnosticLog(this.config.debug, "frame-panel", {
97
+ status: "generated",
98
+ cellCount: frames.length,
99
+ canvasWidth: dimensions.width,
100
+ canvasHeight: dimensions.height,
101
+ imageBytes: artifact.byteSize,
102
+ });
103
+ return { artifact, dimensions, cacheHit: false };
104
+ }
105
+ finally {
106
+ await rm(working, { recursive: true, force: true });
107
+ }
108
+ }
109
+ }
110
+ //# sourceMappingURL=frame-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-panel.js","sourceRoot":"","sources":["../../../src/acquisition/frame-panel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { UrmaConfig } from "../config.js";
2
+ import type { InvestigationRef } from "../core/ids.js";
3
+ import type { ResolvedSource } from "../sources/types.js";
4
+ import { BlobStore } from "../store/blob-store.js";
5
+ import type { StoredArtifact, UrmaStore } from "../store/store.js";
6
+ import { MediaAcquirer } from "./media.js";
7
+ import type { RemoteOperationContext } from "../remote/worker.js";
8
+ export declare function exactFrameRequestKey(source: Pick<ResolvedSource, "sourceRef" | "revision">, atMs: number): string;
9
+ export type FrameTargetOutcome = Readonly<{
10
+ status: "success";
11
+ atMs: number;
12
+ artifact: StoredArtifact;
13
+ cacheHit: boolean;
14
+ }> | Readonly<{
15
+ status: "error";
16
+ atMs: number;
17
+ error: unknown;
18
+ }> | Readonly<{
19
+ status: "unfinished";
20
+ atMs: number;
21
+ }>;
22
+ export declare class FrameAcquirer {
23
+ #private;
24
+ readonly config: UrmaConfig;
25
+ readonly store: UrmaStore;
26
+ readonly blobs: BlobStore;
27
+ readonly remoteContext: RemoteOperationContext | null;
28
+ readonly media: MediaAcquirer;
29
+ constructor(config: UrmaConfig, store: UrmaStore, blobs: BlobStore, media?: MediaAcquirer, remoteContext?: RemoteOperationContext | null);
30
+ get(source: ResolvedSource, ref: InvestigationRef, timesMs: readonly number[], signal?: AbortSignal): Promise<Array<{
31
+ atMs: number;
32
+ artifact: StoredArtifact;
33
+ cacheHit: boolean;
34
+ }>>;
35
+ /** Keep successful sibling targets when one target fails; cancellation aborts the request */
36
+ getOutcomes(source: ResolvedSource, ref: InvestigationRef, timesMs: readonly number[], signal?: AbortSignal): Promise<readonly FrameTargetOutcome[]>;
37
+ }
@@ -0,0 +1,463 @@
1
+ import { mkdtemp, rm } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { currentExactFrameDiagnosticTrace, measureDiagnosticAsync, } from "../core/diagnostics.js";
4
+ import { normalizeError, UrmaError } from "../core/errors.js";
5
+ import { deterministicRequestKey } from "../core/request-key.js";
6
+ import { verifyPinnedLocalVideo } from "../sources/local.js";
7
+ import { Ffmpeg } from "../subprocess/ffmpeg.js";
8
+ import { collectBinaryVersions } from "../subprocess/versions.js";
9
+ import { BlobStore } from "../store/blob-store.js";
10
+ import { URMA_VERSION } from "../version.js";
11
+ import { MediaAcquirer } from "./media.js";
12
+ import { isTimestampCovered, parseStoredBoundedVideoCoverage, parseStoredVideoCoverage, physicalSeekMs, } from "./video-timing.js";
13
+ import { chooseFrameTransport, } from "./transport-policy.js";
14
+ function targetedDerivativeUnavailable(message, detail = {}) {
15
+ return new UrmaError("TARGETED_MEDIA_UNAVAILABLE", message, { detail });
16
+ }
17
+ export function exactFrameRequestKey(source, atMs) {
18
+ return deterministicRequestKey(source.revision, "frame", { sourceRef: source.sourceRef, atMs, format: "jpeg" }, "frame-extractor");
19
+ }
20
+ function mediaForGlobalTimestamp(artifact, mediaPath, globalTimeMs, transportCacheHit) {
21
+ if (artifact.startMs === null ||
22
+ artifact.endMs === null ||
23
+ globalTimeMs < artifact.startMs ||
24
+ globalTimeMs >= artifact.endMs) {
25
+ return null;
26
+ }
27
+ if (artifact.kind === "evidence_media") {
28
+ const coverage = parseStoredVideoCoverage(artifact.producer);
29
+ if (coverage === null)
30
+ return null;
31
+ const nominalLocalMs = globalTimeMs - artifact.startMs;
32
+ if (!isTimestampCovered(coverage, nominalLocalMs))
33
+ return null;
34
+ return {
35
+ path: mediaPath,
36
+ seekMs: physicalSeekMs(coverage, nominalLocalMs),
37
+ parent: artifact,
38
+ coverage,
39
+ transportCacheHit,
40
+ };
41
+ }
42
+ if (artifact.kind !== "media_section")
43
+ return null;
44
+ const coverage = parseStoredBoundedVideoCoverage(artifact.producer);
45
+ if (coverage === null)
46
+ return null;
47
+ const nominalLocalMs = globalTimeMs - artifact.startMs;
48
+ if (!isTimestampCovered(coverage, nominalLocalMs))
49
+ return null;
50
+ return {
51
+ path: mediaPath,
52
+ seekMs: physicalSeekMs(coverage, nominalLocalMs),
53
+ parent: artifact,
54
+ coverage,
55
+ transportCacheHit,
56
+ };
57
+ }
58
+ export class FrameAcquirer {
59
+ config;
60
+ store;
61
+ blobs;
62
+ remoteContext;
63
+ media;
64
+ constructor(config, store, blobs, media, remoteContext = null) {
65
+ this.config = config;
66
+ this.store = store;
67
+ this.blobs = blobs;
68
+ this.remoteContext = remoteContext;
69
+ this.media = media ?? new MediaAcquirer(config, store, blobs, undefined, remoteContext);
70
+ }
71
+ async get(source, ref, timesMs, signal) {
72
+ const outcomes = await this.#getOutcomes(source, ref, timesMs, signal, false);
73
+ return outcomes.map((outcome) => {
74
+ if (outcome.status === "success") {
75
+ return {
76
+ atMs: outcome.atMs,
77
+ artifact: outcome.artifact,
78
+ cacheHit: outcome.cacheHit,
79
+ };
80
+ }
81
+ if (outcome.status === "error")
82
+ throw normalizeError(outcome.error);
83
+ throw new UrmaError("INTERNAL_ERROR", `Exact-frame target ${outcome.atMs} ms was left unfinished by strict extraction`);
84
+ });
85
+ }
86
+ /** Keep successful sibling targets when one target fails; cancellation aborts the request */
87
+ async getOutcomes(source, ref, timesMs, signal) {
88
+ return await this.#getOutcomes(source, ref, timesMs, signal, true);
89
+ }
90
+ async #getOutcomes(source, ref, timesMs, signal, allowTargetErrors) {
91
+ const trace = currentExactFrameDiagnosticTrace();
92
+ trace?.setRequestedTimestamps(timesMs);
93
+ const frameIndexByTime = new Map();
94
+ for (const [index, atMs] of timesMs.entries()) {
95
+ if (!frameIndexByTime.has(atMs))
96
+ frameIndexByTime.set(atMs, index);
97
+ }
98
+ const frameIndexForTime = (atMs) => frameIndexByTime.get(atMs) ?? 0;
99
+ const recordSelection = (atMs, media) => {
100
+ const index = frameIndexForTime(atMs);
101
+ trace?.markFrameSelection(index, atMs, {
102
+ path: media.parent === null
103
+ ? "local-direct"
104
+ : media.parent.kind === "media_section"
105
+ ? "bounded-section"
106
+ : "reusable-evidence",
107
+ transportCacheHit: media.transportCacheHit,
108
+ sectionStartMs: media.parent?.startMs ?? null,
109
+ sectionEndMs: media.parent?.endMs ?? null,
110
+ physicalSeekMs: media.seekMs,
111
+ coverage: media.coverage === null ? null : {
112
+ startSeconds: media.coverage.startSeconds,
113
+ endSeconds: media.coverage.endSeconds,
114
+ startPts: media.coverage.startPts,
115
+ endPts: media.coverage.endPts,
116
+ durationTs: media.coverage.durationTs,
117
+ timeBase: media.coverage.timeBase,
118
+ },
119
+ });
120
+ if (media.parent?.kind === "media_section") {
121
+ trace?.markCacheStatus(index, atMs, "reusable", "not-needed");
122
+ }
123
+ };
124
+ const results = [];
125
+ const targetErrors = new Map();
126
+ const markTargetError = (atMs, error) => {
127
+ targetErrors.set(atMs, error);
128
+ const normalized = normalizeError(error);
129
+ trace?.markFrameStatus(frameIndexForTime(atMs), atMs, normalized.code === "CANCELLED" ? "cancelled" : "failed", normalized.code);
130
+ };
131
+ const finishOutcomes = () => timesMs.map((atMs) => {
132
+ const error = targetErrors.get(atMs);
133
+ if (error !== undefined) {
134
+ return { status: "error", atMs, error };
135
+ }
136
+ const result = results.find((item) => item.atMs === atMs);
137
+ if (result) {
138
+ return {
139
+ status: "success",
140
+ atMs,
141
+ artifact: result.artifact,
142
+ cacheHit: result.cacheHit,
143
+ };
144
+ }
145
+ return { status: "unfinished", atMs };
146
+ });
147
+ const missing = [];
148
+ for (const [index, atMs] of timesMs.entries()) {
149
+ trace?.ensureFrame(index, atMs);
150
+ const lookupStarted = performance.now();
151
+ let cacheHit = false;
152
+ try {
153
+ const key = exactFrameRequestKey(source, atMs);
154
+ const artifact = this.store.getArtifactByRequest(key);
155
+ if (artifact) {
156
+ try {
157
+ await this.blobs.verify(artifact.artifactId, artifact.blobPath);
158
+ results.push({ atMs, artifact, cacheHit: true });
159
+ cacheHit = true;
160
+ }
161
+ catch {
162
+ }
163
+ }
164
+ }
165
+ finally {
166
+ const elapsedMs = performance.now() - lookupStarted;
167
+ trace?.addStage("exactFrameCacheLookupMs", elapsedMs);
168
+ trace?.addFrameStage(index, "exactFrameCacheLookupMs", elapsedMs);
169
+ }
170
+ trace?.markExactFrameCache(index, atMs, cacheHit);
171
+ if (!cacheHit)
172
+ missing.push(atMs);
173
+ }
174
+ if (missing.length === 0)
175
+ return finishOutcomes();
176
+ const mediaFor = new Map();
177
+ const acquireReusable = async (requestedTimes) => {
178
+ if (requestedTimes.length === 0)
179
+ return;
180
+ try {
181
+ const reusable = await this.media.reusableEvidence(source, ref, signal);
182
+ for (const time of requestedTimes) {
183
+ const media = mediaForGlobalTimestamp(reusable.artifact, reusable.path, time, reusable.cacheHit);
184
+ if (media === null) {
185
+ const error = targetedDerivativeUnavailable(`Reusable evidence media does not provide validated timing coverage for target ${time} ms`, { reason: "reusable-coverage-miss", targetMs: time });
186
+ if (!allowTargetErrors)
187
+ throw error;
188
+ markTargetError(time, error);
189
+ continue;
190
+ }
191
+ mediaFor.set(time, media);
192
+ recordSelection(time, media);
193
+ }
194
+ }
195
+ catch (error) {
196
+ const normalized = normalizeError(error);
197
+ if (!allowTargetErrors || normalized.code === "CANCELLED")
198
+ throw error;
199
+ for (const time of requestedTimes)
200
+ markTargetError(time, normalized);
201
+ }
202
+ };
203
+ if (source.kind === "local") {
204
+ let pinnedPath;
205
+ try {
206
+ pinnedPath = await verifyPinnedLocalVideo(source.safeMetadata.localSnapshot, this.blobs);
207
+ }
208
+ catch (error) {
209
+ if (!allowTargetErrors)
210
+ throw error;
211
+ for (const time of missing)
212
+ markTargetError(time, error);
213
+ pinnedPath = "";
214
+ }
215
+ const rawTiming = source.safeMetadata.videoTiming;
216
+ const coverage = typeof rawTiming === "object" &&
217
+ rawTiming !== null && !Array.isArray(rawTiming)
218
+ ? parseStoredVideoCoverage(rawTiming)
219
+ : null;
220
+ if (pinnedPath && coverage === null) {
221
+ const error = new UrmaError("MEDIA_INVALID", "Local source has no valid retained video PTS coverage; the exact target is unavailable", { detail: { reason: "local-timing-unavailable" } });
222
+ if (!allowTargetErrors)
223
+ throw error;
224
+ for (const time of missing)
225
+ markTargetError(time, error);
226
+ }
227
+ else if (pinnedPath && coverage !== null) {
228
+ for (const time of missing) {
229
+ if (!isTimestampCovered(coverage, time)) {
230
+ const error = targetedDerivativeUnavailable(`Local source timing coverage does not include target ${time} ms`, { reason: "local-coverage-miss", targetMs: time });
231
+ if (!allowTargetErrors)
232
+ throw error;
233
+ markTargetError(time, error);
234
+ continue;
235
+ }
236
+ const media = {
237
+ path: pinnedPath,
238
+ seekMs: physicalSeekMs(coverage, time),
239
+ parent: null,
240
+ coverage,
241
+ transportCacheHit: false,
242
+ };
243
+ mediaFor.set(time, media);
244
+ recordSelection(time, media);
245
+ }
246
+ }
247
+ }
248
+ else {
249
+ const cached = this.store
250
+ .listArtifacts(source.sourceRef, source.revision)
251
+ .filter((artifact) => (artifact.kind === "evidence_media" ||
252
+ artifact.kind === "media_section") &&
253
+ artifact.startMs !== null &&
254
+ artifact.endMs !== null)
255
+ .sort((a, b) => a.endMs - a.startMs - (b.endMs - b.startMs) ||
256
+ a.createdAt.localeCompare(b.createdAt));
257
+ const verified = new Map();
258
+ for (const time of missing) {
259
+ const lookupStarted = performance.now();
260
+ let selected = false;
261
+ try {
262
+ for (const artifact of cached) {
263
+ if (artifact.startMs === null ||
264
+ artifact.endMs === null ||
265
+ time < artifact.startMs ||
266
+ time >= artifact.endMs) {
267
+ continue;
268
+ }
269
+ const candidateStarted = performance.now();
270
+ try {
271
+ let cachedPath = verified.get(artifact.artifactId);
272
+ if (cachedPath === undefined) {
273
+ try {
274
+ cachedPath = await this.blobs.verify(artifact.artifactId, artifact.blobPath);
275
+ }
276
+ catch {
277
+ cachedPath = null;
278
+ }
279
+ verified.set(artifact.artifactId, cachedPath);
280
+ }
281
+ if (cachedPath) {
282
+ const selection = mediaForGlobalTimestamp(artifact, cachedPath, time, true);
283
+ if (selection) {
284
+ mediaFor.set(time, selection);
285
+ recordSelection(time, selection);
286
+ selected = true;
287
+ }
288
+ }
289
+ }
290
+ finally {
291
+ const elapsedMs = performance.now() - candidateStarted;
292
+ if (artifact.kind === "media_section") {
293
+ trace?.addStage("boundedArtifactCacheLookupMs", elapsedMs);
294
+ }
295
+ else {
296
+ trace?.addStage("reusableArtifactCacheLookupMs", elapsedMs);
297
+ }
298
+ }
299
+ if (selected)
300
+ break;
301
+ }
302
+ }
303
+ finally {
304
+ trace?.addStage("artifactCacheLookupMs", performance.now() - lookupStarted);
305
+ }
306
+ }
307
+ const pending = missing.filter((time) => !mediaFor.has(time) && !targetErrors.has(time));
308
+ const policy = chooseFrameTransport(source);
309
+ for (const time of pending) {
310
+ const index = frameIndexForTime(time);
311
+ if (policy.primary === "hls-bounded-section") {
312
+ trace?.markCacheStatus(index, time, "bounded", "miss");
313
+ trace?.markCacheStatus(index, time, "reusable", "miss");
314
+ }
315
+ else {
316
+ trace?.markCacheStatus(index, time, "reusable", "miss");
317
+ }
318
+ }
319
+ if (pending.length > 0 && policy.primary === "hls-bounded-section") {
320
+ const intervals = pending.map((time) => ({
321
+ startMs: Math.max(0, time - 2_000),
322
+ endMs: Math.min(source.durationMs, time + 2_001),
323
+ times: [time],
324
+ }));
325
+ const groups = [];
326
+ for (const interval of intervals.sort((a, b) => a.startMs - b.startMs)) {
327
+ const previous = groups.at(-1);
328
+ if (previous && interval.startMs <= previous.endMs) {
329
+ previous.endMs = Math.max(previous.endMs, interval.endMs);
330
+ previous.times.push(...interval.times);
331
+ }
332
+ else
333
+ groups.push(interval);
334
+ }
335
+ for (const group of groups) {
336
+ for (const time of group.times) {
337
+ trace?.markRequestedSection(frameIndexForTime(time), time, group.startMs, group.endMs);
338
+ }
339
+ }
340
+ let outcomes;
341
+ try {
342
+ outcomes = await this.media.sections(groups.map((group) => ({
343
+ source,
344
+ investigationRef: ref,
345
+ startMs: group.startMs,
346
+ endMs: group.endMs,
347
+ })), signal);
348
+ }
349
+ catch (error) {
350
+ const normalized = normalizeError(error);
351
+ if (!allowTargetErrors || normalized.code === "CANCELLED") {
352
+ throw error;
353
+ }
354
+ for (const group of groups) {
355
+ for (const time of group.times)
356
+ markTargetError(time, normalized);
357
+ }
358
+ outcomes = [];
359
+ }
360
+ for (const [index, outcome] of outcomes.entries()) {
361
+ const group = groups[index];
362
+ if (outcome.status === "fulfilled") {
363
+ for (const time of group.times) {
364
+ const selection = mediaForGlobalTimestamp(outcome.value.artifact, outcome.value.path, time, outcome.value.cacheHit);
365
+ if (selection) {
366
+ mediaFor.set(time, selection);
367
+ recordSelection(time, selection);
368
+ }
369
+ else {
370
+ const error = new UrmaError("TARGETED_MEDIA_UNAVAILABLE", `Bounded section [${group.startMs},${group.endMs}) does not cover target ${time} ms`, {
371
+ detail: {
372
+ reason: "bounded-coverage-miss",
373
+ targetMs: time,
374
+ sectionStartMs: group.startMs,
375
+ sectionEndMs: group.endMs,
376
+ },
377
+ });
378
+ if (!allowTargetErrors)
379
+ throw error;
380
+ markTargetError(time, error);
381
+ }
382
+ }
383
+ }
384
+ else {
385
+ const normalized = normalizeError(outcome.reason);
386
+ if (!allowTargetErrors || normalized.code === "CANCELLED") {
387
+ throw normalized;
388
+ }
389
+ for (const time of group.times)
390
+ markTargetError(time, normalized);
391
+ }
392
+ }
393
+ }
394
+ else if (pending.length > 0) {
395
+ await acquireReusable(pending);
396
+ }
397
+ }
398
+ const extractable = missing.filter((atMs) => mediaFor.has(atMs) && !targetErrors.has(atMs));
399
+ if (extractable.length === 0)
400
+ return finishOutcomes();
401
+ const working = await mkdtemp(path.join(this.config.dataDir, "tmp-frame-"));
402
+ try {
403
+ const ffmpeg = new Ffmpeg(this.config);
404
+ const versions = await collectBinaryVersions(this.config, ["ffmpeg"], signal);
405
+ const extractAndStore = async (atMs, media, outputIndex, frameIndex) => {
406
+ const output = path.join(working, `frame-${outputIndex}.jpg`);
407
+ await measureDiagnosticAsync(trace, "ffmpegExactFrameExtractionMs", () => ffmpeg.extractJpeg(media.path, media.seekMs, output, signal), frameIndex);
408
+ await measureDiagnosticAsync(trace, "jpegValidationMs", async () => {
409
+ await ffmpeg.validateJpeg(output);
410
+ }, frameIndex);
411
+ const blob = await measureDiagnosticAsync(trace, "canonicalExactFrameArtifactCommitMs", () => this.blobs.putFile(output, async (file) => {
412
+ await measureDiagnosticAsync(trace, "jpegValidationMs", () => ffmpeg.validateJpeg(file), frameIndex);
413
+ }), frameIndex);
414
+ const requestKey = exactFrameRequestKey(source, atMs);
415
+ const artifact = {
416
+ artifactId: blob.artifactId,
417
+ sourceRef: source.sourceRef,
418
+ sourceRevision: source.revision,
419
+ kind: "frame",
420
+ role: "evidence",
421
+ mimeType: "image/jpeg",
422
+ sha256: blob.sha256,
423
+ byteSize: blob.byteSize,
424
+ blobPath: blob.relativePath,
425
+ startMs: atMs,
426
+ endMs: atMs,
427
+ params: { atMs, format: "jpeg" },
428
+ producer: {
429
+ version: "frame-extractor",
430
+ urmaVersion: URMA_VERSION,
431
+ ...versions,
432
+ transportArtifactId: media.parent?.artifactId ?? null,
433
+ },
434
+ createdAt: new Date().toISOString(),
435
+ };
436
+ await measureDiagnosticAsync(trace, "canonicalExactFrameArtifactCommitMs", async () => {
437
+ this.store.putArtifact(artifact, { requestKey, operation: "frame" }, media.parent ? [media.parent.artifactId] : []);
438
+ });
439
+ results.push({ atMs, artifact, cacheHit: false });
440
+ trace?.markFrameStatus(frameIndex, atMs, "succeeded");
441
+ };
442
+ for (const [index, atMs] of extractable.entries()) {
443
+ const media = mediaFor.get(atMs);
444
+ try {
445
+ await extractAndStore(atMs, media, index, frameIndexForTime(atMs));
446
+ }
447
+ catch (error) {
448
+ const normalized = normalizeError(error);
449
+ if (!allowTargetErrors || normalized.code === "CANCELLED") {
450
+ trace?.markFrameStatus(frameIndexForTime(atMs), atMs, normalized.code === "CANCELLED" ? "cancelled" : "failed", normalized.code);
451
+ throw normalized;
452
+ }
453
+ markTargetError(atMs, normalized);
454
+ }
455
+ }
456
+ }
457
+ finally {
458
+ await rm(working, { recursive: true, force: true });
459
+ }
460
+ return finishOutcomes();
461
+ }
462
+ }
463
+ //# sourceMappingURL=frames.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frames.js","sourceRoot":"","sources":["../../../src/acquisition/frames.ts"],"names":[],"mappings":"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"}