fix(hook-message-injector): use monotonic counter for deterministic message/part IDs

This commit is contained in:
YeonGyu-Kim 2026-02-28 13:30:14 +09:00
parent cc6ab1addc
commit 6e9f27350d
2 changed files with 41 additions and 8 deletions

View File

@ -4,6 +4,8 @@ import {
findFirstMessageWithAgent, findFirstMessageWithAgent,
findNearestMessageWithFieldsFromSDK, findNearestMessageWithFieldsFromSDK,
findFirstMessageWithAgentFromSDK, findFirstMessageWithAgentFromSDK,
generateMessageId,
generatePartId,
injectHookMessage, injectHookMessage,
} from "./injector" } from "./injector"
import { isSqliteBackend, resetSqliteBackendCache } from "../../shared/opencode-storage-detection" import { isSqliteBackend, resetSqliteBackendCache } from "../../shared/opencode-storage-detection"
@ -192,6 +194,38 @@ describe("findFirstMessageWithAgentFromSDK", () => {
}) })
}) })
describe("generateMessageId", () => {
it("returns deterministic sequential IDs with fixed format", () => {
// given
const format = /^msg_\d{12}$/
// when
const firstId = generateMessageId()
const secondId = generateMessageId()
// then
expect(firstId).toMatch(format)
expect(secondId).toMatch(format)
expect(Number(secondId.slice(4))).toBe(Number(firstId.slice(4)) + 1)
})
})
describe("generatePartId", () => {
it("returns deterministic sequential IDs with fixed format", () => {
// given
const format = /^prt_\d{12}$/
// when
const firstId = generatePartId()
const secondId = generatePartId()
// then
expect(firstId).toMatch(format)
expect(secondId).toMatch(format)
expect(Number(secondId.slice(4))).toBe(Number(firstId.slice(4)) + 1)
})
})
describe("injectHookMessage", () => { describe("injectHookMessage", () => {
beforeEach(() => { beforeEach(() => {
vi.clearAllMocks() vi.clearAllMocks()

View File

@ -29,6 +29,9 @@ interface SDKMessage {
} }
} }
let messageCounter = 0
let partCounter = 0
function convertSDKMessageToStoredMessage(msg: SDKMessage): StoredMessage | null { function convertSDKMessageToStoredMessage(msg: SDKMessage): StoredMessage | null {
const info = msg.info const info = msg.info
if (!info) return null if (!info) return null
@ -204,16 +207,12 @@ export function findFirstMessageWithAgent(messageDir: string): string | null {
return null return null
} }
function generateMessageId(): string { export function generateMessageId(): string {
const timestamp = Date.now().toString(16) return `msg_${String(++messageCounter).padStart(12, "0")}`
const random = Math.random().toString(36).substring(2, 14)
return `msg_${timestamp}${random}`
} }
function generatePartId(): string { export function generatePartId(): string {
const timestamp = Date.now().toString(16) return `prt_${String(++partCounter).padStart(12, "0")}`
const random = Math.random().toString(36).substring(2, 10)
return `prt_${timestamp}${random}`
} }
function getOrCreateMessageDir(sessionID: string): string { function getOrCreateMessageDir(sessionID: string): string {