Files
oh-my-opencode/src/agents/atlas/agent.ts
T
2026-05-16 17:41:35 +09:00

154 lines
5.2 KiB
TypeScript

/**
* Atlas - Master Orchestrator Agent
*
* Orchestrates work via task() to complete ALL tasks in a todo list until fully done.
*
* Prompt routing (`getAtlasPromptSource`, evaluated in this order):
* 1. GPT family → gpt.ts (calibrated for GPT-5.5)
* 2. Gemini family → gemini.ts
* 3. Kimi K2.x family → kimi.ts (Claude-family base + K2.6 thinking-mode calibration)
* 4. Claude Opus 4.7 → opus-4-7.ts (literal-following + explicit fan-out push)
* 5. Default (Claude 4.6 family: opus-4-6, sonnet-4-6, haiku-4-5, etc.) → default.ts
*/
import type { AgentConfig } from "@opencode-ai/sdk"
import type { AgentMode, AgentPromptMetadata } from "../types"
import { isClaudeOpus47Model, isGeminiModel, isGptModel, isKimiK2Model } from "../types"
import type { AvailableAgent, AvailableSkill, AvailableCategory } from "../dynamic-agent-prompt-builder"
import { buildAgentIdentitySection, buildCategorySkillsDelegationGuide } from "../dynamic-agent-prompt-builder"
import type { CategoryConfig } from "../../config/schema"
import { mergeCategories } from "../../shared/merge-categories"
import { getDefaultAtlasPrompt } from "./default"
import { getGptAtlasPrompt } from "./gpt"
import { getGeminiAtlasPrompt } from "./gemini"
import { getKimiAtlasPrompt } from "./kimi"
import { getOpus47AtlasPrompt } from "./opus-4-7"
import {
getCategoryDescription,
buildAgentSelectionSection,
buildCategorySection,
buildSkillsSection,
buildDecisionMatrix,
} from "./prompt-section-builder"
const MODE: AgentMode = "primary"
export type AtlasPromptSource = "default" | "gpt" | "gemini" | "kimi" | "opus-4-7"
export function getAtlasPromptSource(model?: string): AtlasPromptSource {
if (model && isGptModel(model)) {
return "gpt"
}
if (model && isGeminiModel(model)) {
return "gemini"
}
if (model && isKimiK2Model(model)) {
return "kimi"
}
if (model && isClaudeOpus47Model(model)) {
return "opus-4-7"
}
return "default"
}
export interface OrchestratorContext {
model?: string
availableAgents?: AvailableAgent[]
availableSkills?: AvailableSkill[]
userCategories?: Record<string, CategoryConfig>
}
export function getAtlasPrompt(model?: string): string {
const source = getAtlasPromptSource(model)
switch (source) {
case "gpt":
return getGptAtlasPrompt()
case "gemini":
return getGeminiAtlasPrompt()
case "kimi":
return getKimiAtlasPrompt()
case "opus-4-7":
return getOpus47AtlasPrompt()
case "default":
default:
return getDefaultAtlasPrompt()
}
}
function buildDynamicOrchestratorPrompt(ctx?: OrchestratorContext): string {
const agents = ctx?.availableAgents ?? []
const skills = ctx?.availableSkills ?? []
const userCategories = ctx?.userCategories
const model = ctx?.model
const allCategories = mergeCategories(userCategories)
const availableCategories: AvailableCategory[] = Object.entries(allCategories).map(([name]) => ({
name,
description: getCategoryDescription(name, userCategories),
}))
const categorySection = buildCategorySection(userCategories)
const agentSection = buildAgentSelectionSection(agents)
const decisionMatrix = buildDecisionMatrix(agents, userCategories)
const skillsSection = buildSkillsSection(skills)
const categorySkillsGuide = buildCategorySkillsDelegationGuide(availableCategories, skills)
const agentIdentity = buildAgentIdentitySection(
"Atlas",
"Master Orchestrator agent from OhMyOpenCode that coordinates specialized agents to complete todo lists",
)
const basePrompt = getAtlasPrompt(model)
return agentIdentity + "\n" + basePrompt
.replace("{CATEGORY_SECTION}", categorySection)
.replace("{AGENT_SECTION}", agentSection)
.replace("{DECISION_MATRIX}", decisionMatrix)
.replace("{SKILLS_SECTION}", skillsSection)
.replace("{{CATEGORY_SKILLS_DELEGATION_GUIDE}}", categorySkillsGuide)
}
export function createAtlasAgent(ctx: OrchestratorContext): AgentConfig {
const baseConfig = {
description:
"Orchestrates work via task() to complete ALL tasks in a todo list until fully done. (Atlas - OhMyOpenCode)",
mode: MODE,
...(ctx.model ? { model: ctx.model } : {}),
temperature: 0.1,
prompt: buildDynamicOrchestratorPrompt(ctx),
color: "#10B981",
}
return baseConfig as AgentConfig
}
createAtlasAgent.mode = MODE
export const atlasPromptMetadata: AgentPromptMetadata = {
category: "advisor",
cost: "EXPENSIVE",
promptAlias: "Atlas",
triggers: [
{
domain: "Todo list orchestration",
trigger: "Complete ALL tasks in a todo list with verification",
},
{
domain: "Multi-agent coordination",
trigger: "Parallel task execution across specialized agents",
},
],
useWhen: [
"User provides a todo list path (.omo/plans/{name}.md)",
"Multiple tasks need to be completed in sequence or parallel",
"Work requires coordination across multiple specialized agents",
],
avoidWhen: [
"Single simple task that doesn't require orchestration",
"Tasks that can be handled directly by one agent",
"When user wants to execute tasks manually",
],
keyTrigger:
"Todo list path provided OR multiple tasks requiring multi-agent orchestration",
}