Merge branch 'codex/invariant-service-seam' into codex/invariant-package-registration-gate

This commit is contained in:
Tianyi Cui
2026-07-20 19:48:51 +08:00
391 changed files with 15415 additions and 8532 deletions
@@ -0,0 +1,77 @@
/** Configuration resolution for deterministic tool-result pruning. */
import { deepFreeze } from '@deepseek-ai/dsh-llm'
import type { ResolvedConfig, ToolResultPruneConfig } from './types.ts'
/** Fixed marker substituted for every removed middle span. */
export const PRUNE_MARKER = '\n\n[... tool result middle pruned ...]\n\n'
/** Low-friction defaults for coding-agent tool output. */
export const DEFAULTS: ResolvedConfig = deepFreeze({
thresholdChars: 8192,
headChars: 4096,
tailChars: 1024,
})
const CONFIG_KEYS: ReadonlySet<string> = new Set([
'thresholdChars',
'headChars',
'tailChars',
])
/**
* Count Unicode code points without splitting surrogate pairs.
* @param text - text to measure.
* @returns the Unicode code-point count.
*/
export function codePointLength(text: string): number {
return Array.from(text).length
}
/**
* Resolve and validate pruning budgets.
* @param config - raw plugin configuration.
* @returns a detached deeply immutable configuration.
*/
export function resolveConfig(config: ToolResultPruneConfig = {}): ResolvedConfig {
for (const key of Object.keys(config)) {
if (!CONFIG_KEYS.has(key)) {
throw new Error(
`ToolResultPruneConfig: unknown key "${key}" `
+ '(allowed: thresholdChars, headChars, tailChars)',
)
}
}
const resolved: ResolvedConfig = {
thresholdChars: config.thresholdChars ?? DEFAULTS.thresholdChars,
headChars: config.headChars ?? DEFAULTS.headChars,
tailChars: config.tailChars ?? DEFAULTS.tailChars,
}
assertPositiveInteger('thresholdChars', resolved.thresholdChars)
assertNonNegativeInteger('headChars', resolved.headChars)
assertNonNegativeInteger('tailChars', resolved.tailChars)
const emittedChars = resolved.headChars
+ codePointLength(PRUNE_MARKER)
+ resolved.tailChars
if (emittedChars > resolved.thresholdChars) {
throw new Error(
`ToolResultPruneConfig: headChars + marker + tailChars (${emittedChars}) `
+ `must be at most thresholdChars (${resolved.thresholdChars})`,
)
}
return deepFreeze(structuredClone(resolved))
}
function assertPositiveInteger(name: string, value: number): void {
if (!Number.isInteger(value) || value <= 0) {
throw new Error(`ToolResultPruneConfig: ${name} (${value}) must be a positive integer`)
}
}
function assertNonNegativeInteger(name: string, value: number): void {
if (!Number.isInteger(value) || value < 0) {
throw new Error(`ToolResultPruneConfig: ${name} (${value}) must be a non-negative integer`)
}
}
@@ -0,0 +1,159 @@
/**
* Replay-safe, model-free tool-result pruning service.
*
* @module @deepseek-ai/dsh-compact-tool-result-prune
*/
import { Context, Service } from 'cordis'
import z from 'schemastery'
import type { ContentBlock } from '@deepseek-ai/dsh-llm'
import type { Session, SessionEvent } from '@deepseek-ai/dsh-session'
import { codePointLength, DEFAULTS, PRUNE_MARKER, resolveConfig } from './config.ts'
import type {
PrunedEntry,
PruneResult,
ResolvedConfig,
ToolResultPruneConfig,
} from './types.ts'
export { codePointLength, DEFAULTS, PRUNE_MARKER, resolveConfig } from './config.ts'
export type {
PrunedEntry,
PruneResult,
ResolvedConfig,
ToolResultPruneConfig,
} from './types.ts'
declare module 'cordis' {
interface Context {
toolResultPrune: ToolResultPruneService
}
}
interface SnapshotCandidate {
readonly seq: number
readonly event: SessionEvent<'tool/result'>
}
/** Deterministic head/middle/tail pruning for current tool-result surface nodes. */
export class ToolResultPruneService extends Service {
static Config: z<ToolResultPruneConfig> = z.object({
thresholdChars: z.number().step(1).min(1).default(DEFAULTS.thresholdChars),
headChars: z.number().step(1).min(0).default(DEFAULTS.headChars),
tailChars: z.number().step(1).min(0).default(DEFAULTS.tailChars),
})
/** Resolved and immutable character budgets. */
readonly config: ResolvedConfig
constructor(ctx: Context, config: ToolResultPruneConfig = {}) {
super(ctx, 'toolResultPrune')
this.config = resolveConfig(config)
}
/**
* Measure text content in Unicode code points; non-text blocks cost zero.
* @param blocks - tool-result content to measure.
* @returns total Unicode code points across text blocks.
*/
measureContent(blocks: readonly ContentBlock[]): number {
let chars = 0
for (const block of blocks) {
if (block.type === 'text') chars += codePointLength(block.text)
}
return chars
}
/**
* Replace an over-budget text middle while retaining rich-block order.
* Text slicing is by Unicode code point, not UTF-16 code unit, so a retained
* boundary cannot split a surrogate pair. Grapheme clusters may still split.
* @param blocks - original tool-result content.
* @returns pruned content, or `null` when the text is within budget.
*/
pruneContent(blocks: readonly ContentBlock[]): ContentBlock[] | null {
const totalChars = this.measureContent(blocks)
if (totalChars <= this.config.thresholdChars) return null
const removedStart = this.config.headChars
const removedEnd = totalChars - this.config.tailChars
const pruned: ContentBlock[] = []
let consumed = 0
let markerInserted = false
for (const block of blocks) {
if (block.type !== 'text') {
pruned.push(block)
continue
}
const points = Array.from(block.text)
const blockStart = consumed
const blockEnd = blockStart + points.length
const headEnd = Math.min(points.length, Math.max(0, removedStart - blockStart))
const tailStart = Math.min(points.length, Math.max(0, removedEnd - blockStart))
const intersectsRemoved = blockStart < removedEnd && blockEnd > removedStart
const marker = intersectsRemoved && !markerInserted ? PRUNE_MARKER : ''
if (marker.length > 0) markerInserted = true
const text = points.slice(0, headEnd).join('')
+ marker
+ points.slice(tailStart).join('')
if (text.length > 0) pruned.push({ ...block, text })
consumed = blockEnd
}
/* v8 ignore next -- totalChars > threshold and valid budgets guarantee a removed text span. */
if (!markerInserted) throw new Error('tool-result prune: failed to locate the removed text span')
const charsAfter = this.measureContent(pruned)
/* v8 ignore next -- config validation fixes the emitted head + marker + tail budget. */
if (charsAfter > this.config.thresholdChars || charsAfter >= totalChars) {
throw new Error('tool-result prune: replacement must be smaller and within threshold')
}
return pruned
}
/**
* Prune every over-budget tool result from one stable current-surface snapshot.
* Each replacement preserves the complete event data except for `content`,
* and points at the shadowed node for durable provenance and replay.
* @param session - session whose current surface is rewritten.
* @returns landed replacements and aggregate Unicode-code-point savings.
* @throws when the session rejects a replacement; replacements committed
* earlier in the pass remain durable.
*/
pruneSession(session: Session): PruneResult {
const candidates: SnapshotCandidate[] = []
for (const seq of [...session.surface.nodes]) {
const event = session.events[seq]
/* v8 ignore next -- surface seqs are validated contiguous log references. */
if (event?.type === 'tool/result') candidates.push({ seq, event })
}
const pruned: PrunedEntry[] = []
let charsRemoved = 0
for (const { seq, event } of candidates) {
const content = this.pruneContent(event.data.content)
if (content === null) continue
const charsBefore = this.measureContent(event.data.content)
const charsAfter = this.measureContent(content)
const replacement = session.append('tool/result', {
...event.data,
content,
}, {
surfaceOp: { op: 'replace', start: seq, end: seq },
sourceEventSeqs: [seq],
})
pruned.push({
originalSeq: seq,
replacementSeq: replacement.seq,
callId: event.data.callId,
charsBefore,
charsAfter,
})
charsRemoved += charsBefore - charsAfter
}
return { pruned, charsRemoved }
}
}
export default ToolResultPruneService
@@ -0,0 +1,27 @@
/**
* Package-owned invariant companion for `@deepseek-ai/dsh-compact-tool-result-prune`.
* @module @deepseek-ai/dsh-compact-tool-result-prune/invariant
*/
/* jscpd:ignore-start */
import type { Context } from 'cordis'
import type { InvariantInstaller } from '@deepseek-ai/dsh-invariants'
const PACKAGE_NAME = '@deepseek-ai/dsh-compact-tool-result-prune'
/** Cordis companion plugin name. */
export const name = 'compact-tool-result-prune-invariant'
/** Services required before the companion can register. */
export const inject = ['invariants']
/** No runtime invariant: Session validates each content-only rewrite and its companion owns cross-event enclosure. */
const install: InvariantInstaller = () => {}
/**
* Register this package's invariant companion.
* @param ctx - Cordis context carrying the invariant service.
* @returns the installed registration's disposer after setup succeeds.
*/
export const apply = (ctx: Context): Promise<() => void> =>
Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install))
/* jscpd:ignore-end */
@@ -0,0 +1,40 @@
import type { CallId } from '@deepseek-ai/dsh-llm'
/** Character-budget policy for deterministic tool-result pruning. */
export interface ToolResultPruneConfig {
/** Prune when total text exceeds this many Unicode code points. Defaults to `8192`. */
thresholdChars?: number
/** Maximum leading Unicode code points retained. Defaults to `4096`. */
headChars?: number
/** Maximum trailing Unicode code points retained. Defaults to `1024`. */
tailChars?: number
}
/** Validated, detached, deeply immutable pruning configuration. */
export interface ResolvedConfig {
readonly thresholdChars: number
readonly headChars: number
readonly tailChars: number
}
/** Provenance and size accounting for one landed surface replacement. */
export interface PrunedEntry {
/** Full-fidelity tool-result event shadowed by the replacement. */
readonly originalSeq: number
/** Newly appended pruned tool-result event. */
readonly replacementSeq: number
/** Tool call shared by the original and replacement. */
readonly callId: CallId
/** Original text size in Unicode code points. */
readonly charsBefore: number
/** Replacement text size in Unicode code points. */
readonly charsAfter: number
}
/** Aggregate outcome of one stable-surface pruning pass. */
export interface PruneResult {
/** Replacements in the snapshotted surface order. */
readonly pruned: readonly PrunedEntry[]
/** Total Unicode code points removed across replacements. */
readonly charsRemoved: number
}