Pass available agent metadata to createSisyphusAgent so the delegation table and other dynamic prompt sections are populated instead of being empty. Root cause: buildAgent() only passed `model` to createSisyphusAgent, but not `availableAgents`. This caused the delegation table, tool selection table, and other dynamic sections to be built with empty arrays. Fix: 1. Import all agent metadata exports (*_PROMPT_METADATA) 2. Create agentMetadata map 3. Build non-Sisyphus agents first, collecting AvailableAgent[] 4. Pass availableAgents to createSisyphusAgent 🤖 Generated with assistance of OhMyOpenCode (https://github.com/code-yeongyu/oh-my-opencode)
147 lines
4.7 KiB
TypeScript
147 lines
4.7 KiB
TypeScript
import type { AgentConfig } from "@opencode-ai/sdk"
|
|
import type { BuiltinAgentName, AgentOverrideConfig, AgentOverrides, AgentFactory, AgentPromptMetadata } from "./types"
|
|
import { createSisyphusAgent } from "./sisyphus"
|
|
import { createOracleAgent, ORACLE_PROMPT_METADATA } from "./oracle"
|
|
import { createLibrarianAgent, LIBRARIAN_PROMPT_METADATA } from "./librarian"
|
|
import { createExploreAgent, EXPLORE_PROMPT_METADATA } from "./explore"
|
|
import { createFrontendUiUxEngineerAgent, FRONTEND_PROMPT_METADATA } from "./frontend-ui-ux-engineer"
|
|
import { createDocumentWriterAgent, DOCUMENT_WRITER_PROMPT_METADATA } from "./document-writer"
|
|
import { createMultimodalLookerAgent, MULTIMODAL_LOOKER_PROMPT_METADATA } from "./multimodal-looker"
|
|
import type { AvailableAgent } from "./sisyphus-prompt-builder"
|
|
import { deepMerge } from "../shared"
|
|
|
|
type AgentSource = AgentFactory | AgentConfig
|
|
|
|
const agentSources: Record<BuiltinAgentName, AgentSource> = {
|
|
Sisyphus: createSisyphusAgent,
|
|
oracle: createOracleAgent,
|
|
librarian: createLibrarianAgent,
|
|
explore: createExploreAgent,
|
|
"frontend-ui-ux-engineer": createFrontendUiUxEngineerAgent,
|
|
"document-writer": createDocumentWriterAgent,
|
|
"multimodal-looker": createMultimodalLookerAgent,
|
|
}
|
|
|
|
/**
|
|
* Metadata for each agent, used to build Sisyphus's dynamic prompt sections
|
|
* (Delegation Table, Tool Selection, Key Triggers, etc.)
|
|
*/
|
|
const agentMetadata: Partial<Record<BuiltinAgentName, AgentPromptMetadata>> = {
|
|
oracle: ORACLE_PROMPT_METADATA,
|
|
librarian: LIBRARIAN_PROMPT_METADATA,
|
|
explore: EXPLORE_PROMPT_METADATA,
|
|
"frontend-ui-ux-engineer": FRONTEND_PROMPT_METADATA,
|
|
"document-writer": DOCUMENT_WRITER_PROMPT_METADATA,
|
|
"multimodal-looker": MULTIMODAL_LOOKER_PROMPT_METADATA,
|
|
}
|
|
|
|
function isFactory(source: AgentSource): source is AgentFactory {
|
|
return typeof source === "function"
|
|
}
|
|
|
|
function buildAgent(source: AgentSource, model?: string): AgentConfig {
|
|
return isFactory(source) ? source(model) : source
|
|
}
|
|
|
|
/**
|
|
* Creates OmO-specific environment context (time, timezone, locale).
|
|
* Note: Working directory, platform, and date are already provided by OpenCode's system.ts,
|
|
* so we only include fields that OpenCode doesn't provide to avoid duplication.
|
|
* See: https://github.com/code-yeongyu/oh-my-opencode/issues/379
|
|
*/
|
|
export function createEnvContext(): string {
|
|
const now = new Date()
|
|
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
const locale = Intl.DateTimeFormat().resolvedOptions().locale
|
|
|
|
const timeStr = now.toLocaleTimeString("en-US", {
|
|
hour: "2-digit",
|
|
minute: "2-digit",
|
|
second: "2-digit",
|
|
hour12: true,
|
|
})
|
|
|
|
return `
|
|
<omo-env>
|
|
Current time: ${timeStr}
|
|
Timezone: ${timezone}
|
|
Locale: ${locale}
|
|
</omo-env>`
|
|
}
|
|
|
|
function mergeAgentConfig(
|
|
base: AgentConfig,
|
|
override: AgentOverrideConfig
|
|
): AgentConfig {
|
|
const { prompt_append, ...rest } = override
|
|
const merged = deepMerge(base, rest as Partial<AgentConfig>)
|
|
|
|
if (prompt_append && merged.prompt) {
|
|
merged.prompt = merged.prompt + "\n" + prompt_append
|
|
}
|
|
|
|
return merged
|
|
}
|
|
|
|
export function createBuiltinAgents(
|
|
disabledAgents: BuiltinAgentName[] = [],
|
|
agentOverrides: AgentOverrides = {},
|
|
directory?: string,
|
|
systemDefaultModel?: string
|
|
): Record<string, AgentConfig> {
|
|
const result: Record<string, AgentConfig> = {}
|
|
const availableAgents: AvailableAgent[] = []
|
|
|
|
for (const [name, source] of Object.entries(agentSources)) {
|
|
const agentName = name as BuiltinAgentName
|
|
|
|
if (agentName === "Sisyphus") continue
|
|
if (disabledAgents.includes(agentName)) continue
|
|
|
|
const override = agentOverrides[agentName]
|
|
const model = override?.model
|
|
|
|
let config = buildAgent(source, model)
|
|
|
|
if (agentName === "librarian" && directory && config.prompt) {
|
|
const envContext = createEnvContext()
|
|
config = { ...config, prompt: config.prompt + envContext }
|
|
}
|
|
|
|
if (override) {
|
|
config = mergeAgentConfig(config, override)
|
|
}
|
|
|
|
result[name] = config
|
|
|
|
const metadata = agentMetadata[agentName]
|
|
if (metadata) {
|
|
availableAgents.push({
|
|
name: agentName,
|
|
description: config.description ?? "",
|
|
metadata,
|
|
})
|
|
}
|
|
}
|
|
|
|
if (!disabledAgents.includes("Sisyphus")) {
|
|
const sisyphusOverride = agentOverrides["Sisyphus"]
|
|
const sisyphusModel = sisyphusOverride?.model ?? systemDefaultModel
|
|
|
|
let sisyphusConfig = createSisyphusAgent(sisyphusModel, availableAgents)
|
|
|
|
if (directory && sisyphusConfig.prompt) {
|
|
const envContext = createEnvContext()
|
|
sisyphusConfig = { ...sisyphusConfig, prompt: sisyphusConfig.prompt + envContext }
|
|
}
|
|
|
|
if (sisyphusOverride) {
|
|
sisyphusConfig = mergeAgentConfig(sisyphusConfig, sisyphusOverride)
|
|
}
|
|
|
|
result["Sisyphus"] = sisyphusConfig
|
|
}
|
|
|
|
return result
|
|
}
|