[eas-cli] Add eas chat command#4005
Draft
jonsamp wants to merge 12 commits into
Draft
Conversation
Ask the Expo dashboard AI assistant about your account and EAS projects from the terminal. Streams the reply, supports interactive multi-turn follow-ups, `--project`/`--account` scoping, `--non-interactive`, and `--json` for agent-friendly structured output. Calls the website's `/api/chat` route using the CLI session secret; command is hidden while the backend feature gate rolls out.
ca4d866 to
effddeb
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #4005 +/- ##
==========================================
+ Coverage 59.67% 59.89% +0.22%
==========================================
Files 941 946 +5
Lines 41319 41702 +383
Branches 8675 8775 +100
==========================================
+ Hits 24654 24973 +319
- Misses 16571 16635 +64
Partials 94 94 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Render the streamed assistant reply as ANSI (bold, inline code, headings, bullets, links) one line at a time. Prepend a client-side system message steering the assistant to write terminal-friendly answers and include expo.dev links for referenced artifacts (builds, updates, etc.).
…hat` Replace the per-turn prompt with a reusable Node readline interface: arrow-key history across turns and /help, /clear, /exit slash commands, all in the normal scrolling buffer (no new dependency).
The ora spinner leaves stdin paused when it stops, so the readline prompt had nothing keeping the event loop alive and the process exited the moment the prompt appeared. Resume stdin before each prompt and stop the spinner from grabbing stdin (discardStdin: false).
When run inside a linked EAS project and neither --project nor --account is given, chat now focuses on that project automatically. Detection is silent and read-only: it never prompts, links, or creates a config, and falls back to account scope when the directory is not a linked project.
The first message comes from argv, not the readline prompt, so Up-arrow had nothing to recall at the first follow-up. Pass it as readline's initial history.
Prefix the assistant reply with a magenta "Expo > " label and indent its continuation lines to match, and label the user's turn "Chat > " (both 4-char names so the two align).
Wrap each rendered line to the terminal width minus the indent (ANSI-aware, hard-breaking long URLs) and re-apply the indent to every wrapped piece, so terminal soft-wrapping no longer drops wrapped text to column 0. Also indent the ora spinner to align with the reply body.
The indented ora spinner leaves the cursor at its indent column when it stops (ora's clear() ends with cursorTo(indent)), which pushed the whole reply right by the indent. Reset the cursor to column 0 after stopping. Also move the commands hint above the echoed message and shorten it.
Use ora's prefixText to show "Expo > <spinner> Thinking…" from the first frame instead of the indent option, which rendered unindented for a tick then snapped right. The spinner now reads as the reply and is cleared/replaced by the streamed text.
eas chat commandeas chat command
…ing multi-byte characters
|
✅ Thank you for adding the changelog entry! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
ENG-24455: bring the dashboard AI chat assistant to the terminal so developers (and other agents) can ask questions about their Expo account and EAS projects without leaving the CLI.
The assistant, its tools, and the model all live in the website's
POST /api/chatNext.js route (not the GraphQL API). This command reuses that same endpoint.How
eas chat "message"(src/commands/chat.ts) plus a small client (src/chat/chatClient.ts)./api/chatroute only accepts a session cookie, which it forwards to GraphQL as theexpo-sessionheader. The CLI's stored session secret is exactly the JSON that cookie expects, so the command sends it asCookie: <authStorageKey>.sessionSecret=…(mirrors what a browser session does).EXPO_TOKENaccess tokens are not supported by the endpoint, so the command fails fast with a clear message telling the user toeas login.Reply(default) so you can follow up; the full history is resent each turn. Typeexit/quit/q(or empty Enter / Ctrl+C) to end.-p/--project(focus on a project, validated viaAppQuery.byFullNameAsync, resolves the owner account and frames the question),-a/--account(scope),--non-interactive, and--json(agent-friendly single-turn structured output including the assistant'sresponseand thetoolCallsit used).static hidden = true) for now: the backend chat feature is still behind theDASHBOARD_CHATuser feature gate (prod = admins only today), requires per-accountaiChatEnabled, and a paid plan for a non-zero token budget. It should stay hidden until the backend ships and the gate is widened.Test Plan
yarn typecheck,yarn lint, andyarn fmt:checkpass.src/chat/__tests__/chatClient.test.ts,src/commands/__tests__/chat.test.ts) cover: SSE streaming + text accumulation, tool-call capture, cookie/account header construction, HTTP 401/403/429 → friendly errors, primary/--account/--projectscoping, project-not-found, the interactive follow-up→exit loop, JSON output shape, and the access-token guard.eas chat --helprenders the args/flags; command is absent from the README and top-level help (hidden) but runnable directly. End-to-end against production is gated by the in-progress backend rollout described above.