@absolutejs/voice 0.0.22-beta.672 → 0.0.22-beta.674

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/client/htmxBootstrap.js +61 -6
  2. package/dist/client/index.js +61 -6
  3. package/dist/core/assistantHealth.d.ts +3 -40
  4. package/dist/core/auditDeliveryRoutes.d.ts +5 -40
  5. package/dist/core/auditRoutes.d.ts +3 -27
  6. package/dist/core/bargeInRoutes.d.ts +3 -27
  7. package/dist/core/browserCallProfiles.d.ts +3 -27
  8. package/dist/core/browserMediaRoutes.d.ts +3 -27
  9. package/dist/core/callDebugger.d.ts +3 -27
  10. package/dist/core/campaign.d.ts +166 -143
  11. package/dist/core/competitiveCoverage.d.ts +3 -40
  12. package/dist/core/dataControl.d.ts +3 -27
  13. package/dist/core/deliveryRuntime.d.ts +3 -40
  14. package/dist/core/deliverySinkRoutes.d.ts +3 -40
  15. package/dist/core/demoReadyRoutes.d.ts +3 -27
  16. package/dist/core/diagnosticsRoutes.d.ts +3 -27
  17. package/dist/core/evalRoutes.d.ts +3 -27
  18. package/dist/core/guardrails.d.ts +3 -27
  19. package/dist/core/handoffHealth.d.ts +5 -40
  20. package/dist/core/htmxDashboardRoutes.d.ts +309 -195
  21. package/dist/core/incidentBundle.d.ts +3 -27
  22. package/dist/core/incidentTimeline.d.ts +3 -40
  23. package/dist/core/liveLatency.d.ts +3 -40
  24. package/dist/core/liveOps.d.ts +154 -44
  25. package/dist/core/mediaPipelineRoutes.d.ts +3 -40
  26. package/dist/core/monitor.d.ts +5 -19
  27. package/dist/core/observabilityExport.d.ts +6 -54
  28. package/dist/core/operationalStatus.d.ts +3 -40
  29. package/dist/core/operationsRecord.d.ts +3 -27
  30. package/dist/core/opsActionAuditRoutes.d.ts +160 -51
  31. package/dist/core/opsConsoleRoutes.d.ts +3 -27
  32. package/dist/core/opsRecovery.d.ts +3 -40
  33. package/dist/core/opsStatusRoutes.d.ts +3 -27
  34. package/dist/core/opsWebhook.d.ts +158 -49
  35. package/dist/core/outcomeContract.d.ts +3 -40
  36. package/dist/core/phoneAgentProductionSmoke.d.ts +6 -40
  37. package/dist/core/platformCoverage.d.ts +3 -27
  38. package/dist/core/plugin.d.ts +12 -40
  39. package/dist/core/postCallAnalysis.d.ts +3 -27
  40. package/dist/core/productionReadiness.d.ts +3 -27
  41. package/dist/core/profileSwitchRecommendation.d.ts +299 -116
  42. package/dist/core/proofPack.d.ts +3 -27
  43. package/dist/core/proofTrends.d.ts +15 -135
  44. package/dist/core/providerCapabilities.d.ts +3 -40
  45. package/dist/core/providerDecisionTraces.d.ts +3 -40
  46. package/dist/core/providerHealth.d.ts +3 -40
  47. package/dist/core/providerOrchestration.d.ts +3 -40
  48. package/dist/core/providerSlo.d.ts +3 -27
  49. package/dist/core/providerStackRecommendations.d.ts +3 -27
  50. package/dist/core/qualityRoutes.d.ts +3 -27
  51. package/dist/core/realtimeChannel.d.ts +3 -40
  52. package/dist/core/realtimeProviderContracts.d.ts +3 -40
  53. package/dist/core/reconnectContract.d.ts +153 -79
  54. package/dist/core/resilienceRoutes.d.ts +3 -40
  55. package/dist/core/routeAuth.d.ts +3 -29
  56. package/dist/core/sessionObservability.d.ts +3 -27
  57. package/dist/core/sessionReplay.d.ts +10 -79
  58. package/dist/core/sessionSnapshot.d.ts +148 -39
  59. package/dist/core/simulationSuite.d.ts +3 -40
  60. package/dist/core/sloCalibration.d.ts +6 -54
  61. package/dist/core/telephonyMediaRoutes.d.ts +3 -27
  62. package/dist/core/telephonyOutcome.d.ts +148 -39
  63. package/dist/core/toolContract.d.ts +3 -40
  64. package/dist/core/traceDeliveryRoutes.d.ts +5 -40
  65. package/dist/core/traceTimeline.d.ts +3 -27
  66. package/dist/core/turnLatency.d.ts +3 -40
  67. package/dist/core/turnQuality.d.ts +3 -40
  68. package/dist/core/types.d.ts +9 -3
  69. package/dist/core/voiceMonitoring.d.ts +164 -115
  70. package/dist/index.js +58 -26
  71. package/dist/telephony/matrix.d.ts +148 -39
  72. package/dist/telephony/plivo.d.ts +10 -33
  73. package/dist/telephony/security.d.ts +3 -40
  74. package/dist/telephony/telnyx.d.ts +10 -33
  75. package/dist/testing/index.js +75 -16
  76. package/package.json +7 -81
@@ -208,22 +208,14 @@ export declare const createVoiceTelnyxWebhookVerifier: (options: VoiceTelnyxWebh
208
208
  rawBody: string;
209
209
  headers: Headers;
210
210
  }) => Promise<VoiceTelephonyWebhookVerificationResult>;
211
- export declare const createTelnyxVoiceRoutes: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options?: TelnyxVoiceRoutesOptions<TContext, TSession, TResult>) => Elysia<"", {
211
+ export declare const createTelnyxVoiceRoutes: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options?: TelnyxVoiceRoutesOptions<TContext, TSession, TResult>) => Elysia<"", "local", {
212
212
  decorator: {};
213
213
  store: {};
214
214
  derive: {};
215
- resolve: {};
216
215
  }, {
217
216
  typebox: {};
218
- error: {};
219
- }, {
220
- schema: {};
221
- standaloneSchema: {};
222
- macro: {};
223
- macroFn: {};
224
- parser: {};
225
- response: {};
226
- }, {
217
+ error: [];
218
+ }, import("elysia/types").DefaultMetadata, {
227
219
  [x: string]: {
228
220
  get: {
229
221
  body: unknown;
@@ -233,6 +225,7 @@ export declare const createTelnyxVoiceRoutes: <TContext = unknown, TSession exte
233
225
  response: {
234
226
  200: Response;
235
227
  };
228
+ error: never;
236
229
  };
237
230
  };
238
231
  } & {
@@ -245,17 +238,12 @@ export declare const createTelnyxVoiceRoutes: <TContext = unknown, TSession exte
245
238
  response: {
246
239
  200: Response;
247
240
  };
241
+ error: never;
248
242
  };
249
243
  };
250
244
  } & {
251
245
  [x: string]: {
252
- subscribe: {
253
- body: {};
254
- params: {};
255
- query: {};
256
- headers: {};
257
- response: {};
258
- };
246
+ subscribe: import("elysia/types").CreateWSEdenResponse<string, import("elysia/types").IntersectIfObjectSchema<import("elysia").UnwrapRoute<import("elysia").InputSchema<never>, {}, `/${string}`>, import("elysia/types").MergeScopedSchemas<{}, {}, {}>>, {}, import("elysia/types").ComposeElysiaResponse<import("elysia/types").IntersectIfObjectSchema<import("elysia").UnwrapRoute<import("elysia").InputSchema<never>, {}, `/${string}`>, import("elysia/types").MergeScopedSchemas<{}, {}, {}>>, void, {}, [], string>>;
259
247
  };
260
248
  } & {
261
249
  [x: string]: {
@@ -267,24 +255,13 @@ export declare const createTelnyxVoiceRoutes: <TContext = unknown, TSession exte
267
255
  response: {
268
256
  200: Response | import("..").VoiceTelephonyWebhookDecision<TResult>;
269
257
  };
258
+ error: never;
270
259
  };
271
260
  };
272
- }, {
273
- derive: {};
274
- resolve: {};
275
- schema: {};
276
- standaloneSchema: {};
277
- response: {};
278
- }, {
279
- derive: {};
280
- resolve: {};
281
- schema: {};
282
- standaloneSchema: {};
283
- response: {};
284
- } & {
261
+ }, import("elysia/types").DefaultEphemeral, {
285
262
  derive: {};
286
- resolve: {};
287
263
  schema: {};
288
- standaloneSchema: {};
264
+ schemas: {};
289
265
  response: {};
266
+ error: [];
290
267
  }>;
@@ -2228,6 +2228,49 @@ var createVoiceAudioPlayer = (source, options = {}) => {
2228
2228
  let maxGapMs = 0;
2229
2229
  let errorCount = 0;
2230
2230
  let hasScheduledAnyChunk = false;
2231
+ let buffersScheduled = 0;
2232
+ let lastScheduledTurnId;
2233
+ const audioFormats = new Set;
2234
+ let lastAudioFormat = null;
2235
+ let formatChangeCount = 0;
2236
+ let incompleteFrameChunkCount = 0;
2237
+ let discardedPartialFrameBytes = 0;
2238
+ let pendingFrameBytes = new Uint8Array;
2239
+ let pendingFrameFormat = null;
2240
+ let pendingFrameTurnId;
2241
+ const formatKey = (format) => `${format.container}/${format.encoding}/${String(format.channels)}ch/${String(format.sampleRateHz)}hz`;
2242
+ const frameAlignedChunk = (chunk) => {
2243
+ const format = formatKey(chunk.format);
2244
+ audioFormats.add(format);
2245
+ if (lastAudioFormat !== null && lastAudioFormat !== format) {
2246
+ formatChangeCount += 1;
2247
+ }
2248
+ lastAudioFormat = format;
2249
+ if (pendingFrameBytes.byteLength > 0 && (pendingFrameFormat !== format || pendingFrameTurnId !== chunk.turnId)) {
2250
+ discardedPartialFrameBytes += pendingFrameBytes.byteLength;
2251
+ pendingFrameBytes = new Uint8Array;
2252
+ }
2253
+ const joined = pendingFrameBytes.byteLength === 0 ? chunk.chunk : (() => {
2254
+ const bytes2 = new Uint8Array(pendingFrameBytes.byteLength + chunk.chunk.byteLength);
2255
+ bytes2.set(pendingFrameBytes);
2256
+ bytes2.set(chunk.chunk, pendingFrameBytes.byteLength);
2257
+ return bytes2;
2258
+ })();
2259
+ const frameBytes = Math.max(1, chunk.format.channels) * 2;
2260
+ const completeBytes = joined.byteLength - joined.byteLength % frameBytes;
2261
+ const remainderBytes = joined.byteLength - completeBytes;
2262
+ if (remainderBytes > 0) {
2263
+ incompleteFrameChunkCount += 1;
2264
+ pendingFrameBytes = joined.slice(completeBytes);
2265
+ pendingFrameFormat = format;
2266
+ pendingFrameTurnId = chunk.turnId;
2267
+ } else {
2268
+ pendingFrameBytes = new Uint8Array;
2269
+ pendingFrameFormat = null;
2270
+ pendingFrameTurnId = undefined;
2271
+ }
2272
+ return completeBytes > 0 ? { ...chunk, chunk: joined.subarray(0, completeBytes) } : null;
2273
+ };
2231
2274
  const sampleConcurrency = () => {
2232
2275
  if (activeAudioPlayers.size > observedPeakConcurrency) {
2233
2276
  observedPeakConcurrency = activeAudioPlayers.size;
@@ -2347,7 +2390,7 @@ var createVoiceAudioPlayer = (source, options = {}) => {
2347
2390
  queueEndTime = audioContext.currentTime;
2348
2391
  return audioContext;
2349
2392
  };
2350
- const scheduleBuffer = (context, buffer, rate) => {
2393
+ const scheduleBuffer = (context, buffer, rate, turnId) => {
2351
2394
  const node = context.createBufferSource();
2352
2395
  node.buffer = buffer;
2353
2396
  if (node.playbackRate) {
@@ -2365,13 +2408,15 @@ var createVoiceAudioPlayer = (source, options = {}) => {
2365
2408
  };
2366
2409
  const earliestStart = context.currentTime + lookaheadSeconds;
2367
2410
  const startAt = Math.max(earliestStart, queueEndTime);
2368
- if (hasScheduledAnyChunk && earliestStart > queueEndTime + GAP_EPSILON_S) {
2411
+ if (hasScheduledAnyChunk && turnId !== undefined && turnId === lastScheduledTurnId && earliestStart > queueEndTime + GAP_EPSILON_S) {
2369
2412
  const gapMs = (earliestStart - queueEndTime) * 1000;
2370
2413
  gapCount += 1;
2371
2414
  totalGapMs += gapMs;
2372
2415
  maxGapMs = Math.max(maxGapMs, gapMs);
2373
2416
  }
2374
2417
  hasScheduledAnyChunk = true;
2418
+ lastScheduledTurnId = turnId;
2419
+ buffersScheduled += 1;
2375
2420
  scheduledDurationMs += buffer.duration / rate * 1000;
2376
2421
  sampleConcurrency();
2377
2422
  queueEndTime = startAt + buffer.duration / rate;
@@ -2384,10 +2429,13 @@ var createVoiceAudioPlayer = (source, options = {}) => {
2384
2429
  };
2385
2430
  const scheduleChunk = async (chunk) => {
2386
2431
  const context = await ensureAudioContext();
2387
- const buffer = decodePCM16LEChunk(context, chunk);
2432
+ const alignedChunk = frameAlignedChunk(chunk);
2433
+ if (!alignedChunk)
2434
+ return;
2435
+ const buffer = decodePCM16LEChunk(context, alignedChunk);
2388
2436
  if (Math.abs(playbackRate - 1) <= STRETCH_BYPASS_EPSILON) {
2389
2437
  stretcher?.reset();
2390
- scheduleBuffer(context, buffer, playbackRate);
2438
+ scheduleBuffer(context, buffer, playbackRate, chunk.turnId);
2391
2439
  return;
2392
2440
  }
2393
2441
  const channels = Math.max(1, chunk.format.channels);
@@ -2408,13 +2456,14 @@ var createVoiceAudioPlayer = (source, options = {}) => {
2408
2456
  continue;
2409
2457
  outBuffer.getChannelData(channelIndex).set(channelOut);
2410
2458
  }
2411
- scheduleBuffer(context, outBuffer, 1);
2459
+ scheduleBuffer(context, outBuffer, 1, chunk.turnId);
2412
2460
  };
2413
2461
  const stopQueuedPlayback = (options2) => {
2414
2462
  for (const node of [...sourceNodes]) {
2415
2463
  node.stop?.();
2416
2464
  }
2417
2465
  queueEndTime = audioContext ? audioContext.currentTime : 0;
2466
+ lastScheduledTurnId = undefined;
2418
2467
  if (options2?.forceClear) {
2419
2468
  for (const node of sourceNodes) {
2420
2469
  node.disconnect?.();
@@ -2509,13 +2558,19 @@ var createVoiceAudioPlayer = (source, options = {}) => {
2509
2558
  const chunksReceived = source.assistantAudio.length;
2510
2559
  const chunksScheduled = state.processedChunkCount;
2511
2560
  return {
2561
+ audioFormatCount: audioFormats.size,
2562
+ buffersScheduled,
2512
2563
  chunksReceived,
2513
2564
  chunksScheduled,
2565
+ discardedPartialFrameBytes,
2514
2566
  errorCount,
2567
+ formatChangeCount,
2515
2568
  gapCount,
2569
+ incompleteFrameChunkCount,
2516
2570
  maxConcurrentPlayers: observedPeakConcurrency,
2517
2571
  maxGapMs: Math.round(maxGapMs),
2518
- ok: observedPeakConcurrency <= 1 && errorCount === 0 && chunksScheduled >= chunksReceived,
2572
+ pendingPartialFrameBytes: pendingFrameBytes.byteLength,
2573
+ ok: observedPeakConcurrency <= 1 && errorCount === 0 && chunksScheduled >= chunksReceived && discardedPartialFrameBytes === 0 && pendingFrameBytes.byteLength === 0,
2519
2574
  scheduledDurationMs: Math.round(scheduledDurationMs),
2520
2575
  totalGapMs: Math.round(totalGapMs)
2521
2576
  };
@@ -14284,6 +14339,7 @@ var renderVoiceOperationsRecordIncidentMarkdown = (record) => {
14284
14339
  // src/telephony/twilio.ts
14285
14340
  import { Buffer as Buffer3 } from "buffer";
14286
14341
  import { Elysia as Elysia6 } from "elysia";
14342
+ import { websocket } from "elysia/websocket";
14287
14343
 
14288
14344
  // src/internal/evidence.ts
14289
14345
  var assertVoiceEvidence = (failureMessage, assertion) => {
@@ -15060,7 +15116,9 @@ var createVoiceTelephonyWebhookRoutes = (options = {}) => {
15060
15116
  const handler = createVoiceTelephonyWebhookHandler(options);
15061
15117
  return new Elysia5({
15062
15118
  name: options.name ?? "absolutejs-voice-telephony-webhooks"
15063
- }).post(path, async ({ query, request }) => {
15119
+ }).post(path, {
15120
+ parse: "none"
15121
+ }, async ({ query, request }) => {
15064
15122
  try {
15065
15123
  return await handler({ query, request });
15066
15124
  } catch (error) {
@@ -15074,8 +15132,6 @@ var createVoiceTelephonyWebhookRoutes = (options = {}) => {
15074
15132
  }
15075
15133
  throw error;
15076
15134
  }
15077
- }, {
15078
- parse: "none"
15079
15135
  });
15080
15136
  };
15081
15137
 
@@ -15114,10 +15170,12 @@ var resolveTrustedTwilioRequestUrl = (security, request) => {
15114
15170
  return `${resolveTwilioPublicOrigin(security)}${requestUrl.pathname}${requestUrl.search}`;
15115
15171
  };
15116
15172
  var resolveTwilioSocketHeaders = (socket) => {
15117
- if (!socket.data || typeof socket.data !== "object")
15118
- return new Headers;
15119
- const data = socket.data;
15120
- for (const candidate of [data.request?.headers, data.headers]) {
15173
+ const data = socket.data && typeof socket.data === "object" ? socket.data : {
15174
+ headers: socket.headers,
15175
+ request: socket.request && typeof socket.request === "object" ? socket.request : undefined
15176
+ };
15177
+ const candidates = [data.request?.headers, data.headers];
15178
+ for (const candidate of candidates) {
15121
15179
  if (!candidate)
15122
15180
  continue;
15123
15181
  if (typeof candidate === "object" && "get" in candidate && typeof candidate.get === "function") {
@@ -15129,6 +15187,7 @@ var resolveTwilioSocketHeaders = (socket) => {
15129
15187
  }
15130
15188
  return new Headers;
15131
15189
  };
15190
+ var socketKey = (socket) => ("raw" in socket) && socket.raw && typeof socket.raw === "object" ? socket.raw : socket;
15132
15191
  var readTwilioVoiceForm = async (request) => {
15133
15192
  const declaredLength = Number(request.headers.get("content-length"));
15134
15193
  if (Number.isFinite(declaredLength) && declaredLength > MAX_TWILIO_VOICE_BODY_BYTES) {
@@ -15896,9 +15955,9 @@ var createTwilioVoiceRoutes = (options) => {
15896
15955
  const streamVerificationUrl = options.security.streamVerificationUrl ?? `${resolveTwilioPublicOrigin(options.security).replace(/^https:/, "wss:")}${streamPath}`;
15897
15956
  const app = new Elysia6({
15898
15957
  name: options.name ?? "absolutejs-voice-twilio"
15899
- }).get(twimlPath, renderTwiml).post(twimlPath, renderTwiml, { parse: "none" }).ws(streamPath, {
15958
+ }).use(websocket()).get(twimlPath, renderTwiml).post(twimlPath, { parse: "none" }, renderTwiml).ws(streamPath, {
15900
15959
  close: async (ws, _code, reason) => {
15901
- const key = ws.raw ?? ws;
15960
+ const key = socketKey(ws);
15902
15961
  const bridge = bridges.get(key);
15903
15962
  bridges.delete(key);
15904
15963
  admittedSockets.delete(key);
@@ -15906,7 +15965,7 @@ var createTwilioVoiceRoutes = (options) => {
15906
15965
  await bridge?.close(reason);
15907
15966
  },
15908
15967
  message: async (ws, raw) => {
15909
- const key = ws.raw ?? ws;
15968
+ const key = socketKey(ws);
15910
15969
  if (!admittedSockets.has(key)) {
15911
15970
  const verification = await verifyVoiceTwilioWebhookSignature({
15912
15971
  authToken: options.security.authToken,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.672",
3
+ "version": "0.0.22-beta.674",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,7 +33,7 @@
33
33
  "test:openai": "bun test ./test/live/openai.live.test.ts",
34
34
  "typecheck": "absolute typecheck",
35
35
  "verify-package": "absolute-manifest verify-package",
36
- "check:package": "bun run format && bun run typecheck && bun run test && bun run verify-package && bun run build && bun run verify-package --artifacts"
36
+ "check:package": "bun run format && bun run typecheck && bun run test && bun run verify-package && bun run build"
37
37
  },
38
38
  "exports": {
39
39
  ".": {
@@ -119,7 +119,7 @@
119
119
  "@absolutejs/ai": ">=0.0.5",
120
120
  "@angular/core": ">=21 <23",
121
121
  "drizzle-orm": ">=1.0.0-rc.4 <2",
122
- "elysia": ">=1.4.29 <2",
122
+ "elysia": ">=2.0.0-beta.6 <3",
123
123
  "react": ">=19 <20",
124
124
  "vue": ">=3.5 <4"
125
125
  },
@@ -141,12 +141,12 @@
141
141
  }
142
142
  },
143
143
  "dependencies": {
144
- "@absolutejs/manifest": "0.7.2",
144
+ "@absolutejs/manifest": "0.9.0",
145
145
  "@absolutejs/media": "0.0.1-beta.23",
146
146
  "@sinclair/typebox": "0.34.52"
147
147
  },
148
148
  "devDependencies": {
149
- "@absolutejs/absolute": "0.19.0-beta.1115",
149
+ "@absolutejs/absolute": "0.20.0-beta.0",
150
150
  "@absolutejs/ai": "0.0.47",
151
151
  "@angular/core": "22.0.8",
152
152
  "@electric-sql/pglite": "^0.4.5",
@@ -156,7 +156,7 @@
156
156
  "@types/react": "19.2.0",
157
157
  "@typescript-eslint/parser": "^8.57.2",
158
158
  "drizzle-orm": "1.0.0-rc.4",
159
- "elysia": "1.4.29",
159
+ "elysia": "2.0.0-beta.6",
160
160
  "eslint": "^10.1.0",
161
161
  "eslint-plugin-absolute": "0.11.0-beta.3",
162
162
  "eslint-plugin-promise": "^7.2.1",
@@ -170,80 +170,6 @@
170
170
  "vue": "3.5.40"
171
171
  },
172
172
  "absolutejs": {
173
- "manifestContract": 2,
174
- "runtimePeers": {
175
- "@absolutejs/ai": {
176
- "artifactImports": [],
177
- "buildExternals": [
178
- "@absolutejs/ai",
179
- "@absolutejs/ai/*"
180
- ],
181
- "optional": true,
182
- "range": ">=0.0.5",
183
- "tested": "0.0.47"
184
- },
185
- "@angular/core": {
186
- "artifactImports": [
187
- "@angular/core"
188
- ],
189
- "buildExternals": [
190
- "@angular/core",
191
- "@angular/core/*"
192
- ],
193
- "optional": true,
194
- "range": ">=21 <23",
195
- "tested": "22.0.8"
196
- },
197
- "drizzle-orm": {
198
- "artifactImports": [
199
- "drizzle-orm",
200
- "drizzle-orm/pg-core"
201
- ],
202
- "buildExternals": [
203
- "drizzle-orm",
204
- "drizzle-orm/*"
205
- ],
206
- "optional": true,
207
- "range": ">=1.0.0-rc.4 <2",
208
- "tested": "1.0.0-rc.4"
209
- },
210
- "elysia": {
211
- "artifactImports": [
212
- "elysia"
213
- ],
214
- "buildExternals": [
215
- "elysia",
216
- "elysia/*"
217
- ],
218
- "optional": false,
219
- "range": ">=1.4.29 <2",
220
- "tested": "1.4.29"
221
- },
222
- "react": {
223
- "artifactImports": [
224
- "react",
225
- "react/jsx-dev-runtime"
226
- ],
227
- "buildExternals": [
228
- "react",
229
- "react/*"
230
- ],
231
- "optional": true,
232
- "range": ">=19 <20",
233
- "tested": "19.2.8"
234
- },
235
- "vue": {
236
- "artifactImports": [
237
- "vue"
238
- ],
239
- "buildExternals": [
240
- "vue",
241
- "vue/*"
242
- ],
243
- "optional": true,
244
- "range": ">=3.5 <4",
245
- "tested": "3.5.40"
246
- }
247
- }
173
+ "manifestContract": 2
248
174
  }
249
175
  }