Skip to content

Commit 3a0bf2f

Browse files
authored
fix console account URL handling (#18809)
1 parent b556979 commit 3a0bf2f

2 files changed

Lines changed: 70 additions & 10 deletions

File tree

packages/opencode/src/cli/cmd/account.ts

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,26 @@ const openBrowser = (url: string) => Effect.promise(() => open(url).catch(() =>
1010

1111
const println = (msg: string) => Effect.sync(() => UI.println(msg))
1212

13+
const dim = (value: string) => UI.Style.TEXT_DIM + value + UI.Style.TEXT_NORMAL
14+
15+
const activeSuffix = (isActive: boolean) => (isActive ? dim(" (active)") : "")
16+
17+
export const formatAccountLabel = (account: { email: string; url: string }, isActive: boolean) =>
18+
`${account.email} ${dim(account.url)}${activeSuffix(isActive)}`
19+
20+
const formatOrgChoiceLabel = (account: { email: string }, org: { name: string }, isActive: boolean) =>
21+
`${org.name} (${account.email})${activeSuffix(isActive)}`
22+
23+
export const formatOrgLine = (
24+
account: { email: string; url: string },
25+
org: { id: string; name: string },
26+
isActive: boolean,
27+
) => {
28+
const dot = isActive ? UI.Style.TEXT_SUCCESS + "●" + UI.Style.TEXT_NORMAL : " "
29+
const name = isActive ? UI.Style.TEXT_HIGHLIGHT_BOLD + org.name + UI.Style.TEXT_NORMAL : org.name
30+
return ` ${dot} ${name} ${dim(account.email)} ${dim(account.url)} ${dim(org.id)}`
31+
}
32+
1333
const isActiveOrgChoice = (
1434
active: Option.Option<{ id: AccountID; active_org_id: OrgID | null }>,
1535
choice: { accountID: AccountID; orgID: OrgID },
@@ -76,10 +96,9 @@ const logoutEffect = Effect.fn("logout")(function* (email?: string) {
7696

7797
const opts = accounts.map((a) => {
7898
const isActive = Option.isSome(activeID) && activeID.value === a.id
79-
const server = UI.Style.TEXT_DIM + a.url + UI.Style.TEXT_NORMAL
8099
return {
81100
value: a,
82-
label: isActive ? `${a.email} ${server}` + UI.Style.TEXT_DIM + " (active)" : `${a.email} ${server}`,
101+
label: formatAccountLabel(a, isActive),
83102
}
84103
})
85104

@@ -109,9 +128,7 @@ const switchEffect = Effect.fn("switch")(function* () {
109128
const isActive = isActiveOrgChoice(active, { accountID: group.account.id, orgID: org.id })
110129
return {
111130
value: { orgID: org.id, accountID: group.account.id, label: org.name },
112-
label: isActive
113-
? `${org.name} (${group.account.email})` + UI.Style.TEXT_DIM + " (active)"
114-
: `${org.name} (${group.account.email})`,
131+
label: formatOrgChoiceLabel(group.account, org, isActive),
115132
}
116133
}),
117134
)
@@ -139,15 +156,21 @@ const orgsEffect = Effect.fn("orgs")(function* () {
139156
for (const group of groups) {
140157
for (const org of group.orgs) {
141158
const isActive = isActiveOrgChoice(active, { accountID: group.account.id, orgID: org.id })
142-
const dot = isActive ? UI.Style.TEXT_SUCCESS + "●" + UI.Style.TEXT_NORMAL : " "
143-
const name = isActive ? UI.Style.TEXT_HIGHLIGHT_BOLD + org.name + UI.Style.TEXT_NORMAL : org.name
144-
const email = UI.Style.TEXT_DIM + group.account.email + UI.Style.TEXT_NORMAL
145-
const id = UI.Style.TEXT_DIM + org.id + UI.Style.TEXT_NORMAL
146-
yield* println(` ${dot} ${name} ${email} ${id}`)
159+
yield* println(formatOrgLine(group.account, org, isActive))
147160
}
148161
}
149162
})
150163

164+
const openEffect = Effect.fn("open")(function* () {
165+
const service = yield* Account.Service
166+
const active = yield* service.active()
167+
if (Option.isNone(active)) return yield* println("No active account")
168+
169+
const url = active.value.url
170+
yield* openBrowser(url)
171+
yield* Prompt.outro("Opened " + url)
172+
})
173+
151174
export const LoginCommand = cmd({
152175
command: "login <url>",
153176
describe: false,
@@ -195,6 +218,15 @@ export const OrgsCommand = cmd({
195218
},
196219
})
197220

221+
export const OpenCommand = cmd({
222+
command: "open",
223+
describe: false,
224+
async handler() {
225+
UI.empty()
226+
await Account.runPromise((_svc) => openEffect())
227+
},
228+
})
229+
198230
export const ConsoleCommand = cmd({
199231
command: "console",
200232
describe: false,
@@ -216,6 +248,10 @@ export const ConsoleCommand = cmd({
216248
...OrgsCommand,
217249
describe: "list orgs",
218250
})
251+
.command({
252+
...OpenCommand,
253+
describe: "open active console account",
254+
})
219255
.demandCommand(),
220256
async handler() {},
221257
})
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { describe, expect, test } from "bun:test"
2+
import stripAnsi from "strip-ansi"
3+
4+
import { formatAccountLabel, formatOrgLine } from "../../src/cli/cmd/account"
5+
6+
describe("console account display", () => {
7+
test("includes the account url in account labels", () => {
8+
expect(stripAnsi(formatAccountLabel({ email: "one@example.com", url: "https://one.example.com" }, false))).toBe(
9+
"one@example.com https://one.example.com",
10+
)
11+
})
12+
13+
test("includes the active marker in account labels", () => {
14+
expect(stripAnsi(formatAccountLabel({ email: "one@example.com", url: "https://one.example.com" }, true))).toBe(
15+
"one@example.com https://one.example.com (active)",
16+
)
17+
})
18+
19+
test("includes the account url in org rows", () => {
20+
expect(
21+
stripAnsi(formatOrgLine({ email: "one@example.com", url: "https://one.example.com" }, { id: "org-1", name: "One" }, true)),
22+
).toBe(" ● One one@example.com https://one.example.com org-1")
23+
})
24+
})

0 commit comments

Comments
 (0)