feat: add language synonym mapping and canonicalization
Add LANGUAGE_SYNONYMS dictionary to map language aliases to canonical IDs, _canonical_language_id() to normalize language identifiers, and _language_guidance() to provide language-specific instructions for LLM code generation. This improves language detection and ensures consistent prompt context across different language format variations.
This commit is contained in:
@@ -18,7 +18,7 @@ interface CopilotState {
|
||||
}
|
||||
|
||||
interface CopilotConfig {
|
||||
fetchSuggestion: (prefix: string, suffix: string, signal?: AbortSignal) => Promise<string>
|
||||
fetchSuggestion: (prefix: string, suffix: string, languageId: string, signal?: AbortSignal) => Promise<string>
|
||||
debounceMs?: number
|
||||
}
|
||||
|
||||
@@ -187,6 +187,52 @@ function normalizeSuggestionText(raw: string): string {
|
||||
return text
|
||||
}
|
||||
|
||||
function sanitizeLanguageId(value: string): string {
|
||||
if (!value) return ''
|
||||
const trimmed = value.trim()
|
||||
if (!trimmed) return ''
|
||||
let safe = ''
|
||||
for (const ch of trimmed) {
|
||||
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch === '-' || ch === '_' || ch === '+' || ch === '.') {
|
||||
safe += ch
|
||||
}
|
||||
}
|
||||
return safe.slice(0, 32).toLowerCase()
|
||||
}
|
||||
|
||||
function getCodeBlockLanguage(node: ProseNode): string {
|
||||
const candidates = [node.attrs?.language, node.attrs?.lang, node.attrs?.info]
|
||||
for (const value of candidates) {
|
||||
if (typeof value === 'string' && value.trim()) {
|
||||
return value.trim()
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
function getCursorLanguageId(view: EditorView): string {
|
||||
const fallback = 'markdown'
|
||||
const { $from } = view.state.selection
|
||||
|
||||
for (let depth = $from.depth; depth > 0; depth -= 1) {
|
||||
const node = $from.node(depth)
|
||||
const typeName = node.type?.name || ''
|
||||
|
||||
if (typeName === 'math_inline' || typeName === 'math_block' || typeName === 'latex' || typeName === 'math') {
|
||||
return 'latex'
|
||||
}
|
||||
|
||||
if (typeName === 'code_block' || typeName === 'codeBlock' || typeName === 'code_fence' || typeName === 'fence') {
|
||||
const lang = sanitizeLanguageId(getCodeBlockLanguage(node))
|
||||
if (!lang) return fallback
|
||||
if (lang === 'tex' || lang === 'latex' || lang === 'katex') return 'latex'
|
||||
return lang
|
||||
}
|
||||
}
|
||||
|
||||
return fallback
|
||||
}
|
||||
|
||||
async function insertGhostText(view: EditorView, suggestion: string, from: number, ctx: Ctx) {
|
||||
if (!suggestion) return
|
||||
|
||||
@@ -303,7 +349,8 @@ function doFetchSuggestion(
|
||||
const controller = new AbortController()
|
||||
runtime.abortController = controller
|
||||
|
||||
config.fetchSuggestion(prefix, suffix, controller.signal)
|
||||
const languageId = getCursorLanguageId(view)
|
||||
config.fetchSuggestion(prefix, suffix, languageId, controller.signal)
|
||||
.then((suggestion) => {
|
||||
if (!runtime.enabled) return
|
||||
if (runtime.requestSeq !== requestSeq) return
|
||||
|
||||
+12
-2
@@ -60,7 +60,17 @@ async function getClientIP() {
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchSuggestion(prefix, suffix, signal, apiUrl = API_URL) {
|
||||
export async function fetchSuggestion(prefix, suffix, languageId, signal, apiUrl = API_URL) {
|
||||
let normalizedLanguageId = 'markdown'
|
||||
if (typeof languageId === 'string' && languageId.trim()) {
|
||||
normalizedLanguageId = languageId.trim()
|
||||
} else if (languageId && typeof languageId === 'object' && 'aborted' in languageId) {
|
||||
signal = languageId
|
||||
}
|
||||
if (typeof signal === 'string') {
|
||||
apiUrl = signal
|
||||
signal = undefined
|
||||
}
|
||||
const requestId = generateRequestId()
|
||||
const cancelUrl = getCancelUrl(apiUrl)
|
||||
|
||||
@@ -94,7 +104,7 @@ export async function fetchSuggestion(prefix, suffix, signal, apiUrl = API_URL)
|
||||
const body = {
|
||||
prefix,
|
||||
suffix,
|
||||
languageId: 'markdown',
|
||||
languageId: normalizedLanguageId,
|
||||
model_thinking: settings.modelThinking,
|
||||
privacy_mode: settings.privacyMode,
|
||||
user_preferences: {
|
||||
|
||||
Reference in New Issue
Block a user