fmt(js): npm run fix on merge (#95858)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
a6d6060d61
commit
74cb4cb80c
@@ -1075,7 +1075,10 @@ export function normalizeRegistry(raw: unknown): ConnectionRegistry {
|
||||
if (Array.isArray(parsed.quarantined)) {
|
||||
for (const item of parsed.quarantined) {
|
||||
if (item && typeof item === 'object' && 'entry' in (item as Record<string, unknown>)) {
|
||||
quarantine(String((item as Record<string, unknown>).reason || 'unknown'), (item as Record<string, unknown>).entry)
|
||||
quarantine(
|
||||
String((item as Record<string, unknown>).reason || 'unknown'),
|
||||
(item as Record<string, unknown>).entry
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1105,82 +1108,82 @@ export function normalizeRegistry(raw: unknown): ConnectionRegistry {
|
||||
// One bad entry must never abort the whole registry load (#94246): any
|
||||
// unexpected throw quarantines THIS entry and the loop moves on.
|
||||
try {
|
||||
const entry = item as Record<string, unknown>
|
||||
const kind = entry.kind
|
||||
const entry = item as Record<string, unknown>
|
||||
const kind = entry.kind
|
||||
|
||||
if (kind !== 'local' && kind !== 'remote' && kind !== 'cloud' && kind !== 'ssh') {
|
||||
quarantine('entry-unrecognized-kind', item)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
let label = String(entry.label || '').trim()
|
||||
|
||||
if (!label) {
|
||||
// Defensive: registry entries are always written with labels, but a
|
||||
// hand-edited file may drop one. Derive rather than discard.
|
||||
label =
|
||||
kind === 'ssh' ? String(entry.host || 'ssh') : hostLabelFromBaseUrl(String(entry.url || '')) || String(kind)
|
||||
}
|
||||
|
||||
label = uniqueLabel(label, seenLabels)
|
||||
|
||||
let id = kind === 'local' ? LOCAL_CONNECTION_ID : String(entry.id || '').trim()
|
||||
|
||||
if (!id || (seenIds.has(id) && kind !== 'local')) {
|
||||
id = connectionIdForLabel(label, seenIds)
|
||||
}
|
||||
|
||||
if (seenIds.has(id)) {
|
||||
continue // second 'local' entry — first one wins
|
||||
}
|
||||
|
||||
seenLabels.add(labelKey(label))
|
||||
seenIds.add(id)
|
||||
|
||||
const clean: RegistryConnection = { id, kind, label }
|
||||
|
||||
if (kind === 'remote' || kind === 'cloud') {
|
||||
const url = String(entry.url || '').trim()
|
||||
|
||||
if (!url) {
|
||||
quarantine('entry-missing-url', item)
|
||||
if (kind !== 'local' && kind !== 'remote' && kind !== 'cloud' && kind !== 'ssh') {
|
||||
quarantine('entry-unrecognized-kind', item)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
clean.url = url
|
||||
clean.authMode = normAuthMode(entry.authMode)
|
||||
let label = String(entry.label || '').trim()
|
||||
|
||||
if (entry.token !== undefined) {
|
||||
clean.token = entry.token
|
||||
if (!label) {
|
||||
// Defensive: registry entries are always written with labels, but a
|
||||
// hand-edited file may drop one. Derive rather than discard.
|
||||
label =
|
||||
kind === 'ssh' ? String(entry.host || 'ssh') : hostLabelFromBaseUrl(String(entry.url || '')) || String(kind)
|
||||
}
|
||||
|
||||
const storedHeaders = normalizeRemoteHeaders(entry.headers)
|
||||
label = uniqueLabel(label, seenLabels)
|
||||
|
||||
if (Object.keys(storedHeaders).length > 0) {
|
||||
clean.headers = storedHeaders
|
||||
let id = kind === 'local' ? LOCAL_CONNECTION_ID : String(entry.id || '').trim()
|
||||
|
||||
if (!id || (seenIds.has(id) && kind !== 'local')) {
|
||||
id = connectionIdForLabel(label, seenIds)
|
||||
}
|
||||
|
||||
const org = String(entry.org || '').trim()
|
||||
|
||||
if (kind === 'cloud' && org) {
|
||||
clean.org = org
|
||||
}
|
||||
} else if (kind === 'ssh') {
|
||||
const ssh = normalizeSshConfig({ ...entry, mode: 'ssh' })
|
||||
|
||||
if (!ssh) {
|
||||
quarantine('entry-missing-ssh-host', item)
|
||||
|
||||
continue
|
||||
if (seenIds.has(id)) {
|
||||
continue // second 'local' entry — first one wins
|
||||
}
|
||||
|
||||
const { mode: _mode, ...sshFields } = ssh
|
||||
Object.assign(clean, sshFields)
|
||||
}
|
||||
seenLabels.add(labelKey(label))
|
||||
seenIds.add(id)
|
||||
|
||||
connections.push(clean)
|
||||
const clean: RegistryConnection = { id, kind, label }
|
||||
|
||||
if (kind === 'remote' || kind === 'cloud') {
|
||||
const url = String(entry.url || '').trim()
|
||||
|
||||
if (!url) {
|
||||
quarantine('entry-missing-url', item)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
clean.url = url
|
||||
clean.authMode = normAuthMode(entry.authMode)
|
||||
|
||||
if (entry.token !== undefined) {
|
||||
clean.token = entry.token
|
||||
}
|
||||
|
||||
const storedHeaders = normalizeRemoteHeaders(entry.headers)
|
||||
|
||||
if (Object.keys(storedHeaders).length > 0) {
|
||||
clean.headers = storedHeaders
|
||||
}
|
||||
|
||||
const org = String(entry.org || '').trim()
|
||||
|
||||
if (kind === 'cloud' && org) {
|
||||
clean.org = org
|
||||
}
|
||||
} else if (kind === 'ssh') {
|
||||
const ssh = normalizeSshConfig({ ...entry, mode: 'ssh' })
|
||||
|
||||
if (!ssh) {
|
||||
quarantine('entry-missing-ssh-host', item)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
const { mode: _mode, ...sshFields } = ssh
|
||||
Object.assign(clean, sshFields)
|
||||
}
|
||||
|
||||
connections.push(clean)
|
||||
} catch {
|
||||
quarantine('entry-normalization-failed', safeEntryCopy(item))
|
||||
}
|
||||
|
||||
@@ -68,9 +68,7 @@ describe('resolveOauthPartition (#92183 per-connection cookie jars)', () => {
|
||||
remote('conn-b', 'https://gw-b.example.com')
|
||||
])
|
||||
|
||||
expect(resolveOauthPartition('https://gw-a.example.com/api/status', { registry: reg })).toBe(
|
||||
LEGACY_OAUTH_PARTITION
|
||||
)
|
||||
expect(resolveOauthPartition('https://gw-a.example.com/api/status', { registry: reg })).toBe(LEGACY_OAUTH_PARTITION)
|
||||
expect(resolveOauthPartition('https://gw-b.example.com/api/status', { registry: reg })).not.toBe(
|
||||
LEGACY_OAUTH_PARTITION
|
||||
)
|
||||
@@ -100,12 +98,10 @@ describe('resolveOauthPartition (#92183 per-connection cookie jars)', () => {
|
||||
)
|
||||
expect(resolveOauthPartition('not a url', { registry: reg })).toBe(LEGACY_OAUTH_PARTITION)
|
||||
expect(resolveOauthPartition('', { registry: reg })).toBe(LEGACY_OAUTH_PARTITION)
|
||||
expect(resolveOauthPartition('https://gw-a.example.com', { registry: null as any })).toBe(
|
||||
LEGACY_OAUTH_PARTITION
|
||||
)
|
||||
expect(resolveOauthPartition('https://gw-a.example.com', { registry: { primary: 'x', connections: 'junk' } as any })).toBe(
|
||||
LEGACY_OAUTH_PARTITION
|
||||
)
|
||||
expect(resolveOauthPartition('https://gw-a.example.com', { registry: null as any })).toBe(LEGACY_OAUTH_PARTITION)
|
||||
expect(
|
||||
resolveOauthPartition('https://gw-a.example.com', { registry: { primary: 'x', connections: 'junk' } as any })
|
||||
).toBe(LEGACY_OAUTH_PARTITION)
|
||||
})
|
||||
|
||||
it('does not treat a hostname PREFIX as a base-url match', () => {
|
||||
|
||||
@@ -142,11 +142,7 @@ export function resolveOauthPartition(requestUrl: unknown, opts: ResolveOauthPar
|
||||
// Longest base-url prefix wins (sub-path gateways behind one proxy);
|
||||
// identical URLs tie-break on the lexicographically smallest id so the
|
||||
// choice is deterministic across processes and launches.
|
||||
if (
|
||||
!best ||
|
||||
baseNorm.length > best.baseNorm.length ||
|
||||
(baseNorm.length === best.baseNorm.length && id < best.id)
|
||||
) {
|
||||
if (!best || baseNorm.length > best.baseNorm.length || (baseNorm.length === best.baseNorm.length && id < best.id)) {
|
||||
best = { baseNorm, id }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,11 +12,41 @@ const connections: DesktopRegistryConnection[] = [
|
||||
|
||||
const roster: DesktopAgentRoster = {
|
||||
agents: [
|
||||
{ connectionId: 'pandora', connectionKind: 'remote', connectionLabel: 'Pandora', profile: 'default', handle: 'hermes-pandora' },
|
||||
{ connectionId: 'pandora', connectionKind: 'remote', connectionLabel: 'Pandora', profile: 'scout', handle: 'scout' },
|
||||
{ connectionId: 'pandora', connectionKind: 'remote', connectionLabel: 'Pandora', profile: 'omer', handle: 'omer-pandora' },
|
||||
{ connectionId: 'local', connectionKind: 'local', connectionLabel: 'This device', profile: 'default', handle: 'hermes' },
|
||||
{ connectionId: 'local', connectionKind: 'local', connectionLabel: 'This device', profile: 'omer', handle: 'omer-this-device' }
|
||||
{
|
||||
connectionId: 'pandora',
|
||||
connectionKind: 'remote',
|
||||
connectionLabel: 'Pandora',
|
||||
profile: 'default',
|
||||
handle: 'hermes-pandora'
|
||||
},
|
||||
{
|
||||
connectionId: 'pandora',
|
||||
connectionKind: 'remote',
|
||||
connectionLabel: 'Pandora',
|
||||
profile: 'scout',
|
||||
handle: 'scout'
|
||||
},
|
||||
{
|
||||
connectionId: 'pandora',
|
||||
connectionKind: 'remote',
|
||||
connectionLabel: 'Pandora',
|
||||
profile: 'omer',
|
||||
handle: 'omer-pandora'
|
||||
},
|
||||
{
|
||||
connectionId: 'local',
|
||||
connectionKind: 'local',
|
||||
connectionLabel: 'This device',
|
||||
profile: 'default',
|
||||
handle: 'hermes'
|
||||
},
|
||||
{
|
||||
connectionId: 'local',
|
||||
connectionKind: 'local',
|
||||
connectionLabel: 'This device',
|
||||
profile: 'omer',
|
||||
handle: 'omer-this-device'
|
||||
}
|
||||
],
|
||||
sources: [
|
||||
{ connectionId: 'pandora', kind: 'remote', label: 'Pandora', reachable: true },
|
||||
@@ -38,9 +68,18 @@ describe('buildRestGroups', () => {
|
||||
it('carries each gateway default as its own square plus named profiles alphabetically', () => {
|
||||
const [local] = buildRestGroups({ activeConnectionId: 'pandora', connections, roster })
|
||||
|
||||
expect(local.defaultAgent).toMatchObject({ connectionId: 'local', profile: 'default', isDefault: true, handle: 'hermes' })
|
||||
expect(local.defaultAgent).toMatchObject({
|
||||
connectionId: 'local',
|
||||
profile: 'default',
|
||||
isDefault: true,
|
||||
handle: 'hermes'
|
||||
})
|
||||
expect(local.named.map(agent => agent.profile)).toEqual(['omer'])
|
||||
expect(local.named[0]).toMatchObject({ connectionLabel: 'This device', handle: 'omer-this-device', isDefault: false })
|
||||
expect(local.named[0]).toMatchObject({
|
||||
connectionLabel: 'This device',
|
||||
handle: 'omer-this-device',
|
||||
isDefault: false
|
||||
})
|
||||
|
||||
const [pandora] = buildRestGroups({ activeConnectionId: 'local', connections, roster })
|
||||
expect(pandora.named.map(agent => agent.profile)).toEqual(['omer', 'scout'])
|
||||
@@ -66,7 +105,12 @@ describe('buildRestGroups', () => {
|
||||
})
|
||||
|
||||
it('skips a registration the roster collapsed into another (same backend, two addresses)', () => {
|
||||
const twin: DesktopRegistryConnection = { id: 'pandora-lan', kind: 'remote', label: 'Pandora LAN', url: 'http://10.0.0.2' } as DesktopRegistryConnection
|
||||
const twin: DesktopRegistryConnection = {
|
||||
id: 'pandora-lan',
|
||||
kind: 'remote',
|
||||
label: 'Pandora LAN',
|
||||
url: 'http://10.0.0.2'
|
||||
} as DesktopRegistryConnection
|
||||
const groups = buildRestGroups({ activeConnectionId: 'local', connections: [...connections, twin], roster })
|
||||
|
||||
expect(groups.map(group => group.connectionId)).toEqual(['pandora', 'vps'])
|
||||
|
||||
@@ -142,9 +142,27 @@ const registry: DesktopConnectionsRegistry = {
|
||||
|
||||
const roster: DesktopAgentRoster = {
|
||||
agents: [
|
||||
{ connectionId: 'pandora', connectionKind: 'remote', connectionLabel: 'Pandora', profile: 'default', handle: 'hermes-pandora' },
|
||||
{ connectionId: 'pandora', connectionKind: 'remote', connectionLabel: 'Pandora', profile: 'scout', handle: 'scout' },
|
||||
{ connectionId: 'local', connectionKind: 'local', connectionLabel: 'This device', profile: 'default', handle: 'hermes' },
|
||||
{
|
||||
connectionId: 'pandora',
|
||||
connectionKind: 'remote',
|
||||
connectionLabel: 'Pandora',
|
||||
profile: 'default',
|
||||
handle: 'hermes-pandora'
|
||||
},
|
||||
{
|
||||
connectionId: 'pandora',
|
||||
connectionKind: 'remote',
|
||||
connectionLabel: 'Pandora',
|
||||
profile: 'scout',
|
||||
handle: 'scout'
|
||||
},
|
||||
{
|
||||
connectionId: 'local',
|
||||
connectionKind: 'local',
|
||||
connectionLabel: 'This device',
|
||||
profile: 'default',
|
||||
handle: 'hermes'
|
||||
},
|
||||
{ connectionId: 'local', connectionKind: 'local', connectionLabel: 'This device', profile: 'omer', handle: 'omer' }
|
||||
],
|
||||
sources: [
|
||||
|
||||
@@ -178,8 +178,7 @@ export function ProfileRail() {
|
||||
const connections = registry?.connections
|
||||
|
||||
const restGroups = useMemo(
|
||||
() =>
|
||||
multipleConnections ? buildRestGroups({ activeConnectionId, connections: connections ?? [], roster }) : [],
|
||||
() => (multipleConnections ? buildRestGroups({ activeConnectionId, connections: connections ?? [], roster }) : []),
|
||||
[activeConnectionId, connections, multipleConnections, roster]
|
||||
)
|
||||
|
||||
@@ -353,42 +352,42 @@ export function ProfileRail() {
|
||||
// from the single-gateway rail; fleet mode only decides where it sits).
|
||||
const activeStrip = (
|
||||
<>
|
||||
{multiProfile && (
|
||||
<DndContext
|
||||
collisionDetection={closestCenter}
|
||||
modifiers={[stepThroughCells]}
|
||||
onDragEnd={handleDragEnd}
|
||||
onDragOver={handleDragOver}
|
||||
onDragStart={handleDragStart}
|
||||
sensors={sensors}
|
||||
>
|
||||
<SortableContext items={named.map(profile => profile.name)} strategy={horizontalListSortingStrategy}>
|
||||
{/* relative → the strip is the dragged square's offsetParent, so the
|
||||
{multiProfile && (
|
||||
<DndContext
|
||||
collisionDetection={closestCenter}
|
||||
modifiers={[stepThroughCells]}
|
||||
onDragEnd={handleDragEnd}
|
||||
onDragOver={handleDragOver}
|
||||
onDragStart={handleDragStart}
|
||||
sensors={sensors}
|
||||
>
|
||||
<SortableContext items={named.map(profile => profile.name)} strategy={horizontalListSortingStrategy}>
|
||||
{/* relative → the strip is the dragged square's offsetParent, so the
|
||||
clamp modifier bounds drags to the occupied cells (not the +). */}
|
||||
<div className="relative flex items-center gap-1">
|
||||
{named.map(profile => (
|
||||
<ProfileSquare
|
||||
active={!isAll && normalizeProfileKey(profile.name) === activeKey}
|
||||
color={resolveProfileColor(profile.name, colors)}
|
||||
key={profile.name}
|
||||
label={profileLabel(profile)}
|
||||
// The legacy per-profile remote override predates the
|
||||
// gateway registry; once the rail shows machines directly
|
||||
// it only confuses, so it is offered on single-gateway
|
||||
// setups only.
|
||||
onConnectRemote={multipleConnections ? undefined : () => openRemoteOverrideDialog(profile.name)}
|
||||
onDelete={() => setPendingDelete(profile)}
|
||||
onEditSoul={() => setPendingSoul(profile.name)}
|
||||
onRecolor={color => setProfileColor(profile.name, color)}
|
||||
onRename={() => setPendingRename(profile)}
|
||||
onSelect={() => selectProfile(profile.name)}
|
||||
remoteHost={remoteOverrides[normalizeProfileKey(profile.name)]?.host ?? null}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</SortableContext>
|
||||
</DndContext>
|
||||
)}
|
||||
<div className="relative flex items-center gap-1">
|
||||
{named.map(profile => (
|
||||
<ProfileSquare
|
||||
active={!isAll && normalizeProfileKey(profile.name) === activeKey}
|
||||
color={resolveProfileColor(profile.name, colors)}
|
||||
key={profile.name}
|
||||
label={profileLabel(profile)}
|
||||
// The legacy per-profile remote override predates the
|
||||
// gateway registry; once the rail shows machines directly
|
||||
// it only confuses, so it is offered on single-gateway
|
||||
// setups only.
|
||||
onConnectRemote={multipleConnections ? undefined : () => openRemoteOverrideDialog(profile.name)}
|
||||
onDelete={() => setPendingDelete(profile)}
|
||||
onEditSoul={() => setPendingSoul(profile.name)}
|
||||
onRecolor={color => setProfileColor(profile.name, color)}
|
||||
onRename={() => setPendingRename(profile)}
|
||||
onSelect={() => selectProfile(profile.name)}
|
||||
remoteHost={remoteOverrides[normalizeProfileKey(profile.name)]?.host ?? null}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</SortableContext>
|
||||
</DndContext>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -397,7 +396,12 @@ export function ProfileRail() {
|
||||
{/* Fleet: every gateway carries its own home square inside its group, so
|
||||
the pinned pill is purely the "all profiles on this gateway" toggle. */}
|
||||
{fleet && (
|
||||
<ProfilePill active={isAll} glyph="layers" label={p.fleet.allOnGateway} onSelect={() => setShowAllProfiles(true)} />
|
||||
<ProfilePill
|
||||
active={isAll}
|
||||
glyph="layers"
|
||||
label={p.fleet.allOnGateway}
|
||||
onSelect={() => setShowAllProfiles(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* One button toggles default ↔ all: home face when scoped to a profile,
|
||||
@@ -452,53 +456,51 @@ export function ProfileRail() {
|
||||
{/* The active gateway's squares. In fleet mode they sit in the
|
||||
gateway's registry slot with a home square at their head, so the
|
||||
strip keeps one shape whichever gateway is active. */}
|
||||
{fleet ? (
|
||||
fleetSequence.map((entry, index) =>
|
||||
entry.kind === 'active' ? (
|
||||
<Fragment key="active">
|
||||
<FleetDivider
|
||||
connection={activeConnection}
|
||||
{fleet
|
||||
? fleetSequence.map((entry, index) =>
|
||||
entry.kind === 'active' ? (
|
||||
<Fragment key="active">
|
||||
<FleetDivider
|
||||
connection={activeConnection}
|
||||
first={index === 0}
|
||||
label={activeConnection ? p.fleet.gateway(activeConnection.label) : null}
|
||||
reachable
|
||||
/>
|
||||
<span
|
||||
aria-label={activeConnection ? p.fleet.gateway(activeConnection.label) : undefined}
|
||||
className="flex shrink-0 items-center gap-1"
|
||||
data-active="true"
|
||||
data-connection-id={activeConnection?.id}
|
||||
data-slot="profile-rail-gateway"
|
||||
role="group"
|
||||
>
|
||||
{defaultProfile && (
|
||||
<ProfilePill
|
||||
active={onDefault}
|
||||
glyph="home"
|
||||
label={profileLabel(defaultProfile)}
|
||||
onSelect={() => selectProfile(defaultProfile.name)}
|
||||
/>
|
||||
)}
|
||||
{activeStrip}
|
||||
</span>
|
||||
</Fragment>
|
||||
) : (
|
||||
<FleetRestGroup
|
||||
colors={colors}
|
||||
first={index === 0}
|
||||
label={activeConnection ? p.fleet.gateway(activeConnection.label) : null}
|
||||
reachable
|
||||
group={entry.group}
|
||||
key={entry.group.connectionId}
|
||||
onDelete={setPendingRestDelete}
|
||||
onEditSoul={setPendingRestSoul}
|
||||
onRecolor={(agent, color) => setProfileColor(agent.profile, color)}
|
||||
onRename={setPendingRestRename}
|
||||
onSelect={switchToRest}
|
||||
pendingRoute={pendingRoute}
|
||||
/>
|
||||
<span
|
||||
aria-label={activeConnection ? p.fleet.gateway(activeConnection.label) : undefined}
|
||||
className="flex shrink-0 items-center gap-1"
|
||||
data-active="true"
|
||||
data-connection-id={activeConnection?.id}
|
||||
data-slot="profile-rail-gateway"
|
||||
role="group"
|
||||
>
|
||||
{defaultProfile && (
|
||||
<ProfilePill
|
||||
active={onDefault}
|
||||
glyph="home"
|
||||
label={profileLabel(defaultProfile)}
|
||||
onSelect={() => selectProfile(defaultProfile.name)}
|
||||
/>
|
||||
)}
|
||||
{activeStrip}
|
||||
</span>
|
||||
</Fragment>
|
||||
) : (
|
||||
<FleetRestGroup
|
||||
colors={colors}
|
||||
first={index === 0}
|
||||
group={entry.group}
|
||||
key={entry.group.connectionId}
|
||||
onDelete={setPendingRestDelete}
|
||||
onEditSoul={setPendingRestSoul}
|
||||
onRecolor={(agent, color) => setProfileColor(agent.profile, color)}
|
||||
onRename={setPendingRestRename}
|
||||
onSelect={switchToRest}
|
||||
pendingRoute={pendingRoute}
|
||||
/>
|
||||
)
|
||||
)
|
||||
)
|
||||
) : (
|
||||
activeStrip
|
||||
)}
|
||||
: activeStrip}
|
||||
|
||||
<AddProfileButton label={p.newProfile} onClick={() => setCreateOpen(true)} />
|
||||
<ImportProfileButton label={p.importProfile} />
|
||||
@@ -850,7 +852,16 @@ interface ProfilePillProps {
|
||||
connectionId?: string
|
||||
}
|
||||
|
||||
function ProfilePill({ active, connectionId, glyph, label, muted = false, onSelect, pending = false, slot }: ProfilePillProps) {
|
||||
function ProfilePill({
|
||||
active,
|
||||
connectionId,
|
||||
glyph,
|
||||
label,
|
||||
muted = false,
|
||||
onSelect,
|
||||
pending = false,
|
||||
slot
|
||||
}: ProfilePillProps) {
|
||||
return (
|
||||
<Tip label={label}>
|
||||
<Button
|
||||
|
||||
@@ -661,9 +661,7 @@ describe('typing-aware sessions.changed deferral', () => {
|
||||
updateSessionState: vi.fn(
|
||||
(
|
||||
_sessionId: string,
|
||||
updater: (state: ReturnType<typeof createClientSessionState>) => ReturnType<
|
||||
typeof createClientSessionState
|
||||
>
|
||||
updater: (state: ReturnType<typeof createClientSessionState>) => ReturnType<typeof createClientSessionState>
|
||||
) => updater(createClientSessionState(ACTIVE_STORED_ID))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -724,6 +724,7 @@ export function useBackgroundSync({
|
||||
}
|
||||
|
||||
run()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -327,9 +327,9 @@ describe('useModelControls', () => {
|
||||
|
||||
render(<Harness onReady={value => (controls = value)} requestGateway={requestGateway} />)
|
||||
|
||||
await expect(
|
||||
controls.selectModel({ model: 'muse-spark-1.2-contributor', provider: 'opencode-go' })
|
||||
).resolves.toBe(false)
|
||||
await expect(controls.selectModel({ model: 'muse-spark-1.2-contributor', provider: 'opencode-go' })).resolves.toBe(
|
||||
false
|
||||
)
|
||||
|
||||
expect($currentModel.get()).toBe('gpt-5.6-sol')
|
||||
expect($currentProvider.get()).toBe('openai-codex')
|
||||
|
||||
@@ -14,6 +14,7 @@ async function utilitiesFor(css: string): Promise<string> {
|
||||
const out = build(CANDIDATES)
|
||||
const start = out.indexOf('@layer utilities {')
|
||||
expect(start).toBeGreaterThanOrEqual(0)
|
||||
|
||||
return out.slice(start)
|
||||
}
|
||||
|
||||
|
||||
@@ -235,6 +235,7 @@ function confirmModelWarning(message: string): Promise<boolean> {
|
||||
|
||||
return new Promise(resolve => {
|
||||
let settled = false
|
||||
|
||||
const finish = (value: boolean) => {
|
||||
if (settled) {
|
||||
return
|
||||
|
||||
@@ -345,9 +345,7 @@ describe('closeAllOpenSessionTiles persists Bot Mode Close All (#94137)', () =>
|
||||
workspaceMode: 'bots',
|
||||
workspaceOwnerKey: 'bot:b'
|
||||
})
|
||||
$layoutTree.set(
|
||||
group(['workspace', tilePane('chat-a'), tilePane('chat-b')], { active: 'workspace', id: 'main' })
|
||||
)
|
||||
$layoutTree.set(group(['workspace', tilePane('chat-a'), tilePane('chat-b')], { active: 'workspace', id: 'main' }))
|
||||
|
||||
closeAllOpenSessionTiles('workspace')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user