@trillboards/edge-sdk 0.2.40 → 0.2.42

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 (90) hide show
  1. package/README.md +1 -1
  2. package/deploy/docker/{Dockerfile.cloud-sense → Dockerfile.connector} +52 -39
  3. package/deploy/docker/README.md +73 -1
  4. package/deploy/docker/connector-entrypoint.sh +46 -80
  5. package/deploy/macos/README.md +1 -1
  6. package/deploy/macos/test-install-pair.sh +9 -9
  7. package/deploy/systemd/install.sh +16 -1
  8. package/deploy/systemd/setup-litertlm.sh +201 -0
  9. package/deploy/systemd/trillboards-edge.service +8 -4
  10. package/deploy/systemd/trillboards-litertlm.service +46 -0
  11. package/deploy/windows/register-task.ps1 +6 -3
  12. package/deploy/windows/run-connector.ps1 +1 -1
  13. package/deploy/windows/trillboards-edge-task.vbs +5 -1
  14. package/dist/CloudSensingManager.d.ts +45 -19
  15. package/dist/CloudSensingManager.d.ts.map +1 -1
  16. package/dist/CloudSensingManager.js +89 -46
  17. package/dist/CloudSensingManager.js.map +1 -1
  18. package/dist/EdgeAgent.js +1 -1
  19. package/dist/LiteRtVlmProvider.d.ts +108 -2
  20. package/dist/LiteRtVlmProvider.d.ts.map +1 -1
  21. package/dist/LiteRtVlmProvider.js +79 -13
  22. package/dist/LiteRtVlmProvider.js.map +1 -1
  23. package/dist/SensingProfileClient.d.ts +9 -0
  24. package/dist/SensingProfileClient.d.ts.map +1 -1
  25. package/dist/SensingProfileClient.js +4 -0
  26. package/dist/SensingProfileClient.js.map +1 -1
  27. package/dist/SetupSessionClient.d.ts +0 -1
  28. package/dist/SetupSessionClient.d.ts.map +1 -1
  29. package/dist/autoSense.d.ts +42 -31
  30. package/dist/autoSense.d.ts.map +1 -1
  31. package/dist/autoSense.js +127 -99
  32. package/dist/autoSense.js.map +1 -1
  33. package/dist/cli.d.ts.map +1 -1
  34. package/dist/cli.js +25 -84
  35. package/dist/cli.js.map +1 -1
  36. package/dist/combinedSense.d.ts +1 -3
  37. package/dist/combinedSense.d.ts.map +1 -1
  38. package/dist/combinedSense.js +0 -1
  39. package/dist/combinedSense.js.map +1 -1
  40. package/dist/config.d.ts +17 -64
  41. package/dist/config.d.ts.map +1 -1
  42. package/dist/config.js +0 -10
  43. package/dist/config.js.map +1 -1
  44. package/dist/deployedCadence.d.ts +37 -75
  45. package/dist/deployedCadence.d.ts.map +1 -1
  46. package/dist/deployedCadence.js +45 -105
  47. package/dist/deployedCadence.js.map +1 -1
  48. package/dist/deployedCadenceSource.d.ts +0 -2
  49. package/dist/deployedCadenceSource.d.ts.map +1 -1
  50. package/dist/deployedCadenceSource.js +0 -1
  51. package/dist/deployedCadenceSource.js.map +1 -1
  52. package/dist/diagnose.d.ts +1 -1
  53. package/dist/diagnose.js +1 -1
  54. package/dist/index.d.ts +0 -3
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +1 -8
  57. package/dist/index.js.map +1 -1
  58. package/dist/localInferenceSchema.d.ts +19 -0
  59. package/dist/localInferenceSchema.d.ts.map +1 -1
  60. package/dist/localInferenceSchema.js +23 -0
  61. package/dist/localInferenceSchema.js.map +1 -1
  62. package/dist/localSensing.d.ts +48 -107
  63. package/dist/localSensing.d.ts.map +1 -1
  64. package/dist/localSensing.js +80 -171
  65. package/dist/localSensing.js.map +1 -1
  66. package/dist/localVlmBench.d.ts +36 -0
  67. package/dist/localVlmBench.d.ts.map +1 -1
  68. package/dist/localVlmBench.js +48 -0
  69. package/dist/localVlmBench.js.map +1 -1
  70. package/dist/sensingCatchRate.d.ts +246 -0
  71. package/dist/sensingCatchRate.d.ts.map +1 -0
  72. package/dist/sensingCatchRate.js +514 -0
  73. package/dist/sensingCatchRate.js.map +1 -0
  74. package/dist/sensingRunMode.d.ts +14 -11
  75. package/dist/sensingRunMode.d.ts.map +1 -1
  76. package/dist/sensingRunMode.js +9 -92
  77. package/dist/sensingRunMode.js.map +1 -1
  78. package/dist/setupMode.d.ts +0 -1
  79. package/dist/setupMode.d.ts.map +1 -1
  80. package/dist/setupMode.js +5 -3
  81. package/dist/setupMode.js.map +1 -1
  82. package/dist/startupDiscovery.d.ts +43 -0
  83. package/dist/startupDiscovery.d.ts.map +1 -0
  84. package/dist/startupDiscovery.js +72 -0
  85. package/dist/startupDiscovery.js.map +1 -0
  86. package/package.json +1 -1
  87. package/dist/CloudEscalationPolicy.d.ts +0 -143
  88. package/dist/CloudEscalationPolicy.d.ts.map +0 -1
  89. package/dist/CloudEscalationPolicy.js +0 -137
  90. package/dist/CloudEscalationPolicy.js.map +0 -1
@@ -1,143 +0,0 @@
1
- /**
2
- * CloudEscalationPolicy — WHEN a locally-inferred candidate is worth one cloud
3
- * VLM call, and when it is not.
4
- *
5
- * ── WHY THIS EXISTS ─────────────────────────────────────────────────────────
6
- * The connector's on-device Gemma is an excellent PRESENCE detector and an
7
- * unreliable JUDGE. Measured through the shipped code path against `litert-lm
8
- * serve` on real 640x480 q70 frames (2026-08-12, M4 Max, GPU delegate): the
9
- * empty-scene verdict was right every single run, while the operator's SOP
10
- * booleans on a 5-person kitchen frame flipped between runs at temperature 0 —
11
- * and it reported `confidence` 0.95 on the runs it got WRONG. So the local model
12
- * is trustworthy for "is anything happening here?" and not for "did the thing
13
- * the operator cares about actually happen?".
14
- *
15
- * Escalation makes the second question the CLOUD's: local Gemma stays the
16
- * always-on gate, and the one frame it flags is re-analyzed by the cloud VLM
17
- * before an alert can fire.
18
- *
19
- * ── WHY A POLICY OBJECT AND NOT AN `if` ─────────────────────────────────────
20
- * A cloud call costs money (~$0.002) and, more importantly, sends a frame off
21
- * the customer's premises. Both have to be BOUNDED by construction, not by good
22
- * intentions, because the pathological case is real: a camera pointed at a busy
23
- * pavement produces a candidate on EVERY frame forever. Three independent
24
- * bounds, cheapest first:
25
- *
26
- * 1. NOVELTY (`reconfirmAfterMs`) — a scene whose alert-bearing verdict has
27
- * not CHANGED is not re-asked. This is what makes a permanently-occupied
28
- * camera cost one confirmation per reconfirm window instead of one per
29
- * frame; it is the structural bound, not a rate limit.
30
- * 2. PACING (`minIntervalMs`) — a floor between two escalations on one feed,
31
- * so a rapidly-changing scene cannot spend the hour's budget in a minute.
32
- * 3. BUDGET (`maxPerHour`) — a hard sliding-window ceiling per feed. Whatever
33
- * the scene does, this is the most a camera can ever cost.
34
- *
35
- * The caller supplies the SCENE facts (`hasSignal`, `signature`); this class
36
- * owns only rate + novelty. That split is deliberate: `localSensing.isAlertWorthy`
37
- * stays the ONE authority on "does this frame carry any signal", so the empty-
38
- * scene privacy gate can never drift apart from the escalation gate.
39
- *
40
- * Mirrors `VlmAdmissionGate`'s idiom: `tryEscalate()` COMMITS when it returns
41
- * `escalate: true`, so a decision cannot be counted twice or forgotten.
42
- */
43
- /** Why an escalation was declined (or granted). Surfaced in stats + logs. */
44
- export type EscalationReason =
45
- /** Granted — this frame goes to the cloud VLM for adjudication. */
46
- 'candidate'
47
- /** Feature off (the default). */
48
- | 'disabled'
49
- /** The frame carries no signal at all — an empty scene never escalates. */
50
- | 'no_signal'
51
- /** Same alert-bearing verdict as the last escalation, inside the reconfirm window. */
52
- | 'unchanged'
53
- /** Too soon after the previous escalation on this feed. */
54
- | 'min_interval'
55
- /** This feed has spent its hourly budget. */
56
- | 'hourly_budget';
57
- export interface EscalationVerdict {
58
- escalate: boolean;
59
- reason: EscalationReason;
60
- }
61
- /** The scene facts the caller has already computed for this frame. */
62
- export interface EscalationInput {
63
- /**
64
- * Does this frame carry ANY meaningful signal? Supplied by
65
- * `localSensing.isAlertWorthy` — the same gate that decides whether an
66
- * evidence JPEG may be attached, so escalation can never send a frame the
67
- * privacy gate would have withheld.
68
- */
69
- hasSignal: boolean;
70
- /**
71
- * Stable fingerprint of the ALERT-BEARING fields of this result (see
72
- * `localSensing.alertSignature`). Equal signatures mean "the operator-visible
73
- * state did not change", which is what the novelty bound keys on.
74
- */
75
- signature: string;
76
- }
77
- export interface CloudEscalationPolicyOptions {
78
- /**
79
- * Master switch. Default FALSE: sending a frame off-premises is an explicit
80
- * operator decision, never a silent default — the same standing rule that
81
- * makes `localSensing.allowCloudFallback` opt-in.
82
- */
83
- enabled?: boolean;
84
- /** Floor (ms) between two escalations on this feed. Default 60000. */
85
- minIntervalMs?: number;
86
- /** Hard ceiling on escalations per rolling hour for this feed. Default 12. */
87
- maxPerHour?: number;
88
- /**
89
- * How long an UNCHANGED verdict stays confirmed before the cloud is asked
90
- * again (ms). Default 900000 (15 min). 0 re-confirms every candidate frame
91
- * (bounded only by pacing + budget); a very large value confirms a stable
92
- * scene exactly once.
93
- */
94
- reconfirmAfterMs?: number;
95
- /** Clock injection for tests. Default `Date.now`. */
96
- now?: () => number;
97
- }
98
- export interface CloudEscalationStats {
99
- enabled: boolean;
100
- /** Escalations granted (a cloud call was made). */
101
- escalated: number;
102
- /** Candidate frames declined, by reason. */
103
- skippedUnchanged: number;
104
- skippedMinInterval: number;
105
- skippedBudget: number;
106
- /** Frames that were never candidates (no signal). Cheap, and the common case. */
107
- skippedNoSignal: number;
108
- /** Escalations still available in the current rolling hour. */
109
- remainingThisHour: number;
110
- lastEscalatedAtMs: number | null;
111
- }
112
- export declare class CloudEscalationPolicy {
113
- private readonly enabled;
114
- private readonly minIntervalMs;
115
- private readonly maxPerHour;
116
- private readonly reconfirmAfterMs;
117
- private readonly now;
118
- /** Escalation timestamps inside the rolling hour (never longer than maxPerHour). */
119
- private readonly window;
120
- private lastEscalatedAtMs;
121
- private lastSignature;
122
- private escalated;
123
- private skippedUnchanged;
124
- private skippedMinInterval;
125
- private skippedBudget;
126
- private skippedNoSignal;
127
- constructor(options?: CloudEscalationPolicyOptions);
128
- isEnabled(): boolean;
129
- /**
130
- * Decide — and COMMIT — whether this frame goes to the cloud.
131
- *
132
- * Returning `{ escalate: true }` records the escalation against the pacing
133
- * floor, the hourly budget and the novelty memory, so a caller cannot ask
134
- * twice for one frame. A cloud call that then FAILS is deliberately NOT
135
- * refunded: a broken cloud path must decay to the local verdict at the
136
- * budgeted rate rather than retrying every frame.
137
- */
138
- tryEscalate(input: EscalationInput, nowMs?: number): EscalationVerdict;
139
- getStats(nowMs?: number): CloudEscalationStats;
140
- /** Drop escalation timestamps older than the rolling hour. */
141
- private pruneWindow;
142
- }
143
- //# sourceMappingURL=CloudEscalationPolicy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CloudEscalationPolicy.d.ts","sourceRoot":"","sources":["../src/CloudEscalationPolicy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,6EAA6E;AAC7E,MAAM,MAAM,gBAAgB;AAC1B,mEAAmE;AACjE,WAAW;AACb,iCAAiC;GAC/B,UAAU;AACZ,2EAA2E;GACzE,WAAW;AACb,sFAAsF;GACpF,WAAW;AACb,2DAA2D;GACzD,cAAc;AAChB,6CAA6C;GAC3C,eAAe,CAAC;AAEpB,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,eAAe,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAOD,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IAEnC,oFAAoF;IACpF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,aAAa,CAAuB;IAE5C,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,eAAe,CAAK;gBAEhB,OAAO,GAAE,4BAAiC;IAWtD,SAAS,IAAI,OAAO;IAIpB;;;;;;;;OAQG;IACH,WAAW,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,iBAAiB;IA2CtE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,oBAAoB;IAe9C,8DAA8D;IAC9D,OAAO,CAAC,WAAW;CAKpB"}
@@ -1,137 +0,0 @@
1
- "use strict";
2
- /**
3
- * CloudEscalationPolicy — WHEN a locally-inferred candidate is worth one cloud
4
- * VLM call, and when it is not.
5
- *
6
- * ── WHY THIS EXISTS ─────────────────────────────────────────────────────────
7
- * The connector's on-device Gemma is an excellent PRESENCE detector and an
8
- * unreliable JUDGE. Measured through the shipped code path against `litert-lm
9
- * serve` on real 640x480 q70 frames (2026-08-12, M4 Max, GPU delegate): the
10
- * empty-scene verdict was right every single run, while the operator's SOP
11
- * booleans on a 5-person kitchen frame flipped between runs at temperature 0 —
12
- * and it reported `confidence` 0.95 on the runs it got WRONG. So the local model
13
- * is trustworthy for "is anything happening here?" and not for "did the thing
14
- * the operator cares about actually happen?".
15
- *
16
- * Escalation makes the second question the CLOUD's: local Gemma stays the
17
- * always-on gate, and the one frame it flags is re-analyzed by the cloud VLM
18
- * before an alert can fire.
19
- *
20
- * ── WHY A POLICY OBJECT AND NOT AN `if` ─────────────────────────────────────
21
- * A cloud call costs money (~$0.002) and, more importantly, sends a frame off
22
- * the customer's premises. Both have to be BOUNDED by construction, not by good
23
- * intentions, because the pathological case is real: a camera pointed at a busy
24
- * pavement produces a candidate on EVERY frame forever. Three independent
25
- * bounds, cheapest first:
26
- *
27
- * 1. NOVELTY (`reconfirmAfterMs`) — a scene whose alert-bearing verdict has
28
- * not CHANGED is not re-asked. This is what makes a permanently-occupied
29
- * camera cost one confirmation per reconfirm window instead of one per
30
- * frame; it is the structural bound, not a rate limit.
31
- * 2. PACING (`minIntervalMs`) — a floor between two escalations on one feed,
32
- * so a rapidly-changing scene cannot spend the hour's budget in a minute.
33
- * 3. BUDGET (`maxPerHour`) — a hard sliding-window ceiling per feed. Whatever
34
- * the scene does, this is the most a camera can ever cost.
35
- *
36
- * The caller supplies the SCENE facts (`hasSignal`, `signature`); this class
37
- * owns only rate + novelty. That split is deliberate: `localSensing.isAlertWorthy`
38
- * stays the ONE authority on "does this frame carry any signal", so the empty-
39
- * scene privacy gate can never drift apart from the escalation gate.
40
- *
41
- * Mirrors `VlmAdmissionGate`'s idiom: `tryEscalate()` COMMITS when it returns
42
- * `escalate: true`, so a decision cannot be counted twice or forgotten.
43
- */
44
- Object.defineProperty(exports, "__esModule", { value: true });
45
- exports.CloudEscalationPolicy = void 0;
46
- const DEFAULT_MIN_INTERVAL_MS = 60000;
47
- const DEFAULT_MAX_PER_HOUR = 12;
48
- const DEFAULT_RECONFIRM_AFTER_MS = 15 * 60000;
49
- const HOUR_MS = 3600000;
50
- class CloudEscalationPolicy {
51
- constructor(options = {}) {
52
- /** Escalation timestamps inside the rolling hour (never longer than maxPerHour). */
53
- this.window = [];
54
- this.lastEscalatedAtMs = null;
55
- this.lastSignature = null;
56
- this.escalated = 0;
57
- this.skippedUnchanged = 0;
58
- this.skippedMinInterval = 0;
59
- this.skippedBudget = 0;
60
- this.skippedNoSignal = 0;
61
- this.enabled = options.enabled === true;
62
- this.minIntervalMs = Math.max(0, Math.trunc(options.minIntervalMs ?? DEFAULT_MIN_INTERVAL_MS));
63
- this.maxPerHour = Math.max(0, Math.trunc(options.maxPerHour ?? DEFAULT_MAX_PER_HOUR));
64
- this.reconfirmAfterMs = Math.max(0, Math.trunc(options.reconfirmAfterMs ?? DEFAULT_RECONFIRM_AFTER_MS));
65
- this.now = options.now ?? Date.now;
66
- }
67
- isEnabled() {
68
- return this.enabled;
69
- }
70
- /**
71
- * Decide — and COMMIT — whether this frame goes to the cloud.
72
- *
73
- * Returning `{ escalate: true }` records the escalation against the pacing
74
- * floor, the hourly budget and the novelty memory, so a caller cannot ask
75
- * twice for one frame. A cloud call that then FAILS is deliberately NOT
76
- * refunded: a broken cloud path must decay to the local verdict at the
77
- * budgeted rate rather than retrying every frame.
78
- */
79
- tryEscalate(input, nowMs) {
80
- if (!this.enabled)
81
- return { escalate: false, reason: 'disabled' };
82
- if (!input.hasSignal) {
83
- this.skippedNoSignal++;
84
- return { escalate: false, reason: 'no_signal' };
85
- }
86
- const now = nowMs ?? this.now();
87
- this.pruneWindow(now);
88
- // 1. NOVELTY — an unchanged verdict inside the reconfirm window is already
89
- // adjudicated; asking again buys nothing and costs a frame leaving the
90
- // building. This is the bound that makes a permanently-busy camera cheap.
91
- if (this.lastSignature !== null &&
92
- this.lastSignature === input.signature &&
93
- this.lastEscalatedAtMs !== null &&
94
- now - this.lastEscalatedAtMs < this.reconfirmAfterMs) {
95
- this.skippedUnchanged++;
96
- return { escalate: false, reason: 'unchanged' };
97
- }
98
- // 2. PACING — a scene that changes every frame still cannot outrun this.
99
- if (this.lastEscalatedAtMs !== null && now - this.lastEscalatedAtMs < this.minIntervalMs) {
100
- this.skippedMinInterval++;
101
- return { escalate: false, reason: 'min_interval' };
102
- }
103
- // 3. BUDGET — the hard ceiling. `maxPerHour: 0` disables escalation
104
- // entirely, which is a legitimate (belt-and-braces) operator setting.
105
- if (this.window.length >= this.maxPerHour) {
106
- this.skippedBudget++;
107
- return { escalate: false, reason: 'hourly_budget' };
108
- }
109
- this.window.push(now);
110
- this.lastEscalatedAtMs = now;
111
- this.lastSignature = input.signature;
112
- this.escalated++;
113
- return { escalate: true, reason: 'candidate' };
114
- }
115
- getStats(nowMs) {
116
- const now = nowMs ?? this.now();
117
- this.pruneWindow(now);
118
- return {
119
- enabled: this.enabled,
120
- escalated: this.escalated,
121
- skippedUnchanged: this.skippedUnchanged,
122
- skippedMinInterval: this.skippedMinInterval,
123
- skippedBudget: this.skippedBudget,
124
- skippedNoSignal: this.skippedNoSignal,
125
- remainingThisHour: Math.max(0, this.maxPerHour - this.window.length),
126
- lastEscalatedAtMs: this.lastEscalatedAtMs,
127
- };
128
- }
129
- /** Drop escalation timestamps older than the rolling hour. */
130
- pruneWindow(nowMs) {
131
- while (this.window.length > 0 && nowMs - this.window[0] >= HOUR_MS) {
132
- this.window.shift();
133
- }
134
- }
135
- }
136
- exports.CloudEscalationPolicy = CloudEscalationPolicy;
137
- //# sourceMappingURL=CloudEscalationPolicy.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CloudEscalationPolicy.js","sourceRoot":"","sources":["../src/CloudEscalationPolicy.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;;;AA4EH,MAAM,uBAAuB,GAAG,KAAM,CAAC;AACvC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAChC,MAAM,0BAA0B,GAAG,EAAE,GAAG,KAAM,CAAC;AAC/C,MAAM,OAAO,GAAG,OAAS,CAAC;AAE1B,MAAa,qBAAqB;IAkBhC,YAAY,UAAwC,EAAE;QAXtD,oFAAoF;QACnE,WAAM,GAAa,EAAE,CAAC;QAC/B,sBAAiB,GAAkB,IAAI,CAAC;QACxC,kBAAa,GAAkB,IAAI,CAAC;QAEpC,cAAS,GAAG,CAAC,CAAC;QACd,qBAAgB,GAAG,CAAC,CAAC;QACrB,uBAAkB,GAAG,CAAC,CAAC;QACvB,kBAAa,GAAG,CAAC,CAAC;QAClB,oBAAe,GAAG,CAAC,CAAC;QAG1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,KAAK,IAAI,CAAC;QACxC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,IAAI,uBAAuB,CAAC,CAAC,CAAC;QAC/F,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,IAAI,oBAAoB,CAAC,CAAC,CAAC;QACtF,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAC9B,CAAC,EACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,IAAI,0BAA0B,CAAC,CACnE,CAAC;QACF,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACrC,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED;;;;;;;;OAQG;IACH,WAAW,CAAC,KAAsB,EAAE,KAAc;QAChD,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAClE,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YACrB,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QAClD,CAAC;QAED,MAAM,GAAG,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QAChC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAEtB,2EAA2E;QAC3E,0EAA0E;QAC1E,6EAA6E;QAC7E,IACE,IAAI,CAAC,aAAa,KAAK,IAAI;YAC3B,IAAI,CAAC,aAAa,KAAK,KAAK,CAAC,SAAS;YACtC,IAAI,CAAC,iBAAiB,KAAK,IAAI;YAC/B,GAAG,GAAG,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,EACpD,CAAC;YACD,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QAClD,CAAC;QAED,yEAAyE;QACzE,IAAI,IAAI,CAAC,iBAAiB,KAAK,IAAI,IAAI,GAAG,GAAG,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACzF,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QACrD,CAAC;QAED,oEAAoE;QACpE,yEAAyE;QACzE,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC1C,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;QACtD,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,iBAAiB,GAAG,GAAG,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC;QACrC,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACjD,CAAC;IAED,QAAQ,CAAC,KAAc;QACrB,MAAM,GAAG,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QAChC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACtB,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;YAC3C,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,iBAAiB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YACpE,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;SAC1C,CAAC;IACJ,CAAC;IAED,8DAA8D;IACtD,WAAW,CAAC,KAAa;QAC/B,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC;YACnE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;CACF;AA1GD,sDA0GC"}