fix(tui): notify for form requests
This commit is contained in:
parent
386b2661b2
commit
ba7b009a37
2 changed files with 28 additions and 27 deletions
|
|
@ -29,21 +29,21 @@ function sessionErrorMessage(error: SessionError) {
|
||||||
const tui: TuiPlugin = async (api) => {
|
const tui: TuiPlugin = async (api) => {
|
||||||
const active = new Set<string>()
|
const active = new Set<string>()
|
||||||
const errored = new Set<string>()
|
const errored = new Set<string>()
|
||||||
const questions = new Set<string>()
|
const forms = new Set<string>()
|
||||||
const permissions = new Set<string>()
|
const permissions = new Set<string>()
|
||||||
|
|
||||||
api.event.on("question.asked", (event) => {
|
api.event.on("form.created", (event) => {
|
||||||
if (questions.has(event.data.id)) return
|
if (forms.has(event.data.form.id)) return
|
||||||
questions.add(event.data.id)
|
forms.add(event.data.form.id)
|
||||||
notify(api, event.data.sessionID, "Question needs input", "question")
|
notify(api, event.data.form.sessionID, "Input needs response", "question")
|
||||||
})
|
})
|
||||||
|
|
||||||
api.event.on("question.replied", (event) => {
|
api.event.on("form.replied", (event) => {
|
||||||
questions.delete(event.data.requestID)
|
forms.delete(event.data.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
api.event.on("question.rejected", (event) => {
|
api.event.on("form.cancelled", (event) => {
|
||||||
questions.delete(event.data.requestID)
|
forms.delete(event.data.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
api.event.on("permission.asked", (event) => {
|
api.event.on("permission.asked", (event) => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, expect, test } from "bun:test"
|
import { describe, expect, test } from "bun:test"
|
||||||
import Notifications from "../../../../src/feature-plugins/system/notifications"
|
import Notifications from "../../../../src/feature-plugins/system/notifications"
|
||||||
import type { PermissionRequest, QuestionRequest, Session, V2Event } from "@opencode-ai/sdk/v2"
|
import type { PermissionRequest, Session, V2Event } from "@opencode-ai/sdk/v2"
|
||||||
import type { TuiAttentionNotifyInput } from "@opencode-ai/plugin/tui"
|
import type { TuiAttentionNotifyInput } from "@opencode-ai/plugin/tui"
|
||||||
import { createTuiPluginApi } from "../../../fixture/tui-plugin"
|
import { createTuiPluginApi } from "../../../fixture/tui-plugin"
|
||||||
|
|
||||||
|
|
@ -67,11 +67,12 @@ async function setup() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function question(id: string, sessionID = "session"): QuestionRequest {
|
function form(id: string, sessionID = "session"): Extract<V2Event, { type: "form.created" }>["data"]["form"] {
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
sessionID,
|
sessionID,
|
||||||
questions: [],
|
mode: "form",
|
||||||
|
fields: [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,9 +129,9 @@ function stepFailed(id: string, sessionID = "session"): V2Event {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const questionNotification: TuiAttentionNotifyInput = {
|
const formNotification: TuiAttentionNotifyInput = {
|
||||||
title: "Demo session",
|
title: "Demo session",
|
||||||
message: "Question needs input",
|
message: "Input needs response",
|
||||||
notification: { when: "blurred" },
|
notification: { when: "blurred" },
|
||||||
sound: { name: "question", when: "always" },
|
sound: { name: "question", when: "always" },
|
||||||
}
|
}
|
||||||
|
|
@ -143,26 +144,26 @@ const permissionNotification: TuiAttentionNotifyInput = {
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("internal notifications TUI plugin", () => {
|
describe("internal notifications TUI plugin", () => {
|
||||||
test("notifies for question and permission requests with blurred notifications and always-on sounds", async () => {
|
test("notifies for form and permission requests with blurred notifications and always-on sounds", async () => {
|
||||||
const harness = await setup()
|
const harness = await setup()
|
||||||
|
|
||||||
harness.emit({ id: "event-1", type: "question.asked", data: question("question-1") })
|
harness.emit({ id: "event-1", type: "form.created", data: { form: form("form-1") } })
|
||||||
harness.emit({ id: "event-2", type: "permission.asked", data: permission("permission-1") })
|
harness.emit({ id: "event-2", type: "permission.asked", data: permission("permission-1") })
|
||||||
|
|
||||||
expect(harness.notifications).toEqual([questionNotification, permissionNotification])
|
expect(harness.notifications).toEqual([formNotification, permissionNotification])
|
||||||
})
|
})
|
||||||
|
|
||||||
test("dedupes pending questions and permissions until they are resolved", async () => {
|
test("dedupes pending forms and permissions until they are resolved", async () => {
|
||||||
const harness = await setup()
|
const harness = await setup()
|
||||||
|
|
||||||
harness.emit({ id: "event-1", type: "question.asked", data: question("question-1") })
|
harness.emit({ id: "event-1", type: "form.created", data: { form: form("form-1") } })
|
||||||
harness.emit({ id: "event-2", type: "question.asked", data: question("question-1") })
|
harness.emit({ id: "event-2", type: "form.created", data: { form: form("form-1") } })
|
||||||
harness.emit({
|
harness.emit({
|
||||||
id: "event-3",
|
id: "event-3",
|
||||||
type: "question.replied",
|
type: "form.replied",
|
||||||
data: { sessionID: "session", requestID: "question-1", answers: [] },
|
data: { sessionID: "session", id: "form-1", answer: {} },
|
||||||
})
|
})
|
||||||
harness.emit({ id: "event-4", type: "question.asked", data: question("question-1") })
|
harness.emit({ id: "event-4", type: "form.created", data: { form: form("form-1") } })
|
||||||
|
|
||||||
harness.emit({ id: "event-5", type: "permission.asked", data: permission("permission-1") })
|
harness.emit({ id: "event-5", type: "permission.asked", data: permission("permission-1") })
|
||||||
harness.emit({ id: "event-6", type: "permission.asked", data: permission("permission-1") })
|
harness.emit({ id: "event-6", type: "permission.asked", data: permission("permission-1") })
|
||||||
|
|
@ -174,8 +175,8 @@ describe("internal notifications TUI plugin", () => {
|
||||||
harness.emit({ id: "event-8", type: "permission.asked", data: permission("permission-1") })
|
harness.emit({ id: "event-8", type: "permission.asked", data: permission("permission-1") })
|
||||||
|
|
||||||
expect(harness.notifications).toEqual([
|
expect(harness.notifications).toEqual([
|
||||||
questionNotification,
|
formNotification,
|
||||||
questionNotification,
|
formNotification,
|
||||||
permissionNotification,
|
permissionNotification,
|
||||||
permissionNotification,
|
permissionNotification,
|
||||||
])
|
])
|
||||||
|
|
@ -201,14 +202,14 @@ describe("internal notifications TUI plugin", () => {
|
||||||
test("uses sound-only notifications and subagent_done sound for subagent sessions", async () => {
|
test("uses sound-only notifications and subagent_done sound for subagent sessions", async () => {
|
||||||
const harness = await setup()
|
const harness = await setup()
|
||||||
|
|
||||||
harness.emit({ id: "event-1", type: "question.asked", data: question("question-1", "subagent") })
|
harness.emit({ id: "event-1", type: "form.created", data: { form: form("form-1", "subagent") } })
|
||||||
harness.emit(stepStarted("event-2", "subagent"))
|
harness.emit(stepStarted("event-2", "subagent"))
|
||||||
harness.emit(stepEnded("event-3", "subagent"))
|
harness.emit(stepEnded("event-3", "subagent"))
|
||||||
|
|
||||||
expect(harness.notifications).toEqual([
|
expect(harness.notifications).toEqual([
|
||||||
{
|
{
|
||||||
title: "Subagent session",
|
title: "Subagent session",
|
||||||
message: "Question needs input",
|
message: "Input needs response",
|
||||||
notification: false,
|
notification: false,
|
||||||
sound: { name: "question", when: "always" },
|
sound: { name: "question", when: "always" },
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue