@vibesdotdev/account 1.0.0-rc.4 → 1.0.0-rc.5
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/billing/internal/quota-client.d.ts +59 -0
- package/dist/billing/internal/quota-client.d.ts.map +1 -1
- package/dist/billing/internal/quota-client.js +102 -1
- package/dist/billing/internal/quota-client.js.map +1 -1
- package/dist/billing/overage/overage-policy.config.descriptor.d.ts +114 -0
- package/dist/billing/overage/overage-policy.config.descriptor.d.ts.map +1 -0
- package/dist/billing/overage/overage-policy.config.descriptor.js +52 -0
- package/dist/billing/overage/overage-policy.config.descriptor.js.map +1 -0
- package/dist/billing/overage/overage-policy.d.ts +159 -0
- package/dist/billing/overage/overage-policy.d.ts.map +1 -0
- package/dist/billing/overage/overage-policy.js +93 -0
- package/dist/billing/overage/overage-policy.js.map +1 -0
- package/dist/billing/usage/delivery.d.ts +96 -1
- package/dist/billing/usage/delivery.d.ts.map +1 -1
- package/dist/billing/usage/delivery.js +55 -0
- package/dist/billing/usage/delivery.js.map +1 -1
- package/dist/billing/usage/record-code-session-usage.d.ts +9 -2
- package/dist/billing/usage/record-code-session-usage.d.ts.map +1 -1
- package/dist/billing/usage/record-code-session-usage.js +4 -1
- package/dist/billing/usage/record-code-session-usage.js.map +1 -1
- package/dist/billing/usage/record-platform-resource.d.ts +14 -2
- package/dist/billing/usage/record-platform-resource.d.ts.map +1 -1
- package/dist/billing/usage/record-platform-resource.js +25 -6
- package/dist/billing/usage/record-platform-resource.js.map +1 -1
- package/dist/billing/usage/record-sandbox-uptime.d.ts +16 -3
- package/dist/billing/usage/record-sandbox-uptime.d.ts.map +1 -1
- package/dist/billing/usage/record-sandbox-uptime.js +24 -5
- package/dist/billing/usage/record-sandbox-uptime.js.map +1 -1
- package/dist/plugin/billing-overage.d.ts +9 -0
- package/dist/plugin/billing-overage.d.ts.map +1 -0
- package/dist/plugin/billing-overage.js +17 -0
- package/dist/plugin/billing-overage.js.map +1 -0
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +2 -0
- package/dist/plugin/index.js.map +1 -1
- package/package.json +14 -8
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Overage policy — what happens to running work when a billing subject's
|
|
3
|
+
* credits reach zero.
|
|
4
|
+
*
|
|
5
|
+
* Three behaviors:
|
|
6
|
+
* - `continue-invoice` — keep running and invoice the overage.
|
|
7
|
+
* - `pause` — pause immediately.
|
|
8
|
+
* - `continue-internal` — keep running, never invoice, and record the
|
|
9
|
+
* overage for system visibility.
|
|
10
|
+
*
|
|
11
|
+
* The declared defaults live in the `billing.overage` config manifest
|
|
12
|
+
* (`overage-policy.config.descriptor.ts`) and resolve through the runtime
|
|
13
|
+
* like any other setting; this module is the schema they parse against, never
|
|
14
|
+
* a second copy of the values. Account Web resolves a subject's behavior
|
|
15
|
+
* (`POST /api/billing/overage/resolve`): an explicit override for the user in
|
|
16
|
+
* the org, then the role in the org, then the org, then the class default,
|
|
17
|
+
* then `userDefault` for usage with no org. Callers never hard-code one.
|
|
18
|
+
*/
|
|
19
|
+
import * as z from 'zod/v4';
|
|
20
|
+
export const OVERAGE_POLICY_MANIFEST_ID = 'billing.overage';
|
|
21
|
+
export const OverageBehaviorSchema = z.enum(['continue-invoice', 'pause', 'continue-internal']);
|
|
22
|
+
/**
|
|
23
|
+
* The org class a default is keyed by. `enterprise` is an org whose
|
|
24
|
+
* subscription tier is `accountType: enterprise`; `standard` is every other
|
|
25
|
+
* individual or team org; `internal` is the org a system admin marks as
|
|
26
|
+
* Vibes-internal.
|
|
27
|
+
*/
|
|
28
|
+
export const OverageOrgClassSchema = z.enum(['enterprise', 'standard', 'internal']);
|
|
29
|
+
/** Who may set an org's overage behavior. */
|
|
30
|
+
export const OverageSetterRoleSchema = z.enum(['owner', 'admin']);
|
|
31
|
+
/**
|
|
32
|
+
* The behaviors the Vibes internal org may run under. Drew, 2026-10-29: the
|
|
33
|
+
* internal org "keeps moving" — it is never paused for credits, so `pause` is
|
|
34
|
+
* not a value its default can hold, and Account never resolves it to `pause`
|
|
35
|
+
* from an override either.
|
|
36
|
+
*/
|
|
37
|
+
export const InternalOverageBehaviorSchema = OverageBehaviorSchema.exclude(['pause']);
|
|
38
|
+
/** Per-class defaults (Drew, 2026-10-29). */
|
|
39
|
+
export const OverageClassDefaultsSchema = z.strictObject({
|
|
40
|
+
enterprise: OverageBehaviorSchema.default('continue-invoice'),
|
|
41
|
+
standard: OverageBehaviorSchema.default('pause'),
|
|
42
|
+
internal: InternalOverageBehaviorSchema.default('continue-internal')
|
|
43
|
+
});
|
|
44
|
+
/**
|
|
45
|
+
* Whether a `standard` org may opt in to `continue-invoice`, and on what
|
|
46
|
+
* terms. The terms are the lane D review's (2026-10-29): a payment method on
|
|
47
|
+
* file and an owner or admin making the choice. `allowed` defaults to true and
|
|
48
|
+
* is policy, so it can be changed without code.
|
|
49
|
+
*/
|
|
50
|
+
export const StandardContinueInvoicePolicySchema = z.strictObject({
|
|
51
|
+
allowed: z.boolean().default(true),
|
|
52
|
+
requiresPaymentMethod: z.boolean().default(true),
|
|
53
|
+
setterRoles: z.array(OverageSetterRoleSchema).min(1).default(['owner', 'admin'])
|
|
54
|
+
});
|
|
55
|
+
export const OveragePolicySchema = z.strictObject({
|
|
56
|
+
defaults: OverageClassDefaultsSchema.default(() => OverageClassDefaultsSchema.parse({})),
|
|
57
|
+
/** Usage billed to a user with no org. */
|
|
58
|
+
userDefault: OverageBehaviorSchema.default('pause'),
|
|
59
|
+
standardContinueInvoice: StandardContinueInvoicePolicySchema.default(() => StandardContinueInvoicePolicySchema.parse({}))
|
|
60
|
+
});
|
|
61
|
+
/** Where a resolved behavior came from, most specific first. */
|
|
62
|
+
export const OverageBehaviorSourceSchema = z.enum([
|
|
63
|
+
'user-override',
|
|
64
|
+
'role-override',
|
|
65
|
+
'org-override',
|
|
66
|
+
'class-default',
|
|
67
|
+
'user-default'
|
|
68
|
+
]);
|
|
69
|
+
/** A resolved overage behavior and where it came from. */
|
|
70
|
+
export const OverageResolutionSchema = z.object({
|
|
71
|
+
behavior: OverageBehaviorSchema,
|
|
72
|
+
source: OverageBehaviorSourceSchema
|
|
73
|
+
});
|
|
74
|
+
/**
|
|
75
|
+
* Whether an org of `orgClass` may choose `behavior`, set by `setterRole`.
|
|
76
|
+
* Only `continue-invoice` on a `standard` org is conditioned here; the
|
|
77
|
+
* owner/admin-edit rule for every other choice belongs to the override
|
|
78
|
+
* route's own authorization.
|
|
79
|
+
*/
|
|
80
|
+
export function overageChoiceRefusal(policy, choice) {
|
|
81
|
+
if (choice.orgClass !== 'standard' || choice.behavior !== 'continue-invoice')
|
|
82
|
+
return null;
|
|
83
|
+
const terms = policy.standardContinueInvoice;
|
|
84
|
+
if (!terms.allowed)
|
|
85
|
+
return 'standard-continue-invoice-disallowed';
|
|
86
|
+
if (terms.requiresPaymentMethod && !choice.hasPaymentMethod)
|
|
87
|
+
return 'payment-method-required';
|
|
88
|
+
if (choice.setterRole === 'member' || !terms.setterRoles.includes(choice.setterRole)) {
|
|
89
|
+
return 'setter-role-not-permitted';
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=overage-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overage-policy.js","sourceRoot":"","sources":["../../../src/billing/overage/overage-policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import type { Logger } from '@vibesdotdev/logging';
|
|
8
8
|
import { type Settled, type ValueFreeFailure } from '@vibesdotdev/kernel';
|
|
9
9
|
import type { JsonValue } from '@vibesdotdev/kernel/schemas/json';
|
|
10
|
+
import { type OverageBehavior, type OverageBehaviorSource } from '../overage/overage-policy.ts';
|
|
10
11
|
/** Metadata a usage event carries to Account Web: JSON values; an undefined entry is dropped when serialized. */
|
|
11
12
|
export type BillingEventMetadata = Record<string, JsonValue | undefined>;
|
|
12
13
|
/** How a delivery failed: a non-2xx status, the deadline, or a thrown failure described value-free. */
|
|
@@ -20,7 +21,10 @@ export type DeliveryFailure = {
|
|
|
20
21
|
error: ValueFreeFailure;
|
|
21
22
|
};
|
|
22
23
|
/** The failure a settled delivery ended with, or null when Account Web accepted it. */
|
|
23
|
-
export declare function deliveryFailure(delivered: Settled<
|
|
24
|
+
export declare function deliveryFailure(delivered: Settled<{
|
|
25
|
+
readonly ok: boolean;
|
|
26
|
+
readonly status: number;
|
|
27
|
+
}>): DeliveryFailure | null;
|
|
24
28
|
/** The journal message for a failed delivery: the status, the deadline, or the failure class, never response text. */
|
|
25
29
|
export declare function deliveryFailureMessage(failure: DeliveryFailure, timeoutMs: number): string;
|
|
26
30
|
/**
|
|
@@ -31,4 +35,95 @@ export declare function deliveryFailureMessage(failure: DeliveryFailure, timeout
|
|
|
31
35
|
export declare function keepAlive<Platform>(logger: Pick<Logger, 'error'>, label: string, platform: Platform, promise: Promise<void>): void;
|
|
32
36
|
/** Run a caller's journal callback; a throw or rejection is logged by failure class, never raised into the emitter. */
|
|
33
37
|
export declare function notifyJournal(logger: Pick<Logger, 'warn'>, label: string, callback: (() => Promise<void> | void) | undefined): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* What Account Web did with a delivered usage record, as
|
|
40
|
+
* `/api/billing/usage/record-internal` reports it in its 200 body.
|
|
41
|
+
*
|
|
42
|
+
* Delivery and deduction are separate facts. The usage row is written before
|
|
43
|
+
* the credit deduction, so a record that could not be paid for is still
|
|
44
|
+
* DELIVERED: the journal marks it delivered and the reconciler must not retry
|
|
45
|
+
* it (a retry would write a second usage row). The deduction outcome is what
|
|
46
|
+
* tells a caller the charge was not collected.
|
|
47
|
+
*
|
|
48
|
+
* - `charged` — the rated charge was deducted in full.
|
|
49
|
+
* - `shortfall` — the pools could not cover the charge; `charged` is what
|
|
50
|
+
* was deducted and `shortfallUsd` the uncollected
|
|
51
|
+
* cost-basis USD (rating value of the credits not paid).
|
|
52
|
+
* It carries the subject's overage behavior (see
|
|
53
|
+
* {@link UsageRecordOverage}) so a caller can enforce it.
|
|
54
|
+
* - `unrecorded` — Account Web accepted the request but recorded no charge
|
|
55
|
+
* for a reason other than balance (unknown feature, a
|
|
56
|
+
* failed insert).
|
|
57
|
+
* - `unreported` — the body did not carry the outcome (an Account Web that
|
|
58
|
+
* predates it, or an unreadable body). Never read as paid.
|
|
59
|
+
*/
|
|
60
|
+
export type UsageRecordOutcome = {
|
|
61
|
+
readonly status: 'charged';
|
|
62
|
+
readonly charged: number;
|
|
63
|
+
} | ({
|
|
64
|
+
readonly status: 'shortfall';
|
|
65
|
+
readonly charged: number;
|
|
66
|
+
readonly shortfallUsd: number;
|
|
67
|
+
} & UsageRecordOverage) | {
|
|
68
|
+
readonly status: 'unrecorded';
|
|
69
|
+
readonly error: string;
|
|
70
|
+
} | {
|
|
71
|
+
readonly status: 'unreported';
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* The overage facts a shortfall carries, as record-internal reports them
|
|
75
|
+
* (lane D step 3): the subject's resolved overage behavior, the layer that
|
|
76
|
+
* decided it, and the overage record written for the shortfall.
|
|
77
|
+
*
|
|
78
|
+
* Each is null when the answering Account Web did not report it (one that
|
|
79
|
+
* predates the field) or reported a value this client cannot read. A null
|
|
80
|
+
* behavior is never read as any behavior: an enforcer acts only on an
|
|
81
|
+
* explicit `pause`.
|
|
82
|
+
*/
|
|
83
|
+
export interface UsageRecordOverage {
|
|
84
|
+
readonly behavior: OverageBehavior | null;
|
|
85
|
+
readonly behaviorSource: OverageBehaviorSource | null;
|
|
86
|
+
/** The `billing_overage_records` row; null when none was written or reported. */
|
|
87
|
+
readonly overageRecordId: string | null;
|
|
88
|
+
}
|
|
89
|
+
/** Read the deduction outcome from a record-internal 200 body. */
|
|
90
|
+
export declare function usageRecordOutcome(body: JsonValue): UsageRecordOutcome;
|
|
91
|
+
/** A settled record-internal response: its status, and on a 2xx the outcome its body reported. */
|
|
92
|
+
export interface UsageRecordDelivery {
|
|
93
|
+
readonly ok: boolean;
|
|
94
|
+
readonly status: number;
|
|
95
|
+
readonly outcome: UsageRecordOutcome | null;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Read a record-internal response, body included. Call it inside the same
|
|
99
|
+
* lifecycle deadline as the fetch, so a stalled body is a timeout rather than
|
|
100
|
+
* a read that outlives the emitter's budget.
|
|
101
|
+
*/
|
|
102
|
+
export declare function readUsageRecordDelivery(response: Response): Promise<UsageRecordDelivery>;
|
|
103
|
+
/**
|
|
104
|
+
* How one fire-and-forget usage emission ended: skipped before sending, not
|
|
105
|
+
* delivered, or delivered with the deduction outcome Account Web reported.
|
|
106
|
+
* Every record-internal emitter reports through this one shape, so a caller
|
|
107
|
+
* reads a shortfall the same way whichever emitter it used.
|
|
108
|
+
*/
|
|
109
|
+
export type UsageEmissionOutcome = {
|
|
110
|
+
readonly delivery: 'skipped';
|
|
111
|
+
readonly message: string;
|
|
112
|
+
} | {
|
|
113
|
+
readonly delivery: 'failed';
|
|
114
|
+
readonly failure: DeliveryFailure;
|
|
115
|
+
} | {
|
|
116
|
+
readonly delivery: 'delivered';
|
|
117
|
+
readonly outcome: UsageRecordOutcome;
|
|
118
|
+
};
|
|
119
|
+
/** A settled record-internal call: not delivered (and why), or delivered with its deduction outcome. */
|
|
120
|
+
export type UsageRecordSettlement = {
|
|
121
|
+
readonly delivered: false;
|
|
122
|
+
readonly failure: DeliveryFailure;
|
|
123
|
+
} | {
|
|
124
|
+
readonly delivered: true;
|
|
125
|
+
readonly outcome: UsageRecordOutcome;
|
|
126
|
+
};
|
|
127
|
+
/** Classify a settled {@link readUsageRecordDelivery}; a 2xx without a readable outcome is `unreported`. */
|
|
128
|
+
export declare function usageRecordSettlement(settled: Settled<UsageRecordDelivery>): UsageRecordSettlement;
|
|
34
129
|
//# sourceMappingURL=delivery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/delivery.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAuC,KAAK,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC/G,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/delivery.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import * as z from 'zod/v4';
|
|
8
8
|
import { settle, settleNow, valueFreeFailure } from '@vibesdotdev/kernel';
|
|
9
9
|
import { isWaitTimeout } from "./wait-timeout.js";
|
|
10
|
+
import { OverageBehaviorSchema, OverageBehaviorSourceSchema } from "../overage/overage-policy.js";
|
|
10
11
|
/** The failure a settled delivery ended with, or null when Account Web accepted it. */
|
|
11
12
|
export function deliveryFailure(delivered) {
|
|
12
13
|
if (delivered.ok)
|
|
@@ -58,4 +59,58 @@ export async function notifyJournal(logger, label, callback) {
|
|
|
58
59
|
error: valueFreeFailure(settled.cause)
|
|
59
60
|
});
|
|
60
61
|
}
|
|
62
|
+
/** The fields of the record-internal 200 body the outcome is read from. */
|
|
63
|
+
const recordInternalOutcomeBodySchema = z.object({
|
|
64
|
+
success: z.boolean(),
|
|
65
|
+
charged: z.number().nonnegative(),
|
|
66
|
+
shortfallUsd: z.number().nonnegative(),
|
|
67
|
+
error: z.string().optional(),
|
|
68
|
+
behavior: OverageBehaviorSchema.nullable().optional().catch(null),
|
|
69
|
+
behaviorSource: OverageBehaviorSourceSchema.nullable().optional().catch(null),
|
|
70
|
+
overageRecordId: z.string().min(1).nullable().optional().catch(null)
|
|
71
|
+
});
|
|
72
|
+
/** Read the deduction outcome from a record-internal 200 body. */
|
|
73
|
+
export function usageRecordOutcome(body) {
|
|
74
|
+
const parsed = recordInternalOutcomeBodySchema.safeParse(body);
|
|
75
|
+
if (!parsed.success)
|
|
76
|
+
return { status: 'unreported' };
|
|
77
|
+
const { success, charged, shortfallUsd, error } = parsed.data;
|
|
78
|
+
if (shortfallUsd > 0) {
|
|
79
|
+
return {
|
|
80
|
+
status: 'shortfall',
|
|
81
|
+
charged,
|
|
82
|
+
shortfallUsd,
|
|
83
|
+
behavior: parsed.data.behavior ?? null,
|
|
84
|
+
behaviorSource: parsed.data.behaviorSource ?? null,
|
|
85
|
+
overageRecordId: parsed.data.overageRecordId ?? null
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (!success)
|
|
89
|
+
return { status: 'unrecorded', error: error ?? 'not recorded' };
|
|
90
|
+
return { status: 'charged', charged };
|
|
91
|
+
}
|
|
92
|
+
const jsonBodySchema = z.json();
|
|
93
|
+
/**
|
|
94
|
+
* Read a record-internal response, body included. Call it inside the same
|
|
95
|
+
* lifecycle deadline as the fetch, so a stalled body is a timeout rather than
|
|
96
|
+
* a read that outlives the emitter's budget.
|
|
97
|
+
*/
|
|
98
|
+
export async function readUsageRecordDelivery(response) {
|
|
99
|
+
if (!response.ok)
|
|
100
|
+
return { ok: false, status: response.status, outcome: null };
|
|
101
|
+
const body = await settle(async () => jsonBodySchema.parse(await response.json()));
|
|
102
|
+
return {
|
|
103
|
+
ok: true,
|
|
104
|
+
status: response.status,
|
|
105
|
+
outcome: body.ok ? usageRecordOutcome(body.value) : { status: 'unreported' }
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/** Classify a settled {@link readUsageRecordDelivery}; a 2xx without a readable outcome is `unreported`. */
|
|
109
|
+
export function usageRecordSettlement(settled) {
|
|
110
|
+
const failure = deliveryFailure(settled);
|
|
111
|
+
if (failure)
|
|
112
|
+
return { delivered: false, failure };
|
|
113
|
+
const outcome = settled.ok ? settled.value.outcome : null;
|
|
114
|
+
return { delivered: true, outcome: outcome ?? { status: 'unreported' } };
|
|
115
|
+
}
|
|
61
116
|
//# sourceMappingURL=delivery.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delivery.js","sourceRoot":"","sources":["../../../src/billing/usage/delivery.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAuC,MAAM,qBAAqB,CAAC;AAE/G,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"delivery.js","sourceRoot":"","sources":["../../../src/billing/usage/delivery.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
import type { RuntimeRef } from '@vibesdotdev/kernel';
|
|
27
27
|
import type { CostBasis } from '../rating/schemas/cost-basis.ts';
|
|
28
28
|
import type { HardwarePath } from '../rating/schemas/rated-usage.ts';
|
|
29
|
-
import { type PlatformResourceReason } from './record-platform-resource.ts';
|
|
30
|
-
import type
|
|
29
|
+
import { type PlatformResourceOutcome, type PlatformResourceReason } from './record-platform-resource.ts';
|
|
30
|
+
import { type BillingEventMetadata } from './delivery.ts';
|
|
31
31
|
/** The metadata this emitter's input accepts: JSON values, undefined entries dropped. */
|
|
32
32
|
export type { BillingEventMetadata };
|
|
33
33
|
export interface RecordCodeSessionUsageInput {
|
|
@@ -80,6 +80,13 @@ export interface RecordCodeSessionUsageInput {
|
|
|
80
80
|
message: string;
|
|
81
81
|
}) => Promise<void> | void;
|
|
82
82
|
};
|
|
83
|
+
/**
|
|
84
|
+
* Receives how the emission ended, deduction outcome included (see
|
|
85
|
+
* `record-platform-resource`). A `shortfall` carries the owner's overage
|
|
86
|
+
* behavior, which the code-session meter enforces. Always called once: a
|
|
87
|
+
* zero-compute emission sends nothing and reports `skipped`.
|
|
88
|
+
*/
|
|
89
|
+
onOutcome?: (outcome: PlatformResourceOutcome) => Promise<void> | void;
|
|
83
90
|
}
|
|
84
91
|
/**
|
|
85
92
|
* Fire-and-forget rated emission for code-session compute. Consumer / local
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-code-session-usage.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/record-code-session-usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAGrE,OAAO,EAEN,KAAK,sBAAsB,EAC3B,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"record-code-session-usage.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/record-code-session-usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAGrE,OAAO,EAEN,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAiB,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAEzE,yFAAyF;AACzF,YAAY,EAAE,oBAAoB,EAAE,CAAC;AAQrC,MAAM,WAAW,2BAA2B;IAC3C,8EAA8E;IAC9E,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,6DAA6D;IAC7D,oBAAoB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB,6FAA6F;IAC7F,MAAM,EAAE,sBAAsB,CAAC;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,4EAA4E;IAC5E,OAAO,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;YAClB,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;YAC9C,OAAO,EAAE,MAAM,CAAC;SAChB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC3B,CAAC;IACF;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACvE;AAYD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,2BAA2B,GAAG,IAAI,CA2CpG"}
|
|
@@ -27,6 +27,7 @@ import { getLogger } from '@vibesdotdev/logging';
|
|
|
27
27
|
import { FEATURE_SLUGS } from "../schemas/core/feature-slugs.js";
|
|
28
28
|
import { codeSessionComputeCostBasis } from "./build-session-cost-basis.js";
|
|
29
29
|
import { recordPlatformResource } from "./record-platform-resource.js";
|
|
30
|
+
import { notifyJournal } from "./delivery.js";
|
|
30
31
|
function log(runtime) {
|
|
31
32
|
return getLogger('account', runtime).child({ context: 'record-code-session-usage' });
|
|
32
33
|
}
|
|
@@ -52,6 +53,7 @@ export function recordCodeSessionUsage(runtime, input) {
|
|
|
52
53
|
sessionId: input.sessionId,
|
|
53
54
|
reason: input.reason
|
|
54
55
|
});
|
|
56
|
+
void notifyJournal(log(runtime), 'recordCodeSessionUsage', () => input.onOutcome?.({ delivery: 'skipped', message: 'zero-compute' }));
|
|
55
57
|
return;
|
|
56
58
|
}
|
|
57
59
|
const hardware = input.hardware ?? 'cloud';
|
|
@@ -79,7 +81,8 @@ export function recordCodeSessionUsage(runtime, input) {
|
|
|
79
81
|
computeSeconds,
|
|
80
82
|
...input.metadata
|
|
81
83
|
},
|
|
82
|
-
journal: input.journal
|
|
84
|
+
journal: input.journal,
|
|
85
|
+
onOutcome: input.onOutcome
|
|
83
86
|
});
|
|
84
87
|
}
|
|
85
88
|
//# sourceMappingURL=record-code-session-usage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-code-session-usage.js","sourceRoot":"","sources":["../../../src/billing/usage/record-code-session-usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAIjD,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EACN,sBAAsB,
|
|
1
|
+
{"version":3,"file":"record-code-session-usage.js","sourceRoot":"","sources":["../../../src/billing/usage/record-code-session-usage.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,13 +19,18 @@
|
|
|
19
19
|
* - Returns `void`; failures log structured context.
|
|
20
20
|
* - Honors the same journal callback contract as
|
|
21
21
|
* `record-sandbox-uptime` so app-local audit tables stay consistent.
|
|
22
|
+
* - A delivered record that could not be paid for is NOT success: the
|
|
23
|
+
* caller's `onOutcome` receives `shortfall` with the uncollected
|
|
24
|
+
* cost-basis USD, exactly as `record-sandbox-uptime` reports it.
|
|
22
25
|
*/
|
|
23
26
|
import { type RuntimeRef } from '@vibesdotdev/kernel';
|
|
24
|
-
import { type BillingEventMetadata } from './delivery.ts';
|
|
27
|
+
import { type BillingEventMetadata, type UsageEmissionOutcome, type UsageRecordOutcome } from './delivery.ts';
|
|
25
28
|
import type { CostBasis } from '../rating/schemas/cost-basis.ts';
|
|
26
29
|
import type { HardwarePath, MeasuredUnits } from '../rating/schemas/rated-usage.ts';
|
|
27
30
|
/** The metadata this emitter's input accepts: JSON values, undefined entries dropped. */
|
|
28
|
-
export type { BillingEventMetadata };
|
|
31
|
+
export type { BillingEventMetadata, UsageRecordOutcome };
|
|
32
|
+
/** How one platform-resource emission ended; the shared record-internal outcome. */
|
|
33
|
+
export type PlatformResourceOutcome = UsageEmissionOutcome;
|
|
29
34
|
export type PlatformResourceReason = 'sweep' | 'tick' | 'completion' | 'manual' | 'reconcile';
|
|
30
35
|
export interface RecordPlatformResourceInput {
|
|
31
36
|
/** Origin of the account app. Omit to skip metering. */
|
|
@@ -80,6 +85,13 @@ export interface RecordPlatformResourceInput {
|
|
|
80
85
|
message: string;
|
|
81
86
|
}) => Promise<void> | void;
|
|
82
87
|
};
|
|
88
|
+
/**
|
|
89
|
+
* Receives how the emission ended. The journal tracks DELIVERY (a
|
|
90
|
+
* delivered record must not be re-sent, or the usage row is written
|
|
91
|
+
* twice); this tracks whether the charge was collected. A `shortfall`
|
|
92
|
+
* outcome is delivered and still unpaid.
|
|
93
|
+
*/
|
|
94
|
+
onOutcome?: (outcome: PlatformResourceOutcome) => Promise<void> | void;
|
|
83
95
|
}
|
|
84
96
|
/**
|
|
85
97
|
* Fire-and-forget rated emission. Skipped silently when the inputs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-platform-resource.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/record-platform-resource.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"record-platform-resource.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/record-platform-resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAKN,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EACX,YAAY,EACZ,aAAa,EACb,MAAM,kCAAkC,CAAC;AAE1C,yFAAyF;AACzF,YAAY,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,CAAC;AAEzD,oFAAoF;AACpF,MAAM,MAAM,uBAAuB,GAAG,oBAAoB,CAAC;AAQ3D,MAAM,MAAM,sBAAsB,GAC/B,OAAO,GACP,MAAM,GACN,YAAY,GACZ,QAAQ,GACR,WAAW,CAAC;AAEf,MAAM,WAAW,2BAA2B;IAC3C,wDAAwD;IACxD,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,6DAA6D;IAC7D,oBAAoB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,aAAa,EAAE,aAAa,CAAC;IAC7B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,+BAA+B;IAC/B,MAAM,EAAE,sBAAsB,CAAC;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,yEAAyE;IACzE,OAAO,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;YAClB,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;YAC9C,OAAO,EAAE,MAAM,CAAC;SAChB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC3B,CAAC;IACF;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACvE;AAUD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,2BAA2B,GAAG,IAAI,CA6HpG"}
|
|
@@ -19,10 +19,13 @@
|
|
|
19
19
|
* - Returns `void`; failures log structured context.
|
|
20
20
|
* - Honors the same journal callback contract as
|
|
21
21
|
* `record-sandbox-uptime` so app-local audit tables stay consistent.
|
|
22
|
+
* - A delivered record that could not be paid for is NOT success: the
|
|
23
|
+
* caller's `onOutcome` receives `shortfall` with the uncollected
|
|
24
|
+
* cost-basis USD, exactly as `record-sandbox-uptime` reports it.
|
|
22
25
|
*/
|
|
23
26
|
import { getLogger } from '@vibesdotdev/logging';
|
|
24
27
|
import { settle } from '@vibesdotdev/kernel';
|
|
25
|
-
import {
|
|
28
|
+
import { deliveryFailureMessage, notifyJournal, readUsageRecordDelivery, usageRecordSettlement } from "./delivery.js";
|
|
26
29
|
function log(runtime) {
|
|
27
30
|
return getLogger('account', runtime).child({ context: 'record-platform-resource' });
|
|
28
31
|
}
|
|
@@ -42,8 +45,12 @@ function totalMeasured(units) {
|
|
|
42
45
|
*/
|
|
43
46
|
export function recordPlatformResource(runtime, input) {
|
|
44
47
|
const total = totalMeasured(input.measuredUnits);
|
|
45
|
-
if (total <= 0)
|
|
48
|
+
if (total <= 0) {
|
|
49
|
+
// Nothing to bill, but still an outcome: a caller waiting on
|
|
50
|
+
// `onOutcome` (the code-session meter) must always hear back.
|
|
51
|
+
void notifyJournal(log(runtime), 'recordPlatformResource', () => input.onOutcome?.({ delivery: 'skipped', message: 'zero-quantity' }));
|
|
46
52
|
return;
|
|
53
|
+
}
|
|
47
54
|
if (!input.billingUserId && !input.organizationId) {
|
|
48
55
|
const message = 'neither-billing-user-nor-organization-set';
|
|
49
56
|
log(runtime).debug('recordPlatformResource: skipping (' + message + ')', {
|
|
@@ -52,6 +59,7 @@ export function recordPlatformResource(runtime, input) {
|
|
|
52
59
|
reason: input.reason
|
|
53
60
|
});
|
|
54
61
|
void notifyJournal(log(runtime), 'recordPlatformResource', () => input.journal?.onFailure?.({ reason: 'skip', message }));
|
|
62
|
+
void notifyJournal(log(runtime), 'recordPlatformResource', () => input.onOutcome?.({ delivery: 'skipped', message }));
|
|
55
63
|
return;
|
|
56
64
|
}
|
|
57
65
|
if (!input.accountOrigin) {
|
|
@@ -62,6 +70,7 @@ export function recordPlatformResource(runtime, input) {
|
|
|
62
70
|
reason: input.reason
|
|
63
71
|
});
|
|
64
72
|
void notifyJournal(log(runtime), 'recordPlatformResource', () => input.journal?.onFailure?.({ reason: 'skip', message }));
|
|
73
|
+
void notifyJournal(log(runtime), 'recordPlatformResource', () => input.onOutcome?.({ delivery: 'skipped', message }));
|
|
65
74
|
return;
|
|
66
75
|
}
|
|
67
76
|
const accountOrigin = input.accountOrigin;
|
|
@@ -73,6 +82,7 @@ export function recordPlatformResource(runtime, input) {
|
|
|
73
82
|
reason: input.reason
|
|
74
83
|
});
|
|
75
84
|
void notifyJournal(log(runtime), 'recordPlatformResource', () => input.journal?.onFailure?.({ reason: 'skip', message }));
|
|
85
|
+
void notifyJournal(log(runtime), 'recordPlatformResource', () => input.onOutcome?.({ delivery: 'skipped', message }));
|
|
76
86
|
return;
|
|
77
87
|
}
|
|
78
88
|
const effectiveHardware = input.hardware ?? 'cloud';
|
|
@@ -102,13 +112,21 @@ export function recordPlatformResource(runtime, input) {
|
|
|
102
112
|
}
|
|
103
113
|
}),
|
|
104
114
|
signal
|
|
105
|
-
}), { timeoutMs: USAGE_RECORD_TIMEOUT_MS, reason: 'account platform resource usage record' })).then(async (
|
|
106
|
-
const
|
|
107
|
-
|
|
115
|
+
}).then(readUsageRecordDelivery), { timeoutMs: USAGE_RECORD_TIMEOUT_MS, reason: 'account platform resource usage record' })).then(async (settled) => {
|
|
116
|
+
const settlement = usageRecordSettlement(settled);
|
|
117
|
+
const context = { featureSlug: input.featureSlug, resourceId: input.resourceId };
|
|
118
|
+
if (settlement.delivered) {
|
|
119
|
+
// Delivered, so the journal row is done even when the charge was
|
|
120
|
+
// not collected: re-sending would write the usage row twice.
|
|
108
121
|
await notifyJournal(log(runtime), 'recordPlatformResource', input.journal?.onSuccess);
|
|
122
|
+
const { outcome } = settlement;
|
|
123
|
+
if (outcome.status !== 'charged') {
|
|
124
|
+
log(runtime).warn('recordPlatformResource: usage delivered but not charged in full', { ...context, outcome });
|
|
125
|
+
}
|
|
126
|
+
await notifyJournal(log(runtime), 'recordPlatformResource', () => input.onOutcome?.({ delivery: 'delivered', outcome }));
|
|
109
127
|
return;
|
|
110
128
|
}
|
|
111
|
-
const
|
|
129
|
+
const { failure } = settlement;
|
|
112
130
|
if (failure.reason === 'http') {
|
|
113
131
|
log(runtime).warn('recordPlatformResource: non-2xx from account', { ...context, status: failure.status });
|
|
114
132
|
}
|
|
@@ -120,6 +138,7 @@ export function recordPlatformResource(runtime, input) {
|
|
|
120
138
|
}
|
|
121
139
|
const message = deliveryFailureMessage(failure, USAGE_RECORD_TIMEOUT_MS);
|
|
122
140
|
await notifyJournal(log(runtime), 'recordPlatformResource', () => input.journal?.onFailure?.({ reason: failure.reason, message }));
|
|
141
|
+
await notifyJournal(log(runtime), 'recordPlatformResource', () => input.onOutcome?.({ delivery: 'failed', failure }));
|
|
123
142
|
});
|
|
124
143
|
}
|
|
125
144
|
//# sourceMappingURL=record-platform-resource.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-platform-resource.js","sourceRoot":"","sources":["../../../src/billing/usage/record-platform-resource.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"record-platform-resource.js","sourceRoot":"","sources":["../../../src/billing/usage/record-platform-resource.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,14 +18,20 @@
|
|
|
18
18
|
* Design constraints (same as record-generation-usage.ts)
|
|
19
19
|
* - MUST NOT fail the heartbeat path. Always returns void; swallows
|
|
20
20
|
* errors with structured log.
|
|
21
|
-
* - MUST be time-bounded. 500ms hard cap via AbortController
|
|
21
|
+
* - MUST be time-bounded. 500ms hard cap via AbortController, body
|
|
22
|
+
* read included.
|
|
23
|
+
* - A delivered record that could not be paid for is NOT success: the
|
|
24
|
+
* caller's `onOutcome` receives `shortfall` with the uncollected
|
|
25
|
+
* cost-basis USD.
|
|
22
26
|
*/
|
|
23
27
|
import { type RuntimeRef } from '@vibesdotdev/kernel';
|
|
24
|
-
import { type BillingEventMetadata } from './delivery.ts';
|
|
28
|
+
import { type BillingEventMetadata, type UsageEmissionOutcome, type UsageRecordOutcome } from './delivery.ts';
|
|
25
29
|
import type { CostBasis } from '../rating/schemas/cost-basis.ts';
|
|
26
30
|
import type { HardwarePath } from '../rating/schemas/rated-usage.ts';
|
|
27
31
|
/** The metadata this emitter's input accepts: JSON values, undefined entries dropped. */
|
|
28
|
-
export type { BillingEventMetadata };
|
|
32
|
+
export type { BillingEventMetadata, UsageRecordOutcome };
|
|
33
|
+
/** How one uptime emission ended; the shared record-internal outcome. */
|
|
34
|
+
export type SandboxUptimeOutcome = UsageEmissionOutcome;
|
|
29
35
|
export interface RecordSandboxUptimeInput {
|
|
30
36
|
/** Origin of the account app. Omit to skip metering (dev without account). */
|
|
31
37
|
accountOrigin: string | null | undefined;
|
|
@@ -88,6 +94,13 @@ export interface RecordSandboxUptimeInput {
|
|
|
88
94
|
message: string;
|
|
89
95
|
}) => Promise<void> | void;
|
|
90
96
|
};
|
|
97
|
+
/**
|
|
98
|
+
* Receives how the emission ended. The journal tracks DELIVERY (a
|
|
99
|
+
* delivered record must not be re-sent, or the usage row is written
|
|
100
|
+
* twice); this tracks whether the charge was collected. A `shortfall`
|
|
101
|
+
* outcome is delivered and still unpaid.
|
|
102
|
+
*/
|
|
103
|
+
onOutcome?: (outcome: SandboxUptimeOutcome) => Promise<void> | void;
|
|
91
104
|
}
|
|
92
105
|
export declare function recordSandboxUptime(runtime: RuntimeRef, input: RecordSandboxUptimeInput): void;
|
|
93
106
|
//# sourceMappingURL=record-sandbox-uptime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-sandbox-uptime.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/record-sandbox-uptime.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"record-sandbox-uptime.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/record-sandbox-uptime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAKN,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAErE,yFAAyF;AACzF,YAAY,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,CAAC;AAEzD,yEAAyE;AACzE,MAAM,MAAM,oBAAoB,GAAG,oBAAoB,CAAC;AASxD,MAAM,WAAW,wBAAwB;IACxC,8EAA8E;IAC9E,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC;;;;OAIG;IACH,oBAAoB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,+FAA+F;IAC/F,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;IACxD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;YAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC/G,CAAC;IACF;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACpE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,wBAAwB,GAAG,IAAI,CAiI9F"}
|