| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- import type { Part } from "@kirincode-ai/sdk"
- import type { MemoryStore } from "./memory"
- import type { SkillRegistry } from "./skills"
- let partSeq = 0
- function textPart(text: string, sessionID: string): Part {
- const id = `kc_part_${Date.now()}_${partSeq++}`
- return { id, sessionID, messageID: id, type: "text", text }
- }
- export async function handleMemoryCommand(args: string, store: MemoryStore, sessionID: string): Promise<Part[]> {
- const sub = args.trim()
- if (!sub || sub === "list") {
- return [textPart(store.format(), sessionID)]
- }
- if (sub.startsWith("read ")) {
- const topic = sub.slice(5).trim()
- const content = store.readTopic(topic)
- return [textPart(content || `No topic '${topic}' found. Topics: ${store.listTopics().join(", ") || "none"}`, sessionID)]
- }
- if (sub.startsWith("write ")) {
- const rest = sub.slice(6).trim()
- const spaceIdx = rest.indexOf(" ")
- if (spaceIdx === -1) return [textPart("Usage: /memory write <topic> <content>", sessionID)]
- const topic = rest.slice(0, spaceIdx)
- const content = rest.slice(spaceIdx + 1)
- store.writeTopic(topic, content)
- return [textPart(`Topic '${topic}' saved.`, sessionID)]
- }
- return [textPart("Usage: /memory [list|read <topic>|write <topic> <content>]", sessionID)]
- }
- export async function handleSkillCommand(args: string, registry: SkillRegistry, worktree: string, sessionID: string): Promise<Part[]> {
- const sub = args.trim()
- if (!sub || sub === "list") {
- const skills = registry.list()
- if (skills.length === 0) return [textPart("No skills registered. Use `/skill create <name> <description>` to create one.", sessionID)]
- const lines = skills.map((s) => `- **/${s.manifest.name}** [${s.scope}] — ${s.manifest.description}`)
- return [textPart(lines.join("\n"), sessionID)]
- }
- if (sub.startsWith("create ")) {
- const rest = sub.slice(7).trim()
- const firstQuote = rest.match(/["'](.+?)["']/)
- if (firstQuote) {
- const name = firstQuote[1] ?? ""
- if (!name) return [textPart("Could not parse skill name from quoted string.", sessionID)]
- const desc = rest.slice((firstQuote[0] ?? "").length).trim().replace(/^["'](.+?)["']/, "$1")
- const path = registry.createSkill(name, desc, `# ${name}\n\nTODO: Write skill instructions here.`, "project", worktree)
- registry.load(worktree)
- return [textPart(`Skill '/${name}' created at ${path}\nEdit the file to add instructions, then use /skill ${name} to invoke.`, sessionID)]
- }
- const parts = rest.split(/\s+/)
- if (parts.length < 2) return [textPart("Usage: /skill create <name> <description>", sessionID)]
- const name = parts[0] ?? ""
- if (!name) return [textPart("Usage: /skill create <name> <description>", sessionID)]
- const desc = parts.slice(1).join(" ")
- const path = registry.createSkill(name, desc, `# ${name}\n\nTODO: Write skill instructions here.`, "project", worktree)
- registry.load(worktree)
- return [textPart(`Skill '/${name}' created at ${path}`, sessionID)]
- }
- if (sub === "reload") {
- registry.load(worktree)
- return [textPart(`Skills reloaded. ${registry.list().length} skill(s) available.`, sessionID)]
- }
- // Treat as skill name invocation
- const content = registry.injectSkill(sub)
- return [textPart(content, sessionID)]
- }
|