Merge remote-tracking branch 'origin/master' into worktree/pr628-merge-20260727

# Conflicts:
#	.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.md
#	docs/architecture.i18n.yaml
#	docs/config-catalog.md
#	docs/cordis-catalog/events.md
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/llm-streaming.i18n.yaml
#	docs/core-data-structures/llm-streaming.md
#	docs/core-data-structures/llm-streaming.zh.md
#	docs/event-producer-consumer.md
#	docs/module-graph.md
#	examples/headless-agent/tests/headless.snapshot.ts
#	packages/compact/compact-basic/tests/compact-loop-repro.spec.ts
#	packages/cordis/tool-cordis/src/api-catalog.ts
#	packages/core/agent-loop/README.md
#	packages/core/agent-loop/src/loop.ts
#	packages/examples/agent-spine-demo/README.md
#	packages/llm/README.md
#	packages/llm/llm-deepseek/src/adapter.ts
#	packages/llm/llm-pi-ai/src/adapter.ts
#	packages/llm/llm-retry/README.md
#	packages/llm/llm/README.md
#	packages/llm/llm/src/index.ts
#	packages/llm/llm/tests/service.spec.ts
#	packages/support/llm-replay/src/index.ts
#	packages/support/llm-replay/tests/llm-replay.spec.ts
This commit is contained in:
Tianyi Cui
2026-07-27 22:44:43 +08:00
2019 changed files with 66577 additions and 16794 deletions

View File

@@ -16,7 +16,7 @@ import type {
ContentBlock,
GenerateOptions,
LlmFailure,
LlmModelContext,
LlmResolvedModelInfo,
Message,
StreamChunk,
} from '@deepseek-ai/dsh-llm'
@@ -33,8 +33,13 @@ class ContextAdapter extends LlmAdapter {
super()
}
override resolveModelContext(): Promise<LlmModelContext> {
return Promise.resolve({ contextWindow: this.contextWindow })
override resolveModel(provider: string, model: string): Promise<LlmResolvedModelInfo> {
return Promise.resolve({
provider,
id: model,
name: model,
context: { contextWindow: this.contextWindow },
})
}
override async * stream(): AsyncIterable<StreamChunk> {
@@ -47,9 +52,14 @@ class RoutedContextAdapter extends LlmAdapter {
super()
}
override resolveModelContext(provider: string): Promise<LlmModelContext | undefined> {
override resolveModel(provider: string, model: string): Promise<LlmResolvedModelInfo> {
const contextWindow = this.windows[provider]
return Promise.resolve(contextWindow === undefined ? undefined : { contextWindow })
return Promise.resolve({
provider,
id: model,
name: model,
...contextWindow === undefined ? {} : { context: { contextWindow } },
})
}
override async * stream(): AsyncIterable<StreamChunk> {
@@ -453,6 +463,18 @@ describe('pressure measurement and retention', () => {
.resolves.not.toBeNull()
})
it('forwards turn cancellation to proactive model metadata resolution', async () => {
const ctx = createContext()
const resolveModelInfo = vi.spyOn(ctx.llm, 'resolveModelInfo')
const compact = service(compactConfig, ctx)
const session = conversation()
const signal = new AbortController().signal
await expect(compact.compactIfNeeded(agent(session, MODEL), 'pressure', signal))
.resolves.not.toBeNull()
expect(resolveModelInfo).toHaveBeenCalledWith(MODEL, MODEL, signal)
})
it('re-resolves capacity after a same-model-id provider switch in one session', async () => {
const ctx = new Context()
void new LlmService(ctx)
@@ -485,7 +507,11 @@ describe('pressure measurement and retention', () => {
void new LlmService(ctx)
void new TokenMeterService(ctx)
ctx.llm.registerAdapter(['unknown-context'], new ContextAdapter(1_000))
vi.spyOn(ctx.llm, 'resolveModelContext').mockResolvedValue(undefined)
vi.spyOn(ctx.llm, 'resolveModelInfo').mockImplementation((provider, model) => Promise.resolve({
provider,
id: model,
name: model,
}))
const compact = service(compactConfig, ctx)
const session = conversation(4)
session.append('request/header', {
@@ -1337,7 +1363,11 @@ describe('automatic listener and loader composition', () => {
const ctx = createContext()
const warnings: string[] = []
ctx.logger.warn = ((message: string) => void warnings.push(message)) as typeof ctx.logger.warn
vi.spyOn(ctx.llm, 'resolveModelContext').mockResolvedValue(undefined)
vi.spyOn(ctx.llm, 'resolveModelInfo').mockImplementation((provider, model) => Promise.resolve({
provider,
id: model,
name: model,
}))
void new TestCompactService(ctx, {
thresholdRatio: 0.5,
retainTokens: 180,