# أضف ودجت الدردشة

> أضف ودجت دردشة K-Agent إلى موقعك بوسم script واحد، ودع المستخدمين المسجّلين يحادثون الوكيل بوصفهم عملاء موثّقين عبر رموز عميل يصدرها خادمك.

الودجت فقاعة دردشة لموقعك: وسم `<script>` واحد، دون أي خطوة بناء، ويعمل على أي موقع. هو مكوّن ويب (`<k-agent-chat>`) داخل shadow DOM خاص به، فلا تتعارض أنماط موقعك مع أنماطه أبدًا. يتحدث العربية (من اليمين لليسار) والإنجليزية، ويبث الردود، ويعرض ردود فريقك مباشرة أثناء التحويل، وحجمه أقل من 60 كيلوبايت مضغوطًا.

## 1. أنشئ مفتاحًا قابلًا للنشر

من لوحة التحكم افتح **مفاتيح API ← إنشاء مفتاح قابل للنشر**، واسرد **المصادر المسموح بها** — المواقع التي يُسمح لها بتحميل الودجت بالضبط:

- اكتب كل مصدر بالصيغة `scheme://host[:port]`، مثل `https://www.example.com`؛
- `https://*.example.com` يطابق مستوى واحدًا من النطاقات الفرعية بالضبط؛
- `http://localhost:3000` يجب أن يُدرج صراحة للتطوير المحلي؛
- مصدر واحد على الأقل إلزامي (`422 allowed_origins_required`).

المفتاح القابل للنشر (`kt_pk_live_…`) آمن في صفحتك: لا يستطيع إلا قراءة إعدادات الودجت وبدء جلسات الودجت، ومن تلك المصادر فقط.

## 2. أضف السكربت

الصق هذا قبل `</body>`:

```html
<script
  src="https://api.k-agent.kerneltics.com/widget/v1.js"
  data-agent="agt_01k6rz1m3w8q4t7v9x2b5c0dnf"
  data-key="kt_pk_live_…"
  defer
></script>
```

هذا كل ما يلزم للزوار المجهولين. يحمّل الودجت إعدادات الوكيل **المنشورة** — `bot_name` و`greeting` و`launcher_label` و`theme.accent` و`theme.position` — فتغيّر مظهره من محرّر الوكيل لا من الكود.

| خاصية السكربت | الوصف |
|---|---|
| `data-agent` | معرّف الوكيل. |
| `data-key` | مفتاحك القابل للنشر. |
| `data-api` | اختيارية. مصدر الواجهة البرمجية، إن كان مختلفًا عن المصدر الذي يقدّم السكربت. |

### أو ضع العنصر بنفسك

للتحكم في مكان الدردشة وطريقة ظهورها، حمّل السكربت دون `data-agent` وأضف العنصر:

```html
<script src="https://api.k-agent.kerneltics.com/widget/v1.js" defer></script>

<k-agent-chat
  agent="agt_01k6rz1m3w8q4t7v9x2b5c0dnf"
  publishable-key="kt_pk_live_…"
  lang="ar"
  position="end"
></k-agent-chat>
```

| خاصية العنصر | الوصف |
|---|---|
| `agent` | معرّف الوكيل. إلزامية. |
| `publishable-key` | مفتاحك القابل للنشر. |
| `token-endpoint` | رابط في موقعك يعيد رمز عميل للمستخدم المسجّل (الخطوة 3). |
| `api-base` | مصدر الواجهة البرمجية، اختيارية. |
| `lang` | `ar` أو `en`. الافتراضي خاصية `lang` في العنصر، ثم `<html lang>`، ثم لغة الوكيل. والعربية تُعرض من اليمين لليسار. |
| `position` | `start` أو `end` (الافتراضي). تتبع اتجاه الصفحة: `end` أسفل اليسار بالعربية وأسفل اليمين بالإنجليزية. |
| `open` | وجودها يفتح الدردشة من البداية. |

## ما يحصل عليه الزوار

- تتدفق الردود أثناء كتابتها، وتظهر رسائل الزوار والوكلاء بالاتجاه المناسب للغتها.
- تُحفظ المحادثة لكل متصفح: الزائر الذي يعود من الجهاز نفسه يكمل من حيث توقف. وخيار **محادثة جديدة** يبدأ من الصفر.
- أثناء التحويل يوضح رأس الدردشة أن موظفًا أصبح في المحادثة، وتظهر ردود فريقك مباشرة.
- الودجت يعمل جيدًا مع لوحة المفاتيح وقارئات الشاشة، ويملأ الشاشة على الجوال.

### الزوار المجهولون

الزوار غير المسجّلين **عملاء مجهولون**. ولسلامتهم وسلامتك:

- الأدوات ذات الأثر معطّلة ما لم يفعّل الوكيل `tools.allow_anonymous_actions`؛
- الأدوات التي تحتاج هوية موثّقة لا تعمل أبدًا؛
- تنطبق حدود: لكل عنوان IP، 20 محادثة و60 رسالة في الساعة؛ و40 رسالة كحد أقصى في المحادثة الواحدة؛ و`widget.anonymous_daily_conversations` لكل وكيل (الافتراضي 200). وبعد بلوغ الحد يرى الزائر رسالة مهذبة بالمحاولة لاحقًا.

## 3. المستخدمون المسجّلون (موثّقون)

حين يكون الزائر مسجّلًا الدخول في موقعك، دعه يحادث الوكيل **بهويته**: يستطيع الوكيل حينها استخدام الأدوات المرتبطة بالهوية («وين *طلبي*؟»)، وتذكّر إجراءاته السابقة، ويعرف فريقك من هو.

يصدر خادمك **رمز عميل** قصير العمر للمستخدم بمفتاحك السري، ويجلبه الودجت من `token-endpoint` في موقعك. المفتاح السري لا يصل إلى المتصفح أبدًا.

```html
<script src="https://api.k-agent.kerneltics.com/widget/v1.js" defer></script>

<k-agent-chat
  agent="agt_01k6rz1m3w8q4t7v9x2b5c0dnf"
  publishable-key="kt_pk_live_…"
  token-endpoint="/kagent/token"
></k-agent-chat>
```

يرسل الودجت طلب `POST` إلى `token-endpoint` من صفحتك (مع ملفات تعريف الارتباط الخاصة بموقعك، كطلب من المصدر نفسه)، ويتوقع JSON يحوي `token` و`expires_at`، كما يعيدهما `POST /v1/client_tokens` بالضبط. ويطلب رمزًا جديدًا قبل انتهاء صلاحية الرمز.

**JavaScript**

```js
// Node.js + Express. `requireLogin` is your own authentication middleware.
import express from 'express';

const app = express();

app.post('/kagent/token', requireLogin, async (req, res) => {
  const r = await fetch('https://api.k-agent.kerneltics.com/v1/client_tokens', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.KAGENT_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      agent: 'agt_01k6rz1m3w8q4t7v9x2b5c0dnf',
      end_user: {
        external_id: req.user.customerId, // your stable ID — never an email or phone
        name: req.user.firstName,
        traits: { plan: req.user.plan },
      },
      ttl_seconds: 900,
    }),
  });
  if (!r.ok) return res.status(502).json({ error: 'token_unavailable' });
  const { token, expires_at } = await r.json();
  res.set('Cache-Control', 'no-store').json({ token, expires_at });
});
```

**Python**

```python
# Flask. `login_required` and `current_user` come from your own auth (e.g. Flask-Login).
import os
import requests
from flask import Flask

app = Flask(__name__)

@app.post("/kagent/token")
@login_required
def kagent_token():
    r = requests.post(
        "https://api.k-agent.kerneltics.com/v1/client_tokens",
        headers={"Authorization": f"Bearer {os.environ['KAGENT_API_KEY']}"},
        json={
            "agent": "agt_01k6rz1m3w8q4t7v9x2b5c0dnf",
            "end_user": {
                "external_id": current_user.customer_id,  # never an email or phone
                "name": current_user.first_name,
                "traits": {"plan": current_user.plan},
            },
            "ttl_seconds": 900,
        },
        timeout=10,
    )
    if not r.ok:
        return {"error": "token_unavailable"}, 502
    data = r.json()
    return {"token": data["token"], "expires_at": data["expires_at"]}, 200, {"Cache-Control": "no-store"}
```

- احمِ نقطة النهاية بتسجيل الدخول المعتاد لديك، ولا تصدر الرموز إلا للمستخدم المسجّل نفسه. فالرمز يتيح لحامله المحادثة بصفة ذلك الشخص لمدة `ttl_seconds` (3600 كحد أقصى؛ و900 قيمة افتراضية جيدة).
- استخدم معرّفًا `external_id` ثابتًا ومبهمًا للمستخدم. وإن كان مفتاحك الوحيد بريدًا أو رقم جوال [فاشتقّ منه معرّفًا بالتجزئة](/docs/concepts/sessions/#لا-بيانات-شخصية-في-المعرّفات).
- لمواصلة محادثة بعينها أضف `"session": "<sess_ or external_id>"` عند إصدار الرمز.
- لتمرير قيم المتغيرات التي يعرّفها الوكيل بخاصية `client_settable` أضف `"variables": {…}`.
- يتوقف الرمز عن العمل عند انتهاء صلاحيته، أو عند إلغاء المفتاح الذي أصدره، أو عند محو العميل.

## سياسة أمان المحتوى (CSP)

إذا كان موقعك يرسل ترويسة CSP فاسمح بسكربت الودجت وطلباته إلى الواجهة البرمجية:

```text
script-src 'self' https://api.k-agent.kerneltics.com;
connect-src 'self' https://api.k-agent.kerneltics.com;
```

## حل المشكلات

| الخطأ | السبب والحل |
|---|---|
| `403 origin_not_allowed` | مصدر الصفحة غير مدرج في قائمة المفتاح. أضفه بالضبط، بما في ذلك المنفذ. |
| `403 origin_required` | لم يصدر الطلب من صفحة في متصفح. المفاتيح القابلة للنشر لا تعمل إلا في المتصفحات. |
| `403 principal_not_allowed` | استدعت بيانات اعتماد المتصفح مسارًا لا يُسمح لها به. نفّذ هذا الطلب من خادمك بمفتاح سري. |
| `401 token_expired` | أعادت نقطة الرموز رمزًا منتهي الصلاحية، أو ساعة خادمك غير مضبوطة. |
| `429 anonymous_limit_reached` | بلغ زائر مجهول أحد الحدود. أما المستخدمون المسجّلون برموز العميل فلا يخضعون لهذه الحدود. |
