mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
fix: Add remaining missing types for Files Changed Overview feature
This commit is contained in:
parent
c467d53d09
commit
3dff339218
3 changed files with 195 additions and 87 deletions
|
|
@ -10,7 +10,6 @@ import pWaitFor from "p-wait-for"
|
|||
import { serializeError } from "serialize-error"
|
||||
|
||||
import {
|
||||
type RooCodeSettings,
|
||||
type TaskLike,
|
||||
type TaskMetadata,
|
||||
type TaskEvents,
|
||||
|
|
@ -35,13 +34,15 @@ import {
|
|||
isIdleAsk,
|
||||
isInteractiveAsk,
|
||||
isResumableAsk,
|
||||
QueuedMessage,
|
||||
} from "@roo-code/types"
|
||||
import { TelemetryService } from "@roo-code/telemetry"
|
||||
import { CloudService } from "@roo-code/cloud"
|
||||
import { CloudService, BridgeOrchestrator } from "@roo-code/cloud"
|
||||
|
||||
// api
|
||||
import { ApiHandler, ApiHandlerCreateMessageMetadata, buildApiHandler } from "../../api"
|
||||
import { ApiStream } from "../../api/transform/stream"
|
||||
import { maybeRemoveImageBlocks } from "../../api/transform/image-cleaning"
|
||||
|
||||
// shared
|
||||
import { findLastIndex } from "../../shared/array"
|
||||
|
|
@ -62,7 +63,6 @@ import { BrowserSession } from "../../services/browser/BrowserSession"
|
|||
import { McpHub } from "../../services/mcp/McpHub"
|
||||
import { McpServerManager } from "../../services/mcp/McpServerManager"
|
||||
import { RepoPerTaskCheckpointService } from "../../services/checkpoints"
|
||||
import { CheckpointResult } from "../../services/checkpoints/types"
|
||||
|
||||
// integrations
|
||||
import { DiffViewProvider } from "../../integrations/editor/DiffViewProvider"
|
||||
|
|
@ -80,6 +80,7 @@ import { SYSTEM_PROMPT } from "../prompts/system"
|
|||
|
||||
// core modules
|
||||
import { ToolRepetitionDetector } from "../tools/ToolRepetitionDetector"
|
||||
import { restoreTodoListForTask } from "../tools/updateTodoListTool"
|
||||
import { FileContextTracker } from "../context-tracking/FileContextTracker"
|
||||
import { RooIgnoreController } from "../ignore/RooIgnoreController"
|
||||
import { RooProtectedController } from "../protect/RooProtectedController"
|
||||
|
|
@ -89,7 +90,14 @@ import { truncateConversationIfNeeded } from "../sliding-window"
|
|||
import { ClineProvider } from "../webview/ClineProvider"
|
||||
import { MultiSearchReplaceDiffStrategy } from "../diff/strategies/multi-search-replace"
|
||||
import { MultiFileSearchReplaceDiffStrategy } from "../diff/strategies/multi-file-search-replace"
|
||||
import { readApiMessages, saveApiMessages, readTaskMessages, saveTaskMessages, taskMetadata } from "../task-persistence"
|
||||
import {
|
||||
type ApiMessage,
|
||||
readApiMessages,
|
||||
saveApiMessages,
|
||||
readTaskMessages,
|
||||
saveTaskMessages,
|
||||
taskMetadata,
|
||||
} from "../task-persistence"
|
||||
import { getEnvironmentDetails } from "../environment/getEnvironmentDetails"
|
||||
import { checkContextWindowExceededError } from "../context/context-management/context-error-handling"
|
||||
import {
|
||||
|
|
@ -101,12 +109,11 @@ import {
|
|||
checkpointDiff,
|
||||
} from "../checkpoints"
|
||||
import { processUserContentMentions } from "../mentions/processUserContentMentions"
|
||||
import { ApiMessage } from "../task-persistence/apiMessages"
|
||||
import { getMessagesSinceLastSummary, summarizeConversation } from "../condense"
|
||||
import { maybeRemoveImageBlocks } from "../../api/transform/image-cleaning"
|
||||
import { restoreTodoListForTask } from "../tools/updateTodoListTool"
|
||||
import { AutoApprovalHandler } from "./AutoApprovalHandler"
|
||||
import { Gpt5Metadata, ClineMessageWithMetadata } from "./types"
|
||||
import { MessageQueueService } from "../message-queue/MessageQueueService"
|
||||
|
||||
import { AutoApprovalHandler } from "./AutoApprovalHandler"
|
||||
|
||||
const MAX_EXPONENTIAL_BACKOFF_SECONDS = 600 // 10 minutes
|
||||
const DEFAULT_USAGE_COLLECTION_TIMEOUT_MS = 5000 // 5 seconds
|
||||
|
|
@ -135,6 +142,10 @@ export interface TaskOptions extends CreateTaskOptions {
|
|||
|
||||
export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
||||
readonly taskId: string
|
||||
readonly rootTaskId?: string
|
||||
readonly parentTaskId?: string
|
||||
childTaskId?: string
|
||||
|
||||
readonly instanceId: string
|
||||
readonly metadata: TaskMetadata
|
||||
|
||||
|
|
@ -256,11 +267,15 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
enableCheckpoints: boolean
|
||||
checkpointService?: RepoPerTaskCheckpointService
|
||||
checkpointServiceInitializing = false
|
||||
ongoingCheckpointSaves = new Map<string, Promise<void | CheckpointResult | undefined>>()
|
||||
ongoingCheckpointSaves?: Set<string>
|
||||
|
||||
// Task Bridge
|
||||
enableBridge: boolean
|
||||
|
||||
// Message Queue Service
|
||||
public readonly messageQueueService: MessageQueueService
|
||||
private messageQueueStateChangedHandler: (() => void) | undefined
|
||||
|
||||
// Streaming
|
||||
isWaitingForFirstChunk = false
|
||||
isStreaming = false
|
||||
|
|
@ -303,6 +318,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
}
|
||||
|
||||
this.taskId = historyItem ? historyItem.id : crypto.randomUUID()
|
||||
this.rootTaskId = historyItem ? historyItem.rootTaskId : rootTask?.taskId
|
||||
this.parentTaskId = historyItem ? historyItem.parentTaskId : parentTask?.taskId
|
||||
this.childTaskId = undefined
|
||||
|
||||
this.metadata = {
|
||||
task: historyItem ? historyItem.task : task,
|
||||
|
|
@ -340,7 +358,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
this.enableCheckpoints = enableCheckpoints
|
||||
this.enableBridge = enableBridge
|
||||
|
||||
this.rootTask = rootTask
|
||||
this.parentTask = parentTask
|
||||
this.taskNumber = taskNumber
|
||||
|
||||
|
|
@ -358,9 +375,18 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
TelemetryService.instance.captureTaskCreated(this.taskId)
|
||||
}
|
||||
|
||||
// Initialize the assistant message parser
|
||||
// Initialize the assistant message parser.
|
||||
this.assistantMessageParser = new AssistantMessageParser()
|
||||
|
||||
this.messageQueueService = new MessageQueueService()
|
||||
|
||||
this.messageQueueStateChangedHandler = () => {
|
||||
this.emit(RooCodeEventName.TaskUserMessage, this.taskId)
|
||||
this.providerRef.deref()?.postStateToWebview()
|
||||
}
|
||||
|
||||
this.messageQueueService.on("stateChanged", this.messageQueueStateChangedHandler)
|
||||
|
||||
// Only set up diff strategy if diff is enabled.
|
||||
if (this.diffEnabled) {
|
||||
// Default to old strategy, will be updated if experiment is enabled.
|
||||
|
|
@ -634,12 +660,14 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
})
|
||||
|
||||
const { historyItem, tokenUsage } = await taskMetadata({
|
||||
messages: this.clineMessages,
|
||||
taskId: this.taskId,
|
||||
rootTaskId: this.rootTaskId,
|
||||
parentTaskId: this.parentTaskId,
|
||||
taskNumber: this.taskNumber,
|
||||
messages: this.clineMessages,
|
||||
globalStoragePath: this.globalStoragePath,
|
||||
workspace: this.cwd,
|
||||
mode: this._taskMode || defaultModeSlug, // Use the task's own mode, not the current provider mode
|
||||
mode: this._taskMode || defaultModeSlug, // Use the task's own mode, not the current provider mode.
|
||||
})
|
||||
|
||||
this.emit(RooCodeEventName.TaskTokenUsageUpdated, this.taskId, tokenUsage)
|
||||
|
|
@ -761,10 +789,13 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
// The state is mutable if the message is complete and the task will
|
||||
// block (via the `pWaitFor`).
|
||||
const isBlocking = !(this.askResponse !== undefined || this.lastMessageTs !== askTs)
|
||||
const isStatusMutable = !partial && isBlocking
|
||||
const isMessageQueued = !this.messageQueueService.isEmpty()
|
||||
const isStatusMutable = !partial && isBlocking && !isMessageQueued
|
||||
let statusMutationTimeouts: NodeJS.Timeout[] = []
|
||||
|
||||
if (isStatusMutable) {
|
||||
console.log(`Task#ask will block -> type: ${type}`)
|
||||
|
||||
if (isInteractiveAsk(type)) {
|
||||
statusMutationTimeouts.push(
|
||||
setTimeout(() => {
|
||||
|
|
@ -799,9 +830,19 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
}, 1_000),
|
||||
)
|
||||
}
|
||||
} else if (isMessageQueued) {
|
||||
console.log("Task#ask will process message queue")
|
||||
|
||||
const message = this.messageQueueService.dequeueMessage()
|
||||
|
||||
if (message) {
|
||||
setTimeout(async () => {
|
||||
await this.submitUserMessage(message.text, message.images)
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for askResponse to be set
|
||||
// Wait for askResponse to be set.
|
||||
await pWaitFor(() => this.askResponse !== undefined || this.lastMessageTs !== askTs, { interval: 100 })
|
||||
|
||||
if (this.lastMessageTs !== askTs) {
|
||||
|
|
@ -874,6 +915,8 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
await provider.setProviderProfile(providerProfile)
|
||||
}
|
||||
|
||||
this.emit(RooCodeEventName.TaskUserMessage, this.taskId)
|
||||
|
||||
provider.postMessageToWebview({ type: "invoke", invoke: "sendMessage", text, images })
|
||||
} else {
|
||||
console.error("[Task#submitUserMessage] Provider reference lost")
|
||||
|
|
@ -1095,12 +1138,13 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
return formatResponse.toolError(formatResponse.missingToolParameterError(paramName))
|
||||
}
|
||||
|
||||
// Start / Abort / Resume
|
||||
// Lifecycle
|
||||
// Start / Resume / Abort / Dispose
|
||||
|
||||
private async startTask(task?: string, images?: string[]): Promise<void> {
|
||||
if (this.enableBridge) {
|
||||
try {
|
||||
// BridgeOrchestrator has been removed - bridge functionality disabled
|
||||
await BridgeOrchestrator.subscribeToTask(this)
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`[Task#startTask] BridgeOrchestrator.subscribeToTask() failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
|
|
@ -1138,37 +1182,10 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
])
|
||||
}
|
||||
|
||||
public async resumePausedTask(lastMessage: string) {
|
||||
this.isPaused = false
|
||||
this.emit(RooCodeEventName.TaskUnpaused)
|
||||
|
||||
// Fake an answer from the subtask that it has completed running and
|
||||
// this is the result of what it has done add the message to the chat
|
||||
// history and to the webview ui.
|
||||
try {
|
||||
await this.say("subtask_result", lastMessage)
|
||||
|
||||
await this.addToApiConversationHistory({
|
||||
role: "user",
|
||||
content: [{ type: "text", text: `[new_task completed] Result: ${lastMessage}` }],
|
||||
})
|
||||
|
||||
// Set skipPrevResponseIdOnce to ensure the next API call sends the full conversation
|
||||
// including the subtask result, not just from before the subtask was created
|
||||
this.skipPrevResponseIdOnce = true
|
||||
} catch (error) {
|
||||
this.providerRef
|
||||
.deref()
|
||||
?.log(`Error failed to add reply from subtask into conversation of parent task, error: ${error}`)
|
||||
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
private async resumeTaskFromHistory() {
|
||||
if (this.enableBridge) {
|
||||
try {
|
||||
// BridgeOrchestrator has been removed - bridge functionality disabled
|
||||
await BridgeOrchestrator.subscribeToTask(this)
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`[Task#resumeTaskFromHistory] BridgeOrchestrator.subscribeToTask() failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
|
|
@ -1178,19 +1195,21 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
|
||||
const modifiedClineMessages = await this.getSavedClineMessages()
|
||||
|
||||
// Check for any stored GPT-5 response IDs in the message history
|
||||
// Check for any stored GPT-5 response IDs in the message history.
|
||||
const gpt5Messages = modifiedClineMessages.filter(
|
||||
(m): m is ClineMessage & ClineMessageWithMetadata =>
|
||||
m.type === "say" &&
|
||||
m.say === "text" &&
|
||||
!!(m as ClineMessageWithMetadata).metadata?.gpt5?.previous_response_id,
|
||||
)
|
||||
|
||||
if (gpt5Messages.length > 0) {
|
||||
const lastGpt5Message = gpt5Messages[gpt5Messages.length - 1]
|
||||
// The lastGpt5Message contains the previous_response_id that can be used for continuity
|
||||
// The lastGpt5Message contains the previous_response_id that can be
|
||||
// used for continuity.
|
||||
}
|
||||
|
||||
// Remove any resume messages that may have been added before
|
||||
// Remove any resume messages that may have been added before.
|
||||
const lastRelevantMessageIndex = findLastIndex(
|
||||
modifiedClineMessages,
|
||||
(m) => !(m.ask === "resume_task" || m.ask === "resume_completed_task"),
|
||||
|
|
@ -1408,8 +1427,8 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
newUserContent.push(...formatResponse.imageBlocks(responseImages))
|
||||
}
|
||||
|
||||
// Ensure we have at least some content to send to the API
|
||||
// If newUserContent is empty, add a minimal resumption message
|
||||
// Ensure we have at least some content to send to the API.
|
||||
// If newUserContent is empty, add a minimal resumption message.
|
||||
if (newUserContent.length === 0) {
|
||||
newUserContent.push({
|
||||
type: "text",
|
||||
|
|
@ -1419,14 +1438,51 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
|
||||
await this.overwriteApiConversationHistory(modifiedApiConversationHistory)
|
||||
|
||||
// Task resuming from history item
|
||||
|
||||
// Task resuming from history item.
|
||||
await this.initiateTaskLoop(newUserContent)
|
||||
}
|
||||
|
||||
public async abortTask(isAbandoned = false) {
|
||||
// Aborting task
|
||||
|
||||
// Will stop any autonomously running promises.
|
||||
if (isAbandoned) {
|
||||
this.abandoned = true
|
||||
}
|
||||
|
||||
this.abort = true
|
||||
this.emit(RooCodeEventName.TaskAborted)
|
||||
|
||||
try {
|
||||
this.dispose() // Call the centralized dispose method
|
||||
} catch (error) {
|
||||
console.error(`Error during task ${this.taskId}.${this.instanceId} disposal:`, error)
|
||||
// Don't rethrow - we want abort to always succeed
|
||||
}
|
||||
// Save the countdown message in the automatic retry or other content.
|
||||
try {
|
||||
// Save the countdown message in the automatic retry or other content.
|
||||
await this.saveClineMessages()
|
||||
} catch (error) {
|
||||
console.error(`Error saving messages during abort for task ${this.taskId}.${this.instanceId}:`, error)
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
console.log(`[Task#dispose] disposing task ${this.taskId}.${this.instanceId}`)
|
||||
|
||||
// Dispose message queue and remove event listeners.
|
||||
try {
|
||||
if (this.messageQueueStateChangedHandler) {
|
||||
this.messageQueueService.removeListener("stateChanged", this.messageQueueStateChangedHandler)
|
||||
this.messageQueueStateChangedHandler = undefined
|
||||
}
|
||||
|
||||
this.messageQueueService.dispose()
|
||||
} catch (error) {
|
||||
console.error("Error disposing message queue:", error)
|
||||
}
|
||||
|
||||
// Remove all event listeners to prevent memory leaks.
|
||||
try {
|
||||
this.removeAllListeners()
|
||||
|
|
@ -1434,13 +1490,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
console.error("Error removing event listeners:", error)
|
||||
}
|
||||
|
||||
// Clean up ongoing checkpoint saves to prevent memory leaks
|
||||
try {
|
||||
this.ongoingCheckpointSaves.clear()
|
||||
} catch (error) {
|
||||
console.error("Error clearing ongoing checkpoint saves:", error)
|
||||
}
|
||||
|
||||
// Stop waiting for child task completion.
|
||||
if (this.pauseInterval) {
|
||||
clearInterval(this.pauseInterval)
|
||||
|
|
@ -1448,7 +1497,13 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
}
|
||||
|
||||
if (this.enableBridge) {
|
||||
// BridgeOrchestrator has been removed - bridge functionality disabled
|
||||
BridgeOrchestrator.getInstance()
|
||||
?.unsubscribeFromTask(this.taskId)
|
||||
.catch((error) =>
|
||||
console.error(
|
||||
`[Task#dispose] BridgeOrchestrator#unsubscribeFromTask() failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// Release any terminals associated with this task.
|
||||
|
|
@ -1497,37 +1552,36 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
}
|
||||
}
|
||||
|
||||
public async abortTask(isAbandoned = false) {
|
||||
// Aborting task
|
||||
// Subtasks
|
||||
// Spawn / Wait / Complete
|
||||
|
||||
// Will stop any autonomously running promises.
|
||||
if (isAbandoned) {
|
||||
this.abandoned = true
|
||||
public async startSubtask(message: string, initialTodos: TodoItem[], mode: string) {
|
||||
const provider = this.providerRef.deref()
|
||||
|
||||
if (!provider) {
|
||||
throw new Error("Provider not available")
|
||||
}
|
||||
|
||||
this.abort = true
|
||||
this.emit(RooCodeEventName.TaskAborted)
|
||||
const newTask = await provider.createTask(message, undefined, this, { initialTodos })
|
||||
|
||||
try {
|
||||
this.dispose() // Call the centralized dispose method
|
||||
} catch (error) {
|
||||
console.error(`Error during task ${this.taskId}.${this.instanceId} disposal:`, error)
|
||||
// Don't rethrow - we want abort to always succeed
|
||||
}
|
||||
// Save the countdown message in the automatic retry or other content.
|
||||
try {
|
||||
// Save the countdown message in the automatic retry or other content.
|
||||
await this.saveClineMessages()
|
||||
} catch (error) {
|
||||
console.error(`Error saving messages during abort for task ${this.taskId}.${this.instanceId}:`, error)
|
||||
if (newTask) {
|
||||
this.isPaused = true // Pause parent.
|
||||
this.childTaskId = newTask.taskId
|
||||
|
||||
await provider.handleModeSwitch(mode) // Set child's mode.
|
||||
await delay(500) // Allow mode change to take effect.
|
||||
|
||||
this.emit(RooCodeEventName.TaskPaused, this.taskId)
|
||||
this.emit(RooCodeEventName.TaskSpawned, newTask.taskId)
|
||||
}
|
||||
|
||||
return newTask
|
||||
}
|
||||
|
||||
// Used when a sub-task is launched and the parent task is waiting for it to
|
||||
// finish.
|
||||
// TBD: The 1s should be added to the settings, also should add a timeout to
|
||||
// prevent infinite waiting.
|
||||
public async waitForResume() {
|
||||
// TBD: Add a timeout to prevent infinite waiting.
|
||||
public async waitForSubtask() {
|
||||
await new Promise<void>((resolve) => {
|
||||
this.pauseInterval = setInterval(() => {
|
||||
if (!this.isPaused) {
|
||||
|
|
@ -1539,6 +1593,35 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
})
|
||||
}
|
||||
|
||||
public async completeSubtask(lastMessage: string) {
|
||||
this.isPaused = false
|
||||
this.childTaskId = undefined
|
||||
|
||||
this.emit(RooCodeEventName.TaskUnpaused, this.taskId)
|
||||
|
||||
// Fake an answer from the subtask that it has completed running and
|
||||
// this is the result of what it has done add the message to the chat
|
||||
// history and to the webview ui.
|
||||
try {
|
||||
await this.say("subtask_result", lastMessage)
|
||||
|
||||
await this.addToApiConversationHistory({
|
||||
role: "user",
|
||||
content: [{ type: "text", text: `[new_task completed] Result: ${lastMessage}` }],
|
||||
})
|
||||
|
||||
// Set skipPrevResponseIdOnce to ensure the next API call sends the full conversation
|
||||
// including the subtask result, not just from before the subtask was created
|
||||
this.skipPrevResponseIdOnce = true
|
||||
} catch (error) {
|
||||
this.providerRef
|
||||
.deref()
|
||||
?.log(`Error failed to add reply from subtask into conversation of parent task, error: ${error}`)
|
||||
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// Task Loop
|
||||
|
||||
private async initiateTaskLoop(userContent: Anthropic.Messages.ContentBlockParam[]): Promise<void> {
|
||||
|
|
@ -1625,7 +1708,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
|
||||
if (this.isPaused && provider) {
|
||||
provider.log(`[subtasks] paused ${this.taskId}.${this.instanceId}`)
|
||||
await this.waitForResume()
|
||||
await this.waitForSubtask()
|
||||
provider.log(`[subtasks] resumed ${this.taskId}.${this.instanceId}`)
|
||||
const currentMode = (await provider.getState())?.mode ?? defaultModeSlug
|
||||
|
||||
|
|
@ -2722,10 +2805,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
|
||||
// Getters
|
||||
|
||||
public get cwd() {
|
||||
return this.workspacePath
|
||||
}
|
||||
|
||||
public get taskStatus(): TaskStatus {
|
||||
if (this.interactiveAsk) {
|
||||
return TaskStatus.Interactive
|
||||
|
|
@ -2745,4 +2824,12 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
public get taskAsk(): ClineMessage | undefined {
|
||||
return this.idleAsk || this.resumableAsk || this.interactiveAsk
|
||||
}
|
||||
|
||||
public get queuedMessages(): QueuedMessage[] {
|
||||
return this.messageQueueService.messages
|
||||
}
|
||||
|
||||
public get cwd() {
|
||||
return this.workspacePath
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ export class ClineProvider
|
|||
private mdmService?: MdmService
|
||||
private taskCreationCallback: (task: Task) => void
|
||||
private taskEventListeners: WeakMap<Task, Array<() => void>> = new WeakMap()
|
||||
private fileChangeManager?: any // FileChangeManager instance
|
||||
|
||||
private recentTasksCache?: string[]
|
||||
private globalFileChangeManager?: import("../../services/file-changes/FileChangeManager").FileChangeManager
|
||||
|
|
@ -1746,6 +1747,7 @@ public async clearTask(): Promise<void> {
|
|||
|
||||
return {
|
||||
version: this.context.extension?.packageJSON?.version ?? "",
|
||||
filesChangedEnabled: false, // Add this property
|
||||
apiConfiguration,
|
||||
customInstructions,
|
||||
alwaysAllowReadOnly: alwaysAllowReadOnly ?? false,
|
||||
|
|
@ -1945,6 +1947,7 @@ public async clearTask(): Promise<void> {
|
|||
|
||||
// Return the same structure as before
|
||||
return {
|
||||
filesChangedEnabled: false, // Add this property
|
||||
apiConfiguration: providerSettings,
|
||||
lastShownAnnouncementId: stateValues.lastShownAnnouncementId,
|
||||
customInstructions: stateValues.customInstructions,
|
||||
|
|
@ -2089,6 +2092,20 @@ public async clearTask(): Promise<void> {
|
|||
return this.contextProxy.getValue(key)
|
||||
}
|
||||
|
||||
// File Change Manager methods
|
||||
public getFileChangeManager(): any {
|
||||
return this.fileChangeManager
|
||||
}
|
||||
|
||||
public ensureFileChangeManager(): any {
|
||||
if (!this.fileChangeManager) {
|
||||
// Import and create FileChangeManager instance
|
||||
const { FileChangeManager } = require("../../services/file-changes/FileChangeManager")
|
||||
this.fileChangeManager = new FileChangeManager()
|
||||
}
|
||||
return this.fileChangeManager
|
||||
}
|
||||
|
||||
public async setValue<K extends keyof RooCodeSettings>(key: K, value: RooCodeSettings[K]) {
|
||||
await this.contextProxy.setValue(key, value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ export interface WebviewMessage {
|
|||
| "webviewDidLaunch"
|
||||
| "webviewReady"
|
||||
| "filesChangedRequest"
|
||||
| "filesChangedEnabled"
|
||||
| "filesChangedBaselineUpdate"
|
||||
| "viewDiff"
|
||||
| "acceptFileChange"
|
||||
| "rejectFileChange"
|
||||
|
|
@ -274,6 +276,8 @@ export interface WebviewMessage {
|
|||
visibility?: ShareVisibility // For share visibility
|
||||
hasContent?: boolean // For checkRulesDirectoryResult
|
||||
checkOnly?: boolean // For deleteCustomMode check
|
||||
fileChanges?: any[] // For filesChanged message
|
||||
baseline?: string // For filesChangedBaselineUpdate
|
||||
codeIndexSettings?: {
|
||||
// Global state settings
|
||||
codebaseIndexEnabled: boolean
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue