dsh-lcx-codex 0.4.2 → 0.4.3-pre.13
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 +75 -224
- package/THIRD_PARTY_NOTICES.md +64 -0
- package/cordis.patch.yml +3 -20
- package/lib/auxiliary-usage.js +63 -0
- package/lib/client.js +1398 -167
- package/lib/compact-v2.js +218 -199
- package/lib/dsh-compat.js +294 -100
- package/lib/dsh-responses.js +512 -277
- package/lib/grok-native-search.js +391 -0
- package/lib/index.js +1066 -758
- package/lib/invocation-policy-scope.js +261 -0
- package/lib/json-store.js +57 -31
- package/lib/native-checkpoint.js +520 -194
- package/lib/pi-responses-runtime.js +1571 -0
- package/lib/responses-request.js +109 -121
- package/lib/responses-stream.js +1280 -447
- package/lib/route.js +425 -369
- package/lib/search-accounting.js +86 -0
- package/lib/search-usage.js +86 -0
- package/lib/service-mutex.js +73 -64
- package/lib/token-budget.js +176 -108
- package/lib/transport.js +308 -68
- package/lib/types/client/index.d.ts +18 -0
- package/lib/types/client/search-media.d.ts +16 -0
- package/lib/types/index.d.ts +83 -0
- package/lib/web-run-output.js +189 -18
- package/lib/web-search-alpha.js +1067 -163
- package/lib/web-search-capability.js +80 -65
- package/lib/web-search-hosted.js +321 -33
- package/lib/web-search-ref-store.js +145 -60
- package/package.json +112 -32
- package/ARCHITECTURE.md +0 -117
- package/CHANGELOG.md +0 -224
- package/README_EN.md +0 -277
- package/assets/dsh-lcx-codex-banner.jpg +0 -0
- package/lib/legacy-v3.js +0 -20
- package/lib/responses-replay.js +0 -68
- package/scripts/probe-alpha.mjs +0 -43
- package/scripts/validate-dsh-schema.mjs +0 -31
package/lib/index.js
CHANGED
|
@@ -1,798 +1,1106 @@
|
|
|
1
|
-
import z from
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const SETTINGS_NS = settingsNamespace('lcx-codex')
|
|
95
|
-
const ADVANCED_HOSTED_TOOL = 'websearch_gpt_advanced'
|
|
96
|
-
const ALPHA_TOOL = 'websearch_alpha'
|
|
97
|
-
const COMPACTION_DIRECTIVE = 'You are now acting as a compaction engine'
|
|
98
|
-
const hostedSearchRouteContext = new AsyncLocalStorage()
|
|
99
|
-
|
|
100
|
-
function dshHome() { return process.env.DSH_HOME ?? join(homedir(), '.dsh') }
|
|
101
|
-
function defaultLegacyCheckpointPath() { return join(dshHome(), 'storages', 'lcx-codex', 'checkpoints-v3.json') }
|
|
102
|
-
function defaultAlphaCapabilityPath() { return join(dshHome(), 'storages', 'lcx-codex', 'web-alpha-capabilities.json') }
|
|
103
|
-
function defaultAlphaRefPath() { return join(dshHome(), 'storages', 'lcx-codex', 'web-alpha-refs.json') }
|
|
104
|
-
|
|
1
|
+
import z from "@deepseek-ai/schemastery";
|
|
2
|
+
import { recordHostedUsage, withAuxiliaryUsage } from "./auxiliary-usage.js";
|
|
3
|
+
import { installSearchUsage } from "./search-usage.js";
|
|
4
|
+
import { WEB_SEARCH_MAX_QUERIES, applyWebSearchTool, } from "@deepseek-ai/dsh-tool-web";
|
|
5
|
+
import "@deepseek-ai/dsh-agent";
|
|
6
|
+
import "@deepseek-ai/dsh-tools";
|
|
7
|
+
import "@deepseek-ai/dsh-web";
|
|
8
|
+
import { randomUUID } from "node:crypto";
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
12
|
+
import { getSupportedThinkingLevels } from "./pi-responses-runtime.js";
|
|
13
|
+
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 { InvocationPolicyScope } from "./invocation-policy-scope.js";
|
|
16
|
+
import { authenticatedGrokHeaders, authenticatedHeaders, currentRoute, generationControlsFromSession, grokPromptCacheSessionId, promptCacheKey, promptCacheRetention, promptCacheSessionId, resolveGrokResponsesRouteConfig, resolveResponsesRouteConfig, routeFingerprint, } from "./route.js";
|
|
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";
|
|
18
|
+
import { mergeFeatureHeader, requestNativeCompaction } from "./compact-v2.js";
|
|
19
|
+
import { buildResponsesBody } from "./responses-request.js";
|
|
20
|
+
import { managedFailureChunk, streamResponsesRequest, } from "./responses-stream.js";
|
|
21
|
+
import { assertSupportedCheckpointMessage, checkpointStateForMessage, compactCheckpointId, createNativeCheckpointBlock, nativeCheckpointChunks, portableMessagesForCheckpoint, stateRouteCompatible, } from "./native-checkpoint.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";
|
|
25
|
+
import { AlphaRefStore } from "./web-search-ref-store.js";
|
|
26
|
+
import { ServiceMutex } from "./service-mutex.js";
|
|
27
|
+
import { GROK_NATIVE_SERVER_TOOL_TYPES, grokNativeSearchEnabled, grokVisibleFunctionTools, isGrokNativeServerToolItem, grokWireTools, restoreGrokNativeReplay, } from "./grok-native-search.js";
|
|
28
|
+
export const name = "lcx-codex";
|
|
29
|
+
export const inject = ["llm", "web", "sessions", "tools", "settings", "credentials", "attachments", "fs"];
|
|
30
|
+
const SETTINGS_NS = "lcx-codex";
|
|
31
|
+
const ADVANCED_HOSTED_TOOL = "websearch_gpt_advanced";
|
|
32
|
+
const ALPHA_TOOL = "websearch_alpha";
|
|
33
|
+
const hostedSearchRouteContext = new AsyncLocalStorage();
|
|
34
|
+
const WEB_SEARCH_TIMEOUT_MS = 240_000;
|
|
35
|
+
const AUTO_COMPACTION_THRESHOLD_PERCENT = 90;
|
|
36
|
+
const EMERGENCY_PRUNE_THRESHOLD_PERCENT = 95;
|
|
37
|
+
function positiveInteger(value, fallback, maximum) {
|
|
38
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0)
|
|
39
|
+
return fallback;
|
|
40
|
+
return maximum === undefined ? value : Math.min(value, maximum);
|
|
41
|
+
}
|
|
42
|
+
function stringValue(value, fallback) {
|
|
43
|
+
return typeof value === "string" && value.trim() ? value : fallback;
|
|
44
|
+
}
|
|
45
|
+
function routeWithPolicies(route, config) {
|
|
46
|
+
return {
|
|
47
|
+
...route,
|
|
48
|
+
alphaProfile: config.alphaProfile,
|
|
49
|
+
alphaGroup: config.alphaGroup,
|
|
50
|
+
alphaMaxOutputTokens: config.alphaMaxOutputTokens,
|
|
51
|
+
assistantRetentionPerMessageTokenCap: config.assistantRetentionPerMessageTokenCap,
|
|
52
|
+
assistantRetentionTokenReserve: config.assistantRetentionTokenReserve,
|
|
53
|
+
maxRequestImageBytes: route.maxRequestImageBytes ?? config.maxRequestImageBytes,
|
|
54
|
+
maxResponseBytes: config.maxResponseBytes,
|
|
55
|
+
nativeRetentionTokenBudget: config.nativeRetentionTokenBudget,
|
|
56
|
+
portableReplayMaxChars: config.portableReplayMaxChars,
|
|
57
|
+
requestImageMaxBytes: route.requestImageMaxBytes ?? config.requestImageMaxBytes,
|
|
58
|
+
requestImagePixelBudget: route.requestImagePixelBudget ?? config.requestImagePixelBudget,
|
|
59
|
+
webMaxResults: config.webMaxResults,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function grokReplayRoute(route, config) {
|
|
63
|
+
return {
|
|
64
|
+
...route,
|
|
65
|
+
apiKeyEnv: config.apiKeyEnv,
|
|
66
|
+
headers: config.headers,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function isRecord(value) {
|
|
70
|
+
return value !== null && typeof value === "object";
|
|
71
|
+
}
|
|
72
|
+
function asAbortSignal(value) {
|
|
73
|
+
return value instanceof AbortSignal ? value : undefined;
|
|
74
|
+
}
|
|
75
|
+
function errorDetails(value) {
|
|
76
|
+
return isRecord(value)
|
|
77
|
+
? {
|
|
78
|
+
name: value.name,
|
|
79
|
+
code: value.code,
|
|
80
|
+
status: value.status,
|
|
81
|
+
message: value.message,
|
|
82
|
+
}
|
|
83
|
+
: {};
|
|
84
|
+
}
|
|
85
|
+
function dshHome() {
|
|
86
|
+
return process.env.DSH_HOME ?? join(homedir(), ".dsh");
|
|
87
|
+
}
|
|
88
|
+
function defaultAlphaCapabilityPath() {
|
|
89
|
+
return join(dshHome(), "storages", "lcx-codex", "web-alpha-capabilities.json");
|
|
90
|
+
}
|
|
91
|
+
function defaultAlphaRefPath() {
|
|
92
|
+
return join(dshHome(), "storages", "lcx-codex", "web-alpha-refs.json");
|
|
93
|
+
}
|
|
105
94
|
export const Config = z.object({
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
assistantRetentionTokenReserve: z.number().default(24_000),
|
|
129
|
-
assistantRetentionPerMessageTokenCap: z.number().default(3_000),
|
|
130
|
-
webSearchTimeoutMs: z.number().default(240_000),
|
|
131
|
-
autoCompactionThresholdPercent: z.number().default(90),
|
|
132
|
-
emergencyPruneThresholdPercent: z.number().default(95),
|
|
133
|
-
})
|
|
134
|
-
|
|
95
|
+
supportsLongCacheRetention: z.boolean().default(false),
|
|
96
|
+
supportsExplicitPromptCacheMode: z.boolean().default(false),
|
|
97
|
+
alphaCapabilityPath: z.string().default(""),
|
|
98
|
+
alphaRefPath: z.string().default(""),
|
|
99
|
+
alphaProfile: z.string().default(""),
|
|
100
|
+
alphaGroup: z.string().default(""),
|
|
101
|
+
alphaMaxOutputTokens: z.number().default(2500),
|
|
102
|
+
webSearchProvider: z.string().default("lcx-responses"),
|
|
103
|
+
webMaxResults: z.number().default(8),
|
|
104
|
+
timeoutMs: z.number().default(300000),
|
|
105
|
+
maxResponseBytes: z.number().default(8 * 1024 * 1024),
|
|
106
|
+
maxAttempts: z.number().default(3),
|
|
107
|
+
maxRequestImageBytes: z.number().default(DEFAULT_MAX_REQUEST_IMAGE_BYTES),
|
|
108
|
+
requestImagePixelBudget: z
|
|
109
|
+
.number()
|
|
110
|
+
.default(DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET),
|
|
111
|
+
requestImageMaxBytes: z.number().default(DEFAULT_REQUEST_IMAGE_MAX_BYTES),
|
|
112
|
+
portableReplayMaxChars: z.number().default(80_000),
|
|
113
|
+
nativeRetentionTokenBudget: z.number().default(64_000),
|
|
114
|
+
assistantRetentionTokenReserve: z.number().default(24_000),
|
|
115
|
+
assistantRetentionPerMessageTokenCap: z.number().default(3_000),
|
|
116
|
+
});
|
|
135
117
|
const SettingsSchema = z.object({
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
autoCompactionThresholdPercent: z.number().default(90),
|
|
145
|
-
emergencyPruneThresholdPercent: z.number().default(95),
|
|
146
|
-
provider: z.string().default('lcx'),
|
|
147
|
-
baseURL: z.string().default('https://api.lcxbot.com/v1'),
|
|
148
|
-
apiKeyEnv: z.string().default('LCX_API_KEY'),
|
|
149
|
-
model: z.string().default('gpt-5.6-sol'),
|
|
150
|
-
})
|
|
151
|
-
|
|
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
|
+
});
|
|
152
126
|
function normalizeConfig(input = {}) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
webSearchTimeoutMs: Number.isSafeInteger(input.webSearchTimeoutMs) && input.webSearchTimeoutMs >= 30_000 ? Math.min(input.webSearchTimeoutMs, 600_000) : 240_000,
|
|
180
|
-
autoCompactionThresholdPercent: Number.isFinite(input.autoCompactionThresholdPercent) ? Math.min(95, Math.max(85, Number(input.autoCompactionThresholdPercent))) : 90,
|
|
181
|
-
emergencyPruneThresholdPercent: Number.isFinite(input.emergencyPruneThresholdPercent) ? Math.min(99, Math.max(90, Number(input.emergencyPruneThresholdPercent))) : 95,
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
127
|
+
return {
|
|
128
|
+
supportsLongCacheRetention: input.supportsLongCacheRetention === true,
|
|
129
|
+
supportsExplicitPromptCacheMode: input.supportsExplicitPromptCacheMode === true,
|
|
130
|
+
alphaCapabilityPath: stringValue(input.alphaCapabilityPath, defaultAlphaCapabilityPath()),
|
|
131
|
+
alphaRefPath: stringValue(input.alphaRefPath, defaultAlphaRefPath()),
|
|
132
|
+
alphaProfile: String(input.alphaProfile ?? ""),
|
|
133
|
+
alphaGroup: String(input.alphaGroup ?? ""),
|
|
134
|
+
alphaMaxOutputTokens: positiveInteger(input.alphaMaxOutputTokens, 2500, 32_000),
|
|
135
|
+
webSearchProvider: stringValue(input.webSearchProvider, "lcx-responses"),
|
|
136
|
+
webMaxResults: positiveInteger(input.webMaxResults, 8),
|
|
137
|
+
timeoutMs: positiveInteger(input.timeoutMs, 300000),
|
|
138
|
+
maxResponseBytes: positiveInteger(input.maxResponseBytes, 8 * 1024 * 1024),
|
|
139
|
+
maxAttempts: positiveInteger(input.maxAttempts, 3, 6),
|
|
140
|
+
maxRequestImageBytes: positiveInteger(input.maxRequestImageBytes, DEFAULT_MAX_REQUEST_IMAGE_BYTES),
|
|
141
|
+
requestImagePixelBudget: positiveInteger(input.requestImagePixelBudget, DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET),
|
|
142
|
+
requestImageMaxBytes: positiveInteger(input.requestImageMaxBytes, DEFAULT_REQUEST_IMAGE_MAX_BYTES),
|
|
143
|
+
portableReplayMaxChars: positiveInteger(input.portableReplayMaxChars, 80_000),
|
|
144
|
+
nativeRetentionTokenBudget: positiveInteger(input.nativeRetentionTokenBudget, 64_000),
|
|
145
|
+
assistantRetentionTokenReserve: typeof input.assistantRetentionTokenReserve === "number" &&
|
|
146
|
+
Number.isSafeInteger(input.assistantRetentionTokenReserve) &&
|
|
147
|
+
input.assistantRetentionTokenReserve >= 0
|
|
148
|
+
? input.assistantRetentionTokenReserve
|
|
149
|
+
: 24_000,
|
|
150
|
+
assistantRetentionPerMessageTokenCap: positiveInteger(input.assistantRetentionPerMessageTokenCap, 3_000),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
185
153
|
function webError(message, code, cause) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
154
|
+
const error = new Error(message, cause === undefined ? undefined : { cause });
|
|
155
|
+
error.name = "WebError";
|
|
156
|
+
error.code = code;
|
|
157
|
+
return error;
|
|
158
|
+
}
|
|
159
|
+
function routeConfigValue(value, name) {
|
|
160
|
+
return isRecord(value) ? value[name] : undefined;
|
|
161
|
+
}
|
|
162
|
+
function activeAgentRoute(exec) {
|
|
163
|
+
const route = readAgentRouteState(exec.agent);
|
|
164
|
+
return {
|
|
165
|
+
provider: stringValue(routeConfigValue(route.requestConfig, "provider") ??
|
|
166
|
+
routeConfigValue(route.options, "provider"), ""),
|
|
167
|
+
model: stringValue(routeConfigValue(route.requestConfig, "model") ??
|
|
168
|
+
routeConfigValue(route.options, "model"), ""),
|
|
169
|
+
sessionId: route.sessionId,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function selectedAgentRoute(agent) {
|
|
173
|
+
const route = readAgentRouteState(agent);
|
|
174
|
+
return {
|
|
175
|
+
provider: stringValue(routeConfigValue(route.requestConfig, "provider") ??
|
|
176
|
+
routeConfigValue(route.options, "provider"), ""),
|
|
177
|
+
model: stringValue(routeConfigValue(route.requestConfig, "model") ??
|
|
178
|
+
routeConfigValue(route.options, "model"), ""),
|
|
179
|
+
sessionId: route.sessionId,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
208
182
|
function requestImageOptions(routeConfig, imageSupport, signal, imageMap, extra = {}) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
183
|
+
return {
|
|
184
|
+
imageSupport,
|
|
185
|
+
signal,
|
|
186
|
+
imageMap,
|
|
187
|
+
maxRequestImageBytes: routeConfig.maxRequestImageBytes,
|
|
188
|
+
requestImagePixelBudget: routeConfig.requestImagePixelBudget,
|
|
189
|
+
requestImageMaxBytes: routeConfig.requestImageMaxBytes,
|
|
190
|
+
...extra,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
async function executeHostedSearch(ctx, routeConfig, args, signal, sessionId = "") {
|
|
194
|
+
const normalized = normalizeHostedSearchArgs(args);
|
|
195
|
+
const requestId = randomUUID();
|
|
196
|
+
const route = currentRoute({ provider: routeConfig.provider, model: routeConfig.model, sessionId }, routeConfig);
|
|
197
|
+
const headers = await authenticatedHeaders(ctx, routeConfig, sessionId, requestId);
|
|
198
|
+
const searchCacheKey = sessionId
|
|
199
|
+
? `dsh-lcx-search:${routeFingerprint(route)}`
|
|
200
|
+
: undefined;
|
|
201
|
+
const body = buildHostedSearchBody(normalized, routeConfig.model, {
|
|
202
|
+
promptCacheKey: searchCacheKey,
|
|
203
|
+
});
|
|
204
|
+
const response = await fetchJsonWithRetry(`${routeConfig.baseURL}/responses`, body, headers, signal, routeConfig.timeoutMs, {
|
|
205
|
+
maxAttempts: routeConfig.maxAttempts,
|
|
206
|
+
maxResponseBytes: routeConfig.maxResponseBytes,
|
|
207
|
+
});
|
|
208
|
+
recordHostedUsage(response, requestId, routeConfig.provider, routeConfig.model);
|
|
209
|
+
return parseHostedSearchResponse(response, requestId, routeConfig.webMaxResults);
|
|
210
|
+
}
|
|
229
211
|
class LcxResponsesSearchProvider {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const requested = active ?? { provider: config.provider, model: config.model, sessionId: '' }
|
|
240
|
-
let route = resolveResponsesRouteConfig(this.ctx, requested, config)
|
|
241
|
-
let source = active ? 'active-agent' : 'fallback'
|
|
242
|
-
if (!route && active) {
|
|
243
|
-
route = resolveResponsesRouteConfig(this.ctx, { provider: config.provider, model: config.model }, config)
|
|
244
|
-
source = 'fallback'
|
|
212
|
+
ctx;
|
|
213
|
+
getConfig;
|
|
214
|
+
enabled;
|
|
215
|
+
id;
|
|
216
|
+
constructor(ctx, getConfig, enabled) {
|
|
217
|
+
this.ctx = ctx;
|
|
218
|
+
this.getConfig = getConfig;
|
|
219
|
+
this.enabled = enabled;
|
|
220
|
+
this.id = getConfig().webSearchProvider;
|
|
245
221
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
-
|
|
222
|
+
available() {
|
|
223
|
+
const active = hostedSearchRouteContext.getStore();
|
|
224
|
+
if (!active)
|
|
225
|
+
return false;
|
|
226
|
+
const config = this.getConfig();
|
|
227
|
+
const route = resolveResponsesRouteConfig(this.ctx, active, config);
|
|
228
|
+
return this.enabled() && Boolean(route);
|
|
229
|
+
}
|
|
230
|
+
async search(request, signal) {
|
|
231
|
+
const config = this.getConfig();
|
|
232
|
+
const active = hostedSearchRouteContext.getStore();
|
|
233
|
+
const route = active && resolveResponsesRouteConfig(this.ctx, active, config);
|
|
234
|
+
const routeConfig = route && routeWithPolicies(route, config);
|
|
235
|
+
if (!routeConfig)
|
|
236
|
+
throw webError("LCX Hosted Search requires a configured GPT openai-responses route", "LCX_WEB_ROUTE_UNAVAILABLE");
|
|
237
|
+
const sessionId = active?.sessionId ?? "";
|
|
238
|
+
this.ctx.logger?.info?.(`[lcx-codex] web_search route: ${routeConfig.provider}/${routeConfig.model} (active-agent)`);
|
|
239
|
+
const result = await executeHostedSearch(this.ctx, routeConfig, { query: request.query }, signal, sessionId);
|
|
240
|
+
const max = request.maxResults ?? routeConfig.webMaxResults;
|
|
241
|
+
return {
|
|
242
|
+
content: result.content || undefined,
|
|
243
|
+
sources: result.sources.slice(0, max),
|
|
244
|
+
truncated: result.truncated || result.sources.length > max,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function createScopedGptWebSearchTool(ctx, state, getConfig, provider, fetchEnabled) {
|
|
249
|
+
let definition;
|
|
250
|
+
const composition = {
|
|
251
|
+
web: {
|
|
252
|
+
search: (request, signal) => provider.search(request, signal),
|
|
253
|
+
},
|
|
254
|
+
tools: {
|
|
255
|
+
register(candidate) {
|
|
256
|
+
definition = candidate;
|
|
257
|
+
return () => { };
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
systemPrompt: {
|
|
261
|
+
getSectionOrder: () => 0,
|
|
262
|
+
section: () => () => { },
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
applyWebSearchTool(composition, getConfig().webMaxResults, WEB_SEARCH_MAX_QUERIES, WEB_SEARCH_TIMEOUT_MS, fetchEnabled);
|
|
266
|
+
if (!definition)
|
|
267
|
+
throw new Error("DSH web_search composition did not register a tool");
|
|
268
|
+
const execute = definition.execute.bind(definition);
|
|
269
|
+
const output = definition.output;
|
|
270
|
+
return withAuxiliaryUsage({
|
|
271
|
+
...definition,
|
|
272
|
+
output: {
|
|
273
|
+
...output,
|
|
274
|
+
presentationMeta(args, value) {
|
|
275
|
+
return hostedMediaPresentationMeta(value, "web_search", output.presentationMeta?.(args, value));
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
async execute(args, exec) {
|
|
279
|
+
if (!state.enabled || !state.webSearch)
|
|
280
|
+
throw webError("web_search GPT Hosted Search is disabled", "LCX_WEB_DISABLED");
|
|
281
|
+
const active = activeAgentRoute(exec);
|
|
282
|
+
const route = resolveResponsesRouteConfig(ctx, active, getConfig());
|
|
283
|
+
if (!route)
|
|
284
|
+
throw webError("GPT Hosted Search requires the active GPT openai-responses route", "LCX_WEB_ROUTE_UNAVAILABLE");
|
|
285
|
+
return hostedSearchRouteContext.run(active, () => execute(args, exec));
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
}
|
|
255
289
|
function createAdvancedHostedTool(ctx, state, getConfig) {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
290
|
+
return withAuxiliaryUsage({
|
|
291
|
+
name: ADVANCED_HOSTED_TOOL,
|
|
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.",
|
|
293
|
+
parameters: HOSTED_SEARCH_PARAMETERS,
|
|
294
|
+
output: {
|
|
295
|
+
schema: HOSTED_SEARCH_OUTPUT,
|
|
296
|
+
render: (_args, value) => renderHostedSearchResult(value),
|
|
297
|
+
presentationMeta: (_args, value) => hostedMediaPresentationMeta(value, ADVANCED_HOSTED_TOOL),
|
|
298
|
+
},
|
|
299
|
+
async execute(args, exec) {
|
|
300
|
+
if (!state.enabled || !state.webSearch || !state.advancedHostedSearch)
|
|
301
|
+
throw webError(`${ADVANCED_HOSTED_TOOL} is disabled`, "LCX_WEB_DISABLED");
|
|
302
|
+
const config = getConfig();
|
|
303
|
+
const active = activeAgentRoute(exec);
|
|
304
|
+
const route = resolveResponsesRouteConfig(ctx, active, config);
|
|
305
|
+
if (!route)
|
|
306
|
+
throw webError("Advanced Hosted Search requires the active GPT openai-responses route", "LCX_WEB_ROUTE_UNAVAILABLE");
|
|
307
|
+
return executeHostedSearch(ctx, routeWithPolicies(route, config), args, exec.signal, active.sessionId);
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
function disposeGptToolsForAgent(agent, registrations) {
|
|
312
|
+
const registration = registrations.get(agent);
|
|
313
|
+
if (!registration)
|
|
314
|
+
return;
|
|
315
|
+
registration.dispose();
|
|
316
|
+
registrations.delete(agent);
|
|
317
|
+
}
|
|
318
|
+
function syncGptToolsForAgent(ctx, agent, state, getConfig, provider, registrations) {
|
|
319
|
+
const config = getConfig();
|
|
320
|
+
const active = selectedAgentRoute(agent);
|
|
321
|
+
const route = resolveResponsesRouteConfig(ctx, active, config);
|
|
322
|
+
const webSearch = state.enabled && state.webSearch && Boolean(route);
|
|
323
|
+
const advanced = webSearch && state.advancedHostedSearch;
|
|
324
|
+
if (!webSearch && !advanced) {
|
|
325
|
+
disposeGptToolsForAgent(agent, registrations);
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
const fingerprint = JSON.stringify({
|
|
329
|
+
provider: route?.provider,
|
|
330
|
+
model: route?.model,
|
|
331
|
+
baseURL: route?.baseURL,
|
|
332
|
+
webSearch,
|
|
333
|
+
advanced,
|
|
334
|
+
webMaxResults: config.webMaxResults,
|
|
335
|
+
});
|
|
336
|
+
if (registrations.get(agent)?.fingerprint === fingerprint)
|
|
337
|
+
return true;
|
|
338
|
+
disposeGptToolsForAgent(agent, registrations);
|
|
339
|
+
const scopedTools = scopedToolRuntime(agent);
|
|
340
|
+
if (!scopedTools)
|
|
341
|
+
return false;
|
|
342
|
+
const disposers = [];
|
|
343
|
+
try {
|
|
344
|
+
if (webSearch) {
|
|
345
|
+
const fetchEnabled = Boolean(scopedTools.get?.("web_fetch", agent));
|
|
346
|
+
disposers.push(scopedTools.register(createScopedGptWebSearchTool(ctx, state, getConfig, provider, fetchEnabled)));
|
|
347
|
+
}
|
|
348
|
+
if (advanced)
|
|
349
|
+
disposers.push(scopedTools.register(createAdvancedHostedTool(ctx, state, getConfig)));
|
|
350
|
+
registrations.set(agent, {
|
|
351
|
+
fingerprint,
|
|
352
|
+
dispose() {
|
|
353
|
+
for (const dispose of disposers.reverse())
|
|
354
|
+
dispose();
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
for (const dispose of disposers.reverse())
|
|
361
|
+
dispose();
|
|
362
|
+
ctx.logger?.warn?.(`[lcx-codex] GPT search tool composition unavailable: ${errorDetails(error).message ?? String(error)}`);
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
271
366
|
function alphaCapabilityFor(config, store) {
|
|
272
|
-
|
|
273
|
-
|
|
367
|
+
const fingerprint = alphaCapabilityFingerprint({
|
|
368
|
+
baseURL: config.baseURL,
|
|
369
|
+
provider: config.provider,
|
|
370
|
+
model: config.model,
|
|
371
|
+
profile: config.alphaProfile,
|
|
372
|
+
group: config.alphaGroup,
|
|
373
|
+
schemaFingerprint: ALPHA_SCHEMA_FINGERPRINT,
|
|
374
|
+
});
|
|
375
|
+
return { fingerprint, record: store.get(fingerprint) };
|
|
274
376
|
}
|
|
275
|
-
|
|
276
377
|
function verifiedAlphaCapabilityForRoute(ctx, active, config, store) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
378
|
+
const resolvedRoute = resolveResponsesRouteConfig(ctx, active, config);
|
|
379
|
+
if (!resolvedRoute)
|
|
380
|
+
return { route: undefined, usable: false };
|
|
381
|
+
const route = routeWithPolicies(resolvedRoute, config);
|
|
382
|
+
const { fingerprint, record } = alphaCapabilityFor(route, store);
|
|
383
|
+
return {
|
|
384
|
+
route,
|
|
385
|
+
fingerprint,
|
|
386
|
+
record,
|
|
387
|
+
usable: alphaCapabilityUsable(record) &&
|
|
388
|
+
record?.schemaFingerprint === ALPHA_SCHEMA_FINGERPRINT,
|
|
389
|
+
};
|
|
281
390
|
}
|
|
282
|
-
|
|
283
391
|
async function executeAlpha(ctx, routeConfig, capability, refStore, args, exec) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
392
|
+
const sessionId = agentSessionId(exec?.agent);
|
|
393
|
+
if (!sessionId)
|
|
394
|
+
throw webError("Alpha Search requires a DSH session", "LCX_ALPHA_SESSION_REQUIRED");
|
|
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,
|
|
408
|
+
});
|
|
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;
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
function createAlphaTool(ctx, state, getConfig, capabilityStore, refStore, advertisedRecord) {
|
|
449
|
+
return {
|
|
450
|
+
name: ALPHA_TOOL,
|
|
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.",
|
|
452
|
+
parameters: advertisedRecord
|
|
453
|
+
? alphaSearchParametersFor(advertisedRecord)
|
|
454
|
+
: ALPHA_SEARCH_PARAMETERS,
|
|
455
|
+
output: {
|
|
456
|
+
schema: ALPHA_SEARCH_OUTPUT,
|
|
457
|
+
render: (_args, value) => renderAlphaSearchResult(value),
|
|
458
|
+
},
|
|
459
|
+
async execute(args, exec) {
|
|
460
|
+
if (!state.enabled || !state.alphaSearch)
|
|
461
|
+
throw webError(`${ALPHA_TOOL} is disabled`, "LCX_ALPHA_DISABLED");
|
|
462
|
+
const config = getConfig();
|
|
463
|
+
const active = activeAgentRoute(exec);
|
|
464
|
+
const route = resolveResponsesRouteConfig(ctx, active, config);
|
|
465
|
+
if (!route)
|
|
466
|
+
throw webError("Alpha Search requires the active GPT openai-responses route", "LCX_ALPHA_ROUTE_UNAVAILABLE");
|
|
467
|
+
const routeConfig = routeWithPolicies(route, config);
|
|
468
|
+
const fingerprint = alphaCapabilityFingerprint({
|
|
469
|
+
baseURL: routeConfig.baseURL,
|
|
470
|
+
provider: routeConfig.provider,
|
|
471
|
+
model: routeConfig.model,
|
|
472
|
+
profile: routeConfig.alphaProfile,
|
|
473
|
+
group: routeConfig.alphaGroup,
|
|
474
|
+
schemaFingerprint: ALPHA_SCHEMA_FINGERPRINT,
|
|
475
|
+
});
|
|
476
|
+
const capability = capabilityStore.get(fingerprint);
|
|
477
|
+
if (!alphaCapabilityUsable(capability) ||
|
|
478
|
+
capability?.schemaFingerprint !== ALPHA_SCHEMA_FINGERPRINT)
|
|
479
|
+
throw webError("Alpha Search capability has not been verified for this exact route/schema", "LCX_ALPHA_CAPABILITY_UNVERIFIED");
|
|
480
|
+
return executeAlpha(ctx, routeConfig, capability, refStore, args, exec);
|
|
481
|
+
},
|
|
482
|
+
};
|
|
483
|
+
}
|
|
324
484
|
function syncAlphaToolForAgent(ctx, agent, state, getConfig, capabilityStore, refStore, registrations) {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
485
|
+
const previous = registrations.get(agent);
|
|
486
|
+
if (!state.enabled || !state.alphaSearch) {
|
|
487
|
+
disposeAlphaToolForAgent(agent, registrations);
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
490
|
+
try {
|
|
491
|
+
const config = getConfig();
|
|
492
|
+
const active = selectedAgentRoute(agent);
|
|
493
|
+
const capability = verifiedAlphaCapabilityForRoute(ctx, active, config, capabilityStore);
|
|
494
|
+
if (!capability.usable) {
|
|
495
|
+
disposeAlphaToolForAgent(agent, registrations);
|
|
496
|
+
return false;
|
|
497
|
+
}
|
|
498
|
+
if (previous?.fingerprint === capability.fingerprint)
|
|
499
|
+
return true;
|
|
500
|
+
disposeAlphaToolForAgent(agent, registrations);
|
|
501
|
+
const scopedTools = scopedToolRuntime(agent);
|
|
502
|
+
if (!scopedTools)
|
|
503
|
+
return false;
|
|
504
|
+
// Alpha is route-bound; global registration would advertise a static record to other routes.
|
|
505
|
+
registrations.set(agent, {
|
|
506
|
+
fingerprint: capability.fingerprint,
|
|
507
|
+
dispose: scopedTools.register(createAlphaTool(ctx, state, getConfig, capabilityStore, refStore, capability.record)),
|
|
508
|
+
});
|
|
509
|
+
return true;
|
|
337
510
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
return true
|
|
345
|
-
} catch (error) {
|
|
346
|
-
disposeAlphaToolForAgent(agent, registrations)
|
|
347
|
-
ctx.logger?.warn?.(`[lcx-codex] Alpha capability store unavailable: ${error?.message ?? error}`)
|
|
348
|
-
return false
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
511
|
+
catch (error) {
|
|
512
|
+
disposeAlphaToolForAgent(agent, registrations);
|
|
513
|
+
ctx.logger?.warn?.(`[lcx-codex] Alpha capability store unavailable: ${errorDetails(error).message ?? String(error)}`);
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
352
517
|
function disposeAlphaToolForAgent(agent, registrations) {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
518
|
+
const registration = registrations.get(agent);
|
|
519
|
+
if (!registration)
|
|
520
|
+
return;
|
|
521
|
+
registration.dispose();
|
|
522
|
+
registrations.delete(agent);
|
|
357
523
|
}
|
|
358
|
-
|
|
359
524
|
function isDshCompactionDirective(message) {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
return text.includes(COMPACTION_DIRECTIVE)
|
|
525
|
+
return (message?.role === "user" &&
|
|
526
|
+
message?.source?.kind === "plugin" &&
|
|
527
|
+
message?.source?.plugin === "dsh-compaction-basic");
|
|
364
528
|
}
|
|
365
529
|
function stripCompactionDirective(messages) {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
530
|
+
if (messages.length === 0)
|
|
531
|
+
return [];
|
|
532
|
+
return isDshCompactionDirective(messages.at(-1))
|
|
533
|
+
? messages.slice(0, -1)
|
|
534
|
+
: [...messages];
|
|
535
|
+
}
|
|
536
|
+
function mergeMap(target, source) {
|
|
537
|
+
for (const [key, value] of source ?? [])
|
|
538
|
+
target.set(key, value);
|
|
539
|
+
}
|
|
540
|
+
async function serializeNativeAware(messages, route, routeConfig, ctx, options) {
|
|
541
|
+
const session = sessionFor(ctx, route.sessionId);
|
|
542
|
+
const imageSupport = await resolveModelImageSupport(ctx, route, options.signal);
|
|
543
|
+
const input = [];
|
|
544
|
+
const imageMap = new Map();
|
|
545
|
+
let nativeTools;
|
|
546
|
+
let nativeModel;
|
|
547
|
+
let grammarToolInputProperties;
|
|
548
|
+
let normal = [];
|
|
549
|
+
const serializeOptions = (imageMapOverride = undefined, extra = {}) => requestImageOptions(routeConfig, imageSupport, options.signal, imageMapOverride, {
|
|
550
|
+
route,
|
|
551
|
+
tools: options.tools,
|
|
552
|
+
responsesCompat: routeConfig.responsesCompat,
|
|
553
|
+
...extra,
|
|
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;
|
|
562
|
+
const prelude = await serializeDshMessages([], ctx, serializeOptions(undefined, {
|
|
563
|
+
systemPrompt,
|
|
564
|
+
includeSystemPrompt: true,
|
|
565
|
+
}));
|
|
566
|
+
const ephemeralPreludeItemCount = prelude.input.length;
|
|
567
|
+
input.push(...prelude.input);
|
|
568
|
+
nativeTools = prelude.tools;
|
|
569
|
+
nativeModel = prelude.model;
|
|
570
|
+
grammarToolInputProperties = prelude.grammarToolInputProperties;
|
|
571
|
+
const flush = async () => {
|
|
572
|
+
if (!normal.length)
|
|
573
|
+
return;
|
|
574
|
+
const batch = normal;
|
|
575
|
+
normal = [];
|
|
576
|
+
const serialized = await serializeDshMessages(batch, ctx, serializeOptions());
|
|
577
|
+
nativeTools = serialized.tools ?? nativeTools;
|
|
578
|
+
nativeModel = serialized.model ?? nativeModel;
|
|
579
|
+
grammarToolInputProperties =
|
|
580
|
+
serialized.grammarToolInputProperties ?? grammarToolInputProperties;
|
|
581
|
+
input.push(...restoreGrokNativeReplay(serialized.input, batch, options.grokNativeReplayRoute));
|
|
582
|
+
mergeMap(imageMap, serialized.imageMap);
|
|
583
|
+
};
|
|
584
|
+
for (const message of surfaceMessages ?? []) {
|
|
585
|
+
assertSupportedCheckpointMessage(message);
|
|
586
|
+
const state = session
|
|
587
|
+
? checkpointStateForMessage(session, message)
|
|
588
|
+
: undefined;
|
|
589
|
+
if (state && session) {
|
|
590
|
+
const checkpointId = compactCheckpointId(message);
|
|
591
|
+
if (!checkpointId) {
|
|
592
|
+
normal.push(message);
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
await flush();
|
|
596
|
+
if (stateRouteCompatible(state, route, ctx)) {
|
|
597
|
+
const nativeOutput = state.nativeOutput;
|
|
598
|
+
const hydratedMap = new Map();
|
|
599
|
+
const hydrated = await hydrateNativeImageReferences(nativeOutput, ctx, requestImageOptions(routeConfig, imageSupport, options.signal, hydratedMap));
|
|
600
|
+
input.push(...responseInputItems(hydrated));
|
|
601
|
+
mergeMap(imageMap, hydratedMap);
|
|
412
602
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
603
|
+
else {
|
|
604
|
+
const portable = portableMessagesForCheckpoint(session, checkpointId, { maxChars: routeConfig.portableReplayMaxChars });
|
|
605
|
+
const serialized = await serializeDshMessages(portable, ctx, serializeOptions());
|
|
606
|
+
input.push(...serialized.input);
|
|
607
|
+
mergeMap(imageMap, serialized.imageMap);
|
|
608
|
+
}
|
|
609
|
+
continue;
|
|
419
610
|
}
|
|
420
|
-
|
|
421
|
-
const hydrated = await hydrateNativeImageReferences(nativeOutput, ctx, requestImageOptions(routeConfig, imageSupport, options.signal, hydratedMap))
|
|
422
|
-
input.push(...hydrated); mergeMap(imageMap, hydratedMap)
|
|
423
|
-
} else {
|
|
424
|
-
const portable = portableMessagesForCheckpoint(session, compactCheckpointId(message), { maxChars: routeConfig.portableReplayMaxChars })
|
|
425
|
-
const serialized = await serializeDshMessages(portable, ctx, serializeOptions())
|
|
426
|
-
input.push(...serialized.input); mergeMap(imageMap, serialized.imageMap)
|
|
427
|
-
}
|
|
428
|
-
continue
|
|
429
|
-
}
|
|
430
|
-
const legacyId = legacyV3Id(message)
|
|
431
|
-
if (legacyId) {
|
|
432
|
-
const legacy = loadLegacyRecord(routeConfig.legacyCheckpointPath, legacyId)
|
|
433
|
-
if (legacy) {
|
|
434
|
-
await flush()
|
|
435
|
-
const legacyItems = legacyRouteCompatible(legacy, route, ctx) ? legacy.nativeOutput : (legacy.portableHistory ?? [])
|
|
436
|
-
const hydratedMap = new Map()
|
|
437
|
-
const hydrated = await hydrateNativeImageReferences(legacyItems, ctx, requestImageOptions(routeConfig, imageSupport, options.signal, hydratedMap))
|
|
438
|
-
input.push(...hydrated); mergeMap(imageMap, hydratedMap)
|
|
439
|
-
continue
|
|
440
|
-
}
|
|
611
|
+
normal.push(message);
|
|
441
612
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
613
|
+
await flush();
|
|
614
|
+
if (!nativeModel)
|
|
615
|
+
throw Object.assign(new Error("LCX could not resolve the Pi Responses model descriptor"), { code: "LCX_RESPONSES_MODEL_UNAVAILABLE" });
|
|
616
|
+
return {
|
|
617
|
+
input,
|
|
618
|
+
ephemeralPreludeItemCount,
|
|
619
|
+
imageMap,
|
|
620
|
+
imageSupport,
|
|
621
|
+
tools: nativeTools,
|
|
622
|
+
model: nativeModel,
|
|
623
|
+
grammarToolInputProperties,
|
|
624
|
+
};
|
|
447
625
|
}
|
|
448
|
-
|
|
449
626
|
function fallbackEligible(error, signal) {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
const
|
|
461
|
-
const
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
627
|
+
if (signal?.aborted)
|
|
628
|
+
return false;
|
|
629
|
+
const details = errorDetails(error);
|
|
630
|
+
if (details.name === "AbortError" || details.code === "LCX_ABORTED")
|
|
631
|
+
return false;
|
|
632
|
+
if (details.name === "TimeoutError")
|
|
633
|
+
return true;
|
|
634
|
+
return ["LCX_HTTP_RETRYABLE", "LCX_RETRY_EXHAUSTED"].includes(String(details.code ?? ""));
|
|
635
|
+
}
|
|
636
|
+
async function* remoteCompactionStream(options, routeConfig, ctx, next) {
|
|
637
|
+
const history = stripCompactionDirective(options.messages);
|
|
638
|
+
const route = currentRoute(options, routeConfig);
|
|
639
|
+
try {
|
|
640
|
+
const prepared = await serializeNativeAware(history, route, routeConfig, ctx, { signal: options.signal, tools: options.tools });
|
|
641
|
+
const cacheSessionId = promptCacheSessionId(route, routeConfig, ctx);
|
|
642
|
+
const headers = await authenticatedHeaders(ctx, routeConfig, cacheSessionId, cacheSessionId === undefined ? null : route.sessionId);
|
|
643
|
+
const generation = generationControlsFromSession(sessionFor(ctx, route.sessionId), route);
|
|
644
|
+
const result = await requestNativeCompaction({
|
|
645
|
+
baseURL: routeConfig.baseURL,
|
|
646
|
+
model: route.model,
|
|
647
|
+
modelDescriptor: prepared.model,
|
|
648
|
+
input: prepared.input,
|
|
649
|
+
tools: prepared.tools ?? options.tools,
|
|
650
|
+
promptCacheKey: promptCacheKey(route, routeConfig, ctx),
|
|
651
|
+
promptCacheRetention: promptCacheRetention(routeConfig),
|
|
652
|
+
cacheRetention: routeConfig.cacheRetention,
|
|
653
|
+
reasoningEffort: generation.reasoningEffort,
|
|
654
|
+
temperature: generation.temperature,
|
|
655
|
+
maxTokens: generation.maxTokens,
|
|
656
|
+
idempotencyKey: randomUUID(),
|
|
657
|
+
headers,
|
|
658
|
+
signal: options.signal,
|
|
659
|
+
timeoutMs: routeConfig.timeoutMs,
|
|
660
|
+
maxAttempts: routeConfig.maxAttempts,
|
|
661
|
+
maxResponseBytes: routeConfig.maxResponseBytes,
|
|
662
|
+
});
|
|
663
|
+
const session = sessionFor(ctx, route.sessionId);
|
|
664
|
+
if (session === undefined)
|
|
665
|
+
throw webError("Native compaction requires a live DSH session", "LCX_COMPACT_SESSION_UNAVAILABLE");
|
|
666
|
+
const block = createNativeCheckpointBlock({
|
|
667
|
+
session,
|
|
668
|
+
route,
|
|
669
|
+
result,
|
|
670
|
+
input: prepared.input,
|
|
671
|
+
ephemeralPreludeItemCount: prepared.ephemeralPreludeItemCount,
|
|
672
|
+
imageMap: prepared.imageMap,
|
|
673
|
+
retentionOptions: {
|
|
674
|
+
tokenBudget: routeConfig.nativeRetentionTokenBudget,
|
|
675
|
+
assistantTokenReserve: routeConfig.assistantRetentionTokenReserve,
|
|
676
|
+
assistantPerMessageTokenCap: routeConfig.assistantRetentionPerMessageTokenCap,
|
|
677
|
+
},
|
|
678
|
+
});
|
|
679
|
+
ctx.logger?.info?.(`[lcx-codex] native V2 compaction succeeded; retained ${block.retainedClientCount ?? 0} client + ${block.retainedAssistantCount ?? 0} assistant-visible item(s) (~${block.retainedEstimatedTokens ?? 0} tokens) with the opaque checkpoint`);
|
|
680
|
+
for (const chunk of nativeCheckpointChunks(block, result.usage))
|
|
681
|
+
yield chunk;
|
|
682
|
+
}
|
|
683
|
+
catch (error) {
|
|
684
|
+
const session = sessionFor(ctx, route.sessionId);
|
|
685
|
+
const hasExistingCheckpoint = messagesContainNativeCheckpoint(history, session);
|
|
686
|
+
const details = errorDetails(error);
|
|
687
|
+
const code = details.code ?? details.name ?? "ERROR";
|
|
688
|
+
const status = Number.isInteger(details.status)
|
|
689
|
+
? ` status=${details.status}`
|
|
690
|
+
: "";
|
|
691
|
+
const requestId = isRecord(error) && error.requestId
|
|
692
|
+
? ` requestId=${String(error.requestId)}`
|
|
693
|
+
: "";
|
|
694
|
+
const providerCode = isRecord(error) && error.providerCode
|
|
695
|
+
? ` providerCode=${String(error.providerCode)}`
|
|
696
|
+
: "";
|
|
697
|
+
const providerType = isRecord(error) && error.providerType
|
|
698
|
+
? ` providerType=${String(error.providerType)}`
|
|
699
|
+
: "";
|
|
700
|
+
const providerParam = isRecord(error) && error.providerParam
|
|
701
|
+
? ` providerParam=${String(error.providerParam)}`
|
|
702
|
+
: "";
|
|
703
|
+
ctx.logger?.warn?.(`[lcx-codex] native V2 compaction failed: code=${code}${status}${requestId}${providerCode}${providerType}${providerParam}`);
|
|
704
|
+
if (hasExistingCheckpoint || !fallbackEligible(error, options.signal))
|
|
705
|
+
throw error;
|
|
706
|
+
ctx.logger?.info?.("[lcx-codex] falling back to DSH basic compaction after allowlisted first-checkpoint native failure");
|
|
707
|
+
const stream = await next();
|
|
708
|
+
for await (const chunk of stream)
|
|
709
|
+
yield chunk;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
function routedTargetForAgent(agent) {
|
|
713
|
+
const route = readAgentRouteState(agent);
|
|
714
|
+
const provider = stringValue(routeConfigValue(route.requestConfig, "provider") ??
|
|
715
|
+
routeConfigValue(route.options, "provider"), "");
|
|
716
|
+
const model = stringValue(routeConfigValue(route.requestConfig, "model") ??
|
|
717
|
+
routeConfigValue(route.options, "model"), "");
|
|
718
|
+
return provider && model ? { provider, model } : undefined;
|
|
719
|
+
}
|
|
531
720
|
export function compactionPressureBand(totalTokens, contextWindow, policy) {
|
|
532
|
-
|
|
533
|
-
|
|
721
|
+
const ratioPercent = (totalTokens / contextWindow) * 100;
|
|
722
|
+
return {
|
|
723
|
+
ratioPercent,
|
|
724
|
+
band: ratioPercent < policy.auto
|
|
725
|
+
? "below"
|
|
726
|
+
: ratioPercent < policy.emergency
|
|
727
|
+
? "native"
|
|
728
|
+
: "emergency",
|
|
729
|
+
};
|
|
534
730
|
}
|
|
535
|
-
|
|
536
731
|
function adjustedCompactionConfig(config, target, thresholdRatio) {
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
732
|
+
if (!isRecord(config))
|
|
733
|
+
return config;
|
|
734
|
+
const modelPolicies = Array.isArray(config.modelPolicies)
|
|
735
|
+
? config.modelPolicies.map((policy) => isRecord(policy) &&
|
|
736
|
+
policy.provider === target.provider &&
|
|
737
|
+
policy.model === target.model
|
|
738
|
+
? { ...policy, thresholdRatio }
|
|
739
|
+
: policy)
|
|
740
|
+
: config.modelPolicies;
|
|
741
|
+
return {
|
|
742
|
+
...config,
|
|
743
|
+
thresholdRatio,
|
|
744
|
+
...(modelPolicies === undefined ? {} : { modelPolicies }),
|
|
745
|
+
};
|
|
542
746
|
}
|
|
543
|
-
|
|
544
747
|
function combinedAbortSignal(primary, lifecycle) {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
748
|
+
return primary === lifecycle ? primary : AbortSignal.any([primary, lifecycle]);
|
|
749
|
+
}
|
|
750
|
+
function patchCompactionPressureService(compactionValue, state, getConfig, ctx, records) {
|
|
751
|
+
const candidate = compactionPatchCandidate(compactionValue, records);
|
|
752
|
+
if (!candidate)
|
|
753
|
+
return false;
|
|
754
|
+
const mutex = new ServiceMutex();
|
|
755
|
+
const policyScope = new InvocationPolicyScope();
|
|
756
|
+
const lifecycle = new AbortController();
|
|
757
|
+
return installCompactionPatch(records, candidate, mutex, policyScope, lifecycle, async (agent, trigger, signal, callOriginal) => {
|
|
758
|
+
const activeSignal = combinedAbortSignal(signal, lifecycle.signal);
|
|
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);
|
|
817
|
+
});
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
function patchCompactionPressureForAgent(agent, state, getConfig, ctx, records) {
|
|
821
|
+
return patchCompactionPressureService(resolveAgentService(ctx, agent, "compaction"), state, getConfig, ctx, records);
|
|
822
|
+
}
|
|
600
823
|
async function restoreCompactionPressure(records) {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
824
|
+
const reason = new Error("lcx-codex pressure coordination is shutting down");
|
|
825
|
+
const entries = [...records.values()];
|
|
826
|
+
for (const record of entries) {
|
|
827
|
+
if (!record.lifecycle.signal.aborted)
|
|
828
|
+
record.lifecycle.abort(reason);
|
|
829
|
+
}
|
|
830
|
+
await Promise.allSettled(entries.flatMap((record) => [
|
|
831
|
+
record.policyScope.close(reason),
|
|
832
|
+
record.mutex.close(reason),
|
|
833
|
+
]));
|
|
834
|
+
restoreCompactionPatches(records, entries);
|
|
835
|
+
for (const record of entries)
|
|
836
|
+
record.policyScope.restore();
|
|
837
|
+
}
|
|
838
|
+
function messagesContainNativeCheckpoint(messages, session) {
|
|
839
|
+
return session !== undefined && messages.some((message) => checkpointStateForMessage(session, message));
|
|
840
|
+
}
|
|
619
841
|
function inputHasNativeState(input) {
|
|
620
|
-
|
|
842
|
+
return input.some((item) => isRecord(item) && item.type === "compaction");
|
|
621
843
|
}
|
|
622
|
-
|
|
623
844
|
async function* managedResponsesStream(options, routeConfig, ctx) {
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
async function* unavailableManagedRouteStream(options) {
|
|
663
|
-
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)
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
function installInjected(ctx, configInput = {}) {
|
|
667
|
-
const baseConfig = normalizeConfig(configInput)
|
|
668
|
-
let runtimeConfig = baseConfig
|
|
669
|
-
const state = { enabled: false, webSearch: false, advancedHostedSearch: false, alphaSearch: false, remoteCompaction: false, fallbackToBasicCompaction: true, autoCompaction: true, webSearchTimeoutSeconds: baseConfig.webSearchTimeoutMs / 1000, autoCompactionThresholdPercent: baseConfig.autoCompactionThresholdPercent, emergencyPruneThresholdPercent: baseConfig.emergencyPruneThresholdPercent }
|
|
670
|
-
const originalSearchProvider = readWebSearchProvider(ctx)
|
|
671
|
-
let warnedWebSelection = false
|
|
672
|
-
const provider = new LcxResponsesSearchProvider(ctx, () => runtimeConfig, () => state.enabled && state.webSearch)
|
|
673
|
-
ctx.web.registerSearchProvider(provider)
|
|
674
|
-
const tools = contextService(ctx, 'tools')
|
|
675
|
-
let disposeAdvanced
|
|
676
|
-
const capabilityStore = new AlphaCapabilityStore(baseConfig.alphaCapabilityPath)
|
|
677
|
-
const refStore = new AlphaRefStore(baseConfig.alphaRefPath)
|
|
678
|
-
const alphaAgents = new Set()
|
|
679
|
-
const alphaToolRegistrations = new Map()
|
|
680
|
-
const compactionPatchRecords = new Map()
|
|
681
|
-
const patchedWebSearchDefinitions = new Map()
|
|
682
|
-
const requestHeaders = new Map()
|
|
683
|
-
const seedRequestHeader = (session) => updateRequestHeaderCache(requestHeaders, session, { type: 'compaction/start' })
|
|
684
|
-
for (const session of sessionsService(ctx)?.list?.() ?? []) seedRequestHeader(session)
|
|
685
|
-
ctx.on('session/created', (session) => {
|
|
686
|
-
seedRequestHeader(session)
|
|
687
|
-
}, { global: true })
|
|
688
|
-
ctx.on('session/disposed', (session) => {
|
|
689
|
-
requestHeaders.delete(String(session?.id ?? ''))
|
|
690
|
-
for (const agent of alphaAgents) if (agent?.session === session) {
|
|
691
|
-
disposeAlphaToolForAgent(agent, alphaToolRegistrations)
|
|
692
|
-
alphaAgents.delete(agent)
|
|
845
|
+
const route = currentRoute(options, routeConfig);
|
|
846
|
+
try {
|
|
847
|
+
if (options.stop !== undefined)
|
|
848
|
+
throw Object.assign(new Error("LCX Responses does not support GenerateOptions.stop"), { code: "LCX_RESPONSES_UNSUPPORTED_OPTION" });
|
|
849
|
+
const prepared = await serializeNativeAware(options.messages, route, routeConfig, ctx, { signal: options.signal, tools: options.tools });
|
|
850
|
+
const cacheSessionId = promptCacheSessionId(route, routeConfig, ctx);
|
|
851
|
+
const headers = await authenticatedHeaders(ctx, routeConfig, cacheSessionId, cacheSessionId === undefined ? null : route.sessionId);
|
|
852
|
+
const body = buildResponsesBody({
|
|
853
|
+
model: prepared.model,
|
|
854
|
+
input: prepared.input,
|
|
855
|
+
tools: prepared.tools ?? options.tools,
|
|
856
|
+
sessionId: cacheSessionId,
|
|
857
|
+
promptCacheKey: promptCacheKey(route, routeConfig, ctx),
|
|
858
|
+
promptCacheRetention: promptCacheRetention(routeConfig),
|
|
859
|
+
cacheRetention: routeConfig.cacheRetention,
|
|
860
|
+
reasoningEffort: options.reasoningEffort,
|
|
861
|
+
temperature: options.temperature,
|
|
862
|
+
maxTokens: options.maxTokens,
|
|
863
|
+
});
|
|
864
|
+
const nativeReplay = inputHasNativeState(prepared.input);
|
|
865
|
+
if (nativeReplay) {
|
|
866
|
+
body.tool_choice = "auto";
|
|
867
|
+
body.parallel_tool_calls = true;
|
|
868
|
+
}
|
|
869
|
+
yield* streamResponsesRequest({
|
|
870
|
+
baseURL: routeConfig.baseURL,
|
|
871
|
+
provider: route.provider,
|
|
872
|
+
model: route.model,
|
|
873
|
+
piModel: prepared.model,
|
|
874
|
+
body,
|
|
875
|
+
grammarToolInputProperties: prepared.grammarToolInputProperties,
|
|
876
|
+
headers: nativeReplay ? mergeFeatureHeader(headers) : headers,
|
|
877
|
+
signal: options.signal,
|
|
878
|
+
timeoutMs: routeConfig.timeoutMs,
|
|
879
|
+
maxAttempts: 1,
|
|
880
|
+
maxResponseBytes: routeConfig.maxResponseBytes,
|
|
881
|
+
});
|
|
693
882
|
}
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
updateRequestHeaderCache(requestHeaders, session, event)
|
|
697
|
-
if (event?.type === 'request/header') for (const agent of alphaAgents) if (agent?.session === session) {
|
|
698
|
-
syncAlphaToolForAgent(ctx, agent, state, () => runtimeConfig, capabilityStore, refStore, alphaToolRegistrations)
|
|
883
|
+
catch (error) {
|
|
884
|
+
yield managedFailureChunk(error, options.signal);
|
|
699
885
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
886
|
+
}
|
|
887
|
+
async function* managedGrokNativeSearchStream(options, routeConfig, nativeSearch, ctx) {
|
|
888
|
+
const route = currentRoute(options, routeConfig);
|
|
889
|
+
const nativeReplayRoute = grokReplayRoute(route, routeConfig);
|
|
890
|
+
try {
|
|
891
|
+
if (options.stop !== undefined)
|
|
892
|
+
throw Object.assign(new Error("LCX Responses does not support GenerateOptions.stop"), { code: "LCX_RESPONSES_UNSUPPORTED_OPTION" });
|
|
893
|
+
const visibleTools = grokVisibleFunctionTools(options.tools, nativeSearch);
|
|
894
|
+
const declaredToolNames = new Set(visibleTools?.map((tool) => tool.name) ?? []);
|
|
895
|
+
const prepared = await serializeNativeAware(options.messages, route, routeConfig, ctx, {
|
|
896
|
+
signal: options.signal,
|
|
897
|
+
tools: visibleTools,
|
|
898
|
+
grokNativeReplayRoute: nativeReplayRoute,
|
|
899
|
+
});
|
|
900
|
+
const cacheSessionId = grokPromptCacheSessionId(route, routeConfig);
|
|
901
|
+
const headers = await authenticatedGrokHeaders(ctx, routeConfig, cacheSessionId);
|
|
902
|
+
const model = {
|
|
903
|
+
...prepared.model,
|
|
904
|
+
...routeConfig.modelDefaults,
|
|
905
|
+
...routeConfig.modelControls,
|
|
906
|
+
id: route.model,
|
|
907
|
+
provider: route.provider,
|
|
908
|
+
baseUrl: routeConfig.baseURL,
|
|
909
|
+
api: "openai-responses",
|
|
910
|
+
};
|
|
911
|
+
const effectiveReasoning = options.reasoningEffort ?? routeConfig.profileReasoning;
|
|
912
|
+
if (effectiveReasoning !== undefined &&
|
|
913
|
+
!getSupportedThinkingLevels(model).some((level) => level === effectiveReasoning))
|
|
914
|
+
throw Object.assign(new Error(`Grok route does not support reasoning effort "${String(effectiveReasoning)}"`), { code: "LCX_RESPONSES_UNSUPPORTED_OPTION" });
|
|
915
|
+
const body = buildResponsesBody({
|
|
916
|
+
model,
|
|
917
|
+
input: prepared.input,
|
|
918
|
+
tools: grokWireTools(prepared.tools ?? visibleTools, nativeSearch),
|
|
919
|
+
sessionId: cacheSessionId,
|
|
920
|
+
promptCacheRetention: promptCacheRetention(routeConfig),
|
|
921
|
+
cacheRetention: routeConfig.cacheRetention,
|
|
922
|
+
reasoningEffort: effectiveReasoning,
|
|
923
|
+
temperature: options.temperature,
|
|
924
|
+
maxTokens: options.maxTokens,
|
|
925
|
+
});
|
|
926
|
+
if (nativeSearch.web) {
|
|
927
|
+
const include = new Set(Array.isArray(body.include) ? body.include : []);
|
|
928
|
+
include.add("web_search_call.action.sources");
|
|
929
|
+
body.include = [...include];
|
|
930
|
+
}
|
|
931
|
+
yield* streamResponsesRequest({
|
|
932
|
+
baseURL: routeConfig.baseURL,
|
|
933
|
+
provider: route.provider,
|
|
934
|
+
model: route.model,
|
|
935
|
+
piModel: model,
|
|
936
|
+
body,
|
|
937
|
+
grammarToolInputProperties: prepared.grammarToolInputProperties,
|
|
938
|
+
headers,
|
|
939
|
+
signal: options.signal,
|
|
940
|
+
timeoutMs: routeConfig.timeoutMs,
|
|
941
|
+
applyDefaultTimeout: false,
|
|
942
|
+
streamIdleTimeoutMs: routeConfig.streamIdleTimeoutMs,
|
|
943
|
+
maxAttempts: 1,
|
|
944
|
+
maxResponseBytes: routeConfig.maxResponseBytes,
|
|
945
|
+
serverToolTypes: GROK_NATIVE_SERVER_TOOL_TYPES,
|
|
946
|
+
isServerToolItem: (item) => isGrokNativeServerToolItem(item, nativeSearch, declaredToolNames),
|
|
947
|
+
declaredToolNames,
|
|
948
|
+
nativeReplayRoute,
|
|
949
|
+
onServerToolUsage(usage) {
|
|
950
|
+
ctx.logger?.info?.(`[lcx-codex] Grok native search used ${usage.total} server-side tool call(s) (web=${usage.webSearchCalls}, x=${usage.xSearchCalls})`);
|
|
951
|
+
},
|
|
952
|
+
});
|
|
713
953
|
}
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
const
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
954
|
+
catch (error) {
|
|
955
|
+
yield managedFailureChunk(error, options.signal);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
function isGptLifecycleTarget(options) {
|
|
959
|
+
return /^gpt-/iu.test(String(options.model ?? ""));
|
|
960
|
+
}
|
|
961
|
+
async function* unavailableManagedRouteStream(options) {
|
|
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);
|
|
963
|
+
}
|
|
964
|
+
function installInjected(ctx, configInput = {}) {
|
|
965
|
+
installSearchUsage(ctx);
|
|
966
|
+
const baseConfig = normalizeConfig(configInput);
|
|
967
|
+
let runtimeConfig = baseConfig;
|
|
968
|
+
const state = {
|
|
969
|
+
enabled: false,
|
|
970
|
+
webSearch: false,
|
|
971
|
+
advancedHostedSearch: false,
|
|
972
|
+
alphaSearch: false,
|
|
973
|
+
grokNativeWebSearch: false,
|
|
974
|
+
grokNativeXSearch: false,
|
|
975
|
+
};
|
|
976
|
+
const provider = new LcxResponsesSearchProvider(ctx, () => runtimeConfig, () => state.enabled && state.webSearch);
|
|
977
|
+
const capabilityStore = new AlphaCapabilityStore(baseConfig.alphaCapabilityPath);
|
|
978
|
+
const refStore = new AlphaRefStore(baseConfig.alphaRefPath);
|
|
979
|
+
const managedAgents = new Set();
|
|
980
|
+
const gptToolRegistrations = new Map();
|
|
981
|
+
const alphaToolRegistrations = new Map();
|
|
982
|
+
const compactionPatchRecords = new Map();
|
|
983
|
+
const syncAgentTools = (agent) => {
|
|
984
|
+
syncGptToolsForAgent(ctx, agent, state, () => runtimeConfig, provider, gptToolRegistrations);
|
|
985
|
+
syncAlphaToolForAgent(ctx, agent, state, () => runtimeConfig, capabilityStore, refStore, alphaToolRegistrations);
|
|
986
|
+
};
|
|
987
|
+
const refreshTools = () => {
|
|
988
|
+
for (const agent of managedAgents)
|
|
989
|
+
syncAgentTools(agent);
|
|
990
|
+
};
|
|
991
|
+
ctx.on("session/disposed", (session) => {
|
|
992
|
+
for (const agent of managedAgents)
|
|
993
|
+
if (agentUsesSession(agent, session)) {
|
|
994
|
+
disposeGptToolsForAgent(agent, gptToolRegistrations);
|
|
995
|
+
disposeAlphaToolForAgent(agent, alphaToolRegistrations);
|
|
996
|
+
managedAgents.delete(agent);
|
|
997
|
+
}
|
|
998
|
+
}, { global: true });
|
|
999
|
+
ctx.on("session/event", (session, event) => {
|
|
1000
|
+
if (event.type === "request/header")
|
|
1001
|
+
for (const agent of managedAgents)
|
|
1002
|
+
if (agentUsesSession(agent, session))
|
|
1003
|
+
syncAgentTools(agent);
|
|
1004
|
+
}, { global: true });
|
|
1005
|
+
const settingsEntry = {
|
|
1006
|
+
enabled: false,
|
|
1007
|
+
webSearch: false,
|
|
1008
|
+
advancedHostedSearch: false,
|
|
1009
|
+
alphaSearch: false,
|
|
1010
|
+
grokNativeWebSearch: false,
|
|
1011
|
+
grokNativeXSearch: false,
|
|
1012
|
+
searchMediaPreview: false,
|
|
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
|
+
});
|
|
1041
|
+
runtimeConfig = baseConfig;
|
|
775
1042
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
}
|
|
790
|
-
|
|
1043
|
+
catch { }
|
|
1044
|
+
refreshTools();
|
|
1045
|
+
ctx.inject(["compaction"], (compactionCtx) => {
|
|
1046
|
+
patchCompactionPressureService(resolveContextService(compactionCtx, "compaction"), state, () => runtimeConfig, ctx, compactionPatchRecords);
|
|
1047
|
+
});
|
|
1048
|
+
ctx.on("agent/created", ({ agent }) => {
|
|
1049
|
+
if (agent === null || typeof agent !== "object")
|
|
1050
|
+
return;
|
|
1051
|
+
managedAgents.add(agent);
|
|
1052
|
+
syncAgentTools(agent);
|
|
1053
|
+
const installed = patchCompactionPressureForAgent(agent, state, () => runtimeConfig, ctx, compactionPatchRecords);
|
|
1054
|
+
if (installed)
|
|
1055
|
+
ctx.logger?.info?.("[lcx-codex] pressure coordination installed through AgentPresets service resolver");
|
|
1056
|
+
}, { global: true });
|
|
1057
|
+
ctx.on("agent/status", ({ agent, status }) => {
|
|
1058
|
+
if (status !== "running" ||
|
|
1059
|
+
agent === null ||
|
|
1060
|
+
typeof agent !== "object")
|
|
1061
|
+
return;
|
|
1062
|
+
managedAgents.add(agent);
|
|
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");
|
|
1067
|
+
}, { global: true });
|
|
1068
|
+
ctx.on("llm/stream", (options, next) => {
|
|
1069
|
+
if (options.purpose === "session-title")
|
|
1070
|
+
return next();
|
|
1071
|
+
const grokNativeSearch = {
|
|
1072
|
+
web: state.grokNativeWebSearch,
|
|
1073
|
+
x: state.grokNativeXSearch,
|
|
1074
|
+
};
|
|
1075
|
+
if (options.purpose === undefined && grokNativeSearchEnabled(grokNativeSearch)) {
|
|
1076
|
+
const grokRoute = resolveGrokResponsesRouteConfig(ctx, options, runtimeConfig);
|
|
1077
|
+
if (grokRoute)
|
|
1078
|
+
return managedGrokNativeSearchStream(options, routeWithPolicies(grokRoute, runtimeConfig), grokNativeSearch, ctx);
|
|
1079
|
+
}
|
|
1080
|
+
if (!state.enabled || !isGptLifecycleTarget(options))
|
|
1081
|
+
return next();
|
|
1082
|
+
const routeConfig = resolveResponsesRouteConfig(ctx, options, runtimeConfig);
|
|
1083
|
+
if (options.purpose === "compaction") {
|
|
1084
|
+
if (!routeConfig)
|
|
1085
|
+
return unavailableManagedRouteStream(options);
|
|
1086
|
+
return remoteCompactionStream(options, routeWithPolicies(routeConfig, runtimeConfig), ctx, next);
|
|
1087
|
+
}
|
|
1088
|
+
if (!routeConfig)
|
|
1089
|
+
return unavailableManagedRouteStream(options);
|
|
1090
|
+
return managedResponsesStream(options, routeWithPolicies(routeConfig, runtimeConfig), ctx);
|
|
1091
|
+
});
|
|
1092
|
+
ctx.effect?.(() => async () => {
|
|
1093
|
+
for (const agent of managedAgents) {
|
|
1094
|
+
disposeGptToolsForAgent(agent, gptToolRegistrations);
|
|
1095
|
+
disposeAlphaToolForAgent(agent, alphaToolRegistrations);
|
|
1096
|
+
}
|
|
1097
|
+
managedAgents.clear();
|
|
1098
|
+
await restoreCompactionPressure(compactionPatchRecords);
|
|
1099
|
+
}, "lcx-codex cleanup");
|
|
1100
|
+
}
|
|
791
1101
|
export function apply(ctx, configInput = {}) {
|
|
792
|
-
|
|
1102
|
+
return installInjected(ctx, configInput);
|
|
793
1103
|
}
|
|
794
|
-
|
|
795
|
-
apply.
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
export default apply
|
|
1104
|
+
apply.inject = inject;
|
|
1105
|
+
apply.Config = Config;
|
|
1106
|
+
export default apply;
|