dsh-lcx-codex 0.4.0 → 0.4.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/CHANGELOG.md +29 -2
- package/README.md +138 -183
- package/README_EN.md +137 -118
- package/assets/dsh-lcx-codex-banner.jpg +0 -0
- package/lib/compact-v2.js +129 -16
- package/lib/dsh-compat.js +124 -0
- package/lib/index.js +126 -92
- package/lib/native-checkpoint.js +241 -22
- package/lib/route.js +174 -12
- package/lib/token-budget.js +165 -0
- package/lib/web-search-alpha.js +148 -7
- package/lib/web-search-capability.js +5 -3
- package/package.json +4 -2
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { symbols as cordisSymbols } from '@deepseek-ai/cordis'
|
|
2
|
+
|
|
3
|
+
export function agentSessionId(agent) { return String(agent?.session?.id ?? '') }
|
|
4
|
+
|
|
5
|
+
export function readAgentRouteState(agent) {
|
|
6
|
+
return {
|
|
7
|
+
requestConfig: agent?.session?.requestHeader?.()?.config,
|
|
8
|
+
options: agent?.options,
|
|
9
|
+
sessionId: agentSessionId(agent),
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function sessionsService(ctx) { return ctx?.get?.('sessions') ?? ctx?.sessions }
|
|
14
|
+
export function sessionFor(ctx, sessionId) { return sessionId ? sessionsService(ctx)?.get?.(sessionId) : undefined }
|
|
15
|
+
|
|
16
|
+
export function readWebSearchProvider(ctx) {
|
|
17
|
+
try { return Reflect.get(ctx?.web, 'searchProviderId') } catch { return undefined }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function writeWebSearchProvider(ctx, providerId) {
|
|
21
|
+
if (!ctx?.web) return false
|
|
22
|
+
try {
|
|
23
|
+
if (!Reflect.set(ctx.web, 'searchProviderId', providerId)) return false
|
|
24
|
+
return Reflect.get(ctx.web, 'searchProviderId') === providerId
|
|
25
|
+
} catch { return false }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function contextService(ctx, name) { return ctx?.get?.(name) ?? ctx?.[name] }
|
|
29
|
+
|
|
30
|
+
export function resolveContextService(ctx, name) {
|
|
31
|
+
try { return contextService(ctx, name) } catch { return undefined }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function resolveScopedService(agent, name) { return resolveContextService(agent?.ctx, name) }
|
|
35
|
+
|
|
36
|
+
export function resolveAgentService(ctx, agent, name) {
|
|
37
|
+
const agentPresets = resolveContextService(ctx, 'agentPresets')
|
|
38
|
+
try {
|
|
39
|
+
const service = agentPresets?.serviceFor?.(agent, name)
|
|
40
|
+
if (service !== undefined) return service
|
|
41
|
+
} catch {}
|
|
42
|
+
return resolveScopedService(agent, name)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function concreteService(value) {
|
|
46
|
+
try { return value?.[cordisSymbols.original] ?? value } catch { return value }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function compactionPatchCandidate(value, records) {
|
|
50
|
+
const compaction = concreteService(value)
|
|
51
|
+
if (!compaction || typeof compaction.compactIfNeeded !== 'function' || records.has(compaction)) return undefined
|
|
52
|
+
return { compaction, original: compaction.compactIfNeeded }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function installCompactionPatch(records, record) {
|
|
56
|
+
try { record.compaction.compactIfNeeded = record.wrapper } catch { return false }
|
|
57
|
+
records.set(record.compaction, record)
|
|
58
|
+
return true
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function restoreCompactionPatches(records, entries = [...records.values()]) {
|
|
62
|
+
for (const record of entries) if (record.compaction?.compactIfNeeded === record.wrapper) {
|
|
63
|
+
try { record.compaction.compactIfNeeded = record.original } catch {}
|
|
64
|
+
}
|
|
65
|
+
records.clear()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function toolResultPrunerState(value) {
|
|
69
|
+
const pruner = concreteService(value)
|
|
70
|
+
const original = pruner?.pruneSession
|
|
71
|
+
return { pruner, original }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function patchToolResultPruner(state, replacement) {
|
|
75
|
+
if (!state?.pruner || typeof state.original !== 'function') return undefined
|
|
76
|
+
state.pruner.pruneSession = replacement
|
|
77
|
+
return { ...state, replacement }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function restoreToolResultPruner(record) {
|
|
81
|
+
if (record?.pruner?.pruneSession === record.replacement) {
|
|
82
|
+
try { record.pruner.pruneSession = record.original } catch {}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function compactionConfigState(service) { return { service, original: service?.config } }
|
|
87
|
+
|
|
88
|
+
export function patchCompactionConfig(state, createConfig) {
|
|
89
|
+
if (!state?.original || !state.service || !Object.prototype.hasOwnProperty.call(state.service, 'config')) return undefined
|
|
90
|
+
try {
|
|
91
|
+
const installed = createConfig(state.original)
|
|
92
|
+
state.service.config = installed
|
|
93
|
+
return { ...state, installed }
|
|
94
|
+
} catch { return undefined }
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function restoreCompactionConfig(record) {
|
|
98
|
+
if (record?.service?.config === record.installed) {
|
|
99
|
+
try { record.service.config = record.original } catch {}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function patchVisibleWebSearchTimeout(agent, getTimeoutMs, patchedDefinitions) {
|
|
104
|
+
const tools = resolveScopedService(agent, 'tools')
|
|
105
|
+
const definition = tools?.get?.('web_search', agent)
|
|
106
|
+
if (!definition || typeof definition !== 'object') return
|
|
107
|
+
if (!patchedDefinitions.has(definition)) patchedDefinitions.set(definition, definition.timeoutMs)
|
|
108
|
+
const timeoutMs = getTimeoutMs()
|
|
109
|
+
const target = timeoutMs === undefined ? patchedDefinitions.get(definition) : timeoutMs
|
|
110
|
+
try { definition.timeoutMs = target } catch {}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function refreshVisibleWebSearchTimeouts(patchedDefinitions, timeoutMs) {
|
|
114
|
+
for (const [definition, original] of patchedDefinitions.entries()) {
|
|
115
|
+
try { definition.timeoutMs = timeoutMs === undefined ? original : timeoutMs } catch {}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function restoreVisibleWebSearchTimeouts(patchedDefinitions) {
|
|
120
|
+
for (const [definition, original] of patchedDefinitions.entries()) {
|
|
121
|
+
try { if (original === undefined) delete definition.timeoutMs; else definition.timeoutMs = original } catch {}
|
|
122
|
+
}
|
|
123
|
+
patchedDefinitions.clear()
|
|
124
|
+
}
|
package/lib/index.js
CHANGED
|
@@ -4,8 +4,31 @@ import { randomUUID } from 'node:crypto'
|
|
|
4
4
|
import { homedir } from 'node:os'
|
|
5
5
|
import { join } from 'node:path'
|
|
6
6
|
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
7
|
-
import { symbols as cordisSymbols } from '@deepseek-ai/cordis'
|
|
8
7
|
import { fetchJsonWithRetry } from './transport.js'
|
|
8
|
+
import {
|
|
9
|
+
agentSessionId,
|
|
10
|
+
compactionConfigState,
|
|
11
|
+
compactionPatchCandidate,
|
|
12
|
+
contextService,
|
|
13
|
+
installCompactionPatch,
|
|
14
|
+
patchCompactionConfig,
|
|
15
|
+
patchToolResultPruner,
|
|
16
|
+
patchVisibleWebSearchTimeout,
|
|
17
|
+
readAgentRouteState,
|
|
18
|
+
readWebSearchProvider,
|
|
19
|
+
refreshVisibleWebSearchTimeouts,
|
|
20
|
+
resolveAgentService,
|
|
21
|
+
resolveContextService,
|
|
22
|
+
resolveScopedService,
|
|
23
|
+
restoreCompactionConfig,
|
|
24
|
+
restoreCompactionPatches,
|
|
25
|
+
restoreToolResultPruner,
|
|
26
|
+
restoreVisibleWebSearchTimeouts,
|
|
27
|
+
sessionFor,
|
|
28
|
+
sessionsService,
|
|
29
|
+
toolResultPrunerState,
|
|
30
|
+
writeWebSearchProvider,
|
|
31
|
+
} from './dsh-compat.js'
|
|
9
32
|
import {
|
|
10
33
|
authenticatedHeaders,
|
|
11
34
|
currentRoute,
|
|
@@ -51,6 +74,9 @@ import {
|
|
|
51
74
|
} from './web-search-hosted.js'
|
|
52
75
|
import {
|
|
53
76
|
ALPHA_SCHEMA_FINGERPRINT,
|
|
77
|
+
alphaRefRequiresStore,
|
|
78
|
+
isAlphaContinuationUrl,
|
|
79
|
+
isAlphaHttpUrl,
|
|
54
80
|
ALPHA_SEARCH_OUTPUT,
|
|
55
81
|
ALPHA_SEARCH_PARAMETERS,
|
|
56
82
|
buildAlphaSearchBody,
|
|
@@ -160,17 +186,22 @@ function webError(message, code, cause) {
|
|
|
160
186
|
}
|
|
161
187
|
|
|
162
188
|
function activeAgentRoute(exec, fallback) {
|
|
163
|
-
const
|
|
164
|
-
const latest = agent?.session?.requestHeader?.()?.config
|
|
189
|
+
const route = readAgentRouteState(exec?.agent)
|
|
165
190
|
return {
|
|
166
|
-
provider:
|
|
167
|
-
model:
|
|
168
|
-
sessionId:
|
|
191
|
+
provider: route.requestConfig?.provider ?? route.options?.provider ?? fallback.provider,
|
|
192
|
+
model: route.requestConfig?.model ?? route.options?.model ?? fallback.model,
|
|
193
|
+
sessionId: route.sessionId,
|
|
169
194
|
}
|
|
170
195
|
}
|
|
171
196
|
|
|
172
|
-
function
|
|
173
|
-
|
|
197
|
+
function selectedAgentRoute(agent, fallback) {
|
|
198
|
+
const route = readAgentRouteState(agent)
|
|
199
|
+
return {
|
|
200
|
+
provider: route.options?.provider ?? route.requestConfig?.provider ?? fallback.provider,
|
|
201
|
+
model: route.options?.model ?? route.requestConfig?.model ?? fallback.model,
|
|
202
|
+
sessionId: route.sessionId,
|
|
203
|
+
}
|
|
204
|
+
}
|
|
174
205
|
|
|
175
206
|
function requestImageOptions(routeConfig, imageSupport, signal, imageMap, extra = {}) {
|
|
176
207
|
return {
|
|
@@ -182,17 +213,6 @@ function requestImageOptions(routeConfig, imageSupport, signal, imageMap, extra
|
|
|
182
213
|
}
|
|
183
214
|
}
|
|
184
215
|
|
|
185
|
-
function readWebSearchProvider(ctx) {
|
|
186
|
-
try { return Reflect.get(ctx?.web, 'searchProviderId') } catch { return undefined }
|
|
187
|
-
}
|
|
188
|
-
function writeWebSearchProvider(ctx, providerId) {
|
|
189
|
-
if (!ctx?.web) return false
|
|
190
|
-
try {
|
|
191
|
-
if (!Reflect.set(ctx.web, 'searchProviderId', providerId)) return false
|
|
192
|
-
return Reflect.get(ctx.web, 'searchProviderId') === providerId
|
|
193
|
-
} catch { return false }
|
|
194
|
-
}
|
|
195
|
-
|
|
196
216
|
async function executeHostedSearch(ctx, routeConfig, args, signal, sessionId = '') {
|
|
197
217
|
const normalized = normalizeHostedSearchArgs(args)
|
|
198
218
|
const requestId = randomUUID()
|
|
@@ -251,12 +271,22 @@ function alphaCapabilityFor(config, store) {
|
|
|
251
271
|
return { fingerprint, record: store.get(fingerprint) }
|
|
252
272
|
}
|
|
253
273
|
|
|
274
|
+
function verifiedAlphaCapabilityForRoute(ctx, active, config, store) {
|
|
275
|
+
const route = resolveResponsesRouteConfig(ctx, active, config)
|
|
276
|
+
if (!route) return { route: undefined, usable: false }
|
|
277
|
+
const { fingerprint, record } = alphaCapabilityFor(route, store)
|
|
278
|
+
return { route, fingerprint, record, usable: alphaCapabilityUsable(record) && record?.schemaFingerprint === ALPHA_SCHEMA_FINGERPRINT }
|
|
279
|
+
}
|
|
280
|
+
|
|
254
281
|
async function executeAlpha(ctx, routeConfig, capability, refStore, args, exec) {
|
|
255
282
|
const normalized = normalizeAlphaSearchArgs(args)
|
|
256
|
-
|
|
283
|
+
if (['open', 'find', 'screenshot'].includes(normalized.action) && isAlphaHttpUrl(normalized.refId) && !isAlphaContinuationUrl(normalized.refId)) {
|
|
284
|
+
throw webError('Alpha Search direct URLs must be public HTTP(S) targets', 'LCX_ALPHA_URL_UNAVAILABLE')
|
|
285
|
+
}
|
|
286
|
+
const sessionId = agentSessionId(exec?.agent)
|
|
257
287
|
if (!sessionId) throw webError('Alpha Search requires a DSH session', 'LCX_ALPHA_SESSION_REQUIRED')
|
|
258
288
|
const routeFp = routeFingerprint({ provider: routeConfig.provider, model: routeConfig.model, baseURL: routeConfig.baseURL, sessionId })
|
|
259
|
-
if (
|
|
289
|
+
if (alphaRefRequiresStore(normalized.action, normalized.refId)) refStore.assertUsable(sessionId, routeFp, normalized.refId)
|
|
260
290
|
const requestId = randomUUID(); const headers = await authenticatedHeaders(ctx, routeConfig, sessionId, requestId)
|
|
261
291
|
let response
|
|
262
292
|
try {
|
|
@@ -289,6 +319,41 @@ function createAlphaTool(ctx, state, getConfig, capabilityStore, refStore) {
|
|
|
289
319
|
}
|
|
290
320
|
}
|
|
291
321
|
|
|
322
|
+
function syncAlphaToolForAgent(ctx, agent, state, getConfig, capabilityStore, refStore, registrations) {
|
|
323
|
+
const previous = registrations.get(agent)
|
|
324
|
+
if (!state.enabled || !state.alphaSearch) {
|
|
325
|
+
disposeAlphaToolForAgent(agent, registrations)
|
|
326
|
+
return false
|
|
327
|
+
}
|
|
328
|
+
try {
|
|
329
|
+
const config = getConfig()
|
|
330
|
+
const active = selectedAgentRoute(agent, config)
|
|
331
|
+
const capability = verifiedAlphaCapabilityForRoute(ctx, active, config, capabilityStore)
|
|
332
|
+
if (!capability.usable) {
|
|
333
|
+
disposeAlphaToolForAgent(agent, registrations)
|
|
334
|
+
return false
|
|
335
|
+
}
|
|
336
|
+
if (previous?.fingerprint === capability.fingerprint) return true
|
|
337
|
+
disposeAlphaToolForAgent(agent, registrations)
|
|
338
|
+
const scopedTools = resolveScopedService(agent, 'tools')
|
|
339
|
+
if (!scopedTools?.register) return false
|
|
340
|
+
// Alpha is route-bound; global registration would advertise a static record to other routes.
|
|
341
|
+
registrations.set(agent, { fingerprint: capability.fingerprint, dispose: scopedTools.register(createAlphaTool(ctx, state, getConfig, capabilityStore, refStore)) })
|
|
342
|
+
return true
|
|
343
|
+
} catch (error) {
|
|
344
|
+
disposeAlphaToolForAgent(agent, registrations)
|
|
345
|
+
ctx.logger?.warn?.(`[lcx-codex] Alpha capability store unavailable: ${error?.message ?? error}`)
|
|
346
|
+
return false
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function disposeAlphaToolForAgent(agent, registrations) {
|
|
351
|
+
const registration = registrations.get(agent)
|
|
352
|
+
if (!registration) return
|
|
353
|
+
registration.dispose()
|
|
354
|
+
registrations.delete(agent)
|
|
355
|
+
}
|
|
356
|
+
|
|
292
357
|
function isDshCompactionDirective(message) {
|
|
293
358
|
if (message?.role !== 'user') return false
|
|
294
359
|
if (message?.source?.kind === 'plugin' && message?.source?.plugin === 'dsh-compaction-basic') return true
|
|
@@ -439,9 +504,9 @@ async function* remoteCompactionStream(options, routeConfig, state, ctx, next, r
|
|
|
439
504
|
}
|
|
440
505
|
|
|
441
506
|
function routedTargetForAgent(agent, fallback) {
|
|
442
|
-
const
|
|
443
|
-
const provider =
|
|
444
|
-
const model =
|
|
507
|
+
const route = readAgentRouteState(agent)
|
|
508
|
+
const provider = route.requestConfig?.provider ?? route.options?.provider ?? fallback.provider
|
|
509
|
+
const model = route.requestConfig?.model ?? route.options?.model ?? fallback.model
|
|
445
510
|
return provider && model ? { provider, model } : undefined
|
|
446
511
|
}
|
|
447
512
|
|
|
@@ -465,25 +530,6 @@ function adjustedCompactionConfig(config, target, thresholdRatio) {
|
|
|
465
530
|
return { ...config, thresholdRatio, ...(modelPolicies === undefined ? {} : { modelPolicies }) }
|
|
466
531
|
}
|
|
467
532
|
|
|
468
|
-
function resolveContextService(ctx, name) {
|
|
469
|
-
try { return ctx?.get?.(name) ?? ctx?.[name] } catch { return undefined }
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
function resolveScopedService(agent, name) { return resolveContextService(agent?.ctx, name) }
|
|
473
|
-
|
|
474
|
-
function resolveAgentService(ctx, agent, name) {
|
|
475
|
-
const agentPresets = resolveContextService(ctx, 'agentPresets')
|
|
476
|
-
try {
|
|
477
|
-
const service = agentPresets?.serviceFor?.(agent, name)
|
|
478
|
-
if (service !== undefined) return service
|
|
479
|
-
} catch {}
|
|
480
|
-
return resolveScopedService(agent, name)
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
function concreteService(value) {
|
|
484
|
-
try { return value?.[cordisSymbols.original] ?? value } catch { return value }
|
|
485
|
-
}
|
|
486
|
-
|
|
487
533
|
function combinedAbortSignal(primary, lifecycle) {
|
|
488
534
|
if (!primary) return lifecycle
|
|
489
535
|
if (!lifecycle) return primary
|
|
@@ -492,9 +538,9 @@ function combinedAbortSignal(primary, lifecycle) {
|
|
|
492
538
|
}
|
|
493
539
|
|
|
494
540
|
function patchCompactionPressureService(compactionValue, state, getConfig, ctx, records, requestHeaders) {
|
|
495
|
-
const
|
|
496
|
-
if (!
|
|
497
|
-
const original =
|
|
541
|
+
const candidate = compactionPatchCandidate(compactionValue, records)
|
|
542
|
+
if (!candidate) return false
|
|
543
|
+
const { compaction, original } = candidate
|
|
498
544
|
const record = { compaction, original, wrapper: undefined, mutex: new ServiceMutex(), lifecycle: new AbortController() }
|
|
499
545
|
const wrapper = async function(agentArg, trigger, signal) {
|
|
500
546
|
const activeSignal = combinedAbortSignal(signal, record.lifecycle.signal)
|
|
@@ -517,28 +563,22 @@ function patchCompactionPressureService(compactionValue, state, getConfig, ctx,
|
|
|
517
563
|
const { auto, emergency } = pressurePolicy(state, config)
|
|
518
564
|
const ratioPercent = totalTokens / contextWindow * 100
|
|
519
565
|
if (ratioPercent < auto) return null
|
|
520
|
-
const
|
|
521
|
-
const
|
|
522
|
-
const originalConfig = this?.config
|
|
566
|
+
const prunerState = toolResultPrunerState(resolveAgentService(ctx, agentArg, 'toolResultPruner') ?? resolveContextService(this?.ctx, 'toolResultPruner'))
|
|
567
|
+
const configState = compactionConfigState(this)
|
|
523
568
|
const nativeFirst = ratioPercent < emergency
|
|
524
569
|
const noOpPrune = () => ({ pruned: [], charsRemoved: 0 })
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
if (originalConfig && this && Object.prototype.hasOwnProperty.call(this, 'config')) {
|
|
528
|
-
try { installedConfig = adjustedCompactionConfig(originalConfig, target, auto / 100); this.config = installedConfig } catch {}
|
|
529
|
-
}
|
|
570
|
+
const prunerPatch = nativeFirst ? patchToolResultPruner(prunerState, noOpPrune) : undefined
|
|
571
|
+
const configPatch = patchCompactionConfig(configState, originalConfig => adjustedCompactionConfig(originalConfig, target, auto / 100))
|
|
530
572
|
ctx.logger?.info?.(`[lcx-codex] auto pressure ${ratioPercent.toFixed(1)}%: ${nativeFirst ? 'Native V2 first' : 'emergency DSH prune allowed'} (native ${auto}%, emergency ${emergency}%)`)
|
|
531
573
|
try { return await callOriginal() }
|
|
532
574
|
finally {
|
|
533
|
-
|
|
534
|
-
|
|
575
|
+
restoreCompactionConfig(configPatch)
|
|
576
|
+
restoreToolResultPruner(prunerPatch)
|
|
535
577
|
}
|
|
536
578
|
})
|
|
537
579
|
}
|
|
538
580
|
record.wrapper = wrapper
|
|
539
|
-
|
|
540
|
-
records.set(compaction, record)
|
|
541
|
-
return true
|
|
581
|
+
return installCompactionPatch(records, record)
|
|
542
582
|
}
|
|
543
583
|
|
|
544
584
|
function patchCompactionPressureForAgent(agent, state, getConfig, ctx, records, requestHeaders) {
|
|
@@ -552,36 +592,20 @@ async function restoreCompactionPressure(records) {
|
|
|
552
592
|
if (!record.lifecycle.signal.aborted) record.lifecycle.abort(reason)
|
|
553
593
|
}
|
|
554
594
|
await Promise.allSettled(entries.map((record) => record.mutex.close(reason)))
|
|
555
|
-
|
|
556
|
-
records.clear()
|
|
595
|
+
restoreCompactionPatches(records, entries)
|
|
557
596
|
}
|
|
558
597
|
|
|
559
|
-
function
|
|
560
|
-
const tools = resolveScopedService(agent, 'tools')
|
|
561
|
-
const definition = tools?.get?.('web_search', agent)
|
|
562
|
-
if (!definition || typeof definition !== 'object') return
|
|
563
|
-
if (!patchedDefinitions.has(definition)) patchedDefinitions.set(definition, definition.timeoutMs)
|
|
598
|
+
function visibleWebSearchTimeout(state, getConfig) {
|
|
564
599
|
const config = getConfig()
|
|
565
600
|
const timeoutMs = Number.isFinite(state.webSearchTimeoutSeconds) ? Math.min(600_000, Math.max(30_000, Math.round(state.webSearchTimeoutSeconds * 1000))) : config.webSearchTimeoutMs
|
|
566
|
-
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
function refreshPatchedWebSearchTimeouts(state, getConfig, patchedDefinitions) {
|
|
570
|
-
const config = getConfig()
|
|
571
|
-
const timeoutMs = Number.isFinite(state.webSearchTimeoutSeconds) ? Math.min(600_000, Math.max(30_000, Math.round(state.webSearchTimeoutSeconds * 1000))) : config.webSearchTimeoutMs
|
|
572
|
-
for (const [definition, original] of patchedDefinitions.entries()) { try { definition.timeoutMs = state.enabled && state.webSearch ? timeoutMs : original } catch {} }
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
function restoreWebSearchTimeouts(patchedDefinitions) {
|
|
576
|
-
for (const [definition, original] of patchedDefinitions.entries()) { try { if (original === undefined) delete definition.timeoutMs; else definition.timeoutMs = original } catch {} }
|
|
577
|
-
patchedDefinitions.clear()
|
|
601
|
+
return state.enabled && state.webSearch ? timeoutMs : undefined
|
|
578
602
|
}
|
|
579
603
|
|
|
580
604
|
function messagesContainNativeCheckpoint(messages, session) { return Boolean(session && (messages ?? []).some((message) => checkpointStateForMessage(session, message))) }
|
|
581
605
|
function messagesContainLegacyCheckpoint(messages) { return (messages ?? []).some((message) => Boolean(legacyCheckpointId(message))) }
|
|
582
606
|
|
|
583
607
|
async function* recursiveLlmStream(ctx, options, messages) {
|
|
584
|
-
const llm = ctx
|
|
608
|
+
const llm = contextService(ctx, 'llm')
|
|
585
609
|
if (!llm?.stream) throw Object.assign(new Error('LCX portable replay requires ctx.llm.stream'), { code: 'LCX_CHECKPOINT_REPLAY_UNAVAILABLE' })
|
|
586
610
|
const rewritten = { ...options, messages }
|
|
587
611
|
bypassReplayOptions.add(rewritten)
|
|
@@ -613,10 +637,12 @@ function installInjected(ctx, configInput = {}) {
|
|
|
613
637
|
let warnedWebSelection = false
|
|
614
638
|
const provider = new LcxResponsesSearchProvider(ctx, () => runtimeConfig, () => state.enabled && state.webSearch)
|
|
615
639
|
ctx.web.registerSearchProvider(provider)
|
|
616
|
-
const tools = ctx
|
|
617
|
-
let disposeAdvanced
|
|
640
|
+
const tools = contextService(ctx, 'tools')
|
|
641
|
+
let disposeAdvanced
|
|
618
642
|
const capabilityStore = new AlphaCapabilityStore(baseConfig.alphaCapabilityPath)
|
|
619
643
|
const refStore = new AlphaRefStore(baseConfig.alphaRefPath)
|
|
644
|
+
const alphaAgents = new Set()
|
|
645
|
+
const alphaToolRegistrations = new Map()
|
|
620
646
|
const compactionPatchRecords = new Map()
|
|
621
647
|
const patchedWebSearchDefinitions = new Map()
|
|
622
648
|
const requestHeaders = new Map()
|
|
@@ -627,20 +653,22 @@ function installInjected(ctx, configInput = {}) {
|
|
|
627
653
|
}, { global: true })
|
|
628
654
|
ctx.on('session/disposed', (session) => {
|
|
629
655
|
requestHeaders.delete(String(session?.id ?? ''))
|
|
656
|
+
for (const agent of alphaAgents) if (agent?.session === session) {
|
|
657
|
+
disposeAlphaToolForAgent(agent, alphaToolRegistrations)
|
|
658
|
+
alphaAgents.delete(agent)
|
|
659
|
+
}
|
|
630
660
|
}, { global: true })
|
|
631
661
|
ctx.on('session/event', (session, event) => {
|
|
632
662
|
updateRequestHeaderCache(requestHeaders, session, event)
|
|
663
|
+
if (event?.type === 'request/header') for (const agent of alphaAgents) if (agent?.session === session) {
|
|
664
|
+
syncAlphaToolForAgent(ctx, agent, state, () => runtimeConfig, capabilityStore, refStore, alphaToolRegistrations)
|
|
665
|
+
}
|
|
633
666
|
}, { global: true })
|
|
634
667
|
|
|
635
668
|
const refreshTools = () => {
|
|
636
669
|
if (state.enabled && state.webSearch && state.advancedHostedSearch && !disposeAdvanced && tools?.register) disposeAdvanced = tools.register(createAdvancedHostedTool(ctx, state, () => runtimeConfig))
|
|
637
670
|
if ((!state.enabled || !state.webSearch || !state.advancedHostedSearch) && disposeAdvanced) { disposeAdvanced(); disposeAdvanced = undefined }
|
|
638
|
-
|
|
639
|
-
if (state.enabled && state.alphaSearch) {
|
|
640
|
-
try { const { record } = alphaCapabilityFor(runtimeConfig, capabilityStore); alphaUsable = alphaCapabilityUsable(record) && record?.schemaFingerprint === ALPHA_SCHEMA_FINGERPRINT } catch (error) { ctx.logger?.warn?.(`[lcx-codex] Alpha capability store unavailable: ${error?.message ?? error}`) }
|
|
641
|
-
}
|
|
642
|
-
if (alphaUsable && !disposeAlpha && tools?.register) disposeAlpha = tools.register(createAlphaTool(ctx, state, () => runtimeConfig, capabilityStore, refStore))
|
|
643
|
-
if (!alphaUsable && disposeAlpha) { disposeAlpha(); disposeAlpha = undefined }
|
|
671
|
+
for (const agent of alphaAgents) syncAlphaToolForAgent(ctx, agent, state, () => runtimeConfig, capabilityStore, refStore, alphaToolRegistrations)
|
|
644
672
|
if (ctx.web) {
|
|
645
673
|
const target = state.enabled && state.webSearch ? runtimeConfig.webSearchProvider : originalSearchProvider
|
|
646
674
|
const selected = writeWebSearchProvider(ctx, target)
|
|
@@ -668,7 +696,7 @@ function installInjected(ctx, configInput = {}) {
|
|
|
668
696
|
state.autoCompactionThresholdPercent = clampPercent(value.autoCompactionThresholdPercent, baseConfig.autoCompactionThresholdPercent, 85, 95)
|
|
669
697
|
state.emergencyPruneThresholdPercent = clampPercent(value.emergencyPruneThresholdPercent, baseConfig.emergencyPruneThresholdPercent, 90, 99)
|
|
670
698
|
runtimeConfig = normalizeConfig({ ...baseConfig, provider: value.provider ?? baseConfig.provider, baseURL: value.baseURL ?? baseConfig.baseURL, apiKeyEnv: value.apiKeyEnv ?? baseConfig.apiKeyEnv, model: value.model ?? baseConfig.model })
|
|
671
|
-
refreshTools();
|
|
699
|
+
refreshTools(); refreshVisibleWebSearchTimeouts(patchedWebSearchDefinitions, visibleWebSearchTimeout(state, () => runtimeConfig))
|
|
672
700
|
},
|
|
673
701
|
})
|
|
674
702
|
try {
|
|
@@ -689,15 +717,19 @@ function installInjected(ctx, configInput = {}) {
|
|
|
689
717
|
|
|
690
718
|
ctx.on('agent/created', ({ agent }) => {
|
|
691
719
|
if (!agent) return
|
|
720
|
+
alphaAgents.add(agent)
|
|
721
|
+
syncAlphaToolForAgent(ctx, agent, state, () => runtimeConfig, capabilityStore, refStore, alphaToolRegistrations)
|
|
692
722
|
const installed = patchCompactionPressureForAgent(agent, state, () => runtimeConfig, ctx, compactionPatchRecords, requestHeaders)
|
|
693
723
|
if (installed) ctx.logger?.info?.('[lcx-codex] pressure coordination installed through AgentPresets service resolver')
|
|
694
724
|
}, { global: true })
|
|
695
725
|
|
|
696
726
|
ctx.on('agent/status', ({ agent, status }) => {
|
|
697
727
|
if (status !== 'running' || !agent) return
|
|
728
|
+
alphaAgents.add(agent)
|
|
729
|
+
syncAlphaToolForAgent(ctx, agent, state, () => runtimeConfig, capabilityStore, refStore, alphaToolRegistrations)
|
|
698
730
|
const installed = patchCompactionPressureForAgent(agent, state, () => runtimeConfig, ctx, compactionPatchRecords, requestHeaders)
|
|
699
731
|
if (installed) ctx.logger?.info?.('[lcx-codex] pressure coordination installed through AgentPresets service resolver')
|
|
700
|
-
patchVisibleWebSearchTimeout(agent, state, () => runtimeConfig, patchedWebSearchDefinitions)
|
|
732
|
+
patchVisibleWebSearchTimeout(agent, () => visibleWebSearchTimeout(state, () => runtimeConfig), patchedWebSearchDefinitions)
|
|
701
733
|
}, { global: true })
|
|
702
734
|
|
|
703
735
|
ctx.on('llm/stream', (options, next) => {
|
|
@@ -720,16 +752,18 @@ function installInjected(ctx, configInput = {}) {
|
|
|
720
752
|
})
|
|
721
753
|
|
|
722
754
|
ctx.effect?.(() => async () => {
|
|
723
|
-
disposeAdvanced?.()
|
|
755
|
+
disposeAdvanced?.()
|
|
756
|
+
for (const agent of alphaAgents) disposeAlphaToolForAgent(agent, alphaToolRegistrations)
|
|
757
|
+
alphaAgents.clear()
|
|
724
758
|
await restoreCompactionPressure(compactionPatchRecords)
|
|
725
|
-
|
|
759
|
+
restoreVisibleWebSearchTimeouts(patchedWebSearchDefinitions)
|
|
726
760
|
writeWebSearchProvider(ctx, originalSearchProvider)
|
|
727
761
|
requestHeaders.clear()
|
|
728
762
|
}, 'lcx-codex cleanup')
|
|
729
763
|
}
|
|
730
764
|
|
|
731
765
|
export function apply(ctx, configInput = {}) {
|
|
732
|
-
return
|
|
766
|
+
return installInjected(ctx, configInput)
|
|
733
767
|
}
|
|
734
768
|
|
|
735
769
|
apply.inject = inject
|