From 164b3cb3bd9aac50052430854accb1a40eedf0a7 Mon Sep 17 00:00:00 2001 From: Sadegh Barzegar Date: Wed, 14 Oct 2026 15:49:11 +0330 Subject: [PATCH] feat(desktop): Vazirmatn font + self-healing asar patch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Desktop: embed Vazirmatn (OFL) via @font-face and override --font-family-sans with !important so the whole UI uses it, with no system font install and no network. Engine (patch/lib/patch-asar.mjs): - inject a data-rtl-version marker and upgrade an existing bidi-only patch in place instead of no-op'ing - write .rtl-stamp = v:: so the guard can tell whether the current asar is fully patched Plugin (src/desktop.ts): - new ensureDesktopPatch guard: probes writability (the asar is locked while the Desktop runs) and re-applies the patch on a slow timer, so it self-heals after every app update - new `desktop` option (default true); false leaves app files alone Tests: fix patch-engine test on Windows (path separator) and add font + version-marker assertions. Docs: README.md / README.en.md / README.ar.md — the only viable route is the asar patch (no plugin hook reaches the renderer), self-heal behavior, the `desktop` option and the Vazirmatn credit. --- README.ar.md | 35 ++++++-- README.en.md | 38 ++++++--- README.md | 38 ++++++--- dist/core.d.ts | 3 + dist/core.js | 2 + dist/desktop.d.ts | 6 ++ dist/desktop.js | 113 +++++++++++++++++++++++++ dist/server.js | 2 + dist/tui.js | 2 + examples/opencode.json | 3 +- index.ts | 3 + package-lock.json | 21 ++--- package.json | 6 +- patch/fonts/OFL.txt | 93 +++++++++++++++++++++ patch/fonts/Vazirmatn-Variable.woff2 | Bin 0 -> 111152 bytes patch/lib/patch-asar.mjs | 78 ++++++++++++++++-- plugin-v2.ts | 2 + src/core.ts | 5 ++ src/desktop.ts | 118 +++++++++++++++++++++++++++ src/server.ts | 2 + src/tui.ts | 2 + test/patch-engine.test.js | 13 ++- tui-v2.ts | 2 + tui.ts | 2 + 24 files changed, 534 insertions(+), 55 deletions(-) create mode 100644 dist/desktop.d.ts create mode 100644 dist/desktop.js create mode 100644 index.ts create mode 100644 patch/fonts/OFL.txt create mode 100644 patch/fonts/Vazirmatn-Variable.woff2 create mode 100644 src/desktop.ts create mode 100644 tui.ts diff --git a/README.ar.md b/README.ar.md index 8816a92..2751baf 100644 --- a/README.ar.md +++ b/README.ar.md @@ -39,7 +39,7 @@ | الطبقة | الأداة | ماذا تُصلح | | --- | --- | --- | | **1) طبقة النص (خادم أوبن‌كود)** | إضافة `server` | رسائل المستخدم المُرسلة وسجل المحادثة وردود النموذج ومخرجات الأدوات — عبر **عزل ثنائي الاتجاه** (`RLI` / `LRI` / `PDI`) وفق UAX #9. منذ أوبن‌كود **1.18.31** يتعرّف العرض الطرفي/سطح المكتب على الاتجاه تلقائيًا (`dir="auto"` + plaintext)، لذا تركز هذه الطبقة على الطرفية/الويب والحفاظ على ترميزات LTR | -| **2) طبقة الواجهة (سطح المكتب)** | سكربتات `patch/` (لينكس / ماك / ويندوز) | **حقل الكتابة المباشر** و**عناوين التبويبات/الجلسات** التي لا تصل إليها أي خطافات إضافة — عبر حقن `dir="auto"` + `unicode-bidi: plaintext` داخل `app.asar` | +| **2) طبقة الواجهة (سطح المكتب)** | رقعة `app.asar` (المحرك `patch/lib/patch-asar.mjs` + غلاف لكل نظام تشغيل)، وتطبّقها الإضافة نفسها وتُصلحها ذاتيًا | **كل أسطح النص في الواجهة**: حقل الكتابة المباشر، رسائل الدردشة، عناوين التبويبات/الجلسات والطرفية، القوائم، الحوارات، التنبيهات، الإعدادات، شجرة الملفات، أسماء ملفات المراجعة، المرفقات، الأذونات والأسئلة — عبر حقن `dir="auto"` + `unicode-bidi: plaintext` داخل `app.asar` (الكود والفروق ومخرجات الشل تبقى LTR) — إضافةً إلى خط **Vazirmatn** لكل نص الواجهة |
🔍 كيف يعمل؟ @@ -61,13 +61,15 @@ - ✅ أمران لحالة TUI: `RTL: Show Status` و `RTL: Analyze Sample` (يعملان في v2 أيضًا عبر CLI API الجديد) - ✅ رقعة سطح المكتب لأنظمة التشغيل الثلاثة (لينكس / ماك / ويندوز) مع نسخة احتياطية تلقائية وتحقّق من تخطيط `app.asar.unpacked` وإمكانية التراجع (`--unpatch`) - ✅ تغطية كاملة لواجهة سطح المكتب: الدردشة والمحرر، تبويبات الجلسات والطرفية، القوائم، الحوارات، التنبيهات، الإعدادات، شجرة الملفات وعارض الملفات، لوحة المراجعة، المرفقات، الأذونات والأسئلة — مع حماية LTR للكود والفروق ومخرجات الشل +- ✅ خط **Vazirmatn (OFL)** مُضمَّن في واجهة سطح المكتب (دون تثبيت أي خط على النظام) +- ✅ **إصلاح ذاتي**: إضافة الخادم تطبّق رقعة سطح المكتب تلقائيًا وتُعيد تطبيقها بعد كل تحديث (دون تشغيل يدوي) - ✅ متوافق مع أوبن‌كود **1.19.0** و **2.x** (مدخل `./v2` للخادم و `./v2/tui` للـCLI) ## ⚠️ قيد مهم (بصراحة) **حقل كتابة البرومبت أثناء الكتابة الفعلية قبل الإرسال يُرسم بواجهة أوبن‌كود نفسها ولا يصل إليه أي خطاف إضافة.** لذلك: -- **تطبيق سطح المكتب** → يُصلح هذا الجزء سكربتات `patch/` — `patch/linux/desktop-rtl.sh`, أو `patch/macos/desktop-rtl.sh`, أو `patch/windows/desktop-rtl.ps1` (الطبقة ٢). +- **تطبيق سطح المكتب** → يُصلح هذا الجزء رقعة `app.asar` (المحرك `patch/lib/patch-asar.mjs` مع غلاف لكل نظام تشغيل). لا تصل أي إضافة/امتداد إلى واجهة سطح المكتب، لذا تطبّق إضافة الخادم هذه الرقعة بنفسها و**تُصلحها ذاتيًا** — اضبط `desktop: false` إن كنت تفضّل الترقيع يدويًا. - **الطرفية/TUI** → يُرسم خليةً بخلية عبر `@opentui/core`، والحل النهائي له يرجع إلى أوبن‌كود نفسه؛ لكن فور إرسال الرسالة، يُصلح برومبتك ورد النموذج عبر الطبقة ١ في كل مكان. --- @@ -171,6 +173,7 @@ npm ci && npm run build | `rtlWrapColumn` | `96` | عمود الالتفاف المستخدم في المحاذاة | | `rtlAlignColumn` | `96` | عمود المحاذاة اليمنى | | `directionEnv` | `true` | تصدير `OPENCODE_RTL*` في بيئة الأدوات | +| `desktop` | `true` | تثبيت/إصلاح رقعة سطح المكتب تلقائيًا (`app.asar` + خط Vazirmatn). لجعل الإضافة لا تلمس ملفات التطبيق: `false` | | `debug` | `false` | تسجيل عبر `client.app.log()` | > **ملاحظة الاتجاه:** الاتجاه بحسب «أول حرف قوي»؛ جملة تبدأ بالعربية تصبح RTL، وجملة تبدأ بالإنجليزية/كود تصبح LTR. لفرض RTL دائمًا: `"forceDirection": "rtl"`. @@ -189,7 +192,9 @@ npm ci && npm run build ## 🖥️ رقعة تطبيق سطح المكتب (تغطية كاملة للواجهة) -يُرسم تطبيق Electron أجزاءً من النص دون أي اتجاه تلقائي. تُضيف الرقعة `