Metadata-Version: 2.4
Name: zafiro-skill-whatsapp
Version: 0.1.2
Summary: WhatsApp skill package extracted from ia_orchestrator core
Author-email: Gerald Padilla <gpadillaq@gmail.com>
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/Zafiro-IA/whatsapp-skill
Project-URL: Repository, https://github.com/Zafiro-IA/whatsapp-skill
Project-URL: Issues, https://github.com/Zafiro-IA/whatsapp-skill/issues
Keywords: whatsapp,skill,orchestrator,automation
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Classifier: Topic :: Communications :: Chat
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: requests>=2.31
Requires-Dist: sqlalchemy>=2.0
Requires-Dist: python-magic>=0.4.27
Requires-Dist: neonize
Dynamic: license-file

# zafiro-skill-whatsapp

Autonomous WhatsApp skill package for the Zafiro orchestrator ecosystem.

This package is designed to run as an external skill pack with no direct imports from core `app.*` modules or other skill packages.

## Documentation map

- Core integration guide: `docs/CORE_INTEGRATION.md`
- Full tools contract: `docs/TOOLS_REFERENCE.md`
- Skill manifest/prompt: `skills/whatsapp.md`

## What this package contains

- Skill manifest: `skills/whatsapp.md`
- Skill entry-point registrar: `zafiro_skill_whatsapp.extensions.skills.whatsapp:register_whatsapp_skill`
- Tool entry-point registrar: `zafiro_skill_whatsapp.extensions.tools.whatsapp_tools:register_whatsapp_tools`
- WhatsApp adapter split by domain (`runtime_ops`, `message_ops`, `contacts_ops`, `sync_ops`)
- Policy tools (outbound allowlist and inbound auto-reply controls)
- CLI helpers for `/wa`-style commands
- Local integration layer (`zafiro_skill_whatsapp.integrations`) with optional host hooks

## Adapter layout

```
src/zafiro_skill_whatsapp/
├── integrations.py           # backward-compat facade + legacy path constants
├── admin.py                  # backward-compat facade
├── storage/                  # ORM models, engine, queries (all ≤300 lines)
│   ├── models.py             # SQLAlchemy models
│   ├── engine.py             # session scope, account resolution
│   ├── messages.py           # archive_whatsapp_payload, read_archived_messages
│   ├── directory.py          # load/save contacts+groups JSON directory
│   ├── access_rules.py       # allowlist CRUD
│   ├── hooks.py              # HostRuntimeHooks, configure_host_runtime
│   ├── runtime.py            # analyze_image, transcribe_audio, reset_storage_for_tests
│   └── utils.py              # normalize helpers
├── admin/                    # channel + sync admin commands
│   ├── channel.py            # wa_is_running, wa_start, wa_stop, wa_recover
│   └── sync.py               # wa_sync_full, wa_sync_all, wa_sync_auto_read_archive
├── adapters/whatsapp/        # WhatsApp protocol adapter
│   ├── runtime_ops/          # lifecycle, state, config, connection, types
│   ├── message_ops/          # inbound, outbound, processing, auto-reply, queue
│   ├── contacts_ops/         # directory, discovery (_is_real_phone guard), policy
│   └── sync_ops/             # history, history_ingest, rounds, sync_multi, orchestrator
└── extensions/
    ├── skills/               # skill entry-point registrar
    └── tools/                # tool handlers split by domain
        ├── messaging_send.py # wa_send, wa_reply
        ├── messaging_read.py # wa_read (with archive fallback), wa_read_archive
        └── messaging_ops.py  # wa_status, wa_recover, wa_sync_auto, wa_list_tools
```

### Key architectural constraints

- All source files ≤ 300 lines with single responsibility
- Vertical slice organization: each domain folder owns its models, queries, and handlers
- Backward compatibility: old single-file modules become thin re-export facades
- Contact directory (JSON) is separate from the SQL message archive
- `@lid` JID support: contacts can have a `lid` field for WhatsApp multi-device internal IDs
- `_is_real_phone()` guard in `discovery.py` prevents 14+ digit lid numbers from being saved as contacts

## Local-only artifacts

Keep local execution artifacts out of git (logs, data, media, plan exports).
For plan files generated during local experimentation, use:

- `local_runtime/plans_created/`

This package `.gitignore` excludes these folders by default:

- `logs/`
- `data/`
- `media/`
- `local_runtime/`
- `plans_created/`

## Install

From repository root:

```bash
./venv/bin/python -m pip install -e packages/whatsapp_skill
```

## Console Testing Script

There is now a standalone console tester for this package:

Quick shortcut from the `whatsapp_skill/` directory:

```bash
./scripts/wa.sh tools                                      # list all 17 tools
./scripts/wa.sh tool wa_status                             # channel state
./scripts/wa.sh tool wa_policy                             # send/reply permissions
./scripts/wa.sh tool wa_save_contacts "Gerald|50577427779|owner"
./scripts/wa.sh tool wa_send "Gerald|Hola"                 # send a message
./scripts/wa.sh tool wa_read "Gerald|10"                   # read last 10 messages
./scripts/wa.sh wa "status"                                # /wa admin: status
./scripts/wa.sh wa "sync"                                  # /wa admin: adaptive sync
./scripts/wa.sh wa "sync Zafiro 50 12 8"                   # /wa admin: sync target
./scripts/wa.sh repl                                       # interactive REPL
```

Direct python entrypoint (equivalent):

```bash
python scripts/wa_console.py list-tools
python scripts/wa_console.py tool wa_status
python scripts/wa_console.py tool wa_send "Gerald|Hola"
python scripts/wa_console.py repl
```

What it covers:

- `run-tool`: Executes any registered WhatsApp tool from this skill package.
- `run-wa`: Executes `/wa` admin subcommands (`on`, `off`, `status`, `link`, `unlink`, `actor`, etc.).
- `repl`: Interactive shell where you can test tool/admin commands quickly.

`/wa sync` UX (recommended):

- `/wa sync`: global adaptive sync validation.
- `/wa sync <target> [limit] [max_rounds] [wait_seconds]`: one-shot target sync + archive read.
- Compatibility aliases still available: `sync auto`, `sync oneshot`, `sync os`, `sync all`.

## Skill and tools

Skill name: `WhatsApp`

Declared tools (all use `wa_*` prefix):

| Tool | Purpose |
|---|---|
| `wa_save_contacts` | Save one or more contacts (batch with `;`) |
| `wa_list_contacts` | List saved contacts; auto-refreshes when stale |
| `wa_save_groups` | Save one or more group JID mappings |
| `wa_list_groups` | List saved groups; auto-refreshes when stale |
| `wa_send` | Send outbound message to contact or group |
| `wa_read` | Read recent messages (live buffer + archive fallback) |
| `wa_read_archive` | Read persisted archive messages only |
| `wa_reply` | Reply to a specific message by id |
| `wa_status` | Channel connection state and linked number |
| `wa_recover` | Channel recovery workflow |
| `wa_sync_auto` | Adaptive history sync rounds |
| `wa_policy` | Show inbound/outbound permission lists |
| `wa_allow_send` | Enable outbound send for a target |
| `wa_block_send` | Disable outbound send for a target |
| `wa_allow_reply` | Enable auto-reply inbound for a target |
| `wa_block_reply` | Disable auto-reply inbound for a target |
| `wa_list_tools` | List all tools registered by this skill |

See `docs/TOOLS_REFERENCE.md` for exact argument formats, examples, and output semantics for each tool.

## Runtime model

- Standalone defaults live in `zafiro_skill_whatsapp.integrations`.
- Archive/history, contacts, groups and access-rules use ORM-backed tables created by this skill.
- Data is scoped by connected WhatsApp number (multi-account safe).
- If host ORM is configured (`orm_session_factory` or `orm_engine_factory`), tables are created/reused there.
- If host ORM is not configured, the skill logs a warning and falls back to local SQLite at `WHATSAPP_LOCAL_DB_PATH`.
- Optional host runtime hooks can be provided with `configure_host_runtime(...)` to bridge:
	- active-agent listing
	- task execution
	- effective-agent resolution
	- host ORM session/engine and storage account resolver

See `docs/CORE_INTEGRATION.md` for a full bootstrap example and deployment checklist.

## Host integration contract

- Contract metadata API: `get_host_runtime_contract()`.
- Contract validation API: `validate_host_runtime_contract(...)`.
- Fail-fast API: `assert_host_runtime_contract(...)`.

Expected hooks by mode:

- Core shared database mode (recommended):
	- required: `orm_session_factory` or `orm_engine_factory`
- Multi-account strict mode (recommended):
	- required: `resolve_storage_account_key`
- Optional:
	- `storage_schema_initializer`
	- `get_active_agents`, `execute_task`, `resolve_effective_agent`

Bootstrap order (recommended):

1. `configure_host_runtime(...)`
2. `assert_host_runtime_contract(...)`
3. Load entry points and register skills/tools

Dependency contract:

- Python dependencies are installed by package manager when this skill is added:
	- `sqlalchemy`, `python-magic`, `neonize`
- System dependency required by runtime:
	- `libmagic` (OS package; must be present on host image)

## Entry points

`pyproject.toml` exports:

- `zafiro.skills` -> `whatsapp`
- `zafiro.tools` -> `whatsapp`

## Key environment variables

- `WHATSAPP_SESSION_NAME`
- `WHATSAPP_DEVICE_PLATFORM`
- `WHATSAPP_DEVICE_OS`
- `WHATSAPP_DEVICE_VERSION`
- `WHATSAPP_OUTBOX_DIR`
- `WHATSAPP_CONTACTS_PATH`
- `WHATSAPP_ACCESS_RULES_PATH`
- `WHATSAPP_MEDIA_DIR`
- `WHATSAPP_ACTIVE_ACCOUNT_PATH`
- `MESSAGE_ARCHIVE_PATH`
- `WHATSAPP_LOCAL_DB_PATH`
- `RECENT_SESSION_HISTORY_LIMIT`
- `WHATSAPP_GROUPS_SYNC_TTL_SECONDS`
- `WHATSAPP_CONTACTS_SYNC_TTL_SECONDS`
- `WHATSAPP_DIRECTORY_SYNC_MIN_INTERVAL_SECONDS`
- `WHATSAPP_FORWARD_URL`
- `WHATSAPP_FORWARD_SECRET`
- `WHATSAPP_SIMULATE_TYPING`
- `WHATSAPP_TYPING_MIN_MS`
- `WHATSAPP_TYPING_MAX_MS`
- `WHATSAPP_TYPING_MS_PER_CHAR`
- `WHATSAPP_SEND_AVAILABLE_PRESENCE`
- `WHATSAPP_AUTO_MARK_READ`
- `WHATSAPP_AUTO_REPLY_ENABLED`

## Integration tests

End-to-end integration tests run every tool via `wa.sh` and assert AOT response format:

```bash
cd whatsapp_skill
PYTHONPATH=src .venv/bin/python3 -m pytest tests/test_wa_sh_tools_integration.py -v
```

Coverage: 40 tests (38 standard + 2 skipped for live/send scenarios).

Optional live-mode env flags:

| Flag | Effect |
|---|---|
| `WA_SH_LIVE=1` | Run `wa_sync_auto` live sync test |
| `WA_SH_ALLOW_SEND=1` | Run `wa_send` live send to allowed contact |

## Validation checklist (current)

- No AST-level imports from `app`, `zafiro_skill_hostal`, or `zafiro_skill_media`
- Package imports succeed:
	- `zafiro_skill_whatsapp`
	- `zafiro_skill_whatsapp.integrations`
	- `zafiro_skill_whatsapp.extensions.tools.whatsapp_tools`
	- `zafiro_skill_whatsapp.extensions.skills.whatsapp`
