مواد پر جائیں

چیٹ برج

فراہم کنندہ وائر ویلیو ٹرانسپورٹ اسپیس کی قسم
Slack slack Socket Mode (باہر جانے والا WSS) slack

Slack واحد فراہم کنندہ ہے۔ ChatProvider ایک واحد ویلیو والا enum ہے اور cc_server صرف ایک پلگ اِن رجسٹر کرتا ہے۔ اسکیما، ہر لُک اپ اور ہر یونیک انڈیکس provider پر کلید بند ہیں، اس لیے ids کبھی فراہم کنندگان کے درمیان نہیں جاتے اور کوئی فراہم کنندہ شامل کرنا صرف سرور کی تبدیلی ہے۔

ہر ورک اسپیس × فراہم کنندہ کے لیے فراہم کنندہ کی طرف ایک ایپ۔

کمانڈ کا نام فی ایپ ہوتا ہے (cc بطور ڈیفالٹ، لہٰذا /cc)۔ ایڈمن اُس کا نام بدل سکتا ہے؛ پھر برج وہی استعمال کرتا ہے جس کے ساتھ اُسے آخری بار پکارا گیا تھا۔

کمانڈ اثر
/cc help (یا بغیر کسی فعل کے /cc) بتاتا ہے کہ بوٹ کیا کر سکتا ہے
/cc link <code> ایک بار استعمال ہونے والا کوڈ ریڈیم کرتا ہے اور بھیجنے والے کی چیٹ شناخت لنک کرتا ہے
/cc ticket <title> لنک شدہ رکن کی رپورٹ کردہ مقامی ٹکٹ درج کرتا ہے
/cc ticket <title> | <description> وہی، مگر پہلے | کے بعد کا سب کچھ بطور تفصیل
نامعلوم فعل نامعلوم فعل کے ساتھ مدد کا متن بھی بتاتا ہے

ایجنٹ تک پہنچنے کے طریقے:

اشارہ سلوک
چینل میں @bot … ایک Slack تھریڈ اور اُس سے مماثل Control Center اسپیس کھولتا ہے؛ ایجنٹ Slack تھریڈ میں جواب دیتا ہے
برج شدہ Slack تھریڈ میں جواب اُسی Control Center اسپیس کو جاری رکھتا ہے — کسی ذکر کی ضرورت نہیں
چینل میں سادہ پیغام نظر انداز (نہ بوٹ سے مخاطب ہے اور نہ کسی برج شدہ Slack تھریڈ میں)
بوٹ کو DM فی DM گفتگو ایک Control Center اسپیس؛ Slack تھریڈ کا عنوان اور ایک ”سوچ رہا ہے…“ اسٹیٹس مقرر کرتا ہے جب تک ایجنٹ کام کرتا رہتا ہے

فراہم کنندہ کے ڈسکرپٹر سے بیان کیے جاتے ہیں، اور وہی کنیکٹ ڈائیلاگ بناتا اور جمع کرائی گئی چیز کی توثیق کرتا ہے۔

فیلڈ id لیبل لازمی سابقہ کہاں رہتے ہیں
botToken بوٹ یوزر OAuth ٹوکن ہاں xoxb- OAuth & Permissions
appToken ایپ لیول ٹوکن ہاں xapp- Basic Information → App-Level Tokens، اسکوپ connections:write
configRefreshToken ایپ کنفیگریشن ریفریش ٹوکن نہیں xoxe api.slack.com/apps پر ایپ کنفیگریشن ٹوکنز

configRefreshToken ایپ کے انتظام کی سند ہے: اُس کے بغیر کنکشن چل تو جاتا ہے، مگر بوٹ Control Center سے بنایا یا ترمیم نہیں کیا جا سکتا۔ یہ ہر استعمال پر گھومتا ہے اور گھما ہوا ویلیو فوراً محفوظ کر لیا جاتا ہے۔

ویلیوز تراشے جاتے ہیں، غیر اعلان شدہ کلیدیں گرا دی جاتی ہیں اور سابقے کی عدم مطابقت کلائنٹ اور سرور دونوں پر ایک ہی جملے کے ساتھ مسترد کر دی جاتی ہے۔ ہر کنیکٹ پر لازمی فیلڈز کا موجود ہونا ضروری ہے؛ خالی چھوڑا گیا اختیاری فیلڈ وہی برقرار رکھتا ہے جو پہلے سے محفوظ تھا۔

بوٹ ٹوکن اسکوپس:

app_mentions:read
assistant:write
channels:history
chat:write
commands
groups:history
im:history
users:read
users:read.email

بوٹ ایونٹ سبسکرپشنز:

app_home_opened
app_mention
message.channels
message.groups
message.im

ساختی ترتیبات جو Control Center ایپ بناتے یا ترمیم کرتے وقت نافذ کرتا ہے: Socket Mode فعال، کوئی درخواست URL نہیں، Messages ٹیب فعال اور قابلِ تحریر، بوٹ always_online، مطلوبہ اسکوپس اور ایونٹس ایپ کے پاس پہلے سے موجود ہر چیز میں شامل کر دیے جاتے ہیں (کبھی گھٹائے نہیں جاتے) اور ایک سلیش کمانڈ جس کے ساتھ تفصیل File a ticket or link your Control Center account ہوتی ہے — وہی نشان جو برآمد شدہ manifest میں Control Center کے اپنے کمانڈ کی شناخت کرتا ہے۔

حالت وائر مطلب
منسلک نہیں disconnected اِس ورک اسپیس × فراہم کنندہ کے لیے کوئی اسناد محفوظ نہیں
منسلک ہو رہا ہے… connecting اسناد محفوظ، ٹرانسپورٹ ڈائل یا دوبارہ ڈائل ہو رہی ہے
لائیو connected ٹرانسپورٹ اپ اور ایونٹس وصول کر رہی ہے
کنکشن خرابی error محفوظ مگر ناکام؛ ساتھ ساتھ فراہم کنندہ کی اپنی غلطی بھی دکھائی جاتی ہے

دوبارہ کنیکٹ ہونا jitter کے ساتھ exponential backoff ہے، جس کی حد 30 سیکنڈ ہے۔ فراہم کنندہ کی شروع کردہ ساکٹ روٹیشن backoff بڑھائے بغیر فوراً دوبارہ کنیکٹ ہو جاتی ہے۔ مسترد شدہ سند (invalid_auth، not_authed، token_revoked، account_inactive، token_expired، invalid_app_id) یا غائب اسکوپ حتمی ہے: برج نئی اسناد آنے تک دوبارہ کوشش کرنا بند کر دیتا ہے۔

برج سب سے بھرپور سطح کے مطابق لکھا گیا ہے اور فی صلاحیت گھٹتا جاتا ہے۔

صلاحیت Slack غائب ہونے پر اثر
streaming ہاں پورا جواب ایک ہی بار، آخر میں پوسٹ ہوتا ہے
streamingRequiresThread ہاں تھریڈ اینکر کے بغیر جواب کا ہدف پورے جواب پوسٹ کرتا ہے
ephemeralMessages ہاں بلا قابلِ استعمال جواب ہینڈل والا سلیش کمانڈ جواب گرا دیا جاتا ہے (انکار ہمیشہ تھریڈ کے اندر پوسٹ ہوتے ہیں)
threadStatus ہاں کوئی عارضی ”سوچ رہا ہے…“ سطر نہیں
threadTitle ہاں چیٹ تھریڈ اپنا ڈیفالٹ عنوان برقرار رکھتا ہے
slashCommands ہاں کوئی /cc سطح نہیں
taskCards ہاں صرف متن — جواب کے اوپر کوئی کارڈ نہیں اور کوئی ”View in Control Center“ لنک نہیں
maxMessageLength 39,000 لمبے جوابات Control Center کی طرف اشارے کے ساتھ کاٹ دیے جاتے ہیں
maxStreamChunkLength 3,800 ایپنڈز پیراگراف، سطر یا اسپیس کی حد پر تقسیم ہوتے ہیں

اسٹریمنگ کا اعلان اسٹریمنگ کا وعدہ نہیں: Slack کے لیے ادا شدہ پلان پر Agents & AI Apps فیچر درکار ہوتا ہے۔ کال کے وقت کا انکار (streaming_not_supported، feature_not_enabled، paid_only، …) کنکشن کی پوری عمر کے لیے یاد رکھا جاتا ہے اور streamingAvailable: false کے طور پر سامنے آتا ہے۔ Slack کے ٹاسک کارڈز اُسی کال پر سوار ہوتے ہیں، اس لیے کارڈ کا ڈسپلے موڈ مسترد کرنے والا Slack اپنی اسٹریم برقرار رکھتا ہے اور کنکشن کی عمر میں صرف ایک بار، صرف کارڈ کھو دیتا ہے۔

اسٹریم کو یہ بھی بتانا ہوتا ہے کہ اُس کا قاری کون ہے۔ Slack کا تقاضا ہے کہ کوئی اسٹریم چینل میں کھولنے کے لیے وصول کنندہ صارف اور اُس کی ٹیم دونوں کا نام دے (DM میں ایسا نہیں)، ورنہ missing_recipient_user_id / missing_recipient_team_id کے ساتھ انکار کر دیتا ہے — یہ فی کال انکار ہے، اس لیے برج کوشش کرتا رہتا ہے اور اُس دوران باری ایک پوسٹ شدہ جواب کے طور پر پہنچ جاتی ہے۔ وصول کنندہ وہی ہوتا ہے جس نے پوچھا، جو اِن باؤنڈ پیغام سے لیا جاتا ہے (اُن کی ٹیم، ایپ کی نہیں، چنانچہ Slack Connect چینل درست طور پر حل ہوتا ہے)۔ ایسی باری کے لیے جسے چیٹ سے کسی نے شروع نہ کیا ہو — ایسا کام جو پہلے سے برج شدہ گفتگو پر Control Center میں شروع کیا گیا ہو — وہ رکن ہوتا ہے جس کے لنک نے برج بنایا؛ اگر اُس نے اُس کے بعد اپنا چیٹ اکاؤنٹ اَن لنک کر دیا ہو تو وہ باری اسٹریم ہونے کے بجائے پوری پوسٹ ہوتی ہے۔

فی ایجنٹ باری ایک گروہ بند کارڈ (task_display_mode: plan)، ہر قدم کے لیے ایک قطار۔ ہر قطار id + title + status کا task_update ہے، اور سوچ تیار ہونے پر ایک بار والا details بھی۔ ایک ہی id والے details اور output بغیر کسی جدا کرنے والے کے جڑ جاتے ہیں، اس لیے details صرف ایک بار بھیجے جاتے ہیں اور output کبھی اسٹریم نہیں ہوتا۔ پلان کا عنوان وہ درخواست ہے؛ جواب ایک الگ، بعد میں شامل ہونے والا ایپنڈ ہوتا ہے جس میں markdown_text چنک ہوتا ہے۔

حصہ مواد
پلان کا عنوان جو پوچھا گیا تھا
سیٹ اپ قطار Working on it…، پھر Cloning …، پھر Starting the agent… — ایک قطار، عنوان بدلتا رہتا ہے
سوچ کی قطار Thinking…، ایجنٹ کے استدلال شروع کرنے پر شامل ہوتی ہے؛ سوچ اِسی قطار کا details ہے، جو استدلال ختم ہونے پر ایک بار بھیجا جاتا ہے
ٹول کی قطاریں فی ٹول ایک (Bash which swift)، یونیک id تاکہ وہ ساتھ ساتھ بیٹھیں
اسٹیٹس جب تک وہ قطار چلتی ہے اِن پروگریس؛ اگلی قطار شروع ہونے یا باری ختم ہونے پر مکمل؛ ناکام، مداخلت شدہ اور باری کی حد والی کے لیے error
کال ٹو ایکشن باری ختم ہونے پر آخری قطار کے طور پر View in Control Center — جب تک کام چل رہا ہو غائب اور جب سرور کا کوئی قابلِ رسائی عوامی URL نہ ہو غائب

کارڈ کبھی کیا نہیں اُٹھاتا: ٹول کا آؤٹ پٹ، اُس allow-list سے باہر کوئی آرگومنٹ، یا ڈیٹا بیس سے پڑھی گئی کوئی چیز۔ استدلال کا نثر صرف Thinking… قطار کے details ہوتا ہے (زیادہ سے زیادہ 256 حروف)، پیغام کا باڈی نہیں۔ کوئی نیا کچھ نہ کہنے والا کارڈ دوبارہ نہیں بھیجا جاتا۔ ذکر فوراً اسٹریم کھول دیتا ہے تاکہ Slack تھریڈ خاموش نہ رہے؛ پھر اگر باری سے کوئی متن بالکل بھی پیدا نہ ہو تو دوسرا پیغام پوسٹ کرنے کے بجائے اُسی کارڈ کو ایک مختصر نوٹ کے ساتھ مکمل کر دیا جاتا ہے۔ ایسی باری جو بے لفظ ہو، ایسے اسپیس پر جس نے کبھی اسٹریم نہ کھولا ہو (کوئی کارڈ نہیں، یا اسٹریمنگ پہلے ہی مسترد)، پھر بھی ایک پیغام پوسٹ کرتی ہے جس میں مکمل کارڈ اور نوٹ ہوتا ہے۔

اسٹریم شدہ اور پوسٹ شدہ کارڈز مختلف پے لوڈ ہوتے ہیں:

شکل ڈھانچہ نثر
اسٹریم شدہ id پر کلید بند plan_update کے ساتھ task_update چنکس سادہ اسٹرنگ، فی چنک زیادہ سے زیادہ 256 حروف
پوسٹ شدہ task_id پر کلید بند task_cards کو لپیٹنے والا plan بلاک رچ ٹیکسٹ

ناکامی سے نمٹنے کا سلوک:

صورتِ حال سلوک
فراہم کنندہ ایپنڈ پر کارڈ مسترد کرتا ہے ایپنڈ فوراً بغیر کارڈ دوبارہ آزمایا جاتا ہے؛ نثر پھر بھی لائیو پہنچتا ہے اور کنکشن کی عمر کے لیے کارڈز گرا دیے جاتے ہیں
فراہم کنندہ نثر بھی مسترد کرتا ہے اسٹریم بند کر دی جاتی ہے اور جواب پورا پوسٹ کیا جاتا ہے
جواب کا کچھ حصہ پہنچنے کے بعد اسٹریم ٹوٹ جاتی ہے اسٹریم بند کر دی جاتی ہے اور کچھ بھی دوبارہ پوسٹ نہیں ہوتا

پے لوڈ اِس طرح کیوں تقسیم کیا جاتا ہے، یہ دیکھیں چیٹ برجز۔

کارڈ اُس وقت کھلتا ہے جب کوئی ذکر قبول ہوتا ہے، کلون سے پہلے اور پہلے ٹوکن سے پہلے؛ اُس کے بعد آنے والی باری وہی کارڈ اور اسٹریم اپناتی ہے۔ اُس کے بعد کا بیان ڈومین ایونٹ بس پر SpaceProvisioningChanged سے آتا ہے — وہی پیش رفت جو ڈیسک ٹاپ کا پروویژننگ بینر اسپیس قطار سے پڑھتا ہے۔

پروویژننگ حالت بیان
ذکر قبول Working on it…
قدم repo Cloning <repo>…
قدم prCheckout Checking out the pull request in <repo>…
قدم script Running the setup script for <repo>…
قدم agent Setting up <agent>…
provisioning، ابھی کوئی قدم نہیں Preparing the workspace…
ready Starting the agent…
ایجنٹ کا استدلال Thinking…
failed Workspace setup failed — details are in Control Center.
cancelled Workspace setup was stopped — details are in Control Center.

سیٹ اپ کے بیان کے لیے چاروں شرائط درکار ہیں:

شرط
فراہم کنندہ کارڈز رینڈر کرتا ہے
اِس کنکشن پر اسٹریمنگ دستیاب ہے
اسپیس میں کوئی چیٹ درخواست زیرِ عمل ہے
وہاں کوئی کارڈ پہلے سے کسی باری کی رپورٹ نہیں کر رہا

درخواست اُس وقت تک زیرِ عمل رہتی ہے جب تک کوئی باری شروع نہ ہو یا سیٹ اپ ناکام نہ ہو۔ بغیر کسی پہلے سے کھلے کارڈ والا ready ایونٹ ایک گرم اسپیس ہے، اسے خاموش چھوڑ دیا جاتا ہے، اور ایسی پروویژننگ جس کا چیٹ میں کوئی منتظر نہ ہو — ایپ میں کھولی گئی گفتگو، یا سرور کے آغاز پر دوبارہ شروع کی گئی بے سہارا گفتگو — بالکل کوئی کارڈ پیدا نہیں کرتی۔

چیٹ پروڈکٹس لنک میں http(s) قبول کرتے ہیں اور کچھ نہیں، اس لیے کوئی کال ٹو ایکشن ڈیسک ٹاپ کا اسکیم براہِ راست نہیں لکھ سکتا۔

خصوصیت ویلیو
روٹ GET /open/workspaces/<workspaceId>/(spaces|tickets)/<id>
ماخذ سرور کے عوامی URL سے ماخوذ (ws → http، wss → https)؛ loopback برقرار رکھا جاتا ہے
جواب ایک چھوٹا no-store HTML صفحہ جو control-center://workspaces/<workspaceId>/(spaces|tickets)/<id> پر جاتا ہے اور ایک دستی بٹن دکھاتا ہے
توثیق ids کو [A-Za-z0-9_.-]{1,128} سے مطابقت رکھنی چاہیے؛ اس کے علاوہ کچھ بھی 404 ہے
رسائی عوامی اور غیر فعال — یہ کوئی ڈیٹا بیس نہیں پڑھتا، اس لیے یہ وجود کا اوریکل نہیں؛ جس ایپ کو یہ کھولتا ہے وہی اجازت دیتی ہے
فیلڈ حد نوٹس
appName 1–35 حروف بطور ڈیفالٹ Control Center · <workspace name>
botDisplayName 1–80 حروف بطور ڈیفالٹ control-center
description ≤ 140 حروف
agentDescription ≤ 300 حروف بوٹ کے ساتھ DM کے اوپر دکھایا جاتا ہے
command ≤ 32 حروف معیاری بنایا گیا: شروع کے سلیش ہٹائے گئے، چھوٹے حروف میں، [^a-z0-9_-] ہٹا دیا گیا، خالی cc پر واپس چلا جاتا ہے
agentEnabled — آیا DM/ایجنٹ کا تجربہ سامنے رکھا گیا ہے

خالی خانے کا مطلب ”جوں کا توں رہنے دو“ ہے، ”صاف کر دو“ نہیں۔ حدیں Slack کی ہیں، جو نمونہ بنائے گئے پروڈکٹس میں سب سے تنگ ہیں۔

خصوصیت ویلیو
لمبائی 6 حروف
حروفِ تہجی 23456789ABCDEFGHJKLMNPQRSTVWXYZ (بغیر 0/O، 1/I، U)
عمر 15 منٹ
استعمال ایک
اسٹوریج میموری میں — سرور کا دوبارہ آغاز بقایا کوڈز کو باطل کر دیتا ہے
دائرہ ایک ورک اسپیس اور ایک فراہم کنندہ؛ نیا کوڈ بنانے سے رکن کا پچھلا کوڈ باطل ہو جاتا ہے

ریڈیم کرتے وقت کیس سے قطعِ نظر مماثلت دیکھی جاتی ہے۔ نامعلوم، میعاد ختم، غیر ورک اسپیس اور غلط فراہم کنندہ والے کوڈز سب دانستہ طور پر یکساں ناکام ہوتے ہیں۔

طریقہ وائر کیسے
کوڈ code رکن نے /cc link <code> ریڈیم کیا
ای میل email فراہم کنندہ کے تصدیق شدہ ای میل نے ایسے صارف سے مماثلت کی جو پہلے ہی ورک اسپیس کا رکن ہے

یہ سب ورک اسپیس کے دائرے میں ہیں۔ سرور اسٹیٹ لیس ہے، اس لیے ہر کال اپنے args میں اپنا workspace_id ساتھ لاتی ہے؛ ڈسپیچر کوئی بھی ڈیٹا بیس کھلنے سے پہلے ایسا ورک اسپیس اسکوپڈ op مسترد کر دیتا ہے جو اُسے چھوڑ دے۔ اسناد صرف اندر آتی ہیں — اسٹیٹس کی reads کبھی اُنہیں واپس نہیں کرتیں۔

آپریشن نوع کم از کم کردار ایکشن کلاسز
chat.providers read guest —
chat.status read guest —
chat.connect mutate admin secretAccess, networkEgress
chat.disconnect destructive admin secretAccess
chat.listUserLinks read guest —
chat.beginUserLink mutate member —
chat.unlinkUser mutate خود کے لیے member، کسی اور کے لیے admin —
chat.createApp mutate admin secretAccess, networkEgress
chat.setupLink read admin —
chat.botProfile read admin networkEgress
chat.updateBotProfile mutate admin networkEgress

پڑھنے والے آپریشنز اپنی نوع سے guest کی حد وراثت میں پاتے ہیں؛ بغیر واضح حد والی تبدیلیوں کے لیے member درکار ہوتا ہے۔

chat.setupLink بوٹ پروفائل سے فراہم کنندہ کی ایپ بنانے کا URL ترتیب دیتا ہے۔ یہ کوئی ایکشن کلاس بیان نہیں کرتا کیونکہ نہ کوئی سند پڑھتا ہے اور نہ کہیں کال کرتا ہے — واحد کال صارف کا اپنا براؤزر کرتا ہے۔

ایک ری ایکٹو کوئری اِس سطح کو مکمل کرتی ہے:

کوئری نوع خارج کرتا ہے
chat.watchUserLinks watch روسٹر، جو کوئی لنک بننے یا ہٹنے پر دوبارہ پش ہوتا ہے

یہ اِس لیے موجود ہے کیونکہ لنک بنانا دوسری طرف ہوتا ہے: رکن ایک بار استعمال ہونے والا کوڈ بوٹ میں ٹائپ کرتا ہے، اس لیے کوئی کلائنٹ جواب اُس کا نتیجہ واپس نہیں لا سکتا۔ ترتیبات کا روسٹر اور کھلا ہوا ”میرا اکاؤنٹ لنک کریں“ ڈائیلاگ دونوں اِسی کی پیروی کرتے ہیں اور جس لمحے رکن کا اپنا لنک آتا ہے، ڈائیلاگ تصدیق پر بدل جاتا ہے۔

chat.beginUserLink ہمیشہ کال کرنے والے کی اپنی شناخت کے لیے کوڈ بناتا ہے۔ chat.updateBotProfile صرف اُس وقت remaining_step واپس کرتا ہے جب کوئی قدم باقی ہو (عام طور پر دوبارہ انسٹال)؛ اُس کا نہ ہونا مطلب یہ ہے کہ ترمیم لاگو ہے۔

chat.providers ہر پیش کردہ فراہم کنندہ کے لیے ایک اندراج واپس کرتا ہے — ڈسکرپٹر، اور جہاں موجود ہو، کنکشن اسٹیٹس بھی۔ ترتیبات کا UI جو کچھ رینڈر کرتا ہے وہ اِسی پے لوڈ سے آتا ہے، اسی لیے فراہم کنندہ شامل کرنا صرف سرور کی تبدیلی ہے۔

کیا کہاں
کنکشن کی اسناد <dataDir>/<workspaceId>/chat_credentials/<provider>.json
ادھورا رہ گیا گائیڈڈ سیٹ اپ <dataDir>/<workspaceId>/chat_credentials/<provider>_setup.json
پرانی Slack فائلیں <dataDir>/<workspaceId>/slack_credentials.json اور slack_app_setup.json، ایک بار پڑھی جاتی ہیں اور وہیں منتقل کر دی جاتی ہیں

اسناد ورک اسپیس کے ڈیٹا بیس کے پہلو میں رہتی ہیں، اُس کے اندر نہیں: ورک اسپیس حذف کرنے پر اُس کے چیٹ ٹوکن بھی چلے جاتے ہیں اور workspace.export یا بیک اپ workspace.db نقل کرتا ہے — اس لیے کسی اور کو دیا گیا ورک اسپیس کوئی زندہ بوٹ ٹوکن ساتھ نہیں لے جاتا۔ لکھائی جوہری ہے (عارضی فائل کے ساتھ نام کی تبدیلی) اور صرف مالک تک محدود ہے۔

دونوں ورک اسپیس کے ڈیٹا بیس میں رہتے ہیں، جس میں ایک squashed v1 بیس لائن موجود ہے — اس لیے کراس ورک اسپیس read کمپائل ہی نہیں ہوتا۔

chat_space_links — ایک بیرونی گفتگو ↔ ایک Control Center اسپیس:

کالم نوٹس
id UUID v4
workspace_id ورک اسپیس اسکوپ
provider ChatProvider.wire
external_team_id Slack ٹیم T…، ایسے فراہم کنندگان کے لیے خالی جن میں یہ تصور نہیں
external_channel_id Slack چینل C…، گروپ G…، DM D…
external_thread_id Slack تھریڈ اینکر، یا null جب پوری گفتگو ہی اینکر ہو (بوٹ DMs)
cc_space_id REFERENCES spaces(id) ON DELETE CASCADE
created_by_user_id, created_at, last_activity_at

(workspace_id, provider, external_channel_id, external_thread_id) پر یونیک، اور null تھریڈ ids کے لیے بھی وہی نافذ کرنے والا ایک جزوی انڈیکس (SQLite NULLs کو الگ الگ سمجھتا ہے)۔

chat_user_links — ایک بیرونی رکن ↔ ایک Control Center صارف:

کالم نوٹس
id UUID v4
workspace_id ورک اسپیس اسکوپ
provider ChatProvider.wire
external_team_id, external_user_id Slack رکن U…
user_id Control Center صارف (گلوبل، اس لیے کوئی فارن کی نہیں)
method code یا email
linked_at

(workspace_id, provider, external_team_id, external_user_id) پر اور (workspace_id, provider, user_id) پر یونیک — دونوں سمتوں میں واحد ویلیو انتساب، جبکہ ایک شخص کئی فراہم کنندگان پر لنک ہو سکتا ہے۔

لنک شناخت کا تعین ہے، رسائی کا عطیہ نہیں: رکنیت ہر اِن باؤنڈ ایونٹ پر دوبارہ جانچی جاتی ہے، اس لیے ایسے رکن سے تعلق رکھنے والا لنک جو بعد میں ہٹا دیا گیا ہو، انکار میں حل ہوتا ہے۔

برج شدہ اسپیس فراہم کنندہ کے SpaceKind (slack) کے ساتھ بنایا جاتا ہے۔ یہ عام انسانی اسپیس کی طرح برتاؤ کرتا ہے — topic کی طرح اطلاعات اور سیکشن — اور isExternalChat وہ جانچ ہے جس سے ہر سلوک (آئینہ بندی، بیج لگانا، برقراری) گزرتا ہے۔

برج جو بھی پیغام اندر لاتا ہے، اُس پر metadata['chat'] کی مہر ہوتی ہے:

{
"chat": {
"provider": "slack",
"teamId": "T024BE7LD",
"channelId": "C0G9QF9GW",
"threadId": "1700000000.000100",
"messageId": "1700000000.000200",
"userId": "U024BE7LH",
"userLabel": "sam"
}
}

یہ مہر ایکو گارڈ بھی ہے: باہر جانے والا آئینہ ایسا کوئی بھی پیغام چھوڑ دیتا ہے جس پر یہ ہو، اور یہی چیز اِن باؤنڈ چیٹ پیغام کو سیدھا واپس پوسٹ ہونے سے روکتی ہے۔

سلوک تفصیل
باہر کیا جاتا ہے صرف ایجنٹ کا متن، اور ٹاسک کارڈ کی اسٹیٹس سطر۔ استدلال کا نثر اور ٹول کا آؤٹ پٹ Control Center میں ہی رہتے ہیں
اسٹریمنگ کی رفتار باری چلنے کے دوران ایک سیکنڈ میں ایک فلش تک محدود؛ کارڈ اور جس متن کی وہ وضاحت کرتا ہے وہ ایک ہی کال میں جاتے ہیں
Control Center میں ٹائپ کیے گئے انسانی پیغام لنک شدہ تھریڈ میں منتقل ہوتے ہیں، مصنف کے ڈسپلے نام کے سابقے کے ساتھ
خالی باریاں خاموشی کے بجائے ایک مختصر نوٹ کے طور پر رپورٹ ہوتی ہیں (رن ناکام، مداخلت شدہ، یا اپنی باری کی حد پر رکا ہوا)
ڈی ڈپلیکیشن فراہم کنندہ کے اپنے ایونٹ id پر کلید بند؛ آخری 512 یاد رکھے جاتے ہیں
فرنٹ ڈور ایجنٹ نئی برج شدہ گفتگو ورک اسپیس کے CEO ایجنٹ کو جگاتی ہے، ورنہ اُس کے پہلے ایجنٹ کو، ورنہ کسی کو نہیں
اسپیس کے نام Slack چینل تھریڈ کے لیے #channel · <request>، DM کے لیے Slack DM · <request>، عنوانات 48 حروف تک محدود
ناکامی کی تنہائی ایک خراب ایونٹ کبھی برج کو گرا نہیں سکتا؛ کنکشن ہر دوسری گفتگو کی خدمت کرتا رہتا ہے