System skills were failing to execute with the error:
SyntaxError: Unexpected identifier 'not'
This occurred because the skill execution system was trying to execute the string "File not found" as JavaScript code.
- User registers a skill in their namespace (e.g.,
ns_k0ro71) withfileKey: "my-skill.js" - Admin promotes the skill to system-wide availability
- System skill is stored with the original
fileKey: "my-skill.js"(from the user's namespace) - Another user tries to execute the system skill
- Skill execution calls
handleCodeExec({ key: skill.fileKey, input: args }, authContext) - File retrieval fails because it tries to fetch
"my-skill.js"from the current user's namespace, not the original user's namespace where the file actually exists - Files handler returns
"File not found"as the content - Code execution tries to execute the string
"File not found"as JavaScript code - VM throws syntax error
SyntaxError: Unexpected identifier 'not'because"File not found"is not valid JavaScript
System skills store the original user's fileKey, but when executed, they try to fetch the file from the current user's namespace instead of the original user's namespace.
Approach: When promoting a skill, copy the file content and store it in the system folder (system/skills/skillName.js)
Benefits:
- ✅ Complete isolation from original user
- ✅ System skills work independently
- ✅ No namespace confusion
- ✅ Consistent with system-wide availability concept
- ✅ Files are accessible to all users via system folder
Trade-offs:
- File content is duplicated
- Updates require explicit admin action via
admin-update-promoted-skill
-
src/storage/skill-registry.ts:- Updated
promoteSkillToSystem()to accept afilesStoreparameter - Added file copying logic to copy skill file to
system/skills/skillName.js - Updated
fileKeyin promoted skill to point to system folder - Updated
updatePromotedSkill()to sync file content from original user - Updated
demoteSkillFromSystem()to clean up system files
- Updated
-
src/tools/handlers/admin-tools.ts:- Updated constructor to accept S3 client and bucket name
- Modified admin handlers to create
NamespacedFilesStoreinstances - Updated promotion/demotion/update handlers to pass files store to skill registry
-
src/mcp/handler.ts:- Updated admin handler instantiation to pass S3 client and bucket name
// Copy the skill file to system folder
systemFileKey = `system/skills/${skillName}.js`;
// Store the file content in the system folder using admin context
await filesStore.putWithSystemFolder(
systemFileKey,
originalFile.content,
originalFile.contentType || 'application/javascript',
{
originalFileKey: userSkill.fileKey,
originalNamespace: userNamespace,
promotedBy: authContext.namespace,
promotedAt: new Date().toISOString(),
skillName: skillName
},
authContext
);
const promotedSkillDefinition: SkillDefinition = {
...userSkill,
fileKey: systemFileKey, // Use the system file key instead of original
isSystemSkill: true,
promotedFrom: userNamespace,
promotedAt: now,
promotedBy: authContext.namespace,
updatedAt: now,
};
The fix has been implemented and the server compiles successfully. The system now:
- Promotes skills correctly: Copies file content to system folder during promotion
- Executes system skills reliably: Uses system folder files that are accessible to all users
- Updates promoted skills: Syncs latest content from original user to system folder
- Cleans up properly: Removes system files when skills are demoted
curl -X POST https://your-server/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-admin-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "admin-promote-skill", "arguments": { "userNamespace": "user123", "skillName": "my-skill" } }, "id": 1 }'
curl -X POST https://your-server/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-admin-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "admin-update-promoted-skill", "arguments": { "skillName": "my-skill" } }, "id": 1 }'
System skills now execute reliably without namespace-related file access issues. The file isolation ensures that promoted skills work consistently for all users, regardless of the original user's namespace or file availability.