Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 19 additions & 13 deletions src/cli/__snapshots__/model-fallback.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1425,7 +1425,8 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when
"variant": "xhigh",
},
"multimodal-looker": {
"model": "github-copilot/gpt-5-nano",
"model": "github-copilot/gpt-5.4",
"variant": "medium",
},
"oracle": {
"fallback_models": [
Expand Down Expand Up @@ -1611,7 +1612,8 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with
"variant": "xhigh",
},
"multimodal-looker": {
"model": "github-copilot/gpt-5-nano",
"model": "github-copilot/gpt-5.4",
"variant": "medium",
},
"oracle": {
"fallback_models": [
Expand Down Expand Up @@ -2226,10 +2228,11 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb
"multimodal-looker": {
"fallback_models": [
{
"model": "openai/gpt-5-nano",
"model": "github-copilot/gpt-5.4",
"variant": "medium",
},
{
"model": "github-copilot/gpt-5-nano",
"model": "openai/gpt-5-nano",
},
],
"model": "openai/gpt-5.4",
Expand Down Expand Up @@ -2737,16 +2740,17 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider
"multimodal-looker": {
"fallback_models": [
{
"model": "zai-coding-plan/glm-4.6v",
"model": "opencode/gpt-5.4",
"variant": "medium",
},
{
"model": "github-copilot/gpt-5-nano",
"model": "zai-coding-plan/glm-4.6v",
},
{
"model": "opencode/gpt-5-nano",
},
],
"model": "opencode/gpt-5.4",
"model": "github-copilot/gpt-5.4",
"variant": "medium",
},
"oracle": {
Expand Down Expand Up @@ -3167,6 +3171,10 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe
},
"multimodal-looker": {
"fallback_models": [
{
"model": "github-copilot/gpt-5.4",
"variant": "medium",
},
{
"model": "opencode/gpt-5.4",
"variant": "medium",
Expand All @@ -3177,9 +3185,6 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe
{
"model": "openai/gpt-5-nano",
},
{
"model": "github-copilot/gpt-5-nano",
},
{
"model": "opencode/gpt-5-nano",
},
Expand Down Expand Up @@ -3721,6 +3726,10 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is
},
"multimodal-looker": {
"fallback_models": [
{
"model": "github-copilot/gpt-5.4",
"variant": "medium",
},
{
"model": "opencode/gpt-5.4",
"variant": "medium",
Expand All @@ -3731,9 +3740,6 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is
{
"model": "openai/gpt-5-nano",
},
{
"model": "github-copilot/gpt-5-nano",
},
{
"model": "opencode/gpt-5-nano",
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export async function loadSkillFromPath(options: {
const mcpJsonMcp = await loadMcpJsonFromDir(options.resolvedPath)
const mcpConfig = mcpJsonMcp || frontmatterMcp

const baseName = data.name || options.defaultName
const baseName = data.name == null ? options.defaultName : String(data.name)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fallback to default name when frontmatter name is blank

Using data.name == null ? ... : String(data.name) treats empty-string frontmatter names as valid, so a skill with name: "" now gets registered with an empty command name instead of falling back to the file/directory-derived defaultName. This can create unnamed skills and key collisions during deduplication/lookup (skills.find(s => s.name === name)), whereas the previous || behavior safely used the inferred name for blank values.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fallback when frontmatter name is non-string

Converting every non-null data.name with String(data.name) turns invalid YAML values like name: false into the literal command name "false" instead of using defaultName. Before this change, falsy non-string values fell back to the inferred directory/file name, which avoids accidental collisions and unusable command names when frontmatter is malformed.

Useful? React with 👍 / 👎.

const skillName = namePrefix ? `${namePrefix}/${baseName}` : baseName
const originalDescription = data.description || ""
const isOpencodeSource = options.scope === "opencode" || options.scope === "opencode-project"
Expand Down
28 changes: 28 additions & 0 deletions src/features/opencode-skill-loader/loader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,34 @@ This is a simple skill.
}
})

it("coerces numeric frontmatter names to strings", async () => {
// given
const skillContent = `---
name: 12306
description: Numeric skill name
---
This skill name should still load.
`
createTestSkill("12306", skillContent)

// when
const { discoverSkills } = await import("./loader")
const originalCwd = process.cwd()
process.chdir(TEST_DIR)

try {
const skills = await discoverSkills({ includeClaudeCodePaths: false })
const skill = skills.find(s => s.name === "12306")

// then
expect(skill).toBeDefined()
expect(typeof skill?.name).toBe("string")
expect(skill?.definition.name).toBe("12306")
} finally {
process.chdir(originalCwd)
}
})

it("preserves env var placeholders without expansion", async () => {
// given
const skillContent = `---
Expand Down
4 changes: 2 additions & 2 deletions src/shared/model-requirements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ export const AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
},
"multimodal-looker": {
fallbackChain: [
{ providers: ["openai", "opencode", "vercel"], model: "gpt-5.4", variant: "medium" },
{ providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4", variant: "medium" },
{ providers: ["opencode-go", "vercel"], model: "kimi-k2.5" },
{ providers: ["zai-coding-plan", "vercel"], model: "glm-4.6v" },
{ providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5-nano" },
{ providers: ["openai", "opencode", "vercel"], model: "gpt-5-nano" },
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore a Copilot-capable multimodal fallback

Removing github-copilot from the multimodal-looker gpt-5-nano entry leaves that agent with no matching provider when a user has only Copilot enabled, so generateModelConfig() falls through to ULTIMATE_FALLBACK (opencode/gpt-5-nano) at src/cli/model-fallback.ts:183-190, producing a config that points at an unavailable provider for that environment. I verified this regression by running bun test src/cli/model-fallback.test.ts: this commit introduces snapshot failures in the Copilot-only and mixed-provider scenarios, while the parent commit passes the same test file.

Useful? React with 👍 / 👎.

],
},
prometheus: {
Expand Down
Loading