diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 888422e7..85219676 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -8,7 +8,7 @@ "name": "claudeclaw", "source": "./", "description": "Cron-like daemon that runs Claude prompts on a schedule", - "version": "1.0.44", + "version": "1.0.45", "keywords": [ "cron", "heartbeat", diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 644babac..cc993e55 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,5 +1,5 @@ { "name": "claudeclaw", - "version": "1.0.44", + "version": "1.0.45", "description": "Cron-like daemon that runs Claude prompts on a schedule" } diff --git a/src/commands/discord.ts b/src/commands/discord.ts index ac023cbf..219289d9 100644 --- a/src/commands/discord.ts +++ b/src/commands/discord.ts @@ -1,4 +1,4 @@ -import { ensureProjectClaudeMd, run, runUserMessage, compactCurrentSession, compactCurrentThreadSession, agentDirKey } from "../runner"; +import { ensureProjectClaudeMd, run, runUserMessage, killActive, compactCurrentSession, compactCurrentThreadSession, agentDirKey } from "../runner"; import { wrapUntrusted } from "../prompt-safety"; import { isAllowed, isDiscordAuthorized } from "../allowlist"; import { extractErrorDetail } from "../messaging"; @@ -498,7 +498,7 @@ Rules: const { execSync } = await import("node:child_process"); const input = `${systemPrompt}\n\n---\nUser message: ${text}`; const result = execSync( - `claude --model claude-sonnet-4-20250514 --print --output-format text`, + `claude --model claude-sonnet-5 --print --output-format text`, { input, encoding: "utf-8", @@ -977,6 +977,18 @@ async function handleMessageCreate(token: string, message: DiscordMessage, skipC // Skill routing: detect slash commands and resolve to SKILL.md prompts const command = cleanContent.startsWith("/") ? cleanContent.trim().split(/\s+/, 1)[0].toLowerCase() : null; + if (command === "/kill" || command === "/stop") { + // killActive() is global: it kills every in-flight main run across all + // Discord channels/threads, not just the caller's. Combined with the + // channel-scoped allowlist (#248), a user authorized in one channel can + // kill runs in channels they aren't authorized for. Matches Telegram's + // existing /kill contract (not a regression); thread-scoped kill is + // tracked separately (see #237). + const killed = killActive(); + await sendMessage(config.token, channelId, killed ? "Killed active agent." : "No active agent running."); + return; + } + let skillContext: string | null = null; if (command) { try {