From a35651a7ff74324f2b9e6594cc47ad690f757e66 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:11:54 -0700 Subject: [PATCH 1/9] fix(byo): the daemon keeps an agent running; the run command is the quick try (TASK-645 items 3, 4) Two connect paths had no guidance on which to pick. The run command now says it is a quick try that stops when its Terminal closes, and points to the daemon under Other ways to connect. The daemon block is marked recommended, and its Reload line says the computer appears by name, marked online. The run command's listener note says it stops on close and names commonly daemon install. en and zh-CN; V2AgentBYOConnectPaths covers the states. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: rivet Agent-Model: claude/claude-haiku-5-5/default --- frontend/src/i18n/locales/en.json | 5 +- frontend/src/i18n/locales/zh-CN.json | 5 +- .../__tests__/V2AgentBYOConnectPaths.test.tsx | 124 ++++++++++++++++++ frontend/src/v2/components/V2AgentBYO.tsx | 11 ++ 4 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index d33af655a8..62e3804f7a 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -1711,6 +1711,7 @@ "waiting": "Waiting for {{name}} to check in… this turns green the moment the command connects.", "verified": "{{name}} is listening — mentions will wake it.", "stillWaiting": "Still no check-in from {{name}}. Run the command above in Terminal on your computer, and this page will confirm it.", + "stopsOnClose": "This stops when this Terminal window closes. To keep {{name}} running, run commonly daemon install on this computer instead.", "npmPermission": "If npm stops with EACCES (permission denied), don’t add sudo. Reinstall Node with a version manager such as nvm, then run the four lines again.", "ctaWarning": "{{name}} isn’t listening yet: it won’t answer mentions until the command above is running.", "needs": "Needs Node 20+ with npm and {{tool}} signed in. Run all four lines in one window: the exports last only there.", @@ -1771,9 +1772,11 @@ "slow": "Still waiting — check that commonly daemon run is active on {{machine}}. The agent starts the moment it's back.", "openPod": "Open the pod" }, + "quickTry": "Quick try: this command runs in Terminal and stops when that window closes. For an agent that should keep running, add this computer once with the daemon, under Other ways to connect below.", "addComputer": { "title": "Add a computer", - "after": "Reload to select this computer.", + "recommended": "Recommended for an agent that keeps running. Register this computer once; the daemon keeps your agents running across logins and reboots.", + "after": "Reload this page once it connects. Your computer appears in the list by its name, marked online.", "copy": "Copy", "copied": "Copied" }, diff --git a/frontend/src/i18n/locales/zh-CN.json b/frontend/src/i18n/locales/zh-CN.json index de522bc6a6..3d7c1b51b8 100644 --- a/frontend/src/i18n/locales/zh-CN.json +++ b/frontend/src/i18n/locales/zh-CN.json @@ -1771,6 +1771,7 @@ "waiting": "正在等待 {{name}} 接入…命令一接通,这里就会变绿。", "verified": "{{name}} 已在监听 —— @提及 会唤醒它。", "stillWaiting": "{{name}} 还没接入。请在你电脑的终端里运行上面的命令,这里会自动确认。", + "stopsOnClose": "关闭这个终端窗口后就会停止。要让 {{name}} 持续运行,请改为在这台电脑上运行 commonly daemon install。", "npmPermission": "如果 npm 报 EACCES(权限被拒绝),不要加 sudo。请用版本管理工具(如 nvm)重新安装 Node,然后重新运行这四行。", "ctaWarning": "{{name}} 尚未监听:上面的命令运行起来之前,它不会回复 @提及。", "needs": "需要 Node 20+(含 npm)和已登录的 {{tool}}。四行都要在同一个窗口里运行,换了窗口 export 就失效。", @@ -1831,9 +1832,11 @@ "slow": "仍在等待——请确认 {{machine}} 上正在运行 commonly daemon run,恢复后会立即启动该智能体。", "openPod": "打开 pod" }, + "quickTry": "快速试用:这条命令在终端里运行,关闭那个窗口就会停止。如果希望智能体持续运行,请在下方「其他接入方式」里用守护进程把这台电脑添加一次。", "addComputer": { "title": "添加电脑", - "after": "刷新页面后即可选择这台电脑。", + "recommended": "推荐用于需要持续运行的智能体。把这台电脑注册一次,守护进程会让你的智能体在登录和重启后保持运行。", + "after": "连接完成后刷新页面,这台电脑会以名称出现在列表中,并标记为在线。", "copy": "复制", "copied": "已复制" }, diff --git a/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx b/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx new file mode 100644 index 0000000000..d61480524f --- /dev/null +++ b/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx @@ -0,0 +1,124 @@ +// @ts-nocheck +// Keep setup request assertions independent of funnel telemetry. +jest.mock('../utils/byoTelemetry', () => ({ recordByoStep: jest.fn() })); +// TASK-645 item 3 and 4: the two connect paths. The run command is the quick +// try and dies with its Terminal; the daemon is the one that keeps an agent +// running. Each state is pinned by its own copy, so a rewording can't drop it. +import React from 'react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import { MemoryRouter } from 'react-router-dom'; +import V2AgentBYO from '../components/V2AgentBYO'; +import { AuthContext } from '../../context/AuthContext'; + +jest.mock('../components/V2NavRail', () => () => null); +jest.mock('../hooks/useV2PodAttention', () => ({ + ...jest.requireActual('../hooks/useV2PodAttention'), + useV2PodAttention: () => ({ items: [], count: null, countByPod: {}, refresh: async () => {} }), +})); +jest.mock('axios', () => { + const mock = { + get: jest.fn(), + post: jest.fn(), + patch: jest.fn(), + delete: jest.fn(), + defaults: { baseURL: '', headers: { common: {} } }, + interceptors: { + request: { use: jest.fn(), eject: jest.fn() }, + response: { use: jest.fn(), eject: jest.fn() }, + }, + }; + return { __esModule: true, default: mock, ...mock }; +}); + +const axios = jest.requireMock('axios').default; + +const authValue = { + currentUser: { _id: 'u1', username: 'sam' }, + user: { _id: 'u1', username: 'sam' }, + token: 'user-jwt', + loading: false, + error: null, + isAuthenticated: true, + register: jest.fn(), + login: jest.fn(), + logout: jest.fn(), + updateProfile: jest.fn(), +}; + +const MAC = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0 Safari/537.36'; +const WINDOWS = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0 Safari/537.36'; +const realUserAgent = window.navigator.userAgent; +const setUserAgent = (value) => Object.defineProperty(window.navigator, 'userAgent', { value, configurable: true }); + +const mockPage = ({ machines = [] } = {}) => { + axios.get.mockImplementation((url) => { + if (url.startsWith('/api/hosted/availability')) return Promise.resolve({ data: { configured: false, caps: { agentsPerUser: 1, turnsPerDay: 200 } } }); + if (url === '/api/pods') return Promise.resolve({ data: [{ _id: 'p1', name: 'Workspace', type: 'chat' }] }); + if (url === '/api/machines') return Promise.resolve({ data: { machines, offlineAfterMs: 90000 } }); + if (url.startsWith('/api/registry/agents/next-free-name?')) return Promise.resolve({ data: { name: new URLSearchParams(url.split('?')[1]).get('base') } }); + return Promise.resolve({ data: {} }); + }); + axios.post + .mockResolvedValueOnce({ data: { ok: true } }) + .mockResolvedValueOnce({ data: { token: 'cm_agent_test_token' } }); +}; + +const renderPage = () => render( + + + + + , +); + +const issueRun = async () => { + await waitFor(() => expect(screen.getByText('Workspace (chat)')).toBeInTheDocument()); + await waitFor(() => expect(screen.getByRole('button', { name: /get my connect command/i })).toBeEnabled()); + fireEvent.click(screen.getByRole('button', { name: /get my connect command/i })); + await screen.findByText(/your connect command for/i); +}; + +describe('BYO connect paths: run is the quick try, the daemon keeps it running (TASK-645 items 3 and 4)', () => { + afterEach(() => setUserAgent(realUserAgent)); + beforeEach(() => jest.clearAllMocks()); + + test('run path on a Mac: the quick-try line names the daemon, and the command says it stops with its Terminal', async () => { + setUserAgent(MAC); + mockPage({ machines: [] }); + renderPage(); + expect(await screen.findByTestId('byo-quick-try')).toHaveTextContent(/stops when that window closes/); + expect(screen.getByTestId('byo-quick-try')).toHaveTextContent(/Other ways to connect/); + + await issueRun(); + const stops = screen.getByTestId('byo-listen-stops-on-close'); + expect(stops).toHaveTextContent(/stops when this Terminal window closes/); + expect(stops).toHaveTextContent(/commonly daemon install/); + }); + + test('run path on Windows: no listener command, so no stop-on-close line', async () => { + setUserAgent(WINDOWS); + mockPage({ machines: [] }); + renderPage(); + await issueRun(); + expect(screen.queryByTestId('byo-listen-stops-on-close')).toBeNull(); + }); + + test('daemon path with no computer: marked recommended, and Reload says the computer appears by name, online', async () => { + setUserAgent(MAC); + mockPage({ machines: [] }); + renderPage(); + const add = await screen.findByTestId('byo-add-computer'); + expect(screen.getByTestId('byo-add-computer-recommended')).toHaveTextContent(/Recommended for an agent that keeps running/); + expect(add).toHaveTextContent(/appears in the list by its name, marked online/); + expect(add).toHaveTextContent('commonly daemon register && commonly daemon install'); + }); + + test('with a computer already added, the quick-try line and the daemon block are both gone', async () => { + setUserAgent(MAC); + mockPage({ machines: [{ machineId: 'm1', name: 'Sams-MacBook', status: 'online', lastSeenAt: new Date().toISOString() }] }); + renderPage(); + await waitFor(() => expect(axios.get).toHaveBeenCalledWith('/api/machines', expect.anything())); + expect(screen.queryByTestId('byo-quick-try')).toBeNull(); + expect(screen.queryByTestId('byo-add-computer')).toBeNull(); + }); +}); diff --git a/frontend/src/v2/components/V2AgentBYO.tsx b/frontend/src/v2/components/V2AgentBYO.tsx index 9bae537b7d..04a748f65f 100644 --- a/frontend/src/v2/components/V2AgentBYO.tsx +++ b/frontend/src/v2/components/V2AgentBYO.tsx @@ -1407,6 +1407,11 @@ const V2AgentBYO: React.FC = () => { })()} )} + {/* The run command is the quick try; it dies with its Terminal. The + daemon is the one that keeps the agent running (TASK-645 item 3). */} + {mode === 'byo' && machines.length === 0 && ( +

{t('agentByo.quickTry')}

+ )} {/* One command is THE path (QA BYO walk 1): the daemon and the SDK are real alternatives, but shown as equals beside the button they read as a choice a stranger has to make before starting. */} @@ -1418,6 +1423,7 @@ const V2AgentBYO: React.FC = () => { {machines.length === 0 && (
{t('agentByo.addComputer.title')} +

{t('agentByo.addComputer.recommended')}

{daemonCommand} +
+

{t('agentByo.addComputer.after')}

+
+ ) : null; const runnerPicker = mode === 'byo' && !issued && !onCardStart ? (

{t('agentByo.form.adapterLabel')}{' '} @@ -1420,25 +1441,7 @@ const V2AgentBYO: React.FC = () => { if ((event.target as Element).closest('summary, button, a')) event.preventDefault(); }}>

{t('agentByo.otherWays.title')} - {machines.length === 0 && ( -
- {t('agentByo.addComputer.title')} - {setupOs !== 'windows' && ( -

{t('agentByo.addComputer.recommended')}

- )} -
- {daemonCommand} - -
-

{t('agentByo.addComputer.after')}

-
- )} + {addComputerBlock}

{t(listenerAvailable ? 'agentByo.footnote.cliRoute' : listenAdapter === 'claude' ? 'agentByo.footnote.cliRouteClaudeUnavailable' @@ -1685,6 +1688,7 @@ const V2AgentBYO: React.FC = () => {

{t('agentByo.otherWays.title')} + {addComputerBlock}
{t('agentByo.snippets.runtimeToken')} From c40890ebe3518176286d090ccefe2407ba3ace8d Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Fri, 30 Oct 2026 18:00:54 -0700 Subject: [PATCH 6/9] fix(byo): stop-on-close line stops naming a computer already on file With a computer on file the add-computer block is hidden, but the stop-on-close line still told the person to add this computer. Pick the copy by machine state (en and zh-CN) and pin it in the test. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: rivet Agent-Model: claude/claude-haiku-5-5/default --- frontend/src/i18n/locales/en.json | 1 + frontend/src/i18n/locales/zh-CN.json | 1 + frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx | 4 ++++ frontend/src/v2/components/V2AgentBYO.tsx | 2 +- 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index 2c6fc91b22..bc48ac3340 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -1712,6 +1712,7 @@ "verified": "{{name}} is listening — mentions will wake it.", "stillWaiting": "Still no check-in from {{name}}. Run the command above in Terminal on your computer, and this page will confirm it.", "stopsOnClose": "This stops when this Terminal window closes. For an agent that keeps running, add this computer under Other ways to connect, then choose On my computer.", + "stopsOnCloseWithComputer": "This stops when this Terminal window closes. For an agent that keeps running, choose On my computer under Other ways to connect.", "npmPermission": "If npm stops with EACCES (permission denied), don’t add sudo. Reinstall Node with a version manager such as nvm, then run the four lines again.", "ctaWarning": "{{name}} isn’t listening yet: it won’t answer mentions until the command above is running.", "needs": "Needs Node 20+ with npm and {{tool}} signed in. Run all four lines in one window: the exports last only there.", diff --git a/frontend/src/i18n/locales/zh-CN.json b/frontend/src/i18n/locales/zh-CN.json index 790c886a58..c9e61eb428 100644 --- a/frontend/src/i18n/locales/zh-CN.json +++ b/frontend/src/i18n/locales/zh-CN.json @@ -1772,6 +1772,7 @@ "verified": "{{name}} 已在监听 —— @提及 会唤醒它。", "stillWaiting": "{{name}} 还没接入。请在你电脑的终端里运行上面的命令,这里会自动确认。", "stopsOnClose": "关闭这个终端窗口后就会停止。如果希望智能体持续运行,请在「其他接入方式」里添加这台电脑,然后选择「在我的电脑上」。", + "stopsOnCloseWithComputer": "关闭这个终端窗口后就会停止。如果希望智能体持续运行,请在「其他接入方式」里选择「在我的电脑上」。", "npmPermission": "如果 npm 报 EACCES(权限被拒绝),不要加 sudo。请用版本管理工具(如 nvm)重新安装 Node,然后重新运行这四行。", "ctaWarning": "{{name}} 尚未监听:上面的命令运行起来之前,它不会回复 @提及。", "needs": "需要 Node 20+(含 npm)和已登录的 {{tool}}。四行都要在同一个窗口里运行,换了窗口 export 就失效。", diff --git a/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx b/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx index 92fe6c0e96..2e7116e798 100644 --- a/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx +++ b/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx @@ -108,6 +108,10 @@ describe('BYO connect paths: run is the quick try, the daemon keeps it running ( await issueRun(); expect(screen.getByTestId('byo-result-more-ways')).toBeInTheDocument(); expect(screen.queryByTestId('byo-add-computer')).toBeNull(); + // The stop-on-close line must not send them to add a computer that is already on file. + const stops = screen.getByTestId('byo-listen-stops-on-close'); + expect(stops).not.toHaveTextContent(/add this computer/); + expect(stops).toHaveTextContent(/choose On my computer under Other ways to connect/); }); test('run path on Windows: no listener command, so no stop-on-close line', async () => { diff --git a/frontend/src/v2/components/V2AgentBYO.tsx b/frontend/src/v2/components/V2AgentBYO.tsx index 102049fba9..507ec48b28 100644 --- a/frontend/src/v2/components/V2AgentBYO.tsx +++ b/frontend/src/v2/components/V2AgentBYO.tsx @@ -1631,7 +1631,7 @@ const V2AgentBYO: React.FC = () => { )} {listenerAvailable && (

- {t('agentByo.listen.stopsOnClose')} + {t(machines.length === 0 ? 'agentByo.listen.stopsOnClose' : 'agentByo.listen.stopsOnCloseWithComputer')}

)} {!listenerAvailable ? null : listenState === 'listening' ? ( From 3228a2a40d626f034748a6ee111abbba1aebb0c9 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Fri, 30 Oct 2026 18:11:09 -0700 Subject: [PATCH 7/9] fix(byo): computer-on-file line points at the start form, not the result page On the result page with a computer on file, Other ways to connect has no On my computer choice; that lives on the start form. Say to start another agent and choose On my computer (en and zh-CN), and pin the wording. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: rivet Agent-Model: claude/claude-haiku-5-5/default --- frontend/src/i18n/locales/en.json | 2 +- frontend/src/i18n/locales/zh-CN.json | 2 +- frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index bc48ac3340..1768f2edab 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -1712,7 +1712,7 @@ "verified": "{{name}} is listening — mentions will wake it.", "stillWaiting": "Still no check-in from {{name}}. Run the command above in Terminal on your computer, and this page will confirm it.", "stopsOnClose": "This stops when this Terminal window closes. For an agent that keeps running, add this computer under Other ways to connect, then choose On my computer.", - "stopsOnCloseWithComputer": "This stops when this Terminal window closes. For an agent that keeps running, choose On my computer under Other ways to connect.", + "stopsOnCloseWithComputer": "This stops when this Terminal window closes. For an agent that keeps running, start another agent and choose On my computer.", "npmPermission": "If npm stops with EACCES (permission denied), don’t add sudo. Reinstall Node with a version manager such as nvm, then run the four lines again.", "ctaWarning": "{{name}} isn’t listening yet: it won’t answer mentions until the command above is running.", "needs": "Needs Node 20+ with npm and {{tool}} signed in. Run all four lines in one window: the exports last only there.", diff --git a/frontend/src/i18n/locales/zh-CN.json b/frontend/src/i18n/locales/zh-CN.json index c9e61eb428..b7b04172ff 100644 --- a/frontend/src/i18n/locales/zh-CN.json +++ b/frontend/src/i18n/locales/zh-CN.json @@ -1772,7 +1772,7 @@ "verified": "{{name}} 已在监听 —— @提及 会唤醒它。", "stillWaiting": "{{name}} 还没接入。请在你电脑的终端里运行上面的命令,这里会自动确认。", "stopsOnClose": "关闭这个终端窗口后就会停止。如果希望智能体持续运行,请在「其他接入方式」里添加这台电脑,然后选择「在我的电脑上」。", - "stopsOnCloseWithComputer": "关闭这个终端窗口后就会停止。如果希望智能体持续运行,请在「其他接入方式」里选择「在我的电脑上」。", + "stopsOnCloseWithComputer": "关闭这个终端窗口后就会停止。如果希望智能体持续运行,请再添加一个智能体,然后选择「在我的电脑上」。", "npmPermission": "如果 npm 报 EACCES(权限被拒绝),不要加 sudo。请用版本管理工具(如 nvm)重新安装 Node,然后重新运行这四行。", "ctaWarning": "{{name}} 尚未监听:上面的命令运行起来之前,它不会回复 @提及。", "needs": "需要 Node 20+(含 npm)和已登录的 {{tool}}。四行都要在同一个窗口里运行,换了窗口 export 就失效。", diff --git a/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx b/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx index 2e7116e798..fab373c47d 100644 --- a/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx +++ b/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx @@ -111,7 +111,7 @@ describe('BYO connect paths: run is the quick try, the daemon keeps it running ( // The stop-on-close line must not send them to add a computer that is already on file. const stops = screen.getByTestId('byo-listen-stops-on-close'); expect(stops).not.toHaveTextContent(/add this computer/); - expect(stops).toHaveTextContent(/choose On my computer under Other ways to connect/); + expect(stops).toHaveTextContent(/start another agent and choose On my computer/); }); test('run path on Windows: no listener command, so no stop-on-close line', async () => { From 59c9001c2ea7506f7abdc306db11af27a903260f Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Fri, 30 Oct 2026 18:13:18 -0700 Subject: [PATCH 8/9] fix(byo): On my computer on the result page when a computer is on file; hide daemon command row on Windows (TASK-645 items 3, 4) - Result page Other ways offers On my computer when a computer is on file, so the stop-on-close line's choice is on the page. Clicking it leaves the result and opens machine mode. Tested by clicking it from the result page. - The add-computer command row is hidden on Windows (systemd cannot install there). The title and copy stay. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: rivet Agent-Model: claude/claude-haiku-5-5/default --- .../__tests__/V2AgentBYOConnectPaths.test.tsx | 8 ++++- frontend/src/v2/components/V2AgentBYO.tsx | 34 +++++++++++++------ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx b/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx index fab373c47d..aa36db5487 100644 --- a/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx +++ b/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx @@ -112,6 +112,10 @@ describe('BYO connect paths: run is the quick try, the daemon keeps it running ( const stops = screen.getByTestId('byo-listen-stops-on-close'); expect(stops).not.toHaveTextContent(/add this computer/); expect(stops).toHaveTextContent(/start another agent and choose On my computer/); + // The choice the line names is on this page: clicking it opens machine mode. + fireEvent.click(screen.getByTestId('byo-result-on-my-computer')); + expect(screen.getByTestId('byo-mode-machine')).toHaveAttribute('aria-pressed', 'true'); + expect(screen.queryByText(/your connect command for/i)).toBeNull(); }); test('run path on Windows: no listener command, so no stop-on-close line', async () => { @@ -136,9 +140,11 @@ describe('BYO connect paths: run is the quick try, the daemon keeps it running ( setUserAgent(WINDOWS); mockPage({ machines: [] }); renderPage(); - await screen.findByTestId('byo-add-computer'); + const add = await screen.findByTestId('byo-add-computer'); expect(screen.queryByTestId('byo-quick-try')).toBeNull(); expect(screen.queryByTestId('byo-add-computer-recommended')).toBeNull(); + // Windows gets no daemon command row: systemd cannot install there. + expect(add).not.toHaveTextContent('commonly daemon register && commonly daemon install'); }); test('with a computer already added, the quick-try line and the daemon block are both gone', async () => { diff --git a/frontend/src/v2/components/V2AgentBYO.tsx b/frontend/src/v2/components/V2AgentBYO.tsx index 507ec48b28..5420d7d578 100644 --- a/frontend/src/v2/components/V2AgentBYO.tsx +++ b/frontend/src/v2/components/V2AgentBYO.tsx @@ -1059,16 +1059,18 @@ const V2AgentBYO: React.FC = () => { {setupOs !== 'windows' && (

{t('agentByo.addComputer.recommended')}

)} -
- {daemonCommand} - -
+ {setupOs !== 'windows' && ( +
+ {daemonCommand} + +
+ )}

{t('agentByo.addComputer.after')}

) : null; @@ -1689,6 +1691,18 @@ const V2AgentBYO: React.FC = () => {
{t('agentByo.otherWays.title')} {addComputerBlock} + {machines.length > 0 && ( + // A computer on file: the machine choice is the start form's mode + // picker, which this result page does not show, so offer it here. + + )}
{t('agentByo.snippets.runtimeToken')} From c18a25374374abd9d04c3fe99d13db31268d7fc4 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Fri, 30 Oct 2026 18:15:48 -0700 Subject: [PATCH 9/9] fix(byo): offer no daemon block on Windows, on either page The title and copy stayed on Windows with nothing to run. Gate the whole add-computer block on the setup OS, and assert it is absent on the start page and the result page. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: rivet Agent-Model: claude/claude-haiku-5-5/default --- .../__tests__/V2AgentBYOConnectPaths.test.tsx | 15 ++++++++-- frontend/src/v2/components/V2AgentBYO.tsx | 29 +++++++++---------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx b/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx index aa36db5487..1cf4405b06 100644 --- a/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx +++ b/frontend/src/v2/__tests__/V2AgentBYOConnectPaths.test.tsx @@ -140,11 +140,20 @@ describe('BYO connect paths: run is the quick try, the daemon keeps it running ( setUserAgent(WINDOWS); mockPage({ machines: [] }); renderPage(); - const add = await screen.findByTestId('byo-add-computer'); + await waitFor(() => expect(axios.get).toHaveBeenCalledWith('/api/machines', expect.anything())); expect(screen.queryByTestId('byo-quick-try')).toBeNull(); expect(screen.queryByTestId('byo-add-computer-recommended')).toBeNull(); - // Windows gets no daemon command row: systemd cannot install there. - expect(add).not.toHaveTextContent('commonly daemon register && commonly daemon install'); + // Windows gets no daemon block at all: systemd cannot install there, so + // there is nothing to run and nothing to offer. + expect(screen.queryByTestId('byo-add-computer')).toBeNull(); + }); + + test('on Windows, the result page offers no daemon block either', async () => { + setUserAgent(WINDOWS); + mockPage({ machines: [] }); + renderPage(); + await issueRun(); + expect(screen.queryByTestId('byo-add-computer')).toBeNull(); }); test('with a computer already added, the quick-try line and the daemon block are both gone', async () => { diff --git a/frontend/src/v2/components/V2AgentBYO.tsx b/frontend/src/v2/components/V2AgentBYO.tsx index 5420d7d578..59827139a5 100644 --- a/frontend/src/v2/components/V2AgentBYO.tsx +++ b/frontend/src/v2/components/V2AgentBYO.tsx @@ -1053,24 +1053,21 @@ const V2AgentBYO: React.FC = () => { }; // The daemon block lives in Other ways to connect on both the start form and // the result page, so the stop-on-close line can point to it from the result. - const addComputerBlock = machines.length === 0 ? ( + // Windows has no daemon install (systemd), so there is no block to offer. + const addComputerBlock = machines.length === 0 && setupOs !== 'windows' ? (
{t('agentByo.addComputer.title')} - {setupOs !== 'windows' && ( -

{t('agentByo.addComputer.recommended')}

- )} - {setupOs !== 'windows' && ( -
- {daemonCommand} - -
- )} +

{t('agentByo.addComputer.recommended')}

+
+ {daemonCommand} + +

{t('agentByo.addComputer.after')}

) : null;