- الرئيسية
- Documentation
- التكوين
- النقل من pi-mono: دليل عملي للدمج
النقل من pi-mono: دليل عملي للدمج
هذا الدليل عبارة عن قائمة تحقق قابلة للتكرار لنقل التغييرات من pi-mono إلى هذا المستودع. استخدمه لأي عملية دمج: ملف واحد، أو فرع ميزة، أو مزامنة إصدار كاملة.
نقطة المزامنة الأخيرة
Section titled “نقطة المزامنة الأخيرة”الالتزام: b21b42d032919de2f2e6920a76fa9a37c3920c0a
التاريخ: 2026-03-22
قم بتحديث هذا القسم بعد كل مزامنة؛ لا تعد استخدام النطاق السابق.
عند بدء مزامنة جديدة، قم بتوليد الرقع من هذا الالتزام فصاعداً:
git format-patch b21b42d032919de2f2e6920a76fa9a37c3920c0a..HEAD --stdout > changes.patch0) حدد النطاق
Section titled “0) حدد النطاق”- حدد المرجع الأصلي (التزام، وسم، أو طلب سحب).
- اسرد الحزم أو المجلدات التي تخطط للعمل عليها.
- قرر أي الميزات ضمن النطاق وأيها يتم تخطيها عمداً.
1) انقل الكود بأمان
Section titled “1) انقل الكود بأمان”- فضّل فرقاً نظيفاً ومركّزاً بدلاً من النسخ الشامل.
- تجنب نسخ المخرجات المبنية أو الملفات المولّدة.
- إذا أضاف المصدر الأصلي ملفات جديدة، أضفها صراحةً وراجع محتوياتها.
2) طابق اتفاقيات امتدادات الاستيراد
Section titled “2) طابق اتفاقيات امتدادات الاستيراد”معظم ملفات TypeScript التنفيذية تحذف .js في الاستيرادات الداخلية، لكن بعض نقاط الدخول للاختبارات/المعايير تحتفظ بـ .js لتوافق ESM
في وقت التشغيل. اتبع النمط الموجود في الحزمة المحلية؛ لا تقم بإزالة الامتدادات بشكل شامل.
- في ملفات التشغيل في
packages/coding-agent، احتفظ بالاستيرادات الداخلية بدون امتداد ما لم تستورد أصولاً غير TS. - في
packages/tui/testوpackages/natives/bench، احتفظ بـ.jsحيث تستخدمها الملفات المحيطة بالفعل. - احتفظ بامتدادات الملفات الحقيقية عندما تتطلبها الأدوات (مثل
.json،.css، تضمينات نصوص.md). - مثال:
import { x } from "./foo.js";→import { x } from "./foo";(فقط عندما تكون اتفاقية الحزمة بدون امتداد).
3) استبدل نطاقات الاستيراد
Section titled “3) استبدل نطاقات الاستيراد”يستخدم المصدر الأصلي نطاقات حزم مختلفة. استبدلها بشكل متسق.
- استبدل النطاقات القديمة بالنطاق المحلي المستخدم هنا.
- أمثلة (عدّلها لتتوافق مع الحزم الفعلية التي تنقلها):
@mariozechner/pi-coding-agent→@f5-sales-demo/xcsh@mariozechner/pi-agent-core→@f5-sales-demo/pi-agent-core@mariozechner/pi-tui→@f5-sales-demo/pi-tui@mariozechner/pi-ai→@f5-sales-demo/pi-ai
4) استخدم واجهات Bun حيث تتفوق على Node
Section titled “4) استخدم واجهات Bun حيث تتفوق على Node”نحن نعمل على Bun. استبدل واجهات Node فقط عندما يوفر Bun بديلاً أفضل.
قم بالاستبدال:
- تشغيل العمليات:
child_process.spawn→ Bun Shell$للأوامر البسيطة،Bun.spawn/Bun.spawnSyncللتدفق أو العمل طويل الأمد - إدخال/إخراج الملفات:
fs.readFileSync→Bun.file().text()/Bun.write() - عملاء HTTP:
node-fetch،axios→fetchالأصلي - تجزئة التشفير:
node:crypto→ Web Crypto أوBun.hash - SQLite:
better-sqlite3→bun:sqlite - تحميل المتغيرات البيئية:
dotenv→ يحمّل Bun ملف.envتلقائياً
لا تستبدل (هذه تعمل بشكل جيد في Bun):
os.homedir()— لا تستبدلها بـBun.env.HOMEأوBun.env.HOMEأو القيمة الحرفية"~"os.tmpdir()— لا تستبدلها بـBun.env.TMPDIR || "/tmp"أو مسارات مشفرةfs.mkdtempSync()— لا تستبدلها ببناء المسار يدوياًpath.join()،path.resolve()، إلخ — هذه جيدة كما هي
نمط الاستيراد: استخدم بادئة node: مع استيرادات مساحة الأسماء فقط (لا استيرادات مسماة من node:fs أو node:path).
اتفاقيات Bun الإضافية:
- فضّل Bun Shell
$للأوامر القصيرة غير المتدفقة؛ استخدمBun.spawnفقط عندما تحتاج إلى إدخال/إخراج متدفق أو التحكم في العملية. - استخدم
Bun.file()/Bun.write()للملفات وnode:fs/promisesللمجلدات. - تجنب فحوصات
Bun.file().exists()؛ استخدم معالجةisEnoentفي try/catch. - فضّل
Bun.sleep(ms)على أغلفةsetTimeout.
خطأ:
// BROKEN: env vars may be undefined, "~" is not expandedconst home = Bun.env.HOME || "~";const tmp = Bun.env.TMPDIR || "/tmp";صحيح:
import * as os from "node:os";import * as fs from "node:fs";import * as path from "node:path";
const configDir = path.join(os.homedir(), ".config", "myapp");const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "myapp-"));5) فضّل تضمينات Bun (بدون نسخ)
Section titled “5) فضّل تضمينات Bun (بدون نسخ)”لا تنسخ أصول وقت التشغيل أو ملفات المورّدين في وقت البناء.
- إذا كان المصدر الأصلي ينسخ الأصول إلى مجلد dist، استبدلها بتضمينات متوافقة مع Bun.
- الموجّهات هي ملفات
.mdثابتة؛ استخدم استيرادات نصوص Bun (with { type: "text" }) و Handlebars بدلاً من سلاسل الموجّهات المضمنة. - استخدم
import.meta.dir+Bun.fileلتحميل الموارد المجاورة غير النصية. - احتفظ بالأصول في المستودع ودع المجمّع يضمّنها.
- تخلص من سكربتات النسخ ما لم يطلبها المستخدم صراحةً.
- إذا كان المصدر الأصلي يقرأ ملفاً احتياطياً مجمّعاً في وقت التشغيل، استبدل قراءات نظام الملفات باستيراد تضمين نصي من Bun.
- مثال (احتياطي تعليمات Codex):
const FALLBACK_PROMPT_PATH = join(import.meta.dir, "codex-instructions.md");-> تمت إزالتهimport FALLBACK_INSTRUCTIONS from "./codex-instructions.md" with { type: "text" };- استخدم
return FALLBACK_INSTRUCTIONS;بدلاً منreadFileSync(FALLBACK_PROMPT_PATH, "utf8")
- مثال (احتياطي تعليمات Codex):
6) انقل package.json بعناية
Section titled “6) انقل package.json بعناية”تعامل مع package.json كعقد. ادمج بشكل مقصود.
- احتفظ بـ
nameوversionوtypeوexportsوbinالحاليين ما لم يتطلب النقل تغييرات. - استبدل سكربتات npm/node ببدائل Bun (مثل
bun check،bun test). - تأكد من أن التبعيات تستخدم النطاق الصحيح.
- لا تخفّض إصدارات التبعيات لإصلاح أخطاء الأنواع؛ قم بالترقية بدلاً من ذلك.
- تحقق من روابط حزم مساحة العمل و
peerDependencies.
7) وحّد أسلوب الكود والأدوات
Section titled “7) وحّد أسلوب الكود والأدوات”- حافظ على اتفاقيات التنسيق الحالية.
- لا تُدخل
anyما لم يكن مطلوباً. - تجنب الاستيرادات الديناميكية واستيرادات الأنواع المضمنة؛ استخدم استيرادات المستوى الأعلى فقط.
- لا تبنِ الموجّهات في الكود أبداً؛ الموجّهات هي ملفات
.mdثابتة يتم عرضها باستخدام Handlebars. - في coding-agent، لا تستخدم
console.log/console.warn/console.errorأبداً؛ استخدمloggerمن@f5-sales-demo/pi-utils. - استخدم
Promise.withResolvers()بدلاً منnew Promise((resolve, reject) => ...). - لا تستخدم الكلمات المفتاحية
private/protected/publicعلى حقول الفئة أو الطرق. استخدم حقول ES الخاصة#للتغليف؛ اترك الأعضاء القابلة للوصول بدون كلمة مفتاحية. الاستثناء الوحيد هو خصائص معاملات المُنشئ (constructor(private readonly x: T))، حيث تكون الكلمة المفتاحية مطلوبة بواسطة TypeScript. عند نقل كود المصدر الأصلي الذي يستخدمprivate fooأوprotected bar، حوّلها إلى#foo(خاص) أوbarبدون كلمة مفتاحية (قابل للوصول). - فضّل المساعدات والأدوات الموجودة على الكود الجديد المخصص.
- حافظ على تغييرات البنية التحتية الموجهة لـ Bun التي تم إجراؤها بالفعل في هذا المستودع:
- وقت التشغيل هو Bun (لا نقاط دخول Node).
- مدير الحزم هو Bun (لا ملفات قفل npm).
- واجهات Node الثقيلة (
child_process،readline) مستبدلة ببدائل Bun. - واجهات Node الخفيفة (
os.homedir،os.tmpdir،fs.mkdtempSync،path.*) محفوظة. - سطور shebang لـ CLI تستخدم
bun(ليسnode، ليسtsx). - الحزم تستخدم ملفات المصدر مباشرة (لا خطوة بناء TypeScript).
- سير عمل CI يشغّل Bun للتثبيت/الفحص/الاختبار.
8) أزل طبقات التوافق القديمة
Section titled “8) أزل طبقات التوافق القديمة”ما لم يُطلب ذلك، أزل وسائط التوافق الأصلية.
- احذف الواجهات القديمة التي تم استبدالها.
- حدّث جميع مواقع الاستدعاء للواجهة الجديدة مباشرة.
- لا تحتفظ بنسخ
*_v2أو نسخ متوازية.
9) حدّث التوثيق والمراجع
Section titled “9) حدّث التوثيق والمراجع”- استبدل روابط مستودع pi-mono حيثما كان مناسباً.
- حدّث الأمثلة لاستخدام Bun ونطاقات الحزم الصحيحة.
- تأكد من أن تعليمات README لا تزال تتوافق مع سلوك المستودع الحالي.
10) تحقق من صحة النقل
Section titled “10) تحقق من صحة النقل”شغّل الفحوصات القياسية بعد التغييرات:
bun check
إذا كان المستودع يحتوي بالفعل على فحوصات فاشلة غير مرتبطة بتغييراتك، أشر إلى ذلك.
الاختبارات تستخدم مشغّل Bun (ليس Vitest)، لكن شغّل bun test فقط عند الطلب صراحةً.
11) احمِ الميزات المحسّنة (قائمة فخ الانحدار)
Section titled “11) احمِ الميزات المحسّنة (قائمة فخ الانحدار)”إذا كنت قد حسّنت السلوك محلياً بالفعل، تعامل مع تلك التحسينات على أنها غير قابلة للتفاوض. قبل النقل، دوّن التحسينات وأضف فحوصات صريحة حتى لا تضيع في الدمج.
- جمّد السلوك المتوقع: أضف ملاحظة قصيرة “قبل/بعد” لكل تحسين (المدخلات، المخرجات، القيم الافتراضية، الحالات الحدية). هذا يمنع التراجع الصامت.
- خريطة القديم → الجديد للواجهات: إذا أعاد المصدر الأصلي تسمية المفاهيم (hooks → extensions، custom tools → tools، إلخ)، تأكد من أن كل نقطة دخول قديمة لا تزال متصلة. علم أو تصدير واحد مفقود يعني وظائف مفقودة.
- تحقق من التصديرات: تحقق من
exportsفيpackage.json، والأنواع العامة، وملفات barrel. عمليات النقل الأصلية غالباً تنسى إعادة تصدير الإضافات المحلية. - غطِّ المسارات غير السعيدة: إذا أصلحت معالجة الأخطاء، أو المهل الزمنية، أو منطق الاحتياط، أضف اختباراً أو على الأقل قائمة تحقق يدوية تمارس تلك المسارات.
- تحقق من الافتراضيات وترتيب دمج التكوين: التحسينات غالباً تعيش في الافتراضيات. تأكد من أن الافتراضيات الجديدة لم تتراجع (مثل أسبقية التكوين الجديدة، الميزات المعطلة، قوائم الأدوات).
- دقق سلوك البيئة/الصدفة: إذا أصلحت التنفيذ أو العزل، تحقق من أن المسار الجديد لا يزال يستخدم بيئتك المنقّحة ولا يعيد تقديم تجاوزات الأسماء المستعارة/الدوال.
- أعد تشغيل عينات مستهدفة: احتفظ بمجموعة أدنى من الأمثلة “المعروفة بأنها جيدة” وشغّلها بعد النقل (أعلام CLI، تسجيل الإضافات، تنفيذ الأدوات).
12) اكتشف وتعامل مع الكود المُعاد هيكلته
Section titled “12) اكتشف وتعامل مع الكود المُعاد هيكلته”قبل نقل ملف، تحقق مما إذا كان المصدر الأصلي قد أعاد هيكلته بشكل كبير:
# Compare the file you're about to port against what you have locallygit diff HEAD upstream/main -- path/to/file.tsإذا أظهر الفرق أن الملف تمت إعادة هيكلته (ليس مجرد ترقيع):
- تجريدات جديدة، مفاهيم مُعاد تسميتها، وحدات مدمجة، تدفق بيانات متغير
فيجب عليك قراءة التنفيذ الجديد بالكامل قبل النقل. الدمج الأعمى للكود المُعاد هيكلته يفقد الوظائف لأن:
ملاحظة: تم مؤخراً تقسيم الوضع التفاعلي إلى controllers/utils/types. عند نقل التغييرات المرتبطة بأثر رجعي، انقل التحديثات إلى الملفات الفردية التي أنشأناها وتأكد من بقاء توصيل interactive-mode.ts متزامناً.
-
الافتراضيات تتغير بصمت - متغير جديد
defaultFoo = [a, b]قد يستبدلgetAllFoo()القديم الذي كان يعيد[a, b, c, d, e]. -
خيارات الواجهة تُسقط - عندما تندمج الأنظمة (مثل
hooks+customTools→extensions)، قد لا تتصل الخيارات القديمة بالتنفيذ الجديد. -
مسارات الكود تصبح قديمة - مفهوم مُعاد تسميته (مثل
hookMessage→custom) يحتاج تحديثات في كل عبارة switch، وحارس نوع، ومعالج—ليس فقط التعريف. -
السياق/القدرات تتقلص - الواجهات القديمة ربما كشفت
{ logger, typebox, pi }التي نسيت الواجهات الجديدة تضمينها.
عملية النقل الدلالي
Section titled “عملية النقل الدلالي”عندما يعيد المصدر الأصلي هيكلة وحدة:
-
اقرأ التنفيذ القديم - افهم ماذا كان يفعل، ما الخيارات التي قبلها، ما الذي كشفه.
-
اقرأ التنفيذ الجديد - افهم التجريدات الجديدة وكيف تتوافق مع السلوك القديم.
-
تحقق من تكافؤ الميزات - لكل قدرة في الكود القديم، تأكد من أن الكود الجديد يحافظ عليها أو يزيلها صراحةً.
-
ابحث عن المتبقيات - ابحث عن الأسماء/المفاهيم القديمة التي ربما فاتت في عبارات switch، والمعالجات، ومكونات الواجهة.
-
اختبر الحدود - أعلام CLI، خيارات SDK، معالجات الأحداث، القيم الافتراضية—هذه هي حيث تختبئ الانحدارات.
فحوصات سريعة
Section titled “فحوصات سريعة”# Find all uses of an old concept that may need updatingrg "oldConceptName" --type ts
# Compare default values between versionsgit show upstream/main:path/to/file.ts | rg "default|DEFAULT"
# Check if all enum/union values have handlersrg "case \"" path/to/file.ts13) قائمة تحقق التدقيق السريع
Section titled “13) قائمة تحقق التدقيق السريع”استخدم هذه كمرور نهائي قبل الانتهاء:
14) صيغة رسالة الالتزام
Section titled “14) صيغة رسالة الالتزام”عند التزام نقل بأثر رجعي، اتبع صيغة المستودع <type>(scope): <past-tense description> واحتفظ بنطاق
الالتزامات في العنوان.
fix(coding-agent): backported pi-mono changes (<from>..<to>)
packages/<package>:- <type>: <description>- <type>: <description> (#<issue> by @<contributor>)
packages/<other-package>:- <type>: <description>مثال:
fix(coding-agent): backported pi-mono changes (9f3eef65f..52532c7c0)
packages/ai:- fix: handle "sensitive" stop reason from Anthropic API- fix: normalize tool call IDs with special characters for Responses API- fix: add overflow detection for Bedrock, MiniMax, Kimi providers- fix: 429 status is rate limiting, not context overflow
packages/tui:- fix: refactored autocomplete state tracking- fix: file autocomplete should not trigger on empty text- fix: configurable autocomplete max visible items- fix: improved table column width calculation with word-aware wrapping
packages/coding-agent:- fix: preserve external config.yml edits on save (#1046 by @nicobailonMD)- fix: resolve macOS NFD and curly quote variants in file pathsالقواعد:
- جمّع التغييرات حسب الحزمة
- استخدم أنواع الالتزام التقليدية (
fix،feat،refactor،perf،docs) - ضمّن أرقام المشاكل/طلبات السحب الأصلية ونسبة المساهمين للمساهمات الخارجية
- نطاق الالتزامات في العنوان يساعد في تتبع نقاط المزامنة
15) الاختلافات المقصودة
Section titled “15) الاختلافات المقصودة”يحتوي فرعنا على قرارات معمارية تختلف عن المصدر الأصلي. لا تنقل هذه الأنماط الأصلية:
بنية واجهة المستخدم
Section titled “بنية واجهة المستخدم”| المصدر الأصلي | فرعنا | السبب |
|---|---|---|
فئة FooterDataProvider | StatusLineComponent | سطر حالة أبسط ومتكامل |
ctx.ui.setHeader() / ctx.ui.setFooter() | وسيط فارغ في الأوضاع غير TUI | مُنفّذ في TUI، بدون عملية في غيره |
ctx.ui.setEditorComponent() | وسيط فارغ في الأوضاع غير TUI | مُنفّذ في TUI، بدون عملية في غيره |
كائن خيارات InteractiveModeOptions | معاملات مُنشئ موضعية (نوع الخيارات لا يزال مُصدّراً) | حافظ على توقيع المُنشئ؛ حدّث النوع عندما يضيف المصدر الأصلي حقولاً |
تسمية المكونات
Section titled “تسمية المكونات”| المصدر الأصلي | فرعنا |
|---|---|
extension-input.ts | hook-input.ts |
extension-selector.ts | hook-selector.ts |
ExtensionInputComponent | HookInputComponent |
ExtensionSelectorComponent | HookSelectorComponent |
تسمية الواجهات
Section titled “تسمية الواجهات”| المصدر الأصلي | فرعنا | ملاحظات |
|---|---|---|
sessionManager.appendSessionInfo(name) | sessionManager.setSessionName(name) | نستخدم sessionName في كل مكان |
sessionManager.getSessionName() | sessionManager.getSessionName() | نفسه (وحّدنا ليتوافق مع RPC الأصلي) |
agent.sessionName / setSessionName() | agent.sessionName / setSessionName() | نفسه |
دمج الملفات
Section titled “دمج الملفات”| المصدر الأصلي | فرعنا | السبب |
|---|---|---|
clipboard.ts + clipboard-image.ts (ملفات أدوات) | وحدة الحافظة في @f5-sales-demo/pi-natives | مدمجة في تنفيذ N-API الأصلي |
إطار الاختبار
Section titled “إطار الاختبار”| المصدر الأصلي | فرعنا |
|---|---|
vitest مع vi.mock() | bun:test مع vi من bun |
تأكيدات node:test | مطابقات expect() |
بنية الأدوات
Section titled “بنية الأدوات”| المصدر الأصلي | فرعنا | ملاحظات |
|---|---|---|
createTool(cwd: string, options?) | createTools(session: ToolSession) عبر سجل BUILTIN_TOOLS | مصانع الأدوات تقبل ToolSession ويمكن أن تعيد null |
واجهات *Operations لكل أداة | واجهات كل أداة تبقى (FindOperations، GrepOperations) | تُستخدم لتجاوزات SSH/البعيد |
fs/promises في Node.js في كل مكان | Bun.file()/Bun.write() للملفات؛ node:fs/promises للمجلدات | فضّل واجهات Bun عندما تبسّط |
تخزين المصادقة
Section titled “تخزين المصادقة”| المصدر الأصلي | فرعنا | ملاحظات |
|---|---|---|
proper-lockfile + auth.json | agent.db (bun:sqlite) | بيانات الاعتماد مخزنة حصرياً في agent.db |
| بيانات اعتماد واحدة لكل مزوّد | بيانات اعتماد متعددة مع اختيار دوري | منطق تقارب الجلسة والتراجع محفوظ |
الإضافات
Section titled “الإضافات”| المصدر الأصلي | فرعنا |
|---|---|
jiti لتحميل TypeScript | import() الأصلي في Bun |
حقل pkg.pi في البيان | pkg.xcsh ?? pkg.pi (فضّل مساحة أسمائنا) |
تخطَّ هذه الميزات الأصلية
Section titled “تخطَّ هذه الميزات الأصلية”عند النقل، تخطَّ هذه الملفات/الميزات بالكامل:
footer-data-provider.ts— نستخدم StatusLineComponentclipboard-image.ts— الحافظة في وحدة N-API في@f5-sales-demo/pi-natives- ملفات سير عمل GitHub — لدينا CI خاص بنا
models.generated.ts— مولّد تلقائياً، أعد توليده محلياً (كـ models.json بدلاً من ذلك)
ميزات أضفناها (احفظها)
Section titled “ميزات أضفناها (احفظها)”هذه موجودة في فرعنا ولكن ليست في المصدر الأصلي. لا تكتب فوقها أبداً:
StatusLineComponentفي الوضع التفاعلي- مصادقة متعددة بيانات الاعتماد مع تقارب الجلسة
- نظام الاكتشاف القائم على القدرات (
defineCapability،registerProvider،loadCapability،skillCapability، إلخ) - تكاملات MCP/Exa/SSH
- الكتابة المباشرة عبر LSP للتنسيق عند الحفظ
- اعتراض Bash (
checkBashInterception) - اقتراحات المسارات الضبابية في أداة القراءة