fix: preserve tool details and prevent repeated history growth

Show bounded operation summaries for Continue, DeepSeek Harness and direct-model tools, retaining input details across incremental updates. Use one canonical workspace path for DeepSeek Host startup and ACP sessions so equivalent Windows paths reuse a working Runtime.

Compare persisted subagent tool fields by value, release terminal task caches, and avoid rebuilding caches for duplicate remote events. Upgrade to schema 35 to recompact repeated schema-34 tool blocks while preserving events and provenance. Include regression coverage, validation records and temporary-resource test exclusions.

Validation: 4155 tests passed, 66 skipped; typecheck and lint passed. Full desktop real-model validation covered all three tool-summary paths and both Windows path spellings. Storage validation evidence includes local and remote tool workloads and real database upgrade checks.

Release note: Tool records now show paths, commands and search details across runtimes. Fix DeepSeek Windows workspace failures and repeated subagent history growth; schema 35 reclaims redundant history data while preserving execution records, and older clients cannot reopen the upgraded database.
This commit is contained in:
mesalogo
2026-09-14 00:34:51 +08:00
parent c71da4b6ae
commit 0d7ba55a50
29 changed files with 667 additions and 97 deletions
+24 -9
View File
@@ -1,3 +1,5 @@
import { toolOperationSummary } from './tool-operation-summary'
import { realpath } from 'node:fs/promises'
import type {
AgentRuntimeStatus,
ModelRequestHeaders,
@@ -210,12 +212,16 @@ type ActiveRun = {
toolController: AbortController
authorize?: RuntimeAuthorizer
updates: AcpSessionNotification['update'][]
toolNames: Map<string, string>
toolNames: Map<
string,
{ name: string; input?: string; summary?: string; title?: string }
>
wake?: () => void
closed: boolean
}
type HarnessState = {
workspace: string
child: DeepSeekHarnessChild
connection: AcpConnection
agent: AcpAgent
@@ -778,9 +784,10 @@ export class DeepSeekHarnessRuntime implements AgentRuntime {
this.launchController = launchController
let child: DeepSeekHarnessChild | undefined
try {
const workspace = await realpath(this.options.defaultWorkspace)
child = await withTimeout(
this.options.launch({
cwd: this.options.defaultWorkspace,
cwd: workspace,
signal: launchController.signal,
baseUrl: this.options.baseUrl,
model: this.options.model,
@@ -977,6 +984,7 @@ export class DeepSeekHarnessRuntime implements AgentRuntime {
throw new Error('DeepSeek Harness ACP 客户端初始化失败')
}
const stateWithoutCapabilities = {
workspace,
child,
connection,
agent
@@ -1306,7 +1314,7 @@ export class DeepSeekHarnessRuntime implements AgentRuntime {
}
const creation = state.agent
.newSession({
cwd: this.options.defaultWorkspace,
cwd: state.workspace,
mcpServers: []
})
.then((response) => {
@@ -1336,7 +1344,7 @@ export class DeepSeekHarnessRuntime implements AgentRuntime {
private toRuntimeEvent(
requestId: string,
update: AcpSessionNotification['update'],
toolNames: Map<string, string>
toolNames: ActiveRun['toolNames']
): RuntimeEvent | undefined {
if (update.goodBuddyEvent) {
return this.toUsageEvent(
@@ -1378,16 +1386,23 @@ export class DeepSeekHarnessRuntime implements AgentRuntime {
'DeepSeek Harness 工具'
).slice(0, 200)
const callId = update.toolCallId.slice(0, 256)
const previous = toolNames.get(callId)
const name =
reportedName === 'tool'
? toolNames.get(callId) ?? reportedName
reportedName === 'tool' || (!update.name && !update.title)
? previous?.name ?? reportedName
: reportedName
const title = toolOperationSummary(
undefined,
update.title === 'tool' || update.title === update.name || update.title === previous?.name
? undefined : update.title
) ?? previous?.title
const input = safeStringify(update.rawInput) ?? previous?.input
const summary = toolOperationSummary(update.rawInput, title) ?? previous?.summary
if (state === 'pending' || state === 'running') {
toolNames.set(callId, name)
toolNames.set(callId, { name, input, summary, title })
} else {
toolNames.delete(callId)
}
const input = safeStringify(update.rawInput)
const output = safeStringify(update.rawOutput)
return {
requestId,
@@ -1395,7 +1410,7 @@ export class DeepSeekHarnessRuntime implements AgentRuntime {
callId,
name,
state,
summary: `DeepSeek Harness 工具:${name}`,
summary: summary ?? `DeepSeek Harness 工具:${name}`,
...(input ? { input } : {}),
...(output ? { output } : {})
}