Compare commits

...

3 Commits

Author SHA1 Message Date
Dax Raad 939c2c2411 fix(core): list default agent first 2026-08-13 04:56:23 +00:00
Kit Langton 56973e0ca4 fix(core): reject inherited workspace providers (#42227) 2026-08-12 22:55:32 -04:00
Kit Langton c253d4d311 fix(tui): highlight queued prompts on hover (#42219) 2026-08-12 22:32:30 -04:00
5 changed files with 41 additions and 3 deletions
+4 -1
View File
@@ -122,7 +122,10 @@ const layer = Layer.effect(
return { id: info?.id ?? defaultID, info }
}),
list: Effect.fn("Agent.list")(function* () {
return Array.fromIterable(state.get().agents.values())
const agents = Array.fromIterable(state.get().agents.values())
const selected = selectedDefault()
if (!selected) return agents
return [selected, ...agents.filter((agent) => agent.id !== selected.id)]
}),
})
}),
+1 -1
View File
@@ -55,7 +55,7 @@ export class RegistryService extends Context.Service<RegistryService, Registry>(
export const registry = (drivers: Readonly<Record<string, Interface>>): Registry => ({
get: (provider) => {
const driver = drivers[provider]
const driver = Object.hasOwn(drivers, provider) ? drivers[provider] : undefined
return driver ? Effect.succeed(driver) : Effect.fail(new ProviderNotFound({ provider }))
},
})
+20
View File
@@ -68,6 +68,26 @@ describe("Agent", () => {
}),
)
it.effect("lists the selected default agent first", () =>
Effect.gen(function* () {
const agent = yield* Agent.Service
yield* agent.transform((editor) => {
editor.update(Agent.ID.make("build"), (info) => {
info.mode = "primary"
})
editor.update(Agent.ID.make("reviewer"), (info) => {
info.mode = "primary"
})
editor.update(Agent.ID.make("explore"), (info) => {
info.mode = "subagent"
})
editor.default(Agent.ID.make("reviewer"))
})
expect((yield* agent.list()).map((info) => String(info.id))).toEqual(["reviewer", "build", "explore"])
}),
)
it.effect("rebuilds state when a transform is replaced", () =>
Effect.gen(function* () {
const agent = yield* Agent.Service
+12
View File
@@ -48,6 +48,18 @@ beforeEach(() => {
failConnect = false
})
it.effect("rejects unregistered workspace providers", () =>
Effect.gen(function* () {
const registry = WorkspaceDriver.registry({ fake: driver })
for (const provider of ["missing", "constructor", "toString", "__proto__"]) {
expect(yield* registry.get(provider).pipe(Effect.flip)).toEqual(
new WorkspaceDriver.ProviderNotFound({ provider }),
)
}
}),
)
it.effect("persists the workspace lifecycle and reconnects after idle suspension", () =>
Effect.gen(function* () {
const workspace = yield* Workspace.Service
+4 -1
View File
@@ -2089,6 +2089,7 @@ function UserMessage(props: { message: SessionMessageUser }) {
function QueuedPromptDock(props: { prompts: { id: string; text: string }[]; onOpen: () => void }) {
const theme = useTheme("elevated")
const [hover, setHover] = createSignal(false)
const next = createMemo(() => props.prompts[0]?.text.replaceAll("\n", " "))
return (
@@ -2096,6 +2097,8 @@ function QueuedPromptDock(props: { prompts: { id: string; text: string }[]; onOp
border={["left"]}
borderColor={theme.border.default}
customBorderChars={SplitBorder.customBorderChars}
onMouseOver={() => setHover(true)}
onMouseOut={() => setHover(false)}
onMouseUp={props.onOpen}
>
<box
@@ -2104,7 +2107,7 @@ function QueuedPromptDock(props: { prompts: { id: string; text: string }[]; onOp
paddingBottom={1}
paddingLeft={2}
paddingRight={1}
backgroundColor={theme.background.default}
backgroundColor={hover() ? theme.raise(theme.background.default) : theme.background.default}
flexDirection="row"
>
<text fg={theme.text.subdued} wrapMode="none" truncate flexGrow={1} flexShrink={1} minWidth={0}>