Skip to content

Commit 42a9f80

Browse files
v0.4.7
# v0.4.7 — Multi-Tier Skill Resolution Fix Targeted bugfix release resolving a critical issue where skills from global (`~/.agents/`) and project-level (`.agents/`) directories failed to invoke despite being visible in the UI. --- ## Bug Fixes - **Skills from global/project directories fail with "Unknown skill"** — The UI discovered skills from all 3 tiers (global, workspace, project) via `loadAllSkills`, but the SDK backend only registered the workspace directory as a plugin. Global and project-level skills were shown as invocable but returned "Unknown skill" when used. Fixed by registering all 3 skill directories as SDK plugins, rewriting `qualifySkillName` to resolve the correct plugin prefix per tier, and fixing the UI mention menu to use the correct plugin qualifier based on skill source (0fb687d5) - **Feature flags not bundled in packaged app** — `feature-flags.ts` was missing from the build script's copy step, causing packaged builds (especially Windows) to fail to load compile-time feature flags (6268fefd, c44899cb) ## Improvements - **GitHub issue templates** — Added structured templates for bug reports and feature requests to the OSS repository (35123388) ## Internal - **sourceTemplates feature flag disabled** — Rolled back to `false` pending further stabilization (9f375b4f)
1 parent 88f28c7 commit 42a9f80

File tree

24 files changed

+254
-47
lines changed

24 files changed

+254
-47
lines changed

apps/electron/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@craft-agent/electron",
3-
"version": "0.4.6",
3+
"version": "0.4.7",
44
"description": "Electron desktop app for Craft Agents",
55
"main": "dist/main.cjs",
66
"private": true,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# v0.4.7 — Multi-Tier Skill Resolution Fix
2+
3+
Targeted bugfix release resolving a critical issue where skills from global (`~/.agents/`) and project-level (`.agents/`) directories failed to invoke despite being visible in the UI.
4+
5+
---
6+
7+
## Bug Fixes
8+
9+
- **Skills from global/project directories fail with "Unknown skill"** — The UI discovered skills from all 3 tiers (global, workspace, project) via `loadAllSkills`, but the SDK backend only registered the workspace directory as a plugin. Global and project-level skills were shown as invocable but returned "Unknown skill" when used. Fixed by registering all 3 skill directories as SDK plugins, rewriting `qualifySkillName` to resolve the correct plugin prefix per tier, and fixing the UI mention menu to use the correct plugin qualifier based on skill source (0fb687d5)
10+
- **Feature flags not bundled in packaged app**`feature-flags.ts` was missing from the build script's copy step, causing packaged builds (especially Windows) to fail to load compile-time feature flags (6268fefd, c44899cb)
11+
12+
## Improvements
13+
14+
- **GitHub issue templates** — Added structured templates for bug reports and feature requests to the OSS repository (35123388)
15+
16+
## Internal
17+
18+
- **sourceTemplates feature flag disabled** — Rolled back to `false` pending further stabilization (9f375b4f)

apps/electron/src/renderer/components/ui/mention-menu.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { FadingText } from '@/components/ui/fading-text'
44
import { SkillAvatar } from '@/components/ui/skill-avatar'
55
import { SourceAvatar } from '@/components/ui/source-avatar'
66
import type { LoadedSkill, LoadedSource, FileSearchResult } from '../../../shared/types'
7+
import { AGENTS_PLUGIN_NAME } from '@craft-agent/shared/skills/types'
78

89
// ============================================================================
910
// Types
@@ -633,8 +634,11 @@ export function useInlineMention({
633634
// Skill tool requires this format to resolve workspace-scoped skills.
634635
let mentionText: string
635636
if (item.type === 'skill') {
636-
// Use fully-qualified name for skills: [skill:workspaceId:slug]
637-
const qualifiedName = workspaceId ? `${workspaceId}:${item.id}` : item.id
637+
// Use fully-qualified name for skills: [skill:pluginName:slug]
638+
// Plugin name depends on which tier the skill came from:
639+
// workspace → workspaceId, project/global → ".agents"
640+
const pluginName = item.skill?.source === 'workspace' ? workspaceId : AGENTS_PLUGIN_NAME
641+
const qualifiedName = pluginName ? `${pluginName}:${item.id}` : item.id
638642
mentionText = `[skill:${qualifiedName}] `
639643
} else if (item.type === 'source') {
640644
mentionText = `[source:${item.id}] `

apps/electron/src/renderer/lib/mentions.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import type { ContentBadge } from '@craft-agent/core'
1212
import type { MentionItemType } from '@/components/ui/mention-menu'
1313
import type { LoadedSkill, LoadedSource } from '../../shared/types'
14+
import { AGENTS_PLUGIN_NAME } from '@craft-agent/shared/skills/types'
1415
import { getSourceIconSync, getSkillIconSync } from './icon-cache'
1516

1617
// Import and re-export parsing functions from shared (pure string operations, no renderer deps)
@@ -209,19 +210,23 @@ export function extractBadges(
209210
const sourceSlugs = sources.map(s => s.config.slug)
210211
const matches = findMentionMatches(text, skillSlugs, sourceSlugs)
211212

213+
// Build lookup maps to avoid linear scans per match
214+
const skillsBySlug = new Map(skills.map(s => [s.slug, s]))
215+
const sourcesBySlug = new Map(sources.map(s => [s.config.slug, s]))
216+
212217
return matches.map(match => {
213218
let label = match.id
214219
let iconDataUrl: string | undefined
215220
let filePath: string | undefined
216221

217222
if (match.type === 'skill') {
218-
const skill = skills.find(s => s.slug === match.id)
223+
const skill = skillsBySlug.get(match.id)
219224
label = skill?.metadata.name || match.id
220225

221226
// Get cached icon as data URL (preserves mime type for SVG, PNG, etc.)
222227
iconDataUrl = getSkillIconSync(workspaceId, match.id) ?? undefined
223228
} else if (match.type === 'source') {
224-
const source = sources.find(s => s.config.slug === match.id)
229+
const source = sourcesBySlug.get(match.id)
225230
label = source?.config.name || match.id
226231

227232
// Get cached icon as data URL (preserves mime type for SVG, PNG, etc.)
@@ -236,12 +241,14 @@ export function extractBadges(
236241
filePath = match.id
237242
}
238243

239-
// For skills, create fully-qualified rawText (workspaceId:slug) so the agent
240-
// receives the correct format for the SDK's Skill tool. The SDK requires
241-
// fully-qualified names to resolve skills. Display label stays as the friendly name.
244+
// For skills, create fully-qualified rawText (pluginName:slug) so the agent
245+
// receives the correct format for the SDK's Skill tool. Plugin name depends
246+
// on which tier the skill came from: workspace → workspaceId, project/global → AGENTS_PLUGIN_NAME
242247
let rawText = match.fullMatch
243248
if (match.type === 'skill') {
244-
rawText = `[skill:${workspaceId}:${match.id}]`
249+
const skill = skillsBySlug.get(match.id)
250+
const pluginName = skill?.source === 'workspace' ? workspaceId : AGENTS_PLUGIN_NAME
251+
rawText = `[skill:${pluginName}:${match.id}]`
245252
}
246253

247254
return {

apps/viewer/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@craft-agent/viewer",
3-
"version": "0.4.6",
3+
"version": "0.4.7",
44
"description": "Web viewer for Craft Agents sessions - upload and share session transcripts",
55
"private": true,
66
"type": "module",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "craft-agent",
3-
"version": "0.4.6",
3+
"version": "0.4.7",
44
"description": "Claude Code-like agent for Craft documents",
55
"type": "module",
66
"private": true,

packages/bridge-mcp-server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@craft-agent/bridge-mcp-server",
3-
"version": "0.4.6",
3+
"version": "0.4.7",
44
"license": "Apache-2.0",
55
"description": "MCP server that bridges API sources to Codex via stdio transport",
66
"type": "commonjs",

packages/codex-types/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@craft-agent/codex-types",
3-
"version": "0.4.6",
3+
"version": "0.4.7",
44
"description": "Generated TypeScript types for Codex app-server protocol",
55
"type": "module",
66
"main": "./src/index.ts",

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@craft-agent/core",
3-
"version": "0.4.6",
3+
"version": "0.4.7",
44
"license": "Apache-2.0",
55
"description": "Core types, storage, and agent logic for Craft Agents",
66
"type": "module",

packages/mermaid/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@craft-agent/mermaid",
3-
"version": "0.4.6",
3+
"version": "0.4.7",
44
"license": "Apache-2.0",
55
"description": "Mermaid flowchart to styled SVG renderer with zinc monochrome palette",
66
"type": "module",

0 commit comments

Comments
 (0)