# AI Workspace

The AI Workspace module adds an ERP-aware chatbot, a business-task assistant,
and a Tools Center (PDF, image, file conversion, OCR, translation, document
generation) to PULSE. It follows the same Module → Controller → Service →
Model → View structure as every other module (see `app/Modules/Documents`
for the reference pattern) and plugs into the existing role/permission,
module-registry, and navigation systems — nothing about those systems was
changed, only extended.

## What was added

| Area | What |
|---|---|
| Module | `app/Modules/AiWorkspace/` — Controllers, Services, Views, Routes |
| Models | `App\Models\AiProviderModel`, `AiConversationModel`, `AiMessageModel`, `AiToolLogModel` |
| DB | Migration `2026-08-06-000001_CreateAiWorkspaceTables` → `ai_providers`, `ai_conversations`, `ai_messages`, `ai_tool_logs` |
| Permissions | `ai_workspace.view`, `ai_chat.{view,send}`, `ai_assistant.{view,use}`, `ai_tools.{view,use}`, `ai_settings.{view,edit}` — added to `PermissionSeeder`; administrators inherit them automatically like every other module |
| Module registry | `ai_workspace` entry in `app/Config/ModuleRegistry.php` — can be toggled off per company like any other module |
| Navigation | Sidebar group in `app/Config/Navigation.php`, top navbar entry in `enterprise_navbar.php`, path overrides in `NavigationPermissionService.php` |
| Seeder | `AiProviderSeeder` registers the four connector catalogue rows (disabled, no keys) — called from `DatabaseSeeder` |

## AI connectors

Configure connectors at **AI Workspace → Settings** (admin-only — gated by
both the `ai_settings.edit` permission and `isAdministrator()`). Four
connector slots are pre-registered:

- **Anthropic** (native Messages API)
- **OpenAI**
- **OpenRouter** (routes to dozens of models through one OpenAI-compatible endpoint)
- **Custom** — any other OpenAI-compatible endpoint (self-hosted vLLM/Ollama, Groq, Together, etc.)

Multiple connectors can be enabled at once. Each has a `priority`; the AI
Workspace tries them in priority order and automatically falls back to the
next one if a call fails, so a single provider outage doesn't take down the
chatbot, assistant, translation tool, or document generator. API keys are
encrypted at rest with the app's `encryption.key` (see `AiProviderModel`).

No key is bundled — this repo ships with all four connectors disabled. Add
at least one key under Settings before the chatbot/assistant/translator/
doc-generator will work; until then, every one of those surfaces degrades
gracefully with a clear message instead of erroring.

## ERP-aware chatbot

`Modules\AiWorkspace\Services\Ai\ErpContextService` builds a small, **read-
only, aggregate-only** snapshot (active employee count, pending leave,
low-stock items, overdue invoices, etc.) and injects it into the chatbot's
system prompt — but only the sections the *current* user already has
permission to view (checked via the existing `NavigationPermissionService`).
The AI never receives raw records and has no ability to write back to the
ERP; it can only inform, draft, and advise.

## Tools Center — server requirements

Everything works out of the box with just PHP + GD, **except**:

| Tool | Needs | Debian/Ubuntu package |
|---|---|---|
| PDF merge / split / watermark / compress / extract text | `qpdf`, `poppler-utils`, `ghostscript` | `apt-get install qpdf poppler-utils ghostscript` |
| OCR | `tesseract-ocr` | `apt-get install tesseract-ocr` |
| Office file conversion (docx/xlsx/pptx ⇄ pdf/odt/csv/…) | `libreoffice` | `apt-get install libreoffice` |
| Image convert/resize/compress | GD (bundled with PHP) | none — always available |
| Translation | an enabled AI connector | none — no separate translation API needed |
| Document generation (PDF/DOCX) | none — pure PHP | none |

Every tool checks for its binary before running (`ToolBinaryChecker`) and
shows a clear "needs setup" message with the exact package name instead of
crashing when something isn't installed — the Tools Center is safe to
deploy on a minimal server and gains capabilities as packages are added.

## Testing performed

This was built and verified against a real MySQL/MariaDB database and PHP's
built-in server in the same environment used to write the code (not just
reviewed):

- `php spark migrate` — all migrations, including the new AI Workspace
  tables, ran cleanly against MySQL.
- `php spark db:seed DatabaseSeeder` — permissions, role grants, and the
  four connector rows seed correctly; administrator inherits all 9 new
  permission slugs automatically.
- Logged in as the seeded admin and loaded every top-level page (`/ai`,
  `/ai/chat`, `/ai/assistant`, `/ai/tools`, `/ai/tools/{pdf,image,convert,
  ocr,translate,docgen}`, `/ai/settings`) — all return 200 with no errors,
  and the sidebar/navbar render and highlight correctly.
- Configured a connector through the real Settings form (encrypted key
  storage, "Test connection" button) pointed at a local OpenAI-compatible
  mock server, then exercised the full pipeline for real over HTTP: new
  chat conversation → send message → persisted reply with token counts;
  business assistant task run; text translation; AI-drafted document
  generation in both PDF and DOCX (verified as valid OOXML/PDF output).
- PDF merge tested with real uploaded PDFs via `qpdf` — verified 2-page
  merged output with correct extracted text.
- Image conversion tested PNG → WebP via GD — verified valid WebP output.
- OCR tested against a real generated image via `tesseract` — correctly
  extracted "Hello OCR Test".

What wasn't tested here: real Anthropic/OpenAI/OpenRouter API calls (no
live keys in this environment — the driver code is a thin, direct mapping
to each provider's documented API and was exercised against a protocol-
accurate mock instead), and a full PHPUnit suite (this repository has no
test suite configured for any existing module, so none was added
speculatively for this one — happy to add one if you'd like a pattern
established).

## Known limitations worth knowing about

- PDF watermarking and the built-in PDF writer use a small hand-written PDF
  generator (no third-party library, matching this repo's practice of
  vendoring dependencies rather than depending on Packagist) — it covers
  headings, paragraphs, and bullet lists with word-wrap and pagination,
  which is enough for generated business documents, but it is not a
  general-purpose PDF layout engine.
- Office conversion depends on LibreOffice being installed; where it isn't,
  the tool explains this rather than silently failing.
- The ERP context snapshot is intentionally coarse (counts, not records) —
  by design, not as a current gap.
