Skip to content
Merged
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
5 changes: 3 additions & 2 deletions src/targets/droid.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from "path"
import { copyDir, ensureDir, writeText } from "../utils/files"
import { copyDir, ensureDir, resolveCommandPath, writeText } from "../utils/files"
import type { DroidBundle } from "../types/droid"

export async function writeDroidBundle(outputRoot: string, bundle: DroidBundle): Promise<void> {
Expand All @@ -9,7 +9,8 @@ export async function writeDroidBundle(outputRoot: string, bundle: DroidBundle):
if (bundle.commands.length > 0) {
await ensureDir(paths.commandsDir)
for (const command of bundle.commands) {
await writeText(path.join(paths.commandsDir, `${command.name}.md`), command.content + "\n")
const dest = await resolveCommandPath(paths.commandsDir, command.name, ".md")
await writeText(dest, command.content + "\n")
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/targets/gemini.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from "path"
import { backupFile, copyDir, ensureDir, pathExists, readJson, writeJson, writeText } from "../utils/files"
import { backupFile, copyDir, ensureDir, pathExists, readJson, resolveCommandPath, writeJson, writeText } from "../utils/files"
import type { GeminiBundle } from "../types/gemini"

export async function writeGeminiBundle(outputRoot: string, bundle: GeminiBundle): Promise<void> {
Expand All @@ -20,7 +20,8 @@ export async function writeGeminiBundle(outputRoot: string, bundle: GeminiBundle

if (bundle.commands.length > 0) {
for (const command of bundle.commands) {
await writeText(path.join(paths.commandsDir, `${command.name}.toml`), command.content + "\n")
const dest = await resolveCommandPath(paths.commandsDir, command.name, ".toml")
await writeText(dest, command.content + "\n")
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/targets/opencode.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from "path"
import { backupFile, copyDir, ensureDir, pathExists, readJson, writeJson, writeText } from "../utils/files"
import { backupFile, copyDir, ensureDir, pathExists, readJson, resolveCommandPath, writeJson, writeText } from "../utils/files"
import type { OpenCodeBundle, OpenCodeConfig } from "../types/opencode"

// Merges plugin config into existing opencode.json. User keys win on conflict. See ADR-002.
Expand Down Expand Up @@ -75,7 +75,7 @@ export async function writeOpenCodeBundle(outputRoot: string, bundle: OpenCodeBu
}

for (const commandFile of bundle.commandFiles) {
const dest = path.join(openCodePaths.commandDir, `${commandFile.name}.md`)
const dest = await resolveCommandPath(openCodePaths.commandDir, commandFile.name, ".md")
const cmdBackupPath = await backupFile(dest)
if (cmdBackupPath) {
console.log(`Backed up existing command file to ${cmdBackupPath}`)
Expand Down
13 changes: 3 additions & 10 deletions src/targets/qwen.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from "path"
import { backupFile, copyDir, ensureDir, writeJson, writeText } from "../utils/files"
import { backupFile, copyDir, ensureDir, resolveCommandPath, writeJson, writeText } from "../utils/files"
import type { QwenBundle, QwenExtensionConfig } from "../types/qwen"

export async function writeQwenBundle(outputRoot: string, bundle: QwenBundle): Promise<void> {
Expand Down Expand Up @@ -31,15 +31,8 @@ export async function writeQwenBundle(outputRoot: string, bundle: QwenBundle): P
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")
}
const dest = await resolveCommandPath(commandsDir, commandFile.name, ".md")
await writeText(dest, commandFile.content + "\n")
}

// Copy skills
Expand Down
15 changes: 15 additions & 0 deletions src/utils/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,21 @@ export async function walkFiles(root: string): Promise<string[]> {
return results
}

/**
* Resolve a colon-separated command name into a filesystem path.
* e.g. resolveCommandPath("/commands", "ce:plan", ".md") -> "/commands/ce/plan.md"
* Creates intermediate directories as needed.
*/
export async function resolveCommandPath(dir: string, name: string, ext: string): Promise<string> {
const parts = name.split(":")
if (parts.length > 1) {
const nestedDir = path.join(dir, ...parts.slice(0, -1))
await ensureDir(nestedDir)
return path.join(nestedDir, `${parts[parts.length - 1]}${ext}`)
}
return path.join(dir, `${name}${ext}`)
}

export async function copyDir(sourceDir: string, targetDir: string): Promise<void> {
await ensureDir(targetDir)
const entries = await fs.readdir(sourceDir, { withFileTypes: true })
Expand Down
Loading