Skip to content
This repository was archived by the owner on May 13, 2026. It is now read-only.

Commit dd5a0c5

Browse files
committed
refactor: update and standardize current input file continuation prompt instructions
1 parent 43402e7 commit dd5a0c5

6 files changed

Lines changed: 33 additions & 25 deletions

File tree

docs/prompt-compatibility.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ OpenAI 文件相关实现:
249249

250250
兼容层现在只保留 `current_input_file` 这一种拆分方式;旧的 `history_split` 已废弃,只保留为兼容旧配置的字段,不再参与请求处理。
251251

252-
- `current_input_file` 默认开启;它用于把“完整上下文”合并进 `DS2API_HISTORY.txt` 上下文文件。当最新 user turn 的纯文本长度达到 `current_input_file.min_chars`(默认 `0`)时,兼容层会上传一个文件名为 `DS2API_HISTORY.txt` 的上下文文件。文件内容会先做 OpenAI 消息标准化,再序列化成按轮次编号的 `DS2API_HISTORY.txt` 风格 transcript,带有 `# DS2API_HISTORY.txt` 标题和 `=== N. ROLE ===` 分段;live prompt 中则只保留一个中性的 user 消息要求模型直接回答最新请求,不再暴露文件名或要求模型读取本地文件
252+
- `current_input_file` 默认开启;它用于把“完整上下文”合并进 `DS2API_HISTORY.txt` 上下文文件。当最新 user turn 的纯文本长度达到 `current_input_file.min_chars`(默认 `0`)时,兼容层会上传一个文件名为 `DS2API_HISTORY.txt` 的上下文文件。文件内容会先做 OpenAI 消息标准化,再序列化成按轮次编号的 `DS2API_HISTORY.txt` 风格 transcript,带有 `# DS2API_HISTORY.txt` 标题和 `=== N. ROLE ===` 分段;live prompt 中则会给出一个 continuation 语气的 user 消息,引导模型从 `DS2API_HISTORY.txt` 的最新状态继续推进,并直接回答最新请求,避免把任务拉回起点
253253
- 如果 `current_input_file.enabled=false`,请求会直接透传,不上传任何拆分上下文文件。
254254
- 旧的 `history_split.enabled` / `history_split.trigger_after_turns` 会被读取进配置对象以保持兼容,但不会触发拆分上传,也不会影响 `current_input_file` 的默认开启。
255255
- 即使触发 `current_input_file` 后 live prompt 被缩短,对客户端回包里的上下文 token 统计,仍会沿用**拆分前的完整 prompt 语义**做计数,而不是按缩短后的占位 prompt 计算;否则会把真实上下文显著算小。
@@ -332,7 +332,7 @@ Prior conversation history and tool progress.
332332

333333
```json
334334
{
335-
"prompt": "<|begin▁of▁sentence|><|System|>原 system / developer\n\nYou have access to these tools: ...<|end▁of▁instructions|><|User|>The current request and prior conversation context have already been provided. Answer the latest user request directly.<|Assistant|>",
335+
"prompt": "<|begin▁of▁sentence|><|System|>原 system / developer\n\nYou have access to these tools: ...<|end▁of▁instructions|><|User|>Continue from the latest state in the attached DS2API_HISTORY.txt context. Treat it as the current working state and answer the latest user request directly.<|Assistant|>",
336336
"ref_file_ids": [
337337
"file-current-input-ignore",
338338
"file-systemprompt",

internal/httpapi/openai/chat/chat_history_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,9 @@ func TestChatCompletionsCurrentInputFilePersistsNeutralPrompt(t *testing.T) {
318318
t.Fatalf("expected uploaded current input file to be persisted in history text")
319319
}
320320
if len(full.Messages) != 1 {
321-
t.Fatalf("expected neutral prompt to be the only persisted message, got %#v", full.Messages)
321+
t.Fatalf("expected continuation prompt to be the only persisted message, got %#v", full.Messages)
322322
}
323-
if !strings.Contains(full.Messages[0].Content, "Answer the latest user request directly.") {
324-
t.Fatalf("expected neutral prompt to be persisted, got %#v", full.Messages[0])
323+
if !strings.Contains(full.Messages[0].Content, "Continue from the latest state in the attached DS2API_HISTORY.txt context.") {
324+
t.Fatalf("expected continuation prompt to be persisted, got %#v", full.Messages[0])
325325
}
326326
}

internal/httpapi/openai/chat/vercel_prepare_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ func TestHandleVercelStreamPrepareAppliesCurrentInputFile(t *testing.T) {
130130
t.Fatalf("expected payload object, got %#v", body["payload"])
131131
}
132132
promptText, _ := payload["prompt"].(string)
133-
if !strings.Contains(promptText, "Answer the latest user request directly.") {
134-
t.Fatalf("expected neutral prompt, got %s", promptText)
133+
if !strings.Contains(promptText, "Continue from the latest state in the attached DS2API_HISTORY.txt context.") {
134+
t.Fatalf("expected continuation prompt, got %s", promptText)
135135
}
136136
if strings.Contains(promptText, "first user turn") || strings.Contains(promptText, "latest user turn") {
137137
t.Fatalf("expected original turns hidden from prompt, got %s", promptText)

internal/httpapi/openai/history/current_input_file.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func (s Service) ApplyCurrentInputFile(ctx context.Context, a *auth.RequestAuth,
6262
stdReq.RefFileIDs = prependUniqueRefFileID(stdReq.RefFileIDs, fileID)
6363
stdReq.FinalPrompt, stdReq.ToolNames = promptcompat.BuildOpenAIPrompt(messages, stdReq.ToolsRaw, "", stdReq.ToolChoice, stdReq.Thinking)
6464
// Token accounting must reflect the actual downstream context:
65-
// the uploaded DS2API_HISTORY.txt file content + the neutral live prompt.
65+
// the uploaded DS2API_HISTORY.txt file content + the continuation live prompt.
6666
stdReq.PromptTokenText = fileText + "\n" + stdReq.FinalPrompt
6767
return stdReq, nil
6868
}
@@ -87,5 +87,5 @@ func latestUserInputForFile(messages []any) (int, string) {
8787
}
8888

8989
func currentInputFilePrompt() string {
90-
return "The current request and prior conversation context have already been provided. Answer the latest user request directly."
90+
return "Continue from the latest state in the attached DS2API_HISTORY.txt context. Treat it as the current working state and answer the latest user request directly."
9191
}

internal/httpapi/openai/history_split_test.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -303,11 +303,11 @@ func TestApplyCurrentInputFileUploadsFirstTurnWithNumberedHistoryTranscript(t *t
303303
if strings.Contains(out.FinalPrompt, "first turn content that is long enough") {
304304
t.Fatalf("expected current input text to be replaced in live prompt, got %s", out.FinalPrompt)
305305
}
306-
if strings.Contains(out.FinalPrompt, "CURRENT_USER_INPUT.txt") || strings.Contains(out.FinalPrompt, "DS2API_HISTORY.txt") || strings.Contains(out.FinalPrompt, "DS2API_HISTORY.txt") || strings.Contains(out.FinalPrompt, "Read that file") {
306+
if strings.Contains(out.FinalPrompt, "CURRENT_USER_INPUT.txt") || strings.Contains(out.FinalPrompt, "Read that file") {
307307
t.Fatalf("expected live prompt not to instruct file reads, got %s", out.FinalPrompt)
308308
}
309-
if !strings.Contains(out.FinalPrompt, "Answer the latest user request directly.") {
310-
t.Fatalf("expected neutral continuation instruction in live prompt, got %s", out.FinalPrompt)
309+
if !strings.Contains(out.FinalPrompt, "Continue from the latest state in the attached DS2API_HISTORY.txt context.") {
310+
t.Fatalf("expected continuation-oriented prompt in live prompt, got %s", out.FinalPrompt)
311311
}
312312
if len(out.RefFileIDs) != 1 || out.RefFileIDs[0] != "file-inline-1" {
313313
t.Fatalf("expected current input file id in ref_file_ids, got %#v", out.RefFileIDs)
@@ -358,8 +358,8 @@ func TestApplyCurrentInputFilePreservesFullContextPromptForTokenCounting(t *test
358358
if !strings.Contains(out.PromptTokenText, "# DS2API_HISTORY.txt") || !strings.Contains(out.PromptTokenText, "=== 1. SYSTEM ===") {
359359
t.Fatalf("expected prompt token text to include numbered history transcript, got %q", out.PromptTokenText)
360360
}
361-
if !strings.Contains(out.PromptTokenText, "Answer the latest user request directly.") {
362-
t.Fatalf("expected prompt token text to also include neutral live prompt, got %q", out.PromptTokenText)
361+
if !strings.Contains(out.PromptTokenText, "Continue from the latest state in the attached DS2API_HISTORY.txt context.") {
362+
t.Fatalf("expected prompt token text to also include continuation prompt, got %q", out.PromptTokenText)
363363
}
364364
if strings.Contains(out.FinalPrompt, "first user turn") || strings.Contains(out.FinalPrompt, "latest user turn") {
365365
t.Fatalf("expected live prompt to hide original turns, got %q", out.FinalPrompt)
@@ -406,11 +406,11 @@ func TestApplyCurrentInputFileUploadsFullContextFile(t *testing.T) {
406406
t.Fatalf("expected full context file to contain %q, got %q", want, uploadedText)
407407
}
408408
}
409-
if strings.Contains(out.FinalPrompt, "first user turn") || strings.Contains(out.FinalPrompt, "latest user turn") || strings.Contains(out.FinalPrompt, "CURRENT_USER_INPUT.txt") || strings.Contains(out.FinalPrompt, "DS2API_HISTORY.txt") || strings.Contains(out.FinalPrompt, "DS2API_HISTORY.txt") || strings.Contains(out.FinalPrompt, "Read that file") {
410-
t.Fatalf("expected live prompt to use only a neutral continuation instruction, got %s", out.FinalPrompt)
409+
if strings.Contains(out.FinalPrompt, "first user turn") || strings.Contains(out.FinalPrompt, "latest user turn") || strings.Contains(out.FinalPrompt, "CURRENT_USER_INPUT.txt") || strings.Contains(out.FinalPrompt, "Read that file") {
410+
t.Fatalf("expected live prompt to use only a continuation instruction, got %s", out.FinalPrompt)
411411
}
412-
if !strings.Contains(out.FinalPrompt, "Answer the latest user request directly.") {
413-
t.Fatalf("expected neutral continuation instruction in live prompt, got %s", out.FinalPrompt)
412+
if !strings.Contains(out.FinalPrompt, "Continue from the latest state in the attached DS2API_HISTORY.txt context.") {
413+
t.Fatalf("expected continuation-oriented prompt in live prompt, got %s", out.FinalPrompt)
414414
}
415415
}
416416

@@ -496,8 +496,8 @@ func TestChatCompletionsCurrentInputFileUploadsContextAndKeepsNeutralPrompt(t *t
496496
t.Fatal("expected completion payload to be captured")
497497
}
498498
promptText, _ := ds.completionReq["prompt"].(string)
499-
if !strings.Contains(promptText, "Answer the latest user request directly.") {
500-
t.Fatalf("expected neutral completion prompt, got %s", promptText)
499+
if !strings.Contains(promptText, "Continue from the latest state in the attached DS2API_HISTORY.txt context.") {
500+
t.Fatalf("expected continuation-oriented prompt, got %s", promptText)
501501
}
502502
if strings.Contains(promptText, "first user turn") || strings.Contains(promptText, "latest user turn") {
503503
t.Fatalf("expected prompt to hide original turns, got %s", promptText)
@@ -556,8 +556,8 @@ func TestResponsesCurrentInputFileUploadsContextAndKeepsNeutralPrompt(t *testing
556556
t.Fatal("expected completion payload to be captured")
557557
}
558558
promptText, _ := ds.completionReq["prompt"].(string)
559-
if !strings.Contains(promptText, "Answer the latest user request directly.") {
560-
t.Fatalf("expected neutral completion prompt, got %s", promptText)
559+
if !strings.Contains(promptText, "Continue from the latest state in the attached DS2API_HISTORY.txt context.") {
560+
t.Fatalf("expected continuation-oriented prompt, got %s", promptText)
561561
}
562562
if strings.Contains(promptText, "first user turn") || strings.Contains(promptText, "latest user turn") {
563563
t.Fatalf("expected prompt to hide original turns, got %s", promptText)
@@ -706,7 +706,7 @@ func TestCurrentInputFileWorksAcrossAutoDeleteModes(t *testing.T) {
706706
t.Fatalf("expected completion payload for mode=%s", mode)
707707
}
708708
promptText, _ := ds.completionReq["prompt"].(string)
709-
if !strings.Contains(promptText, "Answer the latest user request directly.") || strings.Contains(promptText, "first user turn") || strings.Contains(promptText, "latest user turn") {
709+
if !strings.Contains(promptText, "Continue from the latest state in the attached DS2API_HISTORY.txt context.") || strings.Contains(promptText, "first user turn") || strings.Contains(promptText, "latest user turn") {
710710
t.Fatalf("unexpected prompt for mode=%s: %s", mode, promptText)
711711
}
712712
})

webui/src/features/chatHistory/ChatHistoryContainer.jsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@ const TOOL_MARKER = '<|Tool|>'
1616
const END_INSTRUCTIONS_MARKER = '<|end▁of▁instructions|>'
1717
const END_SENTENCE_MARKER = '<|end▁of▁sentence|>'
1818
const END_TOOL_RESULTS_MARKER = '<|end▁of▁toolresults|>'
19-
const CURRENT_INPUT_FILE_PROMPT = 'The current request and prior conversation context have already been provided. Answer the latest user request directly.'
19+
const CURRENT_INPUT_FILE_PROMPT = 'Continue from the latest state in the attached DS2API_HISTORY.txt context. Treat it as the current working state and answer the latest user request directly.'
20+
const LEGACY_CURRENT_INPUT_FILE_PROMPTS = new Set([
21+
'The current request and prior conversation context have already been provided. Answer the latest user request directly.',
22+
])
23+
24+
function isCurrentInputFilePrompt(value) {
25+
const text = String(value || '').trim()
26+
return text === CURRENT_INPUT_FILE_PROMPT || LEGACY_CURRENT_INPUT_FILE_PROMPTS.has(text)
27+
}
2028

2129
function formatDateTime(value, lang) {
2230
if (!value) return '-'
@@ -312,7 +320,7 @@ function buildListModeMessages(item, t) {
312320

313321
const placeholderOnly = liveMessages.length === 1
314322
&& String(liveMessages[0]?.role || '').trim().toLowerCase() === 'user'
315-
&& String(liveMessages[0]?.content || '').trim() === CURRENT_INPUT_FILE_PROMPT
323+
&& isCurrentInputFilePrompt(liveMessages[0]?.content)
316324

317325
if (placeholderOnly) {
318326
return { messages: historyMessages, historyMerged: true }

0 commit comments

Comments
 (0)