From a4d1a4f9b155e09e2eea2705d9afce4e67915280 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 9 Nov 2026 05:05:00 +0000 Subject: [PATCH 1/8] Lead the Account step with OpenBot and say what signing in is for The first setup screen read as signing up for a CopilotKit product. It now says OpenBot runs on this computer, that signing in to CopilotKit gets a free license for OpenBot's back end, and what signing in does and doesn't send. CopilotKit's logo no longer heads the step. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012xYtaUpk3r1M5kLhaeB62v --- CHANGELOG.md | 3 +++ desktop/src/App.test.tsx | 10 ++++---- desktop/src/CopilotKitAccount.test.tsx | 33 ++++++++++---------------- desktop/src/CopilotKitAccount.tsx | 27 +++++++++++++-------- 4 files changed, 37 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c864284e6..479ce576d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,9 @@ Newest first. `Unreleased` is what is on `main` and not yet tagged. ### OpenBot Desktop +- **The Account step leads with OpenBot.** It reads "OpenBot runs on this computer", says that + signing in to CopilotKit gets a free license for OpenBot's back end, which runs here too, and + says what signing in does and doesn't send. CopilotKit's logo no longer heads the step. - **A back end setup that stops says why.** OpenBot's log now records how every back end setup, start, update and stop ended: how long it took, its exit code, what its report says went wrong and the end of its error output. A setup that stopped used to leave nothing in the log. The card diff --git a/desktop/src/App.test.tsx b/desktop/src/App.test.tsx index 97509bb68d..88c0ccf8ae 100644 --- a/desktop/src/App.test.tsx +++ b/desktop/src/App.test.tsx @@ -611,11 +611,9 @@ test("a signed-out first run signs in to CopilotKit and accepts the agreement as await installLocal(view); // The first step. OpenBot needs no account, so it installs behind it, exactly once; nothing // of Intelligence's runs before the agreement. - await view.findByRole("heading", { name: "Sign in to CopilotKit" }); + await view.findByRole("heading", { name: "OpenBot runs on this computer" }); expect( - view.getByText( - "Your conversations and files are stored on this computer. Signing in does not send them to CopilotKit.", - ), + view.getByText("Your conversations and files stay on this computer."), ).toBeTruthy(); expect(stepLabel(view)).toBe("Account"); await waitFor(() => @@ -710,7 +708,7 @@ test("the account step says Docker Desktop is starting while Install waits on it }); const view = await renderApp(); await installLocal(view); - await view.findByRole("heading", { name: "Sign in to CopilotKit" }); + await view.findByRole("heading", { name: "OpenBot runs on this computer" }); await emitProgress({ step: "install-engine", @@ -744,7 +742,7 @@ test("a line about OpenBot's own work is not said as a hand-off on the account s }); const view = await renderApp(); await installLocal(view); - await view.findByRole("heading", { name: "Sign in to CopilotKit" }); + await view.findByRole("heading", { name: "OpenBot runs on this computer" }); await emitProgress({ step: "install-engine", ok: true, diff --git a/desktop/src/CopilotKitAccount.test.tsx b/desktop/src/CopilotKitAccount.test.tsx index 2834cbfcfe..3a86ee3e08 100644 --- a/desktop/src/CopilotKitAccount.test.tsx +++ b/desktop/src/CopilotKitAccount.test.tsx @@ -114,39 +114,32 @@ test("Cancel stops the CLI's sign-in and goes back to the start of the step", as ).toBeNull(); }); -/** CopilotKit's logotype, light, with the reversed wordmark for a dark window. */ -function expectCopilotKitLogo(screen: ReturnType) { - const logo = screen.getByRole("img", { name: "CopilotKit" }); - expect(logo.getAttribute("src")).toBe("/copilotkit-logo.svg"); - expect( - logo - .closest("picture") - ?.querySelector('source[media="(prefers-color-scheme: dark)"]') - ?.getAttribute("srcset"), - ).toBe("/copilotkit-logo-dark.svg"); -} - /* - * The step signs in to a CopilotKit account, so it shows CopilotKit's logotype, signed out and - * while the sign-in waits. It showed OpenBot's mark alone. + * The step is OpenBot's, so it leads with OpenBot, not CopilotKit's logotype, and says what signing + * in is for and what it does not send. */ -test("the CopilotKit sign-in shows CopilotKit's logotype, before and while it waits", async () => { +test("the sign-in leads with OpenBot and says what signing in is for", async () => { waitingSignIn(); const screen = render( {}} />, ); await screen.findByRole("button", { name: "Sign in to CopilotKit" }); - expectCopilotKitLogo(screen); + expect( + screen.getByRole("heading", { name: "OpenBot runs on this computer" }), + ).toBeTruthy(); + expect(screen.getByText(/free license/)).toBeTruthy(); + expect(screen.getByText(/Signing in only gets the license/)).toBeTruthy(); + expect(screen.queryByRole("img", { name: "CopilotKit" })).toBeNull(); await userEvent.click( screen.getByRole("button", { name: "Sign in to CopilotKit" }), ); await screen.findByText(PAGE.userCode); - expectCopilotKitLogo(screen); + expect(screen.queryByRole("img", { name: "CopilotKit" })).toBeNull(); }); test("after Accept, the step says it is setting up your apps, not to sign in", async () => { - // Seen on Windows: Accept was followed for two seconds by "Sign in to CopilotKit" and its + // Seen on Windows: Accept was followed for two seconds by the sign-in heading and its // sign-in lede, over "Connecting your apps…", for a person already signed in and agreed. let connected!: () => void; invokeHandler = async ({ command }) => { @@ -180,9 +173,9 @@ test("after Accept, the step says it is setting up your apps, not to sign in", a ).toBeTruthy(); expect(screen.getByText("Connecting your apps…")).toBeTruthy(); expect( - screen.queryByRole("heading", { name: "Sign in to CopilotKit" }), + screen.queryByRole("heading", { name: "OpenBot runs on this computer" }), ).toBeNull(); - expect(screen.queryByText(/Sign in, then accept/)).toBeNull(); + expect(screen.queryByText(/free license/)).toBeNull(); connected(); await waitFor(() => expect(done).toBe("developer-edition-2026-10-01-web")); }); diff --git a/desktop/src/CopilotKitAccount.tsx b/desktop/src/CopilotKitAccount.tsx index a7d2c7819d..7288449a31 100644 --- a/desktop/src/CopilotKitAccount.tsx +++ b/desktop/src/CopilotKitAccount.tsx @@ -5,7 +5,6 @@ import { useRef, useState, } from "react"; -import { CopilotKitLogo } from "./CopilotKitLogo"; import { CopilotKitSignInWait } from "./CopilotKitSignInWait"; import { ExternalLink } from "./ExternalLink"; import { @@ -200,10 +199,10 @@ export function CopilotKitAccount({ const appsFailed = seen.at === "apps-failed"; return (
- {/* OpenBot is what is being set up, so its mark heads this step as it heads every other. - The account is CopilotKit's, so its logotype leads the step itself. */} + {/* OpenBot is what is being set up, so its mark heads this step as it heads every other, + and the step leads with OpenBot. CopilotKit's part is the licence for the back end, said + in one line: its logotype here made the step read as signing up for a CopilotKit product. */} -

{agreement ? "Accept the license agreement" @@ -211,20 +210,28 @@ export function CopilotKitAccount({ ? "Setting up your apps" : appsFailed ? "Connect your apps" - : "Sign in to CopilotKit"} + : "OpenBot runs on this computer"}

{agreement ? `To run OpenBot on this computer, accept the CopilotKit license agreement for ${agreement.organizationName}.` : connecting || appsFailed ? "OpenBot uses your CopilotKit account to set up apps like Gmail and Slack." - : "OpenBot runs on this computer with your CopilotKit account. Sign in, then accept the license agreement."} + : "Its back end, from CopilotKit, runs here too. Sign in to CopilotKit to get a free license for it."}

+ {/* What the person gives up by signing in, and only what holds: the sign-in fetches the + licence, the conversations and files stay here, and what a Bot is asked goes to the AI + provider chosen on the AI step. Nothing broader, such as "no data leaves this computer": setup + and usage telemetry, the AI provider and connected apps all reach the network. */} {!agreement && !connecting && !appsFailed && ( -

- Your conversations and files are stored on this computer. Signing in - does not send them to CopilotKit. -

+
    +
  • Your conversations and files stay on this computer.
  • +
  • + Signing in only gets the license. It doesn’t send your conversations + or files to CopilotKit. +
  • +
  • What you ask a Bot goes to the AI provider you choose.
  • +
)} {/* The account check waits on the engine too. While Docker Desktop starts, this says what From 8ccb8a7d79cecdc9853208a41adfbaed9b4b7323 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 9 Nov 2026 05:10:53 +0000 Subject: [PATCH 2/8] Head the Account step "OpenBot by CopilotKit" and name CopilotKit Intelligence there Per Atai: the step's identity is OpenBot by CopilotKit, and its action is signing in for a free local license key for CopilotKit Intelligence. The copy rule and its guard test allow the name on this step alone, by exact text, and say why. Signing in also sets up apps, so the step says so instead of claiming it only gets the license. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012xYtaUpk3r1M5kLhaeB62v --- .claude/skills/openbot-copy/SKILL.md | 8 +++++- CHANGELOG.md | 7 +++-- desktop/src/App.test.tsx | 12 ++++---- desktop/src/CopilotKitAccount.test.tsx | 22 +++++++++------ desktop/src/CopilotKitAccount.tsx | 32 +++++++++++++--------- tests/no-intelligence-in-user-copy.test.ts | 18 ++++++++++-- 6 files changed, 65 insertions(+), 34 deletions(-) diff --git a/.claude/skills/openbot-copy/SKILL.md b/.claude/skills/openbot-copy/SKILL.md index 07a71273e3..ec4fd085b7 100644 --- a/.claude/skills/openbot-copy/SKILL.md +++ b/.claude/skills/openbot-copy/SKILL.md @@ -46,6 +46,12 @@ end. Try again." Name a feature by what it does (Automatic learning, Memory, Ski docs under `docs/` and `charts/` are not shown to a person and may name it. `tests/no-intelligence-in-user-copy.test.ts` fails on a shown string that says it. +**One exception: OpenBot Desktop's Account step.** Its lede says "OpenBot runs on this computer +with CopilotKit Intelligence, which runs here too. Sign in to get a free local license key for it." +That screen asks the person to sign in to another company's account, and the name is what makes +the license key make sense; the CopilotKit sign-in page it opens says the same. It is listed by +exact text in `SHOWN_BY_DECISION` in the test. Anywhere else, the back end. + **Admin is allowed exact names.** An admin page may name `COMPOSIO_API_KEY`, OAuth and "deployment", because the admin is the one who sets them. A page anybody can open may not. @@ -90,5 +96,5 @@ because the admin is the one who sets them. A page anybody can open may not. | "rather than", an em dash, "which is" in UI text | Rewrite as two short sentences | | A description beginning "The apps…", "What…", "Who…", or "Where…" without a main verb | State the action or behavior in a complete sentence; remove redundant explanation | | An env var, OAuth, Composio or "grant" outside Admin | Say what the person sees | -| "Intelligence", "CopilotKit Intelligence" or "the Intelligence stack" anywhere | Name the part: the back end, the front end, the database | +| "Intelligence", "CopilotKit Intelligence" or "the Intelligence stack" anywhere but the Desktop Account step | Name the part: the back end, the front end, the database | | A test asserting long explanatory copy | Assert the short sentence, or the role and the key words | diff --git a/CHANGELOG.md b/CHANGELOG.md index 479ce576d5..6b399c32b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,9 +31,10 @@ Newest first. `Unreleased` is what is on `main` and not yet tagged. ### OpenBot Desktop -- **The Account step leads with OpenBot.** It reads "OpenBot runs on this computer", says that - signing in to CopilotKit gets a free license for OpenBot's back end, which runs here too, and - says what signing in does and doesn't send. CopilotKit's logo no longer heads the step. +- **The Account step leads with OpenBot.** It reads "OpenBot by CopilotKit", says that signing in + gets a free local license key for CopilotKit Intelligence, which runs on this computer too, and + says what stays on the computer. The button reads "Sign in for a free license key", and + CopilotKit's logo no longer heads the step. - **A back end setup that stops says why.** OpenBot's log now records how every back end setup, start, update and stop ended: how long it took, its exit code, what its report says went wrong and the end of its error output. A setup that stopped used to leave nothing in the log. The card diff --git a/desktop/src/App.test.tsx b/desktop/src/App.test.tsx index 88c0ccf8ae..3060fd1d6b 100644 --- a/desktop/src/App.test.tsx +++ b/desktop/src/App.test.tsx @@ -611,9 +611,9 @@ test("a signed-out first run signs in to CopilotKit and accepts the agreement as await installLocal(view); // The first step. OpenBot needs no account, so it installs behind it, exactly once; nothing // of Intelligence's runs before the agreement. - await view.findByRole("heading", { name: "OpenBot runs on this computer" }); + await view.findByRole("heading", { name: "OpenBot by CopilotKit" }); expect( - view.getByText("Your conversations and files stay on this computer."), + view.getByText(/Your conversations and files stay on this computer/), ).toBeTruthy(); expect(stepLabel(view)).toBe("Account"); await waitFor(() => @@ -623,7 +623,7 @@ test("a signed-out first run signs in to CopilotKit and accepts the agreement as ); expect(localSequence()).toEqual([]); await userEvent.click( - view.getByRole("button", { name: "Sign in to CopilotKit" }), + view.getByRole("button", { name: "Sign in for a free license key" }), ); await view.findByRole("heading", { name: "Accept the license agreement" }); expect( @@ -680,7 +680,7 @@ test("the account step waits for a container engine Install is still setting up, await installLocal(view); await view.findByRole( "button", - { name: "Sign in to CopilotKit" }, + { name: "Sign in for a free license key" }, { timeout: 6000 }, ); expect(asked).toBe(2); @@ -708,7 +708,7 @@ test("the account step says Docker Desktop is starting while Install waits on it }); const view = await renderApp(); await installLocal(view); - await view.findByRole("heading", { name: "OpenBot runs on this computer" }); + await view.findByRole("heading", { name: "OpenBot by CopilotKit" }); await emitProgress({ step: "install-engine", @@ -742,7 +742,7 @@ test("a line about OpenBot's own work is not said as a hand-off on the account s }); const view = await renderApp(); await installLocal(view); - await view.findByRole("heading", { name: "OpenBot runs on this computer" }); + await view.findByRole("heading", { name: "OpenBot by CopilotKit" }); await emitProgress({ step: "install-engine", ok: true, diff --git a/desktop/src/CopilotKitAccount.test.tsx b/desktop/src/CopilotKitAccount.test.tsx index 3a86ee3e08..f229762ad2 100644 --- a/desktop/src/CopilotKitAccount.test.tsx +++ b/desktop/src/CopilotKitAccount.test.tsx @@ -64,7 +64,9 @@ async function startSigningIn() { {}} />, ); await userEvent.click( - await screen.findByRole("button", { name: "Sign in to CopilotKit" }), + await screen.findByRole("button", { + name: "Sign in for a free license key", + }), ); return screen; } @@ -103,7 +105,9 @@ test("Cancel stops the CLI's sign-in and goes back to the start of the step", as { command: "cancel_local_eval", args: { attempt: signInAttempt() } }, ]); expect( - await screen.findByRole("button", { name: "Sign in to CopilotKit" }), + await screen.findByRole("button", { + name: "Sign in for a free license key", + }), ).toBeTruthy(); expect(screen.queryByText(PAGE.userCode)).toBeNull(); // The stopped sign-in is not reported as a failure. @@ -123,16 +127,16 @@ test("the sign-in leads with OpenBot and says what signing in is for", async () const screen = render( {}} />, ); - await screen.findByRole("button", { name: "Sign in to CopilotKit" }); + await screen.findByRole("button", { name: "Sign in for a free license key" }); expect( - screen.getByRole("heading", { name: "OpenBot runs on this computer" }), + screen.getByRole("heading", { name: "OpenBot by CopilotKit" }), ).toBeTruthy(); - expect(screen.getByText(/free license/)).toBeTruthy(); - expect(screen.getByText(/Signing in only gets the license/)).toBeTruthy(); + expect(screen.getByText(/free local license key/)).toBeTruthy(); + expect(screen.getByText(/CopilotKit doesn’t get them/)).toBeTruthy(); expect(screen.queryByRole("img", { name: "CopilotKit" })).toBeNull(); await userEvent.click( - screen.getByRole("button", { name: "Sign in to CopilotKit" }), + screen.getByRole("button", { name: "Sign in for a free license key" }), ); await screen.findByText(PAGE.userCode); expect(screen.queryByRole("img", { name: "CopilotKit" })).toBeNull(); @@ -173,9 +177,9 @@ test("after Accept, the step says it is setting up your apps, not to sign in", a ).toBeTruthy(); expect(screen.getByText("Connecting your apps…")).toBeTruthy(); expect( - screen.queryByRole("heading", { name: "OpenBot runs on this computer" }), + screen.queryByRole("heading", { name: "OpenBot by CopilotKit" }), ).toBeNull(); - expect(screen.queryByText(/free license/)).toBeNull(); + expect(screen.queryByText(/free local license key/)).toBeNull(); connected(); await waitFor(() => expect(done).toBe("developer-edition-2026-10-01-web")); }); diff --git a/desktop/src/CopilotKitAccount.tsx b/desktop/src/CopilotKitAccount.tsx index 7288449a31..377e85467b 100644 --- a/desktop/src/CopilotKitAccount.tsx +++ b/desktop/src/CopilotKitAccount.tsx @@ -200,8 +200,8 @@ export function CopilotKitAccount({ return (
{/* OpenBot is what is being set up, so its mark heads this step as it heads every other, - and the step leads with OpenBot. CopilotKit's part is the licence for the back end, said - in one line: its logotype here made the step read as signing up for a CopilotKit product. */} + and the step leads with OpenBot by CopilotKit. CopilotKit's logotype here made the step read + as signing up for a CopilotKit product. */}

{agreement @@ -210,27 +210,33 @@ export function CopilotKitAccount({ ? "Setting up your apps" : appsFailed ? "Connect your apps" - : "OpenBot runs on this computer"} + : "OpenBot by CopilotKit"}

{agreement ? `To run OpenBot on this computer, accept the CopilotKit license agreement for ${agreement.organizationName}.` : connecting || appsFailed ? "OpenBot uses your CopilotKit account to set up apps like Gmail and Slack." - : "Its back end, from CopilotKit, runs here too. Sign in to CopilotKit to get a free license for it."} + : // Names CopilotKit Intelligence on this step alone: it is what the license key is + // for, and the browser sign-in page that opens next says the same. + "OpenBot runs on this computer with CopilotKit Intelligence, which runs here too. Sign in to get a free local license key for it."}

- {/* What the person gives up by signing in, and only what holds: the sign-in fetches the - licence, the conversations and files stay here, and what a Bot is asked goes to the AI - provider chosen on the AI step. Nothing broader, such as "no data leaves this computer": setup - and usage telemetry, the AI provider and connected apps all reach the network. */} + {/* What the person gives up by signing in, and only what holds: conversations and files stay + here, the sign-in fetches the license key and sets up apps, and what a Bot is asked goes to + the AI provider chosen on the AI step. Nothing broader, such as "no data leaves this + computer": setup and usage telemetry, the AI provider and connected apps all reach the + network. */} {!agreement && !connecting && !appsFailed && (
    -
  • Your conversations and files stay on this computer.
  • - Signing in only gets the license. It doesn’t send your conversations - or files to CopilotKit. + Your conversations and files stay on this computer. CopilotKit + doesn’t get them.
  • -
  • What you ask a Bot goes to the AI provider you choose.
  • +
  • + Signing in gets your license key and lets OpenBot connect apps like + Gmail and Slack. +
  • +
  • What you ask goes to the AI provider you choose.
)} @@ -271,7 +277,7 @@ export function CopilotKitAccount({
{seen.at === "signed-out" && ( )} {agreement && ( diff --git a/tests/no-intelligence-in-user-copy.test.ts b/tests/no-intelligence-in-user-copy.test.ts index 8a5768d9a4..f0aefa6eed 100644 --- a/tests/no-intelligence-in-user-copy.test.ts +++ b/tests/no-intelligence-in-user-copy.test.ts @@ -66,6 +66,20 @@ const NOT_SHOWN: { file: string; text: string; why: string }[] = [ }, ]; +/** + * Shown text that names CopilotKit Intelligence on purpose. One entry, by exact text: OpenBot + * Desktop's Account step, where the name says what the free license key is for and matches the + * CopilotKit sign-in page that opens next. Everywhere else it is still the back end (see + * .claude/skills/openbot-copy). A new entry is a product decision, not a way past this test. + */ +const SHOWN_BY_DECISION: { file: string; text: string; why: string }[] = [ + { + file: "desktop/src/CopilotKitAccount.tsx", + text: "OpenBot runs on this computer with CopilotKit Intelligence, which runs here too. Sign in to get a free local license key for it.", + why: "the Account step names what the sign-in gets a license key for", + }, +]; + /** Calls whose arguments are written to a log, never shown. */ const LOGGING = /^(console\.\w+|log|logger\.\w+|this\.log|options\.log|note|once|sayUnavailable)$/; @@ -183,7 +197,7 @@ function shown(): string[] { } const isNotShown = (hit: string) => - NOT_SHOWN.some( + [...NOT_SHOWN, ...SHOWN_BY_DECISION].some( (entry) => hit.startsWith(`${entry.file}:`) && hit.includes(entry.text), ); @@ -193,7 +207,7 @@ test("no text a person reads in the desktop app, the app, the server or the Reco test("every exception for text that is never shown still matches", () => { const found = shown(); - const stale = NOT_SHOWN.filter( + const stale = [...NOT_SHOWN, ...SHOWN_BY_DECISION].filter( (entry) => !found.some( (hit) => hit.startsWith(`${entry.file}:`) && hit.includes(entry.text), From c6f16af85894b6f1a50355349cf7681a8d12170d Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 9 Nov 2026 05:13:29 +0000 Subject: [PATCH 3/8] Put "by CopilotKit" beside OpenBot's name and keep the step's heading OpenBot's Per the coordinator's spec for Atai: the Account step's header reads OpenBot by CopilotKit, with "by CopilotKit" quieter than the name; the heading stays "OpenBot runs on this computer"; the lede names CopilotKit Intelligence and says the sign-in is at CopilotKit. The second bullet says signing in also lets OpenBot connect apps, which the same step sets up. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012xYtaUpk3r1M5kLhaeB62v --- .claude/skills/openbot-copy/SKILL.md | 5 +++-- CHANGELOG.md | 9 +++++---- desktop/src/App.test.tsx | 6 +++--- desktop/src/CopilotKitAccount.test.tsx | 7 ++++--- desktop/src/CopilotKitAccount.tsx | 22 ++++++++++------------ desktop/src/Sections.tsx | 10 +++++++++- desktop/src/styles.css | 7 +++++++ tests/no-intelligence-in-user-copy.test.ts | 2 +- 8 files changed, 42 insertions(+), 26 deletions(-) diff --git a/.claude/skills/openbot-copy/SKILL.md b/.claude/skills/openbot-copy/SKILL.md index ec4fd085b7..6cec634d9f 100644 --- a/.claude/skills/openbot-copy/SKILL.md +++ b/.claude/skills/openbot-copy/SKILL.md @@ -46,8 +46,9 @@ end. Try again." Name a feature by what it does (Automatic learning, Memory, Ski docs under `docs/` and `charts/` are not shown to a person and may name it. `tests/no-intelligence-in-user-copy.test.ts` fails on a shown string that says it. -**One exception: OpenBot Desktop's Account step.** Its lede says "OpenBot runs on this computer -with CopilotKit Intelligence, which runs here too. Sign in to get a free local license key for it." +**One exception: OpenBot Desktop's Account step.** Its lede says "OpenBot needs CopilotKit +Intelligence, which runs on this computer too. Sign in to CopilotKit to get a free local license key +for it." That screen asks the person to sign in to another company's account, and the name is what makes the license key make sense; the CopilotKit sign-in page it opens says the same. It is listed by exact text in `SHOWN_BY_DECISION` in the test. Anywhere else, the back end. diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b399c32b4..0b1c533c0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,10 +31,11 @@ Newest first. `Unreleased` is what is on `main` and not yet tagged. ### OpenBot Desktop -- **The Account step leads with OpenBot.** It reads "OpenBot by CopilotKit", says that signing in - gets a free local license key for CopilotKit Intelligence, which runs on this computer too, and - says what stays on the computer. The button reads "Sign in for a free license key", and - CopilotKit's logo no longer heads the step. +- **The Account step leads with OpenBot.** Its header reads "OpenBot by CopilotKit" and its + heading "OpenBot runs on this computer". It says that signing in to CopilotKit gets a free local + license key for CopilotKit Intelligence, which runs on this computer too, and what signing in + does and doesn't send. The button reads "Sign in for a free license key", and CopilotKit's logo + no longer heads the step. - **A back end setup that stops says why.** OpenBot's log now records how every back end setup, start, update and stop ended: how long it took, its exit code, what its report says went wrong and the end of its error output. A setup that stopped used to leave nothing in the log. The card diff --git a/desktop/src/App.test.tsx b/desktop/src/App.test.tsx index 3060fd1d6b..a9877bc5df 100644 --- a/desktop/src/App.test.tsx +++ b/desktop/src/App.test.tsx @@ -611,7 +611,7 @@ test("a signed-out first run signs in to CopilotKit and accepts the agreement as await installLocal(view); // The first step. OpenBot needs no account, so it installs behind it, exactly once; nothing // of Intelligence's runs before the agreement. - await view.findByRole("heading", { name: "OpenBot by CopilotKit" }); + await view.findByRole("heading", { name: "OpenBot runs on this computer" }); expect( view.getByText(/Your conversations and files stay on this computer/), ).toBeTruthy(); @@ -708,7 +708,7 @@ test("the account step says Docker Desktop is starting while Install waits on it }); const view = await renderApp(); await installLocal(view); - await view.findByRole("heading", { name: "OpenBot by CopilotKit" }); + await view.findByRole("heading", { name: "OpenBot runs on this computer" }); await emitProgress({ step: "install-engine", @@ -742,7 +742,7 @@ test("a line about OpenBot's own work is not said as a hand-off on the account s }); const view = await renderApp(); await installLocal(view); - await view.findByRole("heading", { name: "OpenBot by CopilotKit" }); + await view.findByRole("heading", { name: "OpenBot runs on this computer" }); await emitProgress({ step: "install-engine", ok: true, diff --git a/desktop/src/CopilotKitAccount.test.tsx b/desktop/src/CopilotKitAccount.test.tsx index f229762ad2..61a8d13b78 100644 --- a/desktop/src/CopilotKitAccount.test.tsx +++ b/desktop/src/CopilotKitAccount.test.tsx @@ -129,10 +129,11 @@ test("the sign-in leads with OpenBot and says what signing in is for", async () ); await screen.findByRole("button", { name: "Sign in for a free license key" }); expect( - screen.getByRole("heading", { name: "OpenBot by CopilotKit" }), + screen.getByRole("heading", { name: "OpenBot runs on this computer" }), ).toBeTruthy(); expect(screen.getByText(/free local license key/)).toBeTruthy(); - expect(screen.getByText(/CopilotKit doesn’t get them/)).toBeTruthy(); + expect(screen.getByText(/Signing in gets the license key/)).toBeTruthy(); + expect(screen.getByText("by CopilotKit")).toBeTruthy(); expect(screen.queryByRole("img", { name: "CopilotKit" })).toBeNull(); await userEvent.click( @@ -177,7 +178,7 @@ test("after Accept, the step says it is setting up your apps, not to sign in", a ).toBeTruthy(); expect(screen.getByText("Connecting your apps…")).toBeTruthy(); expect( - screen.queryByRole("heading", { name: "OpenBot by CopilotKit" }), + screen.queryByRole("heading", { name: "OpenBot runs on this computer" }), ).toBeNull(); expect(screen.queryByText(/free local license key/)).toBeNull(); connected(); diff --git a/desktop/src/CopilotKitAccount.tsx b/desktop/src/CopilotKitAccount.tsx index 377e85467b..f9db0e91b8 100644 --- a/desktop/src/CopilotKitAccount.tsx +++ b/desktop/src/CopilotKitAccount.tsx @@ -200,9 +200,9 @@ export function CopilotKitAccount({ return (
{/* OpenBot is what is being set up, so its mark heads this step as it heads every other, - and the step leads with OpenBot by CopilotKit. CopilotKit's logotype here made the step read - as signing up for a CopilotKit product. */} - + and here it says "by CopilotKit" beside the name. CopilotKit's logotype here made the step + read as signing up for a CopilotKit product. */} +

{agreement ? "Accept the license agreement" @@ -210,7 +210,7 @@ export function CopilotKitAccount({ ? "Setting up your apps" : appsFailed ? "Connect your apps" - : "OpenBot by CopilotKit"} + : "OpenBot runs on this computer"}

{agreement @@ -219,7 +219,7 @@ export function CopilotKitAccount({ ? "OpenBot uses your CopilotKit account to set up apps like Gmail and Slack." : // Names CopilotKit Intelligence on this step alone: it is what the license key is // for, and the browser sign-in page that opens next says the same. - "OpenBot runs on this computer with CopilotKit Intelligence, which runs here too. Sign in to get a free local license key for it."} + "OpenBot needs CopilotKit Intelligence, which runs on this computer too. Sign in to CopilotKit to get a free local license key for it."}

{/* What the person gives up by signing in, and only what holds: conversations and files stay here, the sign-in fetches the license key and sets up apps, and what a Bot is asked goes to @@ -228,15 +228,13 @@ export function CopilotKitAccount({ network. */} {!agreement && !connecting && !appsFailed && (
    +
  • Your conversations and files stay on this computer.
  • - Your conversations and files stay on this computer. CopilotKit - doesn’t get them. + Signing in gets the license key and lets OpenBot connect apps like + Gmail and Slack. It doesn’t send your conversations or files to + CopilotKit.
  • -
  • - Signing in gets your license key and lets OpenBot connect apps like - Gmail and Slack. -
  • -
  • What you ask goes to the AI provider you choose.
  • +
  • What you ask a Bot goes to the AI provider you choose.
)} diff --git a/desktop/src/Sections.tsx b/desktop/src/Sections.tsx index 94ee38361e..1f097e7ba8 100644 --- a/desktop/src/Sections.tsx +++ b/desktop/src/Sections.tsx @@ -15,7 +15,14 @@ const SECTIONS: Section[] = ["Account", "Install", "AI", "Start"]; * step that signs in to a CopilotKit account. The name is decoration here: the window's title * already says it, so it is hidden from assistive technology rather than read on every screen. */ -export function Sections({ at }: { at: Section }) { +export function Sections({ + at, + byCopilotKit = false, +}: { + at: Section; + /** "by CopilotKit" beside OpenBot's name, on the step that asks for a CopilotKit sign-in. */ + byCopilotKit?: boolean; +}) { const names = SECTIONS; const current = names.indexOf(at); return ( @@ -23,6 +30,7 @@ export function Sections({ at }: { at: Section }) {