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
- Render AI inline suggestion in any text editor
Todos os triggers
- Build editor with AI-assisted autocomplete
- Implement Koder Kode, Kortex notebook, or Kanvas typing surface
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 viacost-display.kmd(#112).
Princípios
- Subtle by default — dimmed (50% opacity) ghost text inline; non-intrusive.
- Fast acceptance — Tab/→ accepts full; Cmd+→ word; Cmd+Shift+→ line.
- Easy dismiss — Esc OR any keystroke (other than accept keys) cancels.
- Debounced trigger — 300ms default after typing pauses.
- 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:
textat 50% opacity (perthemes/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
| Condition | Action |
|---|---|
| User types → pause 300ms | Trigger suggestion request |
| User keeps typing | Cancel pending request |
| Cursor moves | Cancel current ghost |
| Window blurs | Cancel current ghost |
Debounce configurable per-user (200-500ms range).
R3 — Accept modes
| Key | Action |
|---|---|
| Tab | Accept full suggestion |
| → (arrow right) | Accept full (alternative — configurable per-OS) |
| Cmd/Ctrl + → | Accept next word |
| Cmd/Ctrl + Shift + → | Accept next line |
| Esc | Discard suggestion |
| Any printable key | Discard + 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
| Surface | API |
|---|---|
| Flutter | KoderGhostTextField({onSuggestionAccept, model, gateway}) em koder_kit/lib/src/ai/ghost_text_field.dart |
| Web | <koder-ghost-text-input> (CodeMirror/Monaco extension recommended) |
| Compose/SwiftUI | futuro |
| Vim / Emacs | LSP 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
| Key | en-US | pt-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.
Cross-link
- 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, futureproducts/dev/kanvas, Kortex notebook - Refs: GitHub Copilot ghost text, VS Code Next Edit Suggestions
Referências
meta/docs/stack/specs/ai-ui/streaming-text.kmdmeta/docs/stack/specs/ai-ui/cost-display.kmdmeta/docs/stack/specs/ai-ui/model-selector.kmd