Merge remote-tracking branch 'origin/master' into xtr/agent-loop-message-machine

This commit is contained in:
_Kerman
2026-07-26 23:23:18 +08:00
98 changed files with 3489 additions and 551 deletions

View File

@@ -60,6 +60,7 @@
"@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^",
"@deepseek-ai/dsh-system-prompt": "workspace:^",
"@deepseek-ai/dsh-tasks": "workspace:^",
"@deepseek-ai/dsh-tasks-local": "workspace:^",
"@deepseek-ai/dsh-tool-tasks": "workspace:^",
"@deepseek-ai/dsh-tools": "workspace:^",
"@deepseek-ai/dsh-user-approval": "workspace:^",

View File

@@ -535,7 +535,7 @@ export function apply(ctx: Context, config: Config = {}): void {
if (tasks === undefined) {
throw new Error('background tasks unavailable: load @deepseek-ai/dsh-tasks and @deepseek-ai/dsh-tool-tasks')
}
// The caller owns cancellation until TaskService commits detached ownership.
// The caller owns cancellation until ctx.tasks commits detached ownership.
if (exec.signal.aborted) {
const error = new HarnessError('tool call aborted', TOOL_ABORTED)
error.name = 'AbortError'

View File

@@ -8,7 +8,7 @@ import SessionPersistenceJsonl from '@deepseek-ai/dsh-session-persistence-jsonl'
import type { Agent } from '@deepseek-ai/dsh-agent'
import AgentLoop from '@deepseek-ai/dsh-agent-loop'
import { mountAgentLoopTestDependencies } from '@deepseek-ai/dsh-agent-loop-testkit'
import TaskService from '@deepseek-ai/dsh-tasks'
import LocalTaskService from '@deepseek-ai/dsh-tasks-local'
import * as ToolTasks from '@deepseek-ai/dsh-tool-tasks'
import { LocalBashExecutor } from '@deepseek-ai/dsh-bash-local'
import * as ToolBash from '@deepseek-ai/dsh-tool-bash'
@@ -27,7 +27,7 @@ async function harness(adapter: MockAdapter, sessionRoot?: string, dshHome?: str
await ctx.plugin(SessionPersistenceJsonl, { root: sessionRoot, compression: 'none' })
}
await ctx.plugin(AgentLoop, { agents: [] })
await ctx.plugin(TaskService)
await ctx.plugin(LocalTaskService)
await ctx.plugin(ToolTasks)
await ctx.plugin(LocalBashExecutor, { timeoutMs: 10_000 })
await ctx.plugin(ToolBash, dshHome === undefined ? {} : { dshHome })
@@ -170,7 +170,7 @@ describe('bash tool through the agent loop', () => {
})
it('background: start ack → completion notice as user/message → task_output collects it', async () => {
// The task id is deterministic (a fresh TaskService counts per kind from 1),
// The task id is deterministic (a fresh LocalTaskService counts per kind from 1),
// so the script can name `bash-1` without threading a generated id.
const adapter = new MockAdapter([
toolCallResponse('call-1', 'bash', { command: 'echo bg-ok', description: 'test command', run_in_background: true }),

View File

@@ -12,7 +12,7 @@ import AgentRegistry from '@deepseek-ai/dsh-agent'
import type { Agent } from '@deepseek-ai/dsh-agent'
import SessionStore, { SessionId } from '@deepseek-ai/dsh-session'
import SessionPersistenceJsonl from '@deepseek-ai/dsh-session-persistence-jsonl'
import TaskService from '@deepseek-ai/dsh-tasks'
import LocalTaskService from '@deepseek-ai/dsh-tasks-local'
import * as ToolTasks from '@deepseek-ai/dsh-tool-tasks'
import ApprovalService from '@deepseek-ai/dsh-user-approval'
import type { ApprovalOutcome } from '@deepseek-ai/dsh-user-approval'
@@ -44,7 +44,7 @@ async function setupWithTasks() {
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(AgentRegistry)
await ctx.plugin(TaskService)
await ctx.plugin(LocalTaskService)
await ctx.plugin(ToolTasks)
await ctx.plugin(LocalBashExecutor, { timeoutMs: 10_000, graceMs: 200 })
;(ctx.bash as LocalBashExecutor).internals = { spillDir }
@@ -180,7 +180,7 @@ async function setupSandboxed(withApproval = false) {
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(AgentRegistry)
await ctx.plugin(TaskService)
await ctx.plugin(LocalTaskService)
await ctx.plugin(ToolTasks)
await ctx.plugin(SandboxPolicyService, {})
await ctx.plugin(RecordingSandboxExecutor)
@@ -472,7 +472,7 @@ describe('background execution through the task runtime', () => {
})
it('fails loud when the task runtime is not loaded', async () => {
const ctx = await setup() // no TaskService / ToolTasks
const ctx = await setup() // no LocalTaskService / ToolTasks
const result = await call(ctx, 'bash', { command: 'sleep 60', description: 'test command', run_in_background: true })
expect(result.isError).toBe(true)
expect(text(result)).toContain('background tasks unavailable: load @deepseek-ai/dsh-tasks and @deepseek-ai/dsh-tool-tasks')
@@ -483,7 +483,7 @@ describe('background execution through the task runtime', () => {
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(AgentRegistry)
await ctx.plugin(TaskService)
await ctx.plugin(LocalTaskService)
await ctx.plugin(ToolTasks)
await ctx.plugin(CountingStartExecutor)
await ctx.plugin(ToolBash)
@@ -511,7 +511,7 @@ describe('background execution through the task runtime', () => {
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(AgentRegistry)
await ctx.plugin(TaskService)
await ctx.plugin(LocalTaskService)
await ctx.plugin(CountingStartExecutor)
await ctx.plugin(ToolBash)
@@ -1073,7 +1073,7 @@ describe('the model-facing bash tool builds its request from named args only (no
await ctx.plugin(SessionStore)
await ctx.plugin(SessionPersistenceJsonl, { root: join(spillDir, 'jsonl') })
}
await ctx.plugin(TaskService)
await ctx.plugin(LocalTaskService)
await ctx.plugin(ToolTasks)
await ctx.plugin(RecordingBashExecutor)
await ctx.plugin(ToolBash, { dshHome: recordingDshHome })