@indigoai-us/hq-cloud 6.14.49 → 6.14.50

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 (112) hide show
  1. package/.github/workflows/unreleased-commits-nag.yml +256 -0
  2. package/dist/bin/sync-runner-watch-loop.d.ts +12 -0
  3. package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
  4. package/dist/bin/sync-runner-watch-loop.js +153 -25
  5. package/dist/bin/sync-runner-watch-loop.js.map +1 -1
  6. package/dist/bin/sync-runner-watch-routes.d.ts +17 -0
  7. package/dist/bin/sync-runner-watch-routes.d.ts.map +1 -1
  8. package/dist/bin/sync-runner-watch-routes.js +11 -0
  9. package/dist/bin/sync-runner-watch-routes.js.map +1 -1
  10. package/dist/bin/sync-runner-watch-routes.test.d.ts +2 -0
  11. package/dist/bin/sync-runner-watch-routes.test.d.ts.map +1 -0
  12. package/dist/bin/sync-runner-watch-routes.test.js +51 -0
  13. package/dist/bin/sync-runner-watch-routes.test.js.map +1 -0
  14. package/dist/bin/sync-runner.d.ts +11 -12
  15. package/dist/bin/sync-runner.d.ts.map +1 -1
  16. package/dist/bin/sync-runner.js.map +1 -1
  17. package/dist/bin/sync-runner.test.js +173 -52
  18. package/dist/bin/sync-runner.test.js.map +1 -1
  19. package/dist/cli/rescue-classify-ordering.test.js +8 -2
  20. package/dist/cli/rescue-classify-ordering.test.js.map +1 -1
  21. package/dist/cli/rescue-core.d.ts +85 -0
  22. package/dist/cli/rescue-core.d.ts.map +1 -1
  23. package/dist/cli/rescue-core.js +390 -1
  24. package/dist/cli/rescue-core.js.map +1 -1
  25. package/dist/cli/rescue-settings-reconcile.test.d.ts +2 -0
  26. package/dist/cli/rescue-settings-reconcile.test.d.ts.map +1 -0
  27. package/dist/cli/rescue-settings-reconcile.test.js +476 -0
  28. package/dist/cli/rescue-settings-reconcile.test.js.map +1 -0
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +1 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/journal.d.ts.map +1 -1
  34. package/dist/journal.js +81 -51
  35. package/dist/journal.js.map +1 -1
  36. package/dist/journal.test.js +11 -19
  37. package/dist/journal.test.js.map +1 -1
  38. package/dist/sync/event-sync.d.ts +8 -25
  39. package/dist/sync/event-sync.d.ts.map +1 -1
  40. package/dist/sync/event-sync.js +23 -48
  41. package/dist/sync/event-sync.js.map +1 -1
  42. package/dist/sync/event-sync.test.js +6 -32
  43. package/dist/sync/event-sync.test.js.map +1 -1
  44. package/dist/sync/feature-flags.d.ts +20 -117
  45. package/dist/sync/feature-flags.d.ts.map +1 -1
  46. package/dist/sync/feature-flags.js +24 -147
  47. package/dist/sync/feature-flags.js.map +1 -1
  48. package/dist/sync/feature-flags.test.js +15 -61
  49. package/dist/sync/feature-flags.test.js.map +1 -1
  50. package/dist/sync/index.d.ts +1 -1
  51. package/dist/sync/index.d.ts.map +1 -1
  52. package/dist/sync/index.js +1 -1
  53. package/dist/sync/index.js.map +1 -1
  54. package/dist/sync/lease-client.d.ts +67 -0
  55. package/dist/sync/lease-client.d.ts.map +1 -0
  56. package/dist/sync/lease-client.js +158 -0
  57. package/dist/sync/lease-client.js.map +1 -0
  58. package/dist/sync/lease-client.test.d.ts +2 -0
  59. package/dist/sync/lease-client.test.d.ts.map +1 -0
  60. package/dist/sync/lease-client.test.js +119 -0
  61. package/dist/sync/lease-client.test.js.map +1 -0
  62. package/dist/sync/push-receiver.d.ts +8 -19
  63. package/dist/sync/push-receiver.d.ts.map +1 -1
  64. package/dist/sync/push-receiver.js +6 -50
  65. package/dist/sync/push-receiver.js.map +1 -1
  66. package/dist/sync/push-receiver.test.js +6 -57
  67. package/dist/sync/push-receiver.test.js.map +1 -1
  68. package/dist/sync/realtime-rollout.d.ts +85 -0
  69. package/dist/sync/realtime-rollout.d.ts.map +1 -0
  70. package/dist/sync/realtime-rollout.js +206 -0
  71. package/dist/sync/realtime-rollout.js.map +1 -0
  72. package/dist/sync/realtime-rollout.test.d.ts +2 -0
  73. package/dist/sync/realtime-rollout.test.d.ts.map +1 -0
  74. package/dist/sync/realtime-rollout.test.js +71 -0
  75. package/dist/sync/realtime-rollout.test.js.map +1 -0
  76. package/dist/sync/state-store.d.ts +40 -0
  77. package/dist/sync/state-store.d.ts.map +1 -0
  78. package/dist/sync/state-store.js +680 -0
  79. package/dist/sync/state-store.js.map +1 -0
  80. package/dist/sync/state-store.test.d.ts +2 -0
  81. package/dist/sync/state-store.test.d.ts.map +1 -0
  82. package/dist/sync/state-store.test.js +159 -0
  83. package/dist/sync/state-store.test.js.map +1 -0
  84. package/dist/types.d.ts +12 -0
  85. package/dist/types.d.ts.map +1 -1
  86. package/package.json +1 -1
  87. package/src/bin/sync-runner-watch-loop.ts +176 -32
  88. package/src/bin/sync-runner-watch-routes.test.ts +71 -0
  89. package/src/bin/sync-runner-watch-routes.ts +27 -0
  90. package/src/bin/sync-runner.test.ts +188 -53
  91. package/src/bin/sync-runner.ts +11 -12
  92. package/src/cli/rescue-classify-ordering.test.ts +9 -3
  93. package/src/cli/rescue-core.ts +459 -1
  94. package/src/cli/rescue-settings-reconcile.test.ts +583 -0
  95. package/src/index.ts +2 -4
  96. package/src/journal.test.ts +19 -21
  97. package/src/journal.ts +87 -54
  98. package/src/sync/event-sync.test.ts +9 -44
  99. package/src/sync/event-sync.ts +26 -52
  100. package/src/sync/feature-flags.test.ts +22 -72
  101. package/src/sync/feature-flags.ts +32 -199
  102. package/src/sync/index.ts +2 -4
  103. package/src/sync/lease-client.test.ts +128 -0
  104. package/src/sync/lease-client.ts +207 -0
  105. package/src/sync/push-receiver.test.ts +6 -58
  106. package/src/sync/push-receiver.ts +9 -74
  107. package/src/sync/realtime-rollout.test.ts +86 -0
  108. package/src/sync/realtime-rollout.ts +262 -0
  109. package/src/sync/state-store.test.ts +194 -0
  110. package/src/sync/state-store.ts +727 -0
  111. package/src/types.ts +14 -0
  112. package/test/e2e/sync/transient-company-leg.test.ts +8 -4
@@ -0,0 +1,71 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { MAX_REALTIME_ROLLOUT_CACHE_MS, RealtimeRolloutClient, parseRealtimeInventory, } from "./realtime-rollout.js";
3
+ const capability = {
4
+ hqCloud: "6.14.49",
5
+ hqDesktop: "none",
6
+ protocol: 2,
7
+ journal: 3,
8
+ durableApply: 1,
9
+ };
10
+ function jsonResponse(body, status = 200) {
11
+ return { ok: status >= 200 && status < 300, status, text: async () => JSON.stringify(body) };
12
+ }
13
+ function request(overrides = {}) {
14
+ return {
15
+ bearer: "token-a",
16
+ deviceId: "machine_a",
17
+ capabilityVector: capability,
18
+ configurationFingerprint: "config-a",
19
+ scopeFingerprint: "personal:prs_1",
20
+ ...overrides,
21
+ };
22
+ }
23
+ const readyInventory = {
24
+ scopes: [{ scopeUid: "prs_1", scopeHandle: "handle_1", scopeRevision: "rev_1", state: "v2-ready", cursor: "cursor_1" }],
25
+ };
26
+ describe("RealtimeRolloutClient", () => {
27
+ it("never reuses a cached positive across bearer, configuration, or scope changes", async () => {
28
+ let now = 1_000;
29
+ const requests = [];
30
+ const fetchImpl = async (_url, init) => {
31
+ requests.push({ headers: init?.headers });
32
+ return jsonResponse(readyInventory);
33
+ };
34
+ const client = new RealtimeRolloutClient({ apiUrl: "https://api.example/", fetchImpl, now: () => now });
35
+ await client.inventory(request());
36
+ await client.inventory(request());
37
+ await client.inventory(request({ bearer: "token-b" }));
38
+ await client.inventory(request({ configurationFingerprint: "config-b" }));
39
+ await client.inventory(request({ scopeFingerprint: "company:cmp_1" }));
40
+ now += MAX_REALTIME_ROLLOUT_CACHE_MS;
41
+ await client.inventory(request());
42
+ expect(requests).toHaveLength(5);
43
+ expect(requests[0]?.headers).toMatchObject({
44
+ Authorization: "Bearer token-a",
45
+ "X-HQ-Sync-Contract": "2",
46
+ "X-HQ-Device-ID": "machine_a",
47
+ "X-HQ-Cloud-Version": "6.14.49",
48
+ "X-HQ-Desktop-Version": "none",
49
+ "X-HQ-Sync-Journal": "3",
50
+ "X-HQ-Sync-Durable-Apply": "1",
51
+ });
52
+ });
53
+ it("fails closed for malformed or non-explicit legacy inventory", () => {
54
+ expect(() => parseRealtimeInventory({ scopes: [{ scopeUid: "prs_1", scopeHandle: "h", scopeRevision: "r", state: "legacy", v1Allowed: false }] })).toThrow("legacy must explicitly allow v1");
55
+ expect(() => parseRealtimeInventory({ scopes: [{ scopeUid: "prs_1", scopeHandle: "h", scopeRevision: "r", state: "v2-ready", cursor: "c", surprise: true }] })).toThrow("unknown field");
56
+ expect(() => parseRealtimeInventory({ scopes: [{ scopeUid: "prs_1", scopeHandle: "h", scopeRevision: "r", state: "unknown" }] })).toThrow("unsupported scope state");
57
+ });
58
+ it("rejects cache durations greater than the protocol maximum", () => {
59
+ expect(() => new RealtimeRolloutClient({ apiUrl: "https://api.example", maxCacheAgeMs: MAX_REALTIME_ROLLOUT_CACHE_MS + 1 })).toThrow("maxCacheAgeMs");
60
+ });
61
+ it("honors transitional retryAfterMs instead of holding a stale negative state", async () => {
62
+ const fetchImpl = vi.fn(async () => jsonResponse({ scopes: [
63
+ { scopeUid: "prs_1", scopeHandle: "handle_1", scopeRevision: "rev_1", state: "restoring", retryAfterMs: 0 },
64
+ ] }));
65
+ const client = new RealtimeRolloutClient({ apiUrl: "https://api.example", fetchImpl });
66
+ await client.inventory(request());
67
+ await client.inventory(request());
68
+ expect(fetchImpl).toHaveBeenCalledTimes(2);
69
+ });
70
+ });
71
+ //# sourceMappingURL=realtime-rollout.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-rollout.test.js","sourceRoot":"","sources":["../../src/sync/realtime-rollout.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAElD,OAAO,EACL,6BAA6B,EAC7B,qBAAqB,EACrB,sBAAsB,GAEvB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,UAAU,GAA6B;IAC3C,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,MAAM;IACjB,QAAQ,EAAE,CAAC;IACX,OAAO,EAAE,CAAC;IACV,YAAY,EAAE,CAAC;CAChB,CAAC;AAEF,SAAS,YAAY,CAAC,IAAa,EAAE,MAAM,GAAG,GAAG;IAC/C,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;AAC/F,CAAC;AAED,SAAS,OAAO,CAAC,YAAwE,EAAE;IACzF,OAAO;QACL,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,WAAW;QACrB,gBAAgB,EAAE,UAAU;QAC5B,wBAAwB,EAAE,UAAU;QACpC,gBAAgB,EAAE,gBAAgB;QAClC,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,MAAM,cAAc,GAAG;IACrB,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;CACxH,CAAC;AAEF,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,IAAI,GAAG,GAAG,KAAK,CAAC;QAChB,MAAM,QAAQ,GAAgD,EAAE,CAAC;QACjE,MAAM,SAAS,GAAG,KAAK,EAAE,IAAY,EAAE,IAA2C,EAAE,EAAE;YACpF,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAC1C,OAAO,YAAY,CAAC,cAAc,CAAC,CAAC;QACtC,CAAC,CAAC;QACF,MAAM,MAAM,GAAG,IAAI,qBAAqB,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;QAExG,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;QAClC,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;QAClC,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;QACvD,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;QAC1E,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,gBAAgB,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC;QACvE,GAAG,IAAI,6BAA6B,CAAC;QACrC,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;QAElC,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,aAAa,CAAC;YACzC,aAAa,EAAE,gBAAgB;YAC/B,oBAAoB,EAAE,GAAG;YACzB,gBAAgB,EAAE,WAAW;YAC7B,oBAAoB,EAAE,SAAS;YAC/B,sBAAsB,EAAE,MAAM;YAC9B,mBAAmB,EAAE,GAAG;YACxB,yBAAyB,EAAE,GAAG;SAC/B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,CAAC,GAAG,EAAE,CAAC,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;QAC9L,MAAM,CAAC,GAAG,EAAE,CAAC,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACzL,MAAM,CAAC,GAAG,EAAE,CAAC,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACvK,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,qBAAqB,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,aAAa,EAAE,6BAA6B,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACxJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC1F,MAAM,SAAS,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE;gBACzD,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,EAAE;aAC5G,EAAE,CAAC,CAAC,CAAC;QACN,MAAM,MAAM,GAAG,IAAI,qBAAqB,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,SAAS,EAAE,CAAC,CAAC;QACvF,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;QAClC,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;QAClC,MAAM,CAAC,SAAS,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,40 @@
1
+ export interface StateStoreRecord<T = unknown> {
2
+ sequence: number;
3
+ type: number;
4
+ flags: number;
5
+ payload: T;
6
+ }
7
+ export interface StateStoreOptions<T> {
8
+ rootDir: string;
9
+ scopeId: string;
10
+ initialState: T;
11
+ reduce: (state: T, record: StateStoreRecord) => T;
12
+ /** Compact after this many WAL records. Defaults to 256. */
13
+ maxRecordsBeforeCompaction?: number;
14
+ }
15
+ export declare class StateStoreCorruptionError extends Error {
16
+ constructor(message: string, options?: ErrorOptions);
17
+ }
18
+ /** A recovered v3 store. `append` is the ordinary hot path. */
19
+ export declare class StateStore<T> {
20
+ private readonly options;
21
+ readonly stateDir: string;
22
+ readonly scopeDigest: Buffer;
23
+ readonly wasCreated: boolean;
24
+ private generation;
25
+ private state;
26
+ private lastRecordSequence;
27
+ private recordCount;
28
+ private constructor();
29
+ static exists(rootDir: string, scopeId: string): boolean;
30
+ static open<T>(options: StateStoreOptions<T>): StateStore<T>;
31
+ getState(): T;
32
+ getGeneration(): number;
33
+ getLastRecordSequence(): number;
34
+ append(type: number, payload: unknown, flags?: number): StateStoreRecord;
35
+ /** Create G+1 without ever merging two generations during recovery. */
36
+ compact(): void;
37
+ private refreshFromDisk;
38
+ private compactUnlocked;
39
+ }
40
+ //# sourceMappingURL=state-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-store.d.ts","sourceRoot":"","sources":["../../src/sync/state-store.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,OAAO;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,CAAC;CACZ;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,CAAC,CAAC;IAChB,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,gBAAgB,KAAK,CAAC,CAAC;IAClD,4DAA4D;IAC5D,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC;AAcD,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;AASD,+DAA+D;AAC/D,qBAAa,UAAU,CAAC,CAAC;IAUrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAT1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,KAAK,CAAI;IACjB,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO;IAcP,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IAUxD,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC;IA6B5D,QAAQ,IAAI,CAAC;IAIb,aAAa,IAAI,MAAM;IAIvB,qBAAqB,IAAI,MAAM;IAI/B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,SAAI,GAAG,gBAAgB;IAyBnE,uEAAuE;IACvE,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,eAAe;CAaxB"}