راهنمای ساخت افزونه
این راهنما «چطور» را میگوید: افزونه چطور نصب میشود، چطور درخواستهای کرسی را وارسی میکند، کرسی را چطور صدا میزند و صفحههایش چطور در پوستهٔ کرسی باز میشوند. برای همهٔ فیلدهای manifest به مرجع manifest و برای یک نمونهٔ کامل به افزونهٔ نمونه سر بزنید.
۱. فایل manifest
همه چیزِ افزونه در korsi-plugin.yaml است و کرسی چیزی بیرون از آن را نمیپذیرد. پیش از ارسال، آن را با همان مدلی که هر instance میخواند بسنجید:
uv run python -m korsi_api.tools.check_plugin_manifest korsi-plugin.yaml
صفحهٔ ارسال نسخه همین پرتال هم manifest را پیش از ارسال با JSON Schema و با بررسیهای کاتالوگ کرسی میسنجد و هر مشکل را کنار فیلد خودش نشان میدهد.
قاعدههایی که بیشتر از همه رد میکنند:
-
idبه شکل reverse-DNS و با حروف کوچک است، مثلir.acme.crm. -
هر چیزی که استفاده میکنید، باید scopeاش را خواسته باشید: نوع رکورد
records.ownمیخواهد، پیشنهادproposals.*، ورود منبعsources.intake.*، و فروش پلنwallet.consume. -
نرخ هر پلن فقط برای خدمتهایی است که در
servicesاعلام شدهاند. -
base_urlفقط برایexternalاست و باید https باشد، بهجزlocalhostدر توسعه. -
افزونهای که کنار instance اجرا میشود (
instance) بهجایbase_urlاینها را میدهد:imageبا digest؛portکه کانتینر روی آن HTTP گوش میدهد (پیشفرض 8080)؛egress، یعنی همهٔ مقصدهای خروجیاش.
آدرس را کرسی برای هر نصب جدا میسازد و همان را در
lifecycleمیفرستد. هر مقصدی غیر از اینها و خود کرسی بسته است. -
اگر نسخهٔ جدید
base_urlیاegressرا عوض کند، ادمین باید دوباره رضایت بدهد.
۲. نصب و اعتبارنامه
وقتی ادمین سازمان افزونه را نصب میکند، کرسی یک کاربر ماشینی برای آن نصب میسازد و به این آدرس خبر میدهد:
POST {base_url}/korsi/lifecycle
{
"event": "installed",
"installation_id": "…",
"api_base": "https://<instance>/plugin/v1",
"token": "…",
"signing_secret": "…",
"scopes": ["…"],
"settings": {}
}
tokenاعتبارنامهٔ افزونه برای/plugin/v1و سرور MCP کرسی است. آن را رمزشده نگه دارید.signing_secretکلیدی است که کرسی هر رویداد و هر فراخوان ابزار را با آن امضا میکند.- برای اطمینان، با همان توکن
GET {api_base}/installationرا صدا بزنید. {"event": "removed"}یعنی نصب حذف شده و توکن دیگر کار نمیکند.
نصب در حالت توسعه: وقتی کرسی به لپتاپ شما دسترسی ندارد، اعتبارنامه تحویل داده نمیشود. ادمین آن را یک بار از صفحهٔ نصب میخواند («خواندن اعتبارنامه») و به شما میدهد. سه چیز است:
- شناسهٔ نصب؛
- توکن؛
signing_secret، که بدون آن نمیشود رویدادها و فراخوانهای ابزار کرسی را وارسی کرد.
افزونهٔ نمونه آن را با email-commitments register میگیرد.
تحویل پس از ثبت: کرسی اعتبارنامه را فقط پس از ثبت کاربر ماشینی میفرستد. پس افزونه میتواند در جواب installed بیدرنگ با همان توکن GET /installation را صدا بزند. اگر افزونه جواب ندهد، کرسی با همان توکن دوباره میفرستد.
۳. امضا
هر درخواستی که کرسی به افزونه میفرستد، این هدر را دارد:
Korsi-Signature: t=<unix>,v1=<hex>
v1 برابر است با HMAC-SHA256 روی "<t>.<body>" با signing_secret. امضای قدیمیتر از پنج دقیقه را رد کنید. تابع verify_signature در نمونه همین کار را میکند.
۴. صدا زدن کرسی
خواندن دادهٔ کرسی: سرور MCP
پرونده، افراد، جلسه، سند، تقویم و حافظه را از سرور MCP کرسی و با همان توکن بخوانید. فقط ابزارهایی را میبینید که scopeهای تأییدشدهتان پوشش میدهند.
نوشتن: صفحهٔ افزونه (/plugin/v1)
مستندات OpenAPI آن در {api_base}/openapi.json است.
| کار | مسیر |
|---|---|
| خودم کیستم | GET /installation |
| همکارانی که میشود پیشنهاد را به آنها داد | GET /people |
| رکوردهای خودم | GET /records/{type}، GET/PUT/DELETE /records/{type}/{external_id} |
| پیشنهاد در رکوردهای کرسی | POST /proposals، GET /proposals |
| وارد کردن پیام یا سند برای بازبینی | POST /sources |
| کیف پول | GET /wallet، POST /wallet/holds، …/settle، …/release، POST /wallet/consume |
| رویدادها با polling | GET /events?after= |
نوشتن در رکوردهای کرسی همیشه پیشنهاد است. یک نفر آن را با کلیک خودش اعمال میکند، یا قاعدهای که سازمان برای نوعهای کمخطر گذاشته است. جواب به شکل رویداد plugin.proposal.settled برمیگردد و اگر کسی دلیل رد نوشته باشد، آن دلیل هم همراهش است. شخص میتواند اول با یک کلیک رد کند و دلیل را بعداً بنویسد. در این حالت همان رویداد یک بار دیگر برای همان external_id و این بار با reason میرسد. آن را بهروزرسانی بدانید، نه حکم تازه.
پول: پیش از هر خدمت رزرو کنید و بعد از آن تسویه. MU را کرسی از نرخ پلن فعال حساب میکند و افزونه فقط کلید خدمت و تعداد را میفرستد.
۵. رویدادها
POST {base_url}/korsi/events
رویدادها امضاشده و دستکم یکبارهاند و Korsi-Event-Id دارند. اگر سرور افزونه از بیرون در دسترس نیست، همین جریان را با GET /events?after= بخوانید.
۶. ابزار برای کرسیار
POST {base_url}/korsi/tools/{name}
بدنه اینهاست: installation_id، user_id، arguments و handle. با handle کرسی را بهجای همان شخص بخوانید. هر چه از این راه ببینید، همان چیزی است که آن شخص میبیند. جواب را به شکل {"content": …} و در کمتر از ده ثانیه برگردانید. ابزار نباید چیزی را تغییر دهد.
۷. صفحهها در پوستهٔ کرسی
ui.app و ui.panels داخل iframe و درون پوستهٔ کرسی باز میشوند. صفحه، Bridge را از همان کرسیای که در آن اجرا میشود بار میکند:
const bridge = await import(`${korsiOrigin}/sdk/korsi-bridge.js`);
const context = await bridge.connect(); // زبان، جهت، تم، تقویم، شخص، رکورد زمینه
const handle = await bridge.getHandle(); // دستهٔ مهرشدهٔ همین شخص، با تمدید خودکار
- با
handleصفحهٔ افزونه را بهجای همان شخص صدا بزنید. - دیالوگهای تأیید و انتخاب فرد یا پرونده را از Bridge بخواهید. اینها را خود کرسی میکشد.
- پنلها فقط وقتی بار میشوند که شخص خودش بازشان کند.
allowedOriginsرا درconnectبدهید و با هدرContent-Security-Policy: frame-ancestors <کرسیها>فقط به کرسی اجازه دهید صفحه را قاب کند.- رنگها، حالت روشن یا تیره، فونت، جهت و زبان در
korsi:init(و دوباره با هر تغییر) میرسد. افزونهٔ نمونه آنها را به متغیرهای CSS تبدیل میکند تا صفحه شبیه خود کرسی باشد.
۸. افزونهٔ نمونه و اجرای محلی
مخزن korsi-plugin-email-commitments یک افزونهٔ کامل است:
- شخص متن ایمیل را در صفحهٔ آن داخل کرسی میگذارد.
- افزونه تعهدها را پیدا میکند.
- بهجای همان شخص، ایمیل را منبع شخصی او میکند و هر تعهد همکار را بهصورت کار پیشنهادی برای خودش میفرستد.
- برای هر گفتگو یک رکورد «رشتهٔ ایمیل» نگه میدارد و هزینه را از کیف پولش میدهد.
اجرای آن کنار یک کرسی محلی:
cd korsi-plugin-email-commitments && uv sync && uv run email-commitments serve --port 8787
cd korsi-api && uv run python -m korsi_api.tools.plugin_dev_release ../korsi-plugin-email-commitments/korsi-plugin.yaml
دستور دوم نسخه را مستقیم در کاتالوگ instance محلی میگذارد، بدون بازبینی. فقط بیرون از production کار میکند. سپس ادمین آن را از فروشگاه (/apps/plugins) نصب میکند و به کیف پولش MU میدهد. ../dev.sh افزونهٔ نمونه را هم با بقیه بالا میآورد.
۹. انتشار
- افزونهٔ
external: نسخهای باbase_urlواقعی (https) را از صفحهٔ ارسال نسخه بفرستید. - افزونهٔ
instance: image را در رجیستری کرسی (registry.korsi.ai) push کنید و در manifest با digest نام ببرید. فعلاً اعتبارنامهٔ push را تیم کرسی میدهد. رجیستری فقط یک حساب دارد و دسترسی جدا برای هر ناشر هنوز ساخته نشده است.