deepline 0.3.303 → 0.3.305
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/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +31 -1
- package/dist/bundling-sources/shared_libs/play-runtime/execute-server-timing.ts +30 -0
- package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +144 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +52 -25
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +10 -0
- package/dist/bundling-sources/shared_libs/product-notifications/billing-sales.ts +13 -0
- package/dist/bundling-sources/shared_libs/product-notifications/catalog.ts +69 -0
- package/dist/bundling-sources/shared_libs/product-notifications/default-policy.ts +26 -1
- package/dist/bundling-sources/shared_libs/product-notifications/events.ts +9 -1
- package/dist/cli/auth-WRUUITRZ.js +31 -0
- package/dist/cli/{auth-337SVWQD.mjs → auth-XMYFUM5L.mjs} +4 -4
- package/dist/cli/{billing-CVQURTWQ.js → billing-NDUDRJ7T.js} +70 -70
- package/dist/cli/{billing-SVGYQSJI.mjs → billing-RXT6NYAU.mjs} +4 -4
- package/dist/cli/{chunk-XXQYOQWO.mjs → chunk-445RPDOQ.mjs} +2 -2
- package/dist/cli/{chunk-PUKK7SZX.mjs → chunk-44GHROVJ.mjs} +1 -1
- package/dist/cli/{chunk-GQUI3NYN.js → chunk-5UZQ75HD.js} +57 -57
- package/dist/cli/{chunk-JWUOPLAR.mjs → chunk-6C4SD4U3.mjs} +1 -1
- package/dist/cli/{chunk-LGGR7CGZ.mjs → chunk-AEMR2R5H.mjs} +4 -4
- package/dist/cli/{chunk-HIXYNASX.js → chunk-B7PAZBJX.js} +4 -4
- package/dist/cli/{chunk-EAIGGEV5.js → chunk-COMHSM6F.js} +6 -6
- package/dist/cli/{chunk-OOQ4IRP4.js → chunk-DNSTXIU4.js} +1 -1
- package/dist/cli/{chunk-JGEFX6FQ.js → chunk-DY72E7K2.js} +6 -6
- package/dist/cli/{chunk-5NEXN4MZ.js → chunk-E4YSOJ2H.js} +2 -2
- package/dist/cli/{chunk-YZLPXH7G.mjs → chunk-HELHRPU6.mjs} +2 -2
- package/dist/cli/{chunk-NFWFUCGM.js → chunk-KNHD6J3X.js} +6 -6
- package/dist/cli/{chunk-MTICVDNY.mjs → chunk-KNK42P4M.mjs} +1 -1
- package/dist/cli/{chunk-WJGRIDWQ.js → chunk-LUBEGHJC.js} +15 -15
- package/dist/cli/{chunk-BVJSAJKV.mjs → chunk-LYPASDJJ.mjs} +1 -1
- package/dist/cli/{chunk-XKW6HTWO.mjs → chunk-QFSISXKO.mjs} +1 -1
- package/dist/cli/{chunk-IVT2CZPM.mjs → chunk-S3HPQWZ3.mjs} +1 -1
- package/dist/cli/{chunk-4LRG6AJZ.mjs → chunk-SCX2AZFY.mjs} +2 -2
- package/dist/cli/{chunk-DH6LEJWD.mjs → chunk-TGOAQTY3.mjs} +3 -3
- package/dist/cli/{chunk-RY6WID7C.js → chunk-UWDFJXBQ.js} +26 -26
- package/dist/cli/{chunk-P2KELOST.js → chunk-XZD3NYOL.js} +48 -48
- package/dist/cli/{chunk-4D5YQETI.js → chunk-ZQOFBLJN.js} +6 -6
- package/dist/cli/client-KBAPBERE.js +20 -0
- package/dist/cli/{client-AMSHGQFH.mjs → client-WOHHEX5X.mjs} +3 -3
- package/dist/cli/{csv-F4RPWI4E.mjs → csv-WNPLDGFR.mjs} +3 -3
- package/dist/cli/{csv-B2OKPMNX.js → csv-WZ5BOOT7.js} +12 -12
- package/dist/cli/{db-AJYYK5HH.js → db-GBK4QSIU.js} +20 -20
- package/dist/cli/{db-QP4WNVSS.mjs → db-GCQJHGME.mjs} +4 -4
- package/dist/cli/{executions-4LHEJCCY.js → executions-BAS6T2BN.js} +6 -6
- package/dist/cli/{executions-NY7HYAEH.mjs → executions-MSB6FRNL.mjs} +4 -4
- package/dist/cli/{feedback-CXXJJARR.js → feedback-UHOHIOPV.js} +6 -6
- package/dist/cli/{feedback-SJYHLVYY.mjs → feedback-VREMIXAX.mjs} +3 -3
- package/dist/cli/git-6QYO4FQH.js +23 -0
- package/dist/cli/{git-DUODO3NL.mjs → git-GQKD556H.mjs} +4 -4
- package/dist/cli/index.js +73 -73
- package/dist/cli/index.mjs +30 -30
- package/dist/cli/{legacy-noops-3UYJVVNW.js → legacy-noops-PIL4KNVA.js} +7 -7
- package/dist/cli/{legacy-noops-IUDXZFYO.mjs → legacy-noops-RI2ROZ6U.mjs} +4 -4
- package/dist/cli/{monitors-PDWE6BGA.mjs → monitors-QHLEULAZ.mjs} +4 -4
- package/dist/cli/{monitors-IEEVACOD.js → monitors-UVQLZDIO.js} +85 -85
- package/dist/cli/{org-VSPO2YF3.mjs → org-BYWI4VI3.mjs} +4 -4
- package/dist/cli/{org-NUFEZRY7.js → org-KXJJZOSK.js} +60 -60
- package/dist/cli/{play-MXYK2BRE.js → play-3XR54PQY.js} +200 -200
- package/dist/cli/{play-KMHPJVWH.mjs → play-WF7AJJ7J.mjs} +6 -6
- package/dist/cli/{providers-YE5YRIML.js → providers-4FYRPS4E.js} +7 -7
- package/dist/cli/{providers-7ENB4EYV.mjs → providers-FG67H5N5.mjs} +4 -4
- package/dist/cli/{quickstart-KXCU2MZ2.js → quickstart-3YCFHVKY.js} +5 -5
- package/dist/cli/{quickstart-GFOOHX2U.mjs → quickstart-IBWIR4LX.mjs} +3 -3
- package/dist/cli/{search-R426JJQW.js → search-6PQ4QBMC.js} +6 -6
- package/dist/cli/{search-KESXCJDL.mjs → search-OZRXENTS.mjs} +5 -5
- package/dist/cli/{secrets-BRB5SIXG.js → secrets-2JW5HCHH.js} +13 -13
- package/dist/cli/{secrets-HDR522GC.mjs → secrets-S3GIROJA.mjs} +4 -4
- package/dist/cli/{sessions-VOOSWVLS.mjs → sessions-6HNVWH3C.mjs} +4 -4
- package/dist/cli/{sessions-IK3OSQC6.js → sessions-AQQ6WHMK.js} +5 -5
- package/dist/cli/{settings-BZKDIHTX.mjs → settings-6FINI54L.mjs} +7 -7
- package/dist/cli/{settings-OPGEFGXL.js → settings-HSHA2FO5.js} +74 -74
- package/dist/cli/{setup-TP2VWSCU.js → setup-O7FZ5EUD.js} +41 -41
- package/dist/cli/{setup-RVPS7AJJ.mjs → setup-XHIBSXCC.mjs} +6 -6
- package/dist/cli/skills-3ASRSEF2.js +28 -0
- package/dist/cli/{skills-7BDD2F4V.mjs → skills-ZFIIWR5G.mjs} +4 -4
- package/dist/cli/{tools-46ILS57M.js → tools-4B4NLVOJ.js} +50 -50
- package/dist/cli/{tools-XLGGDBM3.mjs → tools-WURPIECI.mjs} +5 -5
- package/dist/cli/{update-2JEM7WUF.mjs → update-2THOPAUS.mjs} +6 -6
- package/dist/cli/update-7ZPTMO6H.js +28 -0
- package/dist/cli/{workflow-SSTGMXOQ.mjs → workflow-S2G453ZX.mjs} +5 -5
- package/dist/cli/{workflow-ZKGPY7T4.js → workflow-XS5JSKED.js} +15 -15
- package/dist/{client-DjJfoW8r.d.ts → client-5Nsl0O0v.d.ts} +85 -0
- package/dist/{client-Me88eH3z.d.mts → client-BT11xxG8.d.mts} +85 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +6 -6
- package/dist/index.mjs +3 -3
- package/dist/install-integrity.json +71 -70
- package/dist/plays/run-request.d.mts +1 -1
- package/dist/plays/run-request.d.ts +1 -1
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +2 -2
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
- package/dist/cli/auth-4ME3NANJ.js +0 -31
- package/dist/cli/client-WN33QCMV.js +0 -20
- package/dist/cli/git-K7YPSXLC.js +0 -23
- package/dist/cli/skills-TK2CIWVS.js +0 -28
- package/dist/cli/update-3JOCQWNF.js +0 -28
|
@@ -200,7 +200,7 @@ export const SDK_RELEASE = {
|
|
|
200
200
|
// getters keep their established compatibility behavior.
|
|
201
201
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
202
202
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
203
|
-
version: '0.3.
|
|
203
|
+
version: '0.3.305',
|
|
204
204
|
updateSummary:
|
|
205
205
|
'Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.',
|
|
206
206
|
packageCapabilities: {
|
|
@@ -2452,7 +2452,9 @@ export async function projectRunEventsViaAppRuntime(
|
|
|
2452
2452
|
const batches = partitionRunEventsForAppRuntime(input.events);
|
|
2453
2453
|
const receiptBatch = runLedgerReceiptBatchIndex(batches);
|
|
2454
2454
|
for (const [index, events] of batches.entries()) {
|
|
2455
|
+
const beforeBatchStartedAt = Date.now();
|
|
2455
2456
|
await input.beforeBatch();
|
|
2457
|
+
const beforeBatchMs = Math.max(0, Date.now() - beforeBatchStartedAt);
|
|
2456
2458
|
// Retain the original receipt for the terminal (or final) piece so an acknowledged
|
|
2457
2459
|
// legacy delivery stays acknowledged across the reader rollout.
|
|
2458
2460
|
const idempotencyKey =
|
|
@@ -2476,7 +2478,16 @@ export async function projectRunEventsViaAppRuntime(
|
|
|
2476
2478
|
};
|
|
2477
2479
|
// The durable outbox owns recovery; this helper does not retry OCCs or
|
|
2478
2480
|
// other delivery failures inside an already-leased invocation.
|
|
2479
|
-
|
|
2481
|
+
let responseMeta: RuntimeApiResponseMeta | null = null;
|
|
2482
|
+
const deliveryContext = {
|
|
2483
|
+
...context,
|
|
2484
|
+
retryPolicy: 'none' as const,
|
|
2485
|
+
onResponseMeta(meta: RuntimeApiResponseMeta) {
|
|
2486
|
+
context.onResponseMeta?.(meta);
|
|
2487
|
+
if (meta.action === 'project_run_events') responseMeta = meta;
|
|
2488
|
+
},
|
|
2489
|
+
};
|
|
2490
|
+
const requestStartedAt = Date.now();
|
|
2480
2491
|
try {
|
|
2481
2492
|
await postAppRuntimeApi(deliveryContext, {
|
|
2482
2493
|
action: 'project_run_events',
|
|
@@ -2501,6 +2512,25 @@ export async function projectRunEventsViaAppRuntime(
|
|
|
2501
2512
|
...request,
|
|
2502
2513
|
});
|
|
2503
2514
|
}
|
|
2515
|
+
const requestWallMs = Math.max(0, Date.now() - requestStartedAt);
|
|
2516
|
+
if (beforeBatchMs >= 500 || requestWallMs >= 500) {
|
|
2517
|
+
const observedResponse = responseMeta as RuntimeApiResponseMeta | null;
|
|
2518
|
+
console.info('[run-ledger-outbox.project_transport_slow]', {
|
|
2519
|
+
runId: input.playId,
|
|
2520
|
+
eventCount: events.length,
|
|
2521
|
+
batchIndex: index,
|
|
2522
|
+
batchCount: batches.length,
|
|
2523
|
+
beforeBatchMs,
|
|
2524
|
+
requestWallMs,
|
|
2525
|
+
roundTripMs: observedResponse?.roundTripMs ?? null,
|
|
2526
|
+
requestId: observedResponse?.requestId ?? null,
|
|
2527
|
+
requestBodyRawBytes: observedResponse?.requestBodyRawBytes ?? null,
|
|
2528
|
+
requestBodyWireBytes: observedResponse?.requestBodyWireBytes ?? null,
|
|
2529
|
+
requestBodySerializeMs:
|
|
2530
|
+
observedResponse?.requestBodySerializeMs ?? null,
|
|
2531
|
+
requestBodyPackMs: observedResponse?.requestBodyPackMs ?? null,
|
|
2532
|
+
});
|
|
2533
|
+
}
|
|
2504
2534
|
}
|
|
2505
2535
|
}
|
|
2506
2536
|
|
|
@@ -33,6 +33,36 @@ export const EXECUTE_SERVER_TIMING_STAGES = [
|
|
|
33
33
|
'execute',
|
|
34
34
|
'identity',
|
|
35
35
|
'usage_schedule',
|
|
36
|
+
// Managed AI inference slices: `ai_prepare` includes request preparation and
|
|
37
|
+
// contains `ai_billing_authorize`; `ai_provider_work_start` is the durable
|
|
38
|
+
// pre-call transition; `ai_gateway_first_output` is the time to the first
|
|
39
|
+
// model-output part (excluding SDK control chunks); and
|
|
40
|
+
// `ai_gateway_stream_wall` is the end-to-end SDK stream
|
|
41
|
+
// collection wall. Stream wall includes awaited finish callbacks, so evidence
|
|
42
|
+
// persistence and settlement overlap it. First-output and stream wall both
|
|
43
|
+
// include Gateway/network/upstream time; neither claims provider-internal
|
|
44
|
+
// model time.
|
|
45
|
+
'ai_prepare',
|
|
46
|
+
'ai_billing_authorize',
|
|
47
|
+
'ai_provider_work_start',
|
|
48
|
+
'ai_gateway_first_output',
|
|
49
|
+
'ai_gateway_stream_wall',
|
|
50
|
+
'ai_generation_evidence_persist',
|
|
51
|
+
'ai_billing_settlement',
|
|
52
|
+
'ai_output_canonicalization',
|
|
53
|
+
'ai_result_persist',
|
|
54
|
+
// Provider HTTP slices are only nonzero for calls that take this path:
|
|
55
|
+
// admission; `provider_fetch_headers` until response headers arrive (or
|
|
56
|
+
// `provider_fetch_error_wait` for a rejected fetch); retry backoff; body
|
|
57
|
+
// read, JSON parse, result transform and output normalization are separate.
|
|
58
|
+
'provider_admission',
|
|
59
|
+
'provider_fetch_headers',
|
|
60
|
+
'provider_fetch_error_wait',
|
|
61
|
+
'provider_retry_wait',
|
|
62
|
+
'provider_body_read',
|
|
63
|
+
'provider_json_parse',
|
|
64
|
+
'provider_result_transform',
|
|
65
|
+
'provider_output_normalization',
|
|
36
66
|
'total',
|
|
37
67
|
// The execution gateway preserves these disjoint stages beside the app
|
|
38
68
|
// handler's stages. They are deliberately part of this small, additive
|
|
@@ -12,7 +12,10 @@ import type {
|
|
|
12
12
|
ProviderConcurrencyGrant,
|
|
13
13
|
ProviderPacingGrant,
|
|
14
14
|
} from './governor/rate-state-backend';
|
|
15
|
-
import type {
|
|
15
|
+
import type {
|
|
16
|
+
ExecuteServerTiming,
|
|
17
|
+
ExecuteServerTimingStage,
|
|
18
|
+
} from './execute-server-timing';
|
|
16
19
|
|
|
17
20
|
export type RuntimeResourceLease = WorkLease;
|
|
18
21
|
export type RuntimeProviderPermit = ProviderPermit;
|
|
@@ -511,6 +514,29 @@ export type RuntimePhaseTiming = {
|
|
|
511
514
|
ewmaMs: number | null;
|
|
512
515
|
};
|
|
513
516
|
|
|
517
|
+
const AI_INFERENCE_EXECUTE_STAGES = [
|
|
518
|
+
'ai_prepare',
|
|
519
|
+
'ai_billing_authorize',
|
|
520
|
+
'ai_provider_work_start',
|
|
521
|
+
'ai_gateway_first_output',
|
|
522
|
+
'ai_gateway_stream_wall',
|
|
523
|
+
'ai_generation_evidence_persist',
|
|
524
|
+
'ai_billing_settlement',
|
|
525
|
+
'ai_output_canonicalization',
|
|
526
|
+
'ai_result_persist',
|
|
527
|
+
] as const satisfies readonly ExecuteServerTimingStage[];
|
|
528
|
+
|
|
529
|
+
const PROVIDER_HTTP_EXECUTE_STAGES = [
|
|
530
|
+
'provider_admission',
|
|
531
|
+
'provider_fetch_headers',
|
|
532
|
+
'provider_fetch_error_wait',
|
|
533
|
+
'provider_retry_wait',
|
|
534
|
+
'provider_body_read',
|
|
535
|
+
'provider_json_parse',
|
|
536
|
+
'provider_result_transform',
|
|
537
|
+
'provider_output_normalization',
|
|
538
|
+
] as const satisfies readonly ExecuteServerTimingStage[];
|
|
539
|
+
|
|
514
540
|
/**
|
|
515
541
|
* Selected execute-route stages for the same population as `fetchToHeaders`.
|
|
516
542
|
* These are nested because they partition handler work inside that wall; they
|
|
@@ -523,6 +549,26 @@ export type RuntimeExecuteRouteTiming = {
|
|
|
523
549
|
chargeOpenMs: number;
|
|
524
550
|
fixtureLoadMs: number;
|
|
525
551
|
executeMs: number;
|
|
552
|
+
/**
|
|
553
|
+
* Managed `ai_inference` stages, accumulated independently because each can
|
|
554
|
+
* observe a different request population. `count` is the number of requests
|
|
555
|
+
* with a non-zero `ai_prepare` marker. Stage counters include positive
|
|
556
|
+
* durations only: the header serializes milliseconds to three decimal
|
|
557
|
+
* places, so an absent stage cannot be distinguished from a duration
|
|
558
|
+
* rounded to zero. These slices overlap; in particular stream wall contains
|
|
559
|
+
* awaited evidence persistence and billing settlement.
|
|
560
|
+
*/
|
|
561
|
+
aiInference?: RuntimeExecuteStageGroup<
|
|
562
|
+
(typeof AI_INFERENCE_EXECUTE_STAGES)[number]
|
|
563
|
+
>;
|
|
564
|
+
/**
|
|
565
|
+
* Deepline-owned HTTP provider stages. `count` is the number of requests
|
|
566
|
+
* with a non-zero provider-admission marker; each stage retains its own
|
|
567
|
+
* positive-duration denominator for rolling-build compatibility.
|
|
568
|
+
*/
|
|
569
|
+
providerHttp?: RuntimeExecuteStageGroup<
|
|
570
|
+
(typeof PROVIDER_HTTP_EXECUTE_STAGES)[number]
|
|
571
|
+
>;
|
|
526
572
|
/**
|
|
527
573
|
* Where `chargeOpenMs` went, nested rather than summed: these are disjoint
|
|
528
574
|
* slices of it, never independent phases. Present only when the deployed app
|
|
@@ -557,6 +603,18 @@ export type RuntimeExecuteRouteTiming = {
|
|
|
557
603
|
};
|
|
558
604
|
};
|
|
559
605
|
|
|
606
|
+
/** Fixed-size run summary for one execute-route stage. */
|
|
607
|
+
export type RuntimeExecuteStageTiming = {
|
|
608
|
+
count: number;
|
|
609
|
+
totalMs: number;
|
|
610
|
+
maxMs: number | null;
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
/** A fixed set of named execute stages with one run-level request count. */
|
|
614
|
+
export type RuntimeExecuteStageGroup<Stage extends ExecuteServerTimingStage> = {
|
|
615
|
+
count: number;
|
|
616
|
+
} & Record<Stage, RuntimeExecuteStageTiming>;
|
|
617
|
+
|
|
560
618
|
/**
|
|
561
619
|
* A compact, unitless sample aggregate. Provider permits use it for bucket
|
|
562
620
|
* occupancy at admission, rather than mislabelling an in-flight count as ms.
|
|
@@ -854,6 +912,71 @@ function createPhaseTiming(): {
|
|
|
854
912
|
};
|
|
855
913
|
}
|
|
856
914
|
|
|
915
|
+
function createExecuteStageAccumulator(): {
|
|
916
|
+
observe(value: number): void;
|
|
917
|
+
snapshot(): RuntimeExecuteStageTiming;
|
|
918
|
+
} {
|
|
919
|
+
let count = 0;
|
|
920
|
+
let totalMs = 0;
|
|
921
|
+
let maxMs: number | null = null;
|
|
922
|
+
return {
|
|
923
|
+
observe(value) {
|
|
924
|
+
count += 1;
|
|
925
|
+
totalMs += value;
|
|
926
|
+
maxMs = maxMs === null ? value : Math.max(maxMs, value);
|
|
927
|
+
},
|
|
928
|
+
snapshot() {
|
|
929
|
+
return { count, totalMs, maxMs };
|
|
930
|
+
},
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
function createExecuteStageGroup<
|
|
935
|
+
const Stages extends readonly ExecuteServerTimingStage[],
|
|
936
|
+
>(stages: Stages) {
|
|
937
|
+
type Stage = Stages[number];
|
|
938
|
+
// Keep the tuple's element type explicit through iteration. TypeScript can
|
|
939
|
+
// widen a generic readonly tuple to the full timing-stage union in loops,
|
|
940
|
+
// even though every value here came from this group's stage list.
|
|
941
|
+
const stageNames = stages as readonly Stage[];
|
|
942
|
+
const metrics = Object.fromEntries(
|
|
943
|
+
stageNames.map((stage) => [stage, createExecuteStageAccumulator()]),
|
|
944
|
+
) as Record<Stage, ReturnType<typeof createExecuteStageAccumulator>>;
|
|
945
|
+
let count = 0;
|
|
946
|
+
return {
|
|
947
|
+
get count() {
|
|
948
|
+
return count;
|
|
949
|
+
},
|
|
950
|
+
observe(markerMs: number | null, timing: ExecuteServerTiming) {
|
|
951
|
+
// The execute header renders absent stages as zero, so zero cannot be
|
|
952
|
+
// attributed to an observed stage with confidence. The positive marker
|
|
953
|
+
// selects calls in this group; stage populations remain explicit.
|
|
954
|
+
if (markerMs === null || !Number.isFinite(markerMs) || markerMs <= 0) {
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
count += 1;
|
|
958
|
+
for (const stage of stageNames) {
|
|
959
|
+
const durationMs = timing[stage];
|
|
960
|
+
if (
|
|
961
|
+
durationMs !== null &&
|
|
962
|
+
Number.isFinite(durationMs) &&
|
|
963
|
+
durationMs > 0
|
|
964
|
+
) {
|
|
965
|
+
metrics[stage].observe(durationMs);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
},
|
|
969
|
+
snapshot(): RuntimeExecuteStageGroup<Stage> {
|
|
970
|
+
return {
|
|
971
|
+
count,
|
|
972
|
+
...Object.fromEntries(
|
|
973
|
+
stageNames.map((stage) => [stage, metrics[stage].snapshot()]),
|
|
974
|
+
),
|
|
975
|
+
} as RuntimeExecuteStageGroup<Stage>;
|
|
976
|
+
},
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
|
|
857
980
|
function createSampleTiming(): {
|
|
858
981
|
observe(value: number | null | undefined): void;
|
|
859
982
|
snapshot(): RuntimeSampleTiming;
|
|
@@ -979,6 +1102,12 @@ export function createRuntimeResourceGovernor(input: {
|
|
|
979
1102
|
fixtureLoadMs: 0,
|
|
980
1103
|
executeMs: 0,
|
|
981
1104
|
};
|
|
1105
|
+
const executeAiInference = createExecuteStageGroup(
|
|
1106
|
+
AI_INFERENCE_EXECUTE_STAGES,
|
|
1107
|
+
);
|
|
1108
|
+
const executeProviderHttp = createExecuteStageGroup(
|
|
1109
|
+
PROVIDER_HTTP_EXECUTE_STAGES,
|
|
1110
|
+
);
|
|
982
1111
|
const executeChargeOpen = {
|
|
983
1112
|
count: 0,
|
|
984
1113
|
eligibilityMs: 0,
|
|
@@ -1288,6 +1417,14 @@ export function createRuntimeResourceGovernor(input: {
|
|
|
1288
1417
|
executeRoute.chargeOpenMs += executeRouteTiming.charge_open;
|
|
1289
1418
|
executeRoute.fixtureLoadMs += executeRouteTiming.fixture_load;
|
|
1290
1419
|
executeRoute.executeMs += executeRouteTiming.execute;
|
|
1420
|
+
executeAiInference.observe(
|
|
1421
|
+
executeRouteTiming.ai_prepare,
|
|
1422
|
+
executeRouteTiming,
|
|
1423
|
+
);
|
|
1424
|
+
executeProviderHttp.observe(
|
|
1425
|
+
executeRouteTiming.provider_admission,
|
|
1426
|
+
executeRouteTiming,
|
|
1427
|
+
);
|
|
1291
1428
|
// Same rule as the gateway block below: require the complete substage
|
|
1292
1429
|
// set this app version emits, so an older build that reports only
|
|
1293
1430
|
// `charge_open` does not silently contribute a partial split.
|
|
@@ -1734,6 +1871,12 @@ export function createRuntimeResourceGovernor(input: {
|
|
|
1734
1871
|
? {
|
|
1735
1872
|
executeRoute: {
|
|
1736
1873
|
...executeRoute,
|
|
1874
|
+
...(executeAiInference.count > 0
|
|
1875
|
+
? { aiInference: executeAiInference.snapshot() }
|
|
1876
|
+
: {}),
|
|
1877
|
+
...(executeProviderHttp.count > 0
|
|
1878
|
+
? { providerHttp: executeProviderHttp.snapshot() }
|
|
1879
|
+
: {}),
|
|
1737
1880
|
...(executeChargeOpen.count > 0
|
|
1738
1881
|
? { chargeOpen: { ...executeChargeOpen } }
|
|
1739
1882
|
: {}),
|
|
@@ -1070,7 +1070,7 @@ export async function withRuntimeSchedulerClient<T>(
|
|
|
1070
1070
|
let queryCount = 0;
|
|
1071
1071
|
let queryMs = 0;
|
|
1072
1072
|
try {
|
|
1073
|
-
if (!entry.databasePoolAttached) {
|
|
1073
|
+
if (process.env.VERCEL?.trim() && !entry.databasePoolAttached) {
|
|
1074
1074
|
attachDatabasePool(entry.pool);
|
|
1075
1075
|
entry.databasePoolAttached = true;
|
|
1076
1076
|
}
|
|
@@ -14701,8 +14701,10 @@ function terminalLogProjectionForOutbox(
|
|
|
14701
14701
|
metadata: PlayLogMetadata | null;
|
|
14702
14702
|
entryId: string | null;
|
|
14703
14703
|
} => entry !== null,
|
|
14704
|
-
)
|
|
14705
|
-
|
|
14704
|
+
);
|
|
14705
|
+
// This carrier is consumed into the paginated log store by the terminal
|
|
14706
|
+
// statement. The runner already bounds its envelope by bytes; applying the
|
|
14707
|
+
// status tail here loses retained lines when live delivery was interrupted.
|
|
14706
14708
|
return {
|
|
14707
14709
|
lines: entries.map((entry) => entry.line),
|
|
14708
14710
|
lineContexts: entries.map((entry) => entry.context),
|
|
@@ -18091,10 +18093,10 @@ async function claimPostgresSchedulerOutboxPrefix(
|
|
|
18091
18093
|
? `owned_run AS MATERIALIZED (
|
|
18092
18094
|
SELECT run_id FROM ${tableName('runs', options)}
|
|
18093
18095
|
WHERE run_id = $2
|
|
18094
|
-
--
|
|
18095
|
-
--
|
|
18096
|
-
--
|
|
18097
|
-
FOR UPDATE
|
|
18096
|
+
-- The head is already owned. Wait for the producer, then revalidate
|
|
18097
|
+
-- its lease below; initial selection still skips unrelated busy runs.
|
|
18098
|
+
-- Child-row foreign-key share locks can coexist with this fence.
|
|
18099
|
+
FOR NO KEY UPDATE
|
|
18098
18100
|
),`
|
|
18099
18101
|
: ''
|
|
18100
18102
|
} head AS MATERIALIZED (
|
|
@@ -18117,7 +18119,7 @@ async function claimPostgresSchedulerOutboxPrefix(
|
|
|
18117
18119
|
${
|
|
18118
18120
|
input.extendOwnedHead
|
|
18119
18121
|
? `AND candidate.event_id = $5
|
|
18120
|
-
AND candidate.lease_owner = $3 AND candidate.lease_expires_at >
|
|
18122
|
+
AND candidate.lease_owner = $3 AND candidate.lease_expires_at > clock_timestamp()`
|
|
18121
18123
|
: ''
|
|
18122
18124
|
}
|
|
18123
18125
|
AND candidate.failed_at IS NULL
|
|
@@ -20340,23 +20342,47 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
20340
20342
|
events.length === 1 &&
|
|
20341
20343
|
first.eventType === RUN_SCHEDULER_OUTBOX_EVENT_TYPE.runEvents
|
|
20342
20344
|
) {
|
|
20343
|
-
const widened = await withClient((client) =>
|
|
20344
|
-
|
|
20345
|
-
|
|
20346
|
-
|
|
20347
|
-
|
|
20348
|
-
|
|
20349
|
-
|
|
20350
|
-
|
|
20351
|
-
|
|
20352
|
-
|
|
20353
|
-
|
|
20354
|
-
|
|
20355
|
-
|
|
20356
|
-
|
|
20357
|
-
|
|
20358
|
-
|
|
20359
|
-
|
|
20345
|
+
const widened = await withClient(async (client) => {
|
|
20346
|
+
await client.query('BEGIN');
|
|
20347
|
+
try {
|
|
20348
|
+
await client.query(
|
|
20349
|
+
`SELECT set_config('lock_timeout', $1, true),
|
|
20350
|
+
set_config('statement_timeout', $2, true)`,
|
|
20351
|
+
[
|
|
20352
|
+
`${RUNTIME_SCHEDULER_CANCEL_LOCK_TIMEOUT_MS}ms`,
|
|
20353
|
+
`${RUNTIME_SCHEDULER_CANCEL_STATEMENT_TIMEOUT_MS}ms`,
|
|
20354
|
+
],
|
|
20355
|
+
);
|
|
20356
|
+
// An owned head must extend from a fresh snapshot after the producer
|
|
20357
|
+
// commits. Keep the wait inside the existing SQL budget and permit
|
|
20358
|
+
// child-row foreign-key share locks under the ingress fence.
|
|
20359
|
+
await client.query(
|
|
20360
|
+
`SELECT run_id FROM ${tableName('runs', options)} WHERE run_id = $1 FOR NO KEY UPDATE`,
|
|
20361
|
+
[first.runId],
|
|
20362
|
+
);
|
|
20363
|
+
const prefix = await readPendingPostgresSchedulerOutboxEvents(
|
|
20364
|
+
client,
|
|
20365
|
+
{
|
|
20366
|
+
runId: first.runId,
|
|
20367
|
+
leaseOwner,
|
|
20368
|
+
leaseSeconds: input.leaseSeconds ?? 120,
|
|
20369
|
+
limit: Math.min(
|
|
20370
|
+
RUN_LEDGER_PROJECTION_PREFIX_MAX_FACTS,
|
|
20371
|
+
remainingEvents ?? RUN_LEDGER_PROJECTION_PREFIX_MAX_FACTS,
|
|
20372
|
+
),
|
|
20373
|
+
allowIngressPrefix: true,
|
|
20374
|
+
extendOwnedHead: first.eventId,
|
|
20375
|
+
inTransaction: true,
|
|
20376
|
+
},
|
|
20377
|
+
options,
|
|
20378
|
+
);
|
|
20379
|
+
await client.query('COMMIT');
|
|
20380
|
+
return prefix;
|
|
20381
|
+
} catch (error) {
|
|
20382
|
+
await client.query('ROLLBACK');
|
|
20383
|
+
throw error;
|
|
20384
|
+
}
|
|
20385
|
+
});
|
|
20360
20386
|
if (widened[0]?.eventId !== first.eventId) {
|
|
20361
20387
|
throw new RunLedgerProjectionLeaseLostError(
|
|
20362
20388
|
'head_lease_owner_mismatch',
|
|
@@ -20729,10 +20755,11 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
20729
20755
|
}
|
|
20730
20756
|
const failure = runLedgerDeliveryFailure({ error });
|
|
20731
20757
|
console.warn('[run-ledger-outbox.batch_dispatch_failed]', {
|
|
20732
|
-
runId: input.runId ?? null,
|
|
20758
|
+
runId: input.runId ?? events[0]?.runId ?? null,
|
|
20733
20759
|
eventIds: events.map((event) => event.eventId),
|
|
20734
20760
|
error: error instanceof Error ? error.message : String(error),
|
|
20735
20761
|
code: failure.code,
|
|
20762
|
+
responseStatus: failure.status,
|
|
20736
20763
|
failureReason: failure.failureReason,
|
|
20737
20764
|
...(failure.projectionMismatch
|
|
20738
20765
|
? { projectionMismatch: failure.projectionMismatch }
|
package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts
CHANGED
|
@@ -2793,6 +2793,16 @@ export async function hasRuntimeEventLogPositionIndex(
|
|
|
2793
2793
|
return true;
|
|
2794
2794
|
}
|
|
2795
2795
|
|
|
2796
|
+
/** Deployment-only check for all supported legacy and current log reads. */
|
|
2797
|
+
export async function hasRuntimeEventQueryIndexes(
|
|
2798
|
+
client: PostgresSchedulerQueryClient,
|
|
2799
|
+
): Promise<boolean> {
|
|
2800
|
+
for (const expected of RUNTIME_EVENT_QUERY_INDEXES) {
|
|
2801
|
+
if (!(await hasRuntimeEventQueryIndex(client, expected))) return false;
|
|
2802
|
+
}
|
|
2803
|
+
return true;
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2796
2806
|
/** Prepare old and new position indexes before replacing the projection body. */
|
|
2797
2807
|
export async function prepareRuntimeEventLogPositionIndex(
|
|
2798
2808
|
client: PostgresSchedulerQueryClient,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const BILLING_SALES_GROUP_KEY = 'shadow.billing-sales';
|
|
2
|
+
export const BILLING_SALES_DESTINATION_KEY = 'shadow.billing-sales.slack';
|
|
3
|
+
export const BILLING_SALES_SLACK_CHANNEL_ID = 'C0AGWVD2TNK';
|
|
4
|
+
export const BILLING_SALES_CONNECTION_ID = 'platform-reporting-bot';
|
|
5
|
+
export const BILLING_SALES_CREDIT_PURCHASE_MINIMUM_CENTS = 15_000;
|
|
6
|
+
export const BILLING_SALES_RULE_KEYS: readonly string[] = [
|
|
7
|
+
'internal.billing.credit_purchase',
|
|
8
|
+
'internal.billing.paid_plan',
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
export function isPlatformNotificationGroup(groupKey: string): boolean {
|
|
12
|
+
return groupKey === 'shadow' || groupKey === BILLING_SALES_GROUP_KEY;
|
|
13
|
+
}
|
|
@@ -13,6 +13,10 @@ import {
|
|
|
13
13
|
} from './events';
|
|
14
14
|
import { legacySlackNotificationType } from './legacy-slack';
|
|
15
15
|
import type { NotificationText } from './content';
|
|
16
|
+
import {
|
|
17
|
+
BILLING_SALES_CREDIT_PURCHASE_MINIMUM_CENTS,
|
|
18
|
+
BILLING_SALES_GROUP_KEY,
|
|
19
|
+
} from './billing-sales';
|
|
16
20
|
|
|
17
21
|
type NotificationTypeDefinition = {
|
|
18
22
|
id: string;
|
|
@@ -734,6 +738,71 @@ const PRODUCT_NOTIFICATION_TYPE_REGISTRY = [
|
|
|
734
738
|
}),
|
|
735
739
|
},
|
|
736
740
|
},
|
|
741
|
+
{
|
|
742
|
+
id: 'internal.billing.credit_purchase',
|
|
743
|
+
eventName: ProductNotificationEvent.CreditsPurchaseCompleted,
|
|
744
|
+
requiredFilter: { currency: 'usd' },
|
|
745
|
+
allowedTriggers: ['threshold_crossing'],
|
|
746
|
+
catalog: undefined,
|
|
747
|
+
shadow: true,
|
|
748
|
+
rule: {
|
|
749
|
+
default: {
|
|
750
|
+
ruleKey: 'internal.billing.credit_purchase',
|
|
751
|
+
groupKey: BILLING_SALES_GROUP_KEY,
|
|
752
|
+
},
|
|
753
|
+
create: (_input, base) => ({
|
|
754
|
+
...base,
|
|
755
|
+
repeatMode: 'every_match',
|
|
756
|
+
trigger: {
|
|
757
|
+
kind: 'threshold_crossing',
|
|
758
|
+
direction: 'at_or_above',
|
|
759
|
+
threshold: BILLING_SALES_CREDIT_PURCHASE_MINIMUM_CENTS,
|
|
760
|
+
unit: 'usd_cents',
|
|
761
|
+
},
|
|
762
|
+
}),
|
|
763
|
+
present: ({ payload }) => ({
|
|
764
|
+
title: `Credit purchase: $${(Number(payload.amountPaidCents) / 100).toFixed(2)}`,
|
|
765
|
+
summary: [
|
|
766
|
+
{ workspace: true },
|
|
767
|
+
` purchased ${formatCredits(Number(payload.credits))} credits.`,
|
|
768
|
+
],
|
|
769
|
+
details: [],
|
|
770
|
+
targetUrl: String(payload.targetUrl),
|
|
771
|
+
subjectKind: 'workspace',
|
|
772
|
+
subjectId: String(payload.accountId),
|
|
773
|
+
}),
|
|
774
|
+
},
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
id: 'internal.billing.paid_plan',
|
|
778
|
+
eventName: ProductNotificationEvent.BillingPlanPurchased,
|
|
779
|
+
requiredFilter: {},
|
|
780
|
+
allowedTriggers: ['each_match'],
|
|
781
|
+
catalog: undefined,
|
|
782
|
+
shadow: true,
|
|
783
|
+
rule: {
|
|
784
|
+
default: {
|
|
785
|
+
ruleKey: 'internal.billing.paid_plan',
|
|
786
|
+
groupKey: BILLING_SALES_GROUP_KEY,
|
|
787
|
+
},
|
|
788
|
+
create: (_input, base) => ({
|
|
789
|
+
...base,
|
|
790
|
+
repeatMode: 'every_match',
|
|
791
|
+
trigger: { kind: 'each_match' },
|
|
792
|
+
}),
|
|
793
|
+
present: ({ payload }) => ({
|
|
794
|
+
title: 'New paid plan signup',
|
|
795
|
+
summary: [
|
|
796
|
+
{ workspace: true },
|
|
797
|
+
` signed up for the ${payload.planName} plan.`,
|
|
798
|
+
],
|
|
799
|
+
details: [],
|
|
800
|
+
targetUrl: String(payload.targetUrl),
|
|
801
|
+
subjectKind: 'workspace',
|
|
802
|
+
subjectId: String(payload.accountId),
|
|
803
|
+
}),
|
|
804
|
+
},
|
|
805
|
+
},
|
|
737
806
|
{
|
|
738
807
|
id: 'play.failed',
|
|
739
808
|
eventName: ProductNotificationEvent.PlayRunCompleted,
|
|
@@ -8,13 +8,19 @@ import {
|
|
|
8
8
|
validateProductNotificationDeliveryTiming,
|
|
9
9
|
type ProductNotificationDefaultPolicy,
|
|
10
10
|
} from './configuration';
|
|
11
|
+
import {
|
|
12
|
+
BILLING_SALES_CONNECTION_ID,
|
|
13
|
+
BILLING_SALES_DESTINATION_KEY,
|
|
14
|
+
BILLING_SALES_GROUP_KEY,
|
|
15
|
+
BILLING_SALES_SLACK_CHANNEL_ID,
|
|
16
|
+
} from './billing-sales';
|
|
11
17
|
|
|
12
18
|
/**
|
|
13
19
|
* Product defaults stay in code. Workspaces see these rows synthetically until
|
|
14
20
|
* they create sparse copy-on-write overrides.
|
|
15
21
|
*/
|
|
16
22
|
export const CURRENT_PRODUCT_NOTIFICATION_DEFAULT_POLICY = {
|
|
17
|
-
version:
|
|
23
|
+
version: 9,
|
|
18
24
|
groups: [
|
|
19
25
|
{
|
|
20
26
|
groupKey: 'default',
|
|
@@ -32,6 +38,12 @@ export const CURRENT_PRODUCT_NOTIFICATION_DEFAULT_POLICY = {
|
|
|
32
38
|
enabled: true,
|
|
33
39
|
deliveryTiming: DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING,
|
|
34
40
|
},
|
|
41
|
+
{
|
|
42
|
+
groupKey: BILLING_SALES_GROUP_KEY,
|
|
43
|
+
name: 'Billing sales alerts',
|
|
44
|
+
enabled: true,
|
|
45
|
+
deliveryTiming: { mode: 'immediate' },
|
|
46
|
+
},
|
|
35
47
|
],
|
|
36
48
|
destinations: [
|
|
37
49
|
{
|
|
@@ -48,6 +60,19 @@ export const CURRENT_PRODUCT_NOTIFICATION_DEFAULT_POLICY = {
|
|
|
48
60
|
enabled: true,
|
|
49
61
|
settings: { kind: 'email_roles', roles: ['owner'] },
|
|
50
62
|
},
|
|
63
|
+
{
|
|
64
|
+
destinationKey: BILLING_SALES_DESTINATION_KEY,
|
|
65
|
+
groupKey: BILLING_SALES_GROUP_KEY,
|
|
66
|
+
name: 'Deepline signup channel',
|
|
67
|
+
enabled: true,
|
|
68
|
+
settings: {
|
|
69
|
+
kind: 'slack',
|
|
70
|
+
targetKind: 'channel',
|
|
71
|
+
targetId: BILLING_SALES_SLACK_CHANNEL_ID,
|
|
72
|
+
targetName: 'Deepline signup channel',
|
|
73
|
+
oauthConnectionId: BILLING_SALES_CONNECTION_ID,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
51
76
|
],
|
|
52
77
|
rules: PRODUCT_NOTIFICATION_DEFAULT_RULES,
|
|
53
78
|
} satisfies ProductNotificationDefaultPolicy;
|
|
@@ -206,9 +206,10 @@ export const PRODUCT_NOTIFICATION_EVENT_DEFINITIONS: readonly ProductNotificatio
|
|
|
206
206
|
credits: 'number',
|
|
207
207
|
targetUrl: 'string',
|
|
208
208
|
},
|
|
209
|
+
optionalFacts: { amountPaidCents: 'number', currency: 'string' },
|
|
209
210
|
orderingSubjectFact: 'accountId',
|
|
210
211
|
allowedTriggers: ['threshold_crossing'],
|
|
211
|
-
allowedThresholdUnits: ['credits'],
|
|
212
|
+
allowedThresholdUnits: ['credits', 'usd_cents'],
|
|
212
213
|
},
|
|
213
214
|
{
|
|
214
215
|
// The workspace moved onto a paid acquisition offer.
|
|
@@ -451,6 +452,13 @@ export function adaptProductNotificationObservation(input: {
|
|
|
451
452
|
};
|
|
452
453
|
}
|
|
453
454
|
if (event.eventName === ProductNotificationEvent.CreditsPurchaseCompleted) {
|
|
455
|
+
if (trigger.kind === 'threshold_crossing' && trigger.unit === 'usd_cents') {
|
|
456
|
+
return {
|
|
457
|
+
kind: 'threshold_state',
|
|
458
|
+
currentValue: Number(event.payload.amountPaidCents ?? 0),
|
|
459
|
+
unit: 'usd_cents',
|
|
460
|
+
};
|
|
461
|
+
}
|
|
454
462
|
return {
|
|
455
463
|
kind: 'threshold_state',
|
|
456
464
|
currentValue: Number(event.payload.credits),
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
var _chunkXZD3NYOLjs = require('./chunk-XZD3NYOL.js');
|
|
13
|
+
require('./chunk-COMHSM6F.js');
|
|
14
|
+
require('./chunk-B7PAZBJX.js');
|
|
15
|
+
require('./chunk-XNYIZMNQ.js');
|
|
16
|
+
require('./chunk-DNSTXIU4.js');
|
|
17
|
+
require('./chunk-7P5AA3SN.js');
|
|
18
|
+
require('./chunk-OG64RBAC.js');
|
|
19
|
+
require('./chunk-COGTRVWW.js');
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
exports.EXIT_WORKSPACE_MISMATCH = _chunkXZD3NYOLjs.EXIT_WORKSPACE_MISMATCH; exports.clearPendingClaim = _chunkXZD3NYOLjs.clearPendingClaim; exports.clearSatisfiedPendingClaim = _chunkXZD3NYOLjs.clearSatisfiedPendingClaim; exports.handleRegister = _chunkXZD3NYOLjs.handleRegister; exports.handleStatus = _chunkXZD3NYOLjs.handleStatus; exports.handleWait = _chunkXZD3NYOLjs.handleWait; exports.readPendingAuthClaim = _chunkXZD3NYOLjs.readPendingAuthClaim; exports.registerAuthCommands = _chunkXZD3NYOLjs.registerAuthCommands; exports.reportSetupCompleted = _chunkXZD3NYOLjs.reportSetupCompleted; exports.resolvePendingAuthClaimForResume = _chunkXZD3NYOLjs.resolvePendingAuthClaimForResume;
|
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
registerAuthCommands,
|
|
10
10
|
reportSetupCompleted,
|
|
11
11
|
resolvePendingAuthClaimForResume
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-SCX2AZFY.mjs";
|
|
13
|
+
import "./chunk-QFSISXKO.mjs";
|
|
14
|
+
import "./chunk-6C4SD4U3.mjs";
|
|
15
15
|
import "./chunk-DLIRSHV6.mjs";
|
|
16
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-KNK42P4M.mjs";
|
|
17
17
|
import "./chunk-NXGCO4JB.mjs";
|
|
18
18
|
import "./chunk-WZYKRD7T.mjs";
|
|
19
19
|
import "./chunk-KRD6H754.mjs";
|