Merge latest master into tui-staging-merge-1

This commit is contained in:
Tianyi Cui
2026-07-22 20:45:24 +08:00
392 changed files with 33687 additions and 446 deletions

View File

@@ -38,7 +38,7 @@ The plugin registers the single provider route `deepseek`. A request selects it
## App attribution
Every request carries the shared attribution header from dsh-llm's `attributionHeaders()` - the mandatory `User-Agent` baseline identifying the harness (see [dsh-llm § App attribution](../llm/README.md#app-attribution-attributionts)). Direct DeepSeek requests and OpenAI-compatible gateway requests get no provider-specific app-attribution headers under this adapter contract; OpenRouter app attribution is deferred to a future explicit OpenRouter adapter or mode.
Every request carries the shared attribution header from dsh-llm's `attributionHeaders()` - the mandatory `User-Agent` baseline identifying the harness (see [dsh-llm § App attribution](../llm/README.md#app-attribution-attributionts)). Direct DeepSeek requests and OpenAI-compatible gateway requests get no provider-specific app-attribution headers under this adapter contract; OpenRouter app attribution is deferred to a future explicit OpenRouter adapter or mode. A request whose `GenerateOptions.purpose` is `compaction` (dsh-compact-basic's auxiliary summarization call) additionally carries `x-deepseek-harness-compact: 1`, so the host can separate compaction traffic from conversation requests.
## Wire-format notes (verified live + against the official docs)

View File

@@ -182,6 +182,9 @@ export class DeepSeekAdapter extends LlmAdapter {
...options.sessionId !== undefined
? { 'x-deepseek-harness-session-id': String(options.sessionId) }
: {},
...options.purpose === 'compaction'
? { 'x-deepseek-harness-compact': '1' }
: {},
}
// TODO(http): adopt the Cordis HTTP service when shared transport configuration

View File

@@ -129,6 +129,7 @@ describe('DeepSeekAdapter against a mock server', () => {
expect(server.headers[0]).not.toHaveProperty('http-referer')
expect(server.headers[0]).not.toHaveProperty('x-openrouter-title')
expect(server.headers[0]).not.toHaveProperty('x-openrouter-categories')
expect(server.headers[0]).not.toHaveProperty('x-deepseek-harness-compact')
})
it('streams raw chunks through ctx.llm.stream', async () => {
@@ -159,6 +160,19 @@ describe('DeepSeekAdapter against a mock server', () => {
expect(server.headers[0]?.['x-deepseek-harness-session-id']).toBe('child-session')
})
it('marks the auxiliary compaction call on the wire', async () => {
const server = await mockServer([{ kind: 'sse', events: textEvents }])
const ctx = await harness(server.url)
await assemble(ctx, {
model: 'deepseek-v4-flash',
messages: [{ role: 'user', content: [{ type: 'text', text: 'hi' }] }],
purpose: 'compaction',
})
expect(server.headers[0]?.['x-deepseek-harness-compact']).toBe('1')
})
it('forwards thinking config onto the wire', async () => {
const server = await mockServer([{ kind: 'sse', events: textEvents }])
const ctx = await harness(server.url, { thinking: 'disabled', reasoningEffort: 'high' })

View File

@@ -84,7 +84,10 @@ async function loadYaml(lines: readonly string[]): Promise<Context> {
}
describe('real Loader composition', () => {
it('loads the flat policy and records recovery through the shipping loop', async () => {
// Real-Loader composition resolves workspace packages through tsx at test
// time; first resolution after the host/client program split is slow enough
// to trip the default 5s budget on cold caches.
it('loads the flat policy and records recovery through the shipping loop', { timeout: 60_000 }, async () => {
const loaded = await loadYaml([
"- name: '@deepseek-ai/dsh-llm'",
"- name: '@deepseek-ai/dsh-session'",

View File

@@ -15,12 +15,21 @@
"types": "./lib/types/invariant.d.ts",
"default": "./lib/invariant.js"
},
"./types": {
"types": "./lib/types/types.d.ts",
"default": "./lib/types/types.js"
},
"./brand": {
"types": "./lib/types/brand.d.ts",
"default": "./lib/types/brand.js"
},
"./src/*": "./src/*",
"./package.json": "./package.json"
},
"files": [
"lib/index.js",
"lib/invariant.js",
"lib/types/**/*.js",
"lib/types/**/*.d.ts",
"lib/types/**/*.d.ts.map",
"src"

View File

@@ -226,4 +226,10 @@ export interface GenerateOptions {
* it; replay uses it to keep concurrent parent and child cursors independent.
*/
sessionId?: Branded<'SessionId'>
/**
* Provider-neutral classification for an auxiliary model call. Adapters may
* map the purpose to model-hidden transport metadata. Ordinary conversation
* requests leave it unset.
*/
purpose?: 'compaction'
}