@jacobbd/relay-ai 0.9.0 → 0.9.2

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.
@@ -11,7 +11,7 @@ import { join } from "path";
11
11
  // package.json
12
12
  var package_default = {
13
13
  name: "@jacobbd/relay-ai",
14
- version: "0.9.0",
14
+ version: "0.9.2",
15
15
  publishConfig: {
16
16
  access: "public"
17
17
  },
@@ -345,7 +345,229 @@ async function runOpenAiDeviceCodeFlow(onDeviceCode, opts) {
345
345
 
346
346
  // src/oauth/responses-websocket.ts
347
347
  var RESPONSES_LITE_HEADER = "x-openai-internal-codex-responses-lite";
348
- var TERMINAL_EVENT_TYPES = /* @__PURE__ */ new Set(["response.completed", "response.failed", "response.incomplete"]);
348
+ var TERMINAL_EVENT_TYPES = /* @__PURE__ */ new Set(["response.completed", "response.failed", "response.incomplete", "error"]);
349
+ function isRecord(value) {
350
+ return !!value && typeof value === "object" && !Array.isArray(value);
351
+ }
352
+ function recordKeys(value) {
353
+ return isRecord(value) ? Object.keys(value).sort().join(",") : "";
354
+ }
355
+ function summarizeResponsesLiteEvent(event) {
356
+ if (!isRecord(event)) return `kind=${event == null ? "null" : typeof event}`;
357
+ const parts = [`type=${typeof event.type === "string" ? event.type : "unknown"}`, `keys=${recordKeys(event)}`];
358
+ if (typeof event.delta === "string") parts.push(`deltaChars=${event.delta.length}`);
359
+ if (typeof event.output_index === "number") parts.push(`hasOutputIndex=1`);
360
+ if (typeof event.item_id === "string") parts.push(`hasItemId=1`);
361
+ if (isRecord(event.item)) {
362
+ parts.push(`itemType=${typeof event.item.type === "string" ? event.item.type : "unknown"}`);
363
+ parts.push(`itemKeys=${recordKeys(event.item)}`);
364
+ if (typeof event.item.arguments === "string") parts.push(`argumentsChars=${event.item.arguments.length}`);
365
+ }
366
+ if (isRecord(event.response)) {
367
+ parts.push(`responseKeys=${recordKeys(event.response)}`);
368
+ if (Array.isArray(event.response.output)) {
369
+ parts.push(`outputCount=${event.response.output.length}`);
370
+ parts.push(`outputTypes=${event.response.output.map((item) => isRecord(item) && typeof item.type === "string" ? item.type : "unknown").join(",")}`);
371
+ }
372
+ if (isRecord(event.response.usage)) parts.push(`usageKeys=${recordKeys(event.response.usage)}`);
373
+ if (typeof event.response.status === "string") parts.push(`status=${event.response.status}`);
374
+ }
375
+ if (isRecord(event.error)) {
376
+ parts.push(`errorKeys=${recordKeys(event.error)}`);
377
+ if (typeof event.error.message === "string") parts.push(`messageChars=${event.error.message.length}`);
378
+ }
379
+ return parts.join(" ");
380
+ }
381
+ function createResponsesLiteNormalizeState() {
382
+ return {
383
+ nextId: 1,
384
+ lastOutputIndex: 0,
385
+ textDeltaForwarded: false,
386
+ messageAddedIds: /* @__PURE__ */ new Set(),
387
+ messageDoneIds: /* @__PURE__ */ new Set(),
388
+ functionAddedIndexes: /* @__PURE__ */ new Set(),
389
+ functionDeltaIndexes: /* @__PURE__ */ new Set(),
390
+ functionDoneCallIds: /* @__PURE__ */ new Set()
391
+ };
392
+ }
393
+ function nextId(state, prefix) {
394
+ const id = `${prefix}_${state.nextId}`;
395
+ state.nextId += 1;
396
+ return id;
397
+ }
398
+ function asString(value) {
399
+ return typeof value === "string" && value.length > 0 ? value : void 0;
400
+ }
401
+ function normalizeErrorEvent(event) {
402
+ const raw = isRecord(event.error) ? event.error : { message: typeof event.error === "string" ? event.error : "upstream error" };
403
+ return {
404
+ type: "error",
405
+ sequence_number: typeof event.sequence_number === "number" ? event.sequence_number : 0,
406
+ error: {
407
+ type: asString(raw.type) ?? "server_error",
408
+ code: asString(raw.code) ?? "unknown",
409
+ message: asString(raw.message) ?? "upstream error",
410
+ ...raw.param == null ? {} : { param: raw.param }
411
+ }
412
+ };
413
+ }
414
+ function normalizeFunctionItem(item, state, forDone = false) {
415
+ const callId = asString(item.call_id) ?? asString(item.id) ?? nextId(state, "call");
416
+ const id = asString(item.id) ?? nextId(state, "fc");
417
+ state.lastFunctionItemId = id;
418
+ return {
419
+ ...item,
420
+ type: "function_call",
421
+ id,
422
+ call_id: callId,
423
+ name: asString(item.name) ?? "",
424
+ arguments: typeof item.arguments === "string" ? item.arguments : "",
425
+ ...forDone ? { status: "completed" } : {}
426
+ };
427
+ }
428
+ function messageText(item) {
429
+ if (typeof item.text === "string") return item.text;
430
+ if (!Array.isArray(item.content)) return "";
431
+ let out = "";
432
+ for (const part of item.content) {
433
+ if (isRecord(part) && typeof part.text === "string" && (part.type === "output_text" || part.type === "text")) {
434
+ out += part.text;
435
+ }
436
+ }
437
+ return out;
438
+ }
439
+ function synthesizeMessage(item, outputIndex, state) {
440
+ const text4 = messageText(item);
441
+ if (!text4) return [];
442
+ const id = asString(item.id) ?? nextId(state, "msg");
443
+ state.lastMessageItemId = id;
444
+ state.textDeltaForwarded = true;
445
+ state.messageAddedIds.add(id);
446
+ state.messageDoneIds.add(id);
447
+ return [
448
+ { type: "response.output_item.added", output_index: outputIndex, item: { type: "message", id } },
449
+ { type: "response.output_text.delta", item_id: id, delta: text4 },
450
+ { type: "response.output_item.done", output_index: outputIndex, item: { type: "message", id } }
451
+ ];
452
+ }
453
+ function synthesizeFunctionCall(item, outputIndex, state) {
454
+ const normalized = normalizeFunctionItem(item, state);
455
+ const callId = String(normalized.call_id);
456
+ if (state.functionDoneCallIds.has(callId)) return [];
457
+ const events = [];
458
+ if (!state.functionAddedIndexes.has(outputIndex)) {
459
+ events.push({
460
+ type: "response.output_item.added",
461
+ output_index: outputIndex,
462
+ item: { ...normalized, arguments: "" }
463
+ });
464
+ state.functionAddedIndexes.add(outputIndex);
465
+ }
466
+ if (!state.functionDeltaIndexes.has(outputIndex) && typeof normalized.arguments === "string" && normalized.arguments.length > 0) {
467
+ events.push({
468
+ type: "response.function_call_arguments.delta",
469
+ item_id: normalized.id,
470
+ output_index: outputIndex,
471
+ delta: normalized.arguments
472
+ });
473
+ state.functionDeltaIndexes.add(outputIndex);
474
+ }
475
+ events.push({
476
+ type: "response.output_item.done",
477
+ output_index: outputIndex,
478
+ item: { ...normalized, status: "completed" }
479
+ });
480
+ state.functionDoneCallIds.add(callId);
481
+ state.lastOutputIndex = outputIndex;
482
+ return events;
483
+ }
484
+ function recoverFromCompletedOutput(response, state) {
485
+ if (!Array.isArray(response.output)) return [];
486
+ const recovered = [];
487
+ response.output.forEach((item, index) => {
488
+ if (!isRecord(item) || typeof item.type !== "string") return;
489
+ if (item.type === "message" && !state.textDeltaForwarded) {
490
+ recovered.push(...synthesizeMessage(item, index, state));
491
+ } else if (item.type === "function_call") {
492
+ recovered.push(...synthesizeFunctionCall(item, index, state));
493
+ }
494
+ });
495
+ return recovered;
496
+ }
497
+ function normalizeResponsesLiteEvent(event, state) {
498
+ if (!isRecord(event) || typeof event.type !== "string") return [event];
499
+ if (event.type === "error") return [normalizeErrorEvent(event)];
500
+ if (event.type === "response.output_item.added" && isRecord(event.item)) {
501
+ const outputIndex = typeof event.output_index === "number" ? event.output_index : state.lastOutputIndex;
502
+ state.lastOutputIndex = outputIndex;
503
+ if (event.item.type === "message") {
504
+ const id = asString(event.item.id) ?? nextId(state, "msg");
505
+ state.lastMessageItemId = id;
506
+ state.messageAddedIds.add(id);
507
+ return [{ ...event, output_index: outputIndex, item: { ...event.item, id } }];
508
+ }
509
+ if (event.item.type === "function_call") {
510
+ const item = normalizeFunctionItem(event.item, state);
511
+ state.functionAddedIndexes.add(outputIndex);
512
+ return [{ ...event, output_index: outputIndex, item }];
513
+ }
514
+ return [{ ...event, output_index: outputIndex }];
515
+ }
516
+ if (event.type === "response.output_item.done" && isRecord(event.item)) {
517
+ const outputIndex = typeof event.output_index === "number" ? event.output_index : state.lastOutputIndex;
518
+ if (event.item.type === "function_call") {
519
+ const item = normalizeFunctionItem(event.item, state, true);
520
+ const callId = String(item.call_id);
521
+ state.functionDoneCallIds.add(callId);
522
+ return [{ ...event, output_index: outputIndex, item }];
523
+ }
524
+ if (event.item.type === "message") {
525
+ const id = asString(event.item.id) ?? state.lastMessageItemId ?? nextId(state, "msg");
526
+ state.lastMessageItemId = id;
527
+ state.messageDoneIds.add(id);
528
+ return [{ ...event, output_index: outputIndex, item: { ...event.item, id } }];
529
+ }
530
+ return [{ ...event, output_index: outputIndex }];
531
+ }
532
+ if (event.type === "response.output_text.delta") {
533
+ const itemId = asString(event.item_id) ?? state.lastMessageItemId ?? nextId(state, "msg");
534
+ state.lastMessageItemId = itemId;
535
+ state.textDeltaForwarded = true;
536
+ const events = [];
537
+ if (!state.messageAddedIds.has(itemId)) {
538
+ events.push({
539
+ type: "response.output_item.added",
540
+ output_index: state.lastOutputIndex,
541
+ item: { type: "message", id: itemId }
542
+ });
543
+ state.messageAddedIds.add(itemId);
544
+ }
545
+ events.push({ ...event, item_id: itemId, delta: typeof event.delta === "string" ? event.delta : "" });
546
+ return events;
547
+ }
548
+ if (event.type === "response.function_call_arguments.delta") {
549
+ const itemId = asString(event.item_id) ?? state.lastFunctionItemId ?? nextId(state, "fc");
550
+ const outputIndex = typeof event.output_index === "number" ? event.output_index : state.lastOutputIndex;
551
+ state.lastFunctionItemId = itemId;
552
+ state.lastOutputIndex = outputIndex;
553
+ state.functionDeltaIndexes.add(outputIndex);
554
+ return [{ ...event, item_id: itemId, output_index: outputIndex, delta: typeof event.delta === "string" ? event.delta : "" }];
555
+ }
556
+ if (event.type === "response.completed" || event.type === "response.incomplete") {
557
+ const response = isRecord(event.response) ? event.response : {};
558
+ const recovered = recoverFromCompletedOutput(response, state);
559
+ if (state.lastMessageItemId && state.textDeltaForwarded && !state.messageDoneIds.has(state.lastMessageItemId)) {
560
+ recovered.push({
561
+ type: "response.output_item.done",
562
+ output_index: state.lastOutputIndex,
563
+ item: { type: "message", id: state.lastMessageItemId }
564
+ });
565
+ state.messageDoneIds.add(state.lastMessageItemId);
566
+ }
567
+ return [...recovered, event];
568
+ }
569
+ return [event];
570
+ }
349
571
  function toHeaderRecord(headers) {
350
572
  const out = {};
351
573
  if (!headers) return out;
@@ -403,10 +625,14 @@ function createResponsesWebSocketFetch(wsUrl, log7) {
403
625
  if (hasResponsesLiteHeader(headers)) {
404
626
  payload = applyResponsesLiteShape(payload);
405
627
  }
628
+ debug(
629
+ `request type=response.create keys=${Object.keys(payload).sort().join(",")} toolCount=${Array.isArray(payload.tools) ? payload.tools.length : 0} store=${String(payload.store)} parallelToolCalls=${String(payload.parallel_tool_calls)} reasoningKeys=${recordKeys(payload.reasoning)}`
630
+ );
406
631
  const outgoing = JSON.stringify({ type: "response.create", ...payload });
407
632
  const encoder = new TextEncoder();
408
633
  let socket;
409
634
  let frameCount = 0;
635
+ const normalizeState = createResponsesLiteNormalizeState();
410
636
  const stream = new ReadableStream({
411
637
  start(controller) {
412
638
  let closed = false;
@@ -424,13 +650,12 @@ function createResponsesWebSocketFetch(wsUrl, log7) {
424
650
  };
425
651
  const fail = (message) => {
426
652
  if (closed) return;
427
- debug(`fail: ${message}`);
653
+ debug(`fail messageChars=${message.length}`);
428
654
  try {
429
- controller.enqueue(encoder.encode(
430
- `data: ${JSON.stringify({ type: "error", error: { message } })}
655
+ const [errorEvent] = normalizeResponsesLiteEvent({ type: "error", error: { message } }, normalizeState);
656
+ controller.enqueue(encoder.encode(`data: ${JSON.stringify(errorEvent)}
431
657
 
432
- `
433
- ));
658
+ `));
434
659
  } catch {
435
660
  }
436
661
  close();
@@ -446,28 +671,31 @@ function createResponsesWebSocketFetch(wsUrl, log7) {
446
671
  socket.on("message", (data) => {
447
672
  const text4 = Array.isArray(data) ? Buffer.concat(data).toString("utf8") : data.toString("utf8");
448
673
  frameCount += 1;
449
- if (frameCount <= 3) debug(`frame#${frameCount}: ${text4.slice(0, 200)}`);
450
674
  let event;
451
675
  try {
452
676
  event = JSON.parse(text4);
453
677
  } catch {
678
+ debug(`frame#${frameCount} non-json chars=${text4.length}`);
454
679
  controller.enqueue(encoder.encode(`data: ${text4.replace(/\r?\n/g, " ")}
455
680
 
456
681
  `));
457
682
  return;
458
683
  }
459
- controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}
684
+ if (frameCount <= 8) debug(`frame#${frameCount} ${summarizeResponsesLiteEvent(event)}`);
685
+ for (const next of normalizeResponsesLiteEvent(event, normalizeState)) {
686
+ controller.enqueue(encoder.encode(`data: ${JSON.stringify(next)}
460
687
 
461
688
  `));
462
- const type = event.type;
463
- if (typeof type === "string" && TERMINAL_EVENT_TYPES.has(type)) {
689
+ }
690
+ const type = isRecord(event) && typeof event.type === "string" ? event.type : void 0;
691
+ if (type && TERMINAL_EVENT_TYPES.has(type)) {
464
692
  debug(`terminal event: ${type} (after ${frameCount} frames)`);
465
693
  close();
466
694
  }
467
695
  });
468
696
  socket.on("error", (err) => fail(err.message));
469
697
  socket.on("close", (code, reason) => {
470
- debug(`close code=${code} frames=${frameCount}${reason?.length ? ` reason=${reason.toString("utf8").slice(0, 200)}` : ""}`);
698
+ debug(`close code=${code} frames=${frameCount}${reason?.length ? ` reasonChars=${reason.length}` : ""}`);
471
699
  if (closed) return;
472
700
  if (code === 1e3 || code === 1005) {
473
701
  close();
@@ -2348,7 +2576,7 @@ var ANTIGRAVITY_BASE_URLS = [
2348
2576
  "https://cloudcode-pa.googleapis.com",
2349
2577
  "https://daily-cloudcode-pa.sandbox.googleapis.com"
2350
2578
  ];
2351
- var API_VERSION = "v1internal";
2579
+ var ANTIGRAVITY_API_VERSION = "v1internal";
2352
2580
  async function buildAntigravityAuthUrl(redirectUri) {
2353
2581
  const { verifier, challenge } = await generatePkce();
2354
2582
  const state = generateOAuthState();
@@ -2470,7 +2698,7 @@ function resolveAntigravityOnboardTierId(data) {
2470
2698
  return pickTierId(sub.currentTier) ?? "legacy-tier";
2471
2699
  }
2472
2700
  async function loadCodeAssist(accessToken) {
2473
- const endpoints = ANTIGRAVITY_BASE_URLS.map((b) => `${b}/${API_VERSION}:loadCodeAssist`);
2701
+ const endpoints = ANTIGRAVITY_BASE_URLS.map((b) => `${b}/${ANTIGRAVITY_API_VERSION}:loadCodeAssist`);
2474
2702
  const res = await fetchFirstOk(endpoints, {
2475
2703
  method: "POST",
2476
2704
  headers: apiHeaders(accessToken),
@@ -2487,7 +2715,7 @@ async function loadCodeAssist(accessToken) {
2487
2715
  };
2488
2716
  }
2489
2717
  async function onboardUser(accessToken, tierId, maxAttempts = 10) {
2490
- const endpoints = ANTIGRAVITY_BASE_URLS.map((b) => `${b}/${API_VERSION}:onboardUser`);
2718
+ const endpoints = ANTIGRAVITY_BASE_URLS.map((b) => `${b}/${ANTIGRAVITY_API_VERSION}:onboardUser`);
2491
2719
  let finalProjectId = "";
2492
2720
  for (let i = 0; i < maxAttempts; i++) {
2493
2721
  const res = await fetchFirstOk(endpoints, {
@@ -4742,7 +4970,7 @@ var SubagentRouteRegistry = class {
4742
4970
  // src/subagent-model-routing.ts
4743
4971
  var CLAUDE_MODEL_FAMILIES = ["sonnet", "opus", "haiku", "fable"];
4744
4972
  var CLAUDE_MODEL_FAMILY_SET = new Set(CLAUDE_MODEL_FAMILIES);
4745
- function isRecord(value) {
4973
+ function isRecord2(value) {
4746
4974
  return typeof value === "object" && value !== null && !Array.isArray(value);
4747
4975
  }
4748
4976
  function claudeModelFamily(modelId) {
@@ -4751,10 +4979,10 @@ function claudeModelFamily(modelId) {
4751
4979
  return CLAUDE_MODEL_FAMILIES.find((family) => normalized.includes(family));
4752
4980
  }
4753
4981
  function isClaudeAgentTool(tool4) {
4754
- if (tool4.name !== "Agent" || !isRecord(tool4.input_schema)) return false;
4982
+ if (tool4.name !== "Agent" || !isRecord2(tool4.input_schema)) return false;
4755
4983
  const properties = tool4.input_schema.properties;
4756
- if (!isRecord(properties)) return false;
4757
- return ["description", "prompt", "subagent_type"].every((name) => isRecord(properties[name]));
4984
+ if (!isRecord2(properties)) return false;
4985
+ return ["description", "prompt", "subagent_type"].every((name) => isRecord2(properties[name]));
4758
4986
  }
4759
4987
  var UnavailableSubagentModelError = class extends Error {
4760
4988
  constructor(selector, routing) {
@@ -4771,7 +4999,7 @@ var UnavailableSubagentModelError = class extends Error {
4771
4999
  statusCode = 400;
4772
5000
  };
4773
5001
  function normalizeClaudeAgentInput(input, routing) {
4774
- const source = isRecord(input) ? input : {};
5002
+ const source = isRecord2(input) ? input : {};
4775
5003
  const normalized = { ...source };
4776
5004
  if (source.subagent_type === "fork") {
4777
5005
  return { input: normalized, decision: { kind: "fork" } };
@@ -4843,9 +5071,9 @@ function prepareClaudeAgentInput(input, routing) {
4843
5071
  return { input: clientInput, decision };
4844
5072
  }
4845
5073
  function augmentClaudeAgentTool(tool4, routing) {
4846
- const inputSchema = isRecord(tool4.input_schema) ? tool4.input_schema : {};
4847
- const properties = isRecord(inputSchema.properties) ? inputSchema.properties : {};
4848
- const originalModel = isRecord(properties.model) ? properties.model : {};
5074
+ const inputSchema = isRecord2(tool4.input_schema) ? tool4.input_schema : {};
5075
+ const properties = isRecord2(inputSchema.properties) ? inputSchema.properties : {};
5076
+ const originalModel = isRecord2(properties.model) ? properties.model : {};
4849
5077
  const smallCatalog = routing.models.length <= MAX_MODEL_CATALOG;
4850
5078
  const modelProperty = {
4851
5079
  ...originalModel,
@@ -7501,15 +7729,10 @@ var model_incompatible_default = {
7501
7729
 
7502
7730
  // src/model-compatibility.ts
7503
7731
  var BLACKLIST_ENTRIES = model_incompatible_default.entries ?? [];
7504
- var ANTIGRAVITY_VALIDATED_AGENT_MODELS = /* @__PURE__ */ new Set([
7505
- "gemini-3.5-flash-low",
7506
- "gemini-3.5-flash-extra-low",
7507
- "gemini-3.1-pro-low",
7508
- "gemini-pro-agent",
7509
- "claude-sonnet-4-6",
7510
- "claude-opus-4-6-thinking",
7511
- "gpt-oss-120b-medium"
7512
- ]);
7732
+ var ANTIGRAVITY_HELPER_SLOT = /^(tab_|chat_|models\/)|image/i;
7733
+ function isAntigravityCloudCodeHelperSlot(modelId) {
7734
+ return ANTIGRAVITY_HELPER_SLOT.test(modelId);
7735
+ }
7513
7736
  function matchesAgent(entryAgents, agent) {
7514
7737
  if (!entryAgents || entryAgents.length === 0) return true;
7515
7738
  return entryAgents.includes(agent);
@@ -7527,8 +7750,8 @@ function findBlacklistEntry(ctx) {
7527
7750
  return null;
7528
7751
  }
7529
7752
  function hideReason(ctx) {
7530
- if (ctx.providerId === "antigravity" && !ANTIGRAVITY_VALIDATED_AGENT_MODELS.has(ctx.modelId)) {
7531
- return "[antigravity-oauth] not a validated user-selectable Cloud Code agent model";
7753
+ if (ctx.providerId === "antigravity" && isAntigravityCloudCodeHelperSlot(ctx.modelId)) {
7754
+ return "[antigravity-oauth] Cloud Code helper/internal slot";
7532
7755
  }
7533
7756
  const blacklist = findBlacklistEntry(ctx);
7534
7757
  if (blacklist) return `[blacklist:${blacklist.category}] ${blacklist.reason}`;
@@ -9855,7 +10078,7 @@ async function refreshAntigravityOAuthModels(accessToken) {
9855
10078
  const body = await res.json();
9856
10079
  const raw = body.models && typeof body.models === "object" && !Array.isArray(body.models) ? Object.entries(body.models).map(([id, model]) => ({ id, ...model })) : Array.isArray(body.models) ? body.models.filter((m) => typeof m.id === "string" && m.id.length > 0) : [];
9857
10080
  if (raw.length === 0) continue;
9858
- const models = raw.filter((m) => typeof m.id === "string" && m.id.length > 0).map((m) => {
10081
+ const models = raw.filter((m) => typeof m.id === "string" && m.id.length > 0 && !isAntigravityCloudCodeHelperSlot(m.id)).map((m) => {
9859
10082
  const id = m.id;
9860
10083
  const name = m.displayName ?? m.name ?? id;
9861
10084
  const isGemini = id.startsWith("gemini");
@@ -10240,7 +10463,7 @@ async function refreshProviderModels(providerId, apiKey, registry = loadRegistry
10240
10463
  id: provider.id,
10241
10464
  name: provider.name,
10242
10465
  ok: false,
10243
- reason: "No validated Antigravity agent models were returned \u2014 kept the existing model cache."
10466
+ reason: "Cloud Code returned no usable Antigravity models \u2014 kept the existing model cache."
10244
10467
  };
10245
10468
  }
10246
10469
  updateProviderCache(registry, providerId, enriched, baseUrl);
@@ -13297,4 +13520,4 @@ export {
13297
13520
  supportsClaudeTransparentMode,
13298
13521
  buildHttpProxyRoutes
13299
13522
  };
13300
- //# sourceMappingURL=chunk-R4AWEK7T.js.map
13523
+ //# sourceMappingURL=chunk-GQCFLSEM.js.map