Skip to content

feat(cloud-agent): prompt autocomplete (ghost text)#2119

Closed
kilo-code-bot[bot] wants to merge 1 commit intomainfrom
mark/cloud-agent-chat-autocomplete-monorepo
Closed

feat(cloud-agent): prompt autocomplete (ghost text)#2119
kilo-code-bot[bot] wants to merge 1 commit intomainfrom
mark/cloud-agent-chat-autocomplete-monorepo

Conversation

@kilo-code-bot
Copy link
Copy Markdown
Contributor

@kilo-code-bot kilo-code-bot Bot commented Apr 7, 2026

Summary

Recreates PR #5 by @markijbema on the monorepo main, as requested by @jeanduplessis.

  • Adds cloudAgent.getFimAutocomplete tRPC mutation backed by Mistral Codestral FIM endpoint
  • Adds useChatGhostText hook in cloud-agent-next with debounced completion requests and stale-request guard
  • Adds ghost text overlay rendering in cloud-agent-next/ChatInput; accept with Tab (full), ArrowRight (next word), or dismiss with Escape
  • Improves sendProxiedChatCompletion error handling to catch network failures and JSON parse errors gracefully

Verification

  • TypeScript typecheck passes (tsgo --noEmit -p apps/web/tsconfig.json)
  • Format check passes (oxfmt)

Visual Changes

N/A (ghost text overlay is invisible until a suggestion is returned)

Reviewer Notes

  • The getFimAutocomplete endpoint uses generateApiToken with internalApiUse: true to bypass abuse heuristics, consistent with the original PR's intent
  • The hook targets trpc.cloudAgent.getFimAutocomplete (not cloudAgentNext) since the FIM endpoint is user-scoped, not session-scoped
  • Files moved from src/components/cloud-agent/apps/web/src/components/cloud-agent-next/ and src/routers/apps/web/src/routers/ per monorepo structure

Closes #5

Implements ghost-text prompt autocomplete for the Cloud Agent chat input
(based on original PR #5 by @markijbema, rebased on monorepo main).

- Adds `cloudAgent.getFimAutocomplete` tRPC mutation using Mistral Codestral FIM
- Adds `useChatGhostText` hook with debounced completion requests
- Adds ghost text overlay rendering in `cloud-agent-next` ChatInput
- Accept suggestion: Tab (all), ArrowRight (next word), Escape clears
- Improves error handling in `sendProxiedChatCompletion`
const newCursorPos = selectionStart + text.length;
textarea.setSelectionRange(newCursorPos, newCursorPos);
// Trigger input event so React sees the change
textarea.dispatchEvent(new Event('input', { bubbles: true }));
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Accepting a suggestion does not reliably sync the controlled textarea state

This helper mutates textarea.value directly and then relies on a synthetic input event to drive onChange, but the textarea is controlled by React via value={value}. React's value tracker usually treats programmatic element.value = ... writes as already observed, so onChange may never fire here. When that happens the accepted text can disappear on the next render or leave derived UI like the send-button disabled state out of sync.

} catch (error) {
debugCloudAgentAutocomplete('error', error);
// Silently ignore errors - just don't show ghost text
setGhostText('');
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Stale failed requests can erase a newer completion

The success path only updates ghostText when requestId === completionRequestIdRef.current, but this catch block always calls setGhostText(''). If request A fails after request B has already started or populated a suggestion, A will clear B's result even though it is stale. The error path needs the same request-id guard as the success path.

// Ignore keyboard events during IME composition (Chinese, Japanese, Korean input)
if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return;

if (handleGhostTextKeyDown(e)) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Ghost-text shortcuts now take precedence over slash-command shortcuts

handleGhostTextKeyDown runs before the existing slash-command autocomplete logic. When the input starts with / and a ghost suggestion is present, pressing Tab will accept ghost text instead of selecting the highlighted slash command, which regresses the current slash-command keyboard flow. Slash-command handling should keep precedence while that popover is open.

@kilo-code-bot
Copy link
Copy Markdown
Contributor Author

kilo-code-bot Bot commented Apr 7, 2026

Code Review Summary

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 3
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
apps/web/src/components/cloud-agent-next/hooks/useChatGhostText.ts 29 Programmatic textarea mutation can bypass React state updates when accepting a suggestion.
apps/web/src/components/cloud-agent-next/hooks/useChatGhostText.ts 118 A stale failed request can clear a newer ghost-text suggestion.
apps/web/src/components/cloud-agent-next/ChatInput.tsx 182 Ghost-text keyboard handling takes precedence over slash-command shortcuts and changes existing Tab behavior.
Other Observations (not in diff)

No additional issues found outside the diff.

Files Reviewed (7 files)
  • apps/web/src/app/globals.css - 0 issues
  • apps/web/src/components/cloud-agent-next/ChatInput.tsx - 1 issue
  • apps/web/src/components/cloud-agent-next/hooks/useChatGhostText.ts - 2 issues
  • apps/web/src/lib/cloud-agent/chat-completion.ts - 0 issues
  • apps/web/src/lib/llm-proxy-helpers.ts - 0 issues
  • apps/web/src/routers/cloud-agent-router.ts - 0 issues
  • apps/web/src/routers/cloud-agent-schemas.ts - 0 issues

Reviewed by gpt-5.4-20260305 · 489,292 tokens

@markijbema
Copy link
Copy Markdown
Contributor

Closing to recreate as a new PR

@markijbema markijbema closed this Apr 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant