Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/presenter/agentRepository/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ const mergeDeepChatConfig = (
defaultModelPreset: overrideConfig.defaultModelPreset ?? baseConfig.defaultModelPreset ?? null,
assistantModel: overrideConfig.assistantModel ?? baseConfig.assistantModel ?? null,
visionModel: overrideConfig.visionModel ?? baseConfig.visionModel ?? null,
imageGenerationModel:
overrideConfig.imageGenerationModel ?? baseConfig.imageGenerationModel ?? null,
defaultProjectPath: overrideConfig.defaultProjectPath ?? baseConfig.defaultProjectPath ?? null,
systemPrompt: overrideConfig.systemPrompt ?? baseConfig.systemPrompt ?? '',
permissionMode: overrideConfig.permissionMode ?? baseConfig.permissionMode ?? 'full_access',
Expand Down
38 changes: 26 additions & 12 deletions src/main/presenter/agentRuntimePresenter/dispatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ import { buildTerminalErrorBlocks } from './messageStore'
import { finalizeTrailingPendingNarrativeBlocks } from './accumulator'
import type { EchoHandle } from './echo'
import { cloneBlocksForRenderer } from './echo'
import {
insertBlocksAfterToolCall,
prepareToolImagePreviewPresentation
} from './imageGenerationBlocks'
import {
buildAssistantPreviewMarkdown,
buildAssistantResponseMarkdown,
Expand Down Expand Up @@ -56,6 +60,8 @@ type ToolExecutionContext = {
type StagedToolResult = {
toolCallId: string
toolName: string
toolSource?: 'mcp' | 'agent'
serverName?: string
toolArgs: string
responseText: string
isError: boolean
Expand Down Expand Up @@ -431,6 +437,8 @@ function buildToolErrorOutcome(
stagedResult: {
toolCallId: execution.completedToolCall.id,
toolName: execution.completedToolCall.name,
toolSource: execution.toolDef?.source,
serverName: execution.toolContext.serverName,
toolArgs: execution.completedToolCall.arguments,
responseText: `Error: ${errorText}`,
isError: true,
Expand Down Expand Up @@ -535,6 +543,13 @@ function applyFinalizedToolResults(params: {
}
}

const imagePresentation = prepareToolImagePreviewPresentation({
toolName: stagedResult.toolName,
toolSource: stagedResult.toolSource,
serverName: stagedResult.serverName,
isError: fittedResult.isError,
imagePreviews: stagedResult.imagePreviews
})
updateToolCallBlock(
state.blocks,
fittedResult.toolCallId,
Expand All @@ -547,7 +562,12 @@ function applyFinalizedToolResults(params: {
rtkMode: stagedResult.rtkMode,
rtkFallbackReason: stagedResult.rtkFallbackReason
},
stagedResult.imagePreviews
imagePresentation.toolBlockImagePreviews
)
insertBlocksAfterToolCall(
state.blocks,
fittedResult.toolCallId,
imagePresentation.promotedBlocks
)

if (fittedResult.isError) {
Expand Down Expand Up @@ -890,6 +910,8 @@ async function runToolCall(params: {
stagedResult: {
toolCallId: completedToolCall.id,
toolName: completedToolCall.name,
toolSource: execution.toolDef?.source,
serverName: toolContext.serverName,
toolArgs: completedToolCall.arguments,
responseText: stagedResponseText,
isError: stagedIsError,
Expand Down Expand Up @@ -1112,12 +1134,8 @@ export async function executeTools(
for (const tc of state.completedToolCalls) {
if (io.abortSignal.aborted) break

const { toolCall, toolContext, completedToolCall } = buildToolExecutionContext(
tc,
tools,
io.sessionId,
providerId
)
const execution = buildToolExecutionContext(tc, tools, io.sessionId, providerId)
const { toolCall, toolContext } = execution

try {
if (toolCall.function.name === QUESTION_TOOL_NAME) {
Expand Down Expand Up @@ -1192,11 +1210,7 @@ export async function executeTools(
})

const outcome = await runToolCall({
execution: {
toolCall,
toolContext,
completedToolCall
},
execution,
toolPresenter,
permissionMode,
hooks,
Expand Down
87 changes: 87 additions & 0 deletions src/main/presenter/agentRuntimePresenter/imageGenerationBlocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import type { AssistantMessageBlock } from '@shared/types/agent-interface'
import type { ToolCallImagePreview } from '@shared/types/core/mcp'
import {
IMAGE_GENERATE_TOOL_NAME,
IMAGE_GENERATION_TOOL_SERVER_NAME
} from '@shared/agentImageGenerationTool'

export function prepareToolImagePreviewPresentation(params: {
toolName: string
toolSource?: 'mcp' | 'agent'
serverName?: string
isError: boolean
imagePreviews?: ToolCallImagePreview[]
}): {
toolBlockImagePreviews?: ToolCallImagePreview[]
promotedBlocks: AssistantMessageBlock[]
} {
const { toolName, toolSource, serverName, isError, imagePreviews } = params
if (!imagePreviews) {
return { promotedBlocks: [] }
}

if (
toolName !== IMAGE_GENERATE_TOOL_NAME ||
toolSource !== 'agent' ||
serverName !== IMAGE_GENERATION_TOOL_SERVER_NAME ||
isError ||
imagePreviews.length === 0
) {
return {
toolBlockImagePreviews: imagePreviews,
promotedBlocks: []
}
}

const timestamp = Date.now()
const promotedBlocks: AssistantMessageBlock[] = []
for (const preview of imagePreviews) {
const { data, mimeType } = preview
if (!data || !mimeType) {
continue
}

promotedBlocks.push({
type: 'image',
content: '',
status: 'success',
timestamp,
image_data: {
data,
mimeType
}
})
}

if (promotedBlocks.length === 0) {
return {
toolBlockImagePreviews: imagePreviews,
promotedBlocks: []
}
}

return {
toolBlockImagePreviews: [],
promotedBlocks
}
}

export function insertBlocksAfterToolCall(
blocks: AssistantMessageBlock[],
toolCallId: string,
newBlocks: AssistantMessageBlock[]
): void {
if (newBlocks.length === 0) {
return
}

const toolBlockIndex = blocks.findIndex(
(block) => block.type === 'tool_call' && block.tool_call?.id === toolCallId
)
if (toolBlockIndex === -1) {
blocks.push(...newBlocks)
return
}

blocks.splice(toolBlockIndex + 1, 0, ...newBlocks)
}
19 changes: 18 additions & 1 deletion src/main/presenter/agentRuntimePresenter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ import {
emitDeepChatInternalSessionUpdate,
extractWaitingInteraction
} from './internalSessionEvents'
import {
insertBlocksAfterToolCall,
prepareToolImagePreviewPresentation
} from './imageGenerationBlocks'

type PendingInteractionEntry = {
interaction: PendingToolInteraction
Expand All @@ -112,6 +116,8 @@ type PendingInteractionEntry = {
type DeferredToolExecutionResult = {
responseText: string
isError: boolean
toolSource?: 'mcp' | 'agent'
serverName?: string
offloadPath?: string
rtkApplied?: boolean
rtkMode?: 'rewrite' | 'direct' | 'bypass'
Expand Down Expand Up @@ -1029,6 +1035,14 @@ export class AgentRuntimePresenter implements IAgentImplementation {
this.setSessionStatus(sessionId, 'error')
return { resumed: false }
}
const imagePresentation = prepareToolImagePreviewPresentation({
toolName: toolCall.name || '',
toolSource: execution.toolSource,
serverName: execution.serverName,
isError: execution.isError,
imagePreviews: execution.imagePreviews
})

this.updateToolCallResponse(
blocks,
toolCall.id,
Expand All @@ -1038,9 +1052,10 @@ export class AgentRuntimePresenter implements IAgentImplementation {
rtkApplied: execution.rtkApplied,
rtkMode: execution.rtkMode,
rtkFallbackReason: execution.rtkFallbackReason,
imagePreviews: execution.imagePreviews
imagePreviews: imagePresentation.toolBlockImagePreviews
}
)
insertBlocksAfterToolCall(blocks, toolCall.id, imagePresentation.promotedBlocks)
resumeBudgetToolCall = {
id: toolCall.id,
name: toolCall.name || '',
Expand Down Expand Up @@ -4243,6 +4258,8 @@ export class AgentRuntimePresenter implements IAgentImplementation {
return {
responseText: prepared.content,
isError: Boolean(rawData.isError),
toolSource: toolDefinition.source,
serverName: toolDefinition.server.name,
offloadPath: prepared.offloadPath,
rtkApplied: rawData.rtkApplied,
rtkMode: rawData.rtkMode,
Expand Down
4 changes: 4 additions & 0 deletions src/main/presenter/configPresenter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,10 @@ export class ConfigPresenter implements IConfigPresenter {
updates.visionModel = null
}

if (isDeprecatedBuiltinModelSelection(config.imageGenerationModel)) {
updates.imageGenerationModel = null
}

if (Object.keys(updates).length > 0) {
this.updateBuiltinDeepChatConfig(updates)
}
Expand Down
8 changes: 8 additions & 0 deletions src/main/presenter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,14 @@ export class Presenter implements IPresenter {
temperature,
maxTokens,
options
),
generateImageStandalone: (providerId, prompt, modelId, imageOptions, options) =>
this.llmproviderPresenter.generateImageStandalone(
providerId,
prompt,
modelId,
imageOptions,
options
)
}),
cacheImage: (data) => this.devicePresenter.cacheImage(data),
Expand Down
Loading