Split monolithic atlas.ts into modular structure: index.ts (routing), default.ts (Claude-optimized), gpt.ts (GPT-optimized), utils.ts (shared utilities). Atlas now routes to appropriate prompt based on model type instead of overriding model settings. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
154 lines
4.8 KiB
TypeScript
154 lines
4.8 KiB
TypeScript
/**
|
|
* Atlas - Master Orchestrator Agent
|
|
*
|
|
* Orchestrates work via delegate_task() to complete ALL tasks in a todo list until fully done.
|
|
* You are the conductor of a symphony of specialized agents.
|
|
*
|
|
* Routing:
|
|
* 1. GPT models (openai/*, github-copilot/gpt-*) → gpt.ts (GPT-5.2 optimized)
|
|
* 2. Default (Claude, etc.) → default.ts (Claude-optimized)
|
|
*/
|
|
|
|
import type { AgentConfig } from "@opencode-ai/sdk"
|
|
import type { AgentMode, AgentPromptMetadata } from "../types"
|
|
import { isGptModel } from "../types"
|
|
import type { AvailableAgent, AvailableSkill, AvailableCategory } from "../dynamic-agent-prompt-builder"
|
|
import { buildCategorySkillsDelegationGuide } from "../dynamic-agent-prompt-builder"
|
|
import type { CategoryConfig } from "../../config/schema"
|
|
import { DEFAULT_CATEGORIES } from "../../tools/delegate-task/constants"
|
|
import { createAgentToolRestrictions } from "../../shared/permission-compat"
|
|
|
|
import { ATLAS_SYSTEM_PROMPT, getDefaultAtlasPrompt } from "./default"
|
|
import { ATLAS_GPT_SYSTEM_PROMPT, getGptAtlasPrompt } from "./gpt"
|
|
import {
|
|
getCategoryDescription,
|
|
buildAgentSelectionSection,
|
|
buildCategorySection,
|
|
buildSkillsSection,
|
|
buildDecisionMatrix,
|
|
} from "./utils"
|
|
|
|
export { ATLAS_SYSTEM_PROMPT, getDefaultAtlasPrompt } from "./default"
|
|
export { ATLAS_GPT_SYSTEM_PROMPT, getGptAtlasPrompt } from "./gpt"
|
|
export {
|
|
getCategoryDescription,
|
|
buildAgentSelectionSection,
|
|
buildCategorySection,
|
|
buildSkillsSection,
|
|
buildDecisionMatrix,
|
|
} from "./utils"
|
|
export { isGptModel }
|
|
|
|
const MODE: AgentMode = "primary"
|
|
|
|
export type AtlasPromptSource = "default" | "gpt"
|
|
|
|
/**
|
|
* Determines which Atlas prompt to use based on model.
|
|
*/
|
|
export function getAtlasPromptSource(model?: string): AtlasPromptSource {
|
|
if (model && isGptModel(model)) {
|
|
return "gpt"
|
|
}
|
|
return "default"
|
|
}
|
|
|
|
export interface OrchestratorContext {
|
|
model?: string
|
|
availableAgents?: AvailableAgent[]
|
|
availableSkills?: AvailableSkill[]
|
|
userCategories?: Record<string, CategoryConfig>
|
|
}
|
|
|
|
/**
|
|
* Gets the appropriate Atlas prompt based on model.
|
|
*/
|
|
export function getAtlasPrompt(model?: string): string {
|
|
const source = getAtlasPromptSource(model)
|
|
|
|
switch (source) {
|
|
case "gpt":
|
|
return getGptAtlasPrompt()
|
|
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 = { ...DEFAULT_CATEGORIES, ...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 basePrompt = getAtlasPrompt(model)
|
|
|
|
return 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 restrictions = createAgentToolRestrictions([
|
|
"task",
|
|
"call_omo_agent",
|
|
])
|
|
|
|
const baseConfig = {
|
|
description:
|
|
"Orchestrates work via delegate_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",
|
|
...restrictions,
|
|
}
|
|
|
|
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 (.sisyphus/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",
|
|
}
|