# واجهة KolWrite البرمجية لوكلاء الذكاء الاصطناعي

كيف تتيح لوكيل ذكاء اصطناعي (Claude Code أو Codex أو Cursor أو سكربت من إعدادك)
أن يحوّل التسجيلات إلى نصوص مفرّغة وترجمات SRT وتوقيتات للكلمات عبر واجهة منصة
KolWrite على العنوان `https://api.kolwrite.com`. يُنشئ شخص ما رمزًا مرة واحدة،
ثم يقرؤه الوكيل من متغير بيئة ويستدعي HTTPS مباشرة. لا حاجة إلى حزمة SDK.

هذه واجهة المنصة التي تعمل برموز `kol_`. أما واجهة الرصيد على
`https://app.kolwrite.com` (الترويسة `x-api-key`) فهي واجهة مختلفة، وتجد وصفها (بالإنجليزية) في
https://console.kolwrite.com/llms.txt للاطلاع.

## 1. امنح الوكيل رمزًا

- يُفعَّل الوصول إلى الواجهة لكل حساب على حدة؛ وبدونه يُرفض إنشاء الرمز أو استخدامه.
- ينشئ شخص ما الرمز في تطبيق KolWrite (**الإعدادات ← الحساب ← الوصول إلى API ←
  إنشاء رمز**) ويختار أصغر مجموعة من النطاقات. يظهر السر (`kol_...`) مرة واحدة.
- احفظه في متغير بيئة، وأبعده عن الموجّهات والسجلات وgit.

| المهمة | النطاقات |
|---|---|
| التفريغ والتصدير | `files:write` و`jobs:write` و`jobs:read` و`transcripts:read` |
| ومعها فحص الرصيد | أضف `billing:read` |
| نقاط النهاية المتوافقة مع OpenAI | `ai:use` (يستهلك الرصيد؛ وليس ضمن الإعداد الجاهز Automation في التطبيق) |
| إنشاء روابط المشاركة | أضف `shares:write` |

الصق هذا في `AGENTS.md` أو `CLAUDE.md` أو `.cursorrules`:

```
## KolWrite platform API
- Base URL https://api.kolwrite.com. The token is in the environment variable KOLWRITE_TOKEN: send it as "Authorization: Bearer $KOLWRITE_TOKEN" and never print it.
- Flow: POST /api/v1/media/upload-session, PUT the bytes to data.upload_url, POST /api/v1/media/complete, POST /api/v1/jobs, poll GET /api/v1/jobs/{job_id} until status is succeeded, then GET /api/v1/jobs/{job_id}/export?format=json
- Spec: https://kolwrite-docs.pages.dev/openapi.json. Guide: https://kolwrite-docs.pages.dev/agents.md
```

## 2. أي استدعاء تستخدم

| ما تريده | الاستدعاء |
|---|---|
| نص مفرّغ لملف، مع توقيتات الكلمات والمتحدثين | جلسة رفع، ثم `POST /api/v1/jobs` (`type: transcription`)، ثم `GET /api/v1/jobs/{job_id}/export?format=json` |
| ترجمات SRT أو VTT | `GET /api/v1/jobs/{job_id}/export?format=srt` أو `format=vtt` (خطة Plus أو أعلى) |
| ترجمات بلغة أخرى | `options.target_language` في المهمة، ثم التصدير |
| نص عادي | `export?format=text` |
| نص لمقطع صوتي قصير، بلا مهمة | `POST /api/v1/ai/openai/audio/transcriptions` |
| محادثة واستجابات وتضمينات | `/api/v1/ai/openai/*` ([نقاط النهاية المتوافقة مع OpenAI](/locales/ar/openai-compatible.md)) |
| النص المحفوظ بإصداراته | `GET /api/v1/jobs/{job_id}/artifacts` |
| رصيد الحساب | `GET /api/v1/billing/balance` |
| رابط عام لنص مفرّغ | `POST /api/v1/shares` |
| ملفات النماذج المتاحة | `GET /api/v1/models` |

## 3. تفريغ ملف بلغة Python

```python
import json, mimetypes, os, time
import requests

BASE = "https://api.kolwrite.com"
TOKEN = os.environ["KOLWRITE_TOKEN"]


def call(method, path, **kw):
    headers = {"Authorization": f"Bearer {TOKEN}", **kw.pop("headers", {})}
    r = requests.request(method, BASE + path, headers=headers, timeout=120, **kw)
    r.raise_for_status()
    return r


def transcribe(path, profile="oracle", language="auto"):
    name, size = os.path.basename(path), os.path.getsize(path)
    ctype = mimetypes.guess_type(name)[0] or "application/octet-stream"
    session = call("POST", "/api/v1/media/upload-session",
                   json={"filename": name, "file_size_bytes": size,
                         "content_type": ctype}).json()["data"]
    with open(path, "rb") as f:
        requests.put(session["upload_url"], data=f, headers=session["headers"],
                     timeout=3600).raise_for_status()
    media = call("POST", "/api/v1/media/complete",
                 json={"finalize_token": session["finalize_token"]}).json()["data"]
    job = call("POST", "/api/v1/jobs",
               headers={"Idempotency-Key": f"{name}-{size}-{profile}-{language}"},
               json={"type": "transcription",
                     "input": {"type": "media_ref", "media_id": media["media_id"]},
                     "profile": profile,
                     "options": {"language": language,
                                 "diarization": {"mode": "regular"}}}).json()["data"]
    while True:
        status = call("GET", f"/api/v1/jobs/{job['job_id']}").json()["data"]["status"]
        if status in ("succeeded", "failed", "cancelled"):
            break
        time.sleep(5)
    if status != "succeeded":
        raise RuntimeError(f"job {job['job_id']} {status}")
    export = call("GET", f"/api/v1/jobs/{job['job_id']}/export",
                  params={"format": "json"}).json()
    return job["job_id"], json.loads(export["data"])  # data is a JSON string


job_id, transcript = transcribe("interview.wav")
for seg in transcript["segments"]:
    print(f"{seg['start']:.2f}-{seg['end']:.2f} {seg.get('speaker', '')} {seg['text']}")
```

تُرفع الملفات الكبيرة على أجزاء: تُعيد الجلسة حينها `data.upload_url` بقيمة `null`
وعنوان URL لكل جزء في `data.multipart_part_urls` (راجع
[البدء السريع](/locales/ar/quickstart.md)).

## 4. استخدم التوقيتات

يتضمن تصدير JSON الحقل `segments`، ولكل مقطع `start` و`end` بالثواني، و`text`، و`speaker`
عند تشغيل فصل المتحدثين، و`words` (`text` و`start` و`end`). دع الوكيل يختار المقاطع
بحسب رقمها ويقرأ الأزمنة من النص المفرّغ؛ ولا تدع النموذج يكتب الطوابع الزمنية بنفسه.

```python
import subprocess

keep = [s for s in transcript["segments"] if "pricing" in s["text"].lower()]
for i, seg in enumerate(keep):
    subprocess.run(["ffmpeg", "-y", "-i", "talk.mp4", "-ss", str(seg["start"]),
                    "-to", str(seg["end"]), f"clip{i}.mp4"], check=True)
```

تأتي الترجمات مباشرة من الواجهة. يحذف `include_speakers=false` أسماء المتحدثين،
ويحدد `max_chars_per_entry` طول كل سطر ترجمة:

```bash
curl -H "Authorization: Bearer $KOLWRITE_TOKEN" -o talk.srt \
  "https://api.kolwrite.com/api/v1/jobs/JOB_ID/export?format=srt&include_speakers=false&max_chars_per_entry=42"
```

يتطلب تنزيل SRT وVTT خطة Plus أو أعلى. تتلقى الخطط الأخرى HTTP 403 مع الرمز
`subtitle_export_requires_plus`؛ ولا يتأثر تصدير JSON والنص.

## 5. قواعد للوكلاء

- أرسل `Idempotency-Key` عند إنشاء مهمة، كي لا تبدأ إعادة المحاولة مهمة ثانية.
- أعد المحاولة بعد `429` و`502` و`503` و`504` بتأخير متزايد أُسّيًا؛ وعند `429` انتظر
  حسب `Retry-After`. لا تعد المحاولة بعد `401` أو `403` أو أخطاء التحقق. راجع
  [الأخطاء](/locales/ar/errors.md).
- اقرأ `detail.code` لا نص الرسالة.
- تحجز المهمة رصيدًا عند إنشائها وتسوّيه عند انتهائها؛ افحص
  `GET /api/v1/billing/balance` قبل دفعة كبيرة.
- ملف OpenAPI هو العقد: كل عملية تذكر النطاق المطلوب لها في `x-required-scope`.

## أسئلة

### كيف أصنع ترجمات SRT من فيديو باستخدام وكيل ذكاء اصطناعي؟

ارفع الملف، وأنشئ مهمة تفريغ، وانتظر حتى تصبح الحالة `succeeded`، ثم استدعِ نقطة
التصدير مع `format=srt`. تتطلب الترجمات خطة Plus أو أعلى.

### هل يستطيع Claude Code أو Codex استدعاء واجهة KolWrite؟

نعم. يستدعيانها عبر HTTPS برمز وصول شخصي من متغير بيئة. لا توجد حزمة SDK ولا خادم
MCP لتثبيته.

### كيف يحصل الوكيل على الطوابع الزمنية لكل كلمة؟

صدّر المهمة بصيغة JSON. يحمل كل مقطع `words` مع `start` و`end` بالثواني.
