mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Remove GPT‑5 instructions/reasoning_summary from UI message metadata to prevent ui_messages.json bloat (#8756)
chore(gpt5): stop persisting instructions/reasoning_summary in UI message metadata Problem: ui_messages.json was getting bloated with unused or duplicated content (system 'instructions' and 'reasoning_summary') that we do not read back. Root cause: earlier OpenAI Responses API implementation persisted these fields to per-message metadata; however, 'instructions' are already sent as top-level request instructions and 'reasoning_summary' is surfaced live via streaming events. Neither field is consumed from storage. Changes: (1) Task.persistGpt5Metadata now stores only previous_response_id; (2) removed instructions and reasoning_summary from types; (3) updated Zod schema; (4) persistence layer writes messages as-is (no sanitizer); (5) tests green. Impact: smaller ui_messages.json, no runtime behavior change for requests. Migration: old metadata fields will be ignored by schema.
This commit is contained in:
parent
f3a505fd36
commit
6ffdd440ce
4 changed files with 77 additions and 20 deletions
|
|
@ -221,8 +221,6 @@ export const clineMessageSchema = z.object({
|
|||
gpt5: z
|
||||
.object({
|
||||
previous_response_id: z.string().optional(),
|
||||
instructions: z.string().optional(),
|
||||
reasoning_summary: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
|
|
|
|||
71
src/core/task-persistence/__tests__/taskMessages.spec.ts
Normal file
71
src/core/task-persistence/__tests__/taskMessages.spec.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
import { describe, it, expect, vi, beforeEach } from "vitest"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
import * as fs from "fs/promises"
|
||||
|
||||
// Mocks (use hoisted to avoid initialization ordering issues)
|
||||
const hoisted = vi.hoisted(() => ({
|
||||
safeWriteJsonMock: vi.fn().mockResolvedValue(undefined),
|
||||
}))
|
||||
vi.mock("../../../utils/safeWriteJson", () => ({
|
||||
safeWriteJson: hoisted.safeWriteJsonMock,
|
||||
}))
|
||||
|
||||
// Import after mocks
|
||||
import { saveTaskMessages } from "../taskMessages"
|
||||
|
||||
let tmpBaseDir: string
|
||||
|
||||
beforeEach(async () => {
|
||||
hoisted.safeWriteJsonMock.mockClear()
|
||||
// Create a unique, writable temp directory to act as globalStoragePath
|
||||
tmpBaseDir = await fs.mkdtemp(path.join(os.tmpdir(), "roo-test-"))
|
||||
})
|
||||
|
||||
describe("taskMessages.saveTaskMessages", () => {
|
||||
beforeEach(() => {
|
||||
hoisted.safeWriteJsonMock.mockClear()
|
||||
})
|
||||
|
||||
it("persists messages as-is", async () => {
|
||||
const messages: any[] = [
|
||||
{
|
||||
role: "assistant",
|
||||
content: "Hello",
|
||||
metadata: {
|
||||
gpt5: {
|
||||
previous_response_id: "resp_123",
|
||||
},
|
||||
other: "keep",
|
||||
},
|
||||
},
|
||||
{ role: "user", content: "Do thing" },
|
||||
]
|
||||
|
||||
await saveTaskMessages({
|
||||
messages,
|
||||
taskId: "task-1",
|
||||
globalStoragePath: tmpBaseDir,
|
||||
})
|
||||
|
||||
expect(hoisted.safeWriteJsonMock).toHaveBeenCalledTimes(1)
|
||||
const [, persisted] = hoisted.safeWriteJsonMock.mock.calls[0]
|
||||
expect(persisted).toEqual(messages)
|
||||
})
|
||||
|
||||
it("persists messages without modification when no metadata", async () => {
|
||||
const messages: any[] = [
|
||||
{ role: "assistant", content: "Hi" },
|
||||
{ role: "user", content: "Yo" },
|
||||
]
|
||||
|
||||
await saveTaskMessages({
|
||||
messages,
|
||||
taskId: "task-2",
|
||||
globalStoragePath: tmpBaseDir,
|
||||
})
|
||||
|
||||
const [, persisted] = hoisted.safeWriteJsonMock.mock.calls[0]
|
||||
expect(persisted).toEqual(messages)
|
||||
})
|
||||
})
|
||||
|
|
@ -2267,7 +2267,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
}
|
||||
}
|
||||
|
||||
await this.persistGpt5Metadata(reasoningMessage)
|
||||
await this.persistGpt5Metadata()
|
||||
await this.saveClineMessages()
|
||||
await this.providerRef.deref()?.postStateToWebview()
|
||||
|
||||
|
|
@ -2853,10 +2853,12 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
}
|
||||
|
||||
/**
|
||||
* Persist GPT-5 per-turn metadata (previous_response_id, instructions, reasoning_summary)
|
||||
* Persist GPT-5 per-turn metadata (previous_response_id only)
|
||||
* onto the last complete assistant say("text") message.
|
||||
*
|
||||
* Note: We do not persist system instructions or reasoning summaries.
|
||||
*/
|
||||
private async persistGpt5Metadata(reasoningMessage?: string): Promise<void> {
|
||||
private async persistGpt5Metadata(): Promise<void> {
|
||||
try {
|
||||
const modelId = this.api.getModel().id
|
||||
if (!modelId || !modelId.startsWith("gpt-5")) return
|
||||
|
|
@ -2875,9 +2877,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
}
|
||||
const gpt5Metadata: Gpt5Metadata = {
|
||||
...(msg.metadata.gpt5 ?? {}),
|
||||
previous_response_id: lastResponseId,
|
||||
instructions: this.lastUsedInstructions,
|
||||
reasoning_summary: (reasoningMessage ?? "").trim() || undefined,
|
||||
...(lastResponseId ? { previous_response_id: lastResponseId } : {}),
|
||||
}
|
||||
msg.metadata.gpt5 = gpt5Metadata
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,18 +12,6 @@ export interface Gpt5Metadata {
|
|||
* Used to maintain conversation continuity in subsequent requests
|
||||
*/
|
||||
previous_response_id?: string
|
||||
|
||||
/**
|
||||
* The system instructions/prompt used for this response
|
||||
* Stored to track what instructions were active when the response was generated
|
||||
*/
|
||||
instructions?: string
|
||||
|
||||
/**
|
||||
* The reasoning summary from GPT-5's reasoning process
|
||||
* Contains the model's internal reasoning if reasoning mode was enabled
|
||||
*/
|
||||
reasoning_summary?: string
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue