feat: migrate hook callers to SDK message finders on SQLite backend

This commit is contained in:
YeonGyu-Kim 2026-02-15 14:56:58 +09:00
parent af8de2eaa2
commit 2bf8b15f24
6 changed files with 71 additions and 17 deletions

View File

@ -87,7 +87,7 @@ export function createAtlasEventHandler(input: {
return return
} }
const lastAgent = getLastAgentFromSession(sessionID) const lastAgent = await getLastAgentFromSession(sessionID, ctx.client)
const requiredAgent = (boulderState.agent ?? "atlas").toLowerCase() const requiredAgent = (boulderState.agent ?? "atlas").toLowerCase()
const lastAgentMatchesRequired = lastAgent === requiredAgent const lastAgentMatchesRequired = lastAgent === requiredAgent
const boulderAgentWasNotExplicitlySet = boulderState.agent === undefined const boulderAgentWasNotExplicitlySet = boulderState.agent === undefined

View File

@ -1,6 +1,9 @@
import type { PluginInput } from "@opencode-ai/plugin" import type { PluginInput } from "@opencode-ai/plugin"
import { findNearestMessageWithFields } from "../../features/hook-message-injector" import {
import { getMessageDir } from "../../shared" findNearestMessageWithFields,
findNearestMessageWithFieldsFromSDK,
} from "../../features/hook-message-injector"
import { getMessageDir, isSqliteBackend } from "../../shared"
import type { ModelInfo } from "./types" import type { ModelInfo } from "./types"
export async function resolveRecentModelForSession( export async function resolveRecentModelForSession(
@ -28,8 +31,13 @@ export async function resolveRecentModelForSession(
// ignore - fallback to message storage // ignore - fallback to message storage
} }
const messageDir = getMessageDir(sessionID) let currentMessage = null
const currentMessage = messageDir ? findNearestMessageWithFields(messageDir) : null if (isSqliteBackend()) {
currentMessage = await findNearestMessageWithFieldsFromSDK(ctx.client, sessionID)
} else {
const messageDir = getMessageDir(sessionID)
currentMessage = messageDir ? findNearestMessageWithFields(messageDir) : null
}
const model = currentMessage?.model const model = currentMessage?.model
if (!model?.providerID || !model?.modelID) { if (!model?.providerID || !model?.modelID) {
return undefined return undefined

View File

@ -1,9 +1,24 @@
import { findNearestMessageWithFields } from "../../features/hook-message-injector" import type { PluginInput } from "@opencode-ai/plugin"
import { getMessageDir } from "../../shared"
import { findNearestMessageWithFields } from "../../features/hook-message-injector"
import { findNearestMessageWithFieldsFromSDK } from "../../features/hook-message-injector"
import { getMessageDir, isSqliteBackend } from "../../shared"
type OpencodeClient = PluginInput["client"]
export async function getLastAgentFromSession(
sessionID: string,
client?: OpencodeClient
): Promise<string | null> {
let nearest = null
if (isSqliteBackend() && client) {
nearest = await findNearestMessageWithFieldsFromSDK(client, sessionID)
} else {
const messageDir = getMessageDir(sessionID)
if (!messageDir) return null
nearest = findNearestMessageWithFields(messageDir)
}
export function getLastAgentFromSession(sessionID: string): string | null {
const messageDir = getMessageDir(sessionID)
if (!messageDir) return null
const nearest = findNearestMessageWithFields(messageDir)
return nearest?.agent?.toLowerCase() ?? null return nearest?.agent?.toLowerCase() ?? null
} }

View File

@ -1,9 +1,29 @@
import type { PluginInput } from "@opencode-ai/plugin"
import { findNearestMessageWithFields, findFirstMessageWithAgent } from "../../features/hook-message-injector" import { findNearestMessageWithFields, findFirstMessageWithAgent } from "../../features/hook-message-injector"
import {
findFirstMessageWithAgentFromSDK,
findNearestMessageWithFieldsFromSDK,
} from "../../features/hook-message-injector"
import { getSessionAgent } from "../../features/claude-code-session-state" import { getSessionAgent } from "../../features/claude-code-session-state"
import { readBoulderState } from "../../features/boulder-state" import { readBoulderState } from "../../features/boulder-state"
import { getMessageDir } from "../../shared/opencode-message-dir" import { getMessageDir } from "../../shared/opencode-message-dir"
import { isSqliteBackend } from "../../shared/opencode-storage-detection"
type OpencodeClient = PluginInput["client"]
async function getAgentFromMessageFiles(
sessionID: string,
client?: OpencodeClient
): Promise<string | undefined> {
if (isSqliteBackend() && client) {
const firstAgent = await findFirstMessageWithAgentFromSDK(client, sessionID)
if (firstAgent) return firstAgent
const nearest = await findNearestMessageWithFieldsFromSDK(client, sessionID)
return nearest?.agent
}
function getAgentFromMessageFiles(sessionID: string): string | undefined {
const messageDir = getMessageDir(sessionID) const messageDir = getMessageDir(sessionID)
if (!messageDir) return undefined if (!messageDir) return undefined
return findFirstMessageWithAgent(messageDir) ?? findNearestMessageWithFields(messageDir)?.agent return findFirstMessageWithAgent(messageDir) ?? findNearestMessageWithFields(messageDir)?.agent
@ -21,7 +41,11 @@ function getAgentFromMessageFiles(sessionID: string): string | undefined {
* - Message files return "prometheus" (oldest message from /plan) * - Message files return "prometheus" (oldest message from /plan)
* - But boulder.json has agent: "atlas" (set by /start-work) * - But boulder.json has agent: "atlas" (set by /start-work)
*/ */
export function getAgentFromSession(sessionID: string, directory: string): string | undefined { export async function getAgentFromSession(
sessionID: string,
directory: string,
client?: OpencodeClient
): Promise<string | undefined> {
// Check in-memory first (current session) // Check in-memory first (current session)
const memoryAgent = getSessionAgent(sessionID) const memoryAgent = getSessionAgent(sessionID)
if (memoryAgent) return memoryAgent if (memoryAgent) return memoryAgent
@ -33,5 +57,5 @@ export function getAgentFromSession(sessionID: string, directory: string): strin
} }
// Fallback to message files // Fallback to message files
return getAgentFromMessageFiles(sessionID) return await getAgentFromMessageFiles(sessionID, client)
} }

View File

@ -15,7 +15,7 @@ export function createPrometheusMdOnlyHook(ctx: PluginInput) {
input: { tool: string; sessionID: string; callID: string }, input: { tool: string; sessionID: string; callID: string },
output: { args: Record<string, unknown>; message?: string } output: { args: Record<string, unknown>; message?: string }
): Promise<void> => { ): Promise<void> => {
const agentName = getAgentFromSession(input.sessionID, ctx.directory) const agentName = await getAgentFromSession(input.sessionID, ctx.directory, ctx.client)
if (!isPrometheusAgent(agentName)) { if (!isPrometheusAgent(agentName)) {
return return

View File

@ -3,9 +3,11 @@ import type { PluginInput } from "@opencode-ai/plugin"
import type { BackgroundManager } from "../../features/background-agent" import type { BackgroundManager } from "../../features/background-agent"
import { import {
findNearestMessageWithFields, findNearestMessageWithFields,
findNearestMessageWithFieldsFromSDK,
type ToolPermission, type ToolPermission,
} from "../../features/hook-message-injector" } from "../../features/hook-message-injector"
import { log } from "../../shared/logger" import { log } from "../../shared/logger"
import { isSqliteBackend } from "../../shared/opencode-storage-detection"
import { import {
CONTINUATION_PROMPT, CONTINUATION_PROMPT,
@ -78,8 +80,13 @@ export async function injectContinuation(args: {
let tools = resolvedInfo?.tools let tools = resolvedInfo?.tools
if (!agentName || !model) { if (!agentName || !model) {
const messageDir = getMessageDir(sessionID) let previousMessage = null
const previousMessage = messageDir ? findNearestMessageWithFields(messageDir) : null if (isSqliteBackend()) {
previousMessage = await findNearestMessageWithFieldsFromSDK(ctx.client, sessionID)
} else {
const messageDir = getMessageDir(sessionID)
previousMessage = messageDir ? findNearestMessageWithFields(messageDir) : null
}
agentName = agentName ?? previousMessage?.agent agentName = agentName ?? previousMessage?.agent
model = model =
model ?? model ??