fix(plugin): verify event hook compatibility with v1.4.0
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -3,6 +3,7 @@ const { afterEach, describe, expect, mock, test, afterAll } = require("bun:test"
|
||||
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs"
|
||||
import { join } from "node:path"
|
||||
import { tmpdir } from "node:os"
|
||||
import { PART_STORAGE } from "../../shared"
|
||||
|
||||
const testDirs: string[] = []
|
||||
const TEST_STORAGE_ROOT = join(tmpdir(), `atlas-session-last-agent-${Date.now()}`)
|
||||
@@ -64,4 +65,36 @@ describe("getLastAgentFromSession JSON backend", () => {
|
||||
// then
|
||||
expect(result).toBe("atlas")
|
||||
})
|
||||
|
||||
test("skips JSON messages whose part storage contains a compaction marker", async () => {
|
||||
// given
|
||||
const sessionID = "ses_json_compaction_marker"
|
||||
const messageDir = createTempMessageDir(sessionID)
|
||||
const compactionMessageID = "msg_test_atlas_compaction_marker"
|
||||
const partDir = join(PART_STORAGE, compactionMessageID)
|
||||
testDirs.push(partDir)
|
||||
writeFileSync(join(messageDir, "msg_0001.json"), JSON.stringify({
|
||||
id: compactionMessageID,
|
||||
agent: "atlas",
|
||||
time: { created: 200 },
|
||||
}), "utf-8")
|
||||
mkdirSync(partDir, { recursive: true })
|
||||
writeFileSync(join(partDir, "prt_0001.json"), JSON.stringify({
|
||||
type: "compaction",
|
||||
}), "utf-8")
|
||||
|
||||
writeFileSync(join(messageDir, "msg_0002.json"), JSON.stringify({
|
||||
id: "msg_0002",
|
||||
agent: "sisyphus-junior",
|
||||
time: { created: 100 },
|
||||
}), "utf-8")
|
||||
|
||||
const { getLastAgentFromSession } = await import("./session-last-agent")
|
||||
|
||||
// when
|
||||
const result = await getLastAgentFromSession(sessionID)
|
||||
|
||||
// then
|
||||
expect(result).toBe("sisyphus-junior")
|
||||
})
|
||||
})
|
||||
|
||||
@@ -52,6 +52,30 @@ describe("getLastAgentFromSession SQLite backend ordering", () => {
|
||||
expect(result).toBe("sisyphus-junior")
|
||||
})
|
||||
|
||||
test("skips compaction marker user messages that retain the original agent", async () => {
|
||||
// given
|
||||
const client = {
|
||||
session: {
|
||||
messages: async () => ({
|
||||
data: [
|
||||
{ id: "msg_real", info: { agent: "sisyphus", time: { created: 100 } } },
|
||||
{
|
||||
id: "msg_compaction",
|
||||
info: { agent: "atlas", time: { created: 200 } },
|
||||
parts: [{ type: "compaction" }],
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
// when
|
||||
const result = await getLastAgentFromSession("ses_sqlite_compaction_marker", client as never)
|
||||
|
||||
// then
|
||||
expect(result).toBe("sisyphus")
|
||||
})
|
||||
|
||||
test("returns null instead of throwing when SQLite message lookup fails", async () => {
|
||||
// given
|
||||
const client = {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { readFileSync, readdirSync } from "node:fs"
|
||||
import { join } from "node:path"
|
||||
|
||||
import { getMessageDir, isSqliteBackend, normalizeSDKResponse } from "../../shared"
|
||||
import { hasCompactionPartInStorage, isCompactionMessage } from "../../shared/compaction-marker"
|
||||
|
||||
type SessionMessagesClient = {
|
||||
session: {
|
||||
@@ -9,10 +10,6 @@ type SessionMessagesClient = {
|
||||
}
|
||||
}
|
||||
|
||||
function isCompactionAgent(agent: unknown): boolean {
|
||||
return typeof agent === "string" && agent.toLowerCase() === "compaction"
|
||||
}
|
||||
|
||||
function getLastAgentFromMessageDir(messageDir: string): string | null {
|
||||
try {
|
||||
const messages = readdirSync(messageDir)
|
||||
@@ -20,9 +17,10 @@ function getLastAgentFromMessageDir(messageDir: string): string | null {
|
||||
.map((fileName) => {
|
||||
try {
|
||||
const content = readFileSync(join(messageDir, fileName), "utf-8")
|
||||
const parsed = JSON.parse(content) as { agent?: unknown; time?: { created?: unknown } }
|
||||
const parsed = JSON.parse(content) as { id?: string; agent?: unknown; time?: { created?: unknown } }
|
||||
return {
|
||||
fileName,
|
||||
id: parsed.id,
|
||||
agent: parsed.agent,
|
||||
createdAt: typeof parsed.time?.created === "number" ? parsed.time.created : Number.NEGATIVE_INFINITY,
|
||||
}
|
||||
@@ -30,11 +28,16 @@ function getLastAgentFromMessageDir(messageDir: string): string | null {
|
||||
return null
|
||||
}
|
||||
})
|
||||
.filter((message): message is { fileName: string; agent: unknown; createdAt: number } => message !== null)
|
||||
.sort((left, right) => right.createdAt - left.createdAt || right.fileName.localeCompare(left.fileName))
|
||||
.filter((message): message is { fileName: string; id: string | undefined; agent: unknown; createdAt: number } => message !== null)
|
||||
.sort((left, right) => (right?.createdAt ?? 0) - (left?.createdAt ?? 0) || (right?.fileName ?? "").localeCompare(left?.fileName ?? ""))
|
||||
|
||||
for (const message of messages) {
|
||||
if (typeof message.agent === "string" && !isCompactionAgent(message.agent)) {
|
||||
if (!message) continue
|
||||
if (isCompactionMessage({ agent: message.agent }) || hasCompactionPartInStorage(message?.id)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (typeof message.agent === "string") {
|
||||
return message.agent.toLowerCase()
|
||||
}
|
||||
}
|
||||
@@ -52,7 +55,11 @@ export async function getLastAgentFromSession(
|
||||
if (isSqliteBackend() && client) {
|
||||
try {
|
||||
const response = await client.session.messages({ path: { id: sessionID } })
|
||||
const messages = normalizeSDKResponse(response, [] as Array<{ id?: string; info?: { agent?: string; time?: { created?: number } } }>, {
|
||||
const messages = normalizeSDKResponse(response, [] as Array<{
|
||||
id?: string
|
||||
info?: { agent?: string; time?: { created?: number } }
|
||||
parts?: Array<{ type?: string }>
|
||||
}>, {
|
||||
preferResponseOnMissingData: true,
|
||||
}).sort((left, right) => {
|
||||
const leftTime = (left as { info?: { time?: { created?: number } } }).info?.time?.created ?? Number.NEGATIVE_INFINITY
|
||||
@@ -67,8 +74,12 @@ export async function getLastAgentFromSession(
|
||||
})
|
||||
|
||||
for (const message of messages) {
|
||||
if (isCompactionMessage(message)) {
|
||||
continue
|
||||
}
|
||||
|
||||
const agent = message.info?.agent
|
||||
if (typeof agent === "string" && !isCompactionAgent(agent)) {
|
||||
if (typeof agent === "string") {
|
||||
return agent.toLowerCase()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user