Merge remote-tracking branch 'origin/master' into feat/send-unify
# Conflicts: # docs/persistence-catalog.md # examples/acp-agent/tests/snapshots/code-mode-workspace-context/session.jsonl # examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/session.jsonl # examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/stdout.expected.jsonl # packages/context/time-context/tests/time-context.spec.ts # packages/cordis/tool-cordis/src/api-catalog.ts
This commit is contained in:
@@ -5,7 +5,7 @@ import { CallId, LlmAdapter } from '@deepseek-ai/dsh-llm'
|
||||
import type { GenerateOptions, StreamChunk } from '@deepseek-ai/dsh-llm'
|
||||
import { Session, SessionId, type SessionEvent } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { agentEvents, AgentMessageId, type Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { defineTool } from '@deepseek-ai/dsh-tools'
|
||||
import { defineContentToolFixture } from '@deepseek-ai/dsh-tools'
|
||||
import AgentLoop from '@deepseek-ai/dsh-agent-loop'
|
||||
import { mountAgentLoopTestDependencies } from '@deepseek-ai/dsh-agent-loop-testkit'
|
||||
import * as timeContext from '@deepseek-ai/dsh-time-context'
|
||||
@@ -388,7 +388,7 @@ describe('real agent-loop request history', () => {
|
||||
it('persists one ordered context per request, accumulates readings, and leaves system headers unchanged', async () => {
|
||||
const adapter = new ScriptedAdapter([toolCallResponse(), textResponse('done')])
|
||||
const ctx = await loopHarness(adapter)
|
||||
ctx.tools.register(defineTool({
|
||||
ctx.tools.register(defineContentToolFixture({
|
||||
name: 'tick',
|
||||
description: 'advance fake time',
|
||||
parameters: {},
|
||||
|
||||
@@ -129,8 +129,7 @@ export function apply(ctx: Context, config: Config): void {
|
||||
if (update === undefined) return downstream
|
||||
pendingVersionUpdates.set(exec.token, update.versionUpdates)
|
||||
return {
|
||||
kind: 'accept',
|
||||
...downstream.content !== undefined ? { content: downstream.content } : {},
|
||||
...downstream,
|
||||
additionalContexts: [update.context, ...downstream.additionalContexts ?? []],
|
||||
}
|
||||
})
|
||||
|
||||
@@ -22,8 +22,11 @@ import type {
|
||||
} from '@deepseek-ai/dsh-fs'
|
||||
import LocalFileSystem from '@deepseek-ai/dsh-fs-local'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRegistry, { defineTool } from '@deepseek-ai/dsh-tools'
|
||||
import type { ToolExecution, ToolExecutionToken } from '@deepseek-ai/dsh-tools'
|
||||
import ToolRegistry, { defineContentToolFixture } from '@deepseek-ai/dsh-tools'
|
||||
import type {
|
||||
ToolExecution,
|
||||
ToolExecutionToken,
|
||||
} from '@deepseek-ai/dsh-tools'
|
||||
import * as ToolFs from '@deepseek-ai/dsh-tool-fs'
|
||||
import {
|
||||
discoverBaselineInstructionFiles,
|
||||
@@ -866,6 +869,7 @@ describe('workspace context request injection', () => {
|
||||
agent: stubAgent('/virtual/repo'),
|
||||
}), {
|
||||
isError: false,
|
||||
value: null,
|
||||
content: [{ type: 'text', text: 'file content' }],
|
||||
}, async () => ({
|
||||
kind: 'accept',
|
||||
@@ -902,7 +906,8 @@ describe('workspace context request injection', () => {
|
||||
agent,
|
||||
})
|
||||
const result = {
|
||||
isError: false,
|
||||
isError: false as const,
|
||||
value: null,
|
||||
content: [{ type: 'text' as const, text: 'hello' }],
|
||||
}
|
||||
|
||||
@@ -1701,7 +1706,7 @@ describe('dynamic nested workspace context injection', () => {
|
||||
await ctx.plugin(AgentLoop, { agents: [] })
|
||||
ctx.llm.registerAdapter(['mock'], adapter)
|
||||
const agent = ctx.agentLoop.create(SessionId('workspace-context-abort'), { provider: 'mock', model: 'mock' }, { cwd: root })
|
||||
ctx.tools.register(defineTool({
|
||||
ctx.tools.register(defineContentToolFixture({
|
||||
name: 'abort_step',
|
||||
description: 'Abort the current test step.',
|
||||
parameters: {},
|
||||
@@ -1772,6 +1777,7 @@ describe('dynamic nested workspace context injection', () => {
|
||||
const pending = ctx.waterfall('tools/post-execute', exec, {
|
||||
content: [{ type: 'text', text: 'ok' }],
|
||||
isError: false,
|
||||
value: null,
|
||||
}, () => Promise.resolve({ kind: 'accept' as const }))
|
||||
|
||||
await expect(pending).rejects.toBe(reason)
|
||||
@@ -2776,7 +2782,8 @@ describe('dynamic nested workspace context injection', () => {
|
||||
const result = {
|
||||
callId: CallId('provider-probe-result'),
|
||||
content: [{ type: 'text' as const, text: 'ok' }],
|
||||
isError: false,
|
||||
isError: false as const,
|
||||
value: null,
|
||||
}
|
||||
|
||||
const failedStat = await ctx.waterfall('tools/post-execute', stubToolExecution({
|
||||
@@ -2836,7 +2843,7 @@ describe('dynamic nested workspace context injection', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('preserves nested and downstream post-execute contexts as separate entries', async () => {
|
||||
it('preserves a downstream canonical value replacement and keeps contexts separate', async () => {
|
||||
const root = await tempRepo()
|
||||
const home = await tempRepo()
|
||||
try {
|
||||
@@ -2847,7 +2854,12 @@ describe('dynamic nested workspace context injection', () => {
|
||||
await mountFileToolsAndWorkspaceContext(ctx, { dshHome: home, maxBytes: 65536 })
|
||||
ctx.on('tools/post-execute', async () => ({
|
||||
kind: 'accept' as const,
|
||||
content: [{ type: 'text' as const, text: 'downstream replacement' }],
|
||||
value: {
|
||||
path: 'pkg/deep/file.txt',
|
||||
offset: 1,
|
||||
lines: [{ number: 1, text: 'downstream replacement' }],
|
||||
totalLines: 1,
|
||||
},
|
||||
additionalContexts: [{
|
||||
content: [{ type: 'text' as const, text: 'downstream context' }],
|
||||
source: { kind: 'plugin' as const, plugin: 'downstream' },
|
||||
@@ -2862,7 +2874,15 @@ describe('dynamic nested workspace context injection', () => {
|
||||
agent: stubAgent(root),
|
||||
})
|
||||
|
||||
expect(blocksText(result.content)).toBe('downstream replacement')
|
||||
expect(result.isError).toBe(false)
|
||||
if (result.isError) throw new Error('expected read replacement success')
|
||||
expect(result.value).toEqual({
|
||||
path: 'pkg/deep/file.txt',
|
||||
offset: 1,
|
||||
lines: [{ number: 1, text: 'downstream replacement' }],
|
||||
totalLines: 1,
|
||||
})
|
||||
expect(blocksText(result.content)).toContain('downstream replacement')
|
||||
expect(result.additionalContexts).toHaveLength(2)
|
||||
expect(workspaceContextOf(result)?.source).toEqual({ kind: 'plugin', plugin: 'workspace-context' })
|
||||
expect(workspaceContextOf(result)?.meta).toMatchObject({
|
||||
@@ -2979,7 +2999,7 @@ describe('dynamic nested workspace context injection', () => {
|
||||
await ctx.plugin(ToolRegistry)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: '/' })
|
||||
await ctx.plugin(ToolFs)
|
||||
ctx.tools.register(defineTool({
|
||||
ctx.tools.register(defineContentToolFixture({
|
||||
name: 'composite-read',
|
||||
description: 'read through a nested dispatch',
|
||||
parameters: {},
|
||||
@@ -3034,7 +3054,7 @@ describe('dynamic nested workspace context injection', () => {
|
||||
await ctx.plugin(workspaceContext, { maxBytes: 65536 })
|
||||
const agent = stubAgent('/')
|
||||
const parent = Symbol('parent') as ToolExecutionToken
|
||||
const plainResult = { callId: CallId('plain'), content: [], isError: false }
|
||||
const plainResult = { callId: CallId('plain'), content: [], isError: false as const, value: null }
|
||||
|
||||
ctx.emit('tools/result', stubToolExecution({
|
||||
signal: testToolSignal,
|
||||
@@ -3076,7 +3096,8 @@ describe('dynamic nested workspace context injection', () => {
|
||||
const result = {
|
||||
callId: CallId('manual'),
|
||||
content: [{ type: 'text' as const, text: 'manual result' }],
|
||||
isError: false,
|
||||
isError: false as const,
|
||||
value: null,
|
||||
}
|
||||
const cases = [
|
||||
{ name: 'read', arguments: { file_path: join('pkg', 'deep', 'file.txt') }, agent: undefined },
|
||||
|
||||
Reference in New Issue
Block a user