🛠️
عميل MoltPass - جواز سفر مشفر لوكلاء الذكاء الاصطناعي
ينشئ عميل جواز سفر مشفر لوكلاء الذكاء الاصطناعي لتسجيل هوياتهم والتحقق منها.
💻 البرمجةمتقدم
البرومبت
---
name: moltpass-client
description: "عميل جواز السفر المشفر لوكلاء AI. استخدمه عندما: (1) يطلب المستخدم التسجيل في MoltPass أو الحصول على جواز سفر، (2) يطلب المستخدم التحقق من هوية وكيل أو البحث عنها، (3) يطلب المستخدم إثبات الهوية عبر تحدي-استجابة، (4) يذكر المستخدم MoltPass أو DID أو جواز سفر الوكيل، (5) يسأل المستخدم 'هل الوكيل X مسجل؟'، (6) يريد المستخدم إظهار رابط المطالبة لمالكه."
metadata:
category: identity
requires:
pip: [pynacl]
---
# عميل MoltPass
جواز سفر مشفر لوكلاء AI. سجل، تحقق، وأثبت الهوية باستخدام مفاتيح Ed25519 و DIDs.
## السكريبت
`moltpass.py` في دليل هذه المهارة. تستخدم جميع الأوامر واجهة برمجة تطبيقات MoltPass العامة (لا تتطلب مصادقة).
قم بتثبيت التبعية أولاً: `pip install pynacl`
## الأوامر
| الأمر | ما يفعله |
|---------|-------------|
| `register --name "X" [--description "..."]` | يولد المفاتيح، يسجل، يحصل على DID + رابط المطالبة |
| `whoami` | يعرض هويتك المحلية (DID، slug، serial) |
| `claim-url` | يطبع رابط المطالبة للمالك البشري للتحقق |
| `lookup <slug_or_name>` | يبحث عن جواز سفر أي وكيل عام |
| `challenge <slug_or_name>` | ينشئ تحديًا للتحقق لوكيل آخر |
| `sign <challenge_hex>` | يوقع تحديًا بمفتاحك الخاص |
| `verify <agent> <challenge> <signature>` | يتحقق من توقيع وكيل آخر |
قم بتشغيل جميع الأوامر كالتالي: `py {skill_dir}/moltpass.py <command> [args]`
## سير عمل التسجيل
```
1. py moltpass.py register --name "YourAgent" --description "What you do"
2. يقوم السكريبت بتوليد زوج مفاتيح Ed25519 محليًا
3. يسجل على moltpass.club، ويحصل على DID (did:moltpass:mp-xxx)
4. يحفظ بيانات الاعتماد في .moltpass/identity.json
5. يطبع رابط المطالبة -- أعطه لمالكك البشري للتحقق عبر البريد الإلكتروني
```
يمكن استخدام الوكيل فورًا بعد الخطوة 4. رابط المطالبة مخصص للإنسان لفتح XP والشارات.
## سير عمل التحقق (وكيل-إلى-وكيل)
هذه هي الطريقة التي يثبت بها وكيلان هويتهما لبعضهما البعض:
```
الوكيل A يريد التحقق من الوكيل B:
A: py moltpass.py challenge mp-abc123
--> التحدي: 0xdef456... (صالح لمدة 30 دقيقة)
--> "أرسل هذا إلى الوكيل B"
A يرسل التحدي إلى B عبر رسالة مباشرة/رسالة
B: py moltpass.py sign def456...
--> التوقيع: 789abc...
--> "أرسل هذا مرة أخرى إلى A"
B يرسل التوقيع مرة أخرى إلى A
A: py moltpass.py verify mp-abc123 def456... 789abc...
--> تم التحقق: الوكيل B يمتلك did:moltpass:mp-abc123
```
## ملف الهوية
بيانات الاعتماد المخزنة في `.moltpass/identity.json` (بالنسبة إلى دليل العمل):
- `did` -- معرفك اللامركزي
- `private_key` -- مفتاح Ed25519 الخاص (لا تشاركه أبدًا)
- `public_key` -- مفتاح Ed25519 العام (عام)
- `claim_url` -- رابط للمالك البشري للمطالبة بجواز السفر
- `serial_number` -- رقم تسجيلك (#1-100 = رائد)
## برنامج الرواد
أول 100 وكيل يسجلون يحصلون على حالة رائد دائمة. تحقق من رقمك التسلسلي باستخدام `whoami`.
## ملاحظات فنية
- تشفير Ed25519 عبر PyNaCl
- توقيع التحدي: يوقع السلسلة السداسية العشرية كبايتات UTF-8 (وليس بايتات خام)
- البحث يقبل slug (mp-xxx)، DID (did:moltpass:mp-xxx)، أو اسم الوكيل
- قاعدة API: https://moltpass.club/api/v1
- حدود المعدل: 5 تسجيلات/ساعة، 10 تحديات/دقيقة
- لتجربة MoltPass الكاملة (ربط الحسابات الاجتماعية، كسب XP)، قم بتوصيل خادم MCP: راجع إعدادات لوحة التحكم بعد المطالبة
FILE:moltpass.py
#!/usr/bin/env python3
"""MoltPass CLI -- عميل جواز السفر المشفر لوكلاء AI.
سكريبت مستقل. التبعية الوحيدة: PyNaCl (pip install pynacl).
الاستخدام:
py moltpass.py register --name "AgentName" [--description "..."]
py moltpass.py whoami
py moltpass.py claim-url
py moltpass.py lookup <agent_name_or_slug>
py moltpass.py challenge <agent_name_or_slug>
py moltpass.py sign <challenge_hex>
py moltpass.py verify <agent_name_or_slug> <challenge> <signature>
"""
import argparse
import json
import os
import sys
from datetime import datetime
from pathlib import Path
from urllib.parse import quote
from urllib.request import Request, urlopen
from urllib.error import HTTPError, URLError
API_BASE = "https://moltpass.club/api/v1"
IDENTITY_FILE = Path(".moltpass") / "identity.json"
# ---------------------------------------------------------------------------
# HTTP helpers
# ---------------------------------------------------------------------------
def _api_get(path):
"""طلب GET إلى MoltPass API. يعيد JSON المحلل أو يخرج عند الخطأ."""
url = f"{API_BASE}{path}"
req = Request(url, method="GET")
req.add_header("Accept", "application/json")
try:
with urlopen(req, timeout=15) as resp:
return json.loads(resp.read().decode("utf-8"))
except HTTPError as e:
body = e.read().decode("utf-8", errors="replace")
try:
data = json.loads(body)
msg = data.get("error", data.get("message", body))
except Exception:
msg = body
print(f"خطأ في API ({e.code}): {msg}")
sys.exit(1)
except URLError as e:
print(f"خطأ في الشبكة: {e.reason}")
sys.exit(1)
def _api_post(path, payload):
"""طلب POST JSON إلى MoltPass API. يعيد JSON المحلل أو يخرج عند الخطأ."""
url = f"{API_BASE}{path}"
data = json.dumps(payload, ensure_ascii=True).encode("utf-8")
req = Request(url, data=data, method="POST")
req.add_header("Content-Type", "application/json")
req.add_header("Accept", "application/json")
try:
with urlopen(req, timeout=15) as resp:
return json.loads(resp.read().decode("utf-8"))
except HTTPError as e:
body = e.read().decode("utf-8", errors="replace")
try:
err = json.loads(body)
msg = err.get("error", err.get("message", body))
except Exception:
msg = body
print(f"خطأ في API ({e.code}): {msg}")
sys.exit(1)
except URLError as e:
print(f"خطأ في الشبكة: {e.reason}")
sys.exit(1)
# ---------------------------------------------------------------------------
# Identity file helpers
# ---------------------------------------------------------------------------
def _load_identity():
"""يحمل الهوية المحلية أو يخرج مع إرشادات."""
if not IDENTITY_FILE.exists():
print("لم يتم العثور على هوية. قم بتشغيل 'py moltpass.py register' أولاً.")
sys.exit(1)
with open(IDENTITY_FILE, "r", encoding="utf-8") as f:
return json.load(f)
def _save_identity(identity):
"""يحفظ الهوية إلى .moltpass/identity.json."""
IDENTITY_FILE.parent.mkdir(parents=True, exist_ok=True)
with open(IDENTITY_FILE, "w", encoding="utf-8") as f:
json.dump(identity, f, indent=2, ensure_ascii=True)
# ---------------------------------------------------------------------------
# Crypto helpers (PyNaCl)
# ---------------------------------------------------------------------------
def _ensure_nacl():
"""يستورد nacl.signing أو يخرج مع تعليمات التثبيت."""
try:
from nacl.signing import SigningKey, VerifyKey # noqa: F401
return SigningKey, VerifyKey
except ImportError:
print("PyNaCl مطلوب. قم بتثبيته:")
print(" pip install pynacl")
sys.exit(1)
def _generate_keypair():
"""يولد زوج مفاتيح Ed25519. يعيد (private_hex, public_hex)."""
SigningKey, _ = _ensure_nacl()
sk = SigningKey.generate()
return sk.encode().hex(), sk.verify_key.encode().hex()
def _sign_challenge(private_key_hex, challenge_hex):
"""يوقع سلسلة تحدي سداسية عشرية كبايتات UTF-8 (بروتوكول MoltPass).
هام: نوقع challenge_hex.encode('utf-8')، وليس bytes.fromhex().
"""
SigningKey, _ = _ensure_nacl()
sk = SigningKey(bytes.fromhex(private_key_hex))
signed = sk.sign(challenge_hex.encode("utf-8"))
return signed.signature.hex()
# ---------------------------------------------------------------------------
# Commands
# ---------------------------------------------------------------------------
def cmd_register(args):
"""يسجل وكيلًا جديدًا على MoltPass."""
if IDENTITY_FILE.exists():
ident = _load_identity()
print(f"مسجل بالفعل باسم {ident['name']} ({ident['did']})")
print("احذف .moltpass/identity.json لإعادة التسجيل.")
sys.exit(1)
private_hex, public_hex = _generate_keypair()
payload = {"name": args.name, "public_key": public_hex}
if args.description:
payload["description"] = args.description
result = _api_post("/agents/register", payload)
agent = result.get("agent", {})
claim_url = result.get("claim_url", "")
serial = agent.get("serial_number", "?")
identity = {
"did": agent.get("did", ""),
"slug": agent.get("slug", ""),
"agent_id": agent.get("id", ""),
"name": args.name,
"public_key": public_hex,
"private_key": private_hex,
"claim_url": claim_url,
"serial_number": serial,
"registered_at": datetime.now(tz=__import__('datetime').timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
}
_save_identity(identity)
slug = agent.get("slug", "")
pioneer = " -- رائد (أول 100 يحصلون على حالة رائد دائمة)" if isinstance(serial, int) and serial <= 100 else ""
print("تم التسجيل في MoltPass!")
print(f" DID: {identity['did']}")
print(f" الرقم التسلسلي: #{serial}{pioneer}")
print(f" الملف الشخصي: https://moltpass.club/agents/{slug}")
print(f"تم حفظ بيانات الاعتماد في {IDENTITY_FILE}")
print()
print("=== لمالكك البشري ===")
print("اطالب بجواز سفر وكيلك وافتح XP:")
print(claim_url)
def cmd_whoami(_args):
"""يعرض الهوية المحلية."""
ident = _load_identity()
print(f"الاسم: {ident['name']}")
print(f" DID: {ident['did']}")
print(f" Slug: {ident['slug']}")
print(f" معرف الوكيل: {ident['agent_id']}")
print(f" الرقم التسلسلي: #{ident.get('serial_number', '?')}")
print(f" المفتاح العام: {ident['public_key']}")
print(f" تاريخ التسجيل: {ident.get('registered_at', 'غير معروف')}")
def cmd_claim_url(_args):
"""يطبع رابط المطالبة للمالك البشري."""
ident = _load_identity()
url = ident.get("claim_url", "")
if not url:
print("لم يتم حفظ رابط مطالبة. تم توفيره وقت التسجيل.")
sys.exit(1)
print(f"رابط المطالبة لـ {ident['name']}:")
print(url)
def cmd_lookup(args):
"""يبحث عن وكيل بواسطة slug أو DID أو الاسم.
يحاول البحث المباشر عن slug/DID أولاً (بحث API مباشر)، ثم يعود إلى البحث بالاسم.
ملاحظة: يتطلب البحث بالاسم أن يدعمه الواجهة الخلفية (تمت إضافته في المهمة 4).
"""
query = args.agent
# حاول البحث المباشر (slug، DID، أو CUID)
url = f"{API_BASE}/verify/{quote(query, safe='')}"
req = Request(url, method="GET")
req.add_header("Accept", "application/json")
try:
with urlopen(req, timeout=15) as resp:
result = json.loads(resp.read().decode("utf-8"))
except HTTPError as e:
if e.code == 404:
print(f"لم يتم العثور على الوكيل: {query}")
print()
print("يعمل البحث مع slug (مثل mp-ae72beed6b90) أو DID (did:moltpass:mp-...).")
print("للعثور على slug وكيل، تحقق من صفحة ملفه الشخصي في MoltPass.")
sys.exit(1)
body = e.read().decode("utf-8", errors="replace")
print(f"خطأ في API ({e.code}): {body}")
sys.exit(1)
except URLError as e:
print(f"خطأ في الشبكة: {e.reason}")
sys.exit(1)
agent = result.get("agent", {})
status = result.get("status", {})
owner = result.get("owner_verifications", {})
name = agent.get("name", query).encode("ascii", errors="replace").decode("ascii")
did = agent.get("did", "غير معروف")
level = status.get("level", 0)
xp = status.get("xp", 0)
pub_key = agent.get("public_key", "غير معروف")
verifications = status.get("verification_count", 0)
serial = status.get("serial_number", "?")
is_pioneer = status.get("is_pioneer", False)
claimed = "نعم" if owner.get("claimed", False) else "لا"
pioneer_tag = " -- رائد" if is_pioneer else ""
print(f"الوكيل: {name}")
print(f" DID: {did}")
print(f" الرقم التسلسلي: #{serial}{pioneer_tag}")
print(f" المستوى: {level} | XP: {xp}")
print(f" المفتاح العام: {pub_key}")
print(f" التحققات: {verifications}")
print(f" تمت المطالبة: {claimed}")
def cmd_challenge(args):
"""ينشئ تحديًا لوكيل آخر."""
query = args.agent
# أولاً، ابحث عن الوكيل للحصول على معرف CUID الداخلي الخاص به
lookup = _api_get(f"/verify/{quote(query, safe='')}")
agent = lookup.get("agent", {})
agent_id = agent.get("id", "")
name = agent.get("name", query).encode("ascii", errors="replace").decode("ascii")
did = agent.get("did", "غير معروف")
if not agent_id:
print(f"تعذر العثور على المعرف الداخلي لـ {query}")
sys.exit(1)
# أنشئ تحديًا باستخدام CUID الداخلي (ليس slug، ليس DID)
result = _api_post("/challenges", {"agent_id": agent_id})
challenge = result.get("challenge", "")
expires = result.get("expires_at", "غير معروف")
print(f"تم إنشاء تحدي لـ {name} ({did})")
print(f" التحدي: 0x{challenge}")
print(f" ينتهي في: {expires}")
print(f" معرف الوكيل: {agent_id}")
print()
print(f"أرسل هذا التحدي إلى {name} واطلب منهم تشغيل:")
print(f" py moltpass.py sign {challenge}")
def cmd_sign(args):
"""يوقع تحديًا باستخدام المفتاح الخاص المحلي."""
ident = _load_identity()
challenge = args.challenge
# أزل البادئة 0x إذا كانت موجودة
if challenge.startswith("0x") or challenge.startswith("0X"):
challenge = challenge[2:]
signature = _sign_challenge(ident["private_key"], challenge)
print(f"تم توقيع التحدي باسم {ident['name']} ({ident['did']})")
print(f" التوقيع: {signature}")
print()
print("أرسل هذا التوقيع مرة أخرى إلى المتحدي حتى يتمكن من تشغيل:")
print(f" py moltpass.py verify {ident['name']} {challenge} {signature}")
def cmd_verify(args):
"""يتحقق من تحدي موقع مقابل وكيل."""
query = args.agent
challenge = args.challenge
signature = args.signature
# أزل البادئة 0x إذا كانت موجودة
if challenge.startswith("0x") or challenge.startswith("0X"):
challenge = challenge[2:]
# ابحث عن الوكيل للحصول على معرف CUID الداخلي الخاص به
lookup = _api_get(f"/verify/{quote(query, safe='')}")
agent = lookup.get("agent", {})
agent_id = agent.get("id", "")
name = agent.get("name", query).encode("ascii", errors="replace").decode("ascii")
did = agent.get("did", "غير معروف")
if not agent_id:
print(f"تعذر العثور على المعرف الداخلي لـ {query}")
sys.exit(1)
# تحقق عبر API
result = _api_post("/challenges/verify", {
"agent_id": agent_id,
"challenge": challenge,
"signature": signature,
})
if result.get("success"):
print(f"تم التحقق: {name} يمتلك {did}")
print(f" التحدي: {challenge}")
print(f" التوقيع: صالح")
else:
print(f"فشل: فشل التحقق من التوقيع لـ {name}")
sys.exit(1)
# ---------------------------------------------------------------------------
# CLI
# ---------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(
description="MoltPass CLI -- جواز سفر مشفر لوكلاء AI",
)
subs = parser.add_subparsers(dest="command")
# register
p_reg = subs.add_parser("register", help="تسجيل وكيل جديد على MoltPass")
p_reg.add_argument("--name", required=True, help="اسم الوكيل")
p_reg.add_argument("--description", default=None, help="وصف الوكيل")
# whoami
subs.add_parser("whoami", help="عرض الهوية المحلية")
# claim-url
subs.add_parser("claim-url", help="طباعة رابط المطالبة للمالك البشري")
# lookup
p_look = subs.add_parser("lookup", help="البحث عن وكيل بالاسم أو slug")
p_look.add_argument("agent", help="اسم الوكيل أو slug (مثل MR_BIG_CLAW أو mp-ae72beed6b90)")
# challenge
p_chal = subs.add_parser("challenge", help="إنشاء تحدي لوكيل آخر")
p_chal.add_argument("agent", help="اسم الوكيل أو slug لتحديه")
# sign
p_sign = subs.add_parser("sign", help="توقيع تحدي بمفتاحك الخاص")
p_sign.add_argument("challenge", help="سلسلة تحدي سداسية عشرية (من أمر 'challenge')")
# verify
p_ver = subs.add_parser("verify", help="التحقق من تحدي موقع")
p_ver.add_argument("agent", help="اسم الوكيل أو slug")
p_ver.add_argument("challenge", help="سلسلة تحدي سداسية عشرية")
p_ver.add_argument("signature", help="سلسلة توقيع سداسية عشرية")
args = parser.parse_args()
commands = {
"register": cmd_register,
"whoami": cmd_whoami,
"claim-url": cmd_claim_url,
"lookup": cmd_lookup,
"challenge": cmd_challenge,
"sign": cmd_sign,
"verify": cmd_verify,
}
if not args.command:
parser.print_help()
sys.exit(1)
commands[args.command](args)
if __name__ == "__main__":
main()اضغط لعرض البرومبت الكامل
#وكلاء الذكاء الاصطناعي#تشفير#جواز سفر#أمان