7811943178
GenericTemplateGenerator and FreeDocumentGenerator now, when CaseFilesCore is installed (soft-detected), set the generated Document's folderId to the case "מסמכים" folder via CaseFolderService so it shows in the CaseDocs panel. Existing Case link + NetworkStorage upload unchanged. Verified on dev (P7_OK): php -l clean on both generators; relate/find junction consistency confirmed; folder placement works. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
63 lines
5.8 KiB
Markdown
63 lines
5.8 KiB
Markdown
# SmartAssistant — Architecture (developer reference)
|
||
|
||
> Internal developer doc. Not shipped to clients. Customer overview: `README.md`. Security/dead-code findings: `_AUDIT/SmartAssistant/findings.md`.
|
||
|
||
**Module:** `SmartAssistant` · **Client module:** `smart-assistant` · **Load order:** 37 · **Requires:** EspoCRM ≥ 8.0.0, PHP ≥ 8.1
|
||
|
||
## What it is
|
||
A floating AI legal assistant. A chat widget (case mode / office mode) sends the user message plus rich context (case data, case memory, behavioral rules, prompt sections, learned skills, user profile) to the **shira-hermes** FastAPI backend via a webhook; shira returns response text + a list of tools, which `ActionExecutor` runs against the CRM (task/call/meeting CRUD, status changes, document + memory ops, rule saving), optionally looping tool results back to shira (agentic loop, max 3). Also computes office-wide alerts. Owns 6 entities (AssistantPrompt, AssistantRule, AssistantSkill, CaseMemory, UserProfile, AssistantConversation) and extends `Note` with 3 timeline note types.
|
||
|
||
## File-by-file
|
||
|
||
### Lifecycle
|
||
| File | Purpose |
|
||
|---|---|
|
||
| `scripts/AfterInstall.php` | Idempotently seeds 7 default AssistantPrompt sections (`skipAll`; admin edits win). No uninstall script (seeded entities persist). |
|
||
|
||
### Controllers
|
||
| File | Purpose |
|
||
|---|---|
|
||
| `Controllers/SmartAssistant.php` | ~30 actions: chat, execute, executeTool, alerts, summary, history, conversations, caseMemory, saveMemory, document read/analyze/upload/generate/rename/list/browse/write/move. (S1–S6 — **ACL fixed 2026-06-20**: `assertCaseAccess()` on chat/caseMemory/saveMemory/history; document-read endpoints require `caseId` + ACL + `isPathWithinCase()` containment.) |
|
||
| `Controllers/{AssistantRule,AssistantPrompt,AssistantSkill,CaseMemory,UserProfile}.php` | Thin Record CRUD. **AssistantRule has no owner field — S5.** |
|
||
|
||
### Services
|
||
| File | Purpose |
|
||
|---|---|
|
||
| `SmartAssistantService.php` | Orchestrator: webhook call, agentic loop, conversation persistence, stream notes (SmartRequest/Response/Action), office drill-down. (**fixed 2026-06-20**: `detectDrillDown` ACL-filters matched cases (S6); dead static `$conversations` removed (D1).) Forwards espocrmApiKey — S9 still open. |
|
||
| `ConversationRepository.php` | File-based conversation JSON under `data/conversations/`. |
|
||
| `ActionExecutor.php` | Executes all shira tools. (**ACL fixed 2026-06-20**: resolves the acting user in `execute()`; central `CASE_TOOL_ACCESS` record-ACL gate for case-bound tools (S1); `assertEntityAccess(...,'delete')` on every delete tool (S4); `save_rule` admin-only (S5); plugin tools with a caseId require case edit — also closes LegalAssistance S1.) |
|
||
| `CaseContextBuilder.php` / `OfficeContextBuilder.php` | Build case / office context dicts. **Case context IDOR S3.** |
|
||
| `CaseMemoryContextProvider.php`, `AssistantRuleContextProvider.php`, `AssistantPromptContextProvider.php`, `AssistantSkillContextProvider.php`, `UserProfileContextProvider.php` | Load memories/rules/prompts/skills/profile into the prompt. |
|
||
| `CaseMemoryService.php` | CaseMemory CRUD (category/importance/pinned). **IDOR S3.** |
|
||
| `DocumentAnalyzer.php` | Text extraction/analysis; uses NetworkStorageIntegration NetworkDocumentService. (**fixed 2026-06-20**: added `isPathWithinCase()` containment helper the controller calls before any read — S2.) |
|
||
| `CaseFolderManager.php` | Write/rename/move constrained to the case folder (`resolveSafePath`/`sanitizeRelSegments` — safe). |
|
||
| `GenericTemplateGenerator.php` / `FreeDocumentGenerator.php` | Template-based / free-form document generation. |
|
||
| `AlertCalculator.php` | Office alerts (inactive cases, overdue tasks, hearings without prep, unassigned new cases, deadlines). |
|
||
|
||
### Hooks
|
||
| File | Trigger |
|
||
|---|---|
|
||
| `Hooks/Case/CaseFieldChangeMemory.php` | afterSave — auto-seed CaseMemory on status/judge/court/next-hearing change. |
|
||
| `Hooks/Meeting/HearingScheduledMemory.php` | afterSave — memory when a hearing Meeting is created. |
|
||
|
||
### Resources / client
|
||
| Path | Purpose |
|
||
|---|---|
|
||
| `entityDefs/{AssistantPrompt,AssistantRule,AssistantSkill,CaseMemory,UserProfile,Note,Case}.json` | 6 entities + Note.type extension + Case.caseMemories link. **AssistantRule/UserProfile ACL — S5/S7.** |
|
||
| `integrations/SmartAssistant.json` | webhookUrl, apiKey, espocrmApiKey, thresholds, agenticLoop. **Keys are varchar — S8.** |
|
||
| `routes.json` (12), `clientDefs/*`, `scopes/*`, `layouts/*`, `dashlets/SmartAssistant.json`, `i18n/{en_US,fa_IR}/*`, `data/default-prompts.json` | Routes, UI, ACL, dashlet, translations, seed prompts. |
|
||
| `client/.../src/views/floating-chat.js` | Main chat widget (history, memory browser, mode badge). escape-then-markdown — XSS-safe. |
|
||
| `client/.../src/views/dashlets/smart-assistant.js` | Alerts card. **Unescaped caseId href S10.** |
|
||
| `client/.../src/views/{case/modals/add-memory,fields/prompt-editor,site/navbar}.js`, `stream/notes/smart-{request,response,action}.js` | Memory modal, prompt editor, navbar inject, timeline note item views. |
|
||
|
||
## Dependencies
|
||
- **NetworkStorageIntegration (hard):** DocumentAnalyzer document ops.
|
||
- **shira-hermes (external, hard):** webhook (Integration record `SmartAssistant`). No chat without it.
|
||
- **KnowledgeBase → SmartAssistant (REVERSE, critical):** KnowledgeBase reuses this extension's Integration record. **Do not uninstall SmartAssistant while KnowledgeBase is installed.**
|
||
- **LegalCrm (soft):** Note.type extension.
|
||
|
||
## Post-install gotchas
|
||
- Configure the `SmartAssistant` Integration (webhookUrl + apiKey + espocrmApiKey) — scope the espocrmApiKey to a minimal API user (S9).
|
||
- Known deploy gotchas: a backup-in-modules folder breaks hooks; AfterInstall needs `skipAll`; new role entries need api-key role grant.
|
||
- shira-hermes `/opt/data` must be a named volume (else skills/profiles/cases wiped on redeploy).
|