whatsapp config
This commit is contained in:
parent
bedf4c71b8
commit
6210fb9b39
|
|
@ -60,7 +60,10 @@ spec:
|
||||||
- name: PERSONAL_NUM
|
- name: PERSONAL_NUM
|
||||||
value: "+14085505485"
|
value: "+14085505485"
|
||||||
- name: GROUP_URL
|
- name: GROUP_URL
|
||||||
value: "https://chat.whatsapp.com/FXO0SCLA8DpJwClNNWdhhx"
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: whatsapp-config
|
||||||
|
key: default-group-url
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: app-volume
|
- name: app-volume
|
||||||
mountPath: /app
|
mountPath: /app
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,10 @@ spec:
|
||||||
- name: PERSONAL_NUM
|
- name: PERSONAL_NUM
|
||||||
value: "+14085505485"
|
value: "+14085505485"
|
||||||
- name: GROUP_URL
|
- name: GROUP_URL
|
||||||
value: "https://chat.whatsapp.com/FXO0SCLA8DpJwClNNWdhhx"
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: whatsapp-config
|
||||||
|
key: trip-group-url
|
||||||
- name: ANTHROPIC_API_KEY
|
- name: ANTHROPIC_API_KEY
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,12 @@ spec:
|
||||||
containers:
|
containers:
|
||||||
- name: weather-reporter
|
- name: weather-reporter
|
||||||
image: node:18-alpine
|
image: node:18-alpine
|
||||||
|
env:
|
||||||
|
- name: GROUP_URL
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: whatsapp-config
|
||||||
|
key: default-group-url
|
||||||
command:
|
command:
|
||||||
- "node"
|
- "node"
|
||||||
- "-e"
|
- "-e"
|
||||||
|
|
@ -28,7 +34,7 @@ spec:
|
||||||
|
|
||||||
const ZIP = '16046';
|
const ZIP = '16046';
|
||||||
const GATEWAY = 'http://whatsapp-gateway.ai-agents.svc.cluster.local:5001/send-message';
|
const GATEWAY = 'http://whatsapp-gateway.ai-agents.svc.cluster.local:5001/send-message';
|
||||||
const GROUP = 'https://chat.whatsapp.com/FXO0SCLA8DpJwClNNWdhhx';
|
const GROUP = process.env.GROUP_URL || 'https://chat.whatsapp.com/0Txfg7iZBbvIuvTbTqqgAX';
|
||||||
const PERSONAL = '+14085505485';
|
const PERSONAL = '+14085505485';
|
||||||
|
|
||||||
function weatherEmoji(desc) {
|
function weatherEmoji(desc) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: whatsapp-config
|
||||||
|
namespace: ai-agents
|
||||||
|
data:
|
||||||
|
trip-group-url: "https://chat.whatsapp.com/HN2z93yhXPyEJPuoib3dws"
|
||||||
|
default-group-url: "https://chat.whatsapp.com/0Txfg7iZBbvIuvTbTqqgAX"
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import fs from 'fs';
|
||||||
|
import yaml from 'js-yaml';
|
||||||
|
|
||||||
|
const CONFIG_PATH = 'c:/Users/sunde/proxmox/agentic-os/agents/k8s/whatsapp-config.yaml';
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const fileContents = fs.readFileSync(CONFIG_PATH, 'utf8');
|
||||||
|
const doc = yaml.load(fileContents);
|
||||||
|
return NextResponse.json({ success: true, data: doc.data });
|
||||||
|
} catch (e) {
|
||||||
|
return NextResponse.json({ success: false, error: e.message }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function PUT(req) {
|
||||||
|
try {
|
||||||
|
const body = await req.json();
|
||||||
|
const { defaultGroupUrl, tripGroupUrl } = body;
|
||||||
|
|
||||||
|
const fileContents = fs.readFileSync(CONFIG_PATH, 'utf8');
|
||||||
|
const doc = yaml.load(fileContents);
|
||||||
|
|
||||||
|
if (!doc.data) doc.data = {};
|
||||||
|
if (defaultGroupUrl) doc.data['default-group-url'] = defaultGroupUrl;
|
||||||
|
if (tripGroupUrl) doc.data['trip-group-url'] = tripGroupUrl;
|
||||||
|
|
||||||
|
const newYaml = yaml.dump(doc, { lineWidth: -1 });
|
||||||
|
fs.writeFileSync(CONFIG_PATH, newYaml, 'utf8');
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, data: doc.data });
|
||||||
|
} catch (e) {
|
||||||
|
return NextResponse.json({ success: false, error: e.message }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -98,9 +98,52 @@ export default function Page() {
|
||||||
const [isSavingTrip, setIsSavingTrip] = useState(false);
|
const [isSavingTrip, setIsSavingTrip] = useState(false);
|
||||||
const [isTestingTrip, setIsTestingTrip] = useState(false);
|
const [isTestingTrip, setIsTestingTrip] = useState(false);
|
||||||
|
|
||||||
|
// Config State
|
||||||
|
const [configData, setConfigData] = useState({ defaultGroupUrl: "", tripGroupUrl: "" });
|
||||||
|
const [isSavingConfig, setIsSavingConfig] = useState(false);
|
||||||
|
const [configLoaded, setConfigLoaded] = useState(false);
|
||||||
|
|
||||||
const messagesEndRef = useRef(null);
|
const messagesEndRef = useRef(null);
|
||||||
const terminalEndRef = useRef(null);
|
const terminalEndRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (activeTab === "config" && !configLoaded) {
|
||||||
|
fetch('/api/config/whatsapp')
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
setConfigData({
|
||||||
|
defaultGroupUrl: data.data['default-group-url'] || "",
|
||||||
|
tripGroupUrl: data.data['trip-group-url'] || ""
|
||||||
|
});
|
||||||
|
setConfigLoaded(true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
}
|
||||||
|
}, [activeTab, configLoaded]);
|
||||||
|
|
||||||
|
const handleSaveConfig = async () => {
|
||||||
|
setIsSavingConfig(true);
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/config/whatsapp', {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(configData)
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
if (data.success) {
|
||||||
|
alert("Configuration saved successfully to Kubernetes manifest!");
|
||||||
|
} else {
|
||||||
|
alert("Failed to save: " + data.error);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
alert("Error saving config: " + e.message);
|
||||||
|
} finally {
|
||||||
|
setIsSavingConfig(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
||||||
}, [messages, isClawTyping]);
|
}, [messages, isClawTyping]);
|
||||||
|
|
@ -690,6 +733,20 @@ export default function Page() {
|
||||||
<Layers size={18} />
|
<Layers size={18} />
|
||||||
Workflows & Logs
|
Workflows & Logs
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() => setActiveTab("config")}
|
||||||
|
style={{
|
||||||
|
display: "flex", alignItems: "center", gap: "12px", width: "100%", padding: "12px 16px", border: "none", borderRadius: "8px", cursor: "pointer",
|
||||||
|
background: activeTab === "config" ? "rgba(168, 85, 247, 0.15)" : "transparent",
|
||||||
|
color: activeTab === "config" ? "var(--accent-purple, #a855f7)" : "var(--text-secondary)",
|
||||||
|
fontWeight: activeTab === "config" ? "600" : "500",
|
||||||
|
transition: "all 0.2s"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Settings size={18} />
|
||||||
|
Settings & Config
|
||||||
|
</button>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -1297,6 +1354,79 @@ export default function Page() {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* TAB: CONFIG */}
|
||||||
|
{activeTab === "config" && (
|
||||||
|
<div className="fade-in" style={{ display: "flex", flexDirection: "column", gap: "24px", maxWidth: "800px" }}>
|
||||||
|
<div className="glass" style={{ padding: "24px" }}>
|
||||||
|
<div style={{ display: "flex", alignItems: "center", gap: "12px", marginBottom: "20px" }}>
|
||||||
|
<Settings size={24} style={{ color: "var(--accent-purple, #a855f7)" }} />
|
||||||
|
<h2 style={{ fontSize: "20px", fontWeight: "600" }}>WhatsApp Routing Configuration</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p style={{ color: "var(--text-secondary)", fontSize: "14px", marginBottom: "24px", lineHeight: "1.6" }}>
|
||||||
|
Manage the WhatsApp group invite links used by the various Agentic OS microservices.
|
||||||
|
Changes here are written directly to the Kubernetes <code>whatsapp-config.yaml</code> ConfigMap.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "20px" }}>
|
||||||
|
{/* Default Group */}
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "8px" }}>
|
||||||
|
<label style={{ fontSize: "14px", fontWeight: "600", color: "var(--text-primary)" }}>Default Group URL</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={configData.defaultGroupUrl}
|
||||||
|
onChange={(e) => setConfigData({...configData, defaultGroupUrl: e.target.value})}
|
||||||
|
placeholder="https://chat.whatsapp.com/..."
|
||||||
|
style={{
|
||||||
|
width: "100%", padding: "12px", borderRadius: "8px",
|
||||||
|
background: "rgba(0,0,0,0.2)", border: "1px solid var(--border-color)",
|
||||||
|
color: "var(--text-primary)", fontSize: "14px", fontFamily: "monospace"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<span style={{ fontSize: "12px", color: "var(--text-muted)" }}>
|
||||||
|
Used by <strong>Reminder Service</strong>, <strong>Weather CronJob</strong>, and general notifications.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Trip Group */}
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "8px" }}>
|
||||||
|
<label style={{ fontSize: "14px", fontWeight: "600", color: "var(--text-primary)" }}>Trip & Briefings Group URL</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={configData.tripGroupUrl}
|
||||||
|
onChange={(e) => setConfigData({...configData, tripGroupUrl: e.target.value})}
|
||||||
|
placeholder="https://chat.whatsapp.com/..."
|
||||||
|
style={{
|
||||||
|
width: "100%", padding: "12px", borderRadius: "8px",
|
||||||
|
background: "rgba(0,0,0,0.2)", border: "1px solid var(--border-color)",
|
||||||
|
color: "var(--text-primary)", fontSize: "14px", fontFamily: "monospace"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<span style={{ fontSize: "12px", color: "var(--text-muted)" }}>
|
||||||
|
Used exclusively by the <strong>Trip Service</strong> to isolate travel insights.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Save Button */}
|
||||||
|
<div style={{ marginTop: "16px", display: "flex", justifyContent: "flex-end" }}>
|
||||||
|
<button
|
||||||
|
onClick={handleSaveConfig}
|
||||||
|
disabled={isSavingConfig}
|
||||||
|
style={{
|
||||||
|
padding: "10px 24px", borderRadius: "8px", border: "none",
|
||||||
|
background: "var(--accent-purple, #a855f7)", color: "#fff",
|
||||||
|
fontWeight: "600", cursor: isSavingConfig ? "not-allowed" : "pointer",
|
||||||
|
opacity: isSavingConfig ? 0.7 : 1, transition: "opacity 0.2s"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isSavingConfig ? "Saving to K8s..." : "Save & Apply"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* TAB 5: WORKFLOW MONITOR */}
|
{/* TAB 5: WORKFLOW MONITOR */}
|
||||||
{activeTab === "logs" && (
|
{activeTab === "logs" && (
|
||||||
<div className="fade-in" style={{ display: "flex", flexDirection: "column", gap: "20px" }}>
|
<div className="fade-in" style={{ display: "flex", flexDirection: "column", gap: "20px" }}>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
"": {
|
"": {
|
||||||
"name": "agentic-os-hq-dashboard",
|
"name": "agentic-os-hq-dashboard",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"js-yaml": "^4.2.0",
|
||||||
"lucide-react": "^0.300.0",
|
"lucide-react": "^0.300.0",
|
||||||
"next": "14.2.18",
|
"next": "14.2.18",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
|
|
@ -178,6 +179,12 @@
|
||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/argparse": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||||
|
"license": "Python-2.0"
|
||||||
|
},
|
||||||
"node_modules/busboy": {
|
"node_modules/busboy": {
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||||
|
|
@ -227,6 +234,28 @@
|
||||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/js-yaml": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/puzrin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/nodeca"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"argparse": "^2.0.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"js-yaml": "bin/js-yaml.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/loose-envify": {
|
"node_modules/loose-envify": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,10 @@
|
||||||
"start": "next start"
|
"start": "next start"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"js-yaml": "^4.2.0",
|
||||||
|
"lucide-react": "^0.300.0",
|
||||||
"next": "14.2.18",
|
"next": "14.2.18",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1"
|
||||||
"lucide-react": "^0.300.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ const DATA_FILE = process.env.DATA_FILE || '/data/trips.json';
|
||||||
const GATEWAY_URL = process.env.GATEWAY_URL || 'http://whatsapp-gateway.ai-agents.svc.cluster.local:5001/send-message';
|
const GATEWAY_URL = process.env.GATEWAY_URL || 'http://whatsapp-gateway.ai-agents.svc.cluster.local:5001/send-message';
|
||||||
const OLLAMA_URL = process.env.OLLAMA_URL || 'http://ollama.ai-agents.svc.cluster.local:11434/api/generate';
|
const OLLAMA_URL = process.env.OLLAMA_URL || 'http://ollama.ai-agents.svc.cluster.local:11434/api/generate';
|
||||||
const PERSONAL_NUM = process.env.PERSONAL_NUM || '+14085505485';
|
const PERSONAL_NUM = process.env.PERSONAL_NUM || '+14085505485';
|
||||||
const GROUP_URL = process.env.GROUP_URL || 'https://chat.whatsapp.com/FXO0SCLA8DpJwClNNWdhhx';
|
const GROUP_URL = process.env.GROUP_URL || 'https://chat.whatsapp.com/HN2z93yhXPyEJPuoib3dws';
|
||||||
const PORT = parseInt(process.env.PORT) || 6002;
|
const PORT = parseInt(process.env.PORT) || 6002;
|
||||||
|
|
||||||
// ── Persistence ──────────────────────────────────────────────────────────────
|
// ── Persistence ──────────────────────────────────────────────────────────────
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue