2026-01-18 19:42:58 +08:00
from typing import Tuple
2026-02-16 22:49:32 +08:00
from datetime import datetime , timezone , timedelta
2026-02-19 10:34:31 +08:00
def _get_current_datetime ( timezone_pref : str = "auto" ) -> str :
# Default to UTC+8 if auto or not specified
offset = 8
tz_info = " (UTC+8)"
if timezone_pref and timezone_pref != 'auto' :
# Try to parse something like "UTC+8" or "GMT+8"
import re
match = re . search ( r '([+-])(\d+)' , timezone_pref )
if match :
sign = match . group ( 1 )
hours = int ( match . group ( 2 ))
offset = hours if sign == '+' else - hours
tz_info = f " ( { timezone_pref } )"
else :
tz_info = f " ( { timezone_pref } )"
now = datetime . now ( timezone ( timedelta ( hours = offset )))
2026-02-16 22:49:32 +08:00
weekdays = [ "星期一" , "星期二" , "星期三" , "星期四" , "星期五" , "星期六" , "星期日" ]
weekday = weekdays [ now . weekday ()]
2026-02-19 10:34:31 +08:00
return f " { now . year } 年 { now . month } 月 { now . day } 日 { weekday } { now . hour : 02d } : { now . minute : 02d } : { now . second : 02d }{ tz_info } "
2026-01-18 19:42:58 +08:00
2026-02-14 18:28:37 +08:00
def _sanitize_language_id ( language_id : str ) -> str :
if not language_id :
return "markdown"
allowed = []
for ch in language_id . strip ():
if ch . isalnum () or ch in "-_+." :
allowed . append ( ch )
value = "" . join ( allowed )[: 32 ]
return value or "markdown"
def _prepare_context ( prefix : str , suffix : str ) -> Tuple [ str , str ]:
2026-01-18 19:42:58 +08:00
"""
2026-02-14 18:28:37 +08:00
Prepare prefix/suffix for model completion context.
2026-02-19 11:14:43 +08:00
Filter out potential web-scraping or legacy artifacts like <br>, <br/>, <br\>.
2026-01-18 19:42:58 +08:00
"""
2026-02-19 11:14:43 +08:00
import re
br_pattern = re . compile ( r '<br\s*/?\s* \\ ?>' , re . IGNORECASE )
clean_prefix = br_pattern . sub ( '' , prefix or "" )
clean_suffix = br_pattern . sub ( '' , suffix or "" )
return clean_prefix , clean_suffix
2026-02-15 15:44:09 +08:00
def prepare_prompt_context ( prefix : str , suffix : str ) -> Tuple [ str , str ]:
return _prepare_context ( prefix , suffix )
2026-02-14 18:28:37 +08:00
2026-02-19 10:22:27 +08:00
def build_prompt (
prefix : str ,
suffix : str ,
language_id : str = "markdown" ,
location : str = "" ,
thinking_level : str = "low" ,
preferences : object = None
) -> str :
2026-02-14 18:28:37 +08:00
safe_language_id = _sanitize_language_id ( language_id )
recent_prefix , recent_suffix = _prepare_context ( prefix , suffix )
2026-02-19 10:34:31 +08:00
tz_pref = preferences . timezone if preferences else "auto"
current_time = _get_current_datetime ( tz_pref )
2026-02-18 08:59:28 +08:00
location_info = f " \n User location: { location } " if location else ""
2026-02-19 10:22:27 +08:00
pref_info = []
if preferences :
if preferences . language and preferences . language != 'auto' :
pref_info . append ( f "Preferred language: { preferences . language } " )
if preferences . currency and preferences . currency != 'auto' :
pref_info . append ( f "Preferred currency: { preferences . currency } " )
preferences_instruction = " \n " . join ( pref_info )
if preferences_instruction :
preferences_instruction = f " \n User Preferences: \n { preferences_instruction } "
prompt = f """Current time: { current_time }{ location_info }{ preferences_instruction }
2026-02-14 18:28:37 +08:00
2026-02-16 22:49:32 +08:00
You are an inline completion engine for a { safe_language_id } editor with ghost-text suggestions.
2026-02-14 18:28:37 +08:00
Your job:
- Return ONLY the text that should be inserted at the cursor between PREFIX and SUFFIX.
- Prefer a meaningful, non-empty insertion with moderate length.
2026-02-19 10:34:31 +08:00
- Avoid overly short outputs with little information value.
2026-02-14 18:28:37 +08:00
Important context:
2026-02-14 23:53:26 +08:00
- PREFIX may contain OCR metadata inline after images, e.g.  <OCR:description>.
- The <OCR:...> is hidden context describing image content.
- Never copy, rewrite, or emit OCR tags in output.
- Never output <OCR: or >.
2026-02-14 18:28:37 +08:00
Hard rules:
1. Seamless join:
PREFIX + OUTPUT + SUFFIX must read naturally as one continuous document.
2. No suffix repetition:
Do NOT repeat text that already appears at the start of SUFFIX.
3. Balanced length:
Prefer concise but meaningful continuation, not ultra-short fragments.
2026-02-15 22:17:37 +08:00
Default target is 10-500 characters and 1-20 lines for plain prose.
2026-02-15 15:44:09 +08:00
You may be longer when structure requires it (lists, tables, code blocks, math blocks).
2026-02-14 18:28:37 +08:00
4. Avoid trivial output:
Do not output only punctuation or filler such as ".", ",", ";", ":".
Do not output just one token unless it is structurally necessary.
5. Preserve local style:
Match nearby language, tone, punctuation, spacing, and indentation.
6. Markdown awareness:
Continue active list/checkbox/ordered-list patterns when applicable.
Preserve indentation in nested list/code contexts.
2026-02-15 15:44:09 +08:00
You may output full markdown structures when context needs them: headings, lists, tables, fenced code blocks, blockquotes, and LaTeX ($...$ / $$...$$).
2026-02-14 18:28:37 +08:00
Close obvious unclosed inline markdown markers only when needed to bridge.
7. Strict output format:
Output insertion text only.
2026-02-15 15:44:09 +08:00
No explanations, labels, or wrapper quotes around the whole output.
Markdown syntax is allowed when it is the intended insertion (including fenced code blocks and LaTeX).
2026-02-14 18:28:37 +08:00
Decision policy:
- If PREFIX already connects naturally to SUFFIX, add a brief but useful continuation when possible.
- If uncertain, prefer a complete short phrase or sentence with clear meaning.
Examples:
2026-02-13 21:17:45 +08:00
<PREFIX>The quick brown fox </PREFIX>
<SUFFIX>jumps over the lazy dog.</SUFFIX>
2026-02-14 18:28:37 +08:00
Output: "moved quietly and then "
2026-02-13 21:17:45 +08:00
2026-02-14 18:28:37 +08:00
<PREFIX>## TODO \\ n- [ ] Buy milk \\ n- [ ] </PREFIX>
2026-02-13 21:17:45 +08:00
<SUFFIX></SUFFIX>
2026-02-14 18:28:37 +08:00
Output: "Write release notes and share draft with team"
2026-02-13 21:17:45 +08:00
2026-02-14 18:28:37 +08:00
Now produce the insertion.
2026-01-18 19:42:58 +08:00
2026-02-13 21:17:45 +08:00
<PREFIX>
{ recent_prefix }
</PREFIX>
2026-01-18 19:42:58 +08:00
2026-02-13 21:17:45 +08:00
<SUFFIX>
{ recent_suffix }
</SUFFIX>
2026-02-07 08:53:37 +08:00
2026-02-13 21:17:45 +08:00
Output:"""
2026-02-14 18:28:37 +08:00
2026-01-18 19:42:58 +08:00
return prompt . strip ()