@bitkyc08/opencodex 2.15.1-preview.20260814 → 2.16.0

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 (40) hide show
  1. package/gui/dist/assets/{index-1U3HI8uT.js → index-CZwbOse7.js} +1 -1
  2. package/gui/dist/index.html +1 -1
  3. package/package.json +1 -1
  4. package/src/adapters/base.ts +2 -0
  5. package/src/adapters/cursor/effort-map.ts +4 -5
  6. package/src/adapters/cursor/request-builder.ts +1 -1
  7. package/src/adapters/google-antigravity-replay.ts +9 -1
  8. package/src/adapters/kiro-thinking.ts +8 -0
  9. package/src/adapters/kiro.ts +45 -42
  10. package/src/adapters/openai-chat.ts +5 -2
  11. package/src/adapters/openai-responses.ts +5 -1
  12. package/src/cli/dispatch.ts +6 -3
  13. package/src/cli/index.ts +1 -0
  14. package/src/generated/compatibility-version.json +56 -32
  15. package/src/generated/model-metadata.ts +1 -1
  16. package/src/integrations/config-io.ts +119 -1
  17. package/src/integrations/omp-yaml-source.ts +6 -1
  18. package/src/integrations/serialize.ts +80 -1
  19. package/src/integrations/state.ts +37 -6
  20. package/src/integrations/writer.ts +11 -3
  21. package/src/lab/automation/orchestrator.ts +19 -0
  22. package/src/lib/lab-activation.ts +161 -0
  23. package/src/lib/lab-passive-linker-registration.ts +26 -0
  24. package/src/lib/optional-shutdown-hooks.ts +57 -0
  25. package/src/lib/translator-budget.ts +34 -0
  26. package/src/oauth/index.ts +3 -0
  27. package/src/providers/antigravity-models.ts +156 -36
  28. package/src/providers/model-rename-migration.ts +54 -1
  29. package/src/providers/registry.ts +1 -1
  30. package/src/routing/compatibility/assemble.ts +21 -107
  31. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  32. package/src/routing/compatibility/provider-slot.ts +56 -0
  33. package/src/server/index.ts +8 -17
  34. package/src/server/lifecycle.ts +5 -3
  35. package/src/server/management/routing-profile-routes.ts +9 -1
  36. package/src/server/management-api.ts +37 -6
  37. package/src/server/passive-route-linker.ts +66 -0
  38. package/src/server/responses/core.ts +20 -20
  39. package/src/types.ts +10 -0
  40. package/src/usage/expected-prices.ts +13 -0
@@ -19,6 +19,8 @@ import { createKiroToolNameRegistry, fallbackToolUseId, fingerprint, invocationI
19
19
  import { namespacedToolName } from "../types";
20
20
  import {
21
21
  isTranslatorBudgetExceededError,
22
+ releaseTranslatedEvent,
23
+ retainTranslatedEvent,
22
24
  type TranslatorBudget,
23
25
  } from "../lib/translator-budget";
24
26
  import type {
@@ -636,8 +638,8 @@ export function buildKiroPayload(
636
638
 
637
639
  // Stream parsing (shared by parseStream + parseResponse)
638
640
  // CodeWhisperer GenerateAssistantResponse ALWAYS returns an AWS eventstream body (there is no
639
- // non-streaming mode), so both the streaming bridge and the non-streaming web-search sidecar loop
640
- // decode the same way — parseResponse just collects what parseStream yields.
641
+ // non-streaming wire mode), so the streaming bridge and non-streaming Responses path decode the
642
+ // same way — parseResponse just collects what parseStream yields.
641
643
  interface KiroAttemptParseResult {
642
644
  terminal?: AdapterEvent;
643
645
  needsFallback?: boolean;
@@ -859,16 +861,12 @@ async function* parseKiroAttempt(
859
861
  );
860
862
  let handedOff = false;
861
863
  try {
862
- let next = await attempt.next();
863
- while (!next.done) {
864
- yield next.value;
865
- next = await attempt.next();
866
- }
864
+ const result = yield* attempt;
867
865
  for (const event of deferred.splice(0)) {
868
866
  try { yield event; } finally { retention.releaseEvent(event); }
869
867
  }
870
868
  handedOff = true;
871
- return { ...next.value, releaseRetained: () => retention.releaseAll() };
869
+ return { ...result, releaseRetained: () => retention.releaseAll() };
872
870
  } finally {
873
871
  if (!handedOff) retention.releaseAll();
874
872
  }
@@ -897,6 +895,12 @@ async function* parseKiroAttemptEvents(
897
895
  }
898
896
 
899
897
  let open: { id: string; name: string; chunks: string[]; completion: boolean } | null = null;
898
+ let openCallId: string | undefined;
899
+ const closeOpenCall = () => {
900
+ if (!openCallId) return;
901
+ budget.closeCall(openCallId);
902
+ openCallId = undefined;
903
+ };
900
904
  let outputChars = "";
901
905
  let outputCharsBytes = 0;
902
906
  let contextUsagePercentage: number | undefined;
@@ -1109,7 +1113,7 @@ async function* parseKiroAttemptEvents(
1109
1113
  if (!open) return { events: [] };
1110
1114
  const tool = open;
1111
1115
  open = null;
1112
- budget.closeCall(tool.id);
1116
+ closeOpenCall();
1113
1117
  const input = tool.chunks.join("");
1114
1118
  if (!isCompleteKiroToolInput(input)) {
1115
1119
  return { events: [], terminal: protocolTerminal(kiroTruncationErrorMessage("incomplete tool input JSON"), tool.completion) };
@@ -1221,11 +1225,12 @@ async function* parseKiroAttemptEvents(
1221
1225
  if (started.terminal) return { assistantText, sawReasoning, terminal: started.terminal };
1222
1226
  open = started.tool!;
1223
1227
  budget.openCall(open.id);
1228
+ openCallId = open.id;
1224
1229
  } else if (
1225
1230
  (ev.toolUseId && ev.toolUseId !== open.id)
1226
1231
  || (ev.name && open.name !== "unknown" && ev.name !== open.name)
1227
1232
  ) {
1228
- budget.closeCall(open.id);
1233
+ closeOpenCall();
1229
1234
  open = null;
1230
1235
  return { assistantText, sawReasoning, terminal: protocolTerminal(kiroTruncationErrorMessage("tool input changed identity before stop")) };
1231
1236
  }
@@ -1489,7 +1494,7 @@ async function* parseKiroAttemptEvents(
1489
1494
  };
1490
1495
  } catch (err) {
1491
1496
  if (isTranslatorBudgetExceededError(err)) {
1492
- if (open) budget.closeCall(open.id);
1497
+ closeOpenCall();
1493
1498
  return {
1494
1499
  assistantText,
1495
1500
  sawReasoning,
@@ -1531,6 +1536,9 @@ async function* parseKiroAttemptEvents(
1531
1536
  usage: usage(),
1532
1537
  },
1533
1538
  };
1539
+ } finally {
1540
+ thinking.dispose();
1541
+ closeOpenCall();
1534
1542
  }
1535
1543
  }
1536
1544
 
@@ -1547,7 +1555,7 @@ export async function* parseKiroStream(
1547
1555
  contextInputEstimate?: number,
1548
1556
  ): AsyncGenerator<AdapterEvent> {
1549
1557
  const contextWindowState: KiroContextWindowState = { value: contextWindow };
1550
- const first = parseKiroAttempt(
1558
+ const firstResult = yield* parseKiroAttempt(
1551
1559
  response,
1552
1560
  budget,
1553
1561
  completionMode,
@@ -1559,12 +1567,6 @@ export async function* parseKiroStream(
1559
1567
  contextInputEstimate,
1560
1568
  false,
1561
1569
  );
1562
- let firstNext = await first.next();
1563
- while (!firstNext.done) {
1564
- yield firstNext.value;
1565
- firstNext = await first.next();
1566
- }
1567
- const firstResult = firstNext.value;
1568
1570
  try {
1569
1571
  if (!firstResult.needsFallback) {
1570
1572
  if (firstResult.terminal) yield firstResult.terminal;
@@ -1642,7 +1644,7 @@ export async function* parseKiroStream(
1642
1644
  return;
1643
1645
  }
1644
1646
 
1645
- const second = parseKiroAttempt(
1647
+ const secondResult = yield* parseKiroAttempt(
1646
1648
  fallback.response,
1647
1649
  budget,
1648
1650
  "text_fallback",
@@ -1656,12 +1658,6 @@ export async function* parseKiroStream(
1656
1658
  // A zero-output transport failure here must stay non-retryable to avoid duplicating that text.
1657
1659
  priorEmittedOutput,
1658
1660
  );
1659
- let secondNext = await second.next();
1660
- while (!secondNext.done) {
1661
- yield secondNext.value;
1662
- secondNext = await second.next();
1663
- }
1664
- const secondResult = secondNext.value;
1665
1661
  try {
1666
1662
  if (!secondResult.terminal) {
1667
1663
  yield retryableKiroIncomplete(
@@ -1909,25 +1905,32 @@ export function createKiroAdapter(provider: OcxProviderConfig): ProviderAdapter
1909
1905
  return safeKiroHttpErrorMessage(status, headers, payloadText);
1910
1906
  },
1911
1907
 
1912
- // Non-streaming path used by the web-search sidecar loop (loop.ts runs each iteration
1913
- // non-streamed so it can inspect tool calls). CW only ever event-streams, so we drain the
1914
- // same decoder into an array. Without this, any Codex request that includes the web_search
1915
- // tool failed with "web-search sidecar requires a non-streaming adapter" (kiro-only).
1908
+ // Kiro always returns an event stream, including for non-streaming Responses requests. Drain
1909
+ // the decoder into a budget-owned batch so an upstream stream cannot grow this array without
1910
+ // bound while the caller waits for the complete JSON response.
1916
1911
  async parseResponse(response: Response, budget: TranslatorBudget): Promise<AdapterEvent[]> {
1917
1912
  const events: AdapterEvent[] = [];
1918
- for await (const e of parseKiroStream(
1919
- response,
1920
- budget,
1921
- modelId,
1922
- inputTokens,
1923
- contextWindow,
1924
- toolNameMap,
1925
- conversationId,
1926
- completionMode,
1927
- completionMode === "required" ? fallbackFactory : undefined,
1928
- contextInputEstimate,
1929
- )) events.push(e);
1930
- return events;
1913
+ try {
1914
+ for await (const e of parseKiroStream(
1915
+ response,
1916
+ budget,
1917
+ modelId,
1918
+ inputTokens,
1919
+ contextWindow,
1920
+ toolNameMap,
1921
+ conversationId,
1922
+ completionMode,
1923
+ completionMode === "required" ? fallbackFactory : undefined,
1924
+ contextInputEstimate,
1925
+ )) {
1926
+ retainTranslatedEvent(e, budget, events.at(-1));
1927
+ events.push(e);
1928
+ }
1929
+ return events;
1930
+ } catch (error) {
1931
+ for (const event of events) releaseTranslatedEvent(event, budget);
1932
+ throw error;
1933
+ }
1931
1934
  },
1932
1935
  };
1933
1936
  }
@@ -968,8 +968,11 @@ export function createOpenAIChatAdapter(provider: OcxProviderConfig): ProviderAd
968
968
  if (provider.parallelToolCalls === false) {
969
969
  // NIM documents the Boolean defaulting to false and kimi rejects true; pin the
970
970
  // wire bit so Codex cannot opt in via request.options. Other opted-out providers
971
- // omit the field so strict OpenAI-compatible hosts never see an unsupported knob.
972
- if (provider.baseUrl === "https://integrate.api.nvidia.com/v1") {
971
+ // omit the field by default so strict OpenAI-compatible hosts never see an
972
+ // unsupported knob, but a self-hosted gateway that DOES honor the field and keeps
973
+ // emitting parallel calls without it can opt in via pinParallelToolCallsFalse.
974
+ if (provider.baseUrl === "https://integrate.api.nvidia.com/v1"
975
+ || provider.pinParallelToolCallsFalse === true) {
973
976
  body.parallel_tool_calls = false;
974
977
  }
975
978
  } else if (provider.parallelToolCalls === true) {
@@ -1361,6 +1361,7 @@ export function createResponsesPassthroughAdapter(provider: OcxProviderConfig):
1361
1361
  }
1362
1362
 
1363
1363
  const forward = provider.authMode === "forward";
1364
+ let convertedRoutedCustomToolNames: Set<string> | undefined;
1364
1365
  const unexpandedMiss = !!parsed.previousResponseId && parsed._previousResponseInputExpanded !== true;
1365
1366
  let outBody = stripPreviousResponseId(
1366
1367
  parsed._rawBody,
@@ -1408,7 +1409,9 @@ export function createResponsesPassthroughAdapter(provider: OcxProviderConfig):
1408
1409
  outBody = promoteClientLoadedTools(outBody);
1409
1410
  }
1410
1411
  if (provider.authMode !== "forward") {
1411
- outBody = rewriteRoutedCustomToolsForUpstream(outBody).body;
1412
+ const rewritten = rewriteRoutedCustomToolsForUpstream(outBody);
1413
+ outBody = rewritten.body;
1414
+ convertedRoutedCustomToolNames = rewritten.names;
1412
1415
  }
1413
1416
  const sanitizedBody = normalizeToolSchemas(stripSparkCompatibility(stripUnsupportedReasoningParams(stripItemIdsWhenUnstored(stripInvalidItemIds(stripUnsupportedHostedTools(sanitizeReasoningInputContent(scrubOcxCompactionItems(outBody), { preserveRawReasoningContent: provider.preserveResponsesReasoningContent === true })))))));
1414
1417
  const body = JSON.stringify(stripDisabledReasoningSummaries(
@@ -1426,6 +1429,7 @@ export function createResponsesPassthroughAdapter(provider: OcxProviderConfig):
1426
1429
  headers,
1427
1430
  body,
1428
1431
  releaseBodyObservation,
1432
+ ...(convertedRoutedCustomToolNames ? { convertedRoutedCustomToolNames } : {}),
1429
1433
  };
1430
1434
  },
1431
1435
 
@@ -21,7 +21,6 @@ import { restoreNativeCodexAsync } from "../codex/inject";
21
21
  import { stripGrokConfig } from "../grok/inject";
22
22
  import { afterCatalogWriteHandleAppServers } from "../codex/app-server-processes";
23
23
  import { normalizeUpdateChannel, runGuiUpdateWorker } from "../update/job";
24
- import { serviceCommand } from "../service";
25
24
 
26
25
  export interface CliDispatchDeps {
27
26
  args: string[];
@@ -45,6 +44,7 @@ export interface CliDispatchDeps {
45
44
  handleStatus: () => Promise<void>;
46
45
  handleRecoverHistory: () => Promise<void>;
47
46
  handleReady: (args: ReadyArgs) => Promise<number>;
47
+ serviceCommand: (...args: string[]) => Promise<void>;
48
48
  }
49
49
 
50
50
  type CommandRunner = (deps: CliDispatchDeps) => Promise<number>;
@@ -261,8 +261,11 @@ const commandRunners: Record<string, CommandRunner> = {
261
261
  return 0;
262
262
  },
263
263
  service: async deps => {
264
- await serviceCommand(...deps.args.slice(1));
265
- return 0;
264
+ process.exitCode = 0;
265
+ await deps.serviceCommand(...deps.args.slice(1));
266
+ // serviceCommand uses process.exitCode for recoverable install/stop failures
267
+ // that must finish cleanup before the single top-level process.exit runs.
268
+ return Number(process.exitCode ?? 0);
266
269
  },
267
270
  tray: async deps => {
268
271
  const { windowsTrayCommand } = await import("../tray/windows");
package/src/cli/index.ts CHANGED
@@ -941,4 +941,5 @@ process.exit(await dispatchCommand(head, {
941
941
  handleStatus,
942
942
  handleRecoverHistory,
943
943
  handleReady,
944
+ serviceCommand,
944
945
  }));
@@ -10,11 +10,11 @@
10
10
  },
11
11
  {
12
12
  "path": "package.json",
13
- "sha256": "19cb2e945b0baab774873060ba072cbdb5c3e9c33c3a45e1d4cae1546004804e"
13
+ "sha256": "5c2d417ce3cb466651385bca4d8fee522e0bdf1c6d8c2fc1f84b4cf54574aee1"
14
14
  },
15
15
  {
16
16
  "path": "scripts/model-metadata.source.json",
17
- "sha256": "2efb03a4bc4209e0fef3a3ac04d5d9fd0fa9b38bce3bc353c3e22857e860cef2"
17
+ "sha256": "b7caeff6ccc1f011ffb4a48f6d345bc5febe3605f8304af7f714cd393fb5cd40"
18
18
  },
19
19
  {
20
20
  "path": "src/AGENTS.md",
@@ -42,7 +42,7 @@
42
42
  },
43
43
  {
44
44
  "path": "src/adapters/base.ts",
45
- "sha256": "67f50a3e0e45514f55f08d19726acfcab6fe4a9bd5e88bb7455b5af236a10663"
45
+ "sha256": "f20fdca89cd4bac4ec049ab46e200f2aa6435dae548c5994b7edf5b6d73f1bd5"
46
46
  },
47
47
  {
48
48
  "path": "src/adapters/client-fingerprint.ts",
@@ -74,7 +74,7 @@
74
74
  },
75
75
  {
76
76
  "path": "src/adapters/cursor/effort-map.ts",
77
- "sha256": "bd6c8594040e032fc24e8003670540113ffcb70072c319e177a0f3dff8e8380c"
77
+ "sha256": "d046b326bea7c6b6deab265ac5b4137f1dd8f3178e7bfe94c9a88c359b6872fc"
78
78
  },
79
79
  {
80
80
  "path": "src/adapters/cursor/exec-policy.ts",
@@ -158,7 +158,7 @@
158
158
  },
159
159
  {
160
160
  "path": "src/adapters/cursor/request-builder.ts",
161
- "sha256": "b2c76bb40171e70827c0119c28f246f41332dbc6965035abe37054220795ea30"
161
+ "sha256": "ec30a9988cf25a8bc51b2bb286ce25033b6a86591e5036d8d24b74e79b824704"
162
162
  },
163
163
  {
164
164
  "path": "src/adapters/cursor/thread-continuity.ts",
@@ -182,7 +182,7 @@
182
182
  },
183
183
  {
184
184
  "path": "src/adapters/google-antigravity-replay.ts",
185
- "sha256": "230da5cd5c6a94c2f520eeea2905294df6320e95e6f6e42569a4bfe04724193d"
185
+ "sha256": "52704bcd65eab346025e6faffe70d0c1d07e39651e4139f34bc67759fbaa4f08"
186
186
  },
187
187
  {
188
188
  "path": "src/adapters/google-antigravity-wire.ts",
@@ -242,7 +242,7 @@
242
242
  },
243
243
  {
244
244
  "path": "src/adapters/kiro-thinking.ts",
245
- "sha256": "d4016e1314c8b91bada92fff3ec4b94d0e1d88c4e51db49c29a482584844dfe0"
245
+ "sha256": "c7093dd20dc16156aee4d6a37de0b71f6e646c09f2ba99be8f3c6a388703a981"
246
246
  },
247
247
  {
248
248
  "path": "src/adapters/kiro-tool-fallback.ts",
@@ -262,7 +262,7 @@
262
262
  },
263
263
  {
264
264
  "path": "src/adapters/kiro.ts",
265
- "sha256": "c396bcf9810a1381f71957f95ed8399a13e240f5dc6be878c8836dfa7ca66f52"
265
+ "sha256": "fe61e9e4f8d7eada8baab90e09e9b2b03641c114eabe7846f2947cb0667996f1"
266
266
  },
267
267
  {
268
268
  "path": "src/adapters/mimo-free.ts",
@@ -274,7 +274,7 @@
274
274
  },
275
275
  {
276
276
  "path": "src/adapters/openai-chat.ts",
277
- "sha256": "1fcd9a2da1e675026fa2ac03b396cefa7cd62e3c1baf27844bbe7fd589c70275"
277
+ "sha256": "c87e922e32ccf8c224891e9a3a42e86139eb7db8d97b9c46613f01a132afc6fa"
278
278
  },
279
279
  {
280
280
  "path": "src/adapters/openai-responses-url.ts",
@@ -282,7 +282,7 @@
282
282
  },
283
283
  {
284
284
  "path": "src/adapters/openai-responses.ts",
285
- "sha256": "9c8d4483c0dacf3bf0562f08fe61b43d3c3107f1a978d66fc916c3da5dfe1d17"
285
+ "sha256": "8d4809ac4228beea1fa08716cd43c9ab7a87fdeaed5f30f39336ee808375b98d"
286
286
  },
287
287
  {
288
288
  "path": "src/adapters/run-turn-queue.ts",
@@ -446,7 +446,7 @@
446
446
  },
447
447
  {
448
448
  "path": "src/cli/dispatch.ts",
449
- "sha256": "2cba2f25e64bef2b08f1299a8b94757517bdf8bcd56e9ce2c7d46e50be3cce47"
449
+ "sha256": "478bd9539c26322ec5365e80f44674d507c708ccff6d09605a6e7804abedee79"
450
450
  },
451
451
  {
452
452
  "path": "src/cli/doctor.ts",
@@ -462,7 +462,7 @@
462
462
  },
463
463
  {
464
464
  "path": "src/cli/index.ts",
465
- "sha256": "8e3e096dac1115ae5a1a8c12d740b72766f4a1a1ece1e96c7e05d11b83080adb"
465
+ "sha256": "63e8747afb606295340bd30598d7112b75efb2a89353234a874df42c5fc7e1a7"
466
466
  },
467
467
  {
468
468
  "path": "src/cli/init.ts",
@@ -970,7 +970,7 @@
970
970
  },
971
971
  {
972
972
  "path": "src/generated/model-metadata.ts",
973
- "sha256": "59aa2237bbff037f658dae9faf3c3850a7c143faeedfe32c3e602d5c122101c1"
973
+ "sha256": "ce9038649026f53808e3e83d7862ae9eb453b86125cdd07a88e0392548b6559a"
974
974
  },
975
975
  {
976
976
  "path": "src/github/star-state.ts",
@@ -1038,7 +1038,7 @@
1038
1038
  },
1039
1039
  {
1040
1040
  "path": "src/integrations/config-io.ts",
1041
- "sha256": "5193f6718cab71d9b7117faec5feb3a413bc1ccfc1b1f5649451cba909b5bf15"
1041
+ "sha256": "5271736a6499bc4bcb68bde2ccefd8ef8ce7953bddf13e764fb1b9ee66433fe3"
1042
1042
  },
1043
1043
  {
1044
1044
  "path": "src/integrations/journal.ts",
@@ -1054,7 +1054,7 @@
1054
1054
  },
1055
1055
  {
1056
1056
  "path": "src/integrations/omp-yaml-source.ts",
1057
- "sha256": "b9e4355893d74cfff01892c2b2a0e164420d07beb5222818e14cddaff0c3d718"
1057
+ "sha256": "58a8769edc6c1f409f2851955e52dba3cdb5e30938d6b7dc19e59b900731d219"
1058
1058
  },
1059
1059
  {
1060
1060
  "path": "src/integrations/ownership.ts",
@@ -1066,11 +1066,11 @@
1066
1066
  },
1067
1067
  {
1068
1068
  "path": "src/integrations/serialize.ts",
1069
- "sha256": "e7a23ead6a5a6445ddc7803af9aa8cfebc745e2d6ab325828b95689a50c9b29d"
1069
+ "sha256": "0560601276b25d82eaf6e5460c815e0a67ecb4cf1cf6e378952c60dedfb333e6"
1070
1070
  },
1071
1071
  {
1072
1072
  "path": "src/integrations/state.ts",
1073
- "sha256": "65dd695356bce8ac9593e4cbec64ab85ca9d54784a0e7c8ae7294b9e9a81fba0"
1073
+ "sha256": "e2446f333ab3b57eebc120bf674f37aff6210cde7cf45628e7ff0ca77ca4d4f0"
1074
1074
  },
1075
1075
  {
1076
1076
  "path": "src/integrations/store.ts",
@@ -1078,7 +1078,7 @@
1078
1078
  },
1079
1079
  {
1080
1080
  "path": "src/integrations/writer.ts",
1081
- "sha256": "e2857bcc0351f1b6de8ba7d2fb6da27eff621e35ff69d40138e789ac24b116d6"
1081
+ "sha256": "92cc7c85a6bffa520f0fce57890f45758c712f69a128451be60368444d5ff725"
1082
1082
  },
1083
1083
  {
1084
1084
  "path": "src/lab/artifacts/sanitize.ts",
@@ -1118,7 +1118,7 @@
1118
1118
  },
1119
1119
  {
1120
1120
  "path": "src/lab/automation/orchestrator.ts",
1121
- "sha256": "ea12b23eceb13af13e6139a90ecd6b62ddd9485be118ef15027aff8c75621b6b"
1121
+ "sha256": "5f10d45593ea6464f6ecd1db6ee922bc7627fc6578fe6f3f93b7a35c1b479df8"
1122
1122
  },
1123
1123
  {
1124
1124
  "path": "src/lab/automation/persistence.ts",
@@ -1548,6 +1548,10 @@
1548
1548
  "path": "src/lib/injection-debug-log.ts",
1549
1549
  "sha256": "ab3b8e53c546c0ff43dc129d29c0b11c2d258f86e9d12475d87bf55510eb02c9"
1550
1550
  },
1551
+ {
1552
+ "path": "src/lib/lab-activation.ts",
1553
+ "sha256": "7cdfb758543a789a75354ebfba730c516d264a4d6a10648456f57e2654034dec"
1554
+ },
1551
1555
  {
1552
1556
  "path": "src/lib/lab-live-execution-authority.ts",
1553
1557
  "sha256": "7a4c488521b861ad70a87f560d85cb5c9f552e16493c5d44e19734947b4ac714"
@@ -1564,6 +1568,10 @@
1564
1568
  "path": "src/lib/lab-live-route-production.ts",
1565
1569
  "sha256": "fb890cceb6390cd2d846c86c97e0d490ea8b58783cd7410d032b6d8573a07f49"
1566
1570
  },
1571
+ {
1572
+ "path": "src/lib/lab-passive-linker-registration.ts",
1573
+ "sha256": "5f88d3428f87f1773f944e43d812356b96e881dcb8bd13d34baf504ce509e54c"
1574
+ },
1567
1575
  {
1568
1576
  "path": "src/lib/local-management-attestation.ts",
1569
1577
  "sha256": "1bccf8f85ecd89cb017224024ca3d199d97c8ce88f5ac936dbc1419845a77f6e"
@@ -1580,6 +1588,10 @@
1580
1588
  "path": "src/lib/open-url.ts",
1581
1589
  "sha256": "a6db7ec7181ccb4e95411b2c7499fdd00f3dd48bebcdaca099da086c0dae2e59"
1582
1590
  },
1591
+ {
1592
+ "path": "src/lib/optional-shutdown-hooks.ts",
1593
+ "sha256": "ba1fb3f46ddd1ad7d1cf90e22ae8df5dd2969dbb99449beaf8fac3100425a908"
1594
+ },
1583
1595
  {
1584
1596
  "path": "src/lib/pinned-http.ts",
1585
1597
  "sha256": "27a69c4eac63db31ef754c84d7f5f2e2949221b5fe27e066420f91b40fcc51d7"
@@ -1658,7 +1670,7 @@
1658
1670
  },
1659
1671
  {
1660
1672
  "path": "src/lib/translator-budget.ts",
1661
- "sha256": "872d5d35eb0d2ee099fc4ab4bf3b9331c6207d4282f61f2c1b11a5a36c00d981"
1673
+ "sha256": "4d79fed2d10e23b87af2c67ea0a979ce580eb232ac35e1f6851b5f02ef5a07d7"
1662
1674
  },
1663
1675
  {
1664
1676
  "path": "src/lib/upstream-reachability.ts",
@@ -1754,7 +1766,7 @@
1754
1766
  },
1755
1767
  {
1756
1768
  "path": "src/oauth/index.ts",
1757
- "sha256": "7fa04901697288bb21689e6cfbd32956f1240aa40bf485bb1328904f85695aa8"
1769
+ "sha256": "cbe370cd31412914b4cd2f565fd519eb45897ebd4ec7284503f68926017e127d"
1758
1770
  },
1759
1771
  {
1760
1772
  "path": "src/oauth/key-providers.ts",
@@ -1822,7 +1834,7 @@
1822
1834
  },
1823
1835
  {
1824
1836
  "path": "src/providers/antigravity-models.ts",
1825
- "sha256": "85a21f0548358ce3d74085bb8872bc4d8e2c770644dca3d93ccbe8020e81a620"
1837
+ "sha256": "cbe65f34a127ad44fd8f6bd2214553b238449b4f10d948d5ed67f4b163964874"
1826
1838
  },
1827
1839
  {
1828
1840
  "path": "src/providers/api-keys.ts",
@@ -1882,7 +1894,7 @@
1882
1894
  },
1883
1895
  {
1884
1896
  "path": "src/providers/model-rename-migration.ts",
1885
- "sha256": "cc3bd468dba3387eff13aedaa1fc48e68ea328fb5bc77c02d17bd84dce5e6393"
1897
+ "sha256": "3a321e04e7b73a969536befb115caf3d50994c058b8c365e1213114da3414490"
1886
1898
  },
1887
1899
  {
1888
1900
  "path": "src/providers/model-rename-startup.ts",
@@ -1922,7 +1934,7 @@
1922
1934
  },
1923
1935
  {
1924
1936
  "path": "src/providers/registry.ts",
1925
- "sha256": "af6eee1dda9253297b19a0074b547d7abd7ad282e6bb5f7123b5f63009113f35"
1937
+ "sha256": "7d6a712c9ae027d409c2d367ba77c13ceba46ecaab8199a68c3984c9ea5c4c04"
1926
1938
  },
1927
1939
  {
1928
1940
  "path": "src/providers/slug-codec.ts",
@@ -1990,7 +2002,7 @@
1990
2002
  },
1991
2003
  {
1992
2004
  "path": "src/routing/compatibility/assemble.ts",
1993
- "sha256": "00f0802e3ef8a2bf79779fbe27b62a73e92a94cff11bf5594784fef35dbda495"
2005
+ "sha256": "186010fe58a02823530819cf7bbf06cefdbb3224850ea8321736d1017f32783f"
1994
2006
  },
1995
2007
  {
1996
2008
  "path": "src/routing/compatibility/behavior.ts",
@@ -2004,10 +2016,18 @@
2004
2016
  "path": "src/routing/compatibility/endpoint.ts",
2005
2017
  "sha256": "38578440e02ce712f8d84fa97ec2d1bc3396f31983be9b6e5b0010ef6edd146b"
2006
2018
  },
2019
+ {
2020
+ "path": "src/routing/compatibility/lab-evidence-provider.ts",
2021
+ "sha256": "352a65b6d95c8e6eaa7e6f81fca49284b49a9ddf7bd1895be192b858784fd861"
2022
+ },
2007
2023
  {
2008
2024
  "path": "src/routing/compatibility/policy.ts",
2009
2025
  "sha256": "d903d561ef2ae16c86d16c7ec157556ee0c78557aaa7e83dad46c1abc0e6530c"
2010
2026
  },
2027
+ {
2028
+ "path": "src/routing/compatibility/provider-slot.ts",
2029
+ "sha256": "809c7b5dbe13b6e90d5abf51cadf33825f8d82b5fd1c7355d9ef25b736371bdc"
2030
+ },
2011
2031
  {
2012
2032
  "path": "src/routing/compatibility/reader.ts",
2013
2033
  "sha256": "c48943c0b660609bbdf4d47896de6338cd46b2c9144f1c916646221fe437a678"
@@ -2114,11 +2134,11 @@
2114
2134
  },
2115
2135
  {
2116
2136
  "path": "src/server/index.ts",
2117
- "sha256": "cff5571eb50f6ec315fa2f3ddd835d3bdd25b59c94a5b991771f066ad3e3ffc2"
2137
+ "sha256": "cc6461e629f1f5e373d81ebee0720a9ba85c7deedded457bbd398ac962e0e404"
2118
2138
  },
2119
2139
  {
2120
2140
  "path": "src/server/lifecycle.ts",
2121
- "sha256": "ee926ab2c5bb9925f91ce908ba8ce707859690bae1d07227afc38b259f40ea73"
2141
+ "sha256": "02d0691de03c510419c971341a7015507491599b9a91bec369fd7144f85b05a3"
2122
2142
  },
2123
2143
  {
2124
2144
  "path": "src/server/live.ts",
@@ -2134,7 +2154,7 @@
2134
2154
  },
2135
2155
  {
2136
2156
  "path": "src/server/management-api.ts",
2137
- "sha256": "ccd670a1618afc1ec6611771ec2519ea6c216d0ef43aa9e1114a3a98a9f0e030"
2157
+ "sha256": "0a513030e2b730393d86c87ad237f1e9f35e64586d8736c91c69fed6aaabb60d"
2138
2158
  },
2139
2159
  {
2140
2160
  "path": "src/server/management-auth.ts",
@@ -2214,7 +2234,7 @@
2214
2234
  },
2215
2235
  {
2216
2236
  "path": "src/server/management/routing-profile-routes.ts",
2217
- "sha256": "1185f47d963c31efa7da224baf9f2a447a15a7afee0705c05e6c110e75b465ff"
2237
+ "sha256": "08484dcc92a3672450122316dad9939707a2669eabf396084bfb93fa9dde35f9"
2218
2238
  },
2219
2239
  {
2220
2240
  "path": "src/server/management/shared.ts",
@@ -2248,6 +2268,10 @@
2248
2268
  "path": "src/server/memory-watchdog.ts",
2249
2269
  "sha256": "d2f7f5cd03316cdfb0bd23abd77b4c28d87986a9a1cb9e0f53e3890695f07f4c"
2250
2270
  },
2271
+ {
2272
+ "path": "src/server/passive-route-linker.ts",
2273
+ "sha256": "6a20d1e864efe80cd9d6c69df9616bc6092a6102cd8d339f0cb376f8821bed0b"
2274
+ },
2251
2275
  {
2252
2276
  "path": "src/server/port-reclaim.ts",
2253
2277
  "sha256": "5b1a9e7e5e3d752ee7dd0dca1ea8737eeaf7945e2c9a4e3a0aed9805cc72d253"
@@ -2334,7 +2358,7 @@
2334
2358
  },
2335
2359
  {
2336
2360
  "path": "src/server/responses/core.ts",
2337
- "sha256": "c67fdae5470a8d0c234e24d7d062bf351ec35c911550363c8d73199f4059fc95"
2361
+ "sha256": "0817eb37ba0ce9425afd9b9794eccab1095b7563d217652562cb281479f1df48"
2338
2362
  },
2339
2363
  {
2340
2364
  "path": "src/server/responses/encrypted-payload.ts",
@@ -2482,7 +2506,7 @@
2482
2506
  },
2483
2507
  {
2484
2508
  "path": "src/types.ts",
2485
- "sha256": "d911cdcf36b5694e58918b7e76b94b42c3bf94962ef4a41b93ae01629be36016"
2509
+ "sha256": "33f4ee11228bb8faca03c57fdd5000512f70153c2fd446f88d78b0a43056d330"
2486
2510
  },
2487
2511
  {
2488
2512
  "path": "src/update/badge.ts",
@@ -2534,7 +2558,7 @@
2534
2558
  },
2535
2559
  {
2536
2560
  "path": "src/usage/expected-prices.ts",
2537
- "sha256": "4773850e6417bba4d2ab5bfa7694203aa6898bc72d218e702d03cfe1cc3d2ff9"
2561
+ "sha256": "3b2874f24e7d53979fee5829f6b710b21cfefe06fb96f5cc887247aab5606acc"
2538
2562
  },
2539
2563
  {
2540
2564
  "path": "src/usage/log.ts",
@@ -42,7 +42,7 @@ const DATA: Record<string, readonly Row[]> = {
42
42
  "azure-openai": [["gpt-4.1",1047576,32768,"text,image",0,null,2,8,0.5,0],["gpt-4o",128000,16384,"text,image",0,null,2.5,10,1.25,0],["gpt-4o-mini",128000,16384,"text,image",0,null,0.15,0.6,0.075,0],["o3",200000,100000,"text,image",1,null,2,8,0.5,0],["o3-mini",200000,100000,"text",1,null,1.1,4.4,0.55,0]],
43
43
  "cerebras": [["gemma-4-31b",131072,40960,"text,image",1,null,0.99,1.49,0,0],["gpt-oss-120b",131072,40960,"text",1,null,0.35,0.75,0,0],["llama3.1-8b",32000,8000,"text",0,null,0.1,0.1,0,0],["qwen-3-235b-a22b-instruct-2507",131000,32000,"text",0,null,0.6,1.2,0,0],["qwen-3-coder-480b",131072,32768,"text",0,null,0,0,0,0],["zai-glm-4.6",131072,32768,"text",0,null,0,0,0,0],["zai-glm-4.7",131072,40960,"text",1,null,2.25,2.75,2.25,0]],
44
44
  "deepseek": [["deepseek-v4-flash",1048576,384000,"text",1,null,0.14,0.28,0.0028,0],["deepseek-v4-pro",1048576,384000,"text",1,null,0.435,0.87,0.003625,0]],
45
- "google": [["deep-research-max-preview-04-2026",131072,65536,"text,image",1,null,2,12,0.2,0],["deep-research-preview-04-2026",131072,65536,"text,image",1,null,2,12,0.2,0],["gemini-1.5-flash",1000000,8192,"text,image",0,null,0.075,0.3,0.01875,0],["gemini-1.5-flash-8b",1000000,8192,"text,image",0,null,0.0375,0.15,0.01,0],["gemini-1.5-pro",1000000,8192,"text,image",0,null,1.25,5,0.3125,0],["gemini-2.0-flash",1048576,8192,"text,image",0,null,0.1,0.4,0.025,0],["gemini-2.0-flash-lite",1048576,8192,"text,image",0,null,0.075,0.3,0,0],["gemini-2.5-computer-use-preview-10-2025",131072,65536,"text,image",1,null,1.25,10,0,0],["gemini-2.5-flash",1048576,65536,"text,image",1,null,0.3,2.5,0.03,0],["gemini-2.5-flash-lite",1048576,65536,"text,image",1,null,0.1,0.4,0.01,0],["gemini-2.5-flash-lite-preview-06-17",1048576,65536,"text,image",1,null,0.1,0.4,0.025,0],["gemini-2.5-flash-lite-preview-09-2025",1048576,65536,"text,image",1,null,0.1,0.4,0.025,0],["gemini-2.5-flash-preview-04-17",1048576,65536,"text,image",1,null,0.15,0.6,0.0375,0],["gemini-2.5-flash-preview-05-20",1048576,65536,"text,image",1,null,0.15,0.6,0.0375,0],["gemini-2.5-flash-preview-09-2025",1048576,65536,"text,image",1,null,0.3,2.5,0.075,0],["gemini-2.5-pro",1048576,65536,"text,image",1,null,1.25,10,0.125,0],["gemini-2.5-pro-preview-05-06",1048576,65536,"text,image",1,null,1.25,10,0.31,0],["gemini-2.5-pro-preview-06-05",1048576,65536,"text,image",1,null,1.25,10,0.31,0],["gemini-3-flash-preview",1048576,65536,"text,image",1,null,0.5,3,0.05,0],["gemini-3-pro-preview",1048576,65536,"text,image",1,null,2,12,0.2,0],["gemini-3.1-flash-lite",1048576,65536,"text,image",1,null,0.25,1.5,0.025,0],["gemini-3.1-flash-lite-image",65536,65536,"text,image",1,null,0.25,30,0,0],["gemini-3.1-flash-lite-preview",1048576,65536,"text,image",1,null,0.25,1.5,0.025,0],["gemini-3.1-flash-live-preview",131072,65536,"text,image",1,null,0.75,4.5,0,0],["gemini-3.1-pro-preview",1048576,65536,"text,image",1,null,2,12,0.2,0],["gemini-3.1-pro-preview-customtools",1048576,65536,"text,image",1,null,2,12,0.2,0],["gemini-3.5-flash",1048576,65536,"text,image",1,null,1.5,9,0.15,0],["gemini-3.5-flash-lite",1048576,65536,"text,image",1,null,0.3,2.5,0.03,0],["gemini-3.6-flash",1048576,65536,"text,image",1,null,1.5,7.5,0.15,0],["gemini-flash-latest",1048576,65536,"text,image",1,null,1.5,9,0.15,0],["gemini-flash-lite-latest",1048576,65536,"text,image",1,null,0.25,1.5,0.025,0],["gemini-live-2.5-flash",128000,8000,"text,image",1,null,0.5,2,0,0],["gemini-live-2.5-flash-preview-native-audio",131072,65536,"text",1,null,0.5,2,0,0],["gemini-robotics-er-1.6-preview",131072,65536,"text,image",1,null,1,5,0,0],["gemma-3-27b-it",131072,8192,"text,image",0,null,0,0,0,0],["gemma-4-26b",256000,8192,"text,image",1,null,0,0,0,0],["gemma-4-26b-a4b-it",262144,32768,"text,image",1,null,0,0,0,0],["gemma-4-26b-it",256000,8192,"text,image",1,null,0,0,0,0],["gemma-4-31b",256000,8192,"text,image",1,null,0,0,0,0],["gemma-4-31b-it",262144,32768,"text,image",1,null,0,0,0,0],["gemma-4-E2B-it",131072,8192,"text,image",1,null,0,0,0,0],["gemma-4-E4B-it",131072,8192,"text,image",1,null,0,0,0,0]],
45
+ "google": [["deep-research-max-preview-04-2026",131072,65536,"text,image",1,null,2,12,0.2,0],["deep-research-preview-04-2026",131072,65536,"text,image",1,null,2,12,0.2,0],["gemini-1.5-flash",1000000,8192,"text,image",0,null,0.075,0.3,0.01875,0],["gemini-1.5-flash-8b",1000000,8192,"text,image",0,null,0.0375,0.15,0.01,0],["gemini-1.5-pro",1000000,8192,"text,image",0,null,1.25,5,0.3125,0],["gemini-2.0-flash",1048576,8192,"text,image",0,null,0.1,0.4,0.025,0],["gemini-2.0-flash-lite",1048576,8192,"text,image",0,null,0.075,0.3,0,0],["gemini-2.5-computer-use-preview-10-2025",131072,65536,"text,image",1,null,1.25,10,0,0],["gemini-2.5-flash",1048576,65536,"text,image",1,null,0.3,2.5,0.03,0],["gemini-2.5-flash-lite",1048576,65536,"text,image",1,null,0.1,0.4,0.01,0],["gemini-2.5-flash-lite-preview-06-17",1048576,65536,"text,image",1,null,0.1,0.4,0.025,0],["gemini-2.5-flash-lite-preview-09-2025",1048576,65536,"text,image",1,null,0.1,0.4,0.025,0],["gemini-2.5-flash-preview-04-17",1048576,65536,"text,image",1,null,0.15,0.6,0.0375,0],["gemini-2.5-flash-preview-05-20",1048576,65536,"text,image",1,null,0.15,0.6,0.0375,0],["gemini-2.5-flash-preview-09-2025",1048576,65536,"text,image",1,null,0.3,2.5,0.075,0],["gemini-2.5-pro",1048576,65536,"text,image",1,null,1.25,10,0.125,0],["gemini-2.5-pro-preview-05-06",1048576,65536,"text,image",1,null,1.25,10,0.31,0],["gemini-2.5-pro-preview-06-05",1048576,65536,"text,image",1,null,1.25,10,0.31,0],["gemini-3-flash-preview",1048576,65536,"text,image",1,null,0.5,3,0.05,0],["gemini-3-pro-preview",1048576,65536,"text,image",1,null,2,12,0.2,0],["gemini-3.1-flash-lite",1048576,65536,"text,image",1,null,0.25,1.5,0.025,0],["gemini-3.1-flash-lite-image",65536,65536,"text,image",1,null,0.25,30,0,0],["gemini-3.1-flash-lite-preview",1048576,65536,"text,image",1,null,0.25,1.5,0.025,0],["gemini-3.1-flash-live-preview",131072,65536,"text,image",1,null,0.75,4.5,0,0],["gemini-3.1-pro-preview",1048576,65536,"text,image",1,null,2,12,0.2,0],["gemini-3.1-pro-preview-customtools",1048576,65536,"text,image",1,null,2,12,0.2,0],["gemini-3.5-flash",1048576,65536,"text,image",1,null,1.5,9,0.15,0],["gemini-3.5-flash-lite",1048576,65536,"text,image",1,null,0.3,2.5,0.03,0],["gemini-3.6-flash",1048576,65536,"text,image",1,null,1.5,7.5,0.15,0],["gemini-3.7-flash",1048576,65536,"text,image",1],["gemini-flash-latest",1048576,65536,"text,image",1,null,1.5,9,0.15,0],["gemini-flash-lite-latest",1048576,65536,"text,image",1,null,0.25,1.5,0.025,0],["gemini-live-2.5-flash",128000,8000,"text,image",1,null,0.5,2,0,0],["gemini-live-2.5-flash-preview-native-audio",131072,65536,"text",1,null,0.5,2,0,0],["gemini-robotics-er-1.6-preview",131072,65536,"text,image",1,null,1,5,0,0],["gemma-3-27b-it",131072,8192,"text,image",0,null,0,0,0,0],["gemma-4-26b",256000,8192,"text,image",1,null,0,0,0,0],["gemma-4-26b-a4b-it",262144,32768,"text,image",1,null,0,0,0,0],["gemma-4-26b-it",256000,8192,"text,image",1,null,0,0,0,0],["gemma-4-31b",256000,8192,"text,image",1,null,0,0,0,0],["gemma-4-31b-it",262144,32768,"text,image",1,null,0,0,0,0],["gemma-4-E2B-it",131072,8192,"text,image",1,null,0,0,0,0],["gemma-4-E4B-it",131072,8192,"text,image",1,null,0,0,0,0]],
46
46
  "minimax": [["MiniMax-M2",196608,128000,"text",1,null,0.3,1.2,0,0],["MiniMax-M2.1",204800,131072,"text",1,null,0.3,1.2,0,0],["MiniMax-M2.5",204800,131072,"text",1,null,0.3,1.2,0.03,0.375],["MiniMax-M2.5-highspeed",204800,131072,"text",1,null,0.6,2.4,0.06,0.375],["MiniMax-M2.5-lightning",204800,32000,"text",1,null,0.3,2.4,0,0],["MiniMax-M2.7",204800,131072,"text",1,null,0.3,1.2,0.06,0.375],["MiniMax-M2.7-highspeed",204800,131072,"text",1,null,0.6,2.4,0.06,0.375],["minimax-m3",512000,128000,"text,image",1,null,0.6,2.4,0.12,0],["MiniMax-M3",1000000,128000,"text,image,video",1,null,0.3,1.2,0.06,0]],
47
47
  "mistral": [["codestral-latest",256000,4096,"text",0,null,0.3,0.9,0,0],["devstral-2512",262144,262144,"text",0,null,0.4,2,0,0],["devstral-latest",262144,262144,"text",0,null,0.4,2,0,0],["devstral-medium-2507",128000,128000,"text",0,null,0.4,2,0,0],["devstral-medium-latest",262144,262144,"text",0,null,0.4,2,0,0],["devstral-small-2505",128000,128000,"text",0,null,0.1,0.3,0,0],["devstral-small-2507",128000,128000,"text",0,null,0.1,0.3,0,0],["labs-devstral-small-2512",256000,256000,"text,image",0,null,0,0,0,0],["magistral-medium-latest",128000,16384,"text",1,null,2,5,0,0],["magistral-small",128000,128000,"text",1,null,0.5,1.5,0,0],["ministral-3b-latest",128000,128000,"text",0,null,0.04,0.04,0,0],["ministral-8b-latest",128000,128000,"text",0,null,0.1,0.1,0,0],["mistral-large-2411",131072,16384,"text",0,null,2,6,0,0],["mistral-large-2512",262144,262144,"text,image",0,null,0.5,1.5,0,0],["mistral-large-latest",262144,262144,"text,image",0,null,0.5,1.5,0,0],["mistral-medium-2505",131072,131072,"text,image",0,null,0.4,2,0,0],["mistral-medium-2508",262144,262144,"text,image",0,null,0.4,2,0,0],["mistral-medium-2604",262144,262144,"text,image",1,null,1.5,7.5,0,0],["mistral-medium-latest",262144,262144,"text,image",1,null,1.5,7.5,0,0],["mistral-nemo",128000,128000,"text",0,null,0.15,0.15,0,0],["mistral-small-2506",128000,16384,"text,image",0,null,0.1,0.3,0,0],["mistral-small-2603",256000,256000,"text,image",1,null,0.15,0.6,0,0],["mistral-small-latest",256000,256000,"text,image",1,null,0.15,0.6,0,0],["open-mistral-7b",8000,8000,"text",0,null,0.25,0.25,0,0],["open-mistral-nemo",128000,128000,"text",0,null,0.15,0.15,0,0],["open-mixtral-8x22b",64000,64000,"text",0,null,2,6,0,0],["open-mixtral-8x7b",32000,32000,"text",0,null,0.7,0.7,0,0],["pixtral-12b",128000,128000,"text,image",0,null,0.15,0.15,0,0],["pixtral-large-latest",128000,128000,"text,image",0,null,2,6,0,0]],
48
48
  "moonshot": [["kimi-k2.5",262144,65536,"text,image",1,null,0,0,0,0]],