للجمهور التقني
كيف تعمل الخدمة
يقف MathTrail بين الدردشة التي تستخدمها الأسرة أصلًا وGoogle Drive الخاص بولي الأمر. يكتب نموذج الدردشة كل مسألة، وتقرر الخدمة ما إذا كانت ستصل إلى الطفل. إنه برنامج واحد: لا يستدعي أي نموذج خاص به، ولا يحتفظ بشيء بين الطلبات.
- ملف تنفيذي واحد بلغة Go على Cloud Run
- بلا حالة
- بلا قاعدة بيانات
- بلا استدعاءات LLM خاصة به
- MCP 2026-07-28 · MCP Apps
عميل الدردشة1 · العميل
- Claude
- ChatGPT
- مضيفو MCP Apps الآخرون
يكتب نموذج الدردشة المسألة، وتعرضها البطاقة على الطفل.
MCP · استدعاءات الأدوات عبر HTTPS
MathTrail على Google Cloud2 · بيئة التشغيل
Cloud Run · ملف تنفيذي واحد بلغة Go · بلا حالة
النواة: حسابات بحتة
- القاعدة
- التصنيفات
- الفحوص
- برنامج الحل
- المحتوى
من حولها: OAuth، وخادم MCP، والبطاقة، والختم، والحدود.
Drive API v3 · بالرمز المميز لولي الأمر نفسه
Google Drive3 · التخزين
MathTrail/mathtrail-profile.json
ملف واحد لكل طفل، في Drive الخاص بولي الأمر نفسه، وهو وحده ما يُحفظ طويلًا.
01
الخريطة
من يتحدث إلى من. لا وصول مباشرًا إلى MathTrail، لا للطفل ولا للشخص البالغ: فالحديث يكون مع مضيف الدردشة. وكل ما في الإطار الأوسط جزء من عملية واحدة، لا خدمة منفصلة. اختاروا أي جزء لتروا ما يفعله وبماذا يرتبط.
02
الدرس، استدعاء تلو الآخر
يستدعي النموذج والبطاقة الأدوات نفسها، ويستندان إلى مصدر واحد للحقيقة: ملف الملف الشخصي على Drive الخاص بولي الأمر. ولا يحتاج أحدهما إلى إخبار الآخر بشيء كي يستمر الدرس.
المسألة
- الشخص البالغ
- البطاقة
- نموذج المضيف
- MathTrail
- Drive
1الشخص البالغ → نموذج المضيف: «مسألة جديدة، من فضلك»
2نموذج المضيف → MathTrail: next_task
يرسم المضيف البطاقة فور بدء الاستدعاء: «جار إعداد المسألة التالية…»
الحدود · تختار القاعدة الموضوع والمستوى والصعوبة
3MathTrail → Drive: كتابة الطلب المفتوح
4MathTrail → نموذج المضيف: الطلب مفتوح: اجلب الحزمة
5نموذج المضيف → MathTrail: get_package
6MathTrail → نموذج المضيف: التكليف · 3 مسائل مرجعية · الفخاخ · القوالب · أمثلة الرسوم
يكتب النموذج المسألة، وبرنامج حل بلغة Starlark، وتحققًا ذاتيًا
7نموذج المضيف → MathTrail: submit_task — حتى 3 محاولات
الفحوص · يجب أن يجد برنامج الحل خيارًا صحيحًا واحدًا بالضبط
8MathTrail → Drive: تصبح المسألة هي الحالية، وإجابتها مختومة
9البطاقة → MathTrail: read_task — تسأل البطاقة كل 4 ث
10MathTrail → البطاقة: النص · الرسم · خمسة خيارات · التلميح — دون الإجابة
كل استدعاء يقرأ الملف الشخصي من Drive أيضًا، وقد حُذفت هذه القراءات من الرسم. والبطاقة المنتظرة لا ترى الحزمة أبدًا: فمسائلها المرجعية تحمل إجاباتها. وفي أثناء حلّ الطفل للمسألة، يكتب النموذج المسألة التالية مسبقًا باستخدام prepare_task، وعندما تُطلب مسألة أخرى، يضعها next_task على بطاقة جديدة فورًا، دون هذا الانتظار.
الإجابة
- الشخص البالغ
- الطفل
- البطاقة
- نموذج المضيف
- MathTrail
- Drive
1الطفل → البطاقة: الضغط على C
2البطاقة → MathTrail: submit_answer — لا يُستهلك أي دور في الدردشة
الإجابة الأولى وحدها · يُفتح الختم الآن · لا يتحرك θ و δ إلا بحسب صحتها
3MathTrail → Drive: كتابة التصنيفات وسجلّها
4MathTrail → البطاقة: صحيحة أم لا · الفخ وراء C · رسم الحل · الخطوات · التصنيف قبل ← بعد
تتحول البطاقة إلى مراجعة الإجابة، في مكان المسألة
5البطاقة → نموذج المضيف: ui/update-model-context — سطر واحد، يُقرأ مع الرسالة التالية من الشخص البالغ
6الشخص البالغ → نموذج المضيف: «لماذا عمود إضافي؟»
7نموذج المضيف → الشخص البالغ: يجيب عن هذه المسألة بعينها، مكمّلًا البطاقة
تُسجَّل الإجابة بالضغط قبل أن يُشرح أي شيء، وتتحول البطاقة فورًا إلى مراجعة الإجابة. لا يُستهلك أي دور في الدردشة، ولا يرسم النموذج شيئًا. ويقرأ النموذج سطر البطاقة مع الرسالة التالية من الشخص البالغ، ويجيب عن أي سؤال عن المسألة دون إعادة سرد البطاقة. وإذا ضاع السطر الذي يرسله المضيف إلى النموذج، يلحق النموذج بما فاته عند استدعائه التالي.
الدخول
- متصفح ولي الأمر
- المضيف
- MathTrail
- Drive
1المضيف → MathTrail: POST /mcp، بلا رمز مميز
2MathTrail → المضيف: 401 · مكان البيانات الوصفية
3المضيف → متصفح ولي الأمر: فتح /oauth/authorize · PKCE S256
4متصفح ولي الأمر → MathTrail: authorize
شاشة موافقة خاصة بالخدمة: أي عميل هذا، وإلى أين سيُعاد ولي الأمر
5متصفح ولي الأمر → Google: تسجيل الدخول باستخدام حساب Google · نطاق drive.file وحده
6Google → متصفح ولي الأمر: العودة، مع رمز التفويض من Google
7متصفح ولي الأمر → MathTrail: /oauth/callback
8MathTrail → Google: استبدال رمز التفويض
9MathTrail → Drive: /about — لمن هذا الحساب على Drive؟
معرّف المستخدم = HMAC لحساب Drive · رموز Google المميزة مختومة داخل رمز التفويض الخاص بنا
10MathTrail → متصفح ولي الأمر: 302 · code = mt1.c.…
11متصفح ولي الأمر → المضيف: إعادة رمز التفويض
12المضيف → MathTrail: /oauth/token · رمز التفويض + أداة التحقق
13MathTrail → المضيف: الدخول 15 د · إعادة التحميل 30 يومًا
يسجّل ولي الأمر الدخول مرة واحدة. ولا تحتفظ الخدمة بشيء من هذا التبادل: فالطلب ينتقل مختومًا في المعامل state، ورموز Google المميزة في رمز تفويض مختوم.
المسألة الحالية بوصفها آلة حالات
كل قاعدة من نوع «مرة واحدة فقط» حقل في الملف الشخصي، يُفحص ضمن القراءة والحساب والكتابة نفسها. ولا شيء آخر يتذكر أي شيء.
nonenext_taskالتكليف جاهزrequestedsubmit_task ✓خُتمت وأُعطيتissuedsubmit_answerسُجّلت مرة واحدةanswered
requested ↺رفض مع بقاء محاولات، ولا أكثر من ثلاث لكل طلبrequested → noneثلاث حالات رفض، أو 15 دقيقة منذ فتح الطلب؛ لا تُستهلك مسائل اليوم، وتُحتسب حالات الرفض الثلاث طلبًا فاشلًا من طلبات اليومissued → requested«مسألة أخرى» قبل الإجابة: يُسجَّل التخطي، ولا يتغير التصنيفanswered ↺أي إجابة لاحقة، من علامة تبويب ثانية أو من النموذج، تتلقى النتيجة الأولى ولا تكتب شيئًاanswered → requestedالمسألة التالية، على بطاقة جديدة؛ والمسألة التي أُجيب عنها لم تعد الحاليةanswered → issuedالمسألة التالية مكتوبة مسبقًا: يضعها next_task على بطاقة جديدة فورًا، متجاوزًا الحالة requestedissued → noneلم يعد ممكنًا فتح الختم، فقد دُوّر المفتاح مرتين؛ ولا يُسجَّل شيء
03
أين تقيم الحالة
كل ما كان خادم ذو حالة سيحفظه في قاعدة بيانات يحفظه طرف آخر: في رمز مميز مختوم تحمله الدردشة، أو في ملف تعريف ارتباط في متصفح ولي الأمر، أو في Drive الخاص بولي الأمر نفسه. أعيدوا تشغيل الخدمة أو شغّلوا نسخة ثانية منها: لن يضيع شيء.
MathTrail نفسه
لا شيء
لا حسابات، ولا جلسات، ولا تسجيلات للعملاء، ولا رموز مميزة من Google. كل طلب يحمل كل ما يحتاج إليه.
مخزن الرموز المميزة في الدردشة
رموز مميزة مختومة، معتمة على المضيف
- رمز الدخول
- 15 د
- رمز إعادة التحميل
- 30 يومًا، ≤ 90
تُختم بداخلها رموز Google المميزة، ومعرّف مستخدم معتم للحدود، والبلد الذي سجّل منه ولي الأمر الدخول.
متصفح ولي الأمر
ملفا تعريف ارتباط، بلا جلسة
- العملاء الموافق عليهم
- 180 يومًا
- حماية تسجيل الدخول (CSRF)
- 10 د
فقدانهما يكلّف شاشة موافقة إضافية، أو تسجيل دخول جديدًا.
Drive الخاص بولي الأمر
الشيء الوحيد الذي يُحفظ طويلًا
mathtrail-profile.json- حتى الحذف
الملف الشخصي، والتصنيفات، والمسألة الحالية بإجابتها المختومة. يمكن لولي الأمر فتح الملف، ويحتفظ Drive بنُسخه السابقة.
Secret Manager
تُقرأ مرة واحدة، عند بدء تشغيل مثيل
- مفاتيح الختمبعد التدوير، يبقى المفتاح السابق مقبولًا
- 90 يومًا
- سر العميل من Google
- مثبّت
ذاكرة المثيل
ذاكرة تخزين مؤقت فقط: تضيع عند إعادة التشغيل، ولا يتعطل شيء
- عدّادات وتيرة الطلبات
- دقائق
- مكان ملف الملف الشخصي
- 10 د
- مستندات العملاء
- من 5 د إلى 24 س
ما استُبعد عمدًا من v1
- قاعدة بيانات
- قوائم انتظار
- مخزن جلسات
- ذاكرة تخزين مؤقت مشتركة
- بنك مسائل جاهزة
- عميل API لنموذج LLM
- REST وOpenAPI
04
ملف الملف الشخصي
طفل واحد، ملف JSON واحد: ليس ذاكرة تخزين مؤقت لحقيقة ما على خادم، بل الحقيقة نفسها. لكل قسم سقف يُلتزم به في كل كتابة، فلا يكبر الملف بلا حد: الملف المعتاد يبقى ضمن الهدف، والملف القريب من أسقفه يتجاوزه. وتُحفظ المسائل السابقة بصمات، لا نصوصًا.
حجم الملف
≈ 61 KB / ≈ 79 KB
| القسم | ما يحتويه | من يكتبه | الحجم | |
|---|---|---|---|---|
| البصمات | حتى 200 رسم تقريبي للمسائل التي أُعطيت، لفحص المسائل شبه المكررة، دون نص أو موضوع أو تاريخ | next_tasksubmit_task | 27 KB / 29 KB | |
| سجل التصنيف | قيمة θ وقيمة δ للموضوع قبل كل إجابة حديثة، وقيمة θ وقيم كل المواضيع في بداية كل يوم من آخر 7 أيام فيها إجابات | submit_answer | 14 KB / 15 KB | |
| التصنيفات والمواضيع | θ ونقطة انطلاق الطفل؛ ولكل موضوع: δ، والإجابات، والفخاخ التي سبق الوقوع فيها، والإتقان ومستواه | next_tasksubmit_tasksubmit_answer | 8 KB / 14 KB | |
| الإجابات الأخيرة | آخر 20 من الإجابات وحالات التخطي، ولا يقل ما فيها عن 5 إجابات أبدًا، فهي ما تقرؤه القاعدة | next_tasksubmit_answer | 4 KB / 5 KB | |
| المسألة الحالية، مختومة | الإجابة، والفخ وراء كل خيار خاطئ، والحل، وبرنامج الحل، في سلسلة واحدة معتمة | next_tasksubmit_tasksubmit_answer | 4 KB / 8 KB | |
| المسألة الحالية، مكشوفة | ما تعرضه البطاقة: النص، والرسم، وخمسة خيارات، والتلميح، وبعد الإجابة، الإجابة نفسها | next_tasksubmit_tasksubmit_answer | 2 KB / 4 KB | |
| الطلب المفتوح | في أثناء كتابة المسألة: معرّفها، والتكليف، والمحاولات المستخدمة، ومن اختار الموضوع | next_taskprepare_tasksubmit_task | 1.5 KB / 2 KB | |
| الخدمة والطفل | إصدار المخطط، وUUID عشوائي، والنسخة؛ والاسم المستعار، والصف، والاهتمامات، والملاحظات؛ وعدّادات اليوم | save_profileedit_profileكل كتابة | 0.6 KB / 1.5 KB |
تُحفظ المسألة المكتوبة مسبقًا بجانب الحالية، ويقارب حجمها حجم الحالية. ما لا يحتويه الملف: نصوص المسائل السابقة، والإجابة مكشوفة قبل إجابة الطفل، وأي شيء يسمّي ولي الأمر، والمرحلة، إذ تُحسب المراحل عند عرضها. ولا يدعم Drive الكتابة المشروطة، لذا يُقرأ الملف مرة أخرى قبل الحفظ، وتُرفض الكتابة إن كان قد تغيّر: فلا تمحو علامة تبويب ما كتبته الأخرى بصمت أبدًا.
05
ما يُختم، ولأي مدة
آلية واحدة تؤدي مهمتين: تختم تسجيل الدخول داخل الرموز المميزة التي تحملها الدردشة، وتختم داخل الملف الشخصي إجابة المسألة الحالية وإجابة المسألة المكتوبة مسبقًا. ويحمل كل ختم غرضه، فلا يمكن أن يُقدَّم رمز الدخول على أنه رمز إعادة تحميل، ولا أن تُقدَّم إجابة مختومة على أنها أي شيء آخر.
تشريح رمز مميز
mt1.a.kQ7fWx.5rJ0Yb2mQ8vK1nT4pXc9…
- mt1
- إصدار الصيغة
- الغرض
- c رمز التفويض · a الدخول · r إعادة التحميل · d العميل · s الحالة · k الموافقة · t إجابة مسألة
- معرّف المفتاح
- مأخوذ من المفتاح نفسه، فيمر التدوير دون أن يُلاحظ
- النص المشفر
- XChaCha20-Poly1305، وnonce عشوائي بطول 192 بت
ليس JWT: لا يقرؤه أحد غير الخدمة، ولا يمكن أن تتسرّب أي مطالبة إلى السجل من سلسلة معتمة.
مدد الصلاحية، على مقياس لوغاريتمي
- رمز التفويض
60 ث - تسجيل الدخول قيد التنفيذ
10 د - رمز الدخول
15 د - رمز إعادة التحميل
30 يومًا بنافذة منزلقة، 90 على الأكثر - مفتاح الختم
يُدوَّر كل 90 يومًا - العملاء الموافق عليهم
180 يومًا
لا يستطيع خادم بلا حالة أن يعلّم رمز التفويض بأنه استُخدم، لذا تُبقى نافذة الرمز صغيرة. وبعد التدوير يبقى المفتاح السابق مقبولًا، فلا يضيع رمز مميز ولا إجابة مختومة عند تغيّر المفتاح.