Pular para o conteúdo

AI inline suggest / ghost text

ai-ui specs/ai-ui/inline-suggest.kmd

Copilot-style ghost text autocomplete in any Koder editor surface. Dimmed inline suggestion + Tab/→ to accept + Esc to discard + partial-accept (word/line). Debounce 300ms. Sandbox-isolated streaming from services/ai/gateway. Required for Kode editor, Kortex notebook, future Kanvas.

Quando esta spec se aplica

Triggers primários

Todos os triggers

Corpo da especificação

Spec — AI inline suggest / ghost text

Pattern: GitHub Copilot ghost text + VS Code Next Edit Suggestions. Streams via streaming-text.kmd. Cost transparency via cost-display.kmd (#112).

Princípios

  1. Subtle by default — dimmed (50% opacity) ghost text inline; non-intrusive.
  2. Fast acceptance — Tab/→ accepts full; Cmd+→ word; Cmd+Shift+→ line.
  3. Easy dismiss — Esc OR any keystroke (other than accept keys) cancels.
  4. Debounced trigger — 300ms default after typing pauses.
  5. Cost-aware — every suggestion has token attribution; surfaced in status bar.

R1 — Visual

def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)█  ← ghost suggestion (dimmed)
                                                ▲
                                              cursor
  • Color: text at 50% opacity (per themes/color-roles.kmd).
  • Font: same as editor body (preserve metrics).
  • Background: NONE (transparent overlay).
  • Underline: NONE.

When cursor moves through ghost → ghost text moves accordingly (anchored to cursor position).

R2 — Trigger

ConditionAction
User types → pause 300msTrigger suggestion request
User keeps typingCancel pending request
Cursor movesCancel current ghost
Window blursCancel current ghost

Debounce configurable per-user (200-500ms range).

R3 — Accept modes

KeyAction
TabAccept full suggestion
→ (arrow right)Accept full (alternative — configurable per-OS)
Cmd/Ctrl + →Accept next word
Cmd/Ctrl + Shift + →Accept next line
EscDiscard suggestion
Any printable keyDiscard + new input

Partial accept advances cursor; remaining ghost stays.

R4 — Backend integration

Request via services/ai/gateway:

{
  "type": "inline_suggest",
  "prefix": "...lines before cursor...",
  "suffix": "...lines after cursor...",
  "language": "python",
  "file_path": "lib/math.py",
  "max_tokens": 128,
  "stop_sequences": ["\n\n"]
}

Stream response token-by-token (cross-link streaming-text.kmd):

  • First token within ~500ms (model SLA — surface in cost-display).
  • Display starts rendering at first token.
  • Cancel on any user keystroke after first token already shown.

R5 — Cost transparency

Per-suggestion cost surfaced in editor status bar:

[Editor] · 12 lines · 250 in/45 out · $0.0008

Aggregate session cost via cost-display.kmd (#112).

R6 — Surface enable/disable

User toggle in editor settings:

  • Enabled (default): ghost suggestions appear.
  • Disabled: no requests sent.
  • Manual trigger (Ctrl+Space): only on demand.

Workspace-level + user-level + per-file setting; per-file > workspace > user > stack default.

R7 — Context window

Gateway receives prefix + suffix:

  • Prefix: last N lines before cursor (default 50).
  • Suffix: next M lines after cursor (default 10).
  • File path + language hint per LSP protocol.

Truncated by model context limit — surface warning if file too large for current model.

R8 — Surface bindings

SurfaceAPI
FlutterKoderGhostTextField({onSuggestionAccept, model, gateway}) em koder_kit/lib/src/ai/ghost_text_field.dart
Web<koder-ghost-text-input> (CodeMirror/Monaco extension recommended)
Compose/SwiftUIfuturo
Vim / EmacsLSP server (koder-lsp-suggest)

R9 — Acessibilidade

  • Ghost text: aria-hidden="true" (não anuncia continuously); accept = announce "Suggestion accepted: ".
  • Keyboard shortcuts: documented in aria-keyshortcuts.
  • Reduced-motion: ghost appears instant (no fade-in).
  • Screen reader users: configurable mode "announce all suggestions" (default OFF — noise).

R10 — i18n

Keyen-USpt-BR
ai.suggest.setting.enabled"AI suggestions""Sugestões de IA"
ai.suggest.setting.manual"Manual trigger only""Ativar manualmente"
ai.suggest.accept.full"Suggestion accepted""Sugestão aceita"
ai.suggest.accept.partial"Partial suggestion accepted""Parte da sugestão aceita"
ai.suggest.cost.label"{in}/{out} · {cost}""{in}/{out} · {cost}"

R11 — Multi-tenant

Per-file storage/cost attribution per (koder_user_id, workspace_id, file_id).

T-suite

  • T1 Trigger: type + pause 300ms → suggestion appears.
  • T2 Accept full: Tab → ghost text inserted; cursor at end.
  • T3 Accept word: Cmd+→ → only next word inserted; remaining stays ghost.
  • T4 Accept line: Cmd+Shift+→ → only next line; remaining stays.
  • T5 Esc dismisses: ghost gone.
  • T6 Other keystroke dismisses: user types → ghost gone; new trigger debounce starts.
  • T7 Cursor move cancels: arrow key → ghost gone.
  • T8 Disable: setting OFF → no requests sent.
  • T9 Manual trigger: setting "manual" + Ctrl+Space → suggestion appears.
  • T10 Cost surfaced: each suggestion → status bar updates with cost.
  • T11 Streaming: first token < 500ms (SLA gate via model registry).
  • T12 A11y reduced-motion: ghost appears instant.
  • N1 Large file: file > model context → warning surfaced; suggestions disabled until model switch.
  • Companion: streaming-text.kmd (R4 streaming integration), cost-display.kmd (R5 status bar), model-selector.kmd (model switch affects suggestion quality)
  • Backend: services/ai/gateway/
  • Consumers: products/dev/kdev, future products/dev/kanvas, Kortex notebook
  • Refs: GitHub Copilot ghost text, VS Code Next Edit Suggestions

Referências