Compare commits
1 Commits
feat/git-m
...
fix/issue-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
deef9d864b |
59
src/features/claude-code-command-loader/loader.test.ts
Normal file
59
src/features/claude-code-command-loader/loader.test.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/// <reference types="bun-types" />
|
||||||
|
|
||||||
|
import { afterEach, describe, expect, it } from "bun:test"
|
||||||
|
import { mkdirSync, rmSync, writeFileSync } from "node:fs"
|
||||||
|
import { tmpdir } from "node:os"
|
||||||
|
import { join } from "node:path"
|
||||||
|
import { loadOpencodeGlobalCommands, loadOpencodeProjectCommands } from "./loader"
|
||||||
|
|
||||||
|
const testRoots: string[] = []
|
||||||
|
|
||||||
|
function createTempRoot(): string {
|
||||||
|
const root = join(tmpdir(), `command-loader-${Date.now()}-${Math.random().toString(16).slice(2)}`)
|
||||||
|
mkdirSync(root, { recursive: true })
|
||||||
|
testRoots.push(root)
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeCommand(dir: string, name: string): void {
|
||||||
|
mkdirSync(dir, { recursive: true })
|
||||||
|
writeFileSync(
|
||||||
|
join(dir, `${name}.md`),
|
||||||
|
"---\ndescription: command from test\n---\nUse this command"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
for (const root of testRoots.splice(0)) {
|
||||||
|
rmSync(root, { recursive: true, force: true })
|
||||||
|
}
|
||||||
|
delete process.env.OPENCODE_CONFIG_DIR
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("claude-code-command-loader OpenCode paths", () => {
|
||||||
|
it("loads commands from global OpenCode commands directory", async () => {
|
||||||
|
// given
|
||||||
|
const root = createTempRoot()
|
||||||
|
const opencodeConfigDir = join(root, "config")
|
||||||
|
writeCommand(join(opencodeConfigDir, "commands"), "global-opencode")
|
||||||
|
process.env.OPENCODE_CONFIG_DIR = opencodeConfigDir
|
||||||
|
|
||||||
|
// when
|
||||||
|
const commands = await loadOpencodeGlobalCommands()
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(commands["global-opencode"]).toBeDefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("loads commands from project OpenCode commands directory", async () => {
|
||||||
|
// given
|
||||||
|
const root = createTempRoot()
|
||||||
|
writeCommand(join(root, ".opencode", "commands"), "project-opencode")
|
||||||
|
|
||||||
|
// when
|
||||||
|
const commands = await loadOpencodeProjectCommands(root)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(commands["project-opencode"]).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -122,13 +122,13 @@ export async function loadProjectCommands(directory?: string): Promise<Record<st
|
|||||||
|
|
||||||
export async function loadOpencodeGlobalCommands(): Promise<Record<string, CommandDefinition>> {
|
export async function loadOpencodeGlobalCommands(): Promise<Record<string, CommandDefinition>> {
|
||||||
const configDir = getOpenCodeConfigDir({ binary: "opencode" })
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" })
|
||||||
const opencodeCommandsDir = join(configDir, "command")
|
const opencodeCommandsDir = join(configDir, "commands")
|
||||||
const commands = await loadCommandsFromDir(opencodeCommandsDir, "opencode")
|
const commands = await loadCommandsFromDir(opencodeCommandsDir, "opencode")
|
||||||
return commandsToRecord(commands)
|
return commandsToRecord(commands)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadOpencodeProjectCommands(directory?: string): Promise<Record<string, CommandDefinition>> {
|
export async function loadOpencodeProjectCommands(directory?: string): Promise<Record<string, CommandDefinition>> {
|
||||||
const opencodeProjectDir = join(directory ?? process.cwd(), ".opencode", "command")
|
const opencodeProjectDir = join(directory ?? process.cwd(), ".opencode", "commands")
|
||||||
const commands = await loadCommandsFromDir(opencodeProjectDir, "opencode-project")
|
const commands = await loadCommandsFromDir(opencodeProjectDir, "opencode-project")
|
||||||
return commandsToRecord(commands)
|
return commandsToRecord(commands)
|
||||||
}
|
}
|
||||||
|
|||||||
63
src/hooks/auto-slash-command/executor.test.ts
Normal file
63
src/hooks/auto-slash-command/executor.test.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/// <reference types="bun-types" />
|
||||||
|
|
||||||
|
import { afterEach, describe, expect, it } from "bun:test"
|
||||||
|
import { mkdirSync, rmSync, writeFileSync } from "node:fs"
|
||||||
|
import { tmpdir } from "node:os"
|
||||||
|
import { join } from "node:path"
|
||||||
|
import { executeSlashCommand } from "./executor"
|
||||||
|
|
||||||
|
const testRoots: string[] = []
|
||||||
|
|
||||||
|
function createTempRoot(): string {
|
||||||
|
const root = join(tmpdir(), `auto-slash-executor-${Date.now()}-${Math.random().toString(16).slice(2)}`)
|
||||||
|
mkdirSync(root, { recursive: true })
|
||||||
|
testRoots.push(root)
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeCommand(dir: string, name: string): void {
|
||||||
|
mkdirSync(dir, { recursive: true })
|
||||||
|
writeFileSync(
|
||||||
|
join(dir, `${name}.md`),
|
||||||
|
"---\ndescription: command from test\n---\nRun from OpenCode command directory"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
for (const root of testRoots.splice(0)) {
|
||||||
|
rmSync(root, { recursive: true, force: true })
|
||||||
|
}
|
||||||
|
delete process.env.OPENCODE_CONFIG_DIR
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("auto-slash-command executor OpenCode paths", () => {
|
||||||
|
it("resolves commands from OpenCode global and project plural directories", async () => {
|
||||||
|
// given
|
||||||
|
const root = createTempRoot()
|
||||||
|
const opencodeConfigDir = join(root, "config")
|
||||||
|
writeCommand(join(opencodeConfigDir, "commands"), "global-cmd")
|
||||||
|
writeCommand(join(root, ".opencode", "commands"), "project-cmd")
|
||||||
|
process.env.OPENCODE_CONFIG_DIR = opencodeConfigDir
|
||||||
|
|
||||||
|
const originalCwd = process.cwd()
|
||||||
|
process.chdir(root)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// when
|
||||||
|
const globalResult = await executeSlashCommand(
|
||||||
|
{ command: "global-cmd", args: "", raw: "/global-cmd" },
|
||||||
|
{ skills: [] }
|
||||||
|
)
|
||||||
|
const projectResult = await executeSlashCommand(
|
||||||
|
{ command: "project-cmd", args: "", raw: "/project-cmd" },
|
||||||
|
{ skills: [] }
|
||||||
|
)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(globalResult.success).toBe(true)
|
||||||
|
expect(projectResult.success).toBe(true)
|
||||||
|
} finally {
|
||||||
|
process.chdir(originalCwd)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -105,8 +105,8 @@ async function discoverAllCommands(options?: ExecutorOptions): Promise<CommandIn
|
|||||||
const configDir = getOpenCodeConfigDir({ binary: "opencode" })
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" })
|
||||||
const userCommandsDir = join(getClaudeConfigDir(), "commands")
|
const userCommandsDir = join(getClaudeConfigDir(), "commands")
|
||||||
const projectCommandsDir = join(process.cwd(), ".claude", "commands")
|
const projectCommandsDir = join(process.cwd(), ".claude", "commands")
|
||||||
const opencodeGlobalDir = join(configDir, "command")
|
const opencodeGlobalDir = join(configDir, "commands")
|
||||||
const opencodeProjectDir = join(process.cwd(), ".opencode", "command")
|
const opencodeProjectDir = join(process.cwd(), ".opencode", "commands")
|
||||||
|
|
||||||
const userCommands = discoverCommandsFromDir(userCommandsDir, "user")
|
const userCommands = discoverCommandsFromDir(userCommandsDir, "user")
|
||||||
const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode")
|
const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode")
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ export function discoverCommandsSync(directory?: string): CommandInfo[] {
|
|||||||
const configDir = getOpenCodeConfigDir({ binary: "opencode" })
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" })
|
||||||
const userCommandsDir = join(getClaudeConfigDir(), "commands")
|
const userCommandsDir = join(getClaudeConfigDir(), "commands")
|
||||||
const projectCommandsDir = join(directory ?? process.cwd(), ".claude", "commands")
|
const projectCommandsDir = join(directory ?? process.cwd(), ".claude", "commands")
|
||||||
const opencodeGlobalDir = join(configDir, "command")
|
const opencodeGlobalDir = join(configDir, "commands")
|
||||||
const opencodeProjectDir = join(directory ?? process.cwd(), ".opencode", "command")
|
const opencodeProjectDir = join(directory ?? process.cwd(), ".opencode", "commands")
|
||||||
|
|
||||||
const userCommands = discoverCommandsFromDir(userCommandsDir, "user")
|
const userCommands = discoverCommandsFromDir(userCommandsDir, "user")
|
||||||
const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode")
|
const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode")
|
||||||
|
|||||||
@@ -1,6 +1,27 @@
|
|||||||
import { describe, expect, it } from "bun:test"
|
/// <reference types="bun-types" />
|
||||||
|
|
||||||
|
import { afterEach, describe, expect, it } from "bun:test"
|
||||||
|
import { mkdirSync, rmSync, writeFileSync } from "node:fs"
|
||||||
|
import { tmpdir } from "node:os"
|
||||||
|
import { join } from "node:path"
|
||||||
import * as slashcommand from "./index"
|
import * as slashcommand from "./index"
|
||||||
|
|
||||||
|
const testRoots: string[] = []
|
||||||
|
|
||||||
|
function createTempRoot(): string {
|
||||||
|
const root = join(tmpdir(), `slashcommand-discovery-${Date.now()}-${Math.random().toString(16).slice(2)}`)
|
||||||
|
mkdirSync(root, { recursive: true })
|
||||||
|
testRoots.push(root)
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
for (const root of testRoots.splice(0)) {
|
||||||
|
rmSync(root, { recursive: true, force: true })
|
||||||
|
}
|
||||||
|
delete process.env.OPENCODE_CONFIG_DIR
|
||||||
|
})
|
||||||
|
|
||||||
describe("slashcommand module exports", () => {
|
describe("slashcommand module exports", () => {
|
||||||
it("exports discovery API only", () => {
|
it("exports discovery API only", () => {
|
||||||
// given
|
// given
|
||||||
@@ -14,4 +35,32 @@ describe("slashcommand module exports", () => {
|
|||||||
expect(exportNames).not.toContain("createSlashcommandTool")
|
expect(exportNames).not.toContain("createSlashcommandTool")
|
||||||
expect(exportNames).not.toContain("slashcommand")
|
expect(exportNames).not.toContain("slashcommand")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("discovers commands from OpenCode plural command directories", () => {
|
||||||
|
// given
|
||||||
|
const root = createTempRoot()
|
||||||
|
const opencodeConfigDir = join(root, "config")
|
||||||
|
const globalCommandsDir = join(opencodeConfigDir, "commands")
|
||||||
|
const projectCommandsDir = join(root, ".opencode", "commands")
|
||||||
|
|
||||||
|
mkdirSync(globalCommandsDir, { recursive: true })
|
||||||
|
mkdirSync(projectCommandsDir, { recursive: true })
|
||||||
|
|
||||||
|
writeFileSync(
|
||||||
|
join(globalCommandsDir, "global-cmd.md"),
|
||||||
|
"---\ndescription: global command\n---\nGlobal command body"
|
||||||
|
)
|
||||||
|
writeFileSync(
|
||||||
|
join(projectCommandsDir, "project-cmd.md"),
|
||||||
|
"---\ndescription: project command\n---\nProject command body"
|
||||||
|
)
|
||||||
|
process.env.OPENCODE_CONFIG_DIR = opencodeConfigDir
|
||||||
|
|
||||||
|
// when
|
||||||
|
const commands = slashcommand.discoverCommandsSync(root)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(commands.some((cmd) => cmd.name === "global-cmd" && cmd.scope === "opencode")).toBe(true)
|
||||||
|
expect(commands.some((cmd) => cmd.name === "project-cmd" && cmd.scope === "opencode-project")).toBe(true)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user