Skip to content

Commit 0c753db

Browse files
author
deepinsect
committed
feat(agentic): render integration
1 parent d66a383 commit 0c753db

File tree

91 files changed

+4476
-3791
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+4476
-3791
lines changed

docs/specs/agentic-renderer-integration/chatConfig-removal-spec.md

Lines changed: 406 additions & 0 deletions
Large diffs are not rendered by default.

docs/specs/agentic-renderer-integration/tasks.md

Lines changed: 535 additions & 159 deletions
Large diffs are not rendered by default.

src/main/presenter/agentPresenter/message/messageBuilder.ts

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { modelCapabilities } from '../../configPresenter/modelCapabilities'
99
import { enhanceSystemPromptWithDateTime } from '../utility/promptEnhancer'
1010
import { ToolCallCenter } from '../tool/toolCallCenter'
1111
import { nanoid } from 'nanoid'
12+
import { getRuntimeConfig } from '../runtimeConfig'
1213

1314
import {
1415
addContextMessages,
@@ -83,29 +84,9 @@ function appendPromptSection(base: string, section: string): string {
8384
}
8485

8586
async function resolveSystemPrompt(conversation: CONVERSATION): Promise<string> {
86-
const systemPromptId = conversation.settings.systemPromptId?.trim()
87-
if (!systemPromptId) {
88-
return conversation.settings.systemPrompt || ''
89-
}
90-
91-
if (systemPromptId === 'empty') {
92-
return ''
93-
}
94-
95-
try {
96-
if (systemPromptId === 'default') {
97-
return await presenter.configPresenter.getDefaultSystemPrompt()
98-
}
99-
const prompts = await presenter.configPresenter.getSystemPrompts()
100-
const matchedPrompt = prompts.find((prompt) => prompt.id === systemPromptId)
101-
if (matchedPrompt?.content) {
102-
return matchedPrompt.content
103-
}
104-
} catch (error) {
105-
console.warn('AgentPresenter: Failed to resolve system prompt id', error)
106-
}
107-
108-
return conversation.settings.systemPrompt || ''
87+
// Phase 6: System prompts removed - use agent default
88+
const runtimeConfig = getRuntimeConfig(conversation)
89+
return runtimeConfig.systemPrompt
10990
}
11091

11192
export async function preparePromptContent({
@@ -121,7 +102,9 @@ export async function preparePromptContent({
121102
finalContent: ChatMessage[]
122103
promptTokens: number
123104
}> {
124-
const { contextLength, artifacts, enabledMcpTools } = conversation.settings
105+
// Phase 6: Get runtime config from agent defaults
106+
const runtimeConfig = getRuntimeConfig(conversation)
107+
const { contextLength, artifacts, enabledMcpTools } = runtimeConfig
125108
const systemPrompt = await resolveSystemPrompt(conversation)
126109
const isAgentMode = true
127110
const isToolPromptMode = true

src/main/presenter/agentPresenter/permission/permissionHandler.ts

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import type { StreamGenerationHandler } from '../streaming/streamGenerationHandl
1818
import type { LLMEventHandler } from '../streaming/llmEventHandler'
1919
import { BaseHandler, type ThreadHandlerContext } from '../baseHandler'
2020
import { CommandPermissionService } from '../../permission/commandPermissionService'
21+
import { getRuntimeConfig } from '../runtimeConfig'
2122

2223
export class PermissionHandler extends BaseHandler {
2324
private readonly generatingMessages: Map<string, GeneratingMessageState>
@@ -379,6 +380,8 @@ export class PermissionHandler extends BaseHandler {
379380
const { conversation, contextMessages, userMessage } =
380381
await this.streamGenerationHandler.prepareConversationContext(conversationId, messageId)
381382

383+
// Phase 6: Get runtime config instead of reading from settings
384+
const runtimeConfig = getRuntimeConfig(conversation)
382385
const {
383386
providerId,
384387
modelId,
@@ -391,7 +394,7 @@ export class PermissionHandler extends BaseHandler {
391394
enableSearch,
392395
forcedSearch,
393396
searchStrategy
394-
} = conversation.settings
397+
} = runtimeConfig
395398

396399
const modelConfig = this.ctx.configPresenter.getModelConfig(modelId, providerId)
397400
const completedToolCall = {
@@ -477,6 +480,8 @@ export class PermissionHandler extends BaseHandler {
477480
const { contextMessages, userMessage } =
478481
await this.streamGenerationHandler.prepareConversationContext(conversationId, messageId)
479482

483+
// Phase 6: Get runtime config instead of reading from settings
484+
const runtimeConfig = getRuntimeConfig(conversation)
480485
const modelConfig = this.ctx.configPresenter.getModelConfig(
481486
conversation.settings.modelId,
482487
conversation.settings.providerId
@@ -495,15 +500,15 @@ export class PermissionHandler extends BaseHandler {
495500
finalContent,
496501
conversation.settings.modelId,
497502
messageId,
498-
conversation.settings.temperature,
499-
conversation.settings.maxTokens,
500-
conversation.settings.enabledMcpTools,
501-
conversation.settings.thinkingBudget,
502-
conversation.settings.reasoningEffort,
503-
conversation.settings.verbosity,
504-
conversation.settings.enableSearch,
505-
conversation.settings.forcedSearch,
506-
conversation.settings.searchStrategy,
503+
runtimeConfig.temperature,
504+
runtimeConfig.maxTokens,
505+
runtimeConfig.enabledMcpTools,
506+
runtimeConfig.thinkingBudget,
507+
runtimeConfig.reasoningEffort,
508+
runtimeConfig.verbosity,
509+
runtimeConfig.enableSearch,
510+
runtimeConfig.forcedSearch,
511+
runtimeConfig.searchStrategy,
507512
conversationId
508513
)
509514

@@ -546,6 +551,8 @@ export class PermissionHandler extends BaseHandler {
546551
const { conversation, contextMessages, userMessage } =
547552
await this.streamGenerationHandler.prepareConversationContext(conversationId, message.id)
548553

554+
// Phase 6: Get runtime config instead of reading from settings
555+
const runtimeConfig = getRuntimeConfig(conversation)
549556
const {
550557
providerId,
551558
modelId,
@@ -558,7 +565,7 @@ export class PermissionHandler extends BaseHandler {
558565
enableSearch,
559566
forcedSearch,
560567
searchStrategy
561-
} = conversation.settings
568+
} = runtimeConfig
562569

563570
const modelConfig = this.ctx.configPresenter.getModelConfig(modelId, providerId)
564571
if (!modelConfig) {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* Phase 6: Runtime Configuration Helper
3+
*
4+
* This module provides helper functions to get runtime configuration values
5+
* that were previously stored in CONVERSATION_SETTINGS but now come from:
6+
* 1. Agent's SessionInfo (runtime state from the agent)
7+
* 2. Model configuration defaults
8+
* 3. Hardcoded defaults for removed features
9+
*/
10+
11+
import { CONVERSATION } from '@shared/presenter'
12+
import { presenter } from '@/presenter'
13+
14+
export interface RuntimeConfig {
15+
providerId: string
16+
modelId: string
17+
systemPrompt: string
18+
systemPromptId: string | undefined
19+
temperature: number
20+
contextLength: number
21+
maxTokens: number
22+
artifacts: number
23+
enabledMcpTools: string[] | undefined
24+
thinkingBudget: number | undefined
25+
reasoningEffort: 'minimal' | 'low' | 'medium' | 'high' | undefined
26+
verbosity: 'low' | 'medium' | 'high' | undefined
27+
enableSearch: boolean | undefined
28+
forcedSearch: boolean | undefined
29+
searchStrategy: 'turbo' | 'max' | undefined
30+
selectedVariantsMap: Record<string, string>
31+
activeSkills: string[]
32+
}
33+
34+
/**
35+
* Get runtime configuration for a conversation
36+
* These values now come from agent's SessionInfo, not from stored settings
37+
*/
38+
export function getRuntimeConfig(conversation: CONVERSATION): RuntimeConfig {
39+
// Get model config for defaults
40+
const modelConfig = presenter.configPresenter.getModelConfig(
41+
conversation.settings.modelId,
42+
conversation.settings.providerId
43+
)
44+
45+
return {
46+
providerId: conversation.settings.providerId,
47+
modelId: conversation.settings.modelId,
48+
systemPrompt: '', // Phase 6: Use agent default
49+
systemPromptId: undefined, // Phase 6: System prompts removed
50+
contextLength: modelConfig?.contextLength || 4000,
51+
maxTokens: modelConfig?.maxTokens || 2000,
52+
temperature: modelConfig?.temperature ?? 0.7,
53+
artifacts: 0, // Phase 6: Artifacts feature removed
54+
enabledMcpTools: undefined, // Phase 6: All tools enabled by default
55+
thinkingBudget: modelConfig?.thinkingBudget,
56+
reasoningEffort: undefined, // Phase 6: Use agent default
57+
verbosity: undefined, // Phase 6: Use agent default
58+
enableSearch: undefined, // Phase 6: Use agent default
59+
forcedSearch: undefined, // Phase 6: Use agent default
60+
searchStrategy: undefined, // Phase 6: Use agent default
61+
selectedVariantsMap: {}, // Phase 6: Variant management removed
62+
activeSkills: [] // Phase 6: Active skills feature removed
63+
}
64+
}

src/main/presenter/agentPresenter/session/sessionResolver.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ export function resolveSessionContext(input: SessionResolveInput): SessionContex
1515
supportsVision: modelConfig?.vision ?? false,
1616
supportsFunctionCall: modelConfig?.functionCall ?? false,
1717
agentWorkspacePath: settings.agentWorkspacePath ?? null,
18-
enabledMcpTools: settings.enabledMcpTools
18+
enabledMcpTools: undefined // Phase 6: All MCP tools enabled by default
1919
}
2020
}

src/main/presenter/agentPresenter/streaming/streamGenerationHandler.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import type { LLMEventHandler } from './llmEventHandler'
1818
import { LoopOrchestrator } from '../loop/loopOrchestrator'
1919
import type { AgenticEventEmitter } from '@shared/types/presenters/agentic.presenter.d'
2020
import { normalizeAndEmit } from '../normalizer'
21+
import { getRuntimeConfig } from '../runtimeConfig'
2122

2223
interface StreamGenerationHandlerDeps {
2324
generatingMessages: Map<string, GeneratingMessageState>
@@ -105,6 +106,8 @@ export class StreamGenerationHandler extends BaseHandler {
105106
this.throwIfCancelled(state.message.id)
106107

107108
const currentConversation = await this.getConversation(conversationId)
109+
// Phase 6: Get runtime config instead of reading from settings
110+
const runtimeConfig = getRuntimeConfig(currentConversation)
108111
const {
109112
providerId: currentProviderId,
110113
modelId: currentModelId,
@@ -117,7 +120,7 @@ export class StreamGenerationHandler extends BaseHandler {
117120
enableSearch: currentEnableSearch,
118121
forcedSearch: currentForcedSearch,
119122
searchStrategy: currentSearchStrategy
120-
} = currentConversation.settings
123+
} = runtimeConfig
121124

122125
const stream = this.ctx.llmProviderPresenter.startStreamCompletion(
123126
currentProviderId,
@@ -217,6 +220,8 @@ export class StreamGenerationHandler extends BaseHandler {
217220

218221
this.throwIfCancelled(state.message.id)
219222

223+
// Phase 6: Get runtime config instead of reading from settings
224+
const runtimeConfig = getRuntimeConfig(conversation)
220225
const {
221226
providerId,
222227
modelId,
@@ -229,7 +234,7 @@ export class StreamGenerationHandler extends BaseHandler {
229234
enableSearch,
230235
forcedSearch,
231236
searchStrategy
232-
} = conversation.settings
237+
} = runtimeConfig
233238
const modelConfig = this.ctx.configPresenter.getModelConfig(modelId, providerId)
234239
if (!modelConfig) {
235240
throw new Error(`Model config not found for ${providerId}/${modelId}`)
@@ -442,9 +447,11 @@ export class StreamGenerationHandler extends BaseHandler {
442447
throw new Error('Unsupported message type')
443448
}
444449

450+
// Phase 6: Get context length from runtime config
451+
const runtimeConfig = getRuntimeConfig(conversation)
445452
contextMessages = await this.ctx.messageManager.getMessageHistory(
446453
userMessage.id,
447-
conversation.settings.contextLength
454+
runtimeConfig.contextLength
448455
)
449456
} else {
450457
userMessage = await this.ctx.messageManager.getLastUserMessage(conversationId)
@@ -635,7 +642,9 @@ export class StreamGenerationHandler extends BaseHandler {
635642
}
636643

637644
private async getContextMessages(conversation: CONVERSATION): Promise<Message[]> {
638-
let messageCount = Math.ceil(conversation.settings.contextLength / 300)
645+
// Phase 6: Get context length from runtime config
646+
const runtimeConfig = getRuntimeConfig(conversation)
647+
let messageCount = Math.ceil(runtimeConfig.contextLength / 300)
639648
if (messageCount < 2) {
640649
messageCount = 2
641650
}

src/main/presenter/agentPresenter/utility/utilityHandler.ts

Lines changed: 15 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type {
66
MCPToolDefinition,
77
MESSAGE_METADATA
88
} from '@shared/presenter'
9-
import type { AssistantMessageBlock, Message, UserMessageContent } from '@shared/chat'
9+
import type { AssistantMessageBlock, UserMessageContent } from '@shared/chat'
1010
import { ModelType } from '@shared/model'
1111
import { presenter } from '@/presenter'
1212
import { BaseHandler, type ThreadHandlerContext } from '../baseHandler'
@@ -18,6 +18,7 @@ import {
1818
} from '../../exporter/formats/conversationExporter'
1919
import { preparePromptContent } from '../message/messageBuilder'
2020
import type { StreamGenerationHandler } from '../streaming/streamGenerationHandler'
21+
import { getRuntimeConfig } from '../runtimeConfig'
2122

2223
// Translation constants
2324
const TRANSLATION_TEMPERATURE = 0.3
@@ -204,13 +205,10 @@ export class UtilityHandler extends BaseHandler {
204205
// Filter out unsent messages
205206
const validMessages = messages.filter((msg) => msg.status === 'sent')
206207

207-
// Apply variant selection
208-
const selectedVariantsMap = conversation.settings.selectedVariantsMap || {}
209-
const variantAwareMessages = this.applyVariantSelection(validMessages, selectedVariantsMap)
210-
208+
// Phase 6: Variant management removed - use messages directly
211209
// Generate filename
212210
const filename = generateExportFilename(format)
213-
const content = buildConversationExportContent(conversation, variantAwareMessages, format)
211+
const content = buildConversationExportContent(conversation, validMessages, format)
214212

215213
return { filename, content }
216214
} catch (error) {
@@ -231,16 +229,16 @@ export class UtilityHandler extends BaseHandler {
231229
}
232230
const { providerId, modelId } = conversation.settings
233231

234-
// Get context messages
235-
let messageCount = Math.ceil(conversation.settings.contextLength / DEFAULT_MESSAGE_LENGTH)
232+
// Phase 6: Get context length from runtime config
233+
const runtimeConfig = getRuntimeConfig(conversation)
234+
let messageCount = Math.ceil(runtimeConfig.contextLength / DEFAULT_MESSAGE_LENGTH)
236235
if (messageCount < 2) {
237236
messageCount = 2
238237
}
239238
const messages = await this.ctx.messageManager.getContextMessages(conversation.id, messageCount)
240239

241-
const selectedVariantsMap = conversation.settings.selectedVariantsMap || {}
242-
const variantAwareMessages = this.applyVariantSelection(messages, selectedVariantsMap)
243-
const messagesWithLength = variantAwareMessages
240+
// Phase 6: Variant management removed - use messages directly
241+
const messagesWithLength = messages
244242
.map((msg) => {
245243
if (msg.role === 'user') {
246244
const userContent = msg.content as UserMessageContent
@@ -288,13 +286,15 @@ export class UtilityHandler extends BaseHandler {
288286
}
289287

290288
const conversation = await this.ctx.sqlitePresenter.getConversation(message.conversation_id)
289+
// Phase 6: Get runtime config instead of reading from settings
290+
const runtimeConfig = getRuntimeConfig(conversation)
291291
const {
292292
providerId: defaultProviderId,
293293
modelId: defaultModelId,
294294
temperature,
295295
maxTokens,
296296
enabledMcpTools
297-
} = conversation.settings
297+
} = runtimeConfig
298298

299299
// Parse metadata to get model_provider and model_id
300300
let messageMetadata: MESSAGE_METADATA | null = null
@@ -317,9 +317,10 @@ export class UtilityHandler extends BaseHandler {
317317
const userMessage = this.ctx.messageManager['convertToMessage'](userMessageSqlite)
318318

319319
// Get context messages using getMessageHistory
320+
// Phase 6: Use context length from runtime config
320321
const contextMessages = await this.streamGenerationHandler.getMessageHistory(
321322
userMessage.id,
322-
conversation.settings.contextLength
323+
runtimeConfig.contextLength
323324
)
324325

325326
// Prepare prompt content (reconstruct what was sent)
@@ -437,31 +438,5 @@ export class UtilityHandler extends BaseHandler {
437438
throw error
438439
}
439440
}
440-
441-
/**
442-
* Applies variant selection to messages based on selectedVariantsMap.
443-
* Returns messages with selected variant fields applied when a variant is selected.
444-
*/
445-
private applyVariantSelection(
446-
messages: Message[],
447-
selectedVariantsMap: Record<string, string>
448-
): Message[] {
449-
return messages.map((msg) => {
450-
if (msg.role === 'assistant' && selectedVariantsMap[msg.id] && msg.variants) {
451-
const selectedVariantId = selectedVariantsMap[msg.id]
452-
const selectedVariant = msg.variants.find((v) => v.id === selectedVariantId)
453-
454-
if (selectedVariant) {
455-
const newMsg = JSON.parse(JSON.stringify(msg))
456-
newMsg.content = selectedVariant.content
457-
newMsg.usage = selectedVariant.usage
458-
newMsg.model_id = selectedVariant.model_id
459-
newMsg.model_provider = selectedVariant.model_provider
460-
newMsg.model_name = selectedVariant.model_name
461-
return newMsg
462-
}
463-
}
464-
return msg
465-
})
466-
}
467441
}
442+
// Phase 6: applyVariantSelection method removed - variant management feature removed

0 commit comments

Comments
 (0)