@camstack/addon-post-analysis 1.2.91 → 1.2.93

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.
@@ -29,7 +29,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
29
  enumerable: true
30
30
  }) : target, mod));
31
31
  //#endregion
32
- //#region ../types/dist/event-category-C0lyLd5U.mjs
32
+ //#region ../types/dist/event-category-XfKNtfCc.mjs
33
33
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
34
34
  EventCategory["SystemBoot"] = "system.boot";
35
35
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -68,6 +68,22 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
68
68
  EventCategory["AddonInstalled"] = "addon.installed";
69
69
  EventCategory["AddonUninstalled"] = "addon.uninstalled";
70
70
  EventCategory["AddonCrashed"] = "addon.crashed";
71
+ /**
72
+ * A RUNNER the D6 crash circuit-breaker gave up on — terminal.
73
+ *
74
+ * `AddonCrashed` is the routine, self-healing fact ("it crashed; it is being
75
+ * respawned"); this is the one that never resolves itself. Emitted exactly
76
+ * once per trip, by `process-service.ts`, carrying the node, the runner, the
77
+ * addons it hosted and the crash count that tripped the breaker.
78
+ *
79
+ * It exists because a runner marked terminally `failed` used to be SILENT:
80
+ * on 2026-08-18 the `recorder` runner died of three unhandled ffmpeg spawn
81
+ * errors, the breaker stopped respawning it (correctly), `/health` kept
82
+ * returning 200, and fleet-wide recording was gone for 3h15 before the
83
+ * operator's phone told him. The Notification Center's system-event intake
84
+ * consumes this category and maps it to the `addon-crash-loop` kind.
85
+ */
86
+ EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
71
87
  EventCategory["AddonError"] = "addon.error";
72
88
  EventCategory["AddonPageReady"] = "addon.page-ready";
73
89
  EventCategory["AddonWidgetReady"] = "addon.widget-ready";
@@ -14845,6 +14861,7 @@ var NcSystemEventKindSchema = _enum([
14845
14861
  "node-offline",
14846
14862
  "node-inference-unavailable",
14847
14863
  "detection-blind",
14864
+ "addon-crash-loop",
14848
14865
  "addon-update-available",
14849
14866
  "server-update-available",
14850
14867
  "alarm-triggered",
@@ -15970,6 +15987,10 @@ var NC_CONDITION_CATALOG = [
15970
15987
  value: "detection-blind",
15971
15988
  label: "Camera detecting nothing"
15972
15989
  },
15990
+ {
15991
+ value: "addon-crash-loop",
15992
+ label: "Addon stopped after repeated crashes"
15993
+ },
15973
15994
  {
15974
15995
  value: "addon-update-available",
15975
15996
  label: "Addon update available"
@@ -21487,20 +21508,6 @@ var VectorStatsResultSchema = object({
21487
21508
  exact: boolean()
21488
21509
  });
21489
21510
  method(VectorDeclareIndexInputSchema, _void(), { kind: "mutation" }), method(VectorUpsertInputSchema, VectorUpsertResultSchema, { kind: "mutation" }), method(VectorQueryInputSchema, VectorQueryResultSchema), method(VectorGetInputSchema, VectorGetResultSchema), method(VectorDeleteInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorDeleteByFilterInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorStatsInputSchema, VectorStatsResultSchema);
21490
- /**
21491
- * `videoclips` — the unified, navigable-clip surface for a camera.
21492
- *
21493
- * A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
21494
- * provider per device, substitutable. The DEFAULT provider (registered by
21495
- * `addon-post-analysis`, `defaultActive: true`) composes the analytics event
21496
- * log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
21497
- * is a time-WINDOW over existing footage, never a separate file. A camera that
21498
- * exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
21499
- * wrapper provider for its device and serve its own clip catalog + URLs.
21500
- *
21501
- * A `Clip` is purely time-based (subtree-blind): playback resolves segments by
21502
- * temporal overlap, so the API never decides `continuous` vs `events`.
21503
- */
21504
21511
  var ClipSchema = object({
21505
21512
  /** Opaque, provider-namespaced id. The default provider encodes the time
21506
21513
  * window so `getClipPlayback` is self-contained (no event re-query). */
@@ -21526,12 +21533,41 @@ var ClipSchema = object({
21526
21533
  * of the event that owns `kind` (object > motion > audio). Do not extract
21527
21534
  * a keyframe from the recorded segments. Other providers (onboard, HKSV)
21528
21535
  * mint their own stills.
21536
+ *
21537
+ * **VOUCHED, never fabricated.** A provider emits this only for an event it
21538
+ * has CONFIRMED owns at least one media row (its own, or its owning track's).
21539
+ * Absent is meaningful — "this visit has no event still" — never "we did not
21540
+ * look". Stamping it from a URL template made 35% of one camera's clips point
21541
+ * at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
21542
+ * A read that FAILS drops the claim; it never invents it.
21529
21543
  */
21530
21544
  thumbnail: string().optional(),
21531
- /** Analytics event ids that overlap this visit. Empty on footage-only clips.
21532
- * The default provider's visit grain puts many motion heartbeats on one clip
21533
- * instead of minting one clip per marker. */
21545
+ /**
21546
+ * An instant INSIDE this visit's footage, hole-safe, where a recorded still
21547
+ * can be decoded. Present whenever the visit came from recorded availability;
21548
+ * absent on a per-event padded window (there is no footage to promise).
21549
+ *
21550
+ * This is not a thumbnail and not a second byte path: it is the argument to
21551
+ * the recorder's existing still route. The surface — never the provider —
21552
+ * decides whether to use it. It is the midpoint of the visit's LONGEST
21553
+ * contiguous range, not of the visit: a visit spans its holes by
21554
+ * construction, so a naive midpoint lands in dead air.
21555
+ */
21556
+ stillAtMs: number().optional(),
21557
+ /**
21558
+ * Analytics event ids that overlap this visit — a BOUNDED sample, newest
21559
+ * first within kind (object → motion → audio), capped at
21560
+ * {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
21561
+ *
21562
+ * Bounded because it is not a payload the surface pages through: one visit on
21563
+ * device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
21564
+ * camera-day. Read {@link eventCount} for the true total.
21565
+ */
21534
21566
  eventIds: array(string()).optional(),
21567
+ /** How many analytics events actually overlap this visit. Differs from
21568
+ * `eventIds.length` exactly when the sample was capped — so a truncated
21569
+ * list is never mistaken for a quiet visit. */
21570
+ eventCount: number().int().nonnegative().optional(),
21535
21571
  /** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
21536
21572
  * than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
21537
21573
  * bar keeps showing them via `recording.getAvailability`. */
@@ -38553,7 +38589,7 @@ function systemEventFilterApplies(kind, filter) {
38553
38589
  switch (filter) {
38554
38590
  case "deviceIds": return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind === "alarm-triggered" || kind === "export-completed";
38555
38591
  case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind";
38556
- case "nodeIds": return kind.startsWith("node-") || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "server-updated";
38592
+ case "nodeIds": return kind.startsWith("node-") || kind === "addon-crash-loop" || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "server-updated";
38557
38593
  case "packageNames": return kind.endsWith("update-available") || kind === "addon-updated" || kind === "server-updated";
38558
38594
  }
38559
38595
  }
@@ -39010,6 +39046,303 @@ function cosineSimilarity(a, b) {
39010
39046
  function hfModelUrl(repo, path) {
39011
39047
  return `https://huggingface.co/${repo}/resolve/main/${path}`;
39012
39048
  }
39049
+ var MB = 1024 * 1024;
39050
+ var DEFAULT_POOL_MEMORY_POLICY = {
39051
+ sampleIntervalMs: 6e4,
39052
+ baselineSettleSamples: 5,
39053
+ baselineSampleCount: 3,
39054
+ restartMultiple: 4,
39055
+ floorBytes: 1024 * MB,
39056
+ ceilingBytes: 3072 * MB,
39057
+ cooldownMs: 30 * 6e4,
39058
+ maxRestartsPerWindow: 6,
39059
+ restartWindowMs: 1440 * 6e4
39060
+ };
39061
+ /**
39062
+ * Resolve the policy from env overrides (`CAMSTACK_POOL_MEM_*`). Garbage or
39063
+ * absent values keep the default — an operator typo must never disable the
39064
+ * bound or set it to zero.
39065
+ */
39066
+ function resolvePoolMemoryPolicy(env) {
39067
+ const num = (key, fallback, min) => {
39068
+ const raw = env[key];
39069
+ if (raw === void 0) return fallback;
39070
+ const parsed = Number(raw);
39071
+ return Number.isFinite(parsed) && parsed >= min ? parsed : fallback;
39072
+ };
39073
+ const d = DEFAULT_POOL_MEMORY_POLICY;
39074
+ return {
39075
+ sampleIntervalMs: num("CAMSTACK_POOL_MEM_INTERVAL_MS", d.sampleIntervalMs, 5e3),
39076
+ baselineSettleSamples: d.baselineSettleSamples,
39077
+ baselineSampleCount: d.baselineSampleCount,
39078
+ restartMultiple: num("CAMSTACK_POOL_MEM_MULTIPLE", d.restartMultiple, 1.5),
39079
+ floorBytes: num("CAMSTACK_POOL_MEM_FLOOR_MB", d.floorBytes / MB, 128) * MB,
39080
+ ceilingBytes: num("CAMSTACK_POOL_MEM_CEILING_MB", d.ceilingBytes / MB, 256) * MB,
39081
+ cooldownMs: num("CAMSTACK_POOL_MEM_COOLDOWN_MS", d.cooldownMs, 6e4),
39082
+ maxRestartsPerWindow: num("CAMSTACK_POOL_MEM_MAX_RESTARTS", d.maxRestartsPerWindow, 1),
39083
+ restartWindowMs: num("CAMSTACK_POOL_MEM_RESTART_WINDOW_MS", d.restartWindowMs, 6e4)
39084
+ };
39085
+ }
39086
+ /** Parse the fields this watchdog needs out of `/proc/<pid>/status` text.
39087
+ * Returns null when VmRSS is missing (dead pid, kernel thread, bad read). */
39088
+ function parseProcStatus(text) {
39089
+ const kb = (label) => {
39090
+ const match = text.match(new RegExp(`^${label}:\\s+(\\d+)\\s*kB`, "m"));
39091
+ return match ? Number(match[1]) * 1024 : null;
39092
+ };
39093
+ const rssBytes = kb("VmRSS");
39094
+ if (rssBytes === null) return null;
39095
+ const threadsMatch = text.match(/^Threads:\s+(\d+)/m);
39096
+ return {
39097
+ rssBytes,
39098
+ vmBytes: kb("VmSize") ?? 0,
39099
+ hwmBytes: kb("VmHWM") ?? 0,
39100
+ swapBytes: kb("VmSwap") ?? 0,
39101
+ threads: threadsMatch ? Number(threadsMatch[1]) : 0
39102
+ };
39103
+ }
39104
+ function initialPoolMemoryState() {
39105
+ return {
39106
+ settleSeen: 0,
39107
+ baselineWindow: [],
39108
+ baselineBytes: null,
39109
+ restartsAt: [],
39110
+ lastRestartAt: null
39111
+ };
39112
+ }
39113
+ function median(values) {
39114
+ const sorted = [...values].sort((a, b) => a - b);
39115
+ return sorted[Math.floor(sorted.length / 2)];
39116
+ }
39117
+ function advanceBaseline(state, rssBytes, policy) {
39118
+ if (state.baselineBytes !== null) return state;
39119
+ if (state.settleSeen < policy.baselineSettleSamples) return {
39120
+ ...state,
39121
+ settleSeen: state.settleSeen + 1
39122
+ };
39123
+ const window = [...state.baselineWindow, rssBytes];
39124
+ if (window.length < policy.baselineSampleCount) return {
39125
+ ...state,
39126
+ baselineWindow: window
39127
+ };
39128
+ return {
39129
+ ...state,
39130
+ baselineWindow: window,
39131
+ baselineBytes: median(window)
39132
+ };
39133
+ }
39134
+ /** The one place a pool's restart threshold is computed. */
39135
+ function poolMemoryThreshold(baselineBytes, policy) {
39136
+ if (baselineBytes === null) return policy.ceilingBytes;
39137
+ return Math.min(policy.ceilingBytes, Math.max(policy.floorBytes, policy.restartMultiple * baselineBytes));
39138
+ }
39139
+ function pruneRestarts(restartsAt, nowMs, policy) {
39140
+ return restartsAt.filter((t) => nowMs - t < policy.restartWindowMs);
39141
+ }
39142
+ /**
39143
+ * Evaluate one RSS sample. Pure: returns the successor state plus the verdict.
39144
+ * The caller performs (and logs) the restart, then commits it via
39145
+ * {@link commitWatchdogRestart}.
39146
+ */
39147
+ function evaluatePoolMemory(state, rssBytes, nowMs, policy) {
39148
+ const next = advanceBaseline(state, rssBytes, policy);
39149
+ const thresholdBytes = poolMemoryThreshold(next.baselineBytes, policy);
39150
+ if (rssBytes <= thresholdBytes) return {
39151
+ state: next,
39152
+ action: next.baselineBytes === null ? "baseline-pending" : "ok",
39153
+ baselineBytes: next.baselineBytes,
39154
+ thresholdBytes
39155
+ };
39156
+ const inWindow = pruneRestarts(next.restartsAt, nowMs, policy);
39157
+ const pruned = {
39158
+ ...next,
39159
+ restartsAt: inWindow
39160
+ };
39161
+ if (inWindow.length >= policy.maxRestartsPerWindow) return {
39162
+ state: pruned,
39163
+ action: "exhausted",
39164
+ baselineBytes: next.baselineBytes,
39165
+ thresholdBytes
39166
+ };
39167
+ if (pruned.lastRestartAt !== null && nowMs - pruned.lastRestartAt < policy.cooldownMs) return {
39168
+ state: pruned,
39169
+ action: "cooldown",
39170
+ baselineBytes: next.baselineBytes,
39171
+ thresholdBytes
39172
+ };
39173
+ return {
39174
+ state: pruned,
39175
+ action: "restart",
39176
+ baselineBytes: next.baselineBytes,
39177
+ thresholdBytes
39178
+ };
39179
+ }
39180
+ /** Record a performed watchdog restart: budget consumed, baseline reset —
39181
+ * the recreated pool is a NEW process and gets a fresh settle window. */
39182
+ function commitWatchdogRestart(state, nowMs) {
39183
+ return {
39184
+ ...initialPoolMemoryState(),
39185
+ restartsAt: [...state.restartsAt, nowMs],
39186
+ lastRestartAt: nowMs
39187
+ };
39188
+ }
39189
+ /** Reset baseline tracking (pool process replaced OUTSIDE the watchdog —
39190
+ * kernel OOM kill + respawn, idle-reaper eviction, tuning respawn). The
39191
+ * restart budget is kept: it bounds the WATCHDOG, not the pool. */
39192
+ function resetPoolBaseline(state) {
39193
+ return {
39194
+ ...initialPoolMemoryState(),
39195
+ restartsAt: state.restartsAt,
39196
+ lastRestartAt: state.lastRestartAt
39197
+ };
39198
+ }
39199
+ /**
39200
+ * Pick ONE pool to restart this sweep — the worst overage ratio. Restarting
39201
+ * several pools at once (e.g. after a model rollout grew every baseline)
39202
+ * would take detection down on every camera simultaneously; one per sweep
39203
+ * means the survivors keep serving while the worst offender reloads, and the
39204
+ * next sweep (one interval later) takes the next one.
39205
+ */
39206
+ function pickRestartCandidate(candidates) {
39207
+ if (candidates.length === 0) return null;
39208
+ let worst = candidates[0];
39209
+ for (const c of candidates) if (c.rssBytes / c.thresholdBytes > worst.rssBytes / worst.thresholdBytes) worst = c;
39210
+ return worst.key;
39211
+ }
39212
+ var PoolMemoryWatchdog = class {
39213
+ pools = /* @__PURE__ */ new Map();
39214
+ timer = null;
39215
+ sweeping = false;
39216
+ stopped = false;
39217
+ opts;
39218
+ now;
39219
+ setTimer;
39220
+ clearTimer;
39221
+ constructor(opts) {
39222
+ this.opts = opts;
39223
+ this.now = opts.now ?? (() => Date.now());
39224
+ this.setTimer = opts.setTimer ?? ((fn, ms) => setTimeout(fn, ms));
39225
+ this.clearTimer = opts.clearTimer ?? ((t) => clearTimeout(t));
39226
+ }
39227
+ start() {
39228
+ if (this.timer || this.stopped) return;
39229
+ this.arm();
39230
+ }
39231
+ stop() {
39232
+ this.stopped = true;
39233
+ if (this.timer) {
39234
+ this.clearTimer(this.timer);
39235
+ this.timer = null;
39236
+ }
39237
+ }
39238
+ arm() {
39239
+ const timer = this.setTimer(() => {
39240
+ this.sweep().finally(() => {
39241
+ if (!this.stopped) this.arm();
39242
+ });
39243
+ }, this.opts.policy.sampleIntervalMs);
39244
+ if (typeof timer.unref === "function") timer.unref();
39245
+ this.timer = timer;
39246
+ }
39247
+ /** One sweep: sample → log every pool → restart at most one. Public so the
39248
+ * loop is testable without fake global timers. */
39249
+ async sweep() {
39250
+ if (this.sweeping) return;
39251
+ this.sweeping = true;
39252
+ try {
39253
+ await this.doSweep();
39254
+ } catch (err) {
39255
+ this.opts.log.warn("pool memory sweep failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
39256
+ } finally {
39257
+ this.sweeping = false;
39258
+ }
39259
+ }
39260
+ async doSweep() {
39261
+ const nowMs = this.now();
39262
+ const samples = await this.opts.sample();
39263
+ const candidates = [];
39264
+ const verdictByKey = /* @__PURE__ */ new Map();
39265
+ for (const t of samples) {
39266
+ const tracked = this.pools.get(t.key);
39267
+ let state = tracked?.state ?? initialPoolMemoryState();
39268
+ if (tracked && tracked.pids.length > 0 && !samePids(tracked.pids, t.pids)) {
39269
+ this.opts.log.warn("pool process changed outside the watchdog — re-baselining", { meta: {
39270
+ poolKey: t.key,
39271
+ previousPids: tracked.pids,
39272
+ pids: t.pids
39273
+ } });
39274
+ state = resetPoolBaseline(state);
39275
+ }
39276
+ const verdict = evaluatePoolMemory(state, t.rssBytes, nowMs, this.opts.policy);
39277
+ this.pools.set(t.key, {
39278
+ state: verdict.state,
39279
+ pids: t.pids
39280
+ });
39281
+ verdictByKey.set(t.key, verdict);
39282
+ this.opts.log.info("pool memory", { meta: {
39283
+ poolKey: t.key,
39284
+ pids: t.pids,
39285
+ rssMb: Math.round(t.rssBytes / MB),
39286
+ baselineMb: verdict.baselineBytes === null ? null : Math.round(verdict.baselineBytes / MB),
39287
+ thresholdMb: Math.round(verdict.thresholdBytes / MB),
39288
+ action: verdict.action,
39289
+ ...t.meta
39290
+ } });
39291
+ if (verdict.action === "restart") candidates.push({
39292
+ key: t.key,
39293
+ rssBytes: t.rssBytes,
39294
+ thresholdBytes: verdict.thresholdBytes
39295
+ });
39296
+ else if (verdict.action === "cooldown") this.opts.log.warn("pool over memory threshold but inside restart cooldown", { meta: {
39297
+ poolKey: t.key,
39298
+ rssMb: Math.round(t.rssBytes / MB),
39299
+ thresholdMb: Math.round(verdict.thresholdBytes / MB),
39300
+ cooldownMs: this.opts.policy.cooldownMs
39301
+ } });
39302
+ else if (verdict.action === "exhausted") this.opts.log.error("pool memory watchdog gave up — restart budget exhausted, pool leaks faster than restarts can pay for; needs a heap profile (py-spy / tracemalloc)", { meta: {
39303
+ poolKey: t.key,
39304
+ rssMb: Math.round(t.rssBytes / MB),
39305
+ thresholdMb: Math.round(verdict.thresholdBytes / MB),
39306
+ maxRestartsPerWindow: this.opts.policy.maxRestartsPerWindow,
39307
+ restartWindowMs: this.opts.policy.restartWindowMs
39308
+ } });
39309
+ }
39310
+ for (const key of [...this.pools.keys()]) if (!samples.some((t) => t.key === key)) this.pools.delete(key);
39311
+ const pickedKey = pickRestartCandidate(candidates);
39312
+ if (pickedKey === null) return;
39313
+ const picked = candidates.find((c) => c.key === pickedKey);
39314
+ const verdict = verdictByKey.get(pickedKey);
39315
+ const tracked = this.pools.get(pickedKey);
39316
+ const restartsInWindow = tracked.state.restartsAt.length + 1;
39317
+ this.opts.log.warn("pool memory watchdog restarting pool — RSS over threshold", { meta: {
39318
+ poolKey: pickedKey,
39319
+ pids: tracked.pids,
39320
+ rssMb: Math.round(picked.rssBytes / MB),
39321
+ thresholdMb: Math.round(picked.thresholdBytes / MB),
39322
+ baselineMb: verdict.baselineBytes === null ? null : Math.round(verdict.baselineBytes / MB),
39323
+ restartsInWindow,
39324
+ deferredCandidates: candidates.filter((c) => c.key !== pickedKey).map((c) => c.key)
39325
+ } });
39326
+ try {
39327
+ await this.opts.restart(pickedKey);
39328
+ this.pools.set(pickedKey, {
39329
+ state: commitWatchdogRestart(tracked.state, this.now()),
39330
+ pids: []
39331
+ });
39332
+ } catch (err) {
39333
+ this.opts.log.error("pool memory watchdog restart failed", { meta: {
39334
+ poolKey: pickedKey,
39335
+ error: err instanceof Error ? err.message : String(err)
39336
+ } });
39337
+ }
39338
+ }
39339
+ };
39340
+ function samePids(a, b) {
39341
+ if (a.length !== b.length) return false;
39342
+ const sortedA = [...a].sort((x, y) => x - y);
39343
+ const sortedB = [...b].sort((x, y) => x - y);
39344
+ return sortedA.every((v, i) => v === sortedB[i]);
39345
+ }
39013
39346
  /**
39014
39347
  * Vector wire codec — base64 of little-endian Float32.
39015
39348
  *
@@ -39219,6 +39552,12 @@ Object.defineProperty(exports, "OpsLogEntrySchema", {
39219
39552
  return OpsLogEntrySchema;
39220
39553
  }
39221
39554
  });
39555
+ Object.defineProperty(exports, "PoolMemoryWatchdog", {
39556
+ enumerable: true,
39557
+ get: function() {
39558
+ return PoolMemoryWatchdog;
39559
+ }
39560
+ });
39222
39561
  Object.defineProperty(exports, "RECORDING_EXPORT_MAX_READ_BYTES", {
39223
39562
  enumerable: true,
39224
39563
  get: function() {
@@ -39489,6 +39828,12 @@ Object.defineProperty(exports, "object", {
39489
39828
  return object;
39490
39829
  }
39491
39830
  });
39831
+ Object.defineProperty(exports, "parseProcStatus", {
39832
+ enumerable: true,
39833
+ get: function() {
39834
+ return parseProcStatus;
39835
+ }
39836
+ });
39492
39837
  Object.defineProperty(exports, "partialRecord", {
39493
39838
  enumerable: true,
39494
39839
  get: function() {
@@ -39525,6 +39870,12 @@ Object.defineProperty(exports, "record", {
39525
39870
  return record;
39526
39871
  }
39527
39872
  });
39873
+ Object.defineProperty(exports, "resolvePoolMemoryPolicy", {
39874
+ enumerable: true,
39875
+ get: function() {
39876
+ return resolvePoolMemoryPolicy;
39877
+ }
39878
+ });
39528
39879
  Object.defineProperty(exports, "sceneMonitorCapability", {
39529
39880
  enumerable: true,
39530
39881
  get: function() {