Files
HarvmasterandClaude Opus 5.5 87d3c3c3bf
ci / build (push) Canceled after 0s
Extension 0.6.0: next-edit, token healing, TS errors context, cursor-move, prewarm
- shared/nextedit.ts: next-edit prompt format (region rewrite or NO_EDIT, Qwen spare special tokens)
- shared/diagnostics.ts: TS errors near the cursor as context; symbols format 2 adds namespace imports
- shared/prompt.ts: token healing (cut the half-typed word, force it via grammar), errors header section
- daemon: model profiles carry contextFormat/errors/members/nextEdit; /v1/next-edit with edit-burst
  tracking; /v1/prewarm; /v1/debug/last; token healing on by default
- extension: next-edit decorations (Tab apply / Esc dismiss), suggest on cursor move, prewarm on focus,
  Show Last Prompt, update check against releases, diagnostics in the edit recorder
- models/README: training-data attribution; release script profiles for stage-d/stage-e
- .gitea/workflows/ci.yml: build + test, publish release on vscode-v* tags (needs a runner + RELEASE_TOKEN)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J39imRDT8L7xYbWzsVWd8A
2026-10-03 17:21:38 +00:00

65 lines
2.6 KiB
TypeScript

/**
* TypeScript errors near the cursor, as prompt context ("TS errors as context") and for verifying generated
* training data. Shared by the training pipeline and the daemon so the format is identical in both.
*
* Rendered as a pseudo-file in the repo header:
* <|file_sep|>{dir}/__errors__.txt
* TS2304 Cannot find name 'getU'. | const user = getU
*/
export interface Diagnostic {
/** 0-based line in the visible file. */
line: number
code: number
message: string
category: 'error' | 'warning'
}
/**
* Errors that are noise for completion: environment problems (unresolved modules or types when dependencies
* aren't installed) rather than mistakes in the code being written.
*/
export const IGNORED_CODES = new Set([
2307, // Cannot find module
7016, // Could not find a declaration file for module
2792, // Cannot find module. Did you mean to set moduleResolution…
7006, // Parameter implicitly has an 'any' type
7031, // Binding element implicitly has an 'any' type
2875, // JSX tag requires the module path … to exist
6133, // declared but never read (unused), noise while writing
6196, // declared but never used
])
export function relevantDiagnostics(diags: Diagnostic[], cursorLine: number, opts: { window?: number; max?: number } = {}): Diagnostic[] {
const window = opts.window ?? 20
const max = opts.max ?? 8
return diags
.filter(d => !IGNORED_CODES.has(d.code) && Math.abs(d.line - cursorLine) <= window)
.sort((a, b) => Math.abs(a.line - cursorLine) - Math.abs(b.line - cursorLine) || a.line - b.line)
.slice(0, max)
}
/** One line per diagnostic: code, message (first line), and the trimmed source line it points at. */
export function formatDiagnostics(diags: Diagnostic[], visible: string): string {
const lines = visible.split('\n')
return diags.map(d => {
const message = d.message.split('\n')[0].slice(0, 160)
const src = (lines[d.line] ?? '').trim().slice(0, 100)
return `TS${d.code} ${message} | ${src}`
}).join('\n')
}
/** Diagnostics present in `after` but not in `before`, matched by code + message (positions shift with edits). */
export function newDiagnostics(before: Diagnostic[], after: Diagnostic[]): Diagnostic[] {
const counts = new Map<string, number>()
for (const d of before) counts.set(`${d.code}:${d.message}`, (counts.get(`${d.code}:${d.message}`) ?? 0) + 1)
const out: Diagnostic[] = []
for (const d of after) {
const key = `${d.code}:${d.message}`
const n = counts.get(key) ?? 0
if (n > 0) counts.set(key, n - 1)
else if (!IGNORED_CODES.has(d.code)) out.push(d)
}
return out
}