- Fix P1: Remove dead TOOL_MAP constant (defined but never referenced)
- Fix P1: Replace curl fallback for remote MCP servers with warn-and-skip,
matching the kiro pattern — curl is not an MCP server
- Fix P1: Remove incorrect literal cwd field ("${extensionPath}${/}") from
stdio MCP server config; the value was never interpolated
- Fix P1: Fix plugin.name → plugin.manifest.name in generateContextFile
(plugin.name does not exist on ClaudePlugin; produced "# undefined")
- Fix P1: Wire qwenHome through resolveTargetOutputRoot; previously the
--qwen-home CLI flag was parsed but silently discarded
- Fix P1: Remove hardcoded "compound-engineering" from qwen output path;
now uses plugin.manifest.name via new qwenHome + pluginName params
- Fix P1: Collapse dead-code resolveQwenPaths branches (both returned
identical structures; simplify to a single return)
- Fix P3: Remove rewriting of .opencode/ paths to .qwen/ — Claude plugins
do not reference opencode paths, and rewriting them is incorrect
- Fix P3: inferTemperature now returns undefined for unrecognized agents
instead of 0.3 (matching the explicit doc branch), letting the model
use its default temperature
- Fix P2: Add lookbehind guards to rewriteQwenPaths() matching kiro pattern
to avoid rewriting paths inside compound tokens or URLs
- Update --qwen-home default to ~/.qwen/extensions (plugin name appended)
- Add qwen-converter.test.ts with 16 tests covering all scenarios
Co-Authored-By: Claude <noreply@anthropic.com>
65 lines
2.2 KiB
TypeScript
65 lines
2.2 KiB
TypeScript
import path from "path"
|
|
import { backupFile, copyDir, ensureDir, writeJson, writeText } from "../utils/files"
|
|
import type { QwenBundle, QwenExtensionConfig } from "../types/qwen"
|
|
|
|
export async function writeQwenBundle(outputRoot: string, bundle: QwenBundle): Promise<void> {
|
|
const qwenPaths = resolveQwenPaths(outputRoot)
|
|
await ensureDir(qwenPaths.root)
|
|
|
|
// Write qwen-extension.json config
|
|
const configPath = qwenPaths.configPath
|
|
const backupPath = await backupFile(configPath)
|
|
if (backupPath) {
|
|
console.log(`Backed up existing config to ${backupPath}`)
|
|
}
|
|
await writeJson(configPath, bundle.config)
|
|
|
|
// Write context file (QWEN.md)
|
|
if (bundle.contextFile) {
|
|
await writeText(qwenPaths.contextPath, bundle.contextFile + "\n")
|
|
}
|
|
|
|
// Write agents
|
|
const agentsDir = qwenPaths.agentsDir
|
|
await ensureDir(agentsDir)
|
|
for (const agent of bundle.agents) {
|
|
const ext = agent.format === "yaml" ? "yaml" : "md"
|
|
await writeText(path.join(agentsDir, `${agent.name}.${ext}`), agent.content + "\n")
|
|
}
|
|
|
|
// Write commands
|
|
const commandsDir = qwenPaths.commandsDir
|
|
await ensureDir(commandsDir)
|
|
for (const commandFile of bundle.commandFiles) {
|
|
// Support nested commands with colon separator
|
|
const parts = commandFile.name.split(":")
|
|
if (parts.length > 1) {
|
|
const nestedDir = path.join(commandsDir, ...parts.slice(0, -1))
|
|
await ensureDir(nestedDir)
|
|
await writeText(path.join(nestedDir, `${parts[parts.length - 1]}.md`), commandFile.content + "\n")
|
|
} else {
|
|
await writeText(path.join(commandsDir, `${commandFile.name}.md`), commandFile.content + "\n")
|
|
}
|
|
}
|
|
|
|
// Copy skills
|
|
if (bundle.skillDirs.length > 0) {
|
|
const skillsRoot = qwenPaths.skillsDir
|
|
await ensureDir(skillsRoot)
|
|
for (const skill of bundle.skillDirs) {
|
|
await copyDir(skill.sourceDir, path.join(skillsRoot, skill.name))
|
|
}
|
|
}
|
|
}
|
|
|
|
function resolveQwenPaths(outputRoot: string) {
|
|
return {
|
|
root: outputRoot,
|
|
configPath: path.join(outputRoot, "qwen-extension.json"),
|
|
contextPath: path.join(outputRoot, "QWEN.md"),
|
|
agentsDir: path.join(outputRoot, "agents"),
|
|
commandsDir: path.join(outputRoot, "commands"),
|
|
skillsDir: path.join(outputRoot, "skills"),
|
|
}
|
|
}
|