mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-14 12:10:45 +03:00
refactor(client): derive session inputs from pending items (#46926)
This commit is contained in:
committed by
GitHub
Unverified
parent
4beaffbda9
commit
5e38101fba
@@ -107,7 +107,6 @@ type Store = {
|
||||
messageCursor: Record<string, string | undefined>
|
||||
messageLoading: Record<string, boolean>
|
||||
pending: Record<string, SessionInboxInfo[]>
|
||||
input: Record<string, string[]>
|
||||
permission: Record<string, PermissionRequest[]>
|
||||
// Pending forms keyed by owner: a session ID or the temporary "global" elicitation sentinel.
|
||||
form: Record<string, FormWithLocation[]>
|
||||
@@ -198,7 +197,6 @@ export function createData(config: CreateDataInput) {
|
||||
messageCursor: {},
|
||||
messageLoading: {},
|
||||
pending: {},
|
||||
input: {},
|
||||
permission: {},
|
||||
form: {},
|
||||
},
|
||||
@@ -231,13 +229,6 @@ export function createData(config: CreateDataInput) {
|
||||
sessionID,
|
||||
(store.session.pending[sessionID] ?? []).filter((item) => item.id !== inboxID),
|
||||
)
|
||||
if (store.session.input[sessionID]?.includes(inboxID))
|
||||
setStore(
|
||||
"session",
|
||||
"input",
|
||||
sessionID,
|
||||
(store.session.input[sessionID] ?? []).filter((id) => id !== inboxID),
|
||||
)
|
||||
}
|
||||
|
||||
function removePermission(sessionID: string, requestID: string) {
|
||||
@@ -335,8 +326,8 @@ export function createData(config: CreateDataInput) {
|
||||
return request
|
||||
}
|
||||
|
||||
// Upsert an admitted inbox item into pending, input, and (for user and
|
||||
// synthetic items) the visible transcript. Used by the inbox.enqueued
|
||||
// Upsert an admitted inbox item into pending and (for user and synthetic
|
||||
// items) the visible transcript. Used by the inbox.enqueued
|
||||
// handler and by optimistic admission; the upsert is what reconciles
|
||||
// the durable echo with an optimistic placeholder — the durable payload and
|
||||
// times replace the client's guess.
|
||||
@@ -351,8 +342,6 @@ export function createData(config: CreateDataInput) {
|
||||
at < 0 ? [...pending, item] : pending.map((entry, index) => (index === at ? item : entry)),
|
||||
)
|
||||
if (item.type === "compaction") return
|
||||
const input = store.session.input[item.sessionID] ?? []
|
||||
if (!input.includes(item.id)) setStore("session", "input", item.sessionID, [...input, item.id])
|
||||
materializeInboxMessage(item)
|
||||
})
|
||||
}
|
||||
@@ -524,12 +513,8 @@ export function createData(config: CreateDataInput) {
|
||||
delete draft.messageCursor[sessionID]
|
||||
delete draft.messageLoading[sessionID]
|
||||
delete draft.pending[sessionID]
|
||||
delete draft.input[sessionID]
|
||||
if (messages.length) draft.message[sessionID] = messages
|
||||
if (pending.length) {
|
||||
draft.pending[sessionID] = pending
|
||||
draft.input[sessionID] = pending.filter((item) => item.type !== "compaction").map((item) => item.id)
|
||||
}
|
||||
if (pending.length) draft.pending[sessionID] = pending
|
||||
}),
|
||||
)
|
||||
}
|
||||
@@ -553,7 +538,6 @@ export function createData(config: CreateDataInput) {
|
||||
delete draft.messageCursor[sessionID]
|
||||
delete draft.messageLoading[sessionID]
|
||||
delete draft.pending[sessionID]
|
||||
delete draft.input[sessionID]
|
||||
delete draft.permission[sessionID]
|
||||
delete draft.form[sessionID]
|
||||
for (const [rootID, family] of Object.entries(draft.family)) {
|
||||
@@ -714,7 +698,7 @@ export function createData(config: CreateDataInput) {
|
||||
return
|
||||
}
|
||||
case "session.inbox.delivered": {
|
||||
const admitted = store.session.input[event.data.sessionID]?.includes(event.data.inboxID) ?? false
|
||||
const admitted = result.session.input.has(event.data.sessionID, event.data.inboxID)
|
||||
removePending(event.data.sessionID, event.data.inboxID)
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const position = index.get(event.data.inboxID)
|
||||
@@ -1027,11 +1011,12 @@ export function createData(config: CreateDataInput) {
|
||||
if (store.session.info[event.data.sessionID]) {
|
||||
setStore("session", "info", event.data.sessionID, "revert", undefined)
|
||||
}
|
||||
// The projector also deletes inbox items enqueued at or after the boundary without a cancel event.
|
||||
setStore(
|
||||
"session",
|
||||
"input",
|
||||
"pending",
|
||||
event.data.sessionID,
|
||||
(store.session.input[event.data.sessionID] ?? []).filter((id) => id < event.data.to),
|
||||
(store.session.pending[event.data.sessionID] ?? []).filter((item) => item.id < event.data.to),
|
||||
)
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const position = draft.findIndex((item) => item.id >= event.data.to)
|
||||
@@ -1308,12 +1293,17 @@ export function createData(config: CreateDataInput) {
|
||||
status(sessionID: string) {
|
||||
return store.session.active[sessionID] ?? "idle"
|
||||
},
|
||||
// Inputs are the pending user and synthetic items; compactions are control items.
|
||||
input: {
|
||||
list(sessionID: string) {
|
||||
return store.session.input[sessionID] ?? []
|
||||
return (store.session.pending[sessionID] ?? []).flatMap((item) =>
|
||||
item.type === "compaction" ? [] : [item.id],
|
||||
)
|
||||
},
|
||||
has(sessionID: string, inboxID: string) {
|
||||
return store.session.input[sessionID]?.includes(inboxID) ?? false
|
||||
return (
|
||||
store.session.pending[sessionID]?.some((item) => item.id === inboxID && item.type !== "compaction") ?? false
|
||||
)
|
||||
},
|
||||
},
|
||||
pending: {
|
||||
@@ -1337,12 +1327,6 @@ export function createData(config: CreateDataInput) {
|
||||
const merged = inflight.length === 0 ? pending : [...pending, ...inflight]
|
||||
batch(() => {
|
||||
setStore("session", "pending", sessionID, reconcile(merged))
|
||||
setStore(
|
||||
"session",
|
||||
"input",
|
||||
sessionID,
|
||||
reconcile(merged.filter((item) => item.type !== "compaction").map((item) => item.id)),
|
||||
)
|
||||
merged.forEach(materializeInboxMessage)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1129,6 +1129,10 @@ test("removes committed revert messages from local state", async () => {
|
||||
expect(data.session.message.list(sessionID).map((message) => message.id)).toEqual(["msg_001"])
|
||||
expect(data.session.message.get(sessionID, "msg_002")).toBeUndefined()
|
||||
expect(data.session.message.get(sessionID, "msg_003")).toBeUndefined()
|
||||
// The projector also drops inbox items enqueued at or after the boundary, without a cancel event.
|
||||
expect(data.session.pending.list(sessionID).map((item) => item.id)).toEqual(["msg_001"])
|
||||
expect(data.session.input.list(sessionID)).toEqual(["msg_001"])
|
||||
expect(data.session.input.has(sessionID, "msg_002")).toBe(false)
|
||||
} finally {
|
||||
app.renderer.destroy()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user