@soulcraft/sdk 1.5.5 → 1.6.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.
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -0
- package/dist/client/index.js.map +1 -1
- package/dist/modules/billing/portal-provider.d.ts +28 -0
- package/dist/modules/billing/portal-provider.d.ts.map +1 -1
- package/dist/modules/billing/portal-provider.js +58 -1
- package/dist/modules/billing/portal-provider.js.map +1 -1
- package/dist/modules/billing/types.d.ts +2 -0
- package/dist/modules/billing/types.d.ts.map +1 -1
- package/dist/modules/billing/usage-buffer.d.ts.map +1 -1
- package/dist/modules/billing/usage-buffer.js +7 -1
- package/dist/modules/billing/usage-buffer.js.map +1 -1
- package/dist/modules/brainy/ydoc-manager.d.ts +175 -0
- package/dist/modules/brainy/ydoc-manager.d.ts.map +1 -0
- package/dist/modules/brainy/ydoc-manager.js +424 -0
- package/dist/modules/brainy/ydoc-manager.js.map +1 -0
- package/dist/modules/skills/types.d.ts +1 -1
- package/dist/modules/skills/types.js +1 -1
- package/dist/server/handlers.d.ts +108 -12
- package/dist/server/handlers.d.ts.map +1 -1
- package/dist/server/handlers.js +167 -5
- package/dist/server/handlers.js.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -0
- package/dist/server/index.js.map +1 -1
- package/dist/transports/ws.d.ts +10 -0
- package/dist/transports/ws.d.ts.map +1 -1
- package/dist/transports/ws.js +15 -0
- package/dist/transports/ws.js.map +1 -1
- package/dist/transports/yjs-provider.d.ts +101 -0
- package/dist/transports/yjs-provider.d.ts.map +1 -0
- package/dist/transports/yjs-provider.js +241 -0
- package/dist/transports/yjs-provider.js.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/docs/ADR-001-sdk-design.md +2 -2
- package/docs/IMPLEMENTATION-PLAN.md +6 -6
- package/docs/KIT-APP-GUIDE.md +2 -2
- package/package.json +5 -2
package/dist/client/index.d.ts
CHANGED
|
@@ -59,6 +59,8 @@ export { PostMessageTransport } from '../transports/postmessage.js';
|
|
|
59
59
|
export type { PostMessageRequest, PostMessageResponse } from '../transports/postmessage.js';
|
|
60
60
|
export type { SDKTransport } from '../transports/transport.js';
|
|
61
61
|
export { createBrainyProxy } from '../modules/brainy/proxy.js';
|
|
62
|
+
export { createYjsProvider } from '../transports/yjs-provider.js';
|
|
63
|
+
export type { YjsProvider } from '../transports/yjs-provider.js';
|
|
62
64
|
export { joinHallRoom } from '../modules/hall/browser.js';
|
|
63
65
|
export type { JoinHallRoomOptions } from '../modules/hall/browser.js';
|
|
64
66
|
export type { HallRoomHandle, HallRoomHandleEvents, TranscriptEvent, ConceptMentionEvent, RelationProposedEvent, SpeakerChangedEvent, PeerJoinedEvent, PeerLeftEvent, RoomOptions, RecordingManifest, ConceptInput, } from '../modules/hall/types.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AACnE,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAC3F,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAG9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAG9D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AACzD,YAAY,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,YAAY,GACb,MAAM,0BAA0B,CAAA;AAGjC,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACnD,YAAY,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AACjE,YAAY,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AACpE,OAAO,EACL,QAAQ,EACR,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,sBAAsB,GACvB,MAAM,6BAA6B,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AACnE,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAC3F,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAG9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAG9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAA;AACjE,YAAY,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAGhE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AACzD,YAAY,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,YAAY,GACb,MAAM,0BAA0B,CAAA;AAGjC,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACnD,YAAY,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AACjE,YAAY,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AACpE,OAAO,EACL,QAAQ,EACR,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,sBAAsB,GACvB,MAAM,6BAA6B,CAAA"}
|
package/dist/client/index.js
CHANGED
|
@@ -60,6 +60,8 @@ export { SseTransport } from '../transports/sse.js';
|
|
|
60
60
|
export { PostMessageTransport } from '../transports/postmessage.js';
|
|
61
61
|
// ── Proxy factory ─────────────────────────────────────────────────────────────
|
|
62
62
|
export { createBrainyProxy } from '../modules/brainy/proxy.js';
|
|
63
|
+
// ── Y.js provider (collaborative editing) ─────────────────────────────────────
|
|
64
|
+
export { createYjsProvider } from '../transports/yjs-provider.js';
|
|
63
65
|
// ── Hall room client (browser WebRTC) ─────────────────────────────────────────
|
|
64
66
|
export { joinHallRoom } from '../modules/hall/browser.js';
|
|
65
67
|
export { SDKError, SDKDisconnectedError, SDKTimeoutError, SDKAuthError, SDKForbiddenError, SDKRpcError, SDKMethodNotFoundError, } from '../modules/brainy/errors.js';
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,iFAAiF;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,iFAAiF;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAInE,iFAAiF;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAE9D,iFAAiF;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAoBzD,OAAO,EACL,QAAQ,EACR,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,sBAAsB,GACvB,MAAM,6BAA6B,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,iFAAiF;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,iFAAiF;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAInE,iFAAiF;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAE9D,iFAAiF;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAA;AAGjE,iFAAiF;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAoBzD,OAAO,EACL,QAAQ,EACR,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,sBAAsB,GACvB,MAAM,6BAA6B,CAAA"}
|
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
*
|
|
19
19
|
* All requests carry `X-Portal-Credit-Secret: <PORTAL_CREDIT_SECRET>`.
|
|
20
20
|
*
|
|
21
|
+
* **Caching:** `checkLimit` results are cached per-user for 30 seconds with
|
|
22
|
+
* singleflight deduplication for concurrent callers. The cache is invalidated
|
|
23
|
+
* automatically when `UsageBuffer` flushes usage to Portal. Worst-case
|
|
24
|
+
* over-grant is ~3–5 messages past exhaustion (acceptable given `recordUsage`
|
|
25
|
+
* is itself 5s-delayed).
|
|
26
|
+
*
|
|
21
27
|
* Subscription data, top-up balances, and usage history are not surfaced via
|
|
22
28
|
* this API — those are managed by Portal directly. Methods that require them
|
|
23
29
|
* (`getUsageStatus`, `getSubscription`, `addTopUp`) return safe defaults.
|
|
@@ -41,6 +47,10 @@ import type { BillingProvider, UsageData, SubscriptionData, LimitCheckResult, Us
|
|
|
41
47
|
* Calls the Portal credit API for all gate checks and usage recording.
|
|
42
48
|
* All requests are authenticated with the `X-Portal-Credit-Secret` header.
|
|
43
49
|
*
|
|
50
|
+
* `checkLimit` responses are cached per-user for 30 seconds with singleflight
|
|
51
|
+
* deduplication. The cache is cleared via `invalidateCache()` when `UsageBuffer`
|
|
52
|
+
* successfully flushes usage — tightening the feedback loop after each batch write.
|
|
53
|
+
*
|
|
44
54
|
* The `userId` parameter on all methods must be the user's **email address** —
|
|
45
55
|
* the same identifier Portal uses to look up the license document.
|
|
46
56
|
*/
|
|
@@ -54,9 +64,27 @@ export declare class PortalBillingProvider implements BillingProvider {
|
|
|
54
64
|
* @param product - The product name sent with consume/batch calls (`'workshop'`, `'venue'`, `'academy'`).
|
|
55
65
|
*/
|
|
56
66
|
constructor(baseUrl: string, secret: string, product: string);
|
|
67
|
+
/** Cached limit check results, keyed by userId (email). */
|
|
68
|
+
private readonly _cache;
|
|
69
|
+
/** In-flight `checkLimit` promises, keyed by userId — singleflight deduplication. */
|
|
70
|
+
private readonly _inflight;
|
|
71
|
+
/** Per-user cache TTL for `checkLimit` results. */
|
|
72
|
+
private static readonly CACHE_TTL_MS;
|
|
57
73
|
private _headers;
|
|
58
74
|
private _post;
|
|
59
75
|
checkLimit(userId: string, hasPersonalKey: boolean): Promise<LimitCheckResult>;
|
|
76
|
+
/**
|
|
77
|
+
* Clear the cached limit check result for a user.
|
|
78
|
+
*
|
|
79
|
+
* Called by `UsageBuffer` after a successful batch flush so the next
|
|
80
|
+
* `checkLimit` call fetches fresh data from Portal rather than serving
|
|
81
|
+
* a stale credit balance.
|
|
82
|
+
*
|
|
83
|
+
* @param userId - The user's email address (same key used in `checkLimit`).
|
|
84
|
+
*/
|
|
85
|
+
invalidateCache(userId: string): void;
|
|
86
|
+
/** Perform the actual Portal HTTP call and populate the cache. */
|
|
87
|
+
private _fetchLimit;
|
|
60
88
|
getUsage(userId: string): Promise<UsageData>;
|
|
61
89
|
getUsageStatus(userId: string, hasPersonalKey: boolean): Promise<UsageStatus>;
|
|
62
90
|
incrementUsage(userId: string, inputTokens: number, outputTokens: number, model: string, _useTopUp: boolean): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portal-provider.d.ts","sourceRoot":"","sources":["../../../src/modules/billing/portal-provider.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"portal-provider.d.ts","sourceRoot":"","sources":["../../../src/modules/billing/portal-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EACnB,MAAM,YAAY,CAAA;AAmBnB;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAsB,YAAW,eAAe;IAOzD,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAR1B;;;;OAIG;gBAEgB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM;IAKlC,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqE;IAE5F,qFAAqF;IACrF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+C;IAEzE,mDAAmD;IACnD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAS;IAI7C,OAAO,CAAC,QAAQ;YAOF,KAAK;IAeb,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA0BpF;;;;;;;;OAQG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIrC,kEAAkE;YACpD,WAAW;IAkCnB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAgB5C,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAgC7E,cAAc,CAClB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC;IAeV,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAe7E,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;IAKvE,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKvD,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKhD,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG7D"}
|
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
*
|
|
19
19
|
* All requests carry `X-Portal-Credit-Secret: <PORTAL_CREDIT_SECRET>`.
|
|
20
20
|
*
|
|
21
|
+
* **Caching:** `checkLimit` results are cached per-user for 30 seconds with
|
|
22
|
+
* singleflight deduplication for concurrent callers. The cache is invalidated
|
|
23
|
+
* automatically when `UsageBuffer` flushes usage to Portal. Worst-case
|
|
24
|
+
* over-grant is ~3–5 messages past exhaustion (acceptable given `recordUsage`
|
|
25
|
+
* is itself 5s-delayed).
|
|
26
|
+
*
|
|
21
27
|
* Subscription data, top-up balances, and usage history are not surfaced via
|
|
22
28
|
* this API — those are managed by Portal directly. Methods that require them
|
|
23
29
|
* (`getUsageStatus`, `getSubscription`, `addTopUp`) return safe defaults.
|
|
@@ -53,6 +59,10 @@ function _thirtyDaysFromNow() {
|
|
|
53
59
|
* Calls the Portal credit API for all gate checks and usage recording.
|
|
54
60
|
* All requests are authenticated with the `X-Portal-Credit-Secret` header.
|
|
55
61
|
*
|
|
62
|
+
* `checkLimit` responses are cached per-user for 30 seconds with singleflight
|
|
63
|
+
* deduplication. The cache is cleared via `invalidateCache()` when `UsageBuffer`
|
|
64
|
+
* successfully flushes usage — tightening the feedback loop after each batch write.
|
|
65
|
+
*
|
|
56
66
|
* The `userId` parameter on all methods must be the user's **email address** —
|
|
57
67
|
* the same identifier Portal uses to look up the license document.
|
|
58
68
|
*/
|
|
@@ -70,6 +80,13 @@ export class PortalBillingProvider {
|
|
|
70
80
|
this.secret = secret;
|
|
71
81
|
this.product = product;
|
|
72
82
|
}
|
|
83
|
+
// ── Cache + singleflight ──────────────────────────────────────────────────
|
|
84
|
+
/** Cached limit check results, keyed by userId (email). */
|
|
85
|
+
_cache = new Map();
|
|
86
|
+
/** In-flight `checkLimit` promises, keyed by userId — singleflight deduplication. */
|
|
87
|
+
_inflight = new Map();
|
|
88
|
+
/** Per-user cache TTL for `checkLimit` results. */
|
|
89
|
+
static CACHE_TTL_MS = 30_000;
|
|
73
90
|
// ── Internal helpers ──────────────────────────────────────────────────────
|
|
74
91
|
_headers() {
|
|
75
92
|
return {
|
|
@@ -91,12 +108,46 @@ export class PortalBillingProvider {
|
|
|
91
108
|
}
|
|
92
109
|
// ── BillingProvider interface ─────────────────────────────────────────────
|
|
93
110
|
async checkLimit(userId, hasPersonalKey) {
|
|
111
|
+
// BYOK users are always allowed — no Portal call needed.
|
|
94
112
|
if (hasPersonalKey) {
|
|
95
113
|
return { ok: true, remaining: Infinity, topUpBalance: 0, totalAvailable: Infinity, useTopUp: false, tier: 'byok' };
|
|
96
114
|
}
|
|
115
|
+
// Return cached result if still fresh.
|
|
116
|
+
const cached = this._cache.get(userId);
|
|
117
|
+
if (cached && Date.now() < cached.expiresAt) {
|
|
118
|
+
return cached.result;
|
|
119
|
+
}
|
|
120
|
+
// Singleflight: if a request is already in flight for this user, join it.
|
|
121
|
+
const existing = this._inflight.get(userId);
|
|
122
|
+
if (existing)
|
|
123
|
+
return existing;
|
|
124
|
+
// Issue a new Portal request and register it as the in-flight promise.
|
|
125
|
+
const promise = this._fetchLimit(userId);
|
|
126
|
+
this._inflight.set(userId, promise);
|
|
127
|
+
try {
|
|
128
|
+
return await promise;
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
this._inflight.delete(userId);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Clear the cached limit check result for a user.
|
|
136
|
+
*
|
|
137
|
+
* Called by `UsageBuffer` after a successful batch flush so the next
|
|
138
|
+
* `checkLimit` call fetches fresh data from Portal rather than serving
|
|
139
|
+
* a stale credit balance.
|
|
140
|
+
*
|
|
141
|
+
* @param userId - The user's email address (same key used in `checkLimit`).
|
|
142
|
+
*/
|
|
143
|
+
invalidateCache(userId) {
|
|
144
|
+
this._cache.delete(userId);
|
|
145
|
+
}
|
|
146
|
+
/** Perform the actual Portal HTTP call and populate the cache. */
|
|
147
|
+
async _fetchLimit(userId) {
|
|
97
148
|
try {
|
|
98
149
|
const result = await this._post('/api/credits/check', { userEmail: userId, product: this.product });
|
|
99
|
-
|
|
150
|
+
const limitResult = {
|
|
100
151
|
ok: result.ok,
|
|
101
152
|
remaining: result.remaining ?? 0,
|
|
102
153
|
topUpBalance: result.topUpBalance ?? 0,
|
|
@@ -105,9 +156,15 @@ export class PortalBillingProvider {
|
|
|
105
156
|
tier: result.tier === 'free' ? 'free' : 'standard',
|
|
106
157
|
...(!result.ok && result.reason ? { reason: result.reason === 'no_subscription' ? 'no_subscription' : 'limit_reached' } : {}),
|
|
107
158
|
};
|
|
159
|
+
this._cache.set(userId, {
|
|
160
|
+
result: limitResult,
|
|
161
|
+
expiresAt: Date.now() + PortalBillingProvider.CACHE_TTL_MS,
|
|
162
|
+
});
|
|
163
|
+
return limitResult;
|
|
108
164
|
}
|
|
109
165
|
catch {
|
|
110
166
|
// Network failure — fail open to avoid blocking AI calls due to Portal downtime.
|
|
167
|
+
// Do not cache failure results so the next call retries immediately.
|
|
111
168
|
return { ok: true, remaining: 1, topUpBalance: 0, totalAvailable: 1, useTopUp: false, tier: 'standard' };
|
|
112
169
|
}
|
|
113
170
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portal-provider.js","sourceRoot":"","sources":["../../../src/modules/billing/portal-provider.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"portal-provider.js","sourceRoot":"","sources":["../../../src/modules/billing/portal-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -185,6 +185,8 @@ export interface BillingProvider {
|
|
|
185
185
|
hasActiveSubscription(userId: string): Promise<boolean>;
|
|
186
186
|
getTopUpBalance(userId: string): Promise<number>;
|
|
187
187
|
canAccessPaidFeature(userId: string): Promise<boolean>;
|
|
188
|
+
/** Clear cached limit data for a user. Called by `UsageBuffer` after a successful flush. */
|
|
189
|
+
invalidateCache?(userId: string): void;
|
|
188
190
|
}
|
|
189
191
|
/**
|
|
190
192
|
* Accumulated usage data for a batch flush.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/modules/billing/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/modules/billing/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage-buffer.d.ts","sourceRoot":"","sources":["../../../src/modules/billing/usage-buffer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,YAAY,CAAA;AAcrE;;;;;;GAMG;AACH,qBAAa,WAAW;IAOV,OAAO,CAAC,QAAQ,CAAC,QAAQ;IANrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAC7D,OAAO,CAAC,MAAM,CAA4C;IAE1D;;OAEG;gBAC0B,QAAQ,EAAE,eAAe;IAItD;;;;;;;;;;;OAWG;IACH,SAAS,CACP,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,OAAO,GAChB,IAAI;IAmBP;;;;;;;OAOG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"usage-buffer.d.ts","sourceRoot":"","sources":["../../../src/modules/billing/usage-buffer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,YAAY,CAAA;AAcrE;;;;;;GAMG;AACH,qBAAa,WAAW;IAOV,OAAO,CAAC,QAAQ,CAAC,QAAQ;IANrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAC7D,OAAO,CAAC,MAAM,CAA4C;IAE1D;;OAEG;gBAC0B,QAAQ,EAAE,eAAe;IAItD;;;;;;;;;;;OAWG;IACH,SAAS,CACP,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,OAAO,GAChB,IAAI;IAmBP;;;;;;;OAOG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC5B;;;OAGG;IACH,IAAI,IAAI,IAAI;IASZ,OAAO,CAAC,MAAM;IASd,OAAO,CAAC,QAAQ;CAgBjB"}
|
|
@@ -94,7 +94,13 @@ export class UsageBuffer {
|
|
|
94
94
|
topUpUsed: acc.topUpUsed,
|
|
95
95
|
byModel: acc.byModel,
|
|
96
96
|
};
|
|
97
|
-
promises.push(this.provider.batchIncrementUsage(userId, batch)
|
|
97
|
+
promises.push(this.provider.batchIncrementUsage(userId, batch)
|
|
98
|
+
.then(() => {
|
|
99
|
+
// Invalidate cached limit data so the next checkLimit fetches a fresh
|
|
100
|
+
// credit balance from Portal rather than serving a stale count.
|
|
101
|
+
this.provider.invalidateCache?.(userId);
|
|
102
|
+
})
|
|
103
|
+
.catch((err) => {
|
|
98
104
|
console.error(`[SDK/billing] Usage flush failed for user ${userId}:`, err);
|
|
99
105
|
// Re-enqueue the failed batch so it is retried on the next flush.
|
|
100
106
|
this._requeue(userId, acc);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage-buffer.js","sourceRoot":"","sources":["../../../src/modules/billing/usage-buffer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,sCAAsC;AACtC,MAAM,iBAAiB,GAAG,KAAK,CAAA;AAW/B;;;;;;GAMG;AACH,MAAM,OAAO,WAAW;IAOO;IANZ,OAAO,GAAG,IAAI,GAAG,EAA2B,CAAA;IACrD,MAAM,CAA4C;IAE1D;;OAEG;IACH,YAA6B,QAAyB;QAAzB,aAAQ,GAAR,QAAQ,CAAiB;QACpD,IAAI,CAAC,MAAM,EAAE,CAAA;IACf,CAAC;IAED;;;;;;;;;;;OAWG;IACH,SAAS,CACP,MAAc,EACd,WAAmB,EACnB,YAAoB,EACpB,KAAa,EACb,QAAiB;QAEjB,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAClC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAA;YACrF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAC/B,CAAC;QAED,GAAG,CAAC,YAAY,IAAI,CAAC,CAAA;QACrB,GAAG,CAAC,WAAW,IAAI,WAAW,CAAA;QAC9B,GAAG,CAAC,YAAY,IAAI,YAAY,CAAA;QAChC,IAAI,QAAQ;YAAE,GAAG,CAAC,SAAS,IAAI,CAAC,CAAA;QAEhC,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAA;QAC9D,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG;YACnB,KAAK,EAAE,QAAQ,CAAC,KAAK,GAAG,WAAW;YACnC,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,YAAY;SACvC,CAAA;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC;YAAE,OAAM;QAEnC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACtC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;QAEpB,MAAM,QAAQ,GAAoB,EAAE,CAAA;QACpC,KAAK,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,QAAQ,EAAE,CAAC;YACrC,MAAM,KAAK,GAAuB;gBAChC,YAAY,EAAE,GAAG,CAAC,YAAY;gBAC9B,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,YAAY,EAAE,GAAG,CAAC,YAAY;gBAC9B,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,OAAO,EAAE,GAAG,CAAC,OAAO;aACrB,CAAA;YACD,QAAQ,CAAC,IAAI,CACX,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"usage-buffer.js","sourceRoot":"","sources":["../../../src/modules/billing/usage-buffer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module modules/brainy/ydoc-manager
|
|
3
|
+
* @description Server-side Y.js document pool with binary append-log persistence.
|
|
4
|
+
*
|
|
5
|
+
* `YDocManager` maintains a pool of live `Y.Doc` instances, one per open file across
|
|
6
|
+
* all connected peers. Every Y.js update (each keypress or structural change) is
|
|
7
|
+
* immediately appended to a `.ydoc` binary file in Brainy's VFS alongside the
|
|
8
|
+
* human-readable `.wdoc`/`.wslide`/`.wviz` file. Brainy's mmap/SSD storage makes
|
|
9
|
+
* per-keypress appends essentially free.
|
|
10
|
+
*
|
|
11
|
+
* ## Persistence strategy
|
|
12
|
+
*
|
|
13
|
+
* ```
|
|
14
|
+
* /project/chapter-1.wdoc ← WDOC JSON, flushed from Y.Doc every 30s
|
|
15
|
+
* /project/chapter-1.ydoc ← binary Y.js update log, every keypress
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* - **On every Y.js update:** append binary update to `.ydoc` via `vfs.appendFile`.
|
|
19
|
+
* - **Every 30s (debounced):** flush the live Y.Doc to `.wdoc` JSON so the canonical
|
|
20
|
+
* format stays fresh for API consumers that read `.wdoc` directly.
|
|
21
|
+
* - **On last peer disconnect:** flush `.wdoc` immediately, then discard the Y.Doc
|
|
22
|
+
* from memory. No warm cache — `.ydoc` binary replay is instant on mmap/SSD.
|
|
23
|
+
* - **On cold start (next peer):** reconstruct Y.Doc by replaying the `.ydoc` log
|
|
24
|
+
* via `Y.applyUpdate`. Falls back to converting `.wdoc` JSON if no `.ydoc` exists.
|
|
25
|
+
*
|
|
26
|
+
* ## Invalidation
|
|
27
|
+
*
|
|
28
|
+
* When a VFS write bypasses Y.js (e.g. import, API overwrite), call `invalidate()`
|
|
29
|
+
* to rebuild the `.ydoc` log from the new `.wdoc` content so future peers get
|
|
30
|
+
* the correct document state.
|
|
31
|
+
*
|
|
32
|
+
* ## Scope key
|
|
33
|
+
*
|
|
34
|
+
* Documents are keyed by `${scope}:${filePath}` where scope is `${emailHash}:${workspaceId}`.
|
|
35
|
+
* This matches the WebSocket session scope so the manager can be addressed directly
|
|
36
|
+
* from message handlers without additional routing.
|
|
37
|
+
*/
|
|
38
|
+
import * as Y from 'yjs';
|
|
39
|
+
import type { Brainy } from '@soulcraft/brainy';
|
|
40
|
+
/**
|
|
41
|
+
* Server-side pool of Y.js documents with binary append-log persistence.
|
|
42
|
+
*
|
|
43
|
+
* One shared instance per product server process. Pass it to `createBrainyWsHandler`
|
|
44
|
+
* so the WebSocket message handler can route Y.js messages to the correct doc.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* import { YDocManager } from '@soulcraft/sdk/server'
|
|
49
|
+
* import { pool } from './instance-pool'
|
|
50
|
+
*
|
|
51
|
+
* export const ydocManager = new YDocManager()
|
|
52
|
+
*
|
|
53
|
+
* const wsHandler = createBrainyWsHandler({
|
|
54
|
+
* resolveBrain: (scope) => pool.forTenant(scope),
|
|
55
|
+
* authenticate: (token, scope) => verifyCapabilityToken(token, process.env.WS_TOKEN_SECRET!),
|
|
56
|
+
* ydocManager,
|
|
57
|
+
* })
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare class YDocManager {
|
|
61
|
+
/** Pool of live Y.Doc instances keyed by `${scope}:${filePath}`. */
|
|
62
|
+
private readonly docs;
|
|
63
|
+
/**
|
|
64
|
+
* Returns the live Y.Doc for the given scope + file, loading from the `.ydoc`
|
|
65
|
+
* binary log (or converting from the canonical format) on first access.
|
|
66
|
+
*
|
|
67
|
+
* Registers `peerId` as an active peer so the manager can track when the last
|
|
68
|
+
* peer disconnects.
|
|
69
|
+
*
|
|
70
|
+
* @param scope - The session scope (`${emailHash}:${workspaceId}`).
|
|
71
|
+
* @param filePath - Absolute VFS path to the source file (e.g. `/proj/doc.wdoc`).
|
|
72
|
+
* @param brain - The Brainy instance owning the VFS for this scope.
|
|
73
|
+
* @param peerId - Unique ID for the connecting peer.
|
|
74
|
+
* @returns The live `Y.Doc` for this file.
|
|
75
|
+
*/
|
|
76
|
+
getOrCreate(scope: string, filePath: string, brain: Brainy, peerId: string): Promise<Y.Doc>;
|
|
77
|
+
/**
|
|
78
|
+
* Applies a Y.js update received from a peer.
|
|
79
|
+
*
|
|
80
|
+
* - Applies the update to the in-memory Y.Doc.
|
|
81
|
+
* - Appends the raw binary update to the `.ydoc` log immediately.
|
|
82
|
+
*
|
|
83
|
+
* The debounced 30s flush to the canonical format runs independently.
|
|
84
|
+
*
|
|
85
|
+
* @param scope - Session scope.
|
|
86
|
+
* @param filePath - Absolute VFS path to the source file.
|
|
87
|
+
* @param update - Raw binary Y.js update (from `Y.encodeStateAsUpdate` or an observer).
|
|
88
|
+
*/
|
|
89
|
+
applyUpdate(scope: string, filePath: string, update: Uint8Array): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Returns the current Y.js state vector for the given document.
|
|
92
|
+
*
|
|
93
|
+
* Used during the Y.js sync protocol: the client sends its state vector,
|
|
94
|
+
* the server replies with the diff (all updates the client is missing).
|
|
95
|
+
*
|
|
96
|
+
* @param scope - Session scope.
|
|
97
|
+
* @param filePath - Absolute VFS path to the source file.
|
|
98
|
+
* @returns Encoded state vector as `Uint8Array`.
|
|
99
|
+
*/
|
|
100
|
+
getStateVector(scope: string, filePath: string, brain: Brainy): Promise<Uint8Array>;
|
|
101
|
+
/**
|
|
102
|
+
* Returns the Y.js diff between the server's state and the client's state vector.
|
|
103
|
+
*
|
|
104
|
+
* Called after the client sends a `y-sync` message. The diff contains all updates
|
|
105
|
+
* the client is missing so it can catch up to the server's current state.
|
|
106
|
+
*
|
|
107
|
+
* @param scope - Session scope.
|
|
108
|
+
* @param filePath - Absolute VFS path to the source file.
|
|
109
|
+
* @param clientStateVector - The state vector encoded by the client.
|
|
110
|
+
* @returns Encoded update diff as `Uint8Array`.
|
|
111
|
+
*/
|
|
112
|
+
getDiff(scope: string, filePath: string, brain: Brainy, clientStateVector: Uint8Array): Promise<Uint8Array>;
|
|
113
|
+
/**
|
|
114
|
+
* Notifies the manager that a peer has disconnected from the given document.
|
|
115
|
+
*
|
|
116
|
+
* If this was the last peer:
|
|
117
|
+
* 1. Flushes the Y.Doc to the canonical format immediately.
|
|
118
|
+
* 2. Cancels the periodic flush timer.
|
|
119
|
+
* 3. Destroys and discards the Y.Doc from memory.
|
|
120
|
+
*
|
|
121
|
+
* No warm cache — `.ydoc` binary replay is instant on mmap/SSD.
|
|
122
|
+
*
|
|
123
|
+
* @param scope - Session scope.
|
|
124
|
+
* @param filePath - Absolute VFS path to the source file.
|
|
125
|
+
* @param peerId - The peer that disconnected.
|
|
126
|
+
*/
|
|
127
|
+
onPeerDisconnect(scope: string, filePath: string, peerId: string): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* Invalidates a cached Y.Doc when the canonical file is overwritten externally
|
|
130
|
+
* (e.g. via import or direct API write that bypasses Y.js).
|
|
131
|
+
*
|
|
132
|
+
* If the document is currently in memory (has active peers), it is rebuilt from
|
|
133
|
+
* the new canonical file content. If no peers are connected, any stale `.ydoc`
|
|
134
|
+
* log is deleted so the next cold start reads the new canonical file.
|
|
135
|
+
*
|
|
136
|
+
* @param scope - Session scope.
|
|
137
|
+
* @param filePath - Absolute VFS path to the source file.
|
|
138
|
+
* @param brain - The Brainy instance owning the VFS.
|
|
139
|
+
*/
|
|
140
|
+
invalidate(scope: string, filePath: string, brain: Brainy): Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* Notifies the manager that a peer has disconnected from ALL documents it had open.
|
|
143
|
+
*
|
|
144
|
+
* Called from `BrainyWsHandler.handleClose()` when a WebSocket connection closes.
|
|
145
|
+
* Iterates all documents in this scope and removes the peer — if it was the last
|
|
146
|
+
* peer on any document, that document is flushed and discarded immediately.
|
|
147
|
+
*
|
|
148
|
+
* @param scope - Session scope (`${emailHash}:${workspaceId}`).
|
|
149
|
+
* @param peerId - The peer that disconnected.
|
|
150
|
+
*/
|
|
151
|
+
onPeerDisconnectAll(scope: string, peerId: string): Promise<void>;
|
|
152
|
+
/**
|
|
153
|
+
* Flushes and discards all Y.Docs for a given scope.
|
|
154
|
+
*
|
|
155
|
+
* Called during unpublish to clean up all open documents for a project before
|
|
156
|
+
* the project is removed from the publish registry.
|
|
157
|
+
*
|
|
158
|
+
* @param scope - Session scope (`${emailHash}:${workspaceId}`).
|
|
159
|
+
*/
|
|
160
|
+
flushAndDiscardScope(scope: string): Promise<void>;
|
|
161
|
+
/**
|
|
162
|
+
* Loads a Y.Doc from the `.ydoc` binary log, falling back to converting the
|
|
163
|
+
* canonical file if no log exists yet.
|
|
164
|
+
*/
|
|
165
|
+
private _load;
|
|
166
|
+
/**
|
|
167
|
+
* Schedules the periodic 30s flush for the given document entry.
|
|
168
|
+
*/
|
|
169
|
+
private _scheduleFlush;
|
|
170
|
+
/**
|
|
171
|
+
* Flushes the live Y.Doc to the canonical format in the VFS.
|
|
172
|
+
*/
|
|
173
|
+
private _flush;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=ydoc-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ydoc-manager.d.ts","sourceRoot":"","sources":["../../../src/modules/brainy/ydoc-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AACxB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AA0C/C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,WAAW;IACtB,oEAAoE;IACpE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA8B;IAInD;;;;;;;;;;;;OAYG;IACG,WAAW,CACf,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAwBjB;;;;;;;;;;;OAWG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAWrF;;;;;;;;;OASG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAYzF;;;;;;;;;;OAUG;IACG,OAAO,CACX,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,iBAAiB,EAAE,UAAU,GAC5B,OAAO,CAAC,UAAU,CAAC;IAYtB;;;;;;;;;;;;;OAaG;IACG,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBtF;;;;;;;;;;;OAWG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA2B/E;;;;;;;;;OASG;IACG,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBvE;;;;;;;OAOG;IACG,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBxD;;;OAGG;YACW,KAAK;IA2BnB;;OAEG;IACH,OAAO,CAAC,cAAc;IAQtB;;OAEG;YACW,MAAM;CAQrB"}
|