feat: 批量上传支持及prompt优化
- 支持多文件批量上传,一次最多10个 - 新增json/toml/yaml格式支持 - 优化inline补全prompt结构,增加边界决策指南 - size计算包含doc_block内容长度 - 超限时显示警告tooltip
This commit is contained in:
+189
-131
@@ -331,124 +331,111 @@ def build_inline_system_prompt(language_id: str = "markdown") -> str:
|
||||
|
||||
Return only the insertion text that should be placed between PREFIX and SUFFIX.
|
||||
|
||||
Hard constraints you must follow:
|
||||
1) Output-only contract:
|
||||
- Output insertion text only.
|
||||
- No explanations, no meta labels, no wrapper quotes around the whole answer.
|
||||
CORE PRINCIPLE: Output insertion text only. No explanations, no meta labels, no wrapper quotes.
|
||||
|
||||
2) Strict math formatting (KaTeX):
|
||||
- If you output any math expression, it must be strict KaTeX-compatible math.
|
||||
- Every formula must be wrapped with either $...$ (inline) or $$...$$ (block).
|
||||
- Never output bare formulas without $ or $$ wrappers.
|
||||
- Exception: If CURSOR_IN_FENCED_CODE_BLOCK=true and CURSOR_FENCE_LANGUAGE is latex/tex/katex,
|
||||
output raw LaTeX without $ or $$ wrappers.
|
||||
PRIORITY 1: CONTEXT AWARENESS (Read these flags from user prompt)
|
||||
- CURSOR_IN_FENCED_CODE_BLOCK: Are you inside a code fence?
|
||||
- CURSOR_FENCE_LANGUAGE: What language is the current fence?
|
||||
- PREFIX_ENDS_WITH_NEWLINE: Does prefix end with newline?
|
||||
- SUFFIX_STARTS_WITH_NEWLINE: Does suffix start with newline?
|
||||
- MERMAID_CONTEXT: Is this a Mermaid diagram context?
|
||||
|
||||
3) Strict code formatting:
|
||||
- Read CURSOR_IN_FENCED_CODE_BLOCK from the user prompt.
|
||||
- If CURSOR_IN_FENCED_CODE_BLOCK=true:
|
||||
- You are already inside a fenced code block.
|
||||
- Never output triple backticks.
|
||||
- Output code lines only.
|
||||
- If CURSOR_IN_FENCED_CODE_BLOCK=false:
|
||||
- Any code output must be in a fenced code block with a language tag:
|
||||
PRIORITY 2: SPECIALIZED CONTENT RULES
|
||||
|
||||
2.1 Code Block Handling:
|
||||
If CURSOR_IN_FENCED_CODE_BLOCK=true:
|
||||
- You are inside a code fence
|
||||
- Output code lines ONLY (no triple backticks)
|
||||
- Use single \\n for code line separation
|
||||
|
||||
If CURSOR_IN_FENCED_CODE_BLOCK=false and code needed:
|
||||
- Wrap code in fenced block with language tag:
|
||||
```{{language}}
|
||||
...
|
||||
code here
|
||||
```
|
||||
- Do not output code snippets as inline backticks.
|
||||
- Choose the language tag from context (no default fallback tag instruction).
|
||||
- Never use inline backticks for code snippets
|
||||
|
||||
4) Mermaid-specific completion rules:
|
||||
- Read CURSOR_FENCE_LANGUAGE and MERMAID_CONTEXT from the user prompt.
|
||||
- If CURSOR_FENCE_LANGUAGE=mermaid:
|
||||
- Output Mermaid statements only.
|
||||
- Never output triple backticks.
|
||||
- Never output prose explanations.
|
||||
- If CURSOR_IN_FENCED_CODE_BLOCK=false and MERMAID_CONTEXT=true:
|
||||
- Output a complete Mermaid fenced block:
|
||||
2.2 Math Formatting (KaTeX):
|
||||
- Inline math: wrap with $...$
|
||||
- Block math: wrap with $$...$$
|
||||
- Never output bare formulas
|
||||
- Exception: inside latex/tex/katex fence, output raw LaTeX
|
||||
|
||||
2.3 Mermaid Diagrams:
|
||||
If CURSOR_FENCE_LANGUAGE=mermaid:
|
||||
- Output Mermaid syntax ONLY
|
||||
- No backticks, no explanations
|
||||
|
||||
If MERMAID_CONTEXT=true and outside fence:
|
||||
- Output complete fenced block:
|
||||
```mermaid
|
||||
...
|
||||
diagram syntax
|
||||
```
|
||||
- Keep Mermaid syntax valid and concise.
|
||||
- Never mix Mermaid code and explanatory narration in one output.
|
||||
|
||||
5) Boundary newline repair:
|
||||
- Read PREFIX_ENDS_WITH_NEWLINE and SUFFIX_STARTS_WITH_NEWLINE from the user prompt.
|
||||
- Carefully reason about whether OUTPUT should start or end with a newline.
|
||||
- If PREFIX lacks a required boundary newline, add it at OUTPUT start.
|
||||
- If SUFFIX lacks a required boundary newline, add it at OUTPUT end.
|
||||
- Ensure PREFIX + OUTPUT + SUFFIX is structurally natural.
|
||||
PRIORITY 3: MARKDOWN STRUCTURE
|
||||
|
||||
6) Context stitching:
|
||||
- Do not repeat text that already appears at the start of SUFFIX.
|
||||
- Preserve nearby language, tone, punctuation, indentation, and markdown structure.
|
||||
- Continue existing structures naturally (lists, tables, block quotes, headings).
|
||||
3.1 Newline Semantics:
|
||||
- Single \\n: soft break (same paragraph, renders as space or <br>)
|
||||
- Double \\n\\n: hard break (new paragraph/block)
|
||||
- Use \\n\\n for: new paragraphs, before headings, starting lists/tables
|
||||
- Use \\n for: continuation within blocks (list items, table cells)
|
||||
- Exception: inside code blocks, use \\n freely for code lines
|
||||
|
||||
7) OCR safety:
|
||||
- PREFIX may include hidden OCR metadata tags like <OCR:...>.
|
||||
- Never output any OCR tag.
|
||||
- Never output OCR tag fragments such as <OCR:...>."""
|
||||
3.2 Boundary Management:
|
||||
Check PREFIX_ENDS_WITH_NEWLINE and SUFFIX_STARTS_WITH_NEWLINE:
|
||||
- If PREFIX lacks needed newline: start OUTPUT with \\n
|
||||
- If SUFFIX lacks needed newline: end OUTPUT with \\n
|
||||
- Common cases requiring leading \\n:
|
||||
* Starting a list after "Steps:"
|
||||
* Creating new paragraph after text
|
||||
* Adding heading after paragraph
|
||||
- Common cases requiring trailing \\n:
|
||||
* Before new heading
|
||||
* End of section
|
||||
|
||||
3.3 Context Stitching:
|
||||
- Never repeat text from SUFFIX beginning
|
||||
- Match PREFIX tone, style, indentation
|
||||
- Continue structures: lists, tables, quotes, headings
|
||||
|
||||
PRIORITY 4: HIDDEN CONTEXT
|
||||
- OCR metadata like <OCR:...> is hidden context
|
||||
- Never copy OCR tags to output
|
||||
- Use OCR content as semantic hint only
|
||||
"""
|
||||
|
||||
if language_guidance:
|
||||
system_prompt = f"{system_prompt.rstrip()}\n{language_guidance.strip()}"
|
||||
system_prompt = f"{system_prompt.rstrip()}\\n{language_guidance.strip()}"
|
||||
|
||||
return system_prompt.strip()
|
||||
|
||||
|
||||
INLINE_EXAMPLES = """[EX01] Prose continuation
|
||||
INLINE_EXAMPLES = """=== CATEGORY A: PROSE CONTINUATION ===
|
||||
|
||||
[EX01] Simple prose continuation
|
||||
<PREFIX>The quick brown fox </PREFIX>
|
||||
<SUFFIX>jumps over the lazy dog.</SUFFIX>
|
||||
Expected OUTPUT:
|
||||
moved quietly and then
|
||||
moved quietly and then
|
||||
|
||||
[EX02] Avoid repeating suffix beginning
|
||||
[EX02] Avoid repeating suffix
|
||||
<PREFIX>Our launch plan starts with </PREFIX>
|
||||
<SUFFIX>phase one, followed by phase two.</SUFFIX>
|
||||
Expected OUTPUT:
|
||||
careful internal testing before
|
||||
careful internal testing before
|
||||
WRONG: phase one starts with (repeats suffix)
|
||||
|
||||
[EX03] Continue markdown checklist
|
||||
=== CATEGORY B: MARKDOWN STRUCTURES ===
|
||||
|
||||
[EX03] Continue checklist
|
||||
<PREFIX>## TODO
|
||||
- [ ] Buy milk
|
||||
- [ ] </PREFIX>
|
||||
<SUFFIX></SUFFIX>
|
||||
Expected OUTPUT:
|
||||
Write release notes and share draft with team
|
||||
Write release notes and share draft with team
|
||||
|
||||
[EX04] Cursor outside code block, code must use fenced block
|
||||
CURSOR_IN_FENCED_CODE_BLOCK=false
|
||||
<PREFIX>Parse this JSON payload in Python:</PREFIX>
|
||||
<SUFFIX></SUFFIX>
|
||||
Expected OUTPUT:
|
||||
```python
|
||||
import json
|
||||
data = json.loads(payload)
|
||||
```
|
||||
|
||||
[EX05] Cursor inside fenced code block, do not output fences
|
||||
CURSOR_IN_FENCED_CODE_BLOCK=true
|
||||
<PREFIX>```python
|
||||
def add(a, b):
|
||||
return </PREFIX>
|
||||
<SUFFIX>
|
||||
```</SUFFIX>
|
||||
Expected OUTPUT:
|
||||
a + b
|
||||
|
||||
[EX06] Inline math must use $...$
|
||||
<PREFIX>The derivative of x^2 is </PREFIX>
|
||||
<SUFFIX>.</SUFFIX>
|
||||
Expected OUTPUT:
|
||||
$2x$
|
||||
|
||||
[EX07] Block math must use $$...$$
|
||||
<PREFIX>We can write the Gaussian integral as:</PREFIX>
|
||||
<SUFFIX></SUFFIX>
|
||||
Expected OUTPUT:
|
||||
$$
|
||||
\\int_{-\\infty}^{\\infty} e^{-x^2}\\,dx = \\sqrt{\\pi}
|
||||
$$
|
||||
|
||||
[EX08] Prefix misses boundary newline; add newline at output start
|
||||
[EX04] Start list after header (PREFIX lacks newline)
|
||||
PREFIX_ENDS_WITH_NEWLINE=false
|
||||
<PREFIX>Deployment steps:</PREFIX>
|
||||
<SUFFIX></SUFFIX>
|
||||
@@ -457,21 +444,7 @@ Expected OUTPUT:
|
||||
- Build artifact
|
||||
- Deploy service
|
||||
|
||||
[EX09] Suffix misses boundary newline; add newline at output end
|
||||
SUFFIX_STARTS_WITH_NEWLINE=false
|
||||
<PREFIX>Summary paragraph complete.</PREFIX>
|
||||
<SUFFIX>## Next Section</SUFFIX>
|
||||
Expected OUTPUT:
|
||||
|
||||
|
||||
[EX10] OCR metadata exists but must never be emitted
|
||||
<PREFIX> <OCR:equation y = mx + b>
|
||||
The relationship is </PREFIX>
|
||||
<SUFFIX>.</SUFFIX>
|
||||
Expected OUTPUT:
|
||||
$y = mx + b$
|
||||
|
||||
[EX11] Continue markdown table with correct row shape
|
||||
[EX05] Continue table row
|
||||
<PREFIX>| Name | Score |
|
||||
| --- | --- |
|
||||
| Alice | 92 |
|
||||
@@ -480,30 +453,91 @@ $y = mx + b$
|
||||
Expected OUTPUT:
|
||||
88 |
|
||||
|
||||
[EX12] Mixed text + math + code in one insertion
|
||||
CURSOR_IN_FENCED_CODE_BLOCK=false
|
||||
<PREFIX>Use the area formula and provide a tiny JS helper.</PREFIX>
|
||||
[EX06] Start new paragraph
|
||||
<PREFIX>First paragraph ends.</PREFIX>
|
||||
<SUFFIX></SUFFIX>
|
||||
Expected OUTPUT:
|
||||
The area is $A = \\pi r^2$.
|
||||
|
||||
```javascript
|
||||
const area = (r) => Math.PI * r * r;
|
||||
Second paragraph starts.
|
||||
WRONG: Second paragraph starts. (missing leading \\n\\n)
|
||||
|
||||
[EX07] Add newline before heading
|
||||
PREFIX_ENDS_WITH_NEWLINE=false
|
||||
<PREFIX>End of previous section.</PREFIX>
|
||||
<SUFFIX>## Next Heading</SUFFIX>
|
||||
Expected OUTPUT:
|
||||
|
||||
WRONG: (would join with heading without separation)
|
||||
|
||||
=== CATEGORY C: CODE BLOCKS ===
|
||||
|
||||
[EX08] Outside fence: wrap code in fence
|
||||
CURSOR_IN_FENCED_CODE_BLOCK=false
|
||||
<PREFIX>Parse this JSON payload in Python:</PREFIX>
|
||||
<SUFFIX></SUFFIX>
|
||||
Expected OUTPUT:
|
||||
```python
|
||||
import json
|
||||
data = json.loads(payload)
|
||||
```
|
||||
WRONG: import json\\ndata = json.loads(payload) (no fence)
|
||||
|
||||
[EX13] Cursor inside mermaid fence: no backticks, mermaid lines only
|
||||
[EX09] Inside fence: output code only
|
||||
CURSOR_IN_FENCED_CODE_BLOCK=true
|
||||
<PREFIX>```python
|
||||
def add(a, b):
|
||||
return </PREFIX>
|
||||
<SUFFIX>
|
||||
```</SUFFIX>
|
||||
Expected OUTPUT:
|
||||
a + b
|
||||
WRONG: ```python\\nreturn a + b\\n``` (duplicate fences)
|
||||
|
||||
[EX10] Code inside fence uses single newline
|
||||
CURSOR_IN_FENCED_CODE_BLOCK=true
|
||||
<PREFIX>```python
|
||||
def hello():</PREFIX>
|
||||
<SUFFIX>
|
||||
```</SUFFIX>
|
||||
Expected OUTPUT:
|
||||
print("Hello")
|
||||
return True
|
||||
(Note: single \\n between code lines, no markdown rules)
|
||||
|
||||
=== CATEGORY D: MATH ===
|
||||
|
||||
[EX11] Inline math
|
||||
<PREFIX>The derivative of x^2 is </PREFIX>
|
||||
<SUFFIX>.</SUFFIX>
|
||||
Expected OUTPUT:
|
||||
$2x$
|
||||
WRONG: 2x (bare formula)
|
||||
|
||||
[EX12] Block math
|
||||
<PREFIX>We can write the Gaussian integral as:</PREFIX>
|
||||
<SUFFIX></SUFFIX>
|
||||
Expected OUTPUT:
|
||||
$$
|
||||
\\int_{-\\infty}^{\\infty} e^{-x^2}\\,dx = \\sqrt{\\pi}
|
||||
$$
|
||||
WRONG: \\int... (bare formula without $$)
|
||||
|
||||
=== CATEGORY E: MERMAID ===
|
||||
|
||||
[EX13] Inside mermaid fence
|
||||
CURSOR_FENCE_LANGUAGE=mermaid
|
||||
CURSOR_IN_FENCED_CODE_BLOCK=true
|
||||
<PREFIX>```mermaid
|
||||
flowchart TD
|
||||
A[Start] --> </PREFIX>
|
||||
A[Start] --> </PREFIX>
|
||||
<SUFFIX>
|
||||
```</SUFFIX>
|
||||
Expected OUTPUT:
|
||||
B{Valid?}
|
||||
B -->|Yes| C[Done]
|
||||
WRONG: ```mermaid\\nB{Valid?}... (duplicate fence)
|
||||
|
||||
[EX14] Mermaid context outside fence: return full mermaid block
|
||||
[EX14] Outside fence with mermaid context
|
||||
CURSOR_IN_FENCED_CODE_BLOCK=false
|
||||
MERMAID_CONTEXT=true
|
||||
<PREFIX>Please provide a simple release pipeline diagram.</PREFIX>
|
||||
@@ -511,8 +545,18 @@ MERMAID_CONTEXT=true
|
||||
Expected OUTPUT:
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Build --> Test --> Deploy
|
||||
```"""
|
||||
Build --> Test --> Deploy
|
||||
```
|
||||
|
||||
=== CATEGORY F: OCR METADATA ===
|
||||
|
||||
[EX15] Use OCR as context, never output
|
||||
<PREFIX> <OCR:equation y = mx + b>
|
||||
The relationship is </PREFIX>
|
||||
<SUFFIX>.</SUFFIX>
|
||||
Expected OUTPUT:
|
||||
$y = mx + b$
|
||||
WRONG: <OCR:equation y = mx + b> (OCR tag in output)"""
|
||||
|
||||
|
||||
def build_completion_prompts(
|
||||
@@ -552,35 +596,49 @@ def build_completion_prompts(
|
||||
preferences_instruction = f"\nUser Preferences:\n{preferences_instruction}"
|
||||
|
||||
user_prompt = f"""Current time: {current_time}{location_info}{preferences_instruction}
|
||||
Reasoning hint: {thinking_level}
|
||||
Editor language id: {safe_language_id}
|
||||
Reasoning level: {thinking_level}
|
||||
Editor language: {safe_language_id}
|
||||
|
||||
Completion state flags:
|
||||
=== STATE FLAGS ===
|
||||
- CURSOR_IN_FENCED_CODE_BLOCK: {"true" if cursor_in_fenced_code_block else "false"}
|
||||
- CURSOR_FENCE_LANGUAGE: {cursor_fence_language}
|
||||
- MERMAID_CONTEXT: {"true" if mermaid_context else "false"}
|
||||
- PREFIX_ENDS_WITH_NEWLINE: {"true" if prefix_ends_with_newline else "false"}
|
||||
- SUFFIX_STARTS_WITH_NEWLINE: {"true" if suffix_starts_with_newline else "false"}
|
||||
|
||||
Task:
|
||||
- Produce the best insertion text at the cursor between PREFIX and SUFFIX.
|
||||
- Keep insertion meaningful and non-empty.
|
||||
- Keep insertion concise unless structure requires more content.
|
||||
=== TASK ===
|
||||
Produce the best insertion text between PREFIX and SUFFIX.
|
||||
Requirements:
|
||||
- Non-empty and meaningful
|
||||
- Concise unless structure needs more
|
||||
- Follows markdown rules in system prompt
|
||||
|
||||
Context notes:
|
||||
- PREFIX may include OCR metadata after image markdown, e.g.  <OCR:description>.
|
||||
- OCR metadata is hidden context and must never be copied into output.
|
||||
- Preserve local style and formatting.
|
||||
=== BOUNDARY DECISION GUIDE ===
|
||||
|
||||
Decision policy:
|
||||
- Prioritize seamless join: PREFIX + OUTPUT + SUFFIX must read naturally.
|
||||
- Do not repeat SUFFIX-leading text.
|
||||
- If uncertain, prefer a complete short phrase/sentence with clear meaning.
|
||||
Step 1: Check PREFIX_ENDS_WITH_NEWLINE
|
||||
If false, ask: "Does output need to start on a new line?"
|
||||
- YES if PREFIX ends with: ":", "steps:", "items:", heading text, or complete sentence before heading
|
||||
- If YES: start output with \\n
|
||||
|
||||
Comprehensive examples:
|
||||
Step 2: Check SUFFIX_STARTS_WITH_NEWLINE
|
||||
If false, ask: "Does output need to end with a newline?"
|
||||
- YES if SUFFIX starts with: heading (##), new paragraph, or list marker
|
||||
- If YES: end output with \\n
|
||||
|
||||
Step 3: Choose newline type
|
||||
- Use \\n\\n for: new paragraphs, before headings, starting lists
|
||||
- Use \\n for: continuing within blocks, list items, table cells
|
||||
- Exception: inside code fences, use \\n freely
|
||||
|
||||
=== CONTEXT NOTES ===
|
||||
- OCR metadata (e.g., <OCR:description>) is hidden context, never copy to output
|
||||
- Match PREFIX tone, style, and indentation
|
||||
- Do not repeat text from SUFFIX beginning
|
||||
|
||||
=== EXAMPLES BY CATEGORY ===
|
||||
{INLINE_EXAMPLES}
|
||||
|
||||
Now produce the insertion.
|
||||
=== NOW COMPLETE THE TASK ===
|
||||
|
||||
<PREFIX>
|
||||
{recent_prefix}
|
||||
|
||||
Reference in New Issue
Block a user