✨ Add status line showing execution environment info#9
Conversation
Add `EnvironmentInfo` message (hostname, repository, branch, agent, model_name) to agent.proto and add it as field 9 in StreamEvent.payload oneof. This is the schema-first foundation for the status line feature.
Extend the AgentAdapter interface with `ModelName() string` and implement it in ClaudeAdapter returning "claude-code". Required for EnvironmentInfo emission.
Add gitinfo.go with GetGitInfo(), GetBranch(), ParseRemoteURL() to gather repository context. Handles detached HEAD (returns short hash), SSH/HTTPS URLs, and git-not-found gracefully with empty string fallback.
Send EnvironmentInfo (sequence=1) before container start on each Execute RPC call. Container output events now start at sequence=2. Update existing tests to account for the additional leading event.
Add useStatusLine hook (ES2022 reverse iteration, FR-011 value preservation), StatusLine component (5-item display with Tailwind truncation), and integrate into chat route below header. Lift useAgent() state to route level.
Configure Vitest with jsdom environment and @testing-library/react. Add 8 hook tests (useStatusLine: fallback, value extraction, FR-011 preservation) and 5 component tests (StatusLine: labels, values, truncation title attribute).
Enter alone conflicted with Japanese IME composition confirm. Cmd+Enter (Mac) / Ctrl+Enter (Windows/Linux) now triggers submit, leaving plain Enter free for newlines and IME input.
Summary of ChangesHello @peacock0803sz, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the user experience by providing immediate and dynamic context about the agent's execution environment directly within the chat interface. By streaming detailed environment information from the backend and displaying it in a dedicated status line, users can quickly understand which host, repository, branch, and model an agent is operating with. This change improves transparency and debugging capabilities during agent interactions. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
Add EnvironmentInfo message (hostname, repository, branch, agent, model_name) as a new oneof variant in StreamEvent, emitted at sequence=1 of each Execute RPC to provide execution context.
buf format enforces single-space before inline comments.
There was a problem hiding this comment.
Code Review
This pull request introduces a new status line feature, providing real-time environment information during agent execution. Key changes include extending the AgentAdapter interface, adding backend logic to retrieve Git repository details, emitting EnvironmentInfo as the first event in the agent stream, and integrating a new StatusLine component in the frontend. The changes also include necessary updates to protobuf definitions and comprehensive tests for the new functionalities. The PromptInput component has been updated to change the send shortcut to Ctrl/Cmd+Enter for improved user experience.
I am having trouble creating individual review comments. Click here to see my feedback.
back/internal/server/agent_server.go (74)
The comment (FR-001, FR-007) refers to internal feature requirements. It would be more helpful to describe the functional purpose directly in the comment, explaining why this event is emitted and its significance, rather than referencing internal IDs.
back/internal/server/agent_server.go (112)
This comment is in Japanese. For consistency and maintainability across the codebase, please translate it to English. The purpose of seq.Store(1) is to ensure subsequent events start from sequence 2, as sequence 1 is reserved for EnvironmentInfo.
seq.Store(1) // sequence=1 is reserved for EnvironmentInfo
back/internal/server/gitinfo.go (37)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// detached HEAD: substitute with short commit hash
back/internal/server/gitinfo.go (54)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// SSH format: git@github.com:owner/repo.gitback/internal/server/gitinfo.go (61)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// HTTPS format: https://github.com/owner/repo.gitback/internal/server/gitinfo.go (67)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// Remove host part: "github.com/owner/repo.git" -> "owner/repo"back/internal/server/gitinfo_test.go (62)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// Create a git repository in a temporary directory to simulate a detached HEAD
back/internal/server/gitinfo_test.go (67)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// Ignore errors in git operations (depends on test environment git config)
back/internal/server/gitinfo_test.go (76)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// Get commit hash and transition to detached HEAD
back/internal/server/gitinfo_test.go (81)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// Remove newline
back/internal/server/gitinfo_test.go (84)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// Switch to detached HEAD
back/internal/server/gitinfo_test.go (90)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// Change to the target repository directory and execute
back/internal/server/gitinfo_test.go (97)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// If detached HEAD, a short hash (7 characters) should be returned
back/internal/server/gitinfo_test.go (137)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// Verify that GetBranch returns an empty string when git is not found in PATH
back/internal/server/gitinfo_test.go (142)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// If git is not found, it should return an empty string, but
back/internal/server/gitinfo_test.go (143)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// GetBranch uses exec.Command directly, so it doesn't use LookPath internally.
back/internal/server/gitinfo_test.go (144)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// Here, we test the fallback via GetGitInfo.
back/internal/server/gitinfo_test.go (147)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// If git is truly unavailable, it should be empty.
back/internal/server/gitinfo_test.go (148)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// If git is found even with an empty PATH (absolute path?), the assertion is skipped.
front/app/components/chat/StatusLine.test.tsx (25)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
it("all labels are displayed in the initial state", () => {
front/app/components/chat/StatusLine.test.tsx (35)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
it("each label's value is displayed as '-' in the initial state", () => {
front/app/components/chat/StatusLine.test.tsx (38)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// Verify that the value span next to each label element is '-'
front/app/components/chat/StatusLine.test.tsx (45)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
it("actual values are displayed correctly", () => {
front/app/components/chat/StatusLine.test.tsx (55)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
it("long values have a title attribute (repo and branch are truncated)", () => {
front/app/components/chat/StatusLine.test.tsx (67)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
it("hostname and model do not have a title attribute (not truncated)", () => {
front/app/lib/hooks/useStatusLine.test.ts (10)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// Factory for test EnvironmentInfo eventsfront/app/lib/hooks/useStatusLine.test.ts (37)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
it("returns '-' for all fields in initial state (empty events)", () => {front/app/lib/hooks/useStatusLine.test.ts (46)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
it("retrieves all fields from EnvironmentInfo event", () => {front/app/lib/hooks/useStatusLine.test.ts (64)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
it("displays empty string fields as '-'", () => {front/app/lib/hooks/useStatusLine.test.ts (81)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
it("uses the last EnvironmentInfo if there are multiple events", () => {front/app/lib/hooks/useStatusLine.test.ts (94)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
it("returns '-' if there are only non-EnvironmentInfo events", () => {front/app/lib/hooks/useStatusLine.test.ts (101)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
it("correctly converts agent types to labels (Codex, Gemini)", () => {front/app/lib/hooks/useStatusLine.test.ts (113)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
it("FR-011: maintains previous value if new event field is empty", () => {front/app/lib/hooks/useStatusLine.test.ts (130)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// If it becomes outside Git management: repository/branch are emptyfront/app/lib/hooks/useStatusLine.test.ts (138)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// Previous non-empty value is maintained (FR-011)front/app/lib/hooks/useStatusLine.test.ts (143)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
it("FR-011: displays new value if updated to non-empty", () => {front/app/lib/hooks/useStatusLine.ts (20)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// ES2022 compatibility: findLast is not available, so iterate in reverse to get the last EnvironmentInfo
front/app/lib/hooks/useStatusLine.ts (46)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// Empty string fields maintain previous values (FR-011)
front/app/test-setup.ts (5)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// React 19's StrictMode mounts components multiple times during development,
front/app/test-setup.ts (6)
This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.
// causing test queries to find duplicate elements. Disable it in the test environment.
There was a problem hiding this comment.
Pull request overview
Adds an execution-environment “status line” to the chat UI by introducing a new EnvironmentInfo stream event emitted at the start of each Execute RPC, then consumed by a frontend hook/component.
Changes:
- Proto: add
EnvironmentInfomessage andStreamEvent.environmentoneof case. - Backend: emit
EnvironmentInfoas the first streamed event (sequence=1); add git repo/branch detection; extendAgentAdapterwithModelName(). - Frontend: add
useStatusLine+StatusLineand integrate into the chat route; add Vitest setup and unit tests.
Reviewed changes
Copilot reviewed 18 out of 19 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| proto/vibra/agent/v1/agent.proto | Adds EnvironmentInfo and a new StreamEvent payload case. |
| back/internal/server/agent_server.go | Emits environment event first and reserves sequence=1. |
| back/internal/server/gitinfo.go | Collects repository + branch info from local git. |
| back/internal/server/gitinfo_test.go | Adds tests for remote parsing + branch detection scenarios. |
| back/internal/server/execute_test.go | Updates expectations for the additional first stream event. |
| back/internal/adapter/adapter.go | Extends adapter interface with ModelName(). |
| back/internal/adapter/claude.go | Implements ModelName() for Claude adapter. |
| back/gen/vibra/agent/v1/agent.pb.go | Regenerated Go protobuf bindings. |
| front/app/routes/chat.$sessionId.tsx | Renders StatusLine and wires it to agent stream events. |
| front/app/lib/hooks/useStatusLine.ts | Extracts latest environment info from stream events. |
| front/app/lib/hooks/useStatusLine.test.ts | Unit tests for status-line extraction + FR-011 preservation. |
| front/app/components/chat/StatusLine.tsx | UI component for status line display/truncation. |
| front/app/components/chat/StatusLine.test.tsx | Render tests for labels/values and title behavior. |
| front/app/components/chat/ChatWindow.tsx | Refactors ChatWindow to accept useAgent() result via props. |
| front/vitest.config.ts | Adds Vitest config (jsdom + setup file). |
| front/app/test-setup.ts | Testing Library setup (disables React StrictMode in tests). |
| front/package.json | Adds test and test:watch scripts. |
| front/gen/vibra/agent/v1/agent_pb.js | Regenerated JS protobuf bindings. |
| front/gen/vibra/agent/v1/agent_pb.d.ts | Regenerated TS typings for protobuf bindings. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export function useStatusLine(events: StreamEvent[]): StatusLineData { | ||
| const prevRef = useRef<StatusLineData>({ | ||
| hostname: FALLBACK, | ||
| repository: FALLBACK, | ||
| branch: FALLBACK, | ||
| agentType: FALLBACK, | ||
| modelName: FALLBACK, | ||
| }); | ||
|
|
||
| const latestEvent = findLatestEnvironment(events); | ||
| if (!latestEvent || latestEvent.payload.case !== "environment") { | ||
| return prevRef.current; | ||
| } |
There was a problem hiding this comment.
useStatusLine preserves prevRef even when events is cleared (e.g., useStream.consume() calls setEvents([]) when starting a new Execute). This can cause the status line to show stale hostname/repo/branch/model from a previous run until the new EnvironmentInfo arrives, instead of resetting to the fallback state. Consider resetting prevRef.current back to all "-" when events.length === 0 (or when the latest environment event sequence restarts), and add a test that covers the reset-on-empty case.
|
|
||
| // ES2022互換: findLast 不可なため逆順走査で最後のEnvironmentInfoを取得 | ||
| function findLatestEnvironment(events: StreamEvent[]) { | ||
| return [...events].reverse().find((e) => e.payload.case === "environment"); |
There was a problem hiding this comment.
findLatestEnvironment allocates and reverses a copy of the full events array ([...events].reverse()) on every render, which can become noticeably expensive as the stream grows. You can scan from the end with a simple for-loop to find the latest environment event without copying.
| return [...events].reverse().find((e) => e.payload.case === "environment"); | |
| for (let i = events.length - 1; i >= 0; i--) { | |
| const event = events[i]; | |
| if (event.payload.case === "environment") { | |
| return event; | |
| } | |
| } | |
| return undefined; |
| out, err := exec.Command("git", "-C", dir, "rev-parse", "HEAD").Output() | ||
| if err != nil { | ||
| t.Skip("could not get HEAD commit") | ||
| } | ||
| commitHash := string(out[:len(out)-1]) // 改行を除去 | ||
|
|
||
| // detached HEADに切り替え | ||
| cmd := exec.Command("git", "checkout", "--detach", commitHash) | ||
| cmd.Dir = dir |
There was a problem hiding this comment.
commitHash := string(out[:len(out)-1]) removes only a single trailing byte. On Windows (CRLF) or if the output format changes, this can leave \r behind and break the subsequent git checkout --detach call. Prefer trimming whitespace (e.g., strings.TrimSpace) instead of slicing.
| run := func(args ...string) { | ||
| cmd := exec.Command("git", args...) | ||
| cmd.Dir = dir | ||
| _ = cmd.Run() | ||
| } | ||
|
|
||
| run("init", "-b", "main") | ||
| run("config", "user.email", "test@example.com") | ||
| run("config", "user.name", "Test") | ||
| run("commit", "--allow-empty", "-m", "initial") |
There was a problem hiding this comment.
In TestGetBranch_NormalBranch, the setup ignores errors and uses git init -b main, which fails on older git versions (and would silently leave the repo uninitialized due to _ = cmd.Run()). This can make the test flaky across CI environments. Consider checking command errors in the run helper and using a more compatible sequence (e.g., git init then rename/create the branch) so the test is deterministic.
| run := func(args ...string) { | |
| cmd := exec.Command("git", args...) | |
| cmd.Dir = dir | |
| _ = cmd.Run() | |
| } | |
| run("init", "-b", "main") | |
| run("config", "user.email", "test@example.com") | |
| run("config", "user.name", "Test") | |
| run("commit", "--allow-empty", "-m", "initial") | |
| run := func(t *testing.T, args ...string) { | |
| t.Helper() | |
| cmd := exec.Command("git", args...) | |
| cmd.Dir = dir | |
| if out, err := cmd.CombinedOutput(); err != nil { | |
| t.Fatalf("git %v failed: %v\nOutput: %s", args, err, string(out)) | |
| } | |
| } | |
| // Initialize repository in a way compatible with older git versions. | |
| run(t, "init") | |
| run(t, "config", "user.email", "test@example.com") | |
| run(t, "config", "user.name", "Test") | |
| run(t, "checkout", "-b", "main") | |
| run(t, "commit", "--allow-empty", "-m", "initial") |
|
@claude Can you review this PR? |
|
@claude once again, cloud you review this? |
|
Claude finished @peacock0803sz's task in 1m 50s —— View job PR Review: ✨ Add status line showing execution environment info
Overall this is a well-scoped feature with good test coverage. There are a few issues worth addressing before merge, ranging from a guideline violation to a functional bug. Critical: Japanese comments violate project guidelines
This affects readability for international contributors. Gemini Code Assist has already suggested specific English translations for each of these. Fix this → Bug:
|
GetGitInfo/GetBranch/getRemoteURL used the server process CWD, causing the status line to always show the vibra repo itself rather than the user's project. Accept a dir parameter and use git -C for all commands. Also improve test robustness: check git command errors instead of silently ignoring, use strings.TrimSpace, and remove os.Chdir pattern.
Replace useRef-based state preservation with a forward iteration over all events, merging EnvironmentInfo fields sequentially. This fixes stale data on session reset (events cleared to []) and eliminates unsafe ref mutation during render (React concurrent mode).
CLAUDE.md requires "All documentation must be in English". Replace Japanese inline comments and test names across backend and frontend.
|
@claude fixed, re-review them! |
|
Claude finished @peacock0803sz's task in 1m 49s —— View job Re-review: All major issues resolved ✅All previously raised issues have been addressed across three commits ( ✅ Japanese comments (Critical → Fixed)All files now have English-only comments and test descriptions. Translation is accurate and natural in every location I checked. No remaining Japanese text found. ✅
|
Summary
Add a status line bar to the chat UI that displays the current execution environment: hostname, repository, branch, agent type, and model name.
EnvironmentInfomessage and extendStreamEvent.oneofwithenvironmentcaseEnvironmentInfoas the first stream event (sequence=1) inExecuteRPC; addgitinfo.gofor repository/branch detection andModelName()to theAgentAdapterinterfaceStatusLinecomponent anduseStatusLinehook that extracts environment data from the event stream, with fallback ("-") for missing fields and value preservation across events (FR-011)Other changes included in this branch
DevUserauth bypass option for local developmentTest plan
useStatusLinehook: unit tests covering initial state, field extraction, empty-field preservation, and agent label mappingStatusLinecomponent: render tests verifying labels, values, and truncationgitinfo.go: unit tests forParseRemoteURL(SSH/HTTPS/edge cases) andGetBranchExecutestream