wingman-ai 1.0.0__py3-none-any.whl
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.
- share/wingman/node_listener/package-lock.json +1785 -0
- share/wingman/node_listener/package.json +50 -0
- share/wingman/node_listener/src/index.ts +108 -0
- share/wingman/node_listener/src/ipc.ts +70 -0
- share/wingman/node_listener/src/messageHandler.ts +135 -0
- share/wingman/node_listener/src/socket.ts +244 -0
- share/wingman/node_listener/src/types.d.ts +13 -0
- share/wingman/node_listener/tsconfig.json +19 -0
- wingman/__init__.py +4 -0
- wingman/__main__.py +6 -0
- wingman/cli/__init__.py +5 -0
- wingman/cli/commands/__init__.py +1 -0
- wingman/cli/commands/auth.py +90 -0
- wingman/cli/commands/config.py +109 -0
- wingman/cli/commands/init.py +71 -0
- wingman/cli/commands/logs.py +84 -0
- wingman/cli/commands/start.py +111 -0
- wingman/cli/commands/status.py +84 -0
- wingman/cli/commands/stop.py +33 -0
- wingman/cli/commands/uninstall.py +113 -0
- wingman/cli/main.py +50 -0
- wingman/cli/wizard.py +356 -0
- wingman/config/__init__.py +31 -0
- wingman/config/paths.py +153 -0
- wingman/config/personality.py +155 -0
- wingman/config/registry.py +343 -0
- wingman/config/settings.py +294 -0
- wingman/core/__init__.py +16 -0
- wingman/core/agent.py +257 -0
- wingman/core/ipc_handler.py +124 -0
- wingman/core/llm/__init__.py +5 -0
- wingman/core/llm/client.py +77 -0
- wingman/core/memory/__init__.py +6 -0
- wingman/core/memory/context.py +109 -0
- wingman/core/memory/models.py +213 -0
- wingman/core/message_processor.py +277 -0
- wingman/core/policy/__init__.py +5 -0
- wingman/core/policy/evaluator.py +265 -0
- wingman/core/process_manager.py +135 -0
- wingman/core/safety/__init__.py +8 -0
- wingman/core/safety/cooldown.py +63 -0
- wingman/core/safety/quiet_hours.py +75 -0
- wingman/core/safety/rate_limiter.py +58 -0
- wingman/core/safety/triggers.py +117 -0
- wingman/core/transports/__init__.py +14 -0
- wingman/core/transports/base.py +106 -0
- wingman/core/transports/imessage/__init__.py +5 -0
- wingman/core/transports/imessage/db_listener.py +280 -0
- wingman/core/transports/imessage/sender.py +162 -0
- wingman/core/transports/imessage/transport.py +140 -0
- wingman/core/transports/whatsapp.py +180 -0
- wingman/daemon/__init__.py +5 -0
- wingman/daemon/manager.py +303 -0
- wingman/installer/__init__.py +5 -0
- wingman/installer/node_installer.py +253 -0
- wingman_ai-1.0.0.dist-info/METADATA +553 -0
- wingman_ai-1.0.0.dist-info/RECORD +60 -0
- wingman_ai-1.0.0.dist-info/WHEEL +4 -0
- wingman_ai-1.0.0.dist-info/entry_points.txt +2 -0
- wingman_ai-1.0.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wingman-ai
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: An AI-powered personal chat agent for WhatsApp and iMessage with configurable personality and policy-driven responses
|
|
5
|
+
Project-URL: Homepage, https://github.com/metanoia-oss/wingman
|
|
6
|
+
Project-URL: Repository, https://github.com/metanoia-oss/wingman
|
|
7
|
+
Project-URL: Documentation, https://github.com/metanoia-oss/wingman#readme
|
|
8
|
+
Project-URL: Issues, https://github.com/metanoia-oss/wingman/issues
|
|
9
|
+
Author: Wingman Contributors
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ai,chatbot,gpt,imessage,openai,personal-assistant,whatsapp
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Communications :: Chat
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: aiosqlite>=0.19.0
|
|
25
|
+
Requires-Dist: openai>=1.0.0
|
|
26
|
+
Requires-Dist: platformdirs>=4.0.0
|
|
27
|
+
Requires-Dist: psutil>=5.9.0
|
|
28
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
29
|
+
Requires-Dist: pyyaml>=6.0
|
|
30
|
+
Requires-Dist: questionary>=2.0.0
|
|
31
|
+
Requires-Dist: rich>=13.0.0
|
|
32
|
+
Requires-Dist: typer[all]>=0.9.0
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: black>=25.0.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
# Wingman
|
|
41
|
+
|
|
42
|
+
[](https://pypi.org/project/wingman-ai/)
|
|
43
|
+
[](https://www.npmjs.com/package/wingman-ai)
|
|
44
|
+
[](https://github.com/metanoia-oss/wingman/actions/workflows/ci.yml)
|
|
45
|
+
[](https://opensource.org/licenses/MIT)
|
|
46
|
+
|
|
47
|
+
An AI-powered personal chat agent that participates in conversations with configurable personality, tone adaptation based on contact relationships, and policy-driven response rules. Supports multiple platforms including WhatsApp and iMessage (with more coming). Built with OpenAI GPT models.
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
|
|
51
|
+
- **Personality-driven responses** - Configurable bot personality with witty, casual tone
|
|
52
|
+
- **Role-based tone adaptation** - Different tones for different relationships (partner, family, friends)
|
|
53
|
+
- **Policy-driven rules** - Fine-grained control over when to respond
|
|
54
|
+
- **Safety controls** - Rate limiting, cooldowns, quiet hours
|
|
55
|
+
- **Conversation memory** - Context-aware responses using message history
|
|
56
|
+
- **Hot-reload config** - Changes to contacts/groups apply without restart
|
|
57
|
+
- **Background daemon** - Runs as a macOS service with auto-restart
|
|
58
|
+
|
|
59
|
+
## Architecture
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
63
|
+
│ WhatsApp Web │
|
|
64
|
+
└─────────────────────────┬───────────────────────────────────┘
|
|
65
|
+
│
|
|
66
|
+
┌─────────────────────────▼───────────────────────────────────┐
|
|
67
|
+
│ Node.js Listener (Baileys) │
|
|
68
|
+
│ node_listener/ │
|
|
69
|
+
│ - Connects to WhatsApp Web │
|
|
70
|
+
│ - Receives messages via WebSocket │
|
|
71
|
+
│ - Sends messages back │
|
|
72
|
+
└─────────────────────────┬───────────────────────────────────┘
|
|
73
|
+
│ IPC (stdin/stdout)
|
|
74
|
+
┌─────────────────────────▼───────────────────────────────────┐
|
|
75
|
+
│ Python Orchestrator │
|
|
76
|
+
│ python_orchestrator/ │
|
|
77
|
+
│ - Message processing & filtering │
|
|
78
|
+
│ - Config-driven identity (contacts.yaml, groups.yaml) │
|
|
79
|
+
│ - Policy-based response rules (policies.yaml) │
|
|
80
|
+
│ - Role-based tone adaptation │
|
|
81
|
+
│ - OpenAI GPT integration │
|
|
82
|
+
│ - Conversation memory (SQLite) │
|
|
83
|
+
│ - Safety controls (rate limits, quiet hours, cooldowns) │
|
|
84
|
+
└─────────────────────────────────────────────────────────────┘
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Prerequisites
|
|
88
|
+
|
|
89
|
+
- **macOS** (tested on macOS, may work on Linux with modifications)
|
|
90
|
+
- **Python 3.10+**
|
|
91
|
+
- **Node.js 18+**
|
|
92
|
+
- **WhatsApp account** (on your phone)
|
|
93
|
+
- **OpenAI API key**
|
|
94
|
+
|
|
95
|
+
## Installation
|
|
96
|
+
|
|
97
|
+
### Quick Install (Recommended)
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
pip install wingman-ai
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Then run the interactive setup:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
wingman init
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The setup wizard will:
|
|
110
|
+
1. Check prerequisites (Python, Node.js, npm)
|
|
111
|
+
2. Configure your OpenAI API key
|
|
112
|
+
3. Set up bot personality and name
|
|
113
|
+
4. Configure safety settings
|
|
114
|
+
5. Install the WhatsApp listener
|
|
115
|
+
|
|
116
|
+
### Development Install
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
git clone https://github.com/metanoia-oss/wingman.git
|
|
120
|
+
cd wingman
|
|
121
|
+
pip install -e .
|
|
122
|
+
wingman init
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## CLI Commands
|
|
126
|
+
|
|
127
|
+
| Command | Description |
|
|
128
|
+
|---------|-------------|
|
|
129
|
+
| `wingman init` | Interactive setup wizard |
|
|
130
|
+
| `wingman auth` | Connect WhatsApp (scan QR code) |
|
|
131
|
+
| `wingman start` | Start bot as background daemon |
|
|
132
|
+
| `wingman start -f` | Start bot in foreground |
|
|
133
|
+
| `wingman stop` | Stop running bot |
|
|
134
|
+
| `wingman status` | Check if running |
|
|
135
|
+
| `wingman logs` | View/stream activity logs |
|
|
136
|
+
| `wingman config` | View or edit configuration |
|
|
137
|
+
| `wingman uninstall` | Remove Wingman and all data |
|
|
138
|
+
|
|
139
|
+
## Quick Start
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# 1. Install
|
|
143
|
+
pip install wingman-ai
|
|
144
|
+
|
|
145
|
+
# 2. Run setup wizard
|
|
146
|
+
wingman init
|
|
147
|
+
|
|
148
|
+
# 3. Connect WhatsApp
|
|
149
|
+
wingman auth
|
|
150
|
+
|
|
151
|
+
# 4. Start the bot
|
|
152
|
+
wingman start
|
|
153
|
+
|
|
154
|
+
# 5. Check status
|
|
155
|
+
wingman status
|
|
156
|
+
|
|
157
|
+
# 6. View logs
|
|
158
|
+
wingman logs
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Running the Bot
|
|
162
|
+
|
|
163
|
+
### First Run: WhatsApp Authentication
|
|
164
|
+
|
|
165
|
+
After setup, connect WhatsApp by scanning a QR code:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
wingman auth
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
1. A QR code will appear in the terminal
|
|
172
|
+
2. Open WhatsApp on your phone
|
|
173
|
+
3. Go to **Settings > Linked Devices > Link a Device**
|
|
174
|
+
4. Scan the QR code
|
|
175
|
+
5. Wait for "Connected!" message
|
|
176
|
+
|
|
177
|
+
### Start as Background Service
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
wingman start
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
This starts Wingman as a macOS launchd service that auto-restarts on crash.
|
|
184
|
+
|
|
185
|
+
### Run in Foreground
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
wingman start --foreground
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Press `Ctrl+C` to stop.
|
|
192
|
+
|
|
193
|
+
### View Logs
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# Stream logs in real-time
|
|
197
|
+
wingman logs
|
|
198
|
+
|
|
199
|
+
# Show last 100 lines without streaming
|
|
200
|
+
wingman logs --no-follow -n 100
|
|
201
|
+
|
|
202
|
+
# Show error logs
|
|
203
|
+
wingman logs --error
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Legacy Installation (Manual)
|
|
209
|
+
|
|
210
|
+
<details>
|
|
211
|
+
<summary>Click to expand manual installation steps</summary>
|
|
212
|
+
|
|
213
|
+
### Step 1: Clone the Repository
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
git clone https://github.com/metanoia-oss/wingman.git
|
|
217
|
+
cd wingman
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Step 2: Set Up Python Environment
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
python3 -m venv .venv
|
|
224
|
+
source .venv/bin/activate
|
|
225
|
+
pip install -r requirements.txt
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Step 3: Build Node.js Listener
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
cd node_listener
|
|
232
|
+
npm install
|
|
233
|
+
npm run build
|
|
234
|
+
cd ..
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Step 4: Configure Environment
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
cp .env.example .env
|
|
241
|
+
nano .env # Add your OPENAI_API_KEY
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Step 5: Configure Contacts & Policies
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
cp config/contacts.yaml.example config/contacts.yaml
|
|
248
|
+
cp config/groups.yaml.example config/groups.yaml
|
|
249
|
+
cp config/policies.yaml.example config/policies.yaml
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Run with Legacy Script
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
python run.py
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
</details>
|
|
259
|
+
|
|
260
|
+
## Configuration
|
|
261
|
+
|
|
262
|
+
### Config File (`~/.config/wingman/config.yaml`)
|
|
263
|
+
|
|
264
|
+
```yaml
|
|
265
|
+
bot:
|
|
266
|
+
name: "Wingman"
|
|
267
|
+
|
|
268
|
+
openai:
|
|
269
|
+
api_key: "sk-..." # Or use OPENAI_API_KEY env var
|
|
270
|
+
model: "gpt-4o"
|
|
271
|
+
max_response_tokens: 150
|
|
272
|
+
temperature: 0.8
|
|
273
|
+
|
|
274
|
+
personality:
|
|
275
|
+
base_prompt: "You are Wingman, a witty and helpful assistant."
|
|
276
|
+
default_tone: casual
|
|
277
|
+
|
|
278
|
+
safety:
|
|
279
|
+
max_replies_per_hour: 30
|
|
280
|
+
cooldown_seconds: 60
|
|
281
|
+
quiet_hours:
|
|
282
|
+
enabled: true
|
|
283
|
+
start: 0
|
|
284
|
+
end: 6
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Environment Variables (Legacy)
|
|
288
|
+
|
|
289
|
+
These are still supported for backward compatibility:
|
|
290
|
+
|
|
291
|
+
| Variable | Default | Description |
|
|
292
|
+
|----------|---------|-------------|
|
|
293
|
+
| `OPENAI_API_KEY` | (required) | Your OpenAI API key |
|
|
294
|
+
| `OPENAI_MODEL` | `gpt-4o` | Model to use (gpt-4o, gpt-4-turbo, gpt-3.5-turbo) |
|
|
295
|
+
| `BOT_NAME` | `Maximus` | Name the bot responds to |
|
|
296
|
+
| `MAX_REPLIES_PER_HOUR` | `30` | Rate limit for replies |
|
|
297
|
+
| `DEFAULT_COOLDOWN_SECONDS` | `60` | Minimum seconds between replies |
|
|
298
|
+
| `QUIET_HOURS_START` | `0` | Hour to start quiet mode (0-23) |
|
|
299
|
+
| `QUIET_HOURS_END` | `6` | Hour to end quiet mode (0-23) |
|
|
300
|
+
| `CONTEXT_WINDOW_SIZE` | `30` | Number of messages to include as context |
|
|
301
|
+
| `MAX_RESPONSE_TOKENS` | `150` | Maximum response length |
|
|
302
|
+
| `TEMPERATURE` | `0.8` | Creativity (0.0-1.0) |
|
|
303
|
+
|
|
304
|
+
### Contact Configuration (`config/contacts.yaml`)
|
|
305
|
+
|
|
306
|
+
Maps WhatsApp JIDs to contact profiles with roles and tone preferences.
|
|
307
|
+
|
|
308
|
+
```yaml
|
|
309
|
+
contacts:
|
|
310
|
+
"+14155551234@s.whatsapp.net":
|
|
311
|
+
name: "Partner"
|
|
312
|
+
role: girlfriend # girlfriend, sister, friend, family, colleague, unknown
|
|
313
|
+
tone: affectionate # loving, affectionate, friendly, casual, sarcastic, neutral
|
|
314
|
+
allow_proactive: true
|
|
315
|
+
cooldown_override: 30 # Custom cooldown (seconds)
|
|
316
|
+
|
|
317
|
+
defaults:
|
|
318
|
+
role: unknown
|
|
319
|
+
tone: neutral
|
|
320
|
+
allow_proactive: false
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**Available Tones:**
|
|
324
|
+
|
|
325
|
+
| Tone | Behavior |
|
|
326
|
+
|------|----------|
|
|
327
|
+
| `loving` | Deep affection and intimacy (for partners) |
|
|
328
|
+
| `affectionate` | Warm, caring, supportive |
|
|
329
|
+
| `friendly` | Playful teasing, sibling vibes |
|
|
330
|
+
| `casual` | Relaxed friend energy |
|
|
331
|
+
| `sarcastic` | Witty banter, dry humor |
|
|
332
|
+
| `neutral` | Polite, maintains boundaries |
|
|
333
|
+
|
|
334
|
+
### Group Configuration (`config/groups.yaml`)
|
|
335
|
+
|
|
336
|
+
Maps group JIDs to categories and reply policies.
|
|
337
|
+
|
|
338
|
+
```yaml
|
|
339
|
+
groups:
|
|
340
|
+
"120363012345678901@g.us":
|
|
341
|
+
name: "Family Chat"
|
|
342
|
+
category: family # family, friends, work, unknown
|
|
343
|
+
reply_policy: always # always, selective, never
|
|
344
|
+
|
|
345
|
+
defaults:
|
|
346
|
+
category: unknown
|
|
347
|
+
reply_policy: selective
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Reply Policies:**
|
|
351
|
+
|
|
352
|
+
| Policy | Behavior |
|
|
353
|
+
|--------|----------|
|
|
354
|
+
| `always` | Always respond to messages |
|
|
355
|
+
| `selective` | Only respond when @mentioned or replying to bot |
|
|
356
|
+
| `never` | Never respond in this chat |
|
|
357
|
+
|
|
358
|
+
### Policy Rules (`config/policies.yaml`)
|
|
359
|
+
|
|
360
|
+
Rules for determining when to respond. Evaluated in order; first match wins.
|
|
361
|
+
|
|
362
|
+
```yaml
|
|
363
|
+
rules:
|
|
364
|
+
- name: "girlfriend_dm"
|
|
365
|
+
conditions:
|
|
366
|
+
is_dm: true
|
|
367
|
+
role: girlfriend
|
|
368
|
+
action: always
|
|
369
|
+
|
|
370
|
+
- name: "unknown_dm"
|
|
371
|
+
conditions:
|
|
372
|
+
is_dm: true
|
|
373
|
+
role: unknown
|
|
374
|
+
action: never
|
|
375
|
+
|
|
376
|
+
- name: "work_group"
|
|
377
|
+
conditions:
|
|
378
|
+
is_group: true
|
|
379
|
+
group_category: work
|
|
380
|
+
action: never
|
|
381
|
+
|
|
382
|
+
fallback:
|
|
383
|
+
action: selective
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
**Available Conditions:**
|
|
387
|
+
- `is_dm: true/false` - Is this a direct message?
|
|
388
|
+
- `is_group: true/false` - Is this a group chat?
|
|
389
|
+
- `role: girlfriend/sister/friend/...` - Contact's role
|
|
390
|
+
- `group_category: family/friends/work/...` - Group's category
|
|
391
|
+
- `is_reply_to_bot: true/false` - Is this a reply to bot's message?
|
|
392
|
+
|
|
393
|
+
### Finding JIDs
|
|
394
|
+
|
|
395
|
+
To find contact and group JIDs:
|
|
396
|
+
|
|
397
|
+
1. Send a message to the contact/group
|
|
398
|
+
2. Check the logs:
|
|
399
|
+
```bash
|
|
400
|
+
./scripts/daemon.sh logs
|
|
401
|
+
```
|
|
402
|
+
3. Look for log entries like:
|
|
403
|
+
```
|
|
404
|
+
Processing message: chat=+14155551234@s.whatsapp.net...
|
|
405
|
+
Resolved: contact=Unknown (role=unknown, tone=neutral)
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
The `chat=` value is the JID you need.
|
|
409
|
+
|
|
410
|
+
## Project Structure
|
|
411
|
+
|
|
412
|
+
```
|
|
413
|
+
wingman/
|
|
414
|
+
├── pyproject.toml # Package configuration
|
|
415
|
+
├── README.md # This file
|
|
416
|
+
├── LICENSE # MIT License
|
|
417
|
+
│
|
|
418
|
+
├── src/wingman/ # Main Python package
|
|
419
|
+
│ ├── cli/ # CLI commands (typer)
|
|
420
|
+
│ │ ├── main.py # CLI entry point
|
|
421
|
+
│ │ ├── wizard.py # Setup wizard
|
|
422
|
+
│ │ └── commands/ # Individual commands
|
|
423
|
+
│ ├── config/ # Configuration
|
|
424
|
+
│ │ ├── paths.py # XDG path management
|
|
425
|
+
│ │ ├── settings.py # Settings loader
|
|
426
|
+
│ │ ├── registry.py # Contact/Group registries
|
|
427
|
+
│ │ └── personality.py # Bot personality prompts
|
|
428
|
+
│ ├── core/ # Core bot logic
|
|
429
|
+
│ │ ├── agent.py # Main agent class
|
|
430
|
+
│ │ ├── process_manager.py # Node.js subprocess
|
|
431
|
+
│ │ ├── message_processor.py # Message handling
|
|
432
|
+
│ │ ├── llm/ # OpenAI integration
|
|
433
|
+
│ │ ├── memory/ # SQLite conversation storage
|
|
434
|
+
│ │ ├── safety/ # Rate limits, quiet hours
|
|
435
|
+
│ │ ├── policy/ # Policy evaluation
|
|
436
|
+
│ │ └── transports/ # WhatsApp & iMessage
|
|
437
|
+
│ ├── daemon/ # Background service management
|
|
438
|
+
│ └── installer/ # Node.js listener installer
|
|
439
|
+
│
|
|
440
|
+
├── node_listener/ # WhatsApp Web connection
|
|
441
|
+
│ ├── src/ # TypeScript source
|
|
442
|
+
│ ├── package.json
|
|
443
|
+
│ └── tsconfig.json
|
|
444
|
+
│
|
|
445
|
+
└── config/ # Example configs (legacy)
|
|
446
|
+
├── contacts.yaml.example
|
|
447
|
+
├── groups.yaml.example
|
|
448
|
+
└── policies.yaml.example
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### User Config Locations (XDG)
|
|
452
|
+
|
|
453
|
+
After running `wingman init`, config files are stored in:
|
|
454
|
+
|
|
455
|
+
```
|
|
456
|
+
~/.config/wingman/
|
|
457
|
+
├── config.yaml # Main configuration
|
|
458
|
+
├── contacts.yaml # Contact profiles
|
|
459
|
+
├── groups.yaml # Group settings
|
|
460
|
+
├── policies.yaml # Response policies
|
|
461
|
+
└── node_listener/ # Installed Node.js listener
|
|
462
|
+
|
|
463
|
+
~/.local/share/wingman/
|
|
464
|
+
├── conversations.db # SQLite database
|
|
465
|
+
└── auth_state/ # WhatsApp credentials
|
|
466
|
+
|
|
467
|
+
~/.cache/wingman/
|
|
468
|
+
└── logs/ # Log files
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
## Troubleshooting
|
|
472
|
+
|
|
473
|
+
### QR Code Won't Scan
|
|
474
|
+
|
|
475
|
+
- Make sure terminal is large enough to display the QR code
|
|
476
|
+
- Try reducing terminal font size
|
|
477
|
+
- Ensure good lighting when scanning
|
|
478
|
+
|
|
479
|
+
### Bot Not Responding
|
|
480
|
+
|
|
481
|
+
1. Check if daemon is running:
|
|
482
|
+
```bash
|
|
483
|
+
wingman status
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
2. Check logs for errors:
|
|
487
|
+
```bash
|
|
488
|
+
wingman logs --error
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
3. Verify OpenAI API key is valid:
|
|
492
|
+
```bash
|
|
493
|
+
wingman config --show
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
4. Check policy rules - the contact may be set to `never` respond
|
|
497
|
+
|
|
498
|
+
### "WhatsApp Logged Out" Error
|
|
499
|
+
|
|
500
|
+
WhatsApp may log out linked devices periodically. Re-authenticate:
|
|
501
|
+
|
|
502
|
+
```bash
|
|
503
|
+
wingman stop
|
|
504
|
+
wingman auth
|
|
505
|
+
wingman start
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### Config Changes Not Working
|
|
509
|
+
|
|
510
|
+
Config files auto-reload every 2 seconds. If changes aren't applying:
|
|
511
|
+
1. Check for YAML syntax errors:
|
|
512
|
+
```bash
|
|
513
|
+
wingman config --show
|
|
514
|
+
```
|
|
515
|
+
2. Check the logs for reload messages:
|
|
516
|
+
```bash
|
|
517
|
+
wingman logs
|
|
518
|
+
|
|
519
|
+
## Important Notes
|
|
520
|
+
|
|
521
|
+
- **Mac must stay logged in** - The daemon runs as a user agent. It won't run when logged out.
|
|
522
|
+
- **Screen lock is OK** - The bot continues running when the screen is locked.
|
|
523
|
+
- **Auto-restart** - If the bot crashes, launchd will automatically restart it.
|
|
524
|
+
- **Rate limiting** - Built-in rate limits prevent spam. Configure in `.env`.
|
|
525
|
+
|
|
526
|
+
## Uninstalling
|
|
527
|
+
|
|
528
|
+
To completely remove Wingman:
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
# Remove all Wingman data, config, and daemon
|
|
532
|
+
wingman uninstall
|
|
533
|
+
|
|
534
|
+
# Then remove the package
|
|
535
|
+
pip uninstall wingman-ai
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
Options:
|
|
539
|
+
- `wingman uninstall --keep-config` - Keep config files, only remove data
|
|
540
|
+
- `wingman uninstall --force` - Don't ask for confirmation
|
|
541
|
+
|
|
542
|
+
## Contributing
|
|
543
|
+
|
|
544
|
+
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
545
|
+
|
|
546
|
+
## License
|
|
547
|
+
|
|
548
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
549
|
+
|
|
550
|
+
## Acknowledgments
|
|
551
|
+
|
|
552
|
+
- [Baileys](https://github.com/WhiskeySockets/Baileys) - WhatsApp Web API
|
|
553
|
+
- [OpenAI](https://openai.com/) - GPT models
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
wingman/__init__.py,sha256=8WTGssI3JFCaRT_VHOkNWufGbl1WXqq8Ac0BxWZpCpo,123
|
|
2
|
+
wingman/__main__.py,sha256=kREwLHRdnMOQCSrbE0m-vhzn9OddUoybMU7YX4kMsJg,113
|
|
3
|
+
wingman/cli/__init__.py,sha256=458Lb8-IJpD4FJFM6iuG0zrCHDf-DBuSkv467oSLm5I,72
|
|
4
|
+
wingman/cli/main.py,sha256=jWty_TfukNcaa-bAIil8pO953WTFs8TECdMWKuAjnMk,1112
|
|
5
|
+
wingman/cli/wizard.py,sha256=fTQ2IH_vSW6lE8WCWkxmbYwRxXsEfend3WRQOjqLxpI,12081
|
|
6
|
+
wingman/cli/commands/__init__.py,sha256=MTFQxPeJOd67WzBSy9T5XogDhXtQwvmcCfK7R2jrRRY,32
|
|
7
|
+
wingman/cli/commands/auth.py,sha256=Gdy3a61QlsRiWor4kcWpHT5nwaOD9-5Hfi8dTRBbi3U,2802
|
|
8
|
+
wingman/cli/commands/config.py,sha256=saHLAWBCesbSA7nGHQLK8WxSLP0oOKISfNRtyR0xCKc,3022
|
|
9
|
+
wingman/cli/commands/init.py,sha256=ssyLgkXNrSN0m1Q9xYw1ZBRRrsHT0BCwDyYJd3cL4ec,2153
|
|
10
|
+
wingman/cli/commands/logs.py,sha256=jpRsi2U3iKITed6XkURrhcLVlPbpdGxRZgIb4hEijQs,2204
|
|
11
|
+
wingman/cli/commands/start.py,sha256=MJow0KM6N-Gk-IeWNc4MrCJhIPG84GNiwLs2z5fniMA,3320
|
|
12
|
+
wingman/cli/commands/status.py,sha256=FPeY4fOKU7PFP4eATIqL84h3K1glRZZDxNIycdwQk1Q,2474
|
|
13
|
+
wingman/cli/commands/stop.py,sha256=nsuTYf1fXGFz0lhaLjlp9FD9RHhu1wCpHzWph-r8C9E,760
|
|
14
|
+
wingman/cli/commands/uninstall.py,sha256=G5Rpw1oox-nJqCR6GdABhL_qxqFyLx48rcqBbDXKa5c,3119
|
|
15
|
+
wingman/config/__init__.py,sha256=5MQxkW9vxWNDGYRge3gHLpu5PIjxsnQZFg1AVZPcYDw,659
|
|
16
|
+
wingman/config/paths.py,sha256=JARqPakBbRkS_oCSMGa9pdW4YF047MNhyizHr051yXk,5104
|
|
17
|
+
wingman/config/personality.py,sha256=xHW2CZBUocB-g2Kc4Z0lur43fn1RmzMOxTTpsfHOBYU,5668
|
|
18
|
+
wingman/config/registry.py,sha256=uwrD37QdOHbR5GsIRp6sZB_R7tbHj4onFLG-IE20ZYo,12159
|
|
19
|
+
wingman/config/settings.py,sha256=al_BWHhENFdmJnoCKkBMBJEdfWD6pUKNFTK0hWfWt30,11751
|
|
20
|
+
wingman/core/__init__.py,sha256=ERzWQl-RVAOoKW5zrSGAnbAS3BppTY0PXhMsqSltfh8,423
|
|
21
|
+
wingman/core/agent.py,sha256=KwCw6AKZlF1PMQrHHEY-Cn3iT_ItUuLW5h7D41Qi0gc,8767
|
|
22
|
+
wingman/core/ipc_handler.py,sha256=mV73rDv-i7vdshzHtAvy8S7rTZmPaReCHcAdkm5EDhY,4077
|
|
23
|
+
wingman/core/message_processor.py,sha256=KkK7Z7Qgboh35WfQKEAzkmzuGvdazdA9_0ZEeNBxnFc,9417
|
|
24
|
+
wingman/core/process_manager.py,sha256=dzr-jdgjYVex8no8iEFX9Bj6SzRGT-hbNedjIDRZc90,4626
|
|
25
|
+
wingman/core/llm/__init__.py,sha256=BfbOx9-EEqbBN2dzifg8mFNMbN2SV7j8gkKy0OoB2xA,91
|
|
26
|
+
wingman/core/llm/client.py,sha256=JsOGpKCLg0fAT-HIYPxZ4l6ia-BC4gGekzEOowP6pNQ,2496
|
|
27
|
+
wingman/core/memory/__init__.py,sha256=eQ_txn3afIFGcQ5Fnumdmmsf-NGdtmHSPMMSkWJE8AQ,182
|
|
28
|
+
wingman/core/memory/context.py,sha256=oSM56ZO7Va1q7Cwj8dM4ZfNRQjpNF-Nn72S2wTfMFJs,3412
|
|
29
|
+
wingman/core/memory/models.py,sha256=kvlnJKrWlswHzTvthPdYCpJ61IGtrkrBc8xBcGF92L0,6832
|
|
30
|
+
wingman/core/policy/__init__.py,sha256=5vKc5yDIIvCP-iG7ZZPRM_fqxK6QQ5fXP1_BAzkqE5Q,171
|
|
31
|
+
wingman/core/policy/evaluator.py,sha256=l0EdkREU5sJvsvVDQSE-wehzFFwc6wLaqxwC22eynd4,8020
|
|
32
|
+
wingman/core/safety/__init__.py,sha256=vrcuKEERQL62ipXDwL_pMChUQXL3-vFA01im_10QuOY,279
|
|
33
|
+
wingman/core/safety/cooldown.py,sha256=eGsfX8537LrmBXv9sMNAZjxTm1s_HixGeJapB07w0To,2193
|
|
34
|
+
wingman/core/safety/quiet_hours.py,sha256=kMxJjOaf6twGTMd72d2imN2aKMJLBsYCJT5vbpoHVmo,2291
|
|
35
|
+
wingman/core/safety/rate_limiter.py,sha256=NTs8zAGhAEqRalxptInwFfw94sge2WTyEgmILA39spk,1903
|
|
36
|
+
wingman/core/safety/triggers.py,sha256=6tCF4TOL7aj4GOP2YDKMNUEm3bnKXG1ATAjbPZ5nC3s,3547
|
|
37
|
+
wingman/core/transports/__init__.py,sha256=i3uH-KcKMXIklU87U0uJyDDBVP3v8CYbXJXs9ninqD4,361
|
|
38
|
+
wingman/core/transports/base.py,sha256=DLsDZg4jpT2G53_z_TtlWRs6WZl7Tpk0Pd7mEUlWvQk,2826
|
|
39
|
+
wingman/core/transports/whatsapp.py,sha256=VMjj3bt0E6qsO180ptafu8OQJ-tdZwwcwhVY-ULBASE,6449
|
|
40
|
+
wingman/core/transports/imessage/__init__.py,sha256=5UtZhYPuvr7Jgs-4mYCu9Gk5lPpOc3pgV-mGIaeXBUw,116
|
|
41
|
+
wingman/core/transports/imessage/db_listener.py,sha256=lu4Gx_jvvQUZ4NIJ9kkDZje70T-jnJFUNG2i7p2w-JE,10150
|
|
42
|
+
wingman/core/transports/imessage/sender.py,sha256=iVHW_1NZWhtVc5PbPjSvh1_Glt-NAnOc0euoI8xxzJk,5401
|
|
43
|
+
wingman/core/transports/imessage/transport.py,sha256=wf84e764gtUpeybTcdwWYg7mzEeH-CSCfBwuYMMXSEA,4414
|
|
44
|
+
wingman/daemon/__init__.py,sha256=2rjbJ14j1jzAOFYRc-Mm4amYEL1SPrUZ4pnXye94u84,109
|
|
45
|
+
wingman/daemon/manager.py,sha256=kYwj0e0Q1NMPVKkhFD2El6Q9ZcBVSEXn568T5dOvvFU,8743
|
|
46
|
+
wingman/installer/__init__.py,sha256=WwidNCn2YHB5lsjReuvGEB63QM2-tbgM1hwyND9dZH0,108
|
|
47
|
+
wingman/installer/node_installer.py,sha256=wsqDNLU9Zq5v_OY4XcE9TttHcTCwNk0CThrzgSeikGM,8744
|
|
48
|
+
share/wingman/node_listener/package-lock.json,sha256=dY_cBJDRCB-70L-LrCOUx-8x6gS0nEPJ6JBuJOQkee0,63694
|
|
49
|
+
share/wingman/node_listener/package.json,sha256=jfGUaO1l4L8raoUcqRlvKBeAD-dPSr4iGO5h6fis6T8,1148
|
|
50
|
+
share/wingman/node_listener/src/index.ts,sha256=H4gUz7AhErbu1jwt1lV_Vtu4Ii-ZAfCvL54kq5oexE4,3284
|
|
51
|
+
share/wingman/node_listener/src/ipc.ts,sha256=ISPNn6ojmtkMrXHqioudWuUJFy10GL2z_MDR1Op7gQA,1862
|
|
52
|
+
share/wingman/node_listener/src/messageHandler.ts,sha256=rQ3FwhLtVM_W9fkjo82eyCJMXJjuxNneHBFSd-6nLw8,3524
|
|
53
|
+
share/wingman/node_listener/src/socket.ts,sha256=p084U-qoNGOjPvWqDsm5qFNenJTrGuWd9L7V5ZV3nfA,7893
|
|
54
|
+
share/wingman/node_listener/src/types.d.ts,sha256=dUrJiqohfMu1kW_OS2k-4HObXPnlGhFkE_fi2oANo4I,298
|
|
55
|
+
share/wingman/node_listener/tsconfig.json,sha256=1JvbZY8iK_NpSI21p-9_cZO2kqMfxPjU_JeRIt8oDK8,445
|
|
56
|
+
wingman_ai-1.0.0.dist-info/METADATA,sha256=x73SCT6ugaqt5JBijgMsia9h-wB2mS72Fkhopr_XalY,16306
|
|
57
|
+
wingman_ai-1.0.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
58
|
+
wingman_ai-1.0.0.dist-info/entry_points.txt,sha256=N_G9HZ5d_Km1JNGmhU5WFsLSc4VMGwaQFQ5aNNzLxxE,49
|
|
59
|
+
wingman_ai-1.0.0.dist-info/licenses/LICENSE,sha256=DCe1o-4lfg-dJZAo0nPu_PpenYX3eFz_xteB5Dq5rfw,1072
|
|
60
|
+
wingman_ai-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Rakshit Dwivedi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|