refactor: cleanup shared constants and add async SDK support for isCallerOrchestrator
- Use shared OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE constants - Make isCallerOrchestrator async with SDK fallback for beta - Fix cache implementation using Symbol sentinel - Update atlas hooks and sisyphus-junior-notepad to use async isCallerOrchestrator
This commit is contained in:
parent
1bb5a3a037
commit
068831f79e
@ -1,10 +1,6 @@
|
|||||||
import { join } from "node:path"
|
import { MESSAGE_STORAGE, PART_STORAGE } from "../../shared"
|
||||||
import { getOpenCodeStorageDir } from "../../shared/data-path"
|
|
||||||
|
|
||||||
const OPENCODE_STORAGE_DIR = getOpenCodeStorageDir()
|
export { MESSAGE_STORAGE as MESSAGE_STORAGE_DIR, PART_STORAGE as PART_STORAGE_DIR }
|
||||||
|
|
||||||
export const MESSAGE_STORAGE_DIR = join(OPENCODE_STORAGE_DIR, "message")
|
|
||||||
export const PART_STORAGE_DIR = join(OPENCODE_STORAGE_DIR, "part")
|
|
||||||
|
|
||||||
export const TRUNCATION_MESSAGE =
|
export const TRUNCATION_MESSAGE =
|
||||||
"[TOOL RESULT TRUNCATED - Context limit exceeded. Original output was too large and has been truncated to recover the session. Please re-run this tool if you need the full output.]"
|
"[TOOL RESULT TRUNCATED - Context limit exceeded. Original output was too large and has been truncated to recover the session. Please re-run this tool if you need the full output.]"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ export function createAtlasHook(ctx: PluginInput, options?: AtlasHookOptions) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
handler: createAtlasEventHandler({ ctx, options, sessions, getState }),
|
handler: createAtlasEventHandler({ ctx, options, sessions, getState }),
|
||||||
"tool.execute.before": createToolExecuteBeforeHandler({ pendingFilePaths }),
|
"tool.execute.before": createToolExecuteBeforeHandler({ ctx, pendingFilePaths }),
|
||||||
"tool.execute.after": createToolExecuteAfterHandler({ ctx, pendingFilePaths }),
|
"tool.execute.after": createToolExecuteAfterHandler({ ctx, pendingFilePaths }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ export function createToolExecuteAfterHandler(input: {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isCallerOrchestrator(toolInput.sessionID)) {
|
if (!(await isCallerOrchestrator(toolInput.sessionID, ctx.client))) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,21 +1,23 @@
|
|||||||
import { log } from "../../shared/logger"
|
import { log } from "../../shared/logger"
|
||||||
import { SYSTEM_DIRECTIVE_PREFIX } from "../../shared/system-directive"
|
import { SYSTEM_DIRECTIVE_PREFIX } from "../../shared/system-directive"
|
||||||
import { isCallerOrchestrator } from "../../shared/session-utils"
|
import { isCallerOrchestrator } from "../../shared/session-utils"
|
||||||
|
import type { PluginInput } from "@opencode-ai/plugin"
|
||||||
import { HOOK_NAME } from "./hook-name"
|
import { HOOK_NAME } from "./hook-name"
|
||||||
import { ORCHESTRATOR_DELEGATION_REQUIRED, SINGLE_TASK_DIRECTIVE } from "./system-reminder-templates"
|
import { ORCHESTRATOR_DELEGATION_REQUIRED, SINGLE_TASK_DIRECTIVE } from "./system-reminder-templates"
|
||||||
import { isSisyphusPath } from "./sisyphus-path"
|
import { isSisyphusPath } from "./sisyphus-path"
|
||||||
import { isWriteOrEditToolName } from "./write-edit-tool-policy"
|
import { isWriteOrEditToolName } from "./write-edit-tool-policy"
|
||||||
|
|
||||||
export function createToolExecuteBeforeHandler(input: {
|
export function createToolExecuteBeforeHandler(input: {
|
||||||
|
ctx: PluginInput
|
||||||
pendingFilePaths: Map<string, string>
|
pendingFilePaths: Map<string, string>
|
||||||
}): (
|
}): (
|
||||||
toolInput: { tool: string; sessionID?: string; callID?: string },
|
toolInput: { tool: string; sessionID?: string; callID?: string },
|
||||||
toolOutput: { args: Record<string, unknown>; message?: string }
|
toolOutput: { args: Record<string, unknown>; message?: string }
|
||||||
) => Promise<void> {
|
) => Promise<void> {
|
||||||
const { pendingFilePaths } = input
|
const { ctx, pendingFilePaths } = input
|
||||||
|
|
||||||
return async (toolInput, toolOutput): Promise<void> => {
|
return async (toolInput, toolOutput): Promise<void> => {
|
||||||
if (!isCallerOrchestrator(toolInput.sessionID)) {
|
if (!(await isCallerOrchestrator(toolInput.sessionID, ctx.client))) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,4 @@
|
|||||||
import { join } from "node:path"
|
export { OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE } from "../../shared"
|
||||||
import { getOpenCodeStorageDir } from "../../shared/data-path"
|
|
||||||
|
|
||||||
export const OPENCODE_STORAGE = getOpenCodeStorageDir()
|
|
||||||
export const MESSAGE_STORAGE = join(OPENCODE_STORAGE, "message")
|
|
||||||
export const PART_STORAGE = join(OPENCODE_STORAGE, "part")
|
|
||||||
|
|
||||||
export const THINKING_TYPES = new Set(["thinking", "redacted_thinking", "reasoning"])
|
export const THINKING_TYPES = new Set(["thinking", "redacted_thinking", "reasoning"])
|
||||||
export const META_TYPES = new Set(["step-start", "step-finish"])
|
export const META_TYPES = new Set(["step-start", "step-finish"])
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { SYSTEM_DIRECTIVE_PREFIX } from "../../shared/system-directive"
|
|||||||
import { log } from "../../shared/logger"
|
import { log } from "../../shared/logger"
|
||||||
import { HOOK_NAME, NOTEPAD_DIRECTIVE } from "./constants"
|
import { HOOK_NAME, NOTEPAD_DIRECTIVE } from "./constants"
|
||||||
|
|
||||||
export function createSisyphusJuniorNotepadHook(_ctx: PluginInput) {
|
export function createSisyphusJuniorNotepadHook(ctx: PluginInput) {
|
||||||
return {
|
return {
|
||||||
"tool.execute.before": async (
|
"tool.execute.before": async (
|
||||||
input: { tool: string; sessionID: string; callID: string },
|
input: { tool: string; sessionID: string; callID: string },
|
||||||
@ -17,7 +17,7 @@ export function createSisyphusJuniorNotepadHook(_ctx: PluginInput) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Check if caller is Atlas (orchestrator)
|
// 2. Check if caller is Atlas (orchestrator)
|
||||||
if (!isCallerOrchestrator(input.sessionID)) {
|
if (!(await isCallerOrchestrator(input.sessionID, ctx.client))) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,10 +3,11 @@ import { join } from "node:path"
|
|||||||
import { getDataDir } from "./data-path"
|
import { getDataDir } from "./data-path"
|
||||||
import { isOpenCodeVersionAtLeast, OPENCODE_SQLITE_VERSION } from "./opencode-version"
|
import { isOpenCodeVersionAtLeast, OPENCODE_SQLITE_VERSION } from "./opencode-version"
|
||||||
|
|
||||||
let cachedResult: boolean | null = null
|
const NOT_CACHED = Symbol("NOT_CACHED")
|
||||||
|
let cachedResult: boolean | typeof NOT_CACHED = NOT_CACHED
|
||||||
|
|
||||||
export function isSqliteBackend(): boolean {
|
export function isSqliteBackend(): boolean {
|
||||||
if (cachedResult !== null) {
|
if (cachedResult !== NOT_CACHED) {
|
||||||
return cachedResult
|
return cachedResult
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,5 +20,5 @@ export function isSqliteBackend(): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function resetSqliteBackendCache(): void {
|
export function resetSqliteBackendCache(): void {
|
||||||
cachedResult = null
|
cachedResult = NOT_CACHED
|
||||||
}
|
}
|
||||||
@ -1,12 +1,22 @@
|
|||||||
import * as path from "node:path"
|
import { findNearestMessageWithFields, findNearestMessageWithFieldsFromSDK } from "../features/hook-message-injector"
|
||||||
import * as os from "node:os"
|
|
||||||
import { existsSync, readdirSync } from "node:fs"
|
|
||||||
import { join } from "node:path"
|
|
||||||
import { findNearestMessageWithFields, MESSAGE_STORAGE } from "../features/hook-message-injector"
|
|
||||||
import { getMessageDir } from "./opencode-message-dir"
|
import { getMessageDir } from "./opencode-message-dir"
|
||||||
|
import { isSqliteBackend } from "./opencode-storage-detection"
|
||||||
|
import type { PluginInput } from "@opencode-ai/plugin"
|
||||||
|
|
||||||
export function isCallerOrchestrator(sessionID?: string): boolean {
|
export async function isCallerOrchestrator(sessionID?: string, client?: PluginInput["client"]): Promise<boolean> {
|
||||||
if (!sessionID) return false
|
if (!sessionID) return false
|
||||||
|
|
||||||
|
// Beta mode: use SDK if client provided
|
||||||
|
if (isSqliteBackend() && client) {
|
||||||
|
try {
|
||||||
|
const nearest = await findNearestMessageWithFieldsFromSDK(client, sessionID)
|
||||||
|
return nearest?.agent?.toLowerCase() === "atlas"
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stable mode: use JSON files
|
||||||
const messageDir = getMessageDir(sessionID)
|
const messageDir = getMessageDir(sessionID)
|
||||||
if (!messageDir) return false
|
if (!messageDir) return false
|
||||||
const nearest = findNearestMessageWithFields(messageDir)
|
const nearest = findNearestMessageWithFields(messageDir)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user