feat: Claw can send arbitrary WhatsApp messages to personal number on command
This commit is contained in:
parent
08a18e825c
commit
b6851ace08
|
|
@ -36,7 +36,7 @@ export default function Page() {
|
||||||
const [messages, setMessages] = useState([
|
const [messages, setMessages] = useState([
|
||||||
{
|
{
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
content: "Hello! I am Claw, your local agent. I have access to your Kubernetes namespace and Proxmox cluster nodes. Try asking me: `weather`, `check k8s pods`, or `diagnose proxmox container 102`.",
|
content: "Hello! I am Claw, your local agent. Try asking me:\n• `weather` — live weather for Mars, PA\n• `whatsapp me: your message` — send anything to your phone\n• `check k8s pods` — Kubernetes diagnostics\n• `diagnose proxmox container 102` — disk & resource check",
|
||||||
timestamp: "Just now"
|
timestamp: "Just now"
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
@ -118,7 +118,41 @@ export default function Page() {
|
||||||
|
|
||||||
const cleanInput = userText.toLowerCase();
|
const cleanInput = userText.toLowerCase();
|
||||||
|
|
||||||
if (cleanInput.includes("weather")) {
|
// ── WhatsApp Send Command ────────────────────────────────────────────────
|
||||||
|
// Matches: "whatsapp me: ...", "send to whatsapp ...", "message me ...",
|
||||||
|
// "text me ...", "wa me ...", "send 'X' to my whatsapp"
|
||||||
|
const waIntent = /(?:whatsapp\s+me|message\s+me|text\s+me|send\s+(?:to\s+)?(?:my\s+)?whatsapp|wa\s+me|remind\s+me\s+via\s+whatsapp)[:\s]+(.+)/i;
|
||||||
|
const waMatch = userText.match(waIntent);
|
||||||
|
|
||||||
|
if (waMatch) {
|
||||||
|
const waMsg = waMatch[1].replace(/^["'`]|["'`]$/g, '').trim(); // strip surrounding quotes
|
||||||
|
|
||||||
|
setClawTerminalLogs(prev => [...prev,
|
||||||
|
`[Claw] WhatsApp send detected. Message: "${waMsg}"`,
|
||||||
|
`[Claw] Calling /api/send-whatsapp (personalOnly) ...`
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/send-whatsapp', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ message: `📌 *Claw Reminder*\n\n${waMsg}`, personalOnly: true }),
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (data.success) {
|
||||||
|
setClawTerminalLogs(prev => [...prev, `[Claw] ✅ Delivered to +14085505485. MsgID: ${data.messageId}`]);
|
||||||
|
responseText = `✅ Done! I've sent that to your WhatsApp (+14085505485):\n\n> "${waMsg}"\n\nYou should see it arrive shortly.`;
|
||||||
|
} else {
|
||||||
|
throw new Error(data.error || 'Gateway error');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setClawTerminalLogs(prev => [...prev, `[Claw] ❌ WhatsApp send failed: ${err.message}`]);
|
||||||
|
responseText = `❌ Couldn't send to WhatsApp: ${err.message}. Make sure the gateway is running.`;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (cleanInput.includes("weather")) {
|
||||||
|
|
||||||
// Extract optional location override
|
// Extract optional location override
|
||||||
const locMatch = userText.match(/(?:weather\s+(?:in|for|at)?\s*)(.+)/i);
|
const locMatch = userText.match(/(?:weather\s+(?:in|for|at)?\s*)(.+)/i);
|
||||||
const location = locMatch ? locMatch[1].trim() : '16046';
|
const location = locMatch ? locMatch[1].trim() : '16046';
|
||||||
|
|
@ -700,7 +734,7 @@ export default function Page() {
|
||||||
type="text"
|
type="text"
|
||||||
value={inputValue}
|
value={inputValue}
|
||||||
onChange={(e) => setInputValue(e.target.value)}
|
onChange={(e) => setInputValue(e.target.value)}
|
||||||
placeholder="Ask Claw: e.g. 'check pods' or 'check disk VMID 102'..."
|
placeholder="e.g. 'weather', 'whatsapp me: call doctor at 3pm', 'check k8s pods'..."
|
||||||
style={{ flex: 1, padding: "12px 16px", border: "1px solid var(--border-color)", borderRadius: "8px", background: "var(--bg-secondary)", color: "var(--text-primary)", outline: "none", fontSize: "14px" }}
|
style={{ flex: 1, padding: "12px 16px", border: "1px solid var(--border-color)", borderRadius: "8px", background: "var(--bg-secondary)", color: "var(--text-primary)", outline: "none", fontSize: "14px" }}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue