mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-04-28 03:30:23 +00:00
refactor: change default mode from dedicated to self-chat and reorder UI settings
- Change default mode to self-chat across all modules - Update README to reflect self-chat as primary mode with security warning - Move session/media storage from usr/whatsapp to tmp/whatsapp - Reorder config UI: move Mode above Allowed Numbers - Add warning banner when allowed_numbers is empty in self-chat mode - Move Bridge Port and Poll Interval to bottom of settings - Update mode descriptions to clarify self-chat handles both self
This commit is contained in:
parent
9fece911b5
commit
5193ef7501
10 changed files with 73 additions and 51 deletions
|
|
@ -21,18 +21,19 @@ Dependencies are auto-installed on first bridge start if missing.
|
|||
### Configure and pair
|
||||
|
||||
1. Enable the plugin in Settings > External > WhatsApp Integration
|
||||
2. Configure allowed phone numbers (optional)
|
||||
2. Configure allowed phone numbers
|
||||
3. Click Show QR Code and scan with WhatsApp on your phone
|
||||
4. Send a message from an allowed number to start a chat
|
||||
|
||||
The WhatsApp session persists across restarts in `usr/whatsapp/session/`. No re-pairing needed unless you disconnect via settings.
|
||||
The WhatsApp session persists across restarts in `tmp/whatsapp/session/`. No re-pairing needed unless you disconnect via settings.
|
||||
Be careful: if you use your personal number and leave `allowed_numbers` open, other people could misuse your Agent Zero.
|
||||
|
||||
## Configuration
|
||||
|
||||
| Setting | Description | Default |
|
||||
|---------|-------------|---------|
|
||||
| `enabled` | Enable bridge and polling | `false` |
|
||||
| `mode` | `dedicated` (separate number) or `self-chat` (personal number) | `dedicated` |
|
||||
| `mode` | `self-chat` (personal number) or `dedicated` (separate number) | `self-chat` |
|
||||
| `allow_group` | Respond in group chats when mentioned or replied to | `false` |
|
||||
| `bridge_port` | Local HTTP port for bridge | `3100` |
|
||||
| `poll_interval_seconds` | Poll frequency (min 2) | `3` |
|
||||
|
|
@ -43,10 +44,11 @@ The WhatsApp session persists across restarts in `usr/whatsapp/session/`. No re-
|
|||
## How It Works
|
||||
|
||||
1. The bridge connects to WhatsApp via Baileys and exposes HTTP endpoints on localhost
|
||||
2. The plugin polls the bridge for new messages every few seconds
|
||||
3. Incoming messages are routed to existing chats by WhatsApp chat ID or new chats are created
|
||||
4. Agent responses are sent back via the bridge as WhatsApp messages
|
||||
5. Media (images, documents) is supported in both directions
|
||||
2. In personal-number mode, you can message your own WhatsApp number to talk to the agent, and the agent can also handle messages that other people send to that number
|
||||
3. The plugin polls the bridge for new messages every few seconds
|
||||
4. Incoming messages are routed to existing chats by WhatsApp chat ID or new chats are created
|
||||
5. Agent responses are sent back via the bridge as WhatsApp messages
|
||||
6. Media (images, documents) is supported in both directions
|
||||
|
||||
## Architecture
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class QrCode(ApiHandler):
|
|||
async def process(self, input: dict, request: Request) -> dict:
|
||||
config = plugins.get_plugin_config(PLUGIN_NAME) or {}
|
||||
port = int(config.get("bridge_port", 3100))
|
||||
mode = config.get("mode", "dedicated")
|
||||
mode = config.get("mode", "self-chat")
|
||||
|
||||
from plugins._whatsapp_integration.helpers.bridge_manager import (
|
||||
ensure_bridge_http_up,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class Start(ApiHandler):
|
|||
async def process(self, input: dict, request: Request) -> dict:
|
||||
config = plugins.get_plugin_config(PLUGIN_NAME) or {}
|
||||
port = int(config.get("bridge_port", 3100))
|
||||
mode = config.get("mode", "dedicated")
|
||||
mode = config.get("mode", "self-chat")
|
||||
|
||||
from plugins._whatsapp_integration.helpers.bridge_manager import (
|
||||
ensure_bridge_http_up,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
enabled: false
|
||||
mode: dedicated
|
||||
mode: self-chat
|
||||
# dedicated: separate phone number — people message it directly
|
||||
# self-chat: personal number — you message yourself to talk to the agent
|
||||
# self-chat: personal number — you can message yourself, and the agent can also handle messages sent to your number
|
||||
bridge_port: 3100
|
||||
poll_interval_seconds: 3
|
||||
allow_group: false
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ async def _poll_loop() -> None:
|
|||
port = int(config.get("bridge_port", 3100))
|
||||
session_dir = get_bridge_session_dir()
|
||||
cache_dir = get_bridge_media_dir()
|
||||
mode = config.get("mode", "dedicated")
|
||||
mode = config.get("mode", "self-chat")
|
||||
|
||||
# Detect config changes that require bridge restart
|
||||
desired = {"port": port, "mode": mode}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ async def start_bridge(
|
|||
port: int,
|
||||
session_dir: str,
|
||||
cache_dir: str,
|
||||
mode: str = "dedicated",
|
||||
mode: str = "self-chat",
|
||||
) -> bool:
|
||||
async with _get_bridge_lock():
|
||||
return await _ensure_bridge_started(
|
||||
|
|
@ -137,7 +137,7 @@ async def ensure_bridge_http_up(
|
|||
port: int,
|
||||
session_dir: str,
|
||||
cache_dir: str,
|
||||
mode: str = "dedicated",
|
||||
mode: str = "self-chat",
|
||||
) -> bool:
|
||||
"""Start bridge if needed and wait for HTTP server only (not WA connection)."""
|
||||
async with _get_bridge_lock():
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ async def send_wa_reply(
|
|||
response_text = _md_to_whatsapp(response_text)
|
||||
|
||||
# Prefix response in self-chat mode so user can distinguish agent messages
|
||||
mode = config.get("mode", "dedicated")
|
||||
mode = config.get("mode", "self-chat")
|
||||
if mode == "self-chat":
|
||||
response_text = context.agent0.read_prompt(
|
||||
"fw.wa.self_chat_prefix.md", response_text=response_text,
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ from helpers import files
|
|||
|
||||
|
||||
def get_bridge_session_dir() -> str:
|
||||
return files.get_abs_path(files.USER_DIR, "whatsapp", "session")
|
||||
return files.get_abs_path(files.TEMP_DIR, "whatsapp", "session")
|
||||
|
||||
|
||||
def get_bridge_media_dir() -> str:
|
||||
return files.get_abs_path(files.USER_DIR, "whatsapp", "media")
|
||||
return files.get_abs_path(files.TEMP_DIR, "whatsapp", "media")
|
||||
|
|
|
|||
|
|
@ -30,6 +30,11 @@
|
|||
if (Array.isArray(value)) return value.join(', ');
|
||||
return typeof value === 'string' ? value : '';
|
||||
},
|
||||
allowed_is_empty() {
|
||||
const value = config?.allowed_numbers;
|
||||
if (Array.isArray(value)) return value.length === 0;
|
||||
return !String(value || '').trim();
|
||||
},
|
||||
set_allowed(val) {
|
||||
config.allowed_numbers = val.split(',')
|
||||
.map(s => s.trim())
|
||||
|
|
@ -104,10 +109,7 @@
|
|||
<template x-if="config">
|
||||
<div>
|
||||
<div class="section-title">WhatsApp Integration</div>
|
||||
<div class="section-description">
|
||||
Connect Agent Zero to WhatsApp using a Baileys bridge.
|
||||
Requires Node.js installed on the system.
|
||||
</div>
|
||||
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">
|
||||
|
|
@ -122,23 +124,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">
|
||||
<div class="field-title">Mode</div>
|
||||
<div class="field-description"
|
||||
x-text="config.mode === 'self-chat'
|
||||
? 'Message yourself to talk to the agent — no extra number needed'
|
||||
: 'Uses a second phone number — others message it directly'">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field-control">
|
||||
<select x-model="config.mode">
|
||||
<option value="dedicated">Separate number (dedicated)</option>
|
||||
<option value="self-chat">Personal number (self-chat)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- WhatsApp Account (shown when enabled) -->
|
||||
<template x-if="config.enabled">
|
||||
<div>
|
||||
|
|
@ -221,28 +206,43 @@
|
|||
|
||||
<div class="field">
|
||||
<div class="field-label">
|
||||
<div class="field-title">Bridge Port</div>
|
||||
<div class="field-description">Local port for the WhatsApp bridge HTTP server</div>
|
||||
<div class="field-title">Mode</div>
|
||||
<div class="field-description">
|
||||
<span x-show="config.mode === 'self-chat'">
|
||||
Use your personal number. You can message yourself to talk to the agent, and the agent can also handle messages that other people send to your number.
|
||||
</span>
|
||||
<span x-show="config.mode !== 'self-chat'">
|
||||
Use a separate WhatsApp number dedicated to Agent Zero conversations.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field-control">
|
||||
<input type="number" x-model.number="config.bridge_port" placeholder="3100" />
|
||||
<select x-model="config.mode">
|
||||
<option value="self-chat">Personal number (self-chat)</option>
|
||||
<option value="dedicated">Separate number (dedicated)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">
|
||||
<div class="field-title">Poll Interval (seconds)</div>
|
||||
<div class="field-description">How often to check for new messages (minimum 2)</div>
|
||||
<template x-if="config.enabled && allowed_is_empty()">
|
||||
<div style="margin: 8px 0 20px; padding: 12px 14px; border-radius: 10px;
|
||||
border: 1px solid rgba(255, 170, 0, 0.45);
|
||||
background: rgba(255, 170, 0, 0.12);
|
||||
color: var(--color-warning-text);">
|
||||
<div style="font-weight: 600; display: flex; align-items: center; gap: 8px;">
|
||||
<span aria-hidden="true">⚠</span>
|
||||
<span>Warning</span>
|
||||
</div>
|
||||
<div style="margin-top: 4px; line-height: 1.45;">
|
||||
Allowed Numbers is empty. If other people can message this WhatsApp number, they can use your Agent Zero.
|
||||
</div>
|
||||
</div>
|
||||
<div class="field-control">
|
||||
<input type="number" x-model.number="config.poll_interval_seconds" min="2" placeholder="3" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">
|
||||
<div class="field-title">Allowed Numbers</div>
|
||||
<div class="field-description">Comma-separated phone numbers. Matching is normalized by the backend, so punctuation and + prefixes are okay. Empty = allow all</div>
|
||||
<div class="field-description">Comma-separated phone numbers. Matching is normalized by the backend, so punctuation and + prefixes are okay. Empty = allow all.</div>
|
||||
</div>
|
||||
<div class="field-control">
|
||||
<input type="text" :value="allowed_text()" @change="set_allowed($event.target.value)" placeholder="+1 (415) 555-1234, +44 7911 123456" />
|
||||
|
|
@ -287,6 +287,26 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">
|
||||
<div class="field-title">Bridge Port</div>
|
||||
<div class="field-description">Local port for the WhatsApp bridge HTTP server</div>
|
||||
</div>
|
||||
<div class="field-control">
|
||||
<input type="number" x-model.number="config.bridge_port" placeholder="3100" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">
|
||||
<div class="field-title">Poll Interval (seconds)</div>
|
||||
<div class="field-description">How often to check for new messages (minimum 2)</div>
|
||||
</div>
|
||||
<div class="field-control">
|
||||
<input type="number" x-model.number="config.poll_interval_seconds" min="2" placeholder="3" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Test connection -->
|
||||
<div style="margin-top: 16px; display: flex; align-items: center; gap: 12px;">
|
||||
<button class="btn btn-field" @click="test_connection()" :disabled="testing">
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ const PORT = parseInt(getArg('port', '3100'), 10);
|
|||
const SESSION_DIR = getArg('session', path.join(DEFAULT_DATA_ROOT, 'session'));
|
||||
const CACHE_DIR = getArg('cache-dir', path.join(DEFAULT_DATA_ROOT, 'media'));
|
||||
const PAIR_ONLY = args.includes('--pair-only');
|
||||
const MODE = getArg('mode', 'dedicated'); // "dedicated" or "self-chat"
|
||||
const MODE = getArg('mode', 'self-chat'); // "dedicated" or "self-chat"
|
||||
|
||||
|
||||
mkdirSync(SESSION_DIR, { recursive: true });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue