(workspaceId: string, percentage?: number)
| 7948 | } |
| 7949 | |
| 7950 | async truncateHistory(workspaceId: string, percentage?: number): Promise<Result<void>> { |
| 7951 | const session = this.sessions.get(workspaceId); |
| 7952 | if (session?.isBusy() || this.aiService.isStreaming(workspaceId)) { |
| 7953 | return Err( |
| 7954 | "Cannot truncate history while a turn is active. Press Esc to stop the stream first." |
| 7955 | ); |
| 7956 | } |
| 7957 | |
| 7958 | const truncateResult = await this.historyService.truncateHistory( |
| 7959 | workspaceId, |
| 7960 | percentage ?? 1.0 |
| 7961 | ); |
| 7962 | if (!truncateResult.success) { |
| 7963 | return Err(truncateResult.error); |
| 7964 | } |
| 7965 | |
| 7966 | const deletedSequences = truncateResult.data; |
| 7967 | if (deletedSequences.length > 0) { |
| 7968 | const deleteMessage: DeleteMessage = { |
| 7969 | type: "delete", |
| 7970 | historySequences: deletedSequences, |
| 7971 | }; |
| 7972 | // Emit through the session so ORPC subscriptions receive the event |
| 7973 | if (session) { |
| 7974 | session.emitChatEvent(deleteMessage); |
| 7975 | } else { |
| 7976 | // Fallback to direct emit (legacy path) |
| 7977 | this.emit("chat", { workspaceId, message: deleteMessage }); |
| 7978 | } |
| 7979 | } |
| 7980 | |
| 7981 | // On full clear, also delete plan file and clear file change tracking |
| 7982 | if ((percentage ?? 1.0) === 1.0) { |
| 7983 | const metadata = await this.getInfo(workspaceId); |
| 7984 | if (metadata) { |
| 7985 | await this.deletePlanFilesForWorkspace(workspaceId, metadata); |
| 7986 | } |
| 7987 | // A full chat clear removes the context the goal loop was using; require |
| 7988 | // one user re-engagement before later continuation slices resume it. |
| 7989 | try { |
| 7990 | await this.workspaceGoalService?.requireUserAcknowledgment(workspaceId); |
| 7991 | } catch (error) { |
| 7992 | return Err(getErrorMessage(error)); |
| 7993 | } |
| 7994 | this.sessions.get(workspaceId)?.clearFileState(); |
| 7995 | } |
| 7996 | |
| 7997 | return Ok(undefined); |
| 7998 | } |
| 7999 | |
| 8000 | async resetContext(workspaceId: string): Promise<Result<"reset" | "noop">> { |
| 8001 | if (this.resettingContextWorkspaces.has(workspaceId)) { |
nothing calls this directly
no test coverage detected