Merge branch 'fix/v1.1.1-permission-migration' into dev

- Add mode: primary to Planner-Sisyphus for Tab selector visibility
- Skip skills with invalid YAML frontmatter
- Add parseError/hadFrontmatter to FrontmatterResult

🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2026-01-05 05:41:33 +09:00
3 changed files with 27 additions and 10 deletions

View File

@@ -78,7 +78,9 @@ export async function loadSkillFromPathAsync(
): Promise<LoadedSkill | null> { ): Promise<LoadedSkill | null> {
try { try {
const content = await readFile(skillPath, "utf-8") const content = await readFile(skillPath, "utf-8")
const { data, body } = parseFrontmatter<SkillMetadata>(content) const { data, body, parseError } = parseFrontmatter<SkillMetadata>(content)
if (parseError) return null
const frontmatterMcp = parseSkillMcpConfigFromFrontmatter(content) const frontmatterMcp = parseSkillMcpConfigFromFrontmatter(content)
const mcpJsonMcp = await loadMcpJsonFromDirAsync(resolvedPath) const mcpJsonMcp = await loadMcpJsonFromDirAsync(resolvedPath)
const mcpConfig = mcpJsonMcp || frontmatterMcp const mcpConfig = mcpJsonMcp || frontmatterMcp

View File

@@ -152,10 +152,13 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
if (builderEnabled) { if (builderEnabled) {
const { name: _buildName, ...buildConfigWithoutName } = const { name: _buildName, ...buildConfigWithoutName } =
configAgent?.build ?? {}; configAgent?.build ?? {};
const migratedBuildConfig = migrateAgentConfig(
buildConfigWithoutName as Record<string, unknown>
);
const openCodeBuilderOverride = const openCodeBuilderOverride =
pluginConfig.agents?.["OpenCode-Builder"]; pluginConfig.agents?.["OpenCode-Builder"];
const openCodeBuilderBase = { const openCodeBuilderBase = {
...buildConfigWithoutName, ...migratedBuildConfig,
description: `${configAgent?.build?.description ?? "Build agent"} (OpenCode default)`, description: `${configAgent?.build?.description ?? "Build agent"} (OpenCode default)`,
}; };
@@ -167,10 +170,14 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
if (plannerEnabled) { if (plannerEnabled) {
const { name: _planName, ...planConfigWithoutName } = const { name: _planName, ...planConfigWithoutName } =
configAgent?.plan ?? {}; configAgent?.plan ?? {};
const migratedPlanConfig = migrateAgentConfig(
planConfigWithoutName as Record<string, unknown>
);
const plannerSisyphusOverride = const plannerSisyphusOverride =
pluginConfig.agents?.["Planner-Sisyphus"]; pluginConfig.agents?.["Planner-Sisyphus"];
const plannerSisyphusBase = { const plannerSisyphusBase = {
...planConfigWithoutName, ...migratedPlanConfig,
mode: "primary",
prompt: PLAN_SYSTEM_PROMPT, prompt: PLAN_SYSTEM_PROMPT,
permission: PLAN_PERMISSION, permission: PLAN_PERMISSION,
description: `${configAgent?.plan?.description ?? "Plan agent"} (OhMyOpenCode version)`, description: `${configAgent?.plan?.description ?? "Plan agent"} (OhMyOpenCode version)`,
@@ -197,6 +204,14 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
) )
: {}; : {};
const migratedBuild = configAgent?.build
? migrateAgentConfig(configAgent.build as Record<string, unknown>)
: {};
const planDemoteConfig = replacePlan
? { disable: true }
: undefined;
config.agent = { config.agent = {
...agentConfig, ...agentConfig,
...Object.fromEntries( ...Object.fromEntries(
@@ -206,10 +221,8 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
...projectAgents, ...projectAgents,
...pluginAgents, ...pluginAgents,
...filteredConfigAgents, ...filteredConfigAgents,
build: { ...configAgent?.build, mode: "subagent" }, build: { ...migratedBuild, mode: "subagent", hidden: true },
...(replacePlan ...(planDemoteConfig ? { plan: planDemoteConfig } : {}),
? { plan: { ...configAgent?.plan, mode: "subagent" } }
: {}),
}; };
} else { } else {
config.agent = { config.agent = {

View File

@@ -3,6 +3,8 @@ import yaml from "js-yaml"
export interface FrontmatterResult<T = Record<string, unknown>> { export interface FrontmatterResult<T = Record<string, unknown>> {
data: T data: T
body: string body: string
hadFrontmatter: boolean
parseError: boolean
} }
export function parseFrontmatter<T = Record<string, unknown>>( export function parseFrontmatter<T = Record<string, unknown>>(
@@ -12,7 +14,7 @@ export function parseFrontmatter<T = Record<string, unknown>>(
const match = content.match(frontmatterRegex) const match = content.match(frontmatterRegex)
if (!match) { if (!match) {
return { data: {} as T, body: content } return { data: {} as T, body: content, hadFrontmatter: false, parseError: false }
} }
const yamlContent = match[1] const yamlContent = match[1]
@@ -22,8 +24,8 @@ export function parseFrontmatter<T = Record<string, unknown>>(
// Use JSON_SCHEMA for security - prevents code execution via YAML tags // Use JSON_SCHEMA for security - prevents code execution via YAML tags
const parsed = yaml.load(yamlContent, { schema: yaml.JSON_SCHEMA }) const parsed = yaml.load(yamlContent, { schema: yaml.JSON_SCHEMA })
const data = (parsed ?? {}) as T const data = (parsed ?? {}) as T
return { data, body } return { data, body, hadFrontmatter: true, parseError: false }
} catch { } catch {
return { data: {} as T, body } return { data: {} as T, body, hadFrontmatter: true, parseError: true }
} }
} }