dsh-lcx-codex 0.4.3 → 0.5.0-pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -60
- package/lib/abort-error.js +47 -0
- package/lib/client.js +597 -505
- package/lib/dsh-compat.js +37 -0
- package/lib/dsh-responses.js +92 -48
- package/lib/index.js +174 -105
- package/lib/invocation-policy-scope.js +4 -8
- package/lib/native-checkpoint.js +172 -80
- package/lib/pi-responses-runtime.js +252 -98
- package/lib/pi086-responses-allowlist.js +131 -0
- package/lib/responses-request.js +2 -2
- package/lib/responses-stream.js +62 -11
- package/lib/route.js +23 -32
- package/lib/search-accounting.js +22 -6
- package/lib/search-usage.js +32 -18
- package/lib/service-mutex.js +4 -8
- package/lib/token-budget.js +15 -21
- package/lib/transport.js +6 -6
- package/lib/types/client/search-media.d.ts +11 -2
- package/lib/types/index.d.ts +71 -43
- package/lib/web-search-alpha-history.js +62 -0
- package/lib/web-search-alpha.js +141 -124
- package/lib/web-search-capability.js +1 -1
- package/lib/web-search-hosted.js +29 -17
- package/lib/web-search-ref-store.js +27 -5
- package/package.json +41 -27
package/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import z from "@deepseek-ai/schemastery";
|
|
2
2
|
import { recordHostedUsage, withAuxiliaryUsage } from "./auxiliary-usage.js";
|
|
3
3
|
import { installSearchUsage } from "./search-usage.js";
|
|
4
|
+
import { projectToolUpdates } from "@deepseek-ai/dsh-llm";
|
|
4
5
|
import { WEB_SEARCH_MAX_QUERIES, applyWebSearchTool, } from "@deepseek-ai/dsh-tool-web";
|
|
5
6
|
import "@deepseek-ai/dsh-agent";
|
|
6
7
|
import "@deepseek-ai/dsh-tools";
|
|
@@ -11,7 +12,7 @@ import { join } from "node:path";
|
|
|
11
12
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
12
13
|
import { getSupportedThinkingLevels } from "./pi-responses-runtime.js";
|
|
13
14
|
import { fetchJsonWithRetry } from "./transport.js";
|
|
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 { agentSessionId, agentUsesSession, compactionConfigState, compactionPatchCandidate, installCompactionPatch, patchCompactionConfig, patchToolResultPruner, readAgentRouteState, readSelectedAgentRouteState, recordAgentRouteEvent, resolveAgentService, resolveContextService, resolveScopedService, restoreCompactionConfig, restoreCompactionPatches, restoreToolResultPruner, sessionFor, sessionFromAgent, scopedToolRuntime, tokenMeterTotal, toolResultPrunerState, } from "./dsh-compat.js";
|
|
15
16
|
import { InvocationPolicyScope } from "./invocation-policy-scope.js";
|
|
16
17
|
import { authenticatedGrokHeaders, authenticatedHeaders, currentRoute, generationControlsFromSession, grokPromptCacheSessionId, promptCacheKey, promptCacheRetention, promptCacheSessionId, resolveGrokResponsesRouteConfig, resolveResponsesRouteConfig, routeFingerprint, } from "./route.js";
|
|
17
18
|
import { DEFAULT_MAX_REQUEST_IMAGE_BYTES, DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET, DEFAULT_REQUEST_IMAGE_MAX_BYTES, hydrateNativeImageReferences, resolveModelImageSupport, responseInputItems, serializeDshMessages, } from "./dsh-responses.js";
|
|
@@ -20,14 +21,14 @@ import { buildResponsesBody } from "./responses-request.js";
|
|
|
20
21
|
import { managedFailureChunk, streamResponsesRequest, } from "./responses-stream.js";
|
|
21
22
|
import { assertSupportedCheckpointMessage, checkpointStateForMessage, compactCheckpointId, createNativeCheckpointBlock, nativeCheckpointChunks, portableMessagesForCheckpoint, stateRouteCompatible, } from "./native-checkpoint.js";
|
|
22
23
|
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 { ALPHA_SCHEMA_FINGERPRINT, alphaRefRequiresStore, isAlphaContinuationUrl, isAlphaHttpUrl, ALPHA_SEARCH_OUTPUT, ALPHA_SEARCH_PARAMETERS, alphaSearchRetryOptions, buildAlphaSearchBody, normalizeAlphaSearchArgs, parseAlphaSearchResponse, remapAlphaResultRefs, renderAlphaSearchResult, runWithAlphaSessionLock, } from "./web-search-alpha.js";
|
|
25
|
+
import { recentAlphaInput } from "./web-search-alpha-history.js";
|
|
24
26
|
import { AlphaCapabilityStore, alphaCapabilityFingerprint, alphaCapabilityUsable, alphaSearchParametersFor, assertAlphaActionAllowed, } from "./web-search-capability.js";
|
|
25
27
|
import { AlphaRefStore } from "./web-search-ref-store.js";
|
|
26
28
|
import { ServiceMutex } from "./service-mutex.js";
|
|
27
29
|
import { GROK_NATIVE_SERVER_TOOL_TYPES, grokNativeSearchEnabled, grokVisibleFunctionTools, isGrokNativeServerToolItem, grokWireTools, restoreGrokNativeReplay, } from "./grok-native-search.js";
|
|
28
30
|
export const name = "lcx-codex";
|
|
29
31
|
export const inject = ["llm", "web", "sessions", "tools", "settings", "credentials", "attachments", "fs"];
|
|
30
|
-
const SETTINGS_NS = "lcx-codex";
|
|
31
32
|
const ADVANCED_HOSTED_TOOL = "websearch_gpt_advanced";
|
|
32
33
|
const ALPHA_TOOL = "websearch_alpha";
|
|
33
34
|
const hostedSearchRouteContext = new AsyncLocalStorage();
|
|
@@ -92,6 +93,13 @@ function defaultAlphaRefPath() {
|
|
|
92
93
|
return join(dshHome(), "storages", "lcx-codex", "web-alpha-refs.json");
|
|
93
94
|
}
|
|
94
95
|
export const Config = z.object({
|
|
96
|
+
enabled: z.boolean().default(false).volatile(),
|
|
97
|
+
webSearch: z.boolean().default(false).volatile(),
|
|
98
|
+
advancedHostedSearch: z.boolean().default(false).volatile(),
|
|
99
|
+
alphaSearch: z.boolean().default(false).volatile(),
|
|
100
|
+
grokNativeWebSearch: z.boolean().default(false).volatile(),
|
|
101
|
+
grokNativeXSearch: z.boolean().default(false).volatile(),
|
|
102
|
+
searchMediaPreview: z.boolean().default(false).volatile(),
|
|
95
103
|
supportsLongCacheRetention: z.boolean().default(false),
|
|
96
104
|
supportsExplicitPromptCacheMode: z.boolean().default(false),
|
|
97
105
|
alphaCapabilityPath: z.string().default(""),
|
|
@@ -114,15 +122,6 @@ export const Config = z.object({
|
|
|
114
122
|
assistantRetentionTokenReserve: z.number().default(24_000),
|
|
115
123
|
assistantRetentionPerMessageTokenCap: z.number().default(3_000),
|
|
116
124
|
});
|
|
117
|
-
const SettingsSchema = z.object({
|
|
118
|
-
enabled: z.boolean().default(false),
|
|
119
|
-
webSearch: z.boolean().default(false),
|
|
120
|
-
advancedHostedSearch: z.boolean().default(false),
|
|
121
|
-
alphaSearch: z.boolean().default(false),
|
|
122
|
-
grokNativeWebSearch: z.boolean().default(false),
|
|
123
|
-
grokNativeXSearch: z.boolean().default(false),
|
|
124
|
-
searchMediaPreview: z.boolean().default(false),
|
|
125
|
-
});
|
|
126
125
|
function normalizeConfig(input = {}) {
|
|
127
126
|
return {
|
|
128
127
|
supportsLongCacheRetention: input.supportsLongCacheRetention === true,
|
|
@@ -170,7 +169,7 @@ function activeAgentRoute(exec) {
|
|
|
170
169
|
};
|
|
171
170
|
}
|
|
172
171
|
function selectedAgentRoute(agent) {
|
|
173
|
-
const route =
|
|
172
|
+
const route = readSelectedAgentRouteState(agent);
|
|
174
173
|
return {
|
|
175
174
|
provider: stringValue(routeConfigValue(route.requestConfig, "provider") ??
|
|
176
175
|
routeConfigValue(route.options, "provider"), ""),
|
|
@@ -409,11 +408,13 @@ async function executeAlpha(ctx, routeConfig, capability, refStore, args, exec)
|
|
|
409
408
|
const continuedRef = alphaRefRequiresStore(normalized.action, normalized.refId)
|
|
410
409
|
? refStore.assertUsable(sessionId, routeFp, normalized.refId)
|
|
411
410
|
: undefined;
|
|
411
|
+
const rawRefId = continuedRef?.rawRefId ?? continuedRef?.refId;
|
|
412
|
+
const outbound = rawRefId ? { ...normalized, refId: rawRefId } : normalized;
|
|
412
413
|
const requestId = randomUUID();
|
|
413
414
|
const headers = await authenticatedHeaders(ctx, routeConfig, sessionId, requestId);
|
|
414
415
|
let response;
|
|
415
416
|
try {
|
|
416
|
-
response = await fetchJsonWithRetry(`${routeConfig.baseURL}/alpha/search`, buildAlphaSearchBody(
|
|
417
|
+
response = await fetchJsonWithRetry(`${routeConfig.baseURL}/alpha/search`, buildAlphaSearchBody(outbound, routeConfig.model, sessionId, true, routeConfig.alphaMaxOutputTokens, recentAlphaInput(sessionFromAgent(exec?.agent)?.deriveMessages() ?? [])), headers, exec?.signal, routeConfig.timeoutMs, alphaSearchRetryOptions(routeConfig.maxResponseBytes));
|
|
417
418
|
}
|
|
418
419
|
catch (error) {
|
|
419
420
|
const details = errorDetails(error);
|
|
@@ -427,22 +428,21 @@ async function executeAlpha(ctx, routeConfig, capability, refStore, args, exec)
|
|
|
427
428
|
capability: capability.classification,
|
|
428
429
|
requestId,
|
|
429
430
|
});
|
|
430
|
-
const
|
|
431
|
-
|
|
432
|
-
|
|
431
|
+
const echoed = {};
|
|
432
|
+
const refRecords = observedRefs.flatMap((observation) => {
|
|
433
|
+
if (observation.refId !== rawRefId || !continuedRef)
|
|
434
|
+
return [observation];
|
|
433
435
|
const observedArtifact = observation.provenance.artifactFingerprint;
|
|
434
436
|
const acceptedArtifact = continuedRef.provenance.artifactFingerprint;
|
|
435
|
-
if (observedArtifact && observedArtifact !== acceptedArtifact)
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
provenance: { ...continuedRef.provenance },
|
|
442
|
-
};
|
|
437
|
+
if ((observedArtifact && observedArtifact !== acceptedArtifact) ||
|
|
438
|
+
(observation.url && continuedRef.url && observation.url !== continuedRef.url))
|
|
439
|
+
throw webError("Alpha continuation changed its reference observation", "LCX_ALPHA_REF_COLLISION");
|
|
440
|
+
// Echoes retain their existing handle and cannot create a new observation.
|
|
441
|
+
echoed[observation.refId] = continuedRef.refId;
|
|
442
|
+
return [];
|
|
443
443
|
});
|
|
444
|
-
refStore.record(sessionId, routeFp, refRecords);
|
|
445
|
-
return result;
|
|
444
|
+
const handles = refStore.record(sessionId, routeFp, refRecords, true);
|
|
445
|
+
return remapAlphaResultRefs(result, { ...handles, ...echoed });
|
|
446
446
|
});
|
|
447
447
|
}
|
|
448
448
|
function createAlphaTool(ctx, state, getConfig, capabilityStore, refStore, advertisedRecord) {
|
|
@@ -521,10 +521,17 @@ function disposeAlphaToolForAgent(agent, registrations) {
|
|
|
521
521
|
registration.dispose();
|
|
522
522
|
registrations.delete(agent);
|
|
523
523
|
}
|
|
524
|
+
function isPersistedMessage(message) {
|
|
525
|
+
return typeof message.id === "string";
|
|
526
|
+
}
|
|
524
527
|
function isDshCompactionDirective(message) {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
+
// DSH compaction-basic appends a request-only user input in its
|
|
529
|
+
// purpose="compaction" call. Durable conversation messages have an id.
|
|
530
|
+
return (message.role === "user" &&
|
|
531
|
+
!("id" in message) &&
|
|
532
|
+
!("source" in message) &&
|
|
533
|
+
message.content.length === 1 &&
|
|
534
|
+
message.content[0]?.type === "text");
|
|
528
535
|
}
|
|
529
536
|
function stripCompactionDirective(messages) {
|
|
530
537
|
if (messages.length === 0)
|
|
@@ -578,13 +585,13 @@ async function serializeNativeAware(messages, route, routeConfig, ctx, options)
|
|
|
578
585
|
nativeModel = serialized.model ?? nativeModel;
|
|
579
586
|
grammarToolInputProperties =
|
|
580
587
|
serialized.grammarToolInputProperties ?? grammarToolInputProperties;
|
|
581
|
-
input.push(...restoreGrokNativeReplay(serialized.input, batch, options.grokNativeReplayRoute));
|
|
588
|
+
input.push(...restoreGrokNativeReplay(serialized.input, batch.filter(isPersistedMessage), options.grokNativeReplayRoute));
|
|
582
589
|
mergeMap(imageMap, serialized.imageMap);
|
|
583
590
|
};
|
|
584
591
|
for (const message of surfaceMessages ?? []) {
|
|
585
592
|
assertSupportedCheckpointMessage(message);
|
|
586
|
-
const state = session
|
|
587
|
-
? checkpointStateForMessage(session, message)
|
|
593
|
+
const state = session && isPersistedMessage(message) && compactCheckpointId(message)
|
|
594
|
+
? await checkpointStateForMessage(ctx, session, message)
|
|
588
595
|
: undefined;
|
|
589
596
|
if (state && session) {
|
|
590
597
|
const checkpointId = compactCheckpointId(message);
|
|
@@ -601,7 +608,7 @@ async function serializeNativeAware(messages, route, routeConfig, ctx, options)
|
|
|
601
608
|
mergeMap(imageMap, hydratedMap);
|
|
602
609
|
}
|
|
603
610
|
else {
|
|
604
|
-
const portable = portableMessagesForCheckpoint(session, checkpointId, { maxChars: routeConfig.portableReplayMaxChars });
|
|
611
|
+
const portable = await portableMessagesForCheckpoint(ctx, session, checkpointId, { maxChars: routeConfig.portableReplayMaxChars });
|
|
605
612
|
const serialized = await serializeDshMessages(portable, ctx, serializeOptions());
|
|
606
613
|
input.push(...serialized.input);
|
|
607
614
|
mergeMap(imageMap, serialized.imageMap);
|
|
@@ -634,10 +641,11 @@ function fallbackEligible(error, signal) {
|
|
|
634
641
|
return ["LCX_HTTP_RETRYABLE", "LCX_RETRY_EXHAUSTED"].includes(String(details.code ?? ""));
|
|
635
642
|
}
|
|
636
643
|
async function* remoteCompactionStream(options, routeConfig, ctx, next) {
|
|
637
|
-
const
|
|
644
|
+
const projected = projectToolUpdates(options.messages, options.tools, undefined, options.toolHistory);
|
|
645
|
+
const history = stripCompactionDirective(projected.messages);
|
|
638
646
|
const route = currentRoute(options, routeConfig);
|
|
639
647
|
try {
|
|
640
|
-
const prepared = await serializeNativeAware(history, route, routeConfig, ctx, { signal: options.signal, tools:
|
|
648
|
+
const prepared = await serializeNativeAware(history, route, routeConfig, ctx, { signal: options.signal, tools: projected.tools && [...projected.tools] });
|
|
641
649
|
const cacheSessionId = promptCacheSessionId(route, routeConfig, ctx);
|
|
642
650
|
const headers = await authenticatedHeaders(ctx, routeConfig, cacheSessionId, cacheSessionId === undefined ? null : route.sessionId);
|
|
643
651
|
const generation = generationControlsFromSession(sessionFor(ctx, route.sessionId), route);
|
|
@@ -646,7 +654,7 @@ async function* remoteCompactionStream(options, routeConfig, ctx, next) {
|
|
|
646
654
|
model: route.model,
|
|
647
655
|
modelDescriptor: prepared.model,
|
|
648
656
|
input: prepared.input,
|
|
649
|
-
tools: prepared.tools ??
|
|
657
|
+
tools: prepared.tools ?? (projected.tools && [...projected.tools]),
|
|
650
658
|
promptCacheKey: promptCacheKey(route, routeConfig, ctx),
|
|
651
659
|
promptCacheRetention: promptCacheRetention(routeConfig),
|
|
652
660
|
cacheRetention: routeConfig.cacheRetention,
|
|
@@ -663,7 +671,8 @@ async function* remoteCompactionStream(options, routeConfig, ctx, next) {
|
|
|
663
671
|
const session = sessionFor(ctx, route.sessionId);
|
|
664
672
|
if (session === undefined)
|
|
665
673
|
throw webError("Native compaction requires a live DSH session", "LCX_COMPACT_SESSION_UNAVAILABLE");
|
|
666
|
-
const block = createNativeCheckpointBlock({
|
|
674
|
+
const block = await createNativeCheckpointBlock({
|
|
675
|
+
ctx,
|
|
667
676
|
session,
|
|
668
677
|
route,
|
|
669
678
|
result,
|
|
@@ -681,8 +690,10 @@ async function* remoteCompactionStream(options, routeConfig, ctx, next) {
|
|
|
681
690
|
yield chunk;
|
|
682
691
|
}
|
|
683
692
|
catch (error) {
|
|
693
|
+
if (isRecord(error) && error.code === "LCX_SESSION_QUERY_UNAVAILABLE")
|
|
694
|
+
throw error;
|
|
684
695
|
const session = sessionFor(ctx, route.sessionId);
|
|
685
|
-
const hasExistingCheckpoint = messagesContainNativeCheckpoint(history, session);
|
|
696
|
+
const hasExistingCheckpoint = await messagesContainNativeCheckpoint(ctx, history, session);
|
|
686
697
|
const details = errorDetails(error);
|
|
687
698
|
const code = details.code ?? details.name ?? "ERROR";
|
|
688
699
|
const status = Number.isInteger(details.status)
|
|
@@ -718,16 +729,53 @@ function routedTargetForAgent(agent) {
|
|
|
718
729
|
return provider && model ? { provider, model } : undefined;
|
|
719
730
|
}
|
|
720
731
|
export function compactionPressureBand(totalTokens, contextWindow, policy) {
|
|
721
|
-
const
|
|
732
|
+
const pressureBudget = contextWindow - policy.outputReserve - policy.headroomTokens;
|
|
733
|
+
const ratioPercent = (totalTokens / pressureBudget) * 100;
|
|
734
|
+
const nativeThreshold = Math.floor(pressureBudget * policy.auto / 100);
|
|
735
|
+
const emergencyThreshold = Math.floor(pressureBudget * policy.emergency / 100);
|
|
722
736
|
return {
|
|
737
|
+
pressureBudget,
|
|
738
|
+
nativeThreshold,
|
|
739
|
+
emergencyThreshold,
|
|
723
740
|
ratioPercent,
|
|
724
|
-
band:
|
|
741
|
+
band: totalTokens < nativeThreshold
|
|
725
742
|
? "below"
|
|
726
|
-
:
|
|
743
|
+
: totalTokens < emergencyThreshold
|
|
727
744
|
? "native"
|
|
728
745
|
: "emergency",
|
|
729
746
|
};
|
|
730
747
|
}
|
|
748
|
+
function compactionHeadroomTokens(config, target) {
|
|
749
|
+
if (!isRecord(config))
|
|
750
|
+
return undefined;
|
|
751
|
+
const override = Array.isArray(config.modelPolicies)
|
|
752
|
+
? config.modelPolicies.find((policy) => isRecord(policy) && policy.provider === target.provider && policy.model === target.model)
|
|
753
|
+
: undefined;
|
|
754
|
+
const headroom = isRecord(override)
|
|
755
|
+
? override.headroomTokens ?? config.headroomTokens
|
|
756
|
+
: config.headroomTokens;
|
|
757
|
+
return Number.isSafeInteger(headroom) && headroom >= 0
|
|
758
|
+
? headroom
|
|
759
|
+
: undefined;
|
|
760
|
+
}
|
|
761
|
+
function compactionRetainTokens(config, target, messageBudgetTokens) {
|
|
762
|
+
if (!isRecord(config))
|
|
763
|
+
return undefined;
|
|
764
|
+
const override = Array.isArray(config.modelPolicies)
|
|
765
|
+
? config.modelPolicies.find((policy) => isRecord(policy) && policy.provider === target.provider && policy.model === target.model)
|
|
766
|
+
: undefined;
|
|
767
|
+
// Match compaction-basic's resolveRetention/resolveTargetPolicy precedence.
|
|
768
|
+
const retention = isRecord(override) &&
|
|
769
|
+
(override.retainTokens !== undefined || override.retainRatio !== undefined)
|
|
770
|
+
? override
|
|
771
|
+
: config;
|
|
772
|
+
if (retention.retainTokens !== undefined)
|
|
773
|
+
return typeof retention.retainTokens === "number" ? retention.retainTokens : undefined;
|
|
774
|
+
const ratio = retention.retainRatio === undefined ? 0.16 : retention.retainRatio;
|
|
775
|
+
return typeof ratio === "number"
|
|
776
|
+
? Math.floor(messageBudgetTokens * ratio)
|
|
777
|
+
: undefined;
|
|
778
|
+
}
|
|
731
779
|
function adjustedCompactionConfig(config, target, thresholdRatio) {
|
|
732
780
|
if (!isRecord(config))
|
|
733
781
|
return config;
|
|
@@ -778,15 +826,25 @@ function patchCompactionPressureService(compactionValue, state, getConfig, ctx,
|
|
|
778
826
|
if (!session || tokenMeter === undefined)
|
|
779
827
|
return callOriginal(activeSignal);
|
|
780
828
|
let contextWindow;
|
|
829
|
+
let defaultMaxTokens;
|
|
781
830
|
try {
|
|
782
|
-
|
|
831
|
+
const info = await ctx.llm.resolveModelInfo(target.provider, target.model, activeSignal);
|
|
832
|
+
contextWindow = info.context?.contextWindow;
|
|
833
|
+
defaultMaxTokens = info.defaultMaxTokens;
|
|
783
834
|
}
|
|
784
835
|
catch {
|
|
785
836
|
return callOriginal(activeSignal);
|
|
786
837
|
}
|
|
787
838
|
const totalTokens = tokenMeterTotal(tokenMeter, session);
|
|
788
|
-
|
|
839
|
+
const headroomTokens = compactionHeadroomTokens(compactionConfigState(candidate.compaction).original, target);
|
|
840
|
+
const outputReserve = session.requestHeader()?.config.maxTokens ?? defaultMaxTokens ?? 0;
|
|
841
|
+
if (typeof contextWindow !== "number" ||
|
|
842
|
+
!Number.isSafeInteger(contextWindow) ||
|
|
789
843
|
contextWindow <= 0 ||
|
|
844
|
+
!Number.isSafeInteger(outputReserve) ||
|
|
845
|
+
outputReserve < 0 ||
|
|
846
|
+
headroomTokens === undefined ||
|
|
847
|
+
contextWindow - outputReserve - headroomTokens <= 0 ||
|
|
790
848
|
totalTokens === undefined)
|
|
791
849
|
return callOriginal(activeSignal);
|
|
792
850
|
const auto = AUTO_COMPACTION_THRESHOLD_PERCENT;
|
|
@@ -794,14 +852,23 @@ function patchCompactionPressureService(compactionValue, state, getConfig, ctx,
|
|
|
794
852
|
const pressure = compactionPressureBand(totalTokens, contextWindow, {
|
|
795
853
|
auto,
|
|
796
854
|
emergency,
|
|
855
|
+
outputReserve,
|
|
856
|
+
headroomTokens,
|
|
797
857
|
});
|
|
798
858
|
if (pressure.band === "below")
|
|
799
|
-
return
|
|
859
|
+
return callOriginal(activeSignal);
|
|
860
|
+
const effectiveRetain = compactionRetainTokens(compactionConfigState(candidate.compaction).original, target, contextWindow - outputReserve);
|
|
861
|
+
const scopedRatio = pressure.nativeThreshold / contextWindow;
|
|
862
|
+
const scopedThreshold = Math.floor(Math.min(contextWindow * scopedRatio, pressure.pressureBudget));
|
|
863
|
+
if (effectiveRetain === undefined || effectiveRetain >= scopedThreshold) {
|
|
864
|
+
ctx.logger?.info?.("[lcx-codex] auto pressure: retaining upstream DSH threshold for the routed retention policy");
|
|
865
|
+
return callOriginal(activeSignal);
|
|
866
|
+
}
|
|
800
867
|
const nativeFirst = pressure.band === "native";
|
|
801
868
|
const prunerPatch = nativeFirst
|
|
802
869
|
? patchToolResultPruner(prunerState, () => ({ pruned: [], charsRemoved: 0 }))
|
|
803
870
|
: undefined;
|
|
804
|
-
const configPatch = patchCompactionConfig(compactionConfigState(candidate.compaction), (originalConfig) => adjustedCompactionConfig(originalConfig, target,
|
|
871
|
+
const configPatch = patchCompactionConfig(compactionConfigState(candidate.compaction), (originalConfig) => adjustedCompactionConfig(originalConfig, target, scopedRatio));
|
|
805
872
|
ctx.logger?.info?.(`[lcx-codex] auto pressure ${pressure.ratioPercent.toFixed(1)}%: ${nativeFirst ? "Native V2 first" : "emergency DSH prune allowed"} (native ${auto}%, emergency ${emergency}%)`);
|
|
806
873
|
try {
|
|
807
874
|
return await callOriginal(activeSignal);
|
|
@@ -835,8 +902,15 @@ async function restoreCompactionPressure(records) {
|
|
|
835
902
|
for (const record of entries)
|
|
836
903
|
record.policyScope.restore();
|
|
837
904
|
}
|
|
838
|
-
function messagesContainNativeCheckpoint(messages, session) {
|
|
839
|
-
|
|
905
|
+
async function messagesContainNativeCheckpoint(ctx, messages, session) {
|
|
906
|
+
if (!session)
|
|
907
|
+
return false;
|
|
908
|
+
for (const message of messages) {
|
|
909
|
+
if (isPersistedMessage(message) && compactCheckpointId(message) &&
|
|
910
|
+
await checkpointStateForMessage(ctx, session, message))
|
|
911
|
+
return true;
|
|
912
|
+
}
|
|
913
|
+
return false;
|
|
840
914
|
}
|
|
841
915
|
function inputHasNativeState(input) {
|
|
842
916
|
return input.some((item) => isRecord(item) && item.type === "compaction");
|
|
@@ -846,13 +920,14 @@ async function* managedResponsesStream(options, routeConfig, ctx) {
|
|
|
846
920
|
try {
|
|
847
921
|
if (options.stop !== undefined)
|
|
848
922
|
throw Object.assign(new Error("LCX Responses does not support GenerateOptions.stop"), { code: "LCX_RESPONSES_UNSUPPORTED_OPTION" });
|
|
849
|
-
const
|
|
923
|
+
const projected = projectToolUpdates(options.messages, options.tools, undefined, options.toolHistory);
|
|
924
|
+
const prepared = await serializeNativeAware(projected.messages, route, routeConfig, ctx, { signal: options.signal, tools: projected.tools && [...projected.tools] });
|
|
850
925
|
const cacheSessionId = promptCacheSessionId(route, routeConfig, ctx);
|
|
851
926
|
const headers = await authenticatedHeaders(ctx, routeConfig, cacheSessionId, cacheSessionId === undefined ? null : route.sessionId);
|
|
852
927
|
const body = buildResponsesBody({
|
|
853
928
|
model: prepared.model,
|
|
854
929
|
input: prepared.input,
|
|
855
|
-
tools: prepared.tools ??
|
|
930
|
+
tools: prepared.tools ?? (projected.tools && [...projected.tools]),
|
|
856
931
|
sessionId: cacheSessionId,
|
|
857
932
|
promptCacheKey: promptCacheKey(route, routeConfig, ctx),
|
|
858
933
|
promptCacheRetention: promptCacheRetention(routeConfig),
|
|
@@ -890,9 +965,10 @@ async function* managedGrokNativeSearchStream(options, routeConfig, nativeSearch
|
|
|
890
965
|
try {
|
|
891
966
|
if (options.stop !== undefined)
|
|
892
967
|
throw Object.assign(new Error("LCX Responses does not support GenerateOptions.stop"), { code: "LCX_RESPONSES_UNSUPPORTED_OPTION" });
|
|
893
|
-
const
|
|
968
|
+
const projected = projectToolUpdates(options.messages, options.tools, undefined, options.toolHistory);
|
|
969
|
+
const visibleTools = grokVisibleFunctionTools(projected.tools, nativeSearch);
|
|
894
970
|
const declaredToolNames = new Set(visibleTools?.map((tool) => tool.name) ?? []);
|
|
895
|
-
const prepared = await serializeNativeAware(
|
|
971
|
+
const prepared = await serializeNativeAware(projected.messages, route, routeConfig, ctx, {
|
|
896
972
|
signal: options.signal,
|
|
897
973
|
tools: visibleTools,
|
|
898
974
|
grokNativeReplayRoute: nativeReplayRoute,
|
|
@@ -961,7 +1037,7 @@ function isGptLifecycleTarget(options) {
|
|
|
961
1037
|
async function* unavailableManagedRouteStream(options) {
|
|
962
1038
|
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);
|
|
963
1039
|
}
|
|
964
|
-
function installInjected(ctx, configInput
|
|
1040
|
+
function installInjected(ctx, configInput) {
|
|
965
1041
|
installSearchUsage(ctx);
|
|
966
1042
|
const baseConfig = normalizeConfig(configInput);
|
|
967
1043
|
let runtimeConfig = baseConfig;
|
|
@@ -997,73 +1073,66 @@ function installInjected(ctx, configInput = {}) {
|
|
|
997
1073
|
}
|
|
998
1074
|
}, { global: true });
|
|
999
1075
|
ctx.on("session/event", (session, event) => {
|
|
1000
|
-
|
|
1076
|
+
recordAgentRouteEvent(session, event);
|
|
1077
|
+
// DSH 0.2 session/selectModel appends model/selection before the next
|
|
1078
|
+
// prompt assembly projects tools (dsh-api-session-controller/lib/index.js:320).
|
|
1079
|
+
if (event.type === "model/selection" || event.type === "request/header")
|
|
1001
1080
|
for (const agent of managedAgents)
|
|
1002
1081
|
if (agentUsesSession(agent, session))
|
|
1003
1082
|
syncAgentTools(agent);
|
|
1004
1083
|
}, { global: true });
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
};
|
|
1014
|
-
let source = () => settingsEntry;
|
|
1015
|
-
ctx.settings.installSection(ctx, SETTINGS_NS, SettingsSchema, settingsEntry, {
|
|
1016
|
-
setSource(current) {
|
|
1017
|
-
source = current;
|
|
1018
|
-
},
|
|
1019
|
-
onChange() {
|
|
1020
|
-
const value = source();
|
|
1021
|
-
state.enabled = value.enabled;
|
|
1022
|
-
state.webSearch = value.webSearch;
|
|
1023
|
-
state.advancedHostedSearch = value.advancedHostedSearch;
|
|
1024
|
-
state.alphaSearch = value.alphaSearch;
|
|
1025
|
-
state.grokNativeWebSearch = value.grokNativeWebSearch;
|
|
1026
|
-
state.grokNativeXSearch = value.grokNativeXSearch;
|
|
1027
|
-
runtimeConfig = baseConfig;
|
|
1028
|
-
refreshTools();
|
|
1029
|
-
},
|
|
1030
|
-
});
|
|
1031
|
-
try {
|
|
1032
|
-
const value = source();
|
|
1033
|
-
Object.assign(state, {
|
|
1034
|
-
enabled: Boolean(value.enabled),
|
|
1035
|
-
webSearch: Boolean(value.webSearch),
|
|
1036
|
-
advancedHostedSearch: Boolean(value.advancedHostedSearch),
|
|
1037
|
-
alphaSearch: Boolean(value.alphaSearch),
|
|
1038
|
-
grokNativeWebSearch: Boolean(value.grokNativeWebSearch),
|
|
1039
|
-
grokNativeXSearch: Boolean(value.grokNativeXSearch),
|
|
1040
|
-
});
|
|
1084
|
+
ctx.effect(() => ctx.settings.configure({ auto: false }));
|
|
1085
|
+
const syncSettings = () => {
|
|
1086
|
+
state.enabled = configInput.enabled.get();
|
|
1087
|
+
state.webSearch = configInput.webSearch.get();
|
|
1088
|
+
state.advancedHostedSearch = configInput.advancedHostedSearch.get();
|
|
1089
|
+
state.alphaSearch = configInput.alphaSearch.get();
|
|
1090
|
+
state.grokNativeWebSearch = configInput.grokNativeWebSearch.get();
|
|
1091
|
+
state.grokNativeXSearch = configInput.grokNativeXSearch.get();
|
|
1041
1092
|
runtimeConfig = baseConfig;
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1093
|
+
refreshTools();
|
|
1094
|
+
};
|
|
1095
|
+
syncSettings();
|
|
1096
|
+
ctx.on("loader/volatile-update", syncSettings);
|
|
1097
|
+
ctx.on("settings/document-updated", refreshTools);
|
|
1045
1098
|
ctx.inject(["compaction"], (compactionCtx) => {
|
|
1046
1099
|
patchCompactionPressureService(resolveContextService(compactionCtx, "compaction"), state, () => runtimeConfig, ctx, compactionPatchRecords);
|
|
1047
1100
|
});
|
|
1048
|
-
|
|
1101
|
+
/**
|
|
1102
|
+
* LCX instrumentation is optional capability, never a creation precondition.
|
|
1103
|
+
* DSH 0.1.6 awaits `agent/created` serially, so an escaping failure would make
|
|
1104
|
+
* an otherwise valid Agent uncreatable; `agent/status` stays a contained emit.
|
|
1105
|
+
* Both edges therefore fail closed locally: the Agent runs uninstrumented and
|
|
1106
|
+
* the reason is logged, rather than propagating into the host lifecycle.
|
|
1107
|
+
*/
|
|
1108
|
+
const instrumentAgent = (agent, edge) => {
|
|
1109
|
+
try {
|
|
1110
|
+
managedAgents.add(agent);
|
|
1111
|
+
syncAgentTools(agent);
|
|
1112
|
+
const installed = patchCompactionPressureForAgent(agent, state, () => runtimeConfig, ctx, compactionPatchRecords);
|
|
1113
|
+
if (installed)
|
|
1114
|
+
ctx.logger?.info?.("[lcx-codex] pressure coordination installed through AgentPresets service resolver");
|
|
1115
|
+
}
|
|
1116
|
+
catch (error) {
|
|
1117
|
+
ctx.logger?.warn?.(`[lcx-codex] agent instrumentation skipped on ${edge}: ${String(error)}`);
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1120
|
+
/** DSH 0.1.6 lifecycle source, recorded for diagnostics only. */
|
|
1121
|
+
const startSource = (value) => typeof value === "string" && /^[a-z]+$/u.test(value) ? value : "unknown";
|
|
1122
|
+
ctx.on("agent/created", (payload) => {
|
|
1123
|
+
const agent = payload?.agent;
|
|
1049
1124
|
if (agent === null || typeof agent !== "object")
|
|
1050
1125
|
return;
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
if (installed)
|
|
1055
|
-
ctx.logger?.info?.("[lcx-codex] pressure coordination installed through AgentPresets service resolver");
|
|
1126
|
+
// `source` is startup | resume | clear | compact. Recorded, not branched on:
|
|
1127
|
+
// no runtime evidence yet that a source needs different instrumentation.
|
|
1128
|
+
instrumentAgent(agent, `agent/created(${startSource(payload?.source)})`);
|
|
1056
1129
|
}, { global: true });
|
|
1057
1130
|
ctx.on("agent/status", ({ agent, status }) => {
|
|
1058
1131
|
if (status !== "running" ||
|
|
1059
1132
|
agent === null ||
|
|
1060
1133
|
typeof agent !== "object")
|
|
1061
1134
|
return;
|
|
1062
|
-
|
|
1063
|
-
syncAgentTools(agent);
|
|
1064
|
-
const installed = patchCompactionPressureForAgent(agent, state, () => runtimeConfig, ctx, compactionPatchRecords);
|
|
1065
|
-
if (installed)
|
|
1066
|
-
ctx.logger?.info?.("[lcx-codex] pressure coordination installed through AgentPresets service resolver");
|
|
1135
|
+
instrumentAgent(agent, "agent/status(running)");
|
|
1067
1136
|
}, { global: true });
|
|
1068
1137
|
ctx.on("llm/stream", (options, next) => {
|
|
1069
1138
|
if (options.purpose === "session-title")
|
|
@@ -1098,7 +1167,7 @@ function installInjected(ctx, configInput = {}) {
|
|
|
1098
1167
|
await restoreCompactionPressure(compactionPatchRecords);
|
|
1099
1168
|
}, "lcx-codex cleanup");
|
|
1100
1169
|
}
|
|
1101
|
-
export function apply(ctx, configInput
|
|
1170
|
+
export function apply(ctx, configInput) {
|
|
1102
1171
|
return installInjected(ctx, configInput);
|
|
1103
1172
|
}
|
|
1104
1173
|
apply.inject = inject;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
import { abortError } from "./abort-error.js";
|
|
2
3
|
const activePolicy = new AsyncLocalStorage();
|
|
3
4
|
const projections = new WeakMap();
|
|
4
5
|
function scopedValue(values, target, key) {
|
|
@@ -118,11 +119,6 @@ function restoreProjection(record) {
|
|
|
118
119
|
}
|
|
119
120
|
catch { }
|
|
120
121
|
}
|
|
121
|
-
function operationError(signal) {
|
|
122
|
-
if (signal?.reason instanceof Error)
|
|
123
|
-
return signal.reason;
|
|
124
|
-
return new DOMException("The operation was aborted", "AbortError");
|
|
125
|
-
}
|
|
126
122
|
export class InvocationPolicyScope {
|
|
127
123
|
records = new Set();
|
|
128
124
|
queue = [];
|
|
@@ -147,7 +143,7 @@ export class InvocationPolicyScope {
|
|
|
147
143
|
if (this.closed)
|
|
148
144
|
return Promise.reject(this.closeReason ?? new Error("invocation policy scope closed"));
|
|
149
145
|
if (signal?.aborted)
|
|
150
|
-
return Promise.reject(
|
|
146
|
+
return Promise.reject(abortError(signal));
|
|
151
147
|
if (this.queue.length === 0 &&
|
|
152
148
|
!this.exclusiveActive &&
|
|
153
149
|
(mode === "shared" || this.sharedActive === 0)) {
|
|
@@ -165,7 +161,7 @@ export class InvocationPolicyScope {
|
|
|
165
161
|
if (index >= 0)
|
|
166
162
|
this.queue.splice(index, 1);
|
|
167
163
|
signal.removeEventListener("abort", onAbort);
|
|
168
|
-
reject(
|
|
164
|
+
reject(abortError(signal));
|
|
169
165
|
this.flushQueue();
|
|
170
166
|
};
|
|
171
167
|
waiter.onAbort = onAbort;
|
|
@@ -193,7 +189,7 @@ export class InvocationPolicyScope {
|
|
|
193
189
|
this.queue.shift();
|
|
194
190
|
if (waiter.onAbort)
|
|
195
191
|
waiter.signal.removeEventListener("abort", waiter.onAbort);
|
|
196
|
-
waiter.reject(
|
|
192
|
+
waiter.reject(abortError(waiter.signal));
|
|
197
193
|
continue;
|
|
198
194
|
}
|
|
199
195
|
if (waiter.mode === "exclusive") {
|