fix(plugin): normalize event session ids
Handle OpenCode session events that carry the session ID under properties.info.id or properties.info.sessionID so background tasks and continuation hooks do not miss idle/error/delete events. Add regression coverage for nested session.idle events completing background tasks and waking continuation hooks.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
|
||||
import { resolveMessageEventSessionID, resolveSessionEventID } from "./event-session-id"
|
||||
|
||||
describe("event session id resolvers", () => {
|
||||
test("#given legacy message.part.updated properties #when resolving message session id #then part.sessionID is used", () => {
|
||||
const sessionID = resolveMessageEventSessionID({
|
||||
part: {
|
||||
id: "part-1",
|
||||
messageID: "msg-1",
|
||||
sessionID: "ses-part-only",
|
||||
type: "text",
|
||||
text: "working",
|
||||
},
|
||||
})
|
||||
|
||||
expect(sessionID).toBe("ses-part-only")
|
||||
})
|
||||
|
||||
test("#given message.updated info id #when resolving message session id #then message id is not mistaken for session id", () => {
|
||||
const sessionID = resolveMessageEventSessionID({
|
||||
info: {
|
||||
id: "msg-not-session",
|
||||
role: "assistant",
|
||||
},
|
||||
})
|
||||
|
||||
expect(sessionID).toBeUndefined()
|
||||
})
|
||||
|
||||
test("#given legacy session lifecycle properties #when resolving session id #then info.id is used", () => {
|
||||
const sessionID = resolveSessionEventID({
|
||||
info: {
|
||||
id: "ses-legacy-info-id",
|
||||
},
|
||||
})
|
||||
|
||||
expect(sessionID).toBe("ses-legacy-info-id")
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,23 @@
|
||||
import { isRecord } from "./record-type-guard"
|
||||
|
||||
function getStringField(record: Record<string, unknown> | undefined, key: string): string | undefined {
|
||||
const value = record?.[key]
|
||||
return typeof value === "string" && value.length > 0 ? value : undefined
|
||||
}
|
||||
|
||||
export function resolveSessionEventID(properties: unknown): string | undefined {
|
||||
const props = isRecord(properties) ? properties : undefined
|
||||
const info = isRecord(props?.info) ? props.info : undefined
|
||||
return getStringField(props, "sessionID")
|
||||
?? getStringField(info, "sessionID")
|
||||
?? getStringField(info, "id")
|
||||
}
|
||||
|
||||
export function resolveMessageEventSessionID(properties: unknown): string | undefined {
|
||||
const props = isRecord(properties) ? properties : undefined
|
||||
const info = isRecord(props?.info) ? props.info : undefined
|
||||
const part = isRecord(props?.part) ? props.part : undefined
|
||||
return getStringField(props, "sessionID")
|
||||
?? getStringField(info, "sessionID")
|
||||
?? getStringField(part, "sessionID")
|
||||
}
|
||||
@@ -54,6 +54,7 @@ export * from "./fallback-model-availability"
|
||||
export * from "./connected-providers-cache"
|
||||
export * from "./context-limit-resolver"
|
||||
export * from "./session-utils"
|
||||
export * from "./event-session-id"
|
||||
export * from "./tmux"
|
||||
export * from "./model-suggestion-retry"
|
||||
export * from "./opencode-server-auth"
|
||||
|
||||
Reference in New Issue
Block a user