Chatový most
Poskytovatelé
Sekce “Poskytovatelé”| Poskytovatel | Wire hodnota | Přenos | Druh prostoru |
|---|---|---|---|
| Slack | slack |
Socket Mode (odchozí WSS) | slack |
Jediný poskytovatel je Slack. ChatProvider je výčet s jedinou hodnotou a cc_server registruje jeden plugin. Schéma, každé vyhledání i každý unikátní index jsou klíčované podle provider, takže identifikátory se mezi poskytovateli nekříží a přidání dalšího je změna jen na serveru.
Jedna aplikace na straně poskytovatele na každý pracovní prostor × poskytovatel.
Příkazy chatu
Sekce “Příkazy chatu”Jméno příkazu patří aplikaci (výchozí je cc, tedy /cc). Admin ho může přejmenovat; most pak používá to jméno, pod kterým byl naposledy zavolán.
| Příkaz | Účinek |
|---|---|
/cc help (nebo /cc bez slovesa) |
Vypíše, co bot umí |
/cc link <code> |
Uplatní jednorázový kód a propojí chatovou identitu odesílatele |
/cc ticket <title> |
Založí lokální ticket, který nahlásí propojený člen |
/cc ticket <title> | <description> |
Totéž a všechno za prvním | je popis |
| Neznámé sloveso | Nahlásí neznámé sloveso a připojí text nápovědy |
Jak se dostat k agentovi:
| Gesto | Chování |
|---|---|
@bot … v kanálu |
Otevře vlákno Slacku a odpovídající prostor Control Center; agent odpoví ve vláknu Slacku |
| Odpověď v propojeném vláknu Slacku | Pokračuje ve stejném prostoru Control Center — zmínka není potřeba |
| Obyčejná zpráva v kanálu | Ignoruje se (není adresovaná botovi a není v propojeném vláknu Slacku) |
| Přímá zpráva botovi | Jeden prostor Control Center na každou konverzaci v přímé zprávě; nastaví nadpis vlákna Slacku a stav „is thinking…“, dokud agent pracuje |
Pole přihlašovacích údajů (Slack)
Sekce “Pole přihlašovacích údajů (Slack)”Deklaruje je deskriptor poskytovatele. Z něj se generuje dialog připojení a podle něj se kontroluje odeslání.
| Id pole | Popisek | Povinné | Prefix | Kde leží |
|---|---|---|---|---|
botToken |
Bot user OAuth token | Ano | xoxb- |
OAuth & Permissions |
appToken |
App-level token | Ano | xapp- |
Basic Information → App-Level Tokens, scope connections:write |
configRefreshToken |
App configuration refresh token | Ne | xoxe |
App configuration tokens on api.slack.com/apps |
configRefreshToken je přihlašovací údaj pro správu aplikace: bez něj připojení funguje, ale bota z Control Center nejde vytvořit ani upravit. Při každém použití se otočí a otočená hodnota se uloží hned.
Hodnoty se oříznou, nedeklarované klíče se zahodí a nesoulad prefixu se odmítne stejnou větou na klientovi i na serveru. Povinná pole musí být při každém připojení vyplněná; prázdné volitelné pole nechá uloženou hodnotu, jak byla.
Požadavky na aplikaci Slack
Sekce “Požadavky na aplikaci Slack”Scopes tokenu bota:
app_mentions:readassistant:writechannels:historychat:writecommandsgroups:historyim:historyusers:readusers:read.emailOdběry událostí bota:
app_home_openedapp_mentionmessage.channelsmessage.groupsmessage.imStrukturální nastavení, které Control Center vynutí, když aplikaci vytváří nebo upravuje: zapnutý Socket Mode, žádná request URL, Messages tab zapnutá a zapisovatelná, bot always_online, požadované scopes a události sloučené do toho, co aplikace už má (nikdy se neodečítají), a jeden příkaz s lomítkem s popisem File a ticket or link your Control Center account — značka, podle které se v exportovaném manifestu pozná vlastní příkaz Control Center.
Stavy připojení
Sekce “Stavy připojení”| Stav | Wire | Význam |
|---|---|---|
| Nepřipojeno | disconnected |
Pro tenhle pracovní prostor × poskytovatel nejsou uložené žádné přihlašovací údaje |
| Připojování… | connecting |
Přihlašovací údaje jsou uložené, přenos se navazuje nebo navazuje znovu |
| Živě | connected |
Přenos běží a přijímá události |
| Chyba připojení | error |
Uložené, ale selhává; vedle se ukáže vlastní chyba poskytovatele |
Opětovné připojení je exponenciální backoff s jitterem, nanejvýš 30 sekund. Když socket otočí sám poskytovatel, most se připojí znovu hned a backoff přitom nezvyšuje. Odmítnuté přihlašovací údaje (invalid_auth, not_authed, token_revoked, account_inactive, token_expired, invalid_app_id) nebo chybějící scope jsou konečné: most přestane zkoušet znovu, dokud nepřijdou nové přihlašovací údaje.
Schopnosti poskytovatele (Slack)
Sekce “Schopnosti poskytovatele (Slack)”Most je napsaný proti nejbohatší ploše a podle chybějící schopnosti ubírá.
| Schopnost | Slack | Účinek, když chybí |
|---|---|---|
streaming |
ano | Celá odpověď se odešle jednou, na konci |
streamingRequiresThread |
ano | Cíl odpovědi bez kotvy vlákna posílá celé odpovědi |
ephemeralMessages |
ano | Odpověď na příkaz s lomítkem bez použitelného úchytu odpovědi se zahodí (odmítnutí se vždy odešlou do vlákna) |
threadStatus |
ano | Žádný pomíjivý řádek „is thinking…“ |
threadTitle |
ano | Chatové vlákno si nechá výchozí nadpis |
slashCommands |
ano | Žádná plocha /cc |
taskCards |
ano | Jen text — nad odpovědí není karta a chybí odkaz „View in Control Center“ |
maxMessageLength |
39 000 | Delší odpovědi se zkrátí a odkážou do Control Center |
maxStreamChunkLength |
3 800 | Přírůstky se dělí na hranici odstavce, řádku nebo mezery |
Ohlášené streamování ještě není slíbené: to Slacku potřebuje funkci Agents & AI Apps na placeném plánu. Odmítnutí v okamžiku volání (streaming_not_supported, feature_not_enabled, paid_only, …) se pamatuje po celou dobu života spojení a navenek je streamingAvailable: false. Karty úkolů Slacku jedou stejným voláním, takže Slack, který odmítne režim zobrazení karty, si stream nechá a o kartu přijde jen jednou, po celou dobu života spojení.
Stream musí taky pojmenovat čtenáře, pro kterého je. Slack v kanálu (v přímé zprávě ne) vyžaduje jak příjemce, tak jeho tým, jinak otevření odmítne s missing_recipient_user_id / missing_recipient_team_id. To je odmítnutí jednoho volání, takže most to zkouší dál a tah mezitím dorazí jako jedna odeslaná odpověď. Příjemce je ten, kdo se ptal, vzatý z příchozí zprávy (jeho tým, ne tým aplikace, takže se kanál Slack Connect rozřeší správně). U tahu, který z chatu nikdo nespustil — práce spuštěná v Control Center na už propojené konverzaci — je to člen, jehož propojení ten most vytvořilo; když si mezitím chatový účet odpojil, ten tah se odešle celý, bez streamování.
Karty úkolů
Sekce “Karty úkolů”Jedna seskupená karta na tah agenta (task_display_mode: plan), s řádkem na každý krok. Každý řádek je task_update z id + title + status, plus jednorázové details, až je myšlenka hotová. details a output se stejným id se spojí bez oddělovače, takže details se pošlou jednou a output se nikdy nestreamuje. Nadpis plánu je požadavek; odpověď je pozdější samostatný přírůstek s kusem markdown_text.
| Část | Obsah |
|---|---|
| Nadpis plánu | Na co se ptalo |
| Řádek přípravy | Working on it…, pak Cloning …, pak Starting the agent… — jeden řádek, nadpis se nahrazuje |
| Řádek uvažování | Thinking…, přidá se, když agent začne uvažovat; myšlenka jsou details tohoto řádku, odeslané jednou, když uvažování skončí |
| Řádky nástrojů | Jeden na nástroj (Bash which swift), jedinečné id, takže stojí vedle sebe |
| Stav | Probíhá, dokud řádek běží; hotovo, když začne další řádek nebo tah skončí; chyba u selhání, přerušení a limitu tahů |
| Výzva k akci | View in Control Center jako koncový řádek, když tah skončí — chybí, dokud práce ještě běží, a chybí, když server nemá dosažitelnou veřejnou URL |
Co karta nikdy nenese: výstup nástroje, argument mimo ten seznam povolených, ani nic přečteného z databáze. Uvažování v próze jsou jen podrobnosti řádku Thinking… (strop 256 znaků), ne tělo zprávy. Karta, která by neřekla nic nového, se neposílá znovu. Zmínka otevře stream hned, aby vlákno Slacku nemlčelo; tah, který pak nevyprodukoval vůbec žádný text, tu samou kartu uzavře krátkou poznámkou, místo aby poslal druhou zprávu. Tah bez textu v prostoru, který stream nikdy neotevřel (žádné karty, nebo streamování už odmítnuté), pořád odešle jednu zprávu s hotovou kartou a poznámkou.
Streamované a odeslané karty jsou jiné payloady:
| Podoba | Tvar | Próza |
|---|---|---|
| Streamovaná | plan_update plus kusy task_update klíčované id |
Obyčejný řetězec, strop 256 znaků na kus |
| Odeslaná | Blok plan, který obaluje task_card klíčované task_id |
Rich text |
Zacházení se selháním:
| Situace | Chování |
|---|---|
| Poskytovatel odmítne kartu při přírůstku | Přírůstek se hned zopakuje bez ní; próza pořád přichází živě a karty se na dobu života spojení zahodí |
| Poskytovatel odmítne i prózu | Stream se zavře a odpověď se odešle celá |
| Stream se přeruší poté, co část odpovědi dorazila | Stream se zavře a nic se neposílá znovu |
Viz Chatové mosty, proč se payload dělí právě takhle.
Příprava, než existuje tah
Sekce “Příprava, než existuje tah”Karta se otevře, když je zmínka přijata, před klonováním a před prvním tokenem; tah, který následuje, převezme stejnou kartu a stejný stream. Další hlášení přichází z SpaceProvisioningChanged na sběrnici doménových událostí — stejný postup, který čte banner přípravy na desktopu z řádku prostoru.
| Stav přípravy | Hlášení |
|---|---|
| Zmínka přijata | Working on it… |
Krok repo |
Cloning <repo>… |
Krok prCheckout |
Checking out the pull request in <repo>… |
Krok script |
Running the setup script for <repo>… |
Krok agent |
Setting up <agent>… |
provisioning, ještě bez kroku |
Preparing the workspace… |
ready |
Starting the agent… |
| Agent uvažuje | Thinking… |
failed |
Workspace setup failed — details are in Control Center. |
cancelled |
Workspace setup was stopped — details are in Control Center. |
Hlášení přípravy potřebuje všechny čtyři podmínky:
| Podmínka |
|---|
| Poskytovatel vykresluje karty |
| Na tomhle spojení je streamování dostupné |
| V prostoru běží chatový požadavek |
| Žádná karta tam už tah nehlásí |
Požadavek zůstane rozpracovaný, dokud nezačne tah nebo příprava neselže. Událost ready bez už otevřené karty znamená prostor, který už připravený je, a zůstane zticha. Příprava, na kterou v chatu nikdo nečeká — konverzace otevřená v aplikaci, nebo přerušená a obnovená při startu — kartu nevyrobí vůbec.
Odrazová stránka /open
Sekce “Odrazová stránka /open”Chatové produkty v odkazu přijmou http(s) a nic jiného, takže výzva k akci nemůže pojmenovat schéma desktopu přímo.
| Vlastnost | Hodnota |
|---|---|
| Trasa | GET /open/workspaces/<workspaceId>/(spaces|tickets)/<id> |
| Původ | Odvozený z veřejné URL serveru (ws → http, wss → https); loopback se zachová |
| Odpověď | Malá HTML stránka no-store, která přejde na control-center://workspaces/<workspaceId>/(spaces|tickets)/<id> a ukáže ruční tlačítko |
| Kontrola | Identifikátory musí odpovídat [A-Za-z0-9_.-]{1,128}; cokoli jiného je 404 |
| Přístup | Veřejná a netečná — nečte žádnou databázi, takže neprozradí, jestli záznam existuje; autorizaci udělá aplikace, kterou otevře |
Pole profilu bota
Sekce “Pole profilu bota”| Pole | Limit | Poznámky |
|---|---|---|
appName |
1–35 znaků | Výchozí Control Center · <workspace name> |
botDisplayName |
1–80 znaků | Výchozí control-center |
description |
≤ 140 znaků | |
agentDescription |
≤ 300 znaků | Zobrazí se nad přímou zprávou s botem |
command |
≤ 32 znaků | Normalizace: úvodní lomítka pryč, malá písmena, [^a-z0-9_-] se odstraní, prázdný výsledek spadne na cc |
agentEnabled |
— | Jestli se vystavuje rozhraní přímých zpráv a agenta |
Prázdné pole znamená „nech to být“: uložená hodnota zůstane. Limity jsou limity Slacku, nejpřísnější z produktů, které se modelují.
Kódy propojení
Sekce “Kódy propojení”| Vlastnost | Hodnota |
|---|---|
| Délka | 6 znaků |
| Abeceda | 23456789ABCDEFGHJKLMNPQRSTVWXYZ (bez 0/O, 1/I, U) |
| Platnost | 15 minut |
| Použití | Jedno |
| Úložiště | V paměti — restart serveru zneplatní ještě neuplatněné kódy |
| Rozsah | Jeden pracovní prostor a jeden poskytovatel; vystavení nového kódu zneplatní předchozí kód člena |
Uplatnění se páruje bez ohledu na velikost písmen. Neznámý kód, prošlý kód, kód z cizího pracovního prostoru a kód pro špatného poskytovatele selžou schválně stejně.
Způsoby propojení
Sekce “Způsoby propojení”| Způsob | Wire | Jak |
|---|---|---|
| Kód | code |
Člen uplatnil /cc link <code> |
email |
Ověřený e-mail poskytovatele se shodoval s uživatelem, který už je členem pracovního prostoru |
Operace RPC
Sekce “Operace RPC”Všechny jsou v rozsahu pracovního prostoru. Server je bezstavový, takže každé volání nese vlastní workspace_id v argumentech; dispatcher odmítne operaci v rozsahu pracovního prostoru, která ho vynechá, ještě než se otevře jakákoli databáze. Přihlašovací údaje putují jen dovnitř — čtení stavu je nikdy nevrátí.
| Operace | Druh | Minimální role | Třídy akcí |
|---|---|---|---|
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 pro sebe, admin pro kohokoli jiného |
— |
chat.createApp |
mutate | admin |
secretAccess, networkEgress |
chat.setupLink |
read | admin |
— |
chat.botProfile |
read | admin |
networkEgress |
chat.updateBotProfile |
mutate | admin |
networkEgress |
Čtecí operace dědí podlahu guest ze svého druhu; mutace bez výslovné podlahy vyžadují member.
chat.setupLink složí URL pro vytvoření aplikace u poskytovatele z profilu bota. Nedeklaruje třídu akce, protože nečte žádné tajemství a nikam nevolá — jediné volání udělá prohlížeč uživatele.
Plochu doplňuje jeden reaktivní dotaz:
| Dotaz | Druh | Vysílá |
|---|---|---|
chat.watchUserLinks |
watch | Seznam, znovu odeslaný, kdykoli se propojení přidá nebo odebere |
Existuje proto, že propojení se děje na druhé straně: člen napíše jednorázový kód botovi, takže žádná odpověď klientovi tu zprávu nést nemůže. Seznam v nastavení i otevřený dialog „Propojit účet {provider}“ ho oba sledují a dialog se přepne na potvrzení v okamžiku, kdy dorazí vlastní propojení člena.
chat.beginUserLink vždy vystaví kód pro identitu volajícího. chat.updateBotProfile vrátí remaining_step jen tehdy, když nějaký krok zbývá (typicky nová instalace); když pole chybí, úprava už platí.
chat.providers vrátí jednu položku na nabízeného poskytovatele — deskriptor a, když existuje, stav připojení. Všechno, co vykreslí nastavení, pochází z toho payloadu, a proto je přidání poskytovatele změna jen na serveru.
Úložiště
Sekce “Úložiště”| Co | Kde |
|---|---|
| Přihlašovací údaje spojení | <dataDir>/<workspaceId>/chat_credentials/<provider>.json |
| Nedokončené vedené nastavení | <dataDir>/<workspaceId>/chat_credentials/<provider>_setup.json |
| Starší soubory Slacku | <dataDir>/<workspaceId>/slack_credentials.json a slack_app_setup.json, přečtou se jednou a migrují na místě |
Přihlašovací údaje leží vedle databáze pracovního prostoru, ne v ní: smazání pracovního prostoru vezme chatové tokeny s sebou a workspace.export nebo záloha kopíruje workspace.db — takže pracovní prostor předaný někomu jinému v sobě nenese živé tokeny bota. Zápisy jsou atomické (dočasný soubor a přejmenování) a práva se stáhnou jen na vlastníka.
Tabulky databáze
Sekce “Tabulky databáze”Obě žijí v databázi pracovního prostoru, která nese sjednocený baseline v1 — čtení napříč pracovními prostory se proto nezkompiluje.
chat_space_links — jedna externí konverzace ↔ jeden prostor Control Center:
| Sloupec | Poznámky |
|---|---|
id |
UUID v4 |
workspace_id |
Rozsah pracovního prostoru |
provider |
ChatProvider.wire |
external_team_id |
Tým Slacku T…, prázdné u poskytovatelů, kteří ten pojem nemají |
external_channel_id |
Kanál Slacku C…, skupina G…, přímá zpráva D… |
external_thread_id |
Kotva vlákna Slacku, nebo null, když je kotvou celá konverzace (přímé zprávy bota) |
cc_space_id |
REFERENCES spaces(id) ON DELETE CASCADE |
created_by_user_id, created_at, last_activity_at |
Unikátní na (workspace_id, provider, external_channel_id, external_thread_id), s částečným indexem, který totéž vynutí pro prázdná id vlákna (SQLite bere hodnoty NULL jako různé).
chat_user_links — jeden externí člen ↔ jeden uživatel Control Center:
| Sloupec | Poznámky |
|---|---|
id |
UUID v4 |
workspace_id |
Rozsah pracovního prostoru |
provider |
ChatProvider.wire |
external_team_id, external_user_id |
Člen Slacku U… |
user_id |
Uživatel Control Center (globální, proto bez cizího klíče) |
method |
code nebo email |
linked_at |
Unikátní na (workspace_id, provider, external_team_id, external_user_id) a na (workspace_id, provider, user_id) — přiřazení je v obou směrech jednoznačné, přičemž jeden člověk může být propojený u několika poskytovatelů.
Propojení je určení identity, ne udělení přístupu: členství se kontroluje znovu při každé příchozí události, takže propojení člena, který byl mezitím odebrán, skončí odmítnutím.
Druh prostoru a metadata zprávy
Sekce “Druh prostoru a metadata zprávy”Propojený prostor vznikne s SpaceKind poskytovatele (slack). Chová se jako obyčejný prostor pro člověka — oznamovaný a řazený do sekcí jako topic — a isExternalChat je kontrola, kterou projde každé chování (zrcadlení, odznaky, uchovávání).
Každá zpráva, kterou most přinese, nese razítko metadata['chat']:
{ "chat": { "provider": "slack", "teamId": "T024BE7LD", "channelId": "C0G9QF9GW", "threadId": "1700000000.000100", "messageId": "1700000000.000200", "userId": "U024BE7LH", "userLabel": "sam" }}Razítko je taky ochrana proti ozvěně: odchozí zrcadlo přeskočí každou zprávu, která ho nese, a právě to zabrání tomu, aby se příchozí chatová zpráva poslala rovnou zpátky.
Chování předávání
Sekce “Chování předávání”| Chování | Detail |
|---|---|
| Co jde ven | Jen text agenta a stavový řádek karty úkolu. Próza uvažování a výstup nástroje zůstanou v Control Center |
| Kadence streamování | Při běhu tahu nejvýš jedno odeslání za sekundu; karta a text, který vysvětluje, jedou stejným voláním |
| Lidské zprávy napsané v Control Center | Zrcadlí se do propojeného vlákna s předponou zobrazovaného jména autora |
| Prázdné tahy | Nahlásí se krátkou poznámkou (běh selhal, byl přerušen, nebo zastavil na limitu tahů), ne tichem |
| Deduplikace | Klíčem je vlastní id události poskytovatele; pamatuje se posledních 512 |
| Vstupní agent | Nová propojená konverzace probudí agenta CEO pracovního prostoru, jinak jeho prvního agenta, jinak nikoho |
| Pojmenování prostoru | #channel · <request> pro vlákno kanálu Slacku, Slack DM · <request> pro přímou zprávu, nadpisy se stropem 48 znaků |
| Izolace selhání | Jedna špatná událost most neshodí; spojení dál obsluhuje každou další konverzaci |
Viz také
Sekce “Viz také”- Nastavte integraci Slack
- Propojte účet Slack
- Přizpůsobte chatbota
- Chatové mosty
- Guardraily pro třídy akcí, které operace deklarují