()
| 1941 | } |
| 1942 | |
| 1943 | private async resumeTaskFromHistory() { |
| 1944 | try { |
| 1945 | const modifiedClineMessages = await this.getSavedClineMessages() |
| 1946 | |
| 1947 | // Remove any resume messages that may have been added before. |
| 1948 | const lastRelevantMessageIndex = findLastIndex( |
| 1949 | modifiedClineMessages, |
| 1950 | (m) => !(m.ask === "resume_task" || m.ask === "resume_completed_task"), |
| 1951 | ) |
| 1952 | |
| 1953 | if (lastRelevantMessageIndex !== -1) { |
| 1954 | modifiedClineMessages.splice(lastRelevantMessageIndex + 1) |
| 1955 | } |
| 1956 | |
| 1957 | // Remove any trailing reasoning-only UI messages that were not part of the persisted API conversation |
| 1958 | while (modifiedClineMessages.length > 0) { |
| 1959 | const last = modifiedClineMessages[modifiedClineMessages.length - 1] |
| 1960 | if (last.type === "say" && last.say === "reasoning") { |
| 1961 | modifiedClineMessages.pop() |
| 1962 | } else { |
| 1963 | break |
| 1964 | } |
| 1965 | } |
| 1966 | |
| 1967 | // Since we don't use `api_req_finished` anymore, we need to check if the |
| 1968 | // last `api_req_started` has a cost value, if it doesn't and no |
| 1969 | // cancellation reason to present, then we remove it since it indicates |
| 1970 | // an api request without any partial content streamed. |
| 1971 | const lastApiReqStartedIndex = findLastIndex( |
| 1972 | modifiedClineMessages, |
| 1973 | (m) => m.type === "say" && m.say === "api_req_started", |
| 1974 | ) |
| 1975 | |
| 1976 | if (lastApiReqStartedIndex !== -1) { |
| 1977 | const lastApiReqStarted = modifiedClineMessages[lastApiReqStartedIndex] |
| 1978 | const { cost, cancelReason }: ClineApiReqInfo = JSON.parse(lastApiReqStarted.text || "{}") |
| 1979 | |
| 1980 | if (cost === undefined && cancelReason === undefined) { |
| 1981 | modifiedClineMessages.splice(lastApiReqStartedIndex, 1) |
| 1982 | } |
| 1983 | } |
| 1984 | |
| 1985 | await this.overwriteClineMessages(modifiedClineMessages) |
| 1986 | this.clineMessages = await this.getSavedClineMessages() |
| 1987 | |
| 1988 | // Now present the cline messages to the user and ask if they want to |
| 1989 | // resume (NOTE: we ran into a bug before where the |
| 1990 | // apiConversationHistory wouldn't be initialized when opening a old |
| 1991 | // task, and it was because we were waiting for resume). |
| 1992 | // This is important in case the user deletes messages without resuming |
| 1993 | // the task first. |
| 1994 | this.apiConversationHistory = await this.getSavedApiConversationHistory() |
| 1995 | |
| 1996 | const lastClineMessage = this.clineMessages |
| 1997 | .slice() |
| 1998 | .reverse() |
| 1999 | .find((m) => !(m.ask === "resume_task" || m.ask === "resume_completed_task")) // Could be multiple resume tasks. |
| 2000 |
no test coverage detected