Tovább a tartalomhoz

Csevegőhíd

Szolgáltató Átviteli érték Szállítás Tértípus
Slack slack Socket Mode (kimenő WSS) slack

A Slack az egyetlen szolgáltató. A ChatProvider egyetlen értékű enum, és a cc_server egy plugint regisztrál. A séma, minden keresés és minden egyedi index a provider alapján kulcsolt, így az azonosítók soha nem lépnek át szolgáltatók között, és egy új hozzáadása csak szerveroldali változás.

Egy szolgáltató oldali alkalmazás munkaterületenként × szolgáltatónként.

A parancsnév alkalmazásonként értendő (cc az alapértelmezett, tehát /cc). Egy admin átnevezheti; a híd ezután azt használja, amivel utoljára meghívták.

Parancs Hatás
/cc help (vagy /cc ige nélkül) Felsorolja, mit tud a bot
/cc link <code> Bevált egy egyszer használatos kódot, és összekapcsolja a küldő csevegőidentitását
/cc ticket <title> Helyi jegyet hoz létre az összekapcsolt tag bejelentése alapján
/cc ticket <title> | <description> Ugyanaz, az első | utáni minden a leírás
Ismeretlen ige Jelenti az ismeretlen igét és a súgószöveget

Így érhet el egy ügynököt:

Művelet Viselkedés
@bot … egy csatornában Megnyit egy Slack szálat és egy hozzá tartozó Control Center-teret; az ügynök a Slack szálban válaszol
Válasz egy hídon átvezetett Slack szálban Ugyanazt a Control Center-teret folytatja — említés nem szükséges
Egyszerű üzenet egy csatornában Figyelmen kívül marad (nem a botnak szól, és nem egy hídon átvezetett Slack szálban van)
DM a botnak DM-beszélgetésenként egy Control Center-tér; beállít egy Slack szálcímet és egy „is thinking…” állapotot, amíg az ügynök dolgozik

A szolgáltató deskriptora deklarálja őket; ez generálja a csatlakozási párbeszédablakot, és ez érvényesíti a beküldött adatokat.

Mezőazonosító Címke Kötelező Előtag Hol található
botToken Bot token Igen xoxb- OAuth & Permissions
appToken Alkalmazásszintű token Igen xapp- Basic Information → App-Level Tokens, connections:write hatókör
configRefreshToken Alkalmazáskonfigurációs token Nem xoxe App configuration tokens az api.slack.com/apps oldalon

A configRefreshToken az alkalmazáskezelési hitelesítő adat: nélküle a kapcsolat működik, de a bot nem hozható létre és nem szerkeszthető a Control Centerből. Minden használatkor rotálódik, és a rotált érték azonnal tárolásra kerül.

Az értékek elejéről és végéről eltávolítjuk a szóközöket, a nem deklarált kulcsokat eldobjuk, az előtag eltérését pedig ugyanazzal a mondattal utasítja el a kliens és a szerver is. A kötelező mezőknek minden csatlakozáskor jelen kell lenniük; egy üresen hagyott nem kötelező mező megtartja a korábban tárolt értéket.

A bot token hatókörei:

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

A bot eseményfeliratozásai:

app_home_opened
app_mention
message.channels
message.groups
message.im

Szerkezeti beállítások, amelyeket a Control Center kikényszerít, amikor létrehozza vagy szerkeszti az alkalmazást: a Socket Mode bekapcsolva, nincs kérési URL, a Messages fül engedélyezve és írható, a bot always_online, a szükséges hatókörök és események beolvasztva abba, ami az alkalmazásban már megvan (soha nem kivonva), valamint egyetlen slash-parancs, amelynek leírása File a ticket or link your Control Center account — ez a jelölő, amely egy exportált manifesztben azonosítja a Control Center saját parancsát.

Állapot Átviteli érték Jelentés
Nincs csatlakoztatva disconnected Ehhez a munkaterület × szolgáltató pároshoz nincs tárolt hitelesítő adat
Csatlakozás… connecting A hitelesítő adatok tárolva, a szállítás tárcsáz vagy újratárcsáz
Élő connected A szállítás fut, és fogadja az eseményeket
Kapcsolati hiba error Tárolva, de hibázik; mellette a szolgáltató saját hibája látható

Az újracsatlakozás exponenciális visszakapcsolás jitterrel, 30 másodpercben maximalizálva. A szolgáltató által kezdeményezett socket-rotáció azonnal újracsatlakozik, anélkül hogy fokozná a visszakapcsolást. Az elutasított hitelesítő adat (invalid_auth, not_authed, token_revoked, account_inactive, token_expired, invalid_app_id) vagy egy hiányzó hatókör végleges: a híd felhagy az újrapróbálkozással, amíg új hitelesítő adatok nem érkeznek.

A híd a leggazdagabb felületre íródott, és képességenként degradálódik.

Képesség Slack Hatás, ha hiányzik
streaming igen A teljes válasz egyszer, a végén kerül közzétételre
streamingRequiresThread igen Egy szálhorgony nélküli válaszcél teljes válaszokat tesz közzé
ephemeralMessages igen A használható válaszhivatkozás nélküli slash-parancs válasza elvész (az elutasítások mindig a szálban jelennek meg)
threadStatus igen Nincs átmeneti „is thinking…” sor
threadTitle igen A csevegőszál megtartja az alapértelmezett címét
slashCommands igen Nincs /cc felület
taskCards igen Csak szöveg — nincs kártya a válasz felett, és nincs „View in Control Center” hivatkozás
maxMessageLength 39 000 A hosszabb válaszok levágásra kerülnek, a Control Centerre mutató hivatkozással
maxStreamChunkLength 3 800 A hozzáfűzések bekezdés-, sor- vagy szóhatáron tördelődnek

A hirdetett streamelés nem ígéret a streamelésre: a Slackéhez az Agents & AI Apps funkció kell egy fizetős csomagban. A hívás pillanatában érkező elutasítást (streaming_not_supported, feature_not_enabled, paid_only, …) a kapcsolat teljes élettartamára megjegyezzük, és streamingAvailable: false formában jelenítjük meg. A Slack feladatkártyái ugyanezen a híváson mennek keresztül, így egy olyan Slack, amely elutasítja a kártya megjelenítési módját, megtartja a streamjét, és csak a kártyát veszíti el — egyszer, a kapcsolat élettartamára.

Egy streamnek meg kell neveznie azt is, kinek szól. A Slackhez egy csatornában való megnyitáshoz egyszerre kell egy címzett felhasználó és annak csapata (egy DM-hez nem), és minden más esetben missing_recipient_user_id / missing_recipient_team_id hibával utasít el — ez hívásonkénti elutasítás, így a híd tovább próbálkozik, és a kör addig egyetlen közzétett válaszként érkezik meg. A címzett az, aki kérdezett, a bejövő üzenetből véve (az ő csapata, nem az alkalmazásé, így egy Slack Connect-csatorna helyesen oldódik fel). Egy olyan körnél, amelyet senki nem indított a csevegésből — a Control Centerben egy már hídon átvezetett beszélgetésen elindított munka —, az a tag a címzett, akinek az összekapcsolása létrehozta a hidat; ha azóta leválasztotta a csevegőfiókját, az a kör streamelés helyett teljes egészében kerül közzétételre.

Ügynökkörönként egy csoportosított kártya (task_display_mode: plan), lépésenként egy sorral. Minden sor egy task_update id + title + status mezőből, valamint egy egyszeri details, amikor a gondolat készen áll. Az azonos azonosítójú details és output elválasztó nélkül fűződik össze, ezért a details egyszer megy ki, az output pedig soha nem streamelődik. A terv címe a kérés; a válasz egy későbbi, külön hozzáfűzés, amely egy markdown_text darabot hordoz.

Rész Tartalom
Terv címe Mit kértek
Beállítási sor Working on it…, majd Cloning …, majd Starting the agent… — egy sor, a cím cserélődik
Gondolkodási sor Thinking…, akkor kerül hozzá, amikor az ügynök elkezd gondolkodni; a gondolat ennek a sornak a details mezője, egyszer elküldve, amikor a gondolkodás befejeződik
Eszközsorok Eszközönként egy (Bash which swift), egyedi azonosítóval, hogy egymás mellett álljanak
Állapot Folyamatban, amíg az a sor fut; befejezett, amikor a következő sor elindul vagy a kör véget ér; hiba a sikertelen, a megszakított és a körlimit elérése esetén
Cselekvésre felhívás View in Control Center záró sorként, amikor a kör véget ér — hiányzik, amíg a munka még folyik, és hiányzik, ha a szervernek nincs elérhető nyilvános URL-je

Amit egy kártya soha nem hordoz: eszközkimenetet, az engedélylistán kívüli argumentumot, vagy bármit, ami az adatbázisból származik. Az érvelő szöveg csak a Thinking… sor részletei (256 karakterben maximalizálva), nem az üzenettörzs. Egy kártya, amely nem mondana újat, nem kerül újraküldésre. Egy említés azonnal megnyitja a streamet, hogy a Slack szál ne maradjon néma; egy kör, amely ezután egyáltalán nem termelt szöveget, ugyanazt a kártyát zárja le egy rövid megjegyzéssel, ahelyett hogy egy második üzenetet tenne közzé. Egy szótlan kör egy olyan téren, amely soha nem nyitott streamet (nincsenek kártyák, vagy a streamelést már elutasították), akkor is közzétesz egy üzenetet a kész kártyával és a megjegyzéssel.

A streamelt és a közzétett kártyák különböző hasznos terhek:

Forma Alak Szöveg
Streamelt plan_update, valamint id kulccsal ellátott task_update darabok Egyszerű sztring, darabonként 256 karakterben maximalizálva
Közzétett task_id kulcsú task_card-okat körbeölelő plan blokk Formázott szöveg

Hibakezelés:

Helyzet Viselkedés
A szolgáltató elutasítja a kártyát egy hozzáfűzés során A hozzáfűzés azonnal, nélküle kerül újrapróbálásra; a szöveg továbbra is élőben érkezik, a kártyák pedig a kapcsolat élettartamára elmaradnak
A szolgáltató a szöveget is elutasítja A stream lezárul, és a válasz teljes egészében kerül közzétételre
A stream megszakad, miután a válasz egy része megérkezett A stream lezárul, és semmi nem kerül újra közzétételre

Lásd a Csevegőhidak oldalt, hogy miért oszlik meg így a hasznos teher.

A kártya akkor nyílik meg, amikor egy említést elfogadnak, a klónozás előtt és az első token előtt; az ezután következő kör ugyanazt a kártyát és streamet veszi át. Az ezt követő narráció a domaineseménybuszon érkező SpaceProvisioningChanged eseményből származik — ugyanaz a folyamat, amelyet az asztali alkalmazás előkészítési sávja a tér sorából kiolvas.

Előkészítési állapot Narráció
Említés elfogadva Working on it…
repo lépés Cloning <repo>…
prCheckout lépés Checking out the pull request in <repo>…
script lépés Running the setup script for <repo>…
agent lépés Setting up <agent>…
provisioning, még nincs lépés Preparing the workspace…
ready Starting the agent…
Az ügynök gondolkodik Thinking…
failed Workspace setup failed — details are in Control Center.
cancelled Workspace setup was stopped — details are in Control Center.

A beállítási narráció mind a négy feltételt megköveteli:

Feltétel
A szolgáltató kártyákat jelenít meg
A streamelés elérhető ezen a kapcsolaton
A téren van folyamatban lévő csevegőkérés
Ott még egy kártya sem számol be körről

A kérés folyamatban marad, amíg el nem indul egy kör, vagy a beállítás meg nem hibázik. Egy ready esemény, amelyhez még nem nyílt kártya, egy meleg tér, és csendben marad; az olyan előkészítés pedig, amelyre a csevegésben senki sem vár — egy alkalmazásban megnyitott beszélgetés, egy indításkor folytatott, elakadt beszélgetés —, egyáltalán nem hoz létre kártyát.

A csevegőtermékek egy hivatkozásban csak http(s)-t fogadnak el, mást nem, ezért egy cselekvésre felhívás nem nevezheti meg közvetlenül az asztali alkalmazás sémáját.

Tulajdonság Érték
Útvonal GET /open/workspaces/<workspaceId>/(spaces|tickets)/<id>
Eredet A szerver nyilvános URL-jéből származik (ws → http, wss → https); a loopback megmarad
Válasz Egy kis, no-store HTML-oldal, amely a control-center://workspaces/<workspaceId>/(spaces|tickets)/<id> címre navigál, és egy kézi gombot jelenít meg
Érvényesítés Az azonosítóknak meg kell felelniük a [A-Za-z0-9_.-]{1,128} mintának; minden más 404
Hozzáférés Nyilvános és hatástalan — nem olvas adatbázist, így nem létezési orákulum; a megnyitott alkalmazás végzi a jogosultságellenőrzést
Mező Korlát Megjegyzések
appName 1–35 karakter Alapértelmezés: Control Center · <workspace name>
botDisplayName 1–80 karakter Alapértelmezés: control-center
description ≤ 140 karakter
agentDescription ≤ 300 karakter A bottal folytatott DM felett jelenik meg
command ≤ 32 karakter Normalizálva: a vezető perjelek eltávolítva, kisbetűsítve, [^a-z0-9_-] eltávolítva, üres esetén cc az alapértelmezés
agentEnabled — Azt szabályozza, hogy a DM- és ügynöktapasztalat elérhető-e

Egy üres mező azt jelenti, hogy „hagyd békén”, nem azt, hogy „töröld”. A korlátok a Slackéi, amelyek a modellezett termékek közül a legszűkebbek.

Tulajdonság Érték
Hossz 6 karakter
Karakterkészlet 23456789ABCDEFGHJKLMNPQRSTVWXYZ (nincs 0/O, 1/I, U)
Élettartam 15 perc
Felhasználás Egy
Tárolás Memóriában — a szerver újraindítása érvényteleníti a függőben lévő kódokat
Hatókör Egy munkaterület és egy szolgáltató; új kód kiállítása érvényteleníti a tag előző kódját

A beváltás kis- és nagybetűt nem megkülönböztetve történik. Az ismeretlen, a lejárt, a más munkaterülethez tartozó és a rossz szolgáltatóhoz tartozó kódok szándékosan ugyanúgy hibáznak.

Mód Átviteli érték Hogyan
Kód code A tag beváltotta a /cc link <code> parancsot
E-mail email A szolgáltató ellenőrzött e-mail-címe egyezett egy olyan felhasználóval, aki már tagja a munkaterületnek

Mindegyik munkaterülethez kötött. A szerver állapotmentes, ezért minden hívás a saját workspace_id értékét hordozza az argumentumokban; a diszpécser az adatbázis megnyitása előtt elutasítja az azt elhagyó, munkaterülethez kötött műveletet. A hitelesítő adatok csak befelé utaznak — az állapotlekérdezések soha nem adják vissza őket.

Művelet Fajta Minimum szerepkör Műveletosztályok
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 saját magadhoz, admin bárki máshoz —
chat.createApp mutate admin secretAccess, networkEgress
chat.setupLink read admin —
chat.botProfile read admin networkEgress
chat.updateBotProfile mutate admin networkEgress

Az olvasási műveletek a fajtájukból öröklik a guest alsó szintet; a kifejezett alsó szint nélküli módosításokhoz member szükséges.

A chat.setupLink a botprofilból állítja össze a szolgáltató alkalmazáslétrehozási URL-jét. Nem deklarál műveletosztályt, mert nem olvas titkot és nem tárcsáz semmit — az egyetlen hívást a felhasználó saját böngészője indítja.

Egy reaktív lekérdezés teszi teljessé a felületet:

Lekérdezés Fajta Kibocsátás
chat.watchUserLinks watch A névsor, amely újra kiküldésre kerül, amikor egy kapcsolat létrejön vagy megszűnik

Azért létezik, mert az összekapcsolás a másik oldalon történik: a tag a botba írja be az egyszer használatos kódot, így egyetlen kliensválasz sem hozhatja vissza a választ. A beállítások névsora és a nyitva lévő „fiókom összekapcsolása” párbeszédablak is ezt követi, és a párbeszédablak abban a pillanatban visszaigazolásra vált, amikor a tag saját kapcsolata létrejön.

A chat.beginUserLink mindig a hívó saját identitásához állít ki kódot. A chat.updateBotProfile csak akkor ad vissza remaining_step értéket, ha maradt egy lépés (jellemzően egy újratelepítés); ennek hiánya azt jelenti, hogy a szerkesztés életbe lépett.

A chat.providers szolgáltatónként egy bejegyzést ad vissza — a deskriptort, valamint, ha van, a kapcsolat állapotát. Minden, amit a beállítások felülete megjelenít, ebből a hasznos teherből származik, ezért egy szolgáltató hozzáadása csak szerveroldali változás.

Mi Hol
Kapcsolati hitelesítő adatok <dataDir>/<workspaceId>/chat_credentials/<provider>.json
Félkész, vezetett beállítás <dataDir>/<workspaceId>/chat_credentials/<provider>_setup.json
Régi Slack-fájlok <dataDir>/<workspaceId>/slack_credentials.json és slack_app_setup.json, egyszer beolvasva és a helyén migrálva

A hitelesítő adatok a munkaterület adatbázisa mellett élnek, nem benne: egy munkaterület törlése magával viszi a csevegési tokenjeit, a workspace.export vagy egy mentés pedig átmásolja a workspace.db-t — így egy másnak átadott munkaterület nem hordoz élő bottokeneket. Az írások atomikusak (ideiglenes fájl és átnevezés), és csak a tulajdonos számára engedélyezettek.

Mindkettő a munkaterület adatbázisában él, amely egy összevont v1 alapsémát hordoz — így a munkaterületek közötti olvasás nem fordul le.

chat_space_links — egy külső beszélgetés ↔ egy Control Center-tér:

Oszlop Megjegyzések
id UUID v4
workspace_id Munkaterület-hatókör
provider ChatProvider.wire
external_team_id Slack csapat T…, üres azoknál a szolgáltatóknál, amelyeknél nincs ilyen fogalom
external_channel_id Slack csatorna C…, csoport G…, DM D…
external_thread_id Slack szálhorgony, vagy null, amikor a teljes beszélgetés a horgony (bot DM-ek)
cc_space_id REFERENCES spaces(id) ON DELETE CASCADE
created_by_user_id, created_at, last_activity_at

Egyedi a (workspace_id, provider, external_channel_id, external_thread_id) mezőcsoporton, és egy részleges index ugyanezt kényszeríti ki a null szálazonosítókra (az SQLite a NULL értékeket különbözőnek tekinti).

chat_user_links — egy külső tag ↔ egy Control Center-felhasználó:

Oszlop Megjegyzések
id UUID v4
workspace_id Munkaterület-hatókör
provider ChatProvider.wire
external_team_id, external_user_id Slack tag U…
user_id Control Center-felhasználó (globális, ezért nincs idegen kulcs)
method code vagy email
linked_at

Egyedi a (workspace_id, provider, external_team_id, external_user_id) és a (workspace_id, provider, user_id) mezőcsoporton — egyértékű hozzárendelés mindkét irányban, miközben egy személy több szolgáltatónál is összekapcsolható.

Az összekapcsolás identitásfeloldás, nem hozzáférési jogosultság megadása: a tagság minden bejövő eseménynél újraellenőrzésre kerül, így egy olyan taghoz tartozó kapcsolat, akit azóta eltávolítottak, elutasítást eredményez.

A hídon átvezetett tér a szolgáltató SpaceKind értékével (slack) jön létre. Úgy viselkedik, mint egy közönséges, embereknek szánt tér — értesítés és szekcióba sorolás tekintetében mint a topic —, és az isExternalChat az az ellenőrzés, amelyen minden viselkedés (tükrözés, jelvényezés, megőrzés) keresztülmegy.

Minden üzenet, amelyet a híd behoz, metadata['chat'] bélyegzőt hordoz:

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

A bélyegző egyben az echóőr is: a kifelé irányuló tükrözés kihagy minden ilyen bélyegzőt viselő üzenetet, ez az, ami megakadályozza, hogy egy bejövő csevegőüzenet egyenesen visszakerüljön.

Viselkedés Részletek
Mi kerül kifelé Csak az ügynök szövege, valamint a feladatkártya állapotsora. Az érvelő szöveg és az eszközkimenet a Control Centerben marad
Streamelési ütem Egy kör futása közben másodpercenként egy kiíratásra korlátozva; a kártya és az általa magyarázott szöveg ugyanabban a hívásban utazik
A Control Centerben beírt emberi üzenetek A csatolt szálba tükrözve, az író megjelenített nevével az élen
Üres körök Rövid megjegyzésként jelentve (a futás sikertelen, megszakadt, vagy a körlimitjénél leállt), a csend helyett
Deduplikáció A szolgáltató saját eseményazonosítója alapján; az utolsó 512 marad meg
Fogadó ügynök Egy új, hídon átvezetett beszélgetés a munkaterület CEO-ügynökét ébreszti fel, ennek hiányában az első ügynökét, azok hiányában senkit
Tér elnevezése #channel · <request> egy Slack csatornaszálhoz, Slack DM · <request> egy DM-hez, a címek 48 karakterben maximalizálva
Hibaizoláció Egyetlen hibás esemény soha nem viszi le a hidat; a kapcsolat tovább szolgálja az összes többi beszélgetést