dsh-lcx-codex 0.4.3-pre.4 → 0.4.3

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 (42) hide show
  1. package/README.md +68 -126
  2. package/THIRD_PARTY_NOTICES.md +64 -0
  3. package/lib/auxiliary-usage.js +63 -0
  4. package/lib/client.js +1363 -295
  5. package/lib/dsh-compat.js +80 -18
  6. package/lib/dsh-responses.js +75 -8
  7. package/lib/grok-native-search.js +151 -79
  8. package/lib/index.js +159 -101
  9. package/lib/invocation-policy-scope.js +261 -0
  10. package/lib/json-store.js +11 -4
  11. package/lib/pi-responses-runtime.js +1571 -0
  12. package/lib/responses-request.js +1 -1
  13. package/lib/responses-stream.js +152 -84
  14. package/lib/route.js +17 -3
  15. package/lib/search-accounting.js +86 -0
  16. package/lib/search-usage.js +86 -0
  17. package/lib/transport.js +38 -10
  18. package/lib/types/client/index.d.ts +12 -0
  19. package/lib/types/client/search-media.d.ts +16 -0
  20. package/lib/web-run-output.js +22 -0
  21. package/lib/web-search-alpha.js +230 -28
  22. package/lib/web-search-capability.js +26 -1
  23. package/lib/web-search-hosted.js +119 -9
  24. package/lib/web-search-ref-store.js +88 -7
  25. package/package.json +45 -24
  26. package/lib/types/compact-v2.d.ts +0 -104
  27. package/lib/types/dsh-compat.d.ts +0 -78
  28. package/lib/types/dsh-responses.d.ts +0 -82
  29. package/lib/types/grok-native-search.d.ts +0 -39
  30. package/lib/types/json-store.d.ts +0 -10
  31. package/lib/types/native-checkpoint.d.ts +0 -213
  32. package/lib/types/responses-request.d.ts +0 -59
  33. package/lib/types/responses-stream.d.ts +0 -64
  34. package/lib/types/route.d.ts +0 -153
  35. package/lib/types/service-mutex.d.ts +0 -14
  36. package/lib/types/token-budget.d.ts +0 -50
  37. package/lib/types/transport.d.ts +0 -21
  38. package/lib/types/web-run-output.d.ts +0 -29
  39. package/lib/types/web-search-alpha.d.ts +0 -286
  40. package/lib/types/web-search-capability.d.ts +0 -26
  41. package/lib/types/web-search-hosted.d.ts +0 -246
  42. package/lib/types/web-search-ref-store.d.ts +0 -22
package/lib/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import z from "@deepseek-ai/schemastery";
2
+ import { recordHostedUsage, withAuxiliaryUsage } from "./auxiliary-usage.js";
3
+ import { installSearchUsage } from "./search-usage.js";
2
4
  import { WEB_SEARCH_MAX_QUERIES, applyWebSearchTool, } from "@deepseek-ai/dsh-tool-web";
3
5
  import "@deepseek-ai/dsh-agent";
4
6
  import "@deepseek-ai/dsh-tools";
@@ -7,21 +9,22 @@ import { randomUUID } from "node:crypto";
7
9
  import { homedir } from "node:os";
8
10
  import { join } from "node:path";
9
11
  import { AsyncLocalStorage } from "node:async_hooks";
10
- import { getSupportedThinkingLevels } from "@earendil-works/pi-ai";
12
+ import { getSupportedThinkingLevels } from "./pi-responses-runtime.js";
11
13
  import { fetchJsonWithRetry } from "./transport.js";
12
14
  import { agentSessionId, agentUsesSession, compactionConfigState, compactionPatchCandidate, installCompactionPatch, patchCompactionConfig, patchToolResultPruner, readAgentRouteState, resolveAgentService, resolveContextService, resolveScopedService, restoreCompactionConfig, restoreCompactionPatches, restoreToolResultPruner, sessionFor, sessionFromAgent, scopedToolRuntime, tokenMeterTotal, toolResultPrunerState, } from "./dsh-compat.js";
15
+ import { InvocationPolicyScope } from "./invocation-policy-scope.js";
13
16
  import { authenticatedGrokHeaders, authenticatedHeaders, currentRoute, generationControlsFromSession, grokPromptCacheSessionId, promptCacheKey, promptCacheRetention, promptCacheSessionId, resolveGrokResponsesRouteConfig, resolveResponsesRouteConfig, routeFingerprint, } from "./route.js";
14
17
  import { DEFAULT_MAX_REQUEST_IMAGE_BYTES, DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET, DEFAULT_REQUEST_IMAGE_MAX_BYTES, hydrateNativeImageReferences, resolveModelImageSupport, responseInputItems, serializeDshMessages, } from "./dsh-responses.js";
15
18
  import { mergeFeatureHeader, requestNativeCompaction } from "./compact-v2.js";
16
19
  import { buildResponsesBody } from "./responses-request.js";
17
20
  import { managedFailureChunk, streamResponsesRequest, } from "./responses-stream.js";
18
21
  import { assertSupportedCheckpointMessage, checkpointStateForMessage, compactCheckpointId, createNativeCheckpointBlock, nativeCheckpointChunks, portableMessagesForCheckpoint, stateRouteCompatible, } from "./native-checkpoint.js";
19
- import { HOSTED_SEARCH_OUTPUT, HOSTED_SEARCH_PARAMETERS, buildHostedSearchBody, normalizeHostedSearchArgs, parseHostedSearchResponse, renderHostedSearchResult, } from "./web-search-hosted.js";
20
- import { ALPHA_SCHEMA_FINGERPRINT, alphaRefRequiresStore, isAlphaContinuationUrl, isAlphaHttpUrl, ALPHA_SEARCH_OUTPUT, ALPHA_SEARCH_PARAMETERS, buildAlphaSearchBody, normalizeAlphaSearchArgs, parseAlphaSearchResponse, renderAlphaSearchResult, } from "./web-search-alpha.js";
21
- import { AlphaCapabilityStore, alphaCapabilityFingerprint, alphaCapabilityUsable, } from "./web-search-capability.js";
22
+ import { HOSTED_SEARCH_OUTPUT, HOSTED_SEARCH_PARAMETERS, buildHostedSearchBody, hostedMediaPresentationMeta, normalizeHostedSearchArgs, parseHostedSearchResponse, renderHostedSearchResult, } from "./web-search-hosted.js";
23
+ import { ALPHA_SCHEMA_FINGERPRINT, alphaRefRequiresStore, isAlphaContinuationUrl, isAlphaHttpUrl, ALPHA_SEARCH_OUTPUT, ALPHA_SEARCH_PARAMETERS, alphaSearchRetryOptions, buildAlphaSearchBody, normalizeAlphaSearchArgs, parseAlphaSearchResponse, renderAlphaSearchResult, runWithAlphaSessionLock, } from "./web-search-alpha.js";
24
+ import { AlphaCapabilityStore, alphaCapabilityFingerprint, alphaCapabilityUsable, alphaSearchParametersFor, assertAlphaActionAllowed, } from "./web-search-capability.js";
22
25
  import { AlphaRefStore } from "./web-search-ref-store.js";
23
26
  import { ServiceMutex } from "./service-mutex.js";
24
- import { GROK_NATIVE_SERVER_TOOL_TYPES, grokNativeSearchEnabled, grokVisibleFunctionTools, grokWireTools, restoreGrokNativeReplay, } from "./grok-native-search.js";
27
+ import { GROK_NATIVE_SERVER_TOOL_TYPES, grokNativeSearchEnabled, grokVisibleFunctionTools, isGrokNativeServerToolItem, grokWireTools, restoreGrokNativeReplay, } from "./grok-native-search.js";
25
28
  export const name = "lcx-codex";
26
29
  export const inject = ["llm", "web", "sessions", "tools", "settings", "credentials", "attachments", "fs"];
27
30
  const SETTINGS_NS = "lcx-codex";
@@ -118,6 +121,7 @@ const SettingsSchema = z.object({
118
121
  alphaSearch: z.boolean().default(false),
119
122
  grokNativeWebSearch: z.boolean().default(false),
120
123
  grokNativeXSearch: z.boolean().default(false),
124
+ searchMediaPreview: z.boolean().default(false),
121
125
  });
122
126
  function normalizeConfig(input = {}) {
123
127
  return {
@@ -201,6 +205,7 @@ async function executeHostedSearch(ctx, routeConfig, args, signal, sessionId = "
201
205
  maxAttempts: routeConfig.maxAttempts,
202
206
  maxResponseBytes: routeConfig.maxResponseBytes,
203
207
  });
208
+ recordHostedUsage(response, requestId, routeConfig.provider, routeConfig.model);
204
209
  return parseHostedSearchResponse(response, requestId, routeConfig.webMaxResults);
205
210
  }
206
211
  class LcxResponsesSearchProvider {
@@ -261,8 +266,15 @@ function createScopedGptWebSearchTool(ctx, state, getConfig, provider, fetchEnab
261
266
  if (!definition)
262
267
  throw new Error("DSH web_search composition did not register a tool");
263
268
  const execute = definition.execute.bind(definition);
264
- return {
269
+ const output = definition.output;
270
+ return withAuxiliaryUsage({
265
271
  ...definition,
272
+ output: {
273
+ ...output,
274
+ presentationMeta(args, value) {
275
+ return hostedMediaPresentationMeta(value, "web_search", output.presentationMeta?.(args, value));
276
+ },
277
+ },
266
278
  async execute(args, exec) {
267
279
  if (!state.enabled || !state.webSearch)
268
280
  throw webError("web_search GPT Hosted Search is disabled", "LCX_WEB_DISABLED");
@@ -272,16 +284,17 @@ function createScopedGptWebSearchTool(ctx, state, getConfig, provider, fetchEnab
272
284
  throw webError("GPT Hosted Search requires the active GPT openai-responses route", "LCX_WEB_ROUTE_UNAVAILABLE");
273
285
  return hostedSearchRouteContext.run(active, () => execute(args, exec));
274
286
  },
275
- };
287
+ });
276
288
  }
277
289
  function createAdvancedHostedTool(ctx, state, getConfig) {
278
- return {
290
+ return withAuxiliaryUsage({
279
291
  name: ADVANCED_HOSTED_TOOL,
280
292
  description: "Advanced GPT Responses Hosted Search. Use DSH web_search for ordinary lookup. Call this only when you need domain allow/block filters, approximate user location, search-context size, image search, external-web-access or return-token-budget controls. It is one-shot and has no open/find/click state.",
281
293
  parameters: HOSTED_SEARCH_PARAMETERS,
282
294
  output: {
283
295
  schema: HOSTED_SEARCH_OUTPUT,
284
296
  render: (_args, value) => renderHostedSearchResult(value),
297
+ presentationMeta: (_args, value) => hostedMediaPresentationMeta(value, ADVANCED_HOSTED_TOOL),
285
298
  },
286
299
  async execute(args, exec) {
287
300
  if (!state.enabled || !state.webSearch || !state.advancedHostedSearch)
@@ -293,7 +306,7 @@ function createAdvancedHostedTool(ctx, state, getConfig) {
293
306
  throw webError("Advanced Hosted Search requires the active GPT openai-responses route", "LCX_WEB_ROUTE_UNAVAILABLE");
294
307
  return executeHostedSearch(ctx, routeWithPolicies(route, config), args, exec.signal, active.sessionId);
295
308
  },
296
- };
309
+ });
297
310
  }
298
311
  function disposeGptToolsForAgent(agent, registrations) {
299
312
  const registration = registrations.get(agent);
@@ -376,52 +389,69 @@ function verifiedAlphaCapabilityForRoute(ctx, active, config, store) {
376
389
  };
377
390
  }
378
391
  async function executeAlpha(ctx, routeConfig, capability, refStore, args, exec) {
379
- const normalized = normalizeAlphaSearchArgs(args);
380
- if (["open", "find", "screenshot"].includes(normalized.action) &&
381
- isAlphaHttpUrl(normalized.refId) &&
382
- !isAlphaContinuationUrl(normalized.refId)) {
383
- throw webError("Alpha Search direct URLs must be public HTTP(S) targets", "LCX_ALPHA_URL_UNAVAILABLE");
384
- }
385
392
  const sessionId = agentSessionId(exec?.agent);
386
393
  if (!sessionId)
387
394
  throw webError("Alpha Search requires a DSH session", "LCX_ALPHA_SESSION_REQUIRED");
388
- const routeFp = routeFingerprint({
389
- provider: routeConfig.provider,
390
- model: routeConfig.model,
391
- baseURL: routeConfig.baseURL,
392
- sessionId,
393
- });
394
- if (alphaRefRequiresStore(normalized.action, normalized.refId))
395
- refStore.assertUsable(sessionId, routeFp, normalized.refId);
396
- const requestId = randomUUID();
397
- const headers = await authenticatedHeaders(ctx, routeConfig, sessionId, requestId);
398
- let response;
399
- try {
400
- response = await fetchJsonWithRetry(`${routeConfig.baseURL}/alpha/search`, buildAlphaSearchBody(normalized, routeConfig.model, sessionId, true, routeConfig.alphaMaxOutputTokens), headers, exec?.signal, routeConfig.timeoutMs, {
401
- maxAttempts: routeConfig.maxAttempts,
402
- maxResponseBytes: routeConfig.maxResponseBytes,
395
+ return runWithAlphaSessionLock(sessionId, exec?.signal, async () => {
396
+ const normalized = normalizeAlphaSearchArgs(args);
397
+ assertAlphaActionAllowed(capability, normalized.action);
398
+ if (["open", "find", "screenshot"].includes(normalized.action) &&
399
+ isAlphaHttpUrl(normalized.refId) &&
400
+ !isAlphaContinuationUrl(normalized.refId)) {
401
+ throw webError("Alpha Search direct URLs must be public HTTP(S) targets", "LCX_ALPHA_URL_UNAVAILABLE");
402
+ }
403
+ const routeFp = routeFingerprint({
404
+ provider: routeConfig.provider,
405
+ model: routeConfig.model,
406
+ baseURL: routeConfig.baseURL,
407
+ sessionId,
403
408
  });
404
- }
405
- catch (error) {
406
- const details = errorDetails(error);
407
- if ([404, 405].includes(Number(details.status)) ||
408
- /channel does not support/iu.test(String(details.message ?? "")))
409
- throw webError("Alpha Search is not supported by this route", "LCX_ALPHA_UNAVAILABLE", error);
410
- throw webError("Alpha Search provider request failed", "LCX_ALPHA_PROVIDER_ERROR", error);
411
- }
412
- const { refRecords, ...result } = parseAlphaSearchResponse(response, {
413
- action: normalized.action,
414
- capability: capability.classification,
415
- requestId,
409
+ const continuedRef = alphaRefRequiresStore(normalized.action, normalized.refId)
410
+ ? refStore.assertUsable(sessionId, routeFp, normalized.refId)
411
+ : undefined;
412
+ const requestId = randomUUID();
413
+ const headers = await authenticatedHeaders(ctx, routeConfig, sessionId, requestId);
414
+ let response;
415
+ try {
416
+ response = await fetchJsonWithRetry(`${routeConfig.baseURL}/alpha/search`, buildAlphaSearchBody(normalized, routeConfig.model, sessionId, true, routeConfig.alphaMaxOutputTokens), headers, exec?.signal, routeConfig.timeoutMs, alphaSearchRetryOptions(routeConfig.maxResponseBytes));
417
+ }
418
+ catch (error) {
419
+ const details = errorDetails(error);
420
+ if ([404, 405].includes(Number(details.status)) ||
421
+ /channel does not support/iu.test(String(details.message ?? "")))
422
+ throw webError("Alpha Search is not supported by this route", "LCX_ALPHA_UNAVAILABLE", error);
423
+ throw webError("Alpha Search provider request failed", "LCX_ALPHA_PROVIDER_ERROR", error);
424
+ }
425
+ const { refRecords: observedRefs, ...result } = parseAlphaSearchResponse(response, {
426
+ action: normalized.action,
427
+ capability: capability.classification,
428
+ requestId,
429
+ });
430
+ const refRecords = observedRefs.map((observation) => {
431
+ if (observation.refId !== normalized.refId || !continuedRef)
432
+ return observation;
433
+ const observedArtifact = observation.provenance.artifactFingerprint;
434
+ const acceptedArtifact = continuedRef.provenance.artifactFingerprint;
435
+ if (observedArtifact && observedArtifact !== acceptedArtifact)
436
+ return observation;
437
+ // An echoed input ref retains its accepted origin; an omitted URL makes no new claim.
438
+ return {
439
+ ...observation,
440
+ ...(observation.url === undefined && continuedRef.url ? { url: continuedRef.url } : {}),
441
+ provenance: { ...continuedRef.provenance },
442
+ };
443
+ });
444
+ refStore.record(sessionId, routeFp, refRecords);
445
+ return result;
416
446
  });
417
- refStore.record(sessionId, routeFp, refRecords);
418
- return result;
419
447
  }
420
- function createAlphaTool(ctx, state, getConfig, capabilityStore, refStore) {
448
+ function createAlphaTool(ctx, state, getConfig, capabilityStore, refStore, advertisedRecord) {
421
449
  return {
422
450
  name: ALPHA_TOOL,
423
451
  description: "Stateful Codex/Alpha web command tool. Use it for search/open/find/click/PDF screenshot and the structured image/finance/weather/sports/time actions. Use DSH web_search for ordinary search, and websearch_gpt_advanced only for Hosted Search controls.",
424
- parameters: ALPHA_SEARCH_PARAMETERS,
452
+ parameters: advertisedRecord
453
+ ? alphaSearchParametersFor(advertisedRecord)
454
+ : ALPHA_SEARCH_PARAMETERS,
425
455
  output: {
426
456
  schema: ALPHA_SEARCH_OUTPUT,
427
457
  render: (_args, value) => renderAlphaSearchResult(value),
@@ -474,7 +504,7 @@ function syncAlphaToolForAgent(ctx, agent, state, getConfig, capabilityStore, re
474
504
  // Alpha is route-bound; global registration would advertise a static record to other routes.
475
505
  registrations.set(agent, {
476
506
  fingerprint: capability.fingerprint,
477
- dispose: scopedTools.register(createAlphaTool(ctx, state, getConfig, capabilityStore, refStore)),
507
+ dispose: scopedTools.register(createAlphaTool(ctx, state, getConfig, capabilityStore, refStore, capability.record)),
478
508
  });
479
509
  return true;
480
510
  }
@@ -522,8 +552,15 @@ async function serializeNativeAware(messages, route, routeConfig, ctx, options)
522
552
  responsesCompat: routeConfig.responsesCompat,
523
553
  ...extra,
524
554
  });
555
+ const firstMessage = messages[0];
556
+ const systemHead = firstMessage?.role === "system" ? firstMessage : undefined;
557
+ const surfaceMessages = systemHead ? messages.slice(1) : messages;
558
+ const systemPrompt = systemHead?.content
559
+ .filter((block) => block.type === "text")
560
+ .map((block) => block.text)
561
+ .join("") || undefined;
525
562
  const prelude = await serializeDshMessages([], ctx, serializeOptions(undefined, {
526
- systemPrompt: options.system,
563
+ systemPrompt,
527
564
  includeSystemPrompt: true,
528
565
  }));
529
566
  const ephemeralPreludeItemCount = prelude.input.length;
@@ -544,7 +581,7 @@ async function serializeNativeAware(messages, route, routeConfig, ctx, options)
544
581
  input.push(...restoreGrokNativeReplay(serialized.input, batch, options.grokNativeReplayRoute));
545
582
  mergeMap(imageMap, serialized.imageMap);
546
583
  };
547
- for (const message of messages ?? []) {
584
+ for (const message of surfaceMessages ?? []) {
548
585
  assertSupportedCheckpointMessage(message);
549
586
  const state = session
550
587
  ? checkpointStateForMessage(session, message)
@@ -600,7 +637,7 @@ async function* remoteCompactionStream(options, routeConfig, ctx, next) {
600
637
  const history = stripCompactionDirective(options.messages);
601
638
  const route = currentRoute(options, routeConfig);
602
639
  try {
603
- const prepared = await serializeNativeAware(history, route, routeConfig, ctx, { signal: options.signal, system: options.system, tools: options.tools });
640
+ const prepared = await serializeNativeAware(history, route, routeConfig, ctx, { signal: options.signal, tools: options.tools });
604
641
  const cacheSessionId = promptCacheSessionId(route, routeConfig, ctx);
605
642
  const headers = await authenticatedHeaders(ctx, routeConfig, cacheSessionId, cacheSessionId === undefined ? null : route.sessionId);
606
643
  const generation = generationControlsFromSession(sessionFor(ctx, route.sessionId), route);
@@ -715,56 +752,68 @@ function patchCompactionPressureService(compactionValue, state, getConfig, ctx,
715
752
  if (!candidate)
716
753
  return false;
717
754
  const mutex = new ServiceMutex();
755
+ const policyScope = new InvocationPolicyScope();
718
756
  const lifecycle = new AbortController();
719
- return installCompactionPatch(records, candidate, mutex, lifecycle, async (agent, trigger, signal, callOriginal) => {
757
+ return installCompactionPatch(records, candidate, mutex, policyScope, lifecycle, async (agent, trigger, signal, callOriginal) => {
720
758
  const activeSignal = combinedAbortSignal(signal, lifecycle.signal);
721
- return mutex.run(activeSignal, async () => {
722
- if (trigger !== "pressure" || !state.enabled)
723
- return callOriginal(activeSignal);
724
- const config = getConfig();
725
- const target = routedTargetForAgent(agent);
726
- if (!target || !resolveResponsesRouteConfig(ctx, target, config))
727
- return callOriginal(activeSignal);
728
- const session = sessionFromAgent(agent);
729
- const tokenMeter = resolveScopedService(agent, "tokenMeter") ??
730
- resolveContextService(ctx, "tokenMeter");
731
- if (!session || tokenMeter === undefined)
732
- return callOriginal(activeSignal);
733
- let contextWindow;
734
- try {
735
- contextWindow = (await ctx.llm.resolveModelInfo(target.provider, target.model, activeSignal)).context?.contextWindow;
736
- }
737
- catch {
738
- return callOriginal(activeSignal);
739
- }
740
- const totalTokens = tokenMeterTotal(tokenMeter, session);
741
- if (contextWindow === undefined ||
742
- contextWindow <= 0 ||
743
- totalTokens === undefined)
744
- return callOriginal(activeSignal);
745
- const auto = AUTO_COMPACTION_THRESHOLD_PERCENT;
746
- const emergency = EMERGENCY_PRUNE_THRESHOLD_PERCENT;
747
- const pressure = compactionPressureBand(totalTokens, contextWindow, {
748
- auto,
749
- emergency,
750
- });
751
- if (pressure.band === "below")
752
- return null;
753
- const prunerState = toolResultPrunerState(resolveAgentService(ctx, agent, "toolResultPruner"));
754
- const configState = compactionConfigState(compactionValue);
755
- const nativeFirst = pressure.band === "native";
756
- const prunerPatch = nativeFirst
757
- ? patchToolResultPruner(prunerState, () => ({ pruned: [], charsRemoved: 0 }))
758
- : undefined;
759
- const configPatch = patchCompactionConfig(configState, (originalConfig) => adjustedCompactionConfig(originalConfig, target, auto / 100));
760
- ctx.logger?.info?.(`[lcx-codex] auto pressure ${pressure.ratioPercent.toFixed(1)}%: ${nativeFirst ? "Native V2 first" : "emergency DSH prune allowed"} (native ${auto}%, emergency ${emergency}%)`);
761
- try {
762
- return await callOriginal(activeSignal);
763
- }
764
- finally {
765
- restoreCompactionConfig(configPatch);
766
- restoreToolResultPruner(prunerPatch);
767
- }
759
+ const configScoped = policyScope.ensure(compactionConfigState(candidate.compaction).service, "config");
760
+ const prunerState = toolResultPrunerState(resolveAgentService(ctx, agent, "toolResultPruner") ??
761
+ resolveScopedService(agent, "toolResultPruner") ??
762
+ resolveContextService(ctx, "toolResultPruner"));
763
+ const prunerScoped = !prunerState.pruner ||
764
+ (typeof prunerState.original === "function" &&
765
+ policyScope.ensure(prunerState.pruner, "pruneSession"));
766
+ const accessMode = configScoped && prunerScoped ? "shared" : "exclusive";
767
+ return policyScope.run(activeSignal, accessMode, async () => {
768
+ const invoke = async () => {
769
+ if (trigger !== "pressure" || !state.enabled)
770
+ return callOriginal(activeSignal);
771
+ const config = getConfig();
772
+ const target = routedTargetForAgent(agent);
773
+ if (!target || !resolveResponsesRouteConfig(ctx, target, config))
774
+ return callOriginal(activeSignal);
775
+ const session = sessionFromAgent(agent);
776
+ const tokenMeter = resolveScopedService(agent, "tokenMeter") ??
777
+ resolveContextService(ctx, "tokenMeter");
778
+ if (!session || tokenMeter === undefined)
779
+ return callOriginal(activeSignal);
780
+ let contextWindow;
781
+ try {
782
+ contextWindow = (await ctx.llm.resolveModelInfo(target.provider, target.model, activeSignal)).context?.contextWindow;
783
+ }
784
+ catch {
785
+ return callOriginal(activeSignal);
786
+ }
787
+ const totalTokens = tokenMeterTotal(tokenMeter, session);
788
+ if (contextWindow === undefined ||
789
+ contextWindow <= 0 ||
790
+ totalTokens === undefined)
791
+ return callOriginal(activeSignal);
792
+ const auto = AUTO_COMPACTION_THRESHOLD_PERCENT;
793
+ const emergency = EMERGENCY_PRUNE_THRESHOLD_PERCENT;
794
+ const pressure = compactionPressureBand(totalTokens, contextWindow, {
795
+ auto,
796
+ emergency,
797
+ });
798
+ if (pressure.band === "below")
799
+ return null;
800
+ const nativeFirst = pressure.band === "native";
801
+ const prunerPatch = nativeFirst
802
+ ? patchToolResultPruner(prunerState, () => ({ pruned: [], charsRemoved: 0 }))
803
+ : undefined;
804
+ const configPatch = patchCompactionConfig(compactionConfigState(candidate.compaction), (originalConfig) => adjustedCompactionConfig(originalConfig, target, auto / 100));
805
+ ctx.logger?.info?.(`[lcx-codex] auto pressure ${pressure.ratioPercent.toFixed(1)}%: ${nativeFirst ? "Native V2 first" : "emergency DSH prune allowed"} (native ${auto}%, emergency ${emergency}%)`);
806
+ try {
807
+ return await callOriginal(activeSignal);
808
+ }
809
+ finally {
810
+ restoreCompactionConfig(configPatch);
811
+ restoreToolResultPruner(prunerPatch);
812
+ }
813
+ };
814
+ return accessMode === "shared"
815
+ ? invoke()
816
+ : mutex.run(activeSignal, invoke);
768
817
  });
769
818
  });
770
819
  }
@@ -778,8 +827,13 @@ async function restoreCompactionPressure(records) {
778
827
  if (!record.lifecycle.signal.aborted)
779
828
  record.lifecycle.abort(reason);
780
829
  }
781
- await Promise.allSettled(entries.map((record) => record.mutex.close(reason)));
830
+ await Promise.allSettled(entries.flatMap((record) => [
831
+ record.policyScope.close(reason),
832
+ record.mutex.close(reason),
833
+ ]));
782
834
  restoreCompactionPatches(records, entries);
835
+ for (const record of entries)
836
+ record.policyScope.restore();
783
837
  }
784
838
  function messagesContainNativeCheckpoint(messages, session) {
785
839
  return session !== undefined && messages.some((message) => checkpointStateForMessage(session, message));
@@ -792,7 +846,7 @@ async function* managedResponsesStream(options, routeConfig, ctx) {
792
846
  try {
793
847
  if (options.stop !== undefined)
794
848
  throw Object.assign(new Error("LCX Responses does not support GenerateOptions.stop"), { code: "LCX_RESPONSES_UNSUPPORTED_OPTION" });
795
- const prepared = await serializeNativeAware(options.messages, route, routeConfig, ctx, { signal: options.signal, system: options.system, tools: options.tools });
849
+ const prepared = await serializeNativeAware(options.messages, route, routeConfig, ctx, { signal: options.signal, tools: options.tools });
796
850
  const cacheSessionId = promptCacheSessionId(route, routeConfig, ctx);
797
851
  const headers = await authenticatedHeaders(ctx, routeConfig, cacheSessionId, cacheSessionId === undefined ? null : route.sessionId);
798
852
  const body = buildResponsesBody({
@@ -837,9 +891,9 @@ async function* managedGrokNativeSearchStream(options, routeConfig, nativeSearch
837
891
  if (options.stop !== undefined)
838
892
  throw Object.assign(new Error("LCX Responses does not support GenerateOptions.stop"), { code: "LCX_RESPONSES_UNSUPPORTED_OPTION" });
839
893
  const visibleTools = grokVisibleFunctionTools(options.tools, nativeSearch);
894
+ const declaredToolNames = new Set(visibleTools?.map((tool) => tool.name) ?? []);
840
895
  const prepared = await serializeNativeAware(options.messages, route, routeConfig, ctx, {
841
896
  signal: options.signal,
842
- system: options.system,
843
897
  tools: visibleTools,
844
898
  grokNativeReplayRoute: nativeReplayRoute,
845
899
  });
@@ -889,6 +943,8 @@ async function* managedGrokNativeSearchStream(options, routeConfig, nativeSearch
889
943
  maxAttempts: 1,
890
944
  maxResponseBytes: routeConfig.maxResponseBytes,
891
945
  serverToolTypes: GROK_NATIVE_SERVER_TOOL_TYPES,
946
+ isServerToolItem: (item) => isGrokNativeServerToolItem(item, nativeSearch, declaredToolNames),
947
+ declaredToolNames,
892
948
  nativeReplayRoute,
893
949
  onServerToolUsage(usage) {
894
950
  ctx.logger?.info?.(`[lcx-codex] Grok native search used ${usage.total} server-side tool call(s) (web=${usage.webSearchCalls}, x=${usage.xSearchCalls})`);
@@ -906,6 +962,7 @@ async function* unavailableManagedRouteStream(options) {
906
962
  yield managedFailureChunk(Object.assign(new Error("LCX is enabled but the selected DSH route cannot be resolved as an authenticated OpenAI Responses wire route"), { code: "LCX_RESPONSES_ROUTE_UNAVAILABLE" }), options.signal);
907
963
  }
908
964
  function installInjected(ctx, configInput = {}) {
965
+ installSearchUsage(ctx);
909
966
  const baseConfig = normalizeConfig(configInput);
910
967
  let runtimeConfig = baseConfig;
911
968
  const state = {
@@ -952,6 +1009,7 @@ function installInjected(ctx, configInput = {}) {
952
1009
  alphaSearch: false,
953
1010
  grokNativeWebSearch: false,
954
1011
  grokNativeXSearch: false,
1012
+ searchMediaPreview: false,
955
1013
  };
956
1014
  let source = () => settingsEntry;
957
1015
  ctx.settings.installSection(ctx, SETTINGS_NS, SettingsSchema, settingsEntry, {