diegosouzapw--omniroute
409 行
30 KiB
Markdown
409 行
30 KiB
Markdown
# CLAUDE.md (עברית)
|
||
|
||
🌐 **Languages:** 🇺🇸 [English](../../../CLAUDE.md) · 🇸🇦 [ar](../ar/CLAUDE.md) · 🇦🇿 [az](../az/CLAUDE.md) · 🇧🇬 [bg](../bg/CLAUDE.md) · 🇧🇩 [bn](../bn/CLAUDE.md) · 🇨🇿 [cs](../cs/CLAUDE.md) · 🇩🇰 [da](../da/CLAUDE.md) · 🇩🇪 [de](../de/CLAUDE.md) · 🇪🇸 [es](../es/CLAUDE.md) · 🇮🇷 [fa](../fa/CLAUDE.md) · 🇫🇮 [fi](../fi/CLAUDE.md) · 🇫🇷 [fr](../fr/CLAUDE.md) · 🇮🇳 [gu](../gu/CLAUDE.md) · 🇮🇳 [hi](../hi/CLAUDE.md) · 🇭🇺 [hu](../hu/CLAUDE.md) · 🇮🇩 [id](../id/CLAUDE.md) · 🇮🇩 [in](../in/CLAUDE.md) · 🇮🇹 [it](../it/CLAUDE.md) · 🇯🇵 [ja](../ja/CLAUDE.md) · 🇰🇷 [ko](../ko/CLAUDE.md) · 🇮🇳 [mr](../mr/CLAUDE.md) · 🇲🇾 [ms](../ms/CLAUDE.md) · 🇳🇱 [nl](../nl/CLAUDE.md) · 🇳🇴 [no](../no/CLAUDE.md) · 🇵🇭 [phi](../phi/CLAUDE.md) · 🇵🇱 [pl](../pl/CLAUDE.md) · 🇵🇹 [pt](../pt/CLAUDE.md) · 🇧🇷 [pt-BR](../pt-BR/CLAUDE.md) · 🇷🇴 [ro](../ro/CLAUDE.md) · 🇷🇺 [ru](../ru/CLAUDE.md) · 🇸🇰 [sk](../sk/CLAUDE.md) · 🇸🇪 [sv](../sv/CLAUDE.md) · 🇰🇪 [sw](../sw/CLAUDE.md) · 🇮🇳 [ta](../ta/CLAUDE.md) · 🇮🇳 [te](../te/CLAUDE.md) · 🇹🇭 [th](../th/CLAUDE.md) · 🇹🇷 [tr](../tr/CLAUDE.md) · 🇺🇦 [uk-UA](../uk-UA/CLAUDE.md) · 🇵🇰 [ur](../ur/CLAUDE.md) · 🇻🇳 [vi](../vi/CLAUDE.md) · 🇨🇳 [zh-CN](../zh-CN/CLAUDE.md)
|
||
|
||
---
|
||
|
||
הקובץ הזה מספק הנחיות ל-Claude Code (claude.ai/code) כאשר עובדים עם קוד במאגר זה.
|
||
|
||
## התחלה מהירה
|
||
|
||
```bash
|
||
npm install # התקנת תלותים (יוצר אוטומטית .env מ-.env.example)
|
||
npm run dev # שרת פיתוח ב-http://localhost:20128
|
||
npm run build # בניית הפקה (Next.js 16 עצמאי)
|
||
npm run lint # ESLint (0 שגיאות צפויות; אזהרות קיימות מראש)
|
||
npm run typecheck:core # בדיקת TypeScript (אמור להיות נקי)
|
||
npm run typecheck:noimplicit:core # בדיקה מחמירה (בלי implicit any)
|
||
npm run test:coverage # בדיקות יחידה + שער כיסוי (75/75/75/70 — משפטים/שורות/פונקציות/סניפים)
|
||
npm run check # lint + בדיקות משולבות
|
||
npm run check:cycles # זיהוי תלותיות מעגליות
|
||
```
|
||
|
||
### הרצת בדיקות
|
||
|
||
```bash
|
||
# קובץ בדיקה בודד (רץ בדיקות מקורי של Node.js — רוב הבדיקות)
|
||
node --import tsx/esm --test tests/unit/your-file.test.ts
|
||
|
||
# Vitest (שרת MCP, autoCombo, cache)
|
||
npm run test:vitest
|
||
|
||
# כל הסוויטות
|
||
npm run test:all
|
||
```
|
||
|
||
למטריצת הבדיקות המלאה, ראה `CONTRIBUTING.md` → "הרצת בדיקות". לארכיטקטורה מעמיקה, ראה `AGENTS.md`.
|
||
|
||
---
|
||
|
||
## פרויקט במבט חטוף
|
||
|
||
**OmniRoute** — פרוקסי/נתב AI מאוחד. נקודת קצה אחת, 160+ ספקי LLM, חזרה אוטומטית.
|
||
|
||
| שכבה | מיקום | מטרה |
|
||
| ------------- | ----------------------- | ---------------------------------------------------------------- |
|
||
| API Routes | `src/app/api/v1/` | נתב אפליקציית Next.js — נקודות כניסה |
|
||
| Handlers | `open-sse/handlers/` | עיבוד בקשות (צ'אט, הטמעות, וכו') |
|
||
| Executors | `open-sse/executors/` | הפצת HTTP ספציפית לספק |
|
||
| Translators | `open-sse/translator/` | המרת פורמטים (OpenAI↔Claude↔Gemini) |
|
||
| Transformer | `open-sse/transformer/` | API תגובות ↔ השלמות צ'אט |
|
||
| Services | `open-sse/services/` | ניתוב קומבו, מגבלות קצב, קאשינג, וכו' |
|
||
| Database | `src/lib/db/` | מודולי דומיין SQLite (45+ קבצים, 55 מיגרציות) |
|
||
| Domain/Policy | `src/domain/` | מנוע מדיניות, כללי עלות, לוגיקת חזרה |
|
||
| MCP Server | `open-sse/mcp-server/` | 37 כלים (30 בסיס + 3 זיכרון + 4 מיומנויות), 3 תחבורה, ~13 תחומים |
|
||
| A2A Server | `src/lib/a2a/` | פרוטוקול JSON-RPC 2.0 של סוכן |
|
||
| Skills | `src/lib/skills/` | מסגרת מיומנויות ניתנת להרחבה |
|
||
| Memory | `src/lib/memory/` | זיכרון שיחה מתמשך |
|
||
|
||
מונורפו: `src/` (אפליקציית Next.js 16), `open-sse/` (מרחב עבודה של מנוע סטרימינג), `electron/` (אפליקציית שולחן עבודה), `tests/`, `bin/` (נקודת כניסה ל-CLI).
|
||
|
||
---
|
||
|
||
## צינור בקשות
|
||
|
||
```
|
||
Client → /v1/chat/completions (Next.js route)
|
||
→ CORS → Zod validation → auth? → policy check → prompt injection guard
|
||
→ handleChatCore() [open-sse/handlers/chatCore.ts]
|
||
→ cache check → rate limit → combo routing?
|
||
→ resolveComboTargets() → handleSingleModel() per target
|
||
→ translateRequest() → getExecutor() → executor.execute()
|
||
→ fetch() upstream → retry w/ backoff
|
||
→ response translation → SSE stream or JSON
|
||
→ If Responses API: responsesTransformer.ts TransformStream
|
||
```
|
||
|
||
נתיבי API עוקבים אחרי תבנית עקבית: `Route → CORS preflight → Zod body validation → Optional auth (extractApiKey/isValidApiKey) → API key policy enforcement → Handler delegation (open-sse)`. אין middleware גלובלי של Next.js — חיתוך הוא ספציפי לנתיב.
|
||
|
||
**נתיב קומבו** (`open-sse/services/combo.ts`): 14 אסטרטגיות (עדיפות, משוקלל, מילוי ראשון, סיבוב, P2C, אקראי, הכי פחות בשימוש, אופטימיזציה של עלות, מודע לאיפוס, אקראי מחמיר, אוטומטי, lkgp, אופטימיזציה של הקשר, העברת הקשר). כל יעד קורא ל`handleSingleModel()` שמקיף את `handleChatCore()` עם טיפול בשגיאות ספציפי ליעד ובדיקות מפסק מעגל. ראה `docs/routing/AUTO-COMBO.md` עבור ניקוד Auto-Combo של 9 גורמים ו`docs/architecture/RESILIENCE_GUIDE.md` עבור 3 שכבות חוסן.
|
||
|
||
---
|
||
|
||
## מצב ריצה של חוסן
|
||
|
||
OmniRoute יש שלושה מנגנוני כישלון זמניים הקשורים אך שונים. שמור על התחום שלהם נפרד כאשר אתה מדבג התנהגות נתיב. ראה את
|
||
[דיאגרמת חוסן ב-3 שכבות](./docs/diagrams/exported/resilience-3layers.svg)
|
||
(מקור: [docs/diagrams/resilience-3layers.mmd](./docs/diagrams/resilience-3layers.mmd))
|
||
למפת מבט-על.
|
||
|
||
### מפסק מעגל ספק
|
||
|
||
**תחום**: ספק שלם, לדוגמה `glm`, `openai`, `anthropic`.
|
||
|
||
**מטרה**: להפסיק לשלוח תנועה לספק שנכשל שוב ושוב ברמת ה-upstream/service, כך שספק לא בריא אחד לא יאט את כל הבקשות.
|
||
|
||
**יישום**:
|
||
|
||
- מחלקה מרכזית: `src/shared/utils/circuitBreaker.ts`
|
||
- חיבור שער/ביצוע צ'אט: `src/sse/handlers/chatHelpers.ts`, `src/sse/handlers/chat.ts`
|
||
- API מצב ריצה: `src/app/api/monitoring/health/route.ts`
|
||
- עטיפות משותפות: `open-sse/services/accountFallback.ts`
|
||
- טבלת מצב מתמשך: `domain_circuit_breakers`
|
||
|
||
**מצבים**:
|
||
|
||
- `CLOSED`: תנועה רגילה מותרת.
|
||
- `OPEN`: ספק חסום זמנית; callers מקבלים תגובה של provider-circuit-open
|
||
או נתיב קומבו מדלג ליעד אחר.
|
||
- `HALF_OPEN`: זמן האיפוס חלף; מאפשר בקשת בדיקה. הצלחה סוגרת את
|
||
המפסק, כישלון פותח אותו שוב.
|
||
|
||
**ברירות מחדל** (`open-sse/config/constants.ts`):
|
||
|
||
- ספקי OAuth: סף `3`, זמן איפוס `60s`.
|
||
- ספקי API-key: סף `5`, זמן איפוס `30s`.
|
||
- ספקים מקומיים: סף `2`, זמן איפוס `15s`.
|
||
|
||
רק מצבי כישלון ברמת ספק צריכים להפעיל את מפסק הספק:
|
||
|
||
```ts
|
||
(408, 500, 502, 503, 504);
|
||
```
|
||
|
||
אל תפעיל את מפסק הספק הכולל עבור שגיאות רגילות של חשבון/מפתח/מודל כמו רוב
|
||
המקרים של `401`, `403`, או `429`. אלה בדרך כלל שייכים לקירור חיבור או נעילת מודל. ספק API-key כללי `403` צריך להיות ניתן לשחזור אלא אם כן הוא מסווג
|
||
כשגיאת ספק/חשבון סופית.
|
||
|
||
המפסק משתמש בשחזור עצלן, לא בטיימר רקע. כאשר `OPEN` פג, קריאות כמו `getStatus()`, `canExecute()`, ו`getRetryAfterMs()` מעדכנות את המצב ל
|
||
`HALF_OPEN`, כך שדשבורדים ובוני מועמדים לקומבו לא ממשיכים להוציא ספק שפג תוקף לנצח.
|
||
|
||
### קירור חיבור
|
||
|
||
**תחום**: חיבור/חשבון/מפתח ספק אחד.
|
||
|
||
**מטרה**: לדלג זמנית על מפתח/חשבון רע אחד תוך מתן אפשרות לחיבורים אחרים עבור
|
||
אותו ספק להמשיך לשרת בקשות.
|
||
|
||
**יישום**:
|
||
|
||
- נתיב כתיבה/עדכון: `src/sse/services/auth.ts::markAccountUnavailable()`
|
||
- בחירת/סינון חשבון: `src/sse/services/auth.ts::getProviderCredentials...`
|
||
- חישוב קירור: `open-sse/services/accountFallback.ts::checkFallbackError()`
|
||
- הגדרות: `src/lib/resilience/settings.ts`
|
||
|
||
שדות חשובים על חיבורי ספק:
|
||
|
||
```ts
|
||
rateLimitedUntil;
|
||
testStatus: "unavailable";
|
||
lastError;
|
||
lastErrorType;
|
||
errorCode;
|
||
backoffLevel;
|
||
```
|
||
|
||
במהלך בחירת חשבון, חיבור מדולג כאשר:
|
||
|
||
```ts
|
||
new Date(rateLimitedUntil).getTime() > Date.now();
|
||
```
|
||
|
||
קירורים הם גם עצלנים: כאשר `rateLimitedUntil` נמצא בעבר, החיבור הופך
|
||
לזמין שוב. בשימוש מוצלח, `clearAccountError()` מנקה את `testStatus`,
|
||
`rateLimitedUntil`, שדות שגיאה, ו`backoffLevel`.
|
||
|
||
התנהגות ברירת מחדל של קירור חיבור:
|
||
|
||
- קירור בסיסי של OAuth: `5s`.
|
||
- קירור בסיסי של API-key: `3s`.
|
||
- API-key `429` צריך להעדיף רמזי ניסיון מחדש מה-upstream (`Retry-After`, כותרות איפוס, או
|
||
טקסט איפוס שניתן לנתח) כאשר הם זמינים.
|
||
- כישלונות חוזרים שניתן לשחזר משתמשים באיפוס אקספוננציאלי:
|
||
|
||
```ts
|
||
baseCooldownMs * 2 ** failureIndex;
|
||
```
|
||
|
||
שומר ה"אנטי-המון" מונע כישלונות מקבילים על אותו חיבור מהארכת הקירור שוב ושוב או מהגדלת `backoffLevel` פעמיים.
|
||
|
||
מצבים סופיים אינם קירורים. `banned`, `expired`, ו`credits_exhausted` מיועדים להישאר לא זמינים עד ששינויים באישורים/הגדרות יתרחשו או שמפעיל יאפס אותם. אל תחליף מצבים סופיים עם מצב קירור זמני.
|
||
|
||
### נעילת מודל
|
||
|
||
**תחום**: ספק + חיבור + מודל.
|
||
|
||
**מטרה**: להימנע מכיבוי חיבור שלם כאשר רק מודל אחד אינו זמין או
|
||
מוגבל מכסה עבור אותו חיבור.
|
||
|
||
דוגמאות:
|
||
|
||
- ספקי מכסה לפי מודל המחזירים `429`.
|
||
- ספקים מקומיים המחזירים `404` עבור מודל חסר אחד.
|
||
- כישלונות הרשאה של מצב/מודל ספציפיים לספק כמו מצבי Grok שנבחרו.
|
||
|
||
נעילת מודל חיה ב`open-sse/services/accountFallback.ts` ומאפשרת לאותו
|
||
חיבור להמשיך לשרת מודלים אחרים.
|
||
|
||
### הנחיות לדיבוג
|
||
|
||
- אם כל המפתחות עבור ספק מדולגים, בדוק גם את מצב מפסק הספק וגם את
|
||
`rateLimitedUntil`/`testStatus` של כל חיבור.
|
||
- אם ספק נראה מוד excluded באופן קבוע לאחר חלון האיפוס, בדוק אם הקוד
|
||
קורא את `state` הגולמי במקום להשתמש ב`getStatus()`/`canExecute()`.
|
||
- אם מפתח ספק אחד נכשל אבל אחרים צריכים לעבוד, העדיף קירור חיבור על פני
|
||
מפסק ספק.
|
||
- אם רק מודל אחד נכשל, העדיף נעילת מודל על פני קירור חיבור.
|
||
- אם מצב צריך לשחזר את עצמו, עליו להיות עם חותמת זמן עתידית/זמן איפוס ונתיב קריאה שמעודכן מצב שפג תוקף. מצבים קבועים דורשים שינויים ידניים באישורים
|
||
או בהגדרות.
|
||
|
||
## קונבנציות מפתח
|
||
|
||
### סגנון קוד
|
||
|
||
- **2 רווחים**, נקודותיים, ציטוטים כפולים, רוחב 100 תווים, פסיקים בסוף שורות ב-ES5 (מאוכפים על ידי lint-staged דרך Prettier)
|
||
- **ייבוא**: חיצוני → פנימי (`@/`, `@omniroute/open-sse`) → יחסי
|
||
- **שמות**: קבצים=camelCase/kebab, רכיבים=PascalCase, קבועים=UPPER_SNAKE
|
||
- **ESLint**: `no-eval`, `no-implied-eval`, `no-new-func` = שגיאה בכל מקום; `no-explicit-any` = אזהרה ב-`open-sse/` וב-`tests/`
|
||
- **TypeScript**: `strict: false`, יעד ES2022, מודול esnext, פתרון bundler. העדיף סוגים מפורשים.
|
||
|
||
### מסד נתונים
|
||
|
||
- **תמיד** עבור דרך מודולי דומיין ב-`src/lib/db/` — **לעולם לא** כתוב SQL גולמי בנתיבים או במטפלים
|
||
- **לעולם לא** הוסף לוגיקה ל-`src/lib/localDb.ts` (שכבת ייצוא בלבד)
|
||
- **לעולם לא** ייבוא ברוול מ-`localDb.ts` — ייבא מודולים ספציפיים מ-`db/` במקום
|
||
- DB singleton: `getDbInstance()` מ-`src/lib/db/core.ts` (יומני WAL)
|
||
- הגירות: `src/lib/db/migrations/` — קבצי SQL עם גרסאות, אידמפוטנטיים, ריצה בעסקאות
|
||
|
||
### טיפול בשגיאות
|
||
|
||
- try/catch עם סוגי שגיאה ספציפיים, רישום עם הקשר pino
|
||
- לעולם לא לבלוע שגיאות בזרמי SSE — השתמש באותות הפסקה לניקוי
|
||
- החזר קודי סטטוס HTTP נכונים (4xx/5xx)
|
||
|
||
### אבטחה
|
||
|
||
- **לעולם לא** השתמש ב-`eval()`, `new Function()`, או eval מרומז
|
||
- אמת את כל הקלטים עם סכמות Zod
|
||
- הצפן אישורים במצב מנוחה (AES-256-GCM)
|
||
- רשימת דחייה של כותרות עליונות: `src/shared/constants/upstreamHeaders.ts` — שמור על סניטיזציה, סכמות Zod, ובדיקות יחידה מסונכרנות בעת עריכה
|
||
- **אישורים ציבוריים עליונים** (Gemini/Antigravity/Windsurf-style OAuth client_id/secret + מפתחות Firebase Web שהופקו מ-CLIs ציבוריים): **חייבים** להיות מוטמעים דרך `resolvePublicCred()` מ-`open-sse/utils/publicCreds.ts` — **לעולם לא** כמילולי מחרוזת. ראה `docs/security/PUBLIC_CREDS.md` עבור התבנית החובה.
|
||
- **תגובות שגיאה** (HTTP / SSE / מפעיל / MCP handler): **חייבות** לעבור דרך `buildErrorBody()` או `sanitizeErrorMessage()` מ-`open-sse/utils/error.ts` — **לעולם לא** לשים `err.stack` או `err.message` גולמיים בגוף התגובה. ראה `docs/security/ERROR_SANITIZATION.md`.
|
||
- **פקודות Shell שנבנות ממתודולוגיות**: כאשר קוראים ל-`exec()`/`spawn()` עם סקריפט שצריך ערכי ריצה, העבר אותם דרך האופציה `env` (נמלט אוטומטית) — **לעולם לא** לשלב מחרוזות לא מהימנות/חיצוניות בגוף הסקריפט. הפניה: `src/mitm/cert/install.ts::updateNssDatabases`.
|
||
- **ספריות מאובטחות כברירת מחדל** ([tldrsec/awesome-secure-defaults](https://github.com/tldrsec/awesome-secure-defaults)): העדיף Helmet.js, DOMPurify, ssrf-req-filter, safe-regex, Google Tink על פני יישומים מותאמים אישית בכל פעם שמוסיפים משטחים רגישים לאבטחה.
|
||
|
||
---
|
||
|
||
## תרחישי שינוי נפוצים
|
||
|
||
### הוספת ספק חדש
|
||
|
||
1. רשם ב-`src/shared/constants/providers.ts` (מאומת על ידי Zod בעת טעינה)
|
||
2. הוסף מפעיל ב-`open-sse/executors/` אם נדרשת לוגיקה מותאמת (הרחב את `BaseExecutor`)
|
||
3. הוסף מתרגם ב-`open-sse/translator/` אם פורמט שאינו OpenAI
|
||
4. הוסף קונפיגורציית OAuth ב-`src/lib/oauth/constants/oauth.ts` אם מבוסס OAuth — אם ה-CLI העליון מספק client_id/secret ציבורי, מוטמע דרך `resolvePublicCred()` (ראה `docs/security/PUBLIC_CREDS.md`), **לעולם לא** כמילולי
|
||
5. רשם מודלים ב-`open-sse/config/providerRegistry.ts`
|
||
6. כתוב בדיקות ב-`tests/unit/` (כלול את האישור של צורת publicCreds אם הוספת ברירת מחדל מוטמעת חדשה)
|
||
|
||
### הוספת נתיב API חדש
|
||
|
||
1. צור תיקיה תחת `src/app/api/v1/your-route/`
|
||
2. צור `route.ts` עם מטפלים `GET`/`POST`
|
||
3. עקוב אחרי התבנית: CORS → אימות גוף Zod → אימות אופציונלי → הפניית מטפלים
|
||
4. המטפל הולך ל-`open-sse/handlers/` (ייבא משם, לא בשורה)
|
||
5. תגובות שגיאה משתמשות ב-`buildErrorBody()` / `errorResponse()` מ-`open-sse/utils/error.ts` (מסונן אוטומטית — לעולם לא לשים `err.stack` או `err.message` גולמיים בגוף). ראה `docs/security/ERROR_SANITIZATION.md`.
|
||
6. הוסף בדיקות — כולל לפחות אישור אחד שתגובות שגיאה לא דולפות עקבות מחסומים (`!body.error.message.includes("at /")`)
|
||
|
||
### הוספת מודול DB חדש
|
||
|
||
1. צור `src/lib/db/yourModule.ts` — ייבא `getDbInstance` מ-`./core.ts`
|
||
2. ייצא פונקציות CRUD עבור טבלת הדומיין שלך
|
||
3. הוסף הגירה ב-`src/lib/db/migrations/` אם נדרשות טבלאות חדשות
|
||
4. ייצא מחדש מ-`src/lib/localDb.ts` (הוסף לרשימת הייצוא מחדש בלבד)
|
||
5. כתוב בדיקות
|
||
|
||
### הוספת כלי MCP חדש
|
||
|
||
1. הוסף הגדרת כלי ב-`open-sse/mcp-server/tools/` עם סכמת קלט Zod + מטפל אסינכרוני
|
||
2. רשם בערכת הכלים (מחובר על ידי `createMcpServer()`)
|
||
3. הקצה להיקפים המתאימים
|
||
4. כתוב בדיקות (קריאות הכלי נרשמות בטבלת `mcp_audit`)
|
||
|
||
### הוספת מיומנות A2A חדשה
|
||
|
||
1. צור מיומנות ב-`src/lib/a2a/skills/` (5 כבר קיימות: smart-routing, quota-management, provider-discovery, cost-analysis, health-report)
|
||
2. המיומנות מקבלת הקשר משימה (הודעות, מטא-נתונים) → מחזירה תוצאה מובנית
|
||
3. רשם ב-`A2A_SKILL_HANDLERS` ב-`src/lib/a2a/taskExecution.ts`
|
||
4. חשוף ב-`src/app/.well-known/agent.json/route.ts` (כרטיס סוכן)
|
||
5. כתוב בדיקות ב-`tests/unit/`
|
||
6. תעד ב-`docs/frameworks/A2A-SERVER.md` טבלת מיומנויות
|
||
|
||
### הוספת סוכן ענן חדש
|
||
|
||
1. צור מחלקת סוכן ב-`src/lib/cloudAgent/agents/` המרחיבה את `CloudAgentBase` (3 כבר קיימות: codex-cloud, devin, jules)
|
||
2. יישם `createTask`, `getStatus`, `approvePlan`, `sendMessage`, `listSources`
|
||
3. רשם ב-`src/lib/cloudAgent/registry.ts`
|
||
4. הוסף טיפול ב-OAuth/אישורים אם נדרש (`src/lib/oauth/providers/`)
|
||
5. בדיקות + תעד ב-`docs/frameworks/CLOUD_AGENT.md`
|
||
|
||
### הוספת גדר / Eval / מיומנות / אירוע Webhook חדש
|
||
|
||
- גדר: `src/lib/guardrails/` → תיעוד: `docs/security/GUARDRAILS.md`
|
||
- ערכת Eval: `src/lib/evals/` → תיעוד: `docs/frameworks/EVALS.md`
|
||
- מיומנות (סנדבוקס): `src/lib/skills/` → תיעוד: `docs/frameworks/SKILLS.md`
|
||
- אירוע Webhook: `src/lib/webhookDispatcher.ts` → תיעוד: `docs/frameworks/WEBHOOKS.md`
|
||
|
||
## תיעוד הפניה
|
||
|
||
לכל שינוי שאינו טריוויאלי, קרא קודם את המאמר המתאים:
|
||
|
||
| תחום | מסמך |
|
||
| ---------------------------------------- | ----------------------------------------------------------------- |
|
||
| ניווט במאגר | `docs/architecture/REPOSITORY_MAP.md` |
|
||
| ארכיטקטורה | `docs/architecture/ARCHITECTURE.md` |
|
||
| הפניה הנדסית | `docs/architecture/CODEBASE_DOCUMENTATION.md` |
|
||
| אוטו-קומבו (ציון 9 גורמים, 14 אסטרטגיות) | `docs/routing/AUTO-COMBO.md` |
|
||
| חוסן (3 מנגנונים) | `docs/architecture/RESILIENCE_GUIDE.md` |
|
||
| חזרה על הסקת מסקנות | `docs/routing/REASONING_REPLAY.md` |
|
||
| מסגרת מיומנויות | `docs/frameworks/SKILLS.md` |
|
||
| מערכת זיכרון (FTS5 + Qdrant) | `docs/frameworks/MEMORY.md` |
|
||
| סוכני ענן | `docs/frameworks/CLOUD_AGENT.md` |
|
||
| מגני בטיחות (PII / הזרקה / חזון) | `docs/security/GUARDRAILS.md` |
|
||
| אישורים ציבוריים (Gemini/וכו') | `docs/security/PUBLIC_CREDS.md` |
|
||
| סינון הודעות שגיאה | `docs/security/ERROR_SANITIZATION.md` |
|
||
| הערכות | `docs/frameworks/EVALS.md` |
|
||
| ציות / ביקורת | `docs/security/COMPLIANCE.md` |
|
||
| ווב-הוקים | `docs/frameworks/WEBHOOKS.md` |
|
||
| צינור הרשאה | `docs/architecture/AUTHZ_GUIDE.md` |
|
||
| הסתרה (TLS / טביעת אצבע) | `docs/security/STEALTH_GUIDE.md` |
|
||
| פרוטוקולי סוכנים (A2A / ACP / Cloud) | `docs/frameworks/AGENT_PROTOCOLS_GUIDE.md` |
|
||
| שרת MCP | `docs/frameworks/MCP-SERVER.md` |
|
||
| שרת A2A | `docs/frameworks/A2A-SERVER.md` |
|
||
| הפניה ל-API + OpenAPI | `docs/reference/API_REFERENCE.md` + `docs/reference/openapi.yaml` |
|
||
| קטלוג ספקים (נוצר אוטומטית) | `docs/reference/PROVIDER_REFERENCE.md` |
|
||
| זרימת שחרור | `docs/ops/RELEASE_CHECKLIST.md` |
|
||
|
||
---
|
||
|
||
## בדיקות
|
||
|
||
| מה | פקודה |
|
||
| ----------------------- | -------------------------------------------------------------------- |
|
||
| בדיקות יחידה | `npm run test:unit` |
|
||
| קובץ בודד | `node --import tsx/esm --test tests/unit/file.test.ts` |
|
||
| Vitest (MCP, autoCombo) | `npm run test:vitest` |
|
||
| E2E (Playwright) | `npm run test:e2e` |
|
||
| פרוטוקול E2E (MCP+A2A) | `npm run test:protocols:e2e` |
|
||
| אקוסיסטם | `npm run test:ecosystem` |
|
||
| שער כיסוי | `npm run test:coverage` (75/75/75/70 — הצהרות/שורות/פונקציות/סניפים) |
|
||
| דוח כיסוי | `npm run coverage:report` |
|
||
|
||
**כלל PR**: אם אתה משנה קוד ייצור ב-`src/`, `open-sse/`, `electron/`, או `bin/`, עליך לכלול או לעדכן בדיקות באותו PR.
|
||
|
||
**העדפת שכבת בדיקה**: יחידה קודם → אינטגרציה (רב-מודול או מצב DB) → e2e (UI/זרימת עבודה בלבד). קודד שחזורי באגים כבדיקות אוטומטיות לפני או לצד התיקון.
|
||
|
||
**מדיניות כיסוי Copilot**: כאשר PR משנה קוד ייצור והכיסוי נמוך מ-75% (הצהרות/שורות/פונקציות) או 70% (סניפים), אל תדווח רק — הוסף או עדכן בדיקות, הרץ מחדש את שער הכיסוי, ואז בקש אישור. כלול פקודות שהופעלו, קבצי בדיקה שהשתנו, ותוצאת כיסוי סופית בדוח ה-PR.
|
||
|
||
---
|
||
|
||
## זרימת עבודה של Git
|
||
|
||
```bash
|
||
# אל תבצע קומיט ישירות ל-main
|
||
git checkout -b feat/your-feature
|
||
git commit -m "feat: תאר את השינוי שלך"
|
||
git push -u origin feat/your-feature
|
||
```
|
||
|
||
**קידומות סניפים**: `feat/`, `fix/`, `refactor/`, `docs/`, `test/`, `chore/`
|
||
|
||
**פורמט קומיט** (Commits קונבנציונליים): `feat(db): הוסף מפסק מעגל` — תחומים: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`
|
||
|
||
**הוקי Husky**:
|
||
|
||
- **pre-commit**: lint-staged + `check-docs-sync` + `check:any-budget:t11`
|
||
- **pre-push**: `npm run test:unit`
|
||
|
||
---
|
||
|
||
## סביבה
|
||
|
||
- **Runtime**: Node.js ≥20.20.2 <21 || ≥22.22.2 <23 || ≥24 <25, מודולי ES
|
||
- **TypeScript**: 5.9+, יעד ES2022, מודול esnext, פתרון bundler
|
||
- **Alias נתיב**: `@/*` → `src/`, `@omniroute/open-sse` → `open-sse/`, `@omniroute/open-sse/*` → `open-sse/*`
|
||
- **פורט ברירת מחדל**: 20128 (API + לוח מחוונים באותו פורט)
|
||
- **ספריית נתונים**: משתנה סביבה `DATA_DIR`, ברירת מחדל ל-`~/.omniroute/`
|
||
- **משתני סביבה מרכזיים**: `PORT`, `JWT_SECRET`, `API_KEY_SECRET`, `INITIAL_PASSWORD`, `REQUIRE_API_KEY`, `APP_LOG_LEVEL`
|
||
- הגדרה: `cp .env.example .env` ואז צור `JWT_SECRET` (`openssl rand -base64 48`) ו-`API_KEY_SECRET` (`openssl rand -hex 32`)
|
||
|
||
---
|
||
|
||
## כללים נוקשים
|
||
|
||
1. אל תבצע קומיט של סודות או אישורים
|
||
2. אל תוסיף לוגיקה ל-`localDb.ts`
|
||
3. אל תשתמש ב-`eval()` / `new Function()` / eval מרומז
|
||
4. אל תבצע קומיט ישירות ל-`main`
|
||
5. אל תכתוב SQL גולמי בנתיבים — השתמש במודולים מ-`src/lib/db/`
|
||
6. אל תשתיק שגיאות בזרמי SSE בשקט
|
||
7. תמיד אמת קלטים עם סכמות Zod
|
||
8. תמיד כלול בדיקות כאשר אתה משנה קוד ייצור
|
||
9. הכיסוי חייב להישאר ≥75% (הצהרות, שורות, פונקציות) / ≥70% (סניפים). מדוד נוכחי: ~82%.
|
||
10. אל תעקוף הוקי Husky (`--no-verify`, `--no-gpg-sign`) ללא אישור מפעיל מפורש.
|
||
11. אל תטמיע אישורי OAuth ציבוריים upstream client_id/secret או מפתחות Firebase Web כמלל מיתר — תמיד עבור דרך `resolvePublicCred()` (`open-sse/utils/publicCreds.ts`). ראה `docs/security/PUBLIC_CREDS.md`.
|
||
12. אל תחזיר `err.stack` / `err.message` גולמיים בתגובות HTTP / SSE / executor — תמיד נווט דרך `buildErrorBody()` או `sanitizeErrorMessage()` (`open-sse/utils/error.ts`). ראה `docs/security/ERROR_SANITIZATION.md`.
|
||
13. אל תבצע אינטרפולציה של מיתרים של נתיבים חיצוניים או ערכי ריצה לתוך סקריפטים של shell המועברים ל-`exec()`/`spawn()` — העבר דרך אפשרות `env` במקום זאת. הפניה: `src/mitm/cert/install.ts::updateNssDatabases`.
|
||
14. אל תדחה אזהרת CodeQL / סריקת סודות ללא (א) בדיקה ראשונה של מסמכי התבנית למעלה כדי לראות אם העוזר חל, ו-(ב) תיעוד ההצדקה הטכנית בהערת הדחייה. תקדים: `js/stack-trace-exposure` הועלה על אתרי קריאה שכבר נווטים דרך `sanitizeErrorMessage()` היא מגבלה ידועה של CodeQL (מסננים מותאמים אישית לא מוכרים) — דחה כ-`false positive` בהתייחסות ל-`docs/security/ERROR_SANITIZATION.md`.
|
||
15. אל תחשוף נתיבים שמפעילים תהליכים ילדיים (`/api/mcp/`, `/api/cli-tools/runtime/`) ללא סיווג `isLocalOnlyPath()` ב-`src/server/authz/routeGuard.ts`. אכיפת לולאת חזרה מתבצעת ללא תנאים לפני כל בדיקת auth — JWT דלף דרך מנהרה לא יכול להפעיל תהליך. ראה `docs/security/ROUTE_GUARD_TIERS.md`.
|
||
16. לעולם אל תכלול `Co-Authored-By` trailers שמיוחסים לעוזר AI, ל-LLM או לחשבון אוטומציה (למשל שמות המכילים "Claude", "GPT", "Copilot", "Bot"; אימיילים ב-`anthropic.com` / `openai.com` / כתובות `noreply.github.com` השייכות לבוטים). trailers כאלה מנתבים את הייחוס של ה-commit לחשבון הבוט ב-GitHub, ומסתירים את המחבר האמיתי (`diegosouzapw`) בהיסטוריית ה-PR. משתפי פעולה אנושיים — כולל מחברי PR upstream ומדווחי issues שמועתקים ל-OmniRoute — יכולים וחייבים לקבל קרדיט עם trailers סטנדרטיים `Co-authored-by: Name <email>`; תהליכי העבודה של upstream-port (`/port-upstream-features`, `/port-upstream-issues`) תלויים בזה.
|