mirror of
https://fastgit.cc/https://github.com/anomalyco/opencode
synced 2026-04-20 21:00:29 +08:00
make single owner of prompt copy/equality
This commit is contained in:
@@ -46,14 +46,14 @@ export type PromptMove = {
|
||||
apply: boolean
|
||||
}
|
||||
|
||||
function copy(prompt: RunPrompt): RunPrompt {
|
||||
export function promptCopy(prompt: RunPrompt): RunPrompt {
|
||||
return {
|
||||
text: prompt.text,
|
||||
parts: structuredClone(prompt.parts),
|
||||
}
|
||||
}
|
||||
|
||||
function same(a: RunPrompt, b: RunPrompt): boolean {
|
||||
export function promptSame(a: RunPrompt, b: RunPrompt): boolean {
|
||||
return a.text === b.text && JSON.stringify(a.parts) === JSON.stringify(b.parts)
|
||||
}
|
||||
|
||||
@@ -171,10 +171,10 @@ export function promptCycle(
|
||||
}
|
||||
|
||||
export function createPromptHistory(items?: RunPrompt[]): PromptHistoryState {
|
||||
const list = (items ?? []).filter((item) => item.text.trim().length > 0).map(copy)
|
||||
const list = (items ?? []).filter((item) => item.text.trim().length > 0).map(promptCopy)
|
||||
const next: RunPrompt[] = []
|
||||
for (const item of list) {
|
||||
if (next.length > 0 && same(next[next.length - 1], item)) {
|
||||
if (next.length > 0 && promptSame(next[next.length - 1], item)) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -193,8 +193,8 @@ export function pushPromptHistory(state: PromptHistoryState, prompt: RunPrompt):
|
||||
return state
|
||||
}
|
||||
|
||||
const next = copy(prompt)
|
||||
if (state.items[state.items.length - 1] && same(state.items[state.items.length - 1], next)) {
|
||||
const next = promptCopy(prompt)
|
||||
if (state.items[state.items.length - 1] && promptSame(state.items[state.items.length - 1], next)) {
|
||||
return {
|
||||
...state,
|
||||
index: null,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// the current model so the footer can pre-select it.
|
||||
import path from "path"
|
||||
import { fileURLToPath } from "url"
|
||||
import { promptCopy, promptSame } from "./prompt.shared"
|
||||
import type { RunInput, RunPrompt } from "./types"
|
||||
|
||||
const LIMIT = 200
|
||||
@@ -23,17 +24,6 @@ export type RunSession = {
|
||||
turns: Turn[]
|
||||
}
|
||||
|
||||
function copy(prompt: RunPrompt): RunPrompt {
|
||||
return {
|
||||
text: prompt.text,
|
||||
parts: structuredClone(prompt.parts),
|
||||
}
|
||||
}
|
||||
|
||||
function same(a: RunPrompt, b: RunPrompt): boolean {
|
||||
return a.text === b.text && JSON.stringify(a.parts) === JSON.stringify(b.parts)
|
||||
}
|
||||
|
||||
function fileName(url: string, filename?: string) {
|
||||
if (filename) {
|
||||
return filename
|
||||
@@ -175,11 +165,11 @@ export function sessionHistory(session: RunSession, limit = LIMIT): RunPrompt[]
|
||||
continue
|
||||
}
|
||||
|
||||
if (out[out.length - 1] && same(out[out.length - 1], turn.prompt)) {
|
||||
if (out[out.length - 1] && promptSame(out[out.length - 1], turn.prompt)) {
|
||||
continue
|
||||
}
|
||||
|
||||
out.push(copy(turn.prompt))
|
||||
out.push(promptCopy(turn.prompt))
|
||||
}
|
||||
|
||||
return out.slice(-limit)
|
||||
|
||||
@@ -133,18 +133,34 @@ describe("run session shared", () => {
|
||||
})
|
||||
})
|
||||
|
||||
test("dedupes consecutive history entries and drops blank prompts", () => {
|
||||
test("dedupes consecutive history entries, drops blanks, and copies prompt parts", () => {
|
||||
const parts = [
|
||||
{
|
||||
type: "agent" as const,
|
||||
name: "scan",
|
||||
source: {
|
||||
start: 0,
|
||||
end: 5,
|
||||
value: "@scan",
|
||||
},
|
||||
},
|
||||
]
|
||||
const session: RunSession = {
|
||||
first: false,
|
||||
turns: [
|
||||
{ prompt: { text: "one", parts: [] }, provider: "openai", model: "gpt-5", variant: "high" },
|
||||
{ prompt: { text: "one", parts: [] }, provider: "openai", model: "gpt-5", variant: "high" },
|
||||
{ prompt: { text: "one", parts }, provider: "openai", model: "gpt-5", variant: "high" },
|
||||
{ prompt: { text: "one", parts: structuredClone(parts) }, provider: "openai", model: "gpt-5", variant: "high" },
|
||||
{ prompt: { text: " ", parts: [] }, provider: "openai", model: "gpt-5", variant: "high" },
|
||||
{ prompt: { text: "two", parts: [] }, provider: "openai", model: "gpt-5", variant: undefined },
|
||||
],
|
||||
}
|
||||
|
||||
expect(sessionHistory(session).map((item) => item.text)).toEqual(["one", "two"])
|
||||
const out = sessionHistory(session)
|
||||
|
||||
expect(out.map((item) => item.text)).toEqual(["one", "two"])
|
||||
expect(out[0]?.parts).toEqual(parts)
|
||||
expect(out[0]?.parts).not.toBe(parts)
|
||||
expect(out[0]?.parts[0]).not.toBe(parts[0])
|
||||
})
|
||||
|
||||
test("returns the latest matching variant for the active model", () => {
|
||||
|
||||
Reference in New Issue
Block a user