From abd8ea30ead0c8feee236e785a76259c8aa014f6 Mon Sep 17 00:00:00 2001 From: versecafe <147033096+versecafe@users.noreply.github.com> Date: Thu, 5 Feb 2026 16:02:00 -0800 Subject: [PATCH] internal: Metrics tweaks --- src/api/schemas.ts | 2 +- src/editor/edit-display-classifier.ts | 8 ++++---- src/editor/inline-edit-provider.ts | 17 +++++++++++------ src/editor/jump-edit-manager.ts | 2 +- src/telemetry/document-tracker.ts | 22 ++++++++++++++++++---- test/edit-display-classifier.test.ts | 6 +++--- 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/api/schemas.ts b/src/api/schemas.ts index 95dfd01..d255f43 100644 --- a/src/api/schemas.ts +++ b/src/api/schemas.ts @@ -76,7 +76,7 @@ export const AutocompleteResponseSchema = z.object({ export const SuggestionTypeSchema = z.enum([ "GHOST_TEXT", "POPUP", - "JUMP", + "JUMP_TO_EDIT", "MULTI", ]); diff --git a/src/editor/edit-display-classifier.ts b/src/editor/edit-display-classifier.ts index d7bef32..b6e7f94 100644 --- a/src/editor/edit-display-classifier.ts +++ b/src/editor/edit-display-classifier.ts @@ -5,7 +5,7 @@ export interface EditDisplayClassification { reason: | "far-from-cursor" | "before-cursor-multiline" - | "before-cursor-single-line-same-row" + | "before-cursor-single-line" | "single-newline-boundary" | "inline-safe"; } @@ -51,10 +51,10 @@ export function classifyEditDisplay( }; } - if (isBeforeCursor && input.editStartLine === input.cursorLine) { + if (isBeforeCursor) { return { - decision: "SUPPRESS", - reason: "before-cursor-single-line-same-row", + decision: "JUMP", + reason: "before-cursor-single-line", }; } diff --git a/src/editor/inline-edit-provider.ts b/src/editor/inline-edit-provider.ts index 7f26cd1..ed02f85 100644 --- a/src/editor/inline-edit-provider.ts +++ b/src/editor/inline-edit-provider.ts @@ -412,9 +412,6 @@ export class InlineEditProvider implements vscode.InlineCompletionItemProvider { const startPosition = document.positionAt(result.startIndex); const endPosition = document.positionAt(result.endIndex); const editRange = new vscode.Range(startPosition, endPosition); - const metricsPayload = buildMetricsPayload(document, result, { - suggestionType: "GHOST_TEXT", - }); console.log("[Sweep] Creating inline edit:", { id: result.id, @@ -428,12 +425,20 @@ export class InlineEditProvider implements vscode.InlineCompletionItemProvider { }); if (result.startIndex < cursorOffset) { - console.log("[Sweep] Edit before cursor cannot be shown as ghost text", { - id: result.id, - }); + console.log( + "[Sweep] Edit before cursor cannot be shown as ghost text; falling back to jump edit", + { + id: result.id, + }, + ); + this.jumpEditManager.setPendingJumpEdit(document, result); return undefined; } + const metricsPayload = buildMetricsPayload(document, result, { + suggestionType: "GHOST_TEXT", + }); + if (this.lastInlineEdit?.payload.id !== metricsPayload.id) { void this.clearInlineEdit("replaced by new inline edit", { hideSuggestion: false, diff --git a/src/editor/jump-edit-manager.ts b/src/editor/jump-edit-manager.ts index d17c2cb..edbb9cc 100644 --- a/src/editor/jump-edit-manager.ts +++ b/src/editor/jump-edit-manager.ts @@ -167,7 +167,7 @@ export class JumpEditManager implements vscode.Disposable { editEndPos, originCursorLine: editor.selection.active.line, metricsPayload: buildMetricsPayload(document, result, { - suggestionType: "JUMP", + suggestionType: "JUMP_TO_EDIT", }), }; diff --git a/src/telemetry/document-tracker.ts b/src/telemetry/document-tracker.ts index 619b646..9a6d99a 100644 --- a/src/telemetry/document-tracker.ts +++ b/src/telemetry/document-tracker.ts @@ -95,9 +95,10 @@ export class DocumentTracker implements vscode.Disposable { for (const change of event.contentChanges) { if (!change.text && change.rangeLength === 0) continue; + const actionPosition = this.getPostChangePosition(event.document, change); this.cursorPositions.set(uri, { - line: change.range.start.line, + line: actionPosition.line, timestamp: now, }); @@ -122,14 +123,14 @@ export class DocumentTracker implements vscode.Disposable { } if (undoRedoActionType) { - undoRedoPosition = change.range.start; + undoRedoPosition = actionPosition; } else { const actionType = this.getActionType(change); - const offset = utf8ByteOffsetAt(event.document, change.range.start); + const offset = utf8ByteOffsetAt(event.document, actionPosition); this.userActions.push({ action_type: actionType, - line_number: change.range.start.line, + line_number: actionPosition.line, offset, file_path: filepath, timestamp: now, @@ -221,6 +222,19 @@ export class DocumentTracker implements vscode.Disposable { return isMultiChar ? "INSERT_SELECTION" : "INSERT_CHAR"; } + private getPostChangePosition( + document: vscode.TextDocument, + change: vscode.TextDocumentContentChangeEvent, + ): vscode.Position { + const insertionEndOffset = change.rangeOffset + change.text.length; + const documentLength = document.getText().length; + const clampedOffset = Math.max( + 0, + Math.min(insertionEndOffset, documentLength), + ); + return document.positionAt(clampedOffset); + } + private getUndoRedoActionType( reason: vscode.TextDocumentChangeReason | undefined, ): Extract | null { diff --git a/test/edit-display-classifier.test.ts b/test/edit-display-classifier.test.ts index 216efb5..d7c953f 100644 --- a/test/edit-display-classifier.test.ts +++ b/test/edit-display-classifier.test.ts @@ -37,7 +37,7 @@ describe("classifyEditDisplay", () => { }); }); - test("returns SUPPRESS for same-line single-line edits before cursor", () => { + test("returns JUMP for same-line single-line edits before cursor", () => { const result = classifyEditDisplay({ cursorLine: 10, editStartLine: 10, @@ -49,8 +49,8 @@ describe("classifyEditDisplay", () => { }); expect(result).toEqual({ - decision: "SUPPRESS", - reason: "before-cursor-single-line-same-row", + decision: "JUMP", + reason: "before-cursor-single-line", }); });