Skip to content

Conversation

@ThomasK33
Copy link
Member

Add support for @file mentions in chat input so the model can receive file context automatically.

  • Frontend: @-triggered file path autocomplete in ChatInput (reuses CommandSuggestions)
  • Backend: workspace.getFileCompletions endpoint backed by git ls-files -co --exclude-standard with a short TTL cache
  • Backend: request-time expansion of @path / @path#Lx-y into a synthetic user message containing <mux-file> blocks

Tests:

  • make static-check

📋 Implementation Plan

Plan: @file mentions (@path.ts / @path.ts#L1-30) for instant file context

Does this idea make sense?

Yes—this is a sensible and common workflow improvement: it lets the model start from the code instead of spending turns calling file_read for obvious context.

It will “work” as long as we put guardrails around:

  • Context window / cost: whole files can be large; we need size limits + clear truncation messaging.
  • Security/safety: ensure paths stay inside the workspace root (no .. traversal), and handle binary/huge files safely.
  • UX transparency: ideally make it clear which files/ranges were included (without dumping full content into the chat UI).

Recommended implementation: Server-side expansion at request-build time

Net LoC (product code only): ~600–900

Why this approach

  • Keeps chat history clean (we do not persist megabytes of file text into chat.jsonl).
  • Guarantees the model sees current on-disk file contents at send time.
  • Reuses existing “synthetic/context injection” patterns in the request pipeline.

Non-goals (initial cut)

  • No automatic re-injection of mentioned files on subsequent turns.
  • No directory mentions (e.g. @src/) beyond autocomplete convenience.
  • No line-range autocomplete (we only parse/validate it on send).

Syntax + semantics (spec)

  • @relative/path/to/file.ts
    • Includes entire file (subject to size caps).
  • @relative/path/to/file.ts#L1-30
    • Includes inclusive lines 1..30.
  • Parsing rules (MVP):
    • Mention starts at @ and runs until whitespace.
    • Path must resolve within the workspace root after normalization.
    • #L<start>-<end> is optional; start/end are positive ints; start <= end.
Formatting shown to the model (proposed)

Inject a single synthetic user message immediately before the user’s prompt:

<mux-file path="src/foo.ts" range="L1-L30">
```ts
// contents here
```

If truncated:

<mux-file path="src/foo.ts" range="L1-L500" truncated="true">
...
</mux-file>

This mirrors existing “system update”/attachment rendering conventions while staying plain-text compatible.


Work breakdown

1) Frontend: @ file-path autocomplete in ChatInput

  • Reuse the existing suggestions UI (CommandSuggestions) used for slash commands.
  • Add a lightweight “at-mention” suggestion provider:
    • Detect whether the cursor is currently inside an @... token.
    • Query backend for candidate paths (debounced) and show top N.
    • On selection: replace the partial token with @<relativePath>.

Touch points (expected):

  • src/browser/components/ChatInput/index.tsx (detect @ token, render suggestions, replace text)
  • src/browser/components/CommandSuggestions.tsx (reuse existing suggestions dropdown)
  • New helpers: src/browser/utils/atMentions/{parser,suggestions,types}.ts

Implementation notes:

  • Keep this separate from slash commands to reduce risk.
  • Prefer workspace-relative display and replacement.

2) Backend: file completion API

  • Schema: src/common/orpc/schemas/api.ts (add workspace.getFileCompletions)
  • Handler: src/node/orpc/router.ts under workspace: { ... }
    Add a dedicated endpoint to avoid per-keystroke directory scans:
  • workspace.getFileCompletions({ workspaceId, query, limit }) -> { paths: string[] }
  • Implementation (fast path):
    • Use git ls-files (and optionally --others --exclude-standard) in the workspace root.
    • Filter + rank matches server-side; return top ~20.
    • Cache per workspace (short TTL or keyed by .git/index mtime) to keep typing responsive.

3) Backend: expand @file mentions into model-visible context

  • Implementation target: src/node/services/aiService.ts after workspacePath is computed (runtime created) and before provider conversion.
  • Reuse existing safety helpers where possible:
    • readFileString() / execBuffered() from src/node/utils/runtime/helpers.ts
    • Path-in-workspace validation from src/node/services/tools/fileCommon.ts (same checks used by file_read)
      Hook into the request-building pipeline (in-memory only):
  • Parse the pending user message text for @... references.
  • For each reference:
    • Resolve + normalize path; assert it stays inside workspace root.
    • Read file (utf-8); detect binary (NUL bytes) and skip with a clear note.
    • If range provided: slice lines.
    • Apply caps:
      • Per-file max bytes/lines.
      • Per-request total bytes across all expansions.
    • Render into a single synthetic “file context” message inserted immediately before the user message.

Error handling (self-healing):

  • Missing/unreadable file → inject a short <mux-file-error ...> block (don’t throw).
  • Invalid range → inject an error block (don’t silently ignore).

4) (Optional but recommended) UI transparency

  • Add a small, non-intrusive indicator near the send action (or message bubble metadata) like:
    • “Included context: src/foo.ts (L1–30)
  • Do not render full file text in the transcript.

Testing plan

  • Unit tests (pure functions)
    • Frontend: tokenizer/parser that finds the active @... token + replacement logic.
    • Backend: mention extraction, range parsing, and workspace-root path validation.
    • Backend: line slicing (off-by-one, empty range, EOF shorter than requested).
  • Request-pipeline test
    • Given a user message containing @file.ts#L1-3, confirm the produced model messages include the injected <mux-file ...> block in the right order.

Rollout / safety

  • Ship behind an “experimental” feature flag (workspace setting or global config) until validated on large repos.
  • Defaults:
    • Conservative size caps.
    • Clear truncation/error messaging so users learn to use ranges.
Why not use the poll-based notification system?

Mux’s poll-based notifications are currently designed to run after tool calls and only receive limited context (tool name/success/timestamp). They’re great for model-only reminders, but not a natural fit for user-authored @file references.

Doing expansion in the request-building pipeline is simpler, more explicit, and avoids extending the notification context contract.


Generated with mux • Model: openai:gpt-5.2 • Thinking: xhigh

Change-Id: Iec28d70bf3d49a990a75a5b492a647a58b636a14
Signed-off-by: Thomas Kosiewski <tk@coder.com>
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Change-Id: I1c237ca9fa07767aed0c6b1f6a9013abe98b1528
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33
Copy link
Member Author

@codex review

Addressed your note about stale @mention suggestions when the caret moves:

  • Listen for cursor/selection changes (key/mouse/select) and re-run the @mention effect.
  • Invalidate in-flight completion requests when leaving the token so stale results can't pop back open.
  • Avoid refetching when caret moves within the same token/query.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Change-Id: Icd9690bb579fbf55debeddf5417c52972639be4c
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33
Copy link
Member Author

@codex review

Relaxed @mention expansion so root files like @Makefile/@Dockerfile/@license are included:

  • No longer filters mentions by “contains / or .”.
  • Bare @tokens now expand if they resolve to a file; missing/dir bare tokens are ignored to avoid @user noise.
  • Added a unit test for @makefile.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +227 to +231
const pathLooksLikeFilePath = isLikelyFilePathToken(displayPath) || mention.range !== undefined;

if (mention.rangeError) {
const block = renderMuxFileError(displayPath, mention.rangeError);
const blockBytes = Buffer.byteLength(block, "utf8");

Choose a reason for hiding this comment

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

P2 Badge Skip range errors for non-file @mentions

With the relaxed matching, tokens like @alice#123 (issue/PR refs or other non-file uses of @...#...) will now hit the rangeError branch and always inject a <mux-file-error> block, even though the token doesn’t look like a file path. That contradicts the “ignore bare @tokens to avoid @user noise” goal and adds irrelevant context that can skew model responses. Consider gating the rangeError emission on pathLooksLikeFilePath (or confirming the file exists) so non-file mentions with # are ignored instead of producing errors.

Useful? React with 👍 / 👎.

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