@hoverlover/cc-discord 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/scripts/channel-agent.sh
CHANGED
|
@@ -88,6 +88,41 @@ export AGENT_ID="$CHANNEL_ID"
|
|
|
88
88
|
export CLAUDE_AGENT_ID="${CLAUDE_AGENT_ID:-claude-discord}"
|
|
89
89
|
export CLAUDE_RUNTIME_ID="${CLAUDE_RUNTIME_ID:-rt_$(date +%s)_${RANDOM}}"
|
|
90
90
|
|
|
91
|
+
# Determine Claude's project directory (where .claude/skills/ are discovered).
|
|
92
|
+
# - CC_DISCORD_HOME overrides everything
|
|
93
|
+
# - If cwd has a .claude/ directory (local dev / bun start from repo), use cwd
|
|
94
|
+
# - Otherwise default to ~/.cc-discord (bunx / installed package)
|
|
95
|
+
if [ -n "${CC_DISCORD_HOME:-}" ]; then
|
|
96
|
+
CLAUDE_PROJECT_DIR="$CC_DISCORD_HOME"
|
|
97
|
+
elif [ -d ".claude" ]; then
|
|
98
|
+
CLAUDE_PROJECT_DIR="$(pwd)"
|
|
99
|
+
else
|
|
100
|
+
CLAUDE_PROJECT_DIR="$HOME/.cc-discord"
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
mkdir -p "$CLAUDE_PROJECT_DIR/.claude/skills"
|
|
104
|
+
|
|
105
|
+
# Seed built-in skills from the package into the project directory.
|
|
106
|
+
# Only copies skills that don't already exist (user modifications are preserved).
|
|
107
|
+
if [ -d "$ROOT_DIR/.claude/skills" ] && [ "$ROOT_DIR" != "$CLAUDE_PROJECT_DIR" ]; then
|
|
108
|
+
for skill_dir in "$ROOT_DIR/.claude/skills"/*/; do
|
|
109
|
+
skill_name="$(basename "$skill_dir")"
|
|
110
|
+
if [ ! -d "$CLAUDE_PROJECT_DIR/.claude/skills/$skill_name" ]; then
|
|
111
|
+
cp -r "$skill_dir" "$CLAUDE_PROJECT_DIR/.claude/skills/$skill_name"
|
|
112
|
+
echo "[channel-agent:$CHANNEL_NAME] Seeded skill: $skill_name"
|
|
113
|
+
fi
|
|
114
|
+
done
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
# Copy settings.json into the project dir so Claude sees it as a project config.
|
|
118
|
+
if [ "$ROOT_DIR" != "$CLAUDE_PROJECT_DIR" ] && [ -f "$SETTINGS_PATH" ]; then
|
|
119
|
+
mkdir -p "$CLAUDE_PROJECT_DIR/.claude"
|
|
120
|
+
cp "$SETTINGS_PATH" "$CLAUDE_PROJECT_DIR/.claude/settings.json"
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
cd "$CLAUDE_PROJECT_DIR"
|
|
124
|
+
echo "[channel-agent:$CHANNEL_NAME] Claude project dir: $CLAUDE_PROJECT_DIR"
|
|
125
|
+
|
|
91
126
|
# Build the channel-specific system prompt
|
|
92
127
|
SYSTEM_PROMPT="$(sed \
|
|
93
128
|
-e "s|__CHANNEL_ID__|${CHANNEL_ID}|g" \
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Send an iMessage via macOS Messages.app using AppleScript.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* send-imessage --to "+14175551234" "Hello from Alfred!"
|
|
8
|
+
* send-imessage --to "+14175551234" --sms "This goes as SMS"
|
|
9
|
+
* send-imessage --to "user@icloud.com" "Hello via Apple ID"
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { $ } from "bun";
|
|
13
|
+
|
|
14
|
+
const args = process.argv.slice(2);
|
|
15
|
+
let to: string | null = null;
|
|
16
|
+
let useSms = false;
|
|
17
|
+
const textParts: string[] = [];
|
|
18
|
+
|
|
19
|
+
for (let i = 0; i < args.length; i++) {
|
|
20
|
+
const arg = args[i];
|
|
21
|
+
if (arg === "--to" && args[i + 1]) {
|
|
22
|
+
to = args[++i];
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (arg === "--sms") {
|
|
26
|
+
useSms = true;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (arg === "--help" || arg === "-h") {
|
|
30
|
+
console.log(`
|
|
31
|
+
Usage: send-imessage --to <phone_or_appleid> [--sms] "message"
|
|
32
|
+
|
|
33
|
+
Options:
|
|
34
|
+
--to Phone number (with country code, e.g. +14175551234) or Apple ID email
|
|
35
|
+
--sms Force SMS instead of iMessage (uses SMS service)
|
|
36
|
+
|
|
37
|
+
Examples:
|
|
38
|
+
send-imessage --to "+14175551234" "Hello!"
|
|
39
|
+
send-imessage --to "user@icloud.com" "Hey there"
|
|
40
|
+
send-imessage --to "+14175551234" --sms "SMS fallback"
|
|
41
|
+
`);
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
textParts.push(arg);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const message = textParts.join(" ").trim();
|
|
48
|
+
|
|
49
|
+
if (!to) {
|
|
50
|
+
console.error("Error: --to is required. Use --help for usage.");
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!message) {
|
|
55
|
+
console.error("Error: message text is required. Use --help for usage.");
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Normalize phone number: ensure it starts with +1 if it's a 10-digit US number
|
|
60
|
+
let normalizedTo = to;
|
|
61
|
+
if (/^\d{10}$/.test(to)) {
|
|
62
|
+
normalizedTo = `+1${to}`;
|
|
63
|
+
} else if (/^1\d{10}$/.test(to)) {
|
|
64
|
+
normalizedTo = `+${to}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Escape single quotes for AppleScript
|
|
68
|
+
const escapedMessage = message.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
69
|
+
const escapedTo = normalizedTo.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
70
|
+
|
|
71
|
+
// Build AppleScript
|
|
72
|
+
const serviceFilter = useSms
|
|
73
|
+
? 'service type = SMS'
|
|
74
|
+
: 'service type = iMessage';
|
|
75
|
+
|
|
76
|
+
const script = `tell application "Messages" to send "${escapedMessage}" to buddy "${escapedTo}" of (1st service whose ${serviceFilter})`;
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const result = await $`osascript -e ${script}`.quiet();
|
|
80
|
+
|
|
81
|
+
if (result.exitCode !== 0) {
|
|
82
|
+
const stderr = result.stderr.toString().trim();
|
|
83
|
+
console.error(`Failed to send iMessage: ${stderr}`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log(`iMessage sent to ${normalizedTo}: "${message}"`);
|
|
88
|
+
process.exit(0);
|
|
89
|
+
} catch (err: unknown) {
|
|
90
|
+
const error = err as Error & { stderr?: Buffer };
|
|
91
|
+
const stderr = error.stderr?.toString().trim() || error.message;
|
|
92
|
+
console.error(`Failed to send iMessage: ${stderr}`);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export {};
|