dsh-context-compression-improved 0.5.1 → 0.5.3
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/.gitattributes +1 -0
- package/CHANGELOG.ja.md +144 -83
- package/CHANGELOG.ko.md +143 -82
- package/CHANGELOG.md +278 -212
- package/CHANGELOG.zh.md +131 -77
- package/docs/installation.md +103 -103
- package/docs/installation.zh.md +100 -100
- package/package.json +1 -1
- package/packages/selector/cordis.patch.yml +5 -6
- 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 +16 -234
- package/packages/selector/lib/pruner.d.ts +13 -248
- package/packages/selector/lib/pruner.js +148 -552
- package/packages/selector/src/client/EstimatorControls.tsx +0 -101
- package/packages/selector/src/client/index.ts +0 -17
- package/packages/selector/src/client/locales.ts +0 -38
- 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 +24 -271
- package/packages/selector/src/profiles.ts +4 -27
- package/packages/selector/src/pruner/state.ts +2 -25
- package/packages/selector/src/pruner.ts +75 -403
- 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-prompt.ts +188 -188
- package/packages/selector/src/runtime/tokenpilot/advisor-state.ts +149 -133
- package/packages/selector/src/runtime/tokenpilot/advisor.ts +419 -419
- package/packages/selector/src/runtime/tokenpilot/benefit.ts +200 -0
- package/packages/selector/src/runtime/types.ts +0 -17
- package/packages/selector/tests/advisor-report.host.spec.ts +223 -223
- package/packages/selector/tests/preset-options-write.client.spec.ts +7 -23
- package/packages/selector/tests/public/package-contract.client.spec.ts +20 -0
- package/packages/selector/tests/runtime/advice-never-withholds.host.spec.ts +232 -0
- package/packages/selector/tests/runtime/advisor-invariant.spec.ts +272 -272
- package/packages/selector/tests/runtime/advisor.spec.ts +226 -226
- package/packages/selector/tests/runtime/audit.spec.ts +35 -21
- package/packages/selector/tests/runtime/char-basis.spec.ts +30 -30
- 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 +45 -14
- package/scripts/toolclass-corpus-replay.mjs +281 -281
- 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
|
@@ -1,223 +1,223 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Host-side guard for the advisory advisor's HTTP report route.
|
|
3
|
-
*
|
|
4
|
-
* Pins the read-only contract: the route registers under both prefixes only
|
|
5
|
-
* when the row opts in, a session whose advisor never ran reports nulls and
|
|
6
|
-
* empty arrays (not an error), a populated session reports its decay figure
|
|
7
|
-
* and score distribution content-free, and every error path answers a
|
|
8
|
-
* precise status — 400 for a missing sessionId, 404 for an unknown session,
|
|
9
|
-
* 503 when no agents service can resolve sessions at all.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { Context } from '@deepseek-ai/cordis'
|
|
13
|
-
import { afterEach, describe, expect, it } from 'vitest'
|
|
14
|
-
import { apply } from '../src/index.ts'
|
|
15
|
-
import { getAdvisorState, recordScore, recordRecertified } from '../src/runtime/tokenpilot/advisor-state.ts'
|
|
16
|
-
|
|
17
|
-
const REPORT_ROUTE = '/api/dsh-context-compression-improved/advisor-report'
|
|
18
|
-
const LEGACY_REPORT_ROUTE = '/endpoint/dsh-context-compression-improved/advisor-report'
|
|
19
|
-
|
|
20
|
-
interface RegisteredRoute {
|
|
21
|
-
kind: string
|
|
22
|
-
path: string
|
|
23
|
-
handler: (req: unknown, res: unknown) => unknown
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
interface FakeResponse {
|
|
27
|
-
status?: number
|
|
28
|
-
body?: string
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let ctx: Context | undefined
|
|
32
|
-
|
|
33
|
-
afterEach(async () => {
|
|
34
|
-
await ctx?.fiber.dispose()
|
|
35
|
-
ctx = undefined
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
const settle = (): Promise<void> => new Promise(resolve => setTimeout(resolve, 20))
|
|
39
|
-
|
|
40
|
-
async function mountWebServer(runtime: Context, routes: RegisteredRoute[]): Promise<void> {
|
|
41
|
-
await runtime.plugin({
|
|
42
|
-
name: 'fake-webserver',
|
|
43
|
-
apply(webCtx) {
|
|
44
|
-
webCtx.provide('webServer', {
|
|
45
|
-
tables: { exact: new Map<string, RegisteredRoute>() },
|
|
46
|
-
register(this: { tables: { exact: Map<string, RegisteredRoute> } }, route: RegisteredRoute) {
|
|
47
|
-
const table = this.tables.exact
|
|
48
|
-
if (table.has(route.path)) {
|
|
49
|
-
throw new Error(`webserver: duplicate ${route.kind} route "${route.path}"`)
|
|
50
|
-
}
|
|
51
|
-
table.set(route.path, route)
|
|
52
|
-
routes.push(route)
|
|
53
|
-
return () => {}
|
|
54
|
-
},
|
|
55
|
-
})
|
|
56
|
-
},
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/** Mount an agents service that knows session 's1' (and nothing else). */
|
|
61
|
-
function mountAgents(runtime: Context): void {
|
|
62
|
-
void runtime.plugin({
|
|
63
|
-
name: 'fake-agents',
|
|
64
|
-
apply(serviceCtx) {
|
|
65
|
-
serviceCtx.provide('agents', {
|
|
66
|
-
get: (id: unknown) => {
|
|
67
|
-
if (id !== 's1') return undefined
|
|
68
|
-
const session = { id: 's1' }
|
|
69
|
-
const state = getAdvisorState(session as never)
|
|
70
|
-
state.summary = {
|
|
71
|
-
overallTask: 'migrate the auth module',
|
|
72
|
-
activeSubtasks: ['port login flow'],
|
|
73
|
-
keywords: ['auth'],
|
|
74
|
-
todoVersion: 'aaaa1111',
|
|
75
|
-
turn: 4,
|
|
76
|
-
}
|
|
77
|
-
state.lastDecay = { decay: 0.42, weightedChars: 10_000, turn: 4 }
|
|
78
|
-
recordScore(state, 3, { score: 0.95, turn: 4 })
|
|
79
|
-
recordScore(state, 5, { score: 0.10, turn: 4 })
|
|
80
|
-
recordRecertified(state, 5, 4)
|
|
81
|
-
return { session }
|
|
82
|
-
},
|
|
83
|
-
})
|
|
84
|
-
},
|
|
85
|
-
})
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async function invoke(route: RegisteredRoute, req?: unknown): Promise<FakeResponse> {
|
|
89
|
-
const captured: FakeResponse = {}
|
|
90
|
-
const res = {
|
|
91
|
-
writeHead(code: number) { captured.status = code },
|
|
92
|
-
end(body?: string) { if (body !== undefined) captured.body = body },
|
|
93
|
-
}
|
|
94
|
-
await route.handler(req ?? { method: 'GET' }, res)
|
|
95
|
-
await settle()
|
|
96
|
-
return captured
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
describe('advisor report route registration', () => {
|
|
100
|
-
it('registers both prefixes only when the row opts in', async () => {
|
|
101
|
-
const routes: RegisteredRoute[] = []
|
|
102
|
-
const runtime = new Context()
|
|
103
|
-
ctx = runtime
|
|
104
|
-
await mountWebServer(runtime, routes)
|
|
105
|
-
apply(runtime, { advisorReportRoute: true })
|
|
106
|
-
await settle()
|
|
107
|
-
const paths = routes.map(route => route.path)
|
|
108
|
-
expect(paths).toContain(REPORT_ROUTE)
|
|
109
|
-
expect(paths).toContain(LEGACY_REPORT_ROUTE)
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
it('registers nothing by default (advisor off adds zero behavior)', async () => {
|
|
113
|
-
const routes: RegisteredRoute[] = []
|
|
114
|
-
const runtime = new Context()
|
|
115
|
-
ctx = runtime
|
|
116
|
-
await mountWebServer(runtime, routes)
|
|
117
|
-
apply(runtime, {})
|
|
118
|
-
await settle()
|
|
119
|
-
expect(routes.map(route => route.path)).not.toContain(REPORT_ROUTE)
|
|
120
|
-
})
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
describe('advisor report route responses', () => {
|
|
124
|
-
async function mountedRoute(): Promise<RegisteredRoute> {
|
|
125
|
-
const routes: RegisteredRoute[] = []
|
|
126
|
-
const runtime = new Context()
|
|
127
|
-
ctx = runtime
|
|
128
|
-
await mountWebServer(runtime, routes)
|
|
129
|
-
apply(runtime, { advisorReportRoute: true })
|
|
130
|
-
await settle()
|
|
131
|
-
const route = routes.find(entry => entry.path === REPORT_ROUTE)
|
|
132
|
-
expect(route).toBeDefined()
|
|
133
|
-
return route as RegisteredRoute
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
it('answers 503 without an agents service', async () => {
|
|
137
|
-
const route = await mountedRoute()
|
|
138
|
-
const response = await invoke(route, { url: `${REPORT_ROUTE}?sessionId=s1` })
|
|
139
|
-
expect(response.status).toBe(503)
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
it('answers 404 for an unknown session and 400 for a missing sessionId', async () => {
|
|
143
|
-
const routes: RegisteredRoute[] = []
|
|
144
|
-
const runtime = new Context()
|
|
145
|
-
ctx = runtime
|
|
146
|
-
await mountWebServer(runtime, routes)
|
|
147
|
-
mountAgents(runtime)
|
|
148
|
-
apply(runtime, { advisorReportRoute: true })
|
|
149
|
-
await settle()
|
|
150
|
-
const route = routes.find(entry => entry.path === REPORT_ROUTE) as RegisteredRoute
|
|
151
|
-
|
|
152
|
-
const unknown = await invoke(route, { url: `${REPORT_ROUTE}?sessionId=other` })
|
|
153
|
-
expect(unknown.status).toBe(404)
|
|
154
|
-
|
|
155
|
-
const missing = await invoke(route, { url: REPORT_ROUTE })
|
|
156
|
-
expect(missing.status).toBe(400)
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
it('serves the decay figure, summary, and scores content-free', async () => {
|
|
160
|
-
const routes: RegisteredRoute[] = []
|
|
161
|
-
const runtime = new Context()
|
|
162
|
-
ctx = runtime
|
|
163
|
-
await mountWebServer(runtime, routes)
|
|
164
|
-
mountAgents(runtime)
|
|
165
|
-
apply(runtime, { advisorReportRoute: true })
|
|
166
|
-
await settle()
|
|
167
|
-
const route = routes.find(entry => entry.path === REPORT_ROUTE) as RegisteredRoute
|
|
168
|
-
|
|
169
|
-
const response = await invoke(route, { url: `${REPORT_ROUTE}?sessionId=s1` })
|
|
170
|
-
expect(response.status).toBe(200)
|
|
171
|
-
const body = JSON.parse(response.body ?? '{}') as {
|
|
172
|
-
ok: boolean
|
|
173
|
-
sessionId: string
|
|
174
|
-
advisor: {
|
|
175
|
-
summary: { overallTask: string } | null
|
|
176
|
-
decay: number | null
|
|
177
|
-
weightedChars: number | null
|
|
178
|
-
scores: { seq: number, score: number }[]
|
|
179
|
-
lowRelevanceSeqs: number[]
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
expect(body.ok).toBe(true)
|
|
183
|
-
expect(body.sessionId).toBe('s1')
|
|
184
|
-
expect(body.advisor.decay).toBeCloseTo(0.42, 12)
|
|
185
|
-
expect(body.advisor.summary?.overallTask).toBe('migrate the auth module')
|
|
186
|
-
expect(body.advisor.scores).toHaveLength(2)
|
|
187
|
-
expect(body.advisor.lowRelevanceSeqs).toEqual([5])
|
|
188
|
-
// Content-free: no message text ever rides along.
|
|
189
|
-
expect(response.body).not.toContain('"text"')
|
|
190
|
-
expect(response.body).not.toContain('"content"')
|
|
191
|
-
expect(response.body).not.toContain('apiKey')
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
it('answers an empty report (nulls, not an error) for a session whose advisor never ran', async () => {
|
|
195
|
-
const routes: RegisteredRoute[] = []
|
|
196
|
-
const runtime = new Context()
|
|
197
|
-
ctx = runtime
|
|
198
|
-
await mountWebServer(runtime, routes)
|
|
199
|
-
void runtime.plugin({
|
|
200
|
-
name: 'fake-agents-empty',
|
|
201
|
-
apply(serviceCtx) {
|
|
202
|
-
serviceCtx.provide('agents', {
|
|
203
|
-
get: (id: unknown) => (id === 's1' ? { session: { id: 's1' } } : undefined),
|
|
204
|
-
})
|
|
205
|
-
},
|
|
206
|
-
})
|
|
207
|
-
apply(runtime, { advisorReportRoute: true })
|
|
208
|
-
await settle()
|
|
209
|
-
const route = routes.find(entry => entry.path === REPORT_ROUTE) as RegisteredRoute
|
|
210
|
-
|
|
211
|
-
const response = await invoke(route, { url: `${REPORT_ROUTE}?sessionId=s1` })
|
|
212
|
-
expect(response.status).toBe(200)
|
|
213
|
-
const body = JSON.parse(response.body ?? '{}') as {
|
|
214
|
-
ok: boolean
|
|
215
|
-
advisor: { summary: unknown, decay: unknown, scores: unknown[], lowRelevanceSeqs: unknown[] }
|
|
216
|
-
}
|
|
217
|
-
expect(body.ok).toBe(true)
|
|
218
|
-
expect(body.advisor.summary).toBeNull()
|
|
219
|
-
expect(body.advisor.decay).toBeNull()
|
|
220
|
-
expect(body.advisor.scores).toEqual([])
|
|
221
|
-
expect(body.advisor.lowRelevanceSeqs).toEqual([])
|
|
222
|
-
})
|
|
223
|
-
})
|
|
1
|
+
/**
|
|
2
|
+
* Host-side guard for the advisory advisor's HTTP report route.
|
|
3
|
+
*
|
|
4
|
+
* Pins the read-only contract: the route registers under both prefixes only
|
|
5
|
+
* when the row opts in, a session whose advisor never ran reports nulls and
|
|
6
|
+
* empty arrays (not an error), a populated session reports its decay figure
|
|
7
|
+
* and score distribution content-free, and every error path answers a
|
|
8
|
+
* precise status — 400 for a missing sessionId, 404 for an unknown session,
|
|
9
|
+
* 503 when no agents service can resolve sessions at all.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { Context } from '@deepseek-ai/cordis'
|
|
13
|
+
import { afterEach, describe, expect, it } from 'vitest'
|
|
14
|
+
import { apply } from '../src/index.ts'
|
|
15
|
+
import { getAdvisorState, recordScore, recordRecertified } from '../src/runtime/tokenpilot/advisor-state.ts'
|
|
16
|
+
|
|
17
|
+
const REPORT_ROUTE = '/api/dsh-context-compression-improved/advisor-report'
|
|
18
|
+
const LEGACY_REPORT_ROUTE = '/endpoint/dsh-context-compression-improved/advisor-report'
|
|
19
|
+
|
|
20
|
+
interface RegisteredRoute {
|
|
21
|
+
kind: string
|
|
22
|
+
path: string
|
|
23
|
+
handler: (req: unknown, res: unknown) => unknown
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface FakeResponse {
|
|
27
|
+
status?: number
|
|
28
|
+
body?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let ctx: Context | undefined
|
|
32
|
+
|
|
33
|
+
afterEach(async () => {
|
|
34
|
+
await ctx?.fiber.dispose()
|
|
35
|
+
ctx = undefined
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const settle = (): Promise<void> => new Promise(resolve => setTimeout(resolve, 20))
|
|
39
|
+
|
|
40
|
+
async function mountWebServer(runtime: Context, routes: RegisteredRoute[]): Promise<void> {
|
|
41
|
+
await runtime.plugin({
|
|
42
|
+
name: 'fake-webserver',
|
|
43
|
+
apply(webCtx) {
|
|
44
|
+
webCtx.provide('webServer', {
|
|
45
|
+
tables: { exact: new Map<string, RegisteredRoute>() },
|
|
46
|
+
register(this: { tables: { exact: Map<string, RegisteredRoute> } }, route: RegisteredRoute) {
|
|
47
|
+
const table = this.tables.exact
|
|
48
|
+
if (table.has(route.path)) {
|
|
49
|
+
throw new Error(`webserver: duplicate ${route.kind} route "${route.path}"`)
|
|
50
|
+
}
|
|
51
|
+
table.set(route.path, route)
|
|
52
|
+
routes.push(route)
|
|
53
|
+
return () => {}
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
},
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Mount an agents service that knows session 's1' (and nothing else). */
|
|
61
|
+
function mountAgents(runtime: Context): void {
|
|
62
|
+
void runtime.plugin({
|
|
63
|
+
name: 'fake-agents',
|
|
64
|
+
apply(serviceCtx) {
|
|
65
|
+
serviceCtx.provide('agents', {
|
|
66
|
+
get: (id: unknown) => {
|
|
67
|
+
if (id !== 's1') return undefined
|
|
68
|
+
const session = { id: 's1' }
|
|
69
|
+
const state = getAdvisorState(session as never)
|
|
70
|
+
state.summary = {
|
|
71
|
+
overallTask: 'migrate the auth module',
|
|
72
|
+
activeSubtasks: ['port login flow'],
|
|
73
|
+
keywords: ['auth'],
|
|
74
|
+
todoVersion: 'aaaa1111',
|
|
75
|
+
turn: 4,
|
|
76
|
+
}
|
|
77
|
+
state.lastDecay = { decay: 0.42, weightedChars: 10_000, turn: 4 }
|
|
78
|
+
recordScore(state, 3, { score: 0.95, turn: 4 })
|
|
79
|
+
recordScore(state, 5, { score: 0.10, turn: 4 })
|
|
80
|
+
recordRecertified(state, 5, 4)
|
|
81
|
+
return { session }
|
|
82
|
+
},
|
|
83
|
+
})
|
|
84
|
+
},
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function invoke(route: RegisteredRoute, req?: unknown): Promise<FakeResponse> {
|
|
89
|
+
const captured: FakeResponse = {}
|
|
90
|
+
const res = {
|
|
91
|
+
writeHead(code: number) { captured.status = code },
|
|
92
|
+
end(body?: string) { if (body !== undefined) captured.body = body },
|
|
93
|
+
}
|
|
94
|
+
await route.handler(req ?? { method: 'GET' }, res)
|
|
95
|
+
await settle()
|
|
96
|
+
return captured
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
describe('advisor report route registration', () => {
|
|
100
|
+
it('registers both prefixes only when the row opts in', async () => {
|
|
101
|
+
const routes: RegisteredRoute[] = []
|
|
102
|
+
const runtime = new Context()
|
|
103
|
+
ctx = runtime
|
|
104
|
+
await mountWebServer(runtime, routes)
|
|
105
|
+
apply(runtime, { advisorReportRoute: true })
|
|
106
|
+
await settle()
|
|
107
|
+
const paths = routes.map(route => route.path)
|
|
108
|
+
expect(paths).toContain(REPORT_ROUTE)
|
|
109
|
+
expect(paths).toContain(LEGACY_REPORT_ROUTE)
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('registers nothing by default (advisor off adds zero behavior)', async () => {
|
|
113
|
+
const routes: RegisteredRoute[] = []
|
|
114
|
+
const runtime = new Context()
|
|
115
|
+
ctx = runtime
|
|
116
|
+
await mountWebServer(runtime, routes)
|
|
117
|
+
apply(runtime, {})
|
|
118
|
+
await settle()
|
|
119
|
+
expect(routes.map(route => route.path)).not.toContain(REPORT_ROUTE)
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
describe('advisor report route responses', () => {
|
|
124
|
+
async function mountedRoute(): Promise<RegisteredRoute> {
|
|
125
|
+
const routes: RegisteredRoute[] = []
|
|
126
|
+
const runtime = new Context()
|
|
127
|
+
ctx = runtime
|
|
128
|
+
await mountWebServer(runtime, routes)
|
|
129
|
+
apply(runtime, { advisorReportRoute: true })
|
|
130
|
+
await settle()
|
|
131
|
+
const route = routes.find(entry => entry.path === REPORT_ROUTE)
|
|
132
|
+
expect(route).toBeDefined()
|
|
133
|
+
return route as RegisteredRoute
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
it('answers 503 without an agents service', async () => {
|
|
137
|
+
const route = await mountedRoute()
|
|
138
|
+
const response = await invoke(route, { url: `${REPORT_ROUTE}?sessionId=s1` })
|
|
139
|
+
expect(response.status).toBe(503)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('answers 404 for an unknown session and 400 for a missing sessionId', async () => {
|
|
143
|
+
const routes: RegisteredRoute[] = []
|
|
144
|
+
const runtime = new Context()
|
|
145
|
+
ctx = runtime
|
|
146
|
+
await mountWebServer(runtime, routes)
|
|
147
|
+
mountAgents(runtime)
|
|
148
|
+
apply(runtime, { advisorReportRoute: true })
|
|
149
|
+
await settle()
|
|
150
|
+
const route = routes.find(entry => entry.path === REPORT_ROUTE) as RegisteredRoute
|
|
151
|
+
|
|
152
|
+
const unknown = await invoke(route, { url: `${REPORT_ROUTE}?sessionId=other` })
|
|
153
|
+
expect(unknown.status).toBe(404)
|
|
154
|
+
|
|
155
|
+
const missing = await invoke(route, { url: REPORT_ROUTE })
|
|
156
|
+
expect(missing.status).toBe(400)
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it('serves the decay figure, summary, and scores content-free', async () => {
|
|
160
|
+
const routes: RegisteredRoute[] = []
|
|
161
|
+
const runtime = new Context()
|
|
162
|
+
ctx = runtime
|
|
163
|
+
await mountWebServer(runtime, routes)
|
|
164
|
+
mountAgents(runtime)
|
|
165
|
+
apply(runtime, { advisorReportRoute: true })
|
|
166
|
+
await settle()
|
|
167
|
+
const route = routes.find(entry => entry.path === REPORT_ROUTE) as RegisteredRoute
|
|
168
|
+
|
|
169
|
+
const response = await invoke(route, { url: `${REPORT_ROUTE}?sessionId=s1` })
|
|
170
|
+
expect(response.status).toBe(200)
|
|
171
|
+
const body = JSON.parse(response.body ?? '{}') as {
|
|
172
|
+
ok: boolean
|
|
173
|
+
sessionId: string
|
|
174
|
+
advisor: {
|
|
175
|
+
summary: { overallTask: string } | null
|
|
176
|
+
decay: number | null
|
|
177
|
+
weightedChars: number | null
|
|
178
|
+
scores: { seq: number, score: number }[]
|
|
179
|
+
lowRelevanceSeqs: number[]
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
expect(body.ok).toBe(true)
|
|
183
|
+
expect(body.sessionId).toBe('s1')
|
|
184
|
+
expect(body.advisor.decay).toBeCloseTo(0.42, 12)
|
|
185
|
+
expect(body.advisor.summary?.overallTask).toBe('migrate the auth module')
|
|
186
|
+
expect(body.advisor.scores).toHaveLength(2)
|
|
187
|
+
expect(body.advisor.lowRelevanceSeqs).toEqual([5])
|
|
188
|
+
// Content-free: no message text ever rides along.
|
|
189
|
+
expect(response.body).not.toContain('"text"')
|
|
190
|
+
expect(response.body).not.toContain('"content"')
|
|
191
|
+
expect(response.body).not.toContain('apiKey')
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
it('answers an empty report (nulls, not an error) for a session whose advisor never ran', async () => {
|
|
195
|
+
const routes: RegisteredRoute[] = []
|
|
196
|
+
const runtime = new Context()
|
|
197
|
+
ctx = runtime
|
|
198
|
+
await mountWebServer(runtime, routes)
|
|
199
|
+
void runtime.plugin({
|
|
200
|
+
name: 'fake-agents-empty',
|
|
201
|
+
apply(serviceCtx) {
|
|
202
|
+
serviceCtx.provide('agents', {
|
|
203
|
+
get: (id: unknown) => (id === 's1' ? { session: { id: 's1' } } : undefined),
|
|
204
|
+
})
|
|
205
|
+
},
|
|
206
|
+
})
|
|
207
|
+
apply(runtime, { advisorReportRoute: true })
|
|
208
|
+
await settle()
|
|
209
|
+
const route = routes.find(entry => entry.path === REPORT_ROUTE) as RegisteredRoute
|
|
210
|
+
|
|
211
|
+
const response = await invoke(route, { url: `${REPORT_ROUTE}?sessionId=s1` })
|
|
212
|
+
expect(response.status).toBe(200)
|
|
213
|
+
const body = JSON.parse(response.body ?? '{}') as {
|
|
214
|
+
ok: boolean
|
|
215
|
+
advisor: { summary: unknown, decay: unknown, scores: unknown[], lowRelevanceSeqs: unknown[] }
|
|
216
|
+
}
|
|
217
|
+
expect(body.ok).toBe(true)
|
|
218
|
+
expect(body.advisor.summary).toBeNull()
|
|
219
|
+
expect(body.advisor.decay).toBeNull()
|
|
220
|
+
expect(body.advisor.scores).toEqual([])
|
|
221
|
+
expect(body.advisor.lowRelevanceSeqs).toEqual([])
|
|
222
|
+
})
|
|
223
|
+
})
|
|
@@ -148,35 +148,19 @@ describe('presetOptions writes are path-addressed', () => {
|
|
|
148
148
|
expect(writes).toEqual([[{ op: 'set', path: ['presetOptions', 'estimatorProvider'], value: 'local-35b' }]])
|
|
149
149
|
})
|
|
150
150
|
|
|
151
|
-
it('
|
|
151
|
+
it('treats a retired review-gate patch as a no-op instead of a write', async () => {
|
|
152
152
|
const { injected, writes, snapshot } = bindInjected({ estimatorMode: 'host' })
|
|
153
|
+
// The patch surface no longer carries these keys, and the decoders accept
|
|
154
|
+
// them only so a legacy document keeps loading. Cast past the removed type
|
|
155
|
+
// so the test pins the RUNTIME behaviour: nothing is written.
|
|
153
156
|
await injected.savePresetOptions({
|
|
154
157
|
reviewMode: true,
|
|
155
158
|
reviewTimeoutTurns: 8,
|
|
156
159
|
cacheHitDiscountAlpha: 0.2,
|
|
157
160
|
reviewHighImpactTokens: 6000,
|
|
158
|
-
})
|
|
159
|
-
expect(
|
|
160
|
-
|
|
161
|
-
reviewMode: true,
|
|
162
|
-
reviewTimeoutTurns: 8,
|
|
163
|
-
cacheHitDiscountAlpha: 0.2,
|
|
164
|
-
reviewHighImpactTokens: 6000,
|
|
165
|
-
})
|
|
166
|
-
await injected.savePresetOptions({ reviewMode: undefined })
|
|
167
|
-
expect(snapshot()['presetOptions']).toEqual({
|
|
168
|
-
estimatorMode: 'host',
|
|
169
|
-
reviewTimeoutTurns: 8,
|
|
170
|
-
cacheHitDiscountAlpha: 0.2,
|
|
171
|
-
reviewHighImpactTokens: 6000,
|
|
172
|
-
})
|
|
173
|
-
for (const batch of writes) {
|
|
174
|
-
for (const op of batch) {
|
|
175
|
-
expect(op.path).toEqual(['presetOptions', op.path[1] ?? ''])
|
|
176
|
-
expect(['reviewMode', 'reviewTimeoutTurns', 'cacheHitDiscountAlpha', 'reviewHighImpactTokens'])
|
|
177
|
-
.toContain(op.path[1])
|
|
178
|
-
}
|
|
179
|
-
}
|
|
161
|
+
} as unknown as Parameters<typeof injected.savePresetOptions>[0])
|
|
162
|
+
expect(writes).toEqual([])
|
|
163
|
+
expect(snapshot()['presetOptions']).toEqual({ estimatorMode: 'host' })
|
|
180
164
|
})
|
|
181
165
|
|
|
182
166
|
it('never replaces the whole section, so sibling overrides survive', async () => {
|
|
@@ -55,4 +55,24 @@ describe('standalone package contract', () => {
|
|
|
55
55
|
expect(patch).toContain("name: 'dsh-context-compression-improved'")
|
|
56
56
|
expect(patch).not.toContain('@deepseek-ai/dsh-client-ui-context-compression-selector')
|
|
57
57
|
})
|
|
58
|
+
|
|
59
|
+
it('never ships a retired plugin config key in the Bundle patch', () => {
|
|
60
|
+
// Negative control: the patch is loaded by the host and validated against
|
|
61
|
+
// the plugin's own Config schema, but nothing tied the two together — so
|
|
62
|
+
// the retired review gate's `reviewQueueRoute` survived in this file after
|
|
63
|
+
// the key was removed from the schema, advertising a route that can never
|
|
64
|
+
// register. A retired key must fail here instead of shipping quietly.
|
|
65
|
+
//
|
|
66
|
+
// The pin is on KEY-SETTING lines, not on the whole document: the comments
|
|
67
|
+
// above the rows deliberately name the retired key while explaining why it
|
|
68
|
+
// is gone, and prose must not be mistaken for configuration.
|
|
69
|
+
const patch = readFileSync(resolve(root, 'selector/cordis.patch.yml'), 'utf8')
|
|
70
|
+
const lines = patch.split('\n')
|
|
71
|
+
for (const retired of ['reviewQueueRoute', 'reviewMode', 'reviewTimeoutTurns', 'reviewHighImpactTokens']) {
|
|
72
|
+
const setsRetired = lines.find(line => new RegExp(`^\\s*${retired}\\s*:`).test(line))
|
|
73
|
+
expect(setsRetired, `${retired} is still set in the Bundle patch`).toBeUndefined()
|
|
74
|
+
}
|
|
75
|
+
// And the live flag the routes row exists for is still wired.
|
|
76
|
+
expect(patch).toContain('estimatorCatalogRoute: true')
|
|
77
|
+
})
|
|
58
78
|
})
|