refactor(tools): migrate producers to shared metadata bridge
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { tool, type ToolDefinition } from "@opencode-ai/plugin"
|
||||
import type { BackgroundTask } from "../../features/background-agent"
|
||||
import { storeToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { publishToolMetadata } from "../../features/tool-metadata-store"
|
||||
import type { BackgroundOutputArgs } from "./types"
|
||||
import type { BackgroundOutputClient, BackgroundOutputManager } from "./clients"
|
||||
import { BACKGROUND_OUTPUT_DESCRIPTION } from "./constants"
|
||||
@@ -23,13 +23,6 @@ type ToolContextWithMetadata = {
|
||||
call_id?: string
|
||||
}
|
||||
|
||||
function resolveToolCallID(ctx: ToolContextWithMetadata): string | undefined {
|
||||
if (typeof ctx.callID === "string" && ctx.callID.trim() !== "") return ctx.callID
|
||||
if (typeof ctx.callId === "string" && ctx.callId.trim() !== "") return ctx.callId
|
||||
if (typeof ctx.call_id === "string" && ctx.call_id.trim() !== "") return ctx.call_id
|
||||
return undefined
|
||||
}
|
||||
|
||||
function formatResolvedTitle(task: BackgroundTask): string {
|
||||
const label = task.agent === SISYPHUS_JUNIOR_AGENT && task.category ? task.category : task.agent
|
||||
return `${label} - ${task.description}`
|
||||
@@ -80,12 +73,7 @@ export function createBackgroundOutput(manager: BackgroundOutputManager, client:
|
||||
...(task.sessionID ? { sessionId: task.sessionID } : {}),
|
||||
} as Record<string, unknown>,
|
||||
}
|
||||
ctx.metadata?.(meta)
|
||||
|
||||
const callID = resolveToolCallID(ctx)
|
||||
if (callID) {
|
||||
storeToolMetadata(ctx.sessionID, callID, meta)
|
||||
}
|
||||
await publishToolMetadata(ctx, meta)
|
||||
|
||||
const shouldBlock = args.block === true
|
||||
const timeoutMs = Math.min(args.timeout ?? 60000, 600000)
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { BackgroundTaskArgs } from "./types"
|
||||
import { BACKGROUND_TASK_DESCRIPTION } from "./constants"
|
||||
import { resolveMessageContext } from "../../features/hook-message-injector"
|
||||
import { getSessionAgent } from "../../features/claude-code-session-state"
|
||||
import { storeToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { publishToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { log } from "../../shared/logger"
|
||||
import { delay } from "./delay"
|
||||
import { getMessageDir } from "./message-dir"
|
||||
@@ -100,11 +100,7 @@ export function createBackgroundTask(
|
||||
...(sessionId ? { sessionId } : {}),
|
||||
},
|
||||
}
|
||||
ctx.metadata?.(bgMeta)
|
||||
|
||||
if (ctx.callID) {
|
||||
storeToolMetadata(ctx.sessionID, ctx.callID, bgMeta)
|
||||
}
|
||||
await publishToolMetadata(ctx, bgMeta)
|
||||
|
||||
return `Background task launched successfully.
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import type { DelegateTaskArgs, ToolContextWithMetadata } from "./types"
|
||||
import type { ExecutorContext, ParentContext } from "./executor-types"
|
||||
import { storeToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { publishToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { formatDetailedError } from "./error-formatting"
|
||||
import { getSessionTools } from "../../shared/session-tools-store"
|
||||
import { resolveCallID } from "./resolve-call-id"
|
||||
|
||||
export async function executeBackgroundContinuation(
|
||||
args: DelegateTaskArgs,
|
||||
@@ -37,11 +36,7 @@ export async function executeBackgroundContinuation(
|
||||
model: task.model ? { providerID: task.model.providerID, modelID: task.model.modelID } : undefined,
|
||||
},
|
||||
}
|
||||
await ctx.metadata?.(bgContMeta)
|
||||
const callID = resolveCallID(ctx)
|
||||
if (callID) {
|
||||
storeToolMetadata(ctx.sessionID, callID, bgContMeta)
|
||||
}
|
||||
await publishToolMetadata(ctx, bgContMeta)
|
||||
|
||||
return `Background task continued.
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@ import type { ExecutorContext, ParentContext } from "./executor-types"
|
||||
import type { FallbackEntry } from "../../shared/model-requirements"
|
||||
import { getTimingConfig } from "./timing"
|
||||
import { buildTaskPrompt } from "./prompt-builder"
|
||||
import { storeToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { resolveCallID } from "./resolve-call-id"
|
||||
import { publishToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { formatDetailedError } from "./error-formatting"
|
||||
import { getSessionTools } from "../../shared/session-tools-store"
|
||||
import { SessionCategoryRegistry } from "../../shared/session-category-registry"
|
||||
@@ -134,11 +133,7 @@ export async function executeBackgroundTask(
|
||||
title: args.description,
|
||||
metadata,
|
||||
}
|
||||
await ctx.metadata?.(unstableMeta)
|
||||
const callID = resolveCallID(ctx)
|
||||
if (callID) {
|
||||
storeToolMetadata(ctx.sessionID, callID, unstableMeta)
|
||||
}
|
||||
await publishToolMetadata(ctx, unstableMeta)
|
||||
|
||||
const taskMetadataBlock = sessionId
|
||||
? `\n\n<task_metadata>\nsession_id: ${sessionId}\ntask_id: ${task.id}\nbackground_task_id: ${task.id}\n</task_metadata>`
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import { describe, test, expect } from "bun:test"
|
||||
import { resolveCallID } from "./resolve-call-id"
|
||||
import type { ToolContextWithMetadata } from "./types"
|
||||
|
||||
describe("resolveCallID", () => {
|
||||
function makeCtx(overrides: Partial<ToolContextWithMetadata> = {}): ToolContextWithMetadata {
|
||||
return {
|
||||
sessionID: "ses_test",
|
||||
messageID: "msg_test",
|
||||
agent: "sisyphus",
|
||||
abort: new AbortController().signal,
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
test("#given callID is set #then returns callID", () => {
|
||||
const ctx = makeCtx({ callID: "call_abc" })
|
||||
expect(resolveCallID(ctx)).toBe("call_abc")
|
||||
})
|
||||
|
||||
test("#given only callId is set #then returns callId", () => {
|
||||
const ctx = makeCtx({ callId: "call_def" })
|
||||
expect(resolveCallID(ctx)).toBe("call_def")
|
||||
})
|
||||
|
||||
test("#given only call_id is set #then returns call_id", () => {
|
||||
const ctx = makeCtx({ call_id: "call_ghi" })
|
||||
expect(resolveCallID(ctx)).toBe("call_ghi")
|
||||
})
|
||||
|
||||
test("#given callID and callId are both set #then prefers callID", () => {
|
||||
const ctx = makeCtx({ callID: "preferred", callId: "fallback" })
|
||||
expect(resolveCallID(ctx)).toBe("preferred")
|
||||
})
|
||||
|
||||
test("#given no call ID variants are set #then returns undefined", () => {
|
||||
const ctx = makeCtx()
|
||||
expect(resolveCallID(ctx)).toBeUndefined()
|
||||
})
|
||||
})
|
||||
@@ -1,5 +0,0 @@
|
||||
import type { ToolContextWithMetadata } from "./types"
|
||||
|
||||
export function resolveCallID(ctx: ToolContextWithMetadata): string | undefined {
|
||||
return ctx.callID ?? ctx.callId ?? ctx.call_id
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { DelegateTaskArgs, ToolContextWithMetadata } from "./types"
|
||||
import type { ExecutorContext, SessionMessage } from "./executor-types"
|
||||
import { isPlanFamily } from "./constants"
|
||||
import { storeToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { resolveCallID } from "./resolve-call-id"
|
||||
import { publishToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { getTaskToastManager } from "../../features/task-toast-manager"
|
||||
import { getAgentToolRestrictions } from "../../shared/agent-tool-restrictions"
|
||||
import { getMessageDir } from "../../shared"
|
||||
@@ -78,11 +77,7 @@ export async function executeSyncContinuation(
|
||||
model: resumeModel,
|
||||
},
|
||||
}
|
||||
await ctx.metadata?.(syncContMeta)
|
||||
const callID = resolveCallID(ctx)
|
||||
if (callID) {
|
||||
storeToolMetadata(ctx.sessionID, callID, syncContMeta)
|
||||
}
|
||||
await publishToolMetadata(ctx, syncContMeta)
|
||||
|
||||
const allowTask = isPlanFamily(resumeAgent)
|
||||
const tddEnabled = sisyphusAgentConfig?.tdd
|
||||
|
||||
@@ -2,8 +2,7 @@ import type { ModelFallbackInfo } from "../../features/task-toast-manager/types"
|
||||
import type { DelegateTaskArgs, ToolContextWithMetadata, DelegatedModelConfig } from "./types"
|
||||
import type { ExecutorContext, ParentContext } from "./executor-types"
|
||||
import { getTaskToastManager } from "../../features/task-toast-manager"
|
||||
import { storeToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { resolveCallID } from "./resolve-call-id"
|
||||
import { publishToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { subagentSessions, syncSubagentSessions, setSessionAgent } from "../../features/claude-code-session-state"
|
||||
import { log } from "../../shared/logger"
|
||||
import { SessionCategoryRegistry } from "../../shared/session-category-registry"
|
||||
@@ -130,11 +129,7 @@ export async function executeSyncTask(
|
||||
model: categoryModel ? { providerID: categoryModel.providerID, modelID: categoryModel.modelID } : undefined,
|
||||
},
|
||||
}
|
||||
await ctx.metadata?.(syncTaskMeta)
|
||||
const callID = resolveCallID(ctx)
|
||||
if (callID) {
|
||||
storeToolMetadata(ctx.sessionID, callID, syncTaskMeta)
|
||||
}
|
||||
await publishToolMetadata(ctx, syncTaskMeta)
|
||||
|
||||
let effectiveCategoryModel = categoryModel
|
||||
let promptError = await deps.sendSyncPrompt(client, {
|
||||
|
||||
@@ -3,8 +3,7 @@ import type { ExecutorContext, ParentContext, SessionMessage } from "./executor-
|
||||
import { DEFAULT_SYNC_POLL_TIMEOUT_MS, getTimingConfig } from "./timing"
|
||||
import { buildTaskPrompt } from "./prompt-builder"
|
||||
import { cancelUnstableAgentTask } from "./cancel-unstable-agent-task"
|
||||
import { storeToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { resolveCallID } from "./resolve-call-id"
|
||||
import { publishToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { formatDuration } from "./time-formatter"
|
||||
import { formatDetailedError } from "./error-formatting"
|
||||
import { getSessionTools } from "../../shared/session-tools-store"
|
||||
@@ -81,11 +80,7 @@ export async function executeUnstableAgentTask(
|
||||
model: categoryModel ? { providerID: categoryModel.providerID, modelID: categoryModel.modelID } : undefined,
|
||||
},
|
||||
}
|
||||
await ctx.metadata?.(bgTaskMeta)
|
||||
const callID = resolveCallID(ctx)
|
||||
if (callID) {
|
||||
storeToolMetadata(ctx.sessionID, callID, bgTaskMeta)
|
||||
}
|
||||
await publishToolMetadata(ctx, bgTaskMeta)
|
||||
|
||||
const startTime = new Date()
|
||||
const timingCfg = getTimingConfig()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolContext } from "@opencode-ai/plugin/tool"
|
||||
import { storeToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { publishToolMetadata } from "../../features/tool-metadata-store"
|
||||
import { applyHashlineEditsWithReport } from "./edit-operations"
|
||||
import { countLineDiffs, generateUnifiedDiff } from "./diff-utils"
|
||||
import { canonicalizeFileText, restoreFileText } from "./file-text-canonicalization"
|
||||
@@ -26,13 +26,6 @@ type ToolContextWithMetadata = ToolContextWithCallID & {
|
||||
metadata?: (value: unknown) => void
|
||||
}
|
||||
|
||||
function resolveToolCallID(ctx: ToolContextWithCallID): string | undefined {
|
||||
if (typeof ctx.callID === "string" && ctx.callID.trim() !== "") return ctx.callID
|
||||
if (typeof ctx.callId === "string" && ctx.callId.trim() !== "") return ctx.callId
|
||||
if (typeof ctx.call_id === "string" && ctx.call_id.trim() !== "") return ctx.call_id
|
||||
return undefined
|
||||
}
|
||||
|
||||
function canCreateFromMissingFile(edits: HashlineEdit[]): boolean {
|
||||
if (edits.length === 0) return false
|
||||
return edits.every((edit) => (edit.op === "append" || edit.op === "prepend") && !edit.pos)
|
||||
@@ -143,13 +136,7 @@ export async function executeHashlineEditTool(args: HashlineEditArgs, context: T
|
||||
applyResult.noopEdits,
|
||||
applyResult.deduplicatedEdits
|
||||
)
|
||||
if (typeof metadataContext.metadata === "function") {
|
||||
metadataContext.metadata(formattedMeta)
|
||||
}
|
||||
const callID = resolveToolCallID(metadataContext)
|
||||
if (callID) {
|
||||
storeToolMetadata(context.sessionID, callID, formattedMeta)
|
||||
}
|
||||
await publishToolMetadata(metadataContext, formattedMeta)
|
||||
if (rename && rename !== filePath) {
|
||||
await Bun.write(rename, formattedContent)
|
||||
await Bun.file(filePath).delete()
|
||||
@@ -173,14 +160,7 @@ export async function executeHashlineEditTool(args: HashlineEditArgs, context: T
|
||||
applyResult.deduplicatedEdits
|
||||
)
|
||||
|
||||
if (typeof metadataContext.metadata === "function") {
|
||||
metadataContext.metadata(meta)
|
||||
}
|
||||
|
||||
const callID = resolveToolCallID(metadataContext)
|
||||
if (callID) {
|
||||
storeToolMetadata(context.sessionID, callID, meta)
|
||||
}
|
||||
await publishToolMetadata(metadataContext, meta)
|
||||
|
||||
if (rename && rename !== filePath) {
|
||||
return `Moved ${filePath} to ${rename}`
|
||||
|
||||
Reference in New Issue
Block a user