dsh-context-compression-improved 0.5.0 → 0.5.2
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.ja.md +51 -0
- package/CHANGELOG.ko.md +51 -0
- package/CHANGELOG.md +55 -0
- package/CHANGELOG.zh.md +45 -0
- package/package.json +1 -1
- package/packages/selector/lib/advisor-state.js +4 -231
- package/packages/selector/lib/client.d.ts +0 -24
- package/packages/selector/lib/client.js +6 -501
- package/packages/selector/lib/index.d.ts +4 -10
- package/packages/selector/lib/index.js +65 -235
- package/packages/selector/lib/pruner.d.ts +13 -248
- package/packages/selector/lib/pruner.js +148 -552
- package/packages/selector/src/client/EstimatorControls.tsx +277 -378
- package/packages/selector/src/client/index.ts +0 -17
- package/packages/selector/src/client/locales.ts +196 -234
- package/packages/selector/src/client/preset-options.ts +3 -2
- package/packages/selector/src/client/settings-section.tsx +8 -17
- package/packages/selector/src/index.ts +463 -710
- package/packages/selector/src/preset-overlay.ts +60 -1
- package/packages/selector/src/profiles.ts +4 -27
- package/packages/selector/src/pruner/state.ts +50 -73
- package/packages/selector/src/pruner.ts +2402 -2730
- package/packages/selector/src/runtime/audit.ts +27 -21
- package/packages/selector/src/runtime/config.ts +6 -32
- package/packages/selector/src/runtime/tokenpilot/advisor-state.ts +16 -0
- package/packages/selector/src/runtime/tokenpilot/benefit.ts +200 -0
- package/packages/selector/src/runtime/types.ts +0 -17
- package/packages/selector/tests/built/client-artifact.spec.ts +9 -5
- package/packages/selector/tests/preset-options-write.client.spec.ts +7 -23
- package/packages/selector/tests/runtime/advice-never-withholds.host.spec.ts +232 -0
- package/packages/selector/tests/runtime/audit.spec.ts +35 -21
- package/packages/selector/tests/runtime/deprecated-preset-options.spec.ts +96 -0
- package/packages/selector/tests/runtime/tokenpilot/benefit.spec.ts +217 -0
- package/packages/selector/tests/runtime/tokenpilot/profile-baseline.spec.ts +4 -5
- package/packages/selector/tests/settings-seat.client.spec.ts +16 -10
- package/packages/selector/tests/standing-generation.host.spec.ts +54 -5
- package/scripts/packed-components-smoke.mjs +30 -8
- package/scripts/packed-install-e2e.mjs +69 -15
- package/packages/selector/src/client/ReviewOverlay.tsx +0 -320
- package/packages/selector/src/client/review-scope.ts +0 -16
- package/packages/selector/src/runtime/tokenpilot/proposal.ts +0 -267
- package/packages/selector/src/runtime/tokenpilot/review-queue.ts +0 -231
- package/packages/selector/src/runtime/tokenpilot/review-registry.ts +0 -117
- package/packages/selector/src/runtime/tokenpilot/review-storage.ts +0 -122
- package/packages/selector/tests/review-overlay.client.spec.tsx +0 -118
- package/packages/selector/tests/review-routes-registry.host.spec.ts +0 -142
- package/packages/selector/tests/review-routes.host.spec.ts +0 -290
- package/packages/selector/tests/runtime/tokenpilot/proposal.spec.ts +0 -393
- package/packages/selector/tests/runtime/tokenpilot/pruner-review.spec.ts +0 -382
- package/packages/selector/tests/runtime/tokenpilot/review-queue.spec.ts +0 -168
|
@@ -116,6 +116,16 @@ export function standingStampMs(identity: string): number {
|
|
|
116
116
|
return standingStampMsAtWindow(identity, 0)
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
/**
|
|
120
|
+
* True for the filesystem errors a concurrent publish can raise on Windows:
|
|
121
|
+
* `MoveFileEx` reports a lost race — or a reader holding the destination open —
|
|
122
|
+
* as EPERM/EBUSY/EACCES, where POSIX `rename` simply replaces the destination.
|
|
123
|
+
*/
|
|
124
|
+
function isPublishRace(error: unknown): boolean {
|
|
125
|
+
const code = (error as { code?: unknown } | null)?.code
|
|
126
|
+
return code === 'EPERM' || code === 'EBUSY' || code === 'EACCES' || code === 'EEXIST'
|
|
127
|
+
}
|
|
128
|
+
|
|
119
129
|
const COMPRESSION_IDS = new Set([
|
|
120
130
|
'compaction',
|
|
121
131
|
'compaction-basic',
|
|
@@ -224,7 +234,7 @@ class PresetOverlayStore {
|
|
|
224
234
|
// still private. No reader can observe a colliding {mtimeMs,size}
|
|
225
235
|
// between rename and a later corrective utimes call.
|
|
226
236
|
await this.disambiguateStamp(staging, identity)
|
|
227
|
-
await
|
|
237
|
+
await this.publish(staging, path)
|
|
228
238
|
} catch (error) {
|
|
229
239
|
// A failed publish must not leak its staging file into the store; the
|
|
230
240
|
// cleanup must never mask the original failure either.
|
|
@@ -238,6 +248,55 @@ class PresetOverlayStore {
|
|
|
238
248
|
return { ...preset, path }
|
|
239
249
|
}
|
|
240
250
|
|
|
251
|
+
/** In-flight publish chains, one per destination path. */
|
|
252
|
+
private readonly publishChains = new Map<string, Promise<void>>()
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Publish one stamped staging file to its final path, serialized per path.
|
|
256
|
+
*
|
|
257
|
+
* POSIX `rename` replaces an existing destination atomically, so concurrent
|
|
258
|
+
* composers of one identity are naturally idempotent there. Windows
|
|
259
|
+
* `MoveFileEx` instead fails the loser of that race with EPERM/EBUSY, which
|
|
260
|
+
* surfaced as `standingKeyFor()` throwing during concurrent composition.
|
|
261
|
+
* Every composer of one identity writes identical bytes and re-derives the
|
|
262
|
+
* same deterministic identity stamp, so a destination that already observes
|
|
263
|
+
* this staging file's {mtimeMs, size} key IS the intended end state: confirm
|
|
264
|
+
* it and treat the lost race as success. Every other outcome still throws, so
|
|
265
|
+
* a silently reused generation stays forbidden, and the caller still removes
|
|
266
|
+
* the staging file when this rejects.
|
|
267
|
+
*/
|
|
268
|
+
private publish(staging: string, path: string): Promise<void> {
|
|
269
|
+
const previous = this.publishChains.get(path) ?? Promise.resolve()
|
|
270
|
+
const queued = previous.catch(() => undefined).then(async () => {
|
|
271
|
+
try {
|
|
272
|
+
await rename(staging, path)
|
|
273
|
+
return
|
|
274
|
+
} catch (error) {
|
|
275
|
+
if (!isPublishRace(error)) throw error
|
|
276
|
+
try {
|
|
277
|
+
const intended = await this.metadataIo.read(staging)
|
|
278
|
+
const published = await this.metadataIo.read(path)
|
|
279
|
+
// Sub-second precision survives a wrapped seconds field, but NTFS
|
|
280
|
+
// rounds it to 100ns, so compare the standing key within that
|
|
281
|
+
// rounding rather than by exact float equality.
|
|
282
|
+
if (published.size === intended.size
|
|
283
|
+
&& Math.abs(published.mtimeMs - intended.mtimeMs) < 2) {
|
|
284
|
+
await rm(staging, { force: true })
|
|
285
|
+
return
|
|
286
|
+
}
|
|
287
|
+
} catch {
|
|
288
|
+
// The destination is unreadable: report the original publish failure.
|
|
289
|
+
}
|
|
290
|
+
throw error
|
|
291
|
+
}
|
|
292
|
+
})
|
|
293
|
+
const tracked = queued.finally(() => {
|
|
294
|
+
if (this.publishChains.get(path) === tracked) this.publishChains.delete(path)
|
|
295
|
+
})
|
|
296
|
+
this.publishChains.set(path, tracked)
|
|
297
|
+
return tracked
|
|
298
|
+
}
|
|
299
|
+
|
|
241
300
|
/** Observed {mtimeMs,size} keys published by this store, per identity. */
|
|
242
301
|
private readonly standingKeys = new Map<string, string>()
|
|
243
302
|
|
|
@@ -135,11 +135,6 @@ export interface PresetOptionsSettings {
|
|
|
135
135
|
readonly estimatorBaseUrl?: string
|
|
136
136
|
readonly estimatorApiKey?: string
|
|
137
137
|
readonly estimatorTimeoutMs?: number
|
|
138
|
-
/** Review-mode overrides (beta); mirrors the runtime PresetOptions.reviewMode. */
|
|
139
|
-
readonly reviewMode?: boolean
|
|
140
|
-
readonly reviewTimeoutTurns?: number
|
|
141
|
-
readonly cacheHitDiscountAlpha?: number
|
|
142
|
-
readonly reviewHighImpactTokens?: number
|
|
143
138
|
/** Advisory advisor channel; `''` (the default) keeps the advisor off. */
|
|
144
139
|
readonly advisorMode?: '' | 'host' | 'direct'
|
|
145
140
|
readonly advisorTimeoutMs?: number
|
|
@@ -160,12 +155,15 @@ export function decodePresetOptionsSettings(value: unknown): PresetOptionsSettin
|
|
|
160
155
|
const allowed = new Set([
|
|
161
156
|
'dedupeToolResults', 'summaryLocator', 'prefixStabilizer', 'readState', 'estimatorMode',
|
|
162
157
|
'estimatorProvider', 'estimatorModel', 'estimatorBaseUrl', 'estimatorApiKey', 'estimatorTimeoutMs',
|
|
158
|
+
// Legacy keys of the retired review gate: still ACCEPTED so an existing
|
|
159
|
+
// settings document keeps decoding (rejecting them would report the whole
|
|
160
|
+
// card unreadable), and ignored — nothing reads them any more.
|
|
163
161
|
'reviewMode', 'reviewTimeoutTurns', 'cacheHitDiscountAlpha', 'reviewHighImpactTokens',
|
|
164
162
|
'advisorMode', 'advisorTimeoutMs', 'advisorRefreshTurns', 'advisorScoreThreshold', 'advisorSampleLimit',
|
|
165
163
|
'advisorMinTokens',
|
|
166
164
|
])
|
|
167
165
|
if (Object.keys(value).some(key => !allowed.has(key))) return undefined
|
|
168
|
-
for (const key of ['dedupeToolResults', 'summaryLocator', 'prefixStabilizer', 'readState'
|
|
166
|
+
for (const key of ['dedupeToolResults', 'summaryLocator', 'prefixStabilizer', 'readState'] as const) {
|
|
169
167
|
const entry = value[key]
|
|
170
168
|
if (entry !== undefined && typeof entry !== 'boolean') return undefined
|
|
171
169
|
}
|
|
@@ -187,23 +185,6 @@ export function decodePresetOptionsSettings(value: unknown): PresetOptionsSettin
|
|
|
187
185
|
|| estimatorTimeoutMs < 100 || estimatorTimeoutMs > 60_000)) {
|
|
188
186
|
return undefined
|
|
189
187
|
}
|
|
190
|
-
const reviewTimeoutTurns = value.reviewTimeoutTurns
|
|
191
|
-
if (reviewTimeoutTurns !== undefined
|
|
192
|
-
&& (typeof reviewTimeoutTurns !== 'number' || !Number.isSafeInteger(reviewTimeoutTurns) || reviewTimeoutTurns < 1)) {
|
|
193
|
-
return undefined
|
|
194
|
-
}
|
|
195
|
-
const cacheHitDiscountAlpha = value.cacheHitDiscountAlpha
|
|
196
|
-
if (cacheHitDiscountAlpha !== undefined
|
|
197
|
-
&& (typeof cacheHitDiscountAlpha !== 'number' || !Number.isFinite(cacheHitDiscountAlpha)
|
|
198
|
-
|| cacheHitDiscountAlpha <= 0 || cacheHitDiscountAlpha >= 1)) {
|
|
199
|
-
return undefined
|
|
200
|
-
}
|
|
201
|
-
const reviewHighImpactTokens = value.reviewHighImpactTokens
|
|
202
|
-
if (reviewHighImpactTokens !== undefined
|
|
203
|
-
&& (typeof reviewHighImpactTokens !== 'number' || !Number.isSafeInteger(reviewHighImpactTokens)
|
|
204
|
-
|| reviewHighImpactTokens < 0)) {
|
|
205
|
-
return undefined
|
|
206
|
-
}
|
|
207
188
|
const advisorTimeoutMs = value.advisorTimeoutMs
|
|
208
189
|
if (advisorTimeoutMs !== undefined
|
|
209
190
|
&& (typeof advisorTimeoutMs !== 'number' || !Number.isSafeInteger(advisorTimeoutMs)
|
|
@@ -246,10 +227,6 @@ export function decodePresetOptionsSettings(value: unknown): PresetOptionsSettin
|
|
|
246
227
|
if (value.estimatorBaseUrl !== undefined) decoded.estimatorBaseUrl = value.estimatorBaseUrl as string
|
|
247
228
|
if (value.estimatorApiKey !== undefined) decoded.estimatorApiKey = value.estimatorApiKey as string
|
|
248
229
|
if (estimatorTimeoutMs !== undefined) decoded.estimatorTimeoutMs = estimatorTimeoutMs as number
|
|
249
|
-
if (value.reviewMode !== undefined) decoded.reviewMode = value.reviewMode as boolean
|
|
250
|
-
if (reviewTimeoutTurns !== undefined) decoded.reviewTimeoutTurns = reviewTimeoutTurns as number
|
|
251
|
-
if (cacheHitDiscountAlpha !== undefined) decoded.cacheHitDiscountAlpha = cacheHitDiscountAlpha as number
|
|
252
|
-
if (reviewHighImpactTokens !== undefined) decoded.reviewHighImpactTokens = reviewHighImpactTokens as number
|
|
253
230
|
if (advisorMode !== undefined) decoded.advisorMode = advisorMode as '' | 'host' | 'direct'
|
|
254
231
|
if (advisorTimeoutMs !== undefined) decoded.advisorTimeoutMs = advisorTimeoutMs as number
|
|
255
232
|
if (advisorRefreshTurns !== undefined) decoded.advisorRefreshTurns = advisorRefreshTurns as number
|
|
@@ -1,73 +1,50 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Consolidated per-session mutable state for {@link ToolResultPruner}.
|
|
3
|
-
*
|
|
4
|
-
* Every field is a WeakMap keyed by Session, keeping the service
|
|
5
|
-
* stateless across sessions and safe under GC.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { Session } from '@deepseek-ai/dsh-session'
|
|
9
|
-
import type { DedupeTable } from '../runtime/tokenpilot/dedup.ts'
|
|
10
|
-
import type { EstimatorFailures } from '../runtime/tokenpilot/estimator.ts'
|
|
11
|
-
import type {
|
|
12
|
-
import type {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
readonly
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
/** Current pre-step chain identity, shared by this producer and downstream compaction-basic. */
|
|
52
|
-
readonly activeRequestBoundaries: WeakMap<Session, object>
|
|
53
|
-
/** Boundary identity that already attempted one fully preflighted TailTrim publication. */
|
|
54
|
-
readonly tailTrimBoundaryAttempts: WeakMap<Session, object>
|
|
55
|
-
/** Last effective policy audit key emitted for each Session. */
|
|
56
|
-
readonly policyResolutionAudits: WeakMap<Session, string>
|
|
57
|
-
/**
|
|
58
|
-
* TokenPilot-inspired R4: shared review-queue store. Starts as the in-memory
|
|
59
|
-
* fail-open fallback; swapped to the storageDomain-backed adapter when (and
|
|
60
|
-
* if) that seam opens successfully.
|
|
61
|
-
*/
|
|
62
|
-
reviewStore: ReviewQueueStore
|
|
63
|
-
/** Per-session review queue carrying the frozen timeout policy. */
|
|
64
|
-
readonly reviewQueues: WeakMap<Session, ReviewQueue>
|
|
65
|
-
/** Last observed turn index per Session: the monotonic clock for review expiries. */
|
|
66
|
-
readonly reviewClocks: WeakMap<Session, number>
|
|
67
|
-
/** Estimator-reported remaining turns Ŝ per Session; advisory only. */
|
|
68
|
-
readonly estimatorRemainingTurns: WeakMap<Session, number>
|
|
69
|
-
/** Per-session advisor side channel, constructed once with the advisor overrides. */
|
|
70
|
-
readonly advisorChannels: WeakMap<Session, SideChannel>
|
|
71
|
-
/** Four-state outcome counters per Session (floating-window summary row). */
|
|
72
|
-
readonly reviewSummaries: WeakMap<Session, ReviewSessionSummary>
|
|
73
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Consolidated per-session mutable state for {@link ToolResultPruner}.
|
|
3
|
+
*
|
|
4
|
+
* Every field is a WeakMap keyed by Session, keeping the service
|
|
5
|
+
* stateless across sessions and safe under GC.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Session } from '@deepseek-ai/dsh-session'
|
|
9
|
+
import type { DedupeTable } from '../runtime/tokenpilot/dedup.ts'
|
|
10
|
+
import type { EstimatorFailures } from '../runtime/tokenpilot/estimator.ts'
|
|
11
|
+
import type { SideChannel } from '../runtime/tokenpilot/sidechannel.ts'
|
|
12
|
+
import type {
|
|
13
|
+
ContextCompressionSettings,
|
|
14
|
+
ResolvedConfig,
|
|
15
|
+
} from '../runtime/types.ts'
|
|
16
|
+
|
|
17
|
+
/** Mutable per-session state bag used inside {@link ToolResultPruner}. */
|
|
18
|
+
export interface PrunerState {
|
|
19
|
+
/** Resolved immutable deployment configuration. */
|
|
20
|
+
readonly config: ResolvedConfig
|
|
21
|
+
|
|
22
|
+
/** Complete canonical setting document frozen when each Session first reaches this root service. */
|
|
23
|
+
readonly sessionSettings: WeakMap<Session, ContextCompressionSettings>
|
|
24
|
+
/** Original result seqs whose first-exposure KEEP/REDUCE decision has committed. */
|
|
25
|
+
readonly firstExposure: WeakMap<Session, Set<number>>
|
|
26
|
+
/** Result seqs permanently exempt from further reduction (recovery outputs and registered equivalents). */
|
|
27
|
+
readonly recoveryExemptions: WeakMap<Session, Set<number>>
|
|
28
|
+
/** Per-session canonical-content hash index backing tokenpilot-inspired dedupe. */
|
|
29
|
+
readonly dedupeTables: WeakMap<Session, DedupeTable>
|
|
30
|
+
/** Advisory estimator verdicts consumed by the read-state classification. */
|
|
31
|
+
readonly estimatorVerdicts: WeakMap<Session, Map<number, boolean>>
|
|
32
|
+
/** Per-session estimator failure backoff state. */
|
|
33
|
+
readonly estimatorFailures: WeakMap<Session, EstimatorFailures>
|
|
34
|
+
/** Runtime prerequisite warnings deduplicated per Session and failure key. */
|
|
35
|
+
readonly warnedFailures: WeakMap<Session, Set<string>>
|
|
36
|
+
/** Last Adaptive postflight attempt emitted per Session; keeps diagnostics bounded and independent. */
|
|
37
|
+
readonly postflightDiagnostics: WeakMap<Session, string>
|
|
38
|
+
/** Current pre-step chain identity, shared by this producer and downstream compaction-basic. */
|
|
39
|
+
readonly activeRequestBoundaries: WeakMap<Session, object>
|
|
40
|
+
/** Boundary identity that already attempted one fully preflighted TailTrim publication. */
|
|
41
|
+
readonly tailTrimBoundaryAttempts: WeakMap<Session, object>
|
|
42
|
+
/** Last effective policy audit key emitted for each Session. */
|
|
43
|
+
readonly policyResolutionAudits: WeakMap<Session, string>
|
|
44
|
+
/** Last observed turn index per Session: the monotonic clock for advisory records. */
|
|
45
|
+
readonly turnClocks: WeakMap<Session, number>
|
|
46
|
+
/** Estimator-reported remaining turns Ŝ per Session; advisory only. */
|
|
47
|
+
readonly estimatorRemainingTurns: WeakMap<Session, number>
|
|
48
|
+
/** Per-session advisor side channel, constructed once with the advisor overrides. */
|
|
49
|
+
readonly advisorChannels: WeakMap<Session, SideChannel>
|
|
50
|
+
}
|