| Files | Last commit | Last update |
|---|---|---|
Start a sleeping hosted server when a webhook routine gets a delivery (#7232) * Start a sleeping hosted server when a webhook routine gets a delivery Signal answers 503 when the host is not connected, as before, and now also asks the account service to start a sleeping hosted server. The sender's retry then reaches the server. A per-host wake interval of 30 minutes and a per-address lookup limit stop abuse. An older account service rejects the new route platform, so nothing starts there. * Let a failed webhook wake try again and limit all webhook lookups A start that the account service did not confirm no longer blocks the host for 30 minutes. All addresses together ask the account service at most the message limit a minute. A route of a host ID that another owner registered again does not start that host. The docs say that a later retry, not the next one, reaches the server. * Ask again to start a hosted server that stays starting after a failed resume A failed resume keeps the server row running, so the account service answers starting. A webhook now asks for the start again in that state, at most once in the same 30-minute interval for each host. * Count each webhook wake request against the lookup limits After a failed wake, the cached sleeping answer let each request send a new wake request with no limit. Each wake request now passes the per-address and total lookup limits too. | 2 days ago | |
Record webhook use in analytics (#5328) * Record webhook use in analytics The host now sends a system_webhook_delivery event for each webhook request: owner kind, result, reason, status, body size, handle time, delivery age and the test flag. It sends at most 60 events a minute and then a skipped_count. It sends no address, secret, event type or body. Routine run events now show webhook runs with trigger_type webhook. system_inventory adds webhook_route_count. Routine and workflow actions report webhook_route_limit when the host refuses a new address. signal_capacity adds the webhook answers by status and the wait time. Generations: desktop_host 16, desktop 13, signal_capacity 2. scripts/webhook-analytics-e2e.ts checks the events and the redaction. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Count Signal webhook waits of 5 s or more as slow ANALYTICS.md says 5 s or more; the code counted only waits over 5 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Count a Signal webhook wait only after Signal sends the frame Signal timed each generic webhook answer from app.ts, so a request that deliverWebhook refused or could not send (no peer, full pending budget, refused format) counted as a wait of about 0 ms. #deliver now times the wait from the frame to the answer, timeout or cancel. Also stop exporting WebhookDeliveryResult and WebhookIgnoredReason, which knip reports as unused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Leave out absent webhook analytics values with exact optional types types:ratchet allows no exactOptionalPropertyTypes errors in src/main/analytics.ts. The webhook delivery and routine run events now add an optional value only when it is set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> | 7 days ago | |
Start workflows from GitHub events and change GitHub from workflows (#4288) * Fix workflow node fades and ports in browsers without scroll timelines Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add the GitHub workflow contract and the workflows-github-v1 capability GitHub is a trigger type, an output target and a run source. The new capability carries the GitHub catalog, repository options, event history and a run with the last event. A client shows a workflow with a trigger type or an output target that it does not know as read-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add migration 49 for GitHub workflow runs, deliveries and actions Migration 49 rebuilds workflow_runs to accept the github run source and keeps every run id. It adds three tables: - workflow_github_runs: the item of each run that a GitHub event started. - workflow_github_deliveries: the event history of each GitHub trigger, and the per-item queue (a waiting row keeps its payload until it starts). - workflow_github_actions: each change that a GitHub output made, so a retry does not repeat it and the loop guard can find its own events. The latest schema takes the same run source line and tables. Tests cover schemas 46 to 48, a late failure and retry, newer and missing histories, constraint refusals and cascades. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Route GitHub App events through Signal to the hosts that watch them Signal gets POST /v1/github/events. It checks the App signature, reads only the installation and repository IDs, and sends the exact body to every host whose GitHub route ticket names the repository. It keeps no body. The account service signs the 5-minute route ticket after it checks, with the host's GitHub sign-in, which watched repositories that sign-in can see. D1 keeps no GitHub route. The host ingress socket holds a GitHub route through the new GitHubRelay, answers github-delivery frames, and records the offline gaps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Start workflow runs from GitHub events, one run per item - Match GitHub events to triggers by repository, event and filters. - Queue an event when a run of its item is open; start it when that run ends. Runs of other items start at the same time. - Skip echoes of the workflow's own actions (self) and the fourth run in 10 minutes that OpenBot's bot caused on one item (chain). - Keep the newest 50 events per trigger and record offline gaps. - Add the refused skip reason and caused_by_bot to the unreleased v49 table. - Add scripts/github-workflow-e2e.ts (host level). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Make the changes of GitHub outputs as OpenBot's bot A GitHub output makes one of the 10 changes through the GitHub REST API with the App's installation token. "Agent chooses" asks a model once and keeps only the repository's own labels and people. Each change writes a `sending` row before the call and a `done` row after it, so a retry does not post twice and the loop guard knows the change's events. A restart sends again only a change that a second call does not repeat. "Run with last event" starts a run with the newest matching item. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show GitHub triggers and outputs on the workflow canvas The trigger and output cards get GitHub rows: repository, event, filters, action, labels and people, with "Agent chooses". The Events row lists what GitHub sent. Access and event alerts open GitHub, and Connect opens the connect dialog of the GitHub settings page. The run bar lists the open runs and the waiting events, and the canvas shows the steps of the open run that the user views. The renderer reads the catalog, labels, people and event history from the host through new IPC reads and Team API routes. GitHub shows only for an owner or admin on a host with workflows-github-v1. Stories replace the prototype stories. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Translate the GitHub workflow text into 12 languages Name the GitHub event and action labels as literal catalog keys, and remove two keys that no code uses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Test the redaction of GitHub errors, and document GitHub workflows Add a Vitest that checks that GitHub's error text and a failed request put no token into a step's failure. Document the GitHub trigger path, the delivery outcomes and the Team API routes, and add release notes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Remove unused GitHub exports, and fix an optional field in the e2e Knip and the exactOptionalPropertyTypes ratchet failed the Check job. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Send not_planned to GitHub when an output closes an issue as not planned The saved close reason is notPlanned. GitHub refused it with "Please specify a valid state reason." The adapter now maps each saved reason to the state_reason that GitHub accepts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep trigger events off GitHub, and add repository search and loading rows - A GitHub output removes the framed trigger event from its text. A comment that has only the event fails with a clear error and posts nothing. - The repository menus have a search field. - The Labels and Person menus show "Loading…" while the host reads them. - The log says that the GitHub output failed, not that it made no change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Make each loop pass change GitHub, and keep Telegram when a ticket fails - A GitHub output keys its change by run, node and pass. A loop pass makes its own change. A retry or a restart of the same pass does not make the change again. - When the trigger event comes back in a loop, the output also removes the empty "Input N:" names of the event. - A failed GitHub or webhook ticket does not stop Telegram or the other routes on the shared socket. - The connector reads the App events from GITHUB_ROUTE_EVENTS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Let Signal pass GitHub events of up to 512 KiB An issue_comment or pull_request event can hold two texts of 65,536 characters each. Signal refused such an event with 413, and GitHub does not send it again. - GITHUB_DELIVERY_BODY_BYTES_LIMIT is 512 KiB. - The pending budget for each host is 768 KiB, and the socket backpressure limit is 1 MiB, so the largest event fits. - nginx gets a /v1/github/events location with the same body limit, no access log, and the 10-second wait of GitHub. - The Signal e2e sends the largest event and one above the limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep an end marker in a comment inside its event, and stop loading after a failed options read The event frame ends only at the marker on its own line. The JSON of the event keeps no line break, so a commenter cannot end the frame early and get text posted as the bot. A failed read of repository labels and people now stores empty options. The menus stop showing "Loading". A change on GitHub reads them again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> | 12 days ago | |
Send Discord embeds from the messaging_post tool (#5895) * Send Discord embeds from the messaging_post tool An agent can give up to 10 Discord embed objects to messaging_post. The text is optional when the post has embeds. A long text goes in more than one post, and the embeds go on the last post. Each embed text and link is redacted, the same as the post text. Signal validates each embed with Discord's limits and sends it as it is. A host sends the embeds key only with at least one embed, so a plain post continues to work with an older Signal. Deploy Signal before the hosts. The tool shows an embed as an object with no fixed keys, and decodes the call with the full schema. The catalog budget goes up by 164 bytes. Fixes #5882 * Rename the release notes file to the branch name * Put Discord embeds on the first post of a long text When Signal or Discord refuses the embeds, nothing is posted now. Before, the first parts of a long text stayed posted and its last part was lost. messaging_post also accepts an empty embeds list as no embeds. * Let Signal read a Discord call with 10 embeds Signal refused a JSON Discord call larger than 64 KB. A post with 10 embeds can have 60 links of up to 2,048 characters, so a post that both checks accept got 413. The limit is now 512 KB. | 4 days ago | |
Give the agent the embeds of a Discord message (#4741) * Give the agent the embeds of a Discord message Discord bots, such as ticket bots, put their text in embeds. Signal read only the text and files of a message, so a reply to a ticket form gave the agent only "@user Welcome". Signal now reads the embeds of the replied-to message, of a forward and of `listMessages`. It sends each embed as text in the new optional `embeds` field: author, title, link, description, fields, footer, and the image, thumbnail and video links. It leaves out empty parts. An older Signal sends no field, and the host then uses an empty list. The host puts each embed in the context, and keeps an earlier message that has only embeds. The Discord access E2E check now covers a reply to a ticket form and an earlier link preview. Fixes #4732 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Limit Discord embed text and name its mentions Signal now limits the text of all embeds of one message to 6,000 characters, Discord's own limit. The quote and the history then stay in the host's context limits and in the frame limit. An embed of an unexpected shape no longer fails a page of history: Signal leaves out the embeds of that message. The host puts the file names before the embeds, so that a cut of a long reply keeps them, and it names the people that an embed mentions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> | 9 days ago | |
Connect more Discord and Slack servers, add Discord role lists, read replied-to messages (#2502) * Connect more Discord and Slack servers, add Discord role lists, read replied-to messages - One OpenBot server can add a second and later Slack workspace or Discord server. The connect dialog follows the workspace that it adds. - Each Discord server can have a list of roles. OpenBot ignores a mention from a member who has none of them. An empty list lets everyone. Signal sends the author's role IDs and lists the guild's roles (listRoles). The host keeps the list in projection_messaging_allowed_roles (migration 44). A joined server uses the new optional capability discord-access-v1. - Signal passes the text, author and time of the message that a person replies to. The host gives it to the agent as context. Signal asks for the Message Content intent when DISCORD_MESSAGE_CONTENT is true, and connects without it when Discord refuses it (close code 4014). - Add the E2E test test:messaging-discord-access. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Cut long Discord role names and fix knip findings - A Discord role name can have more than 100 UTF-16 units (emoji), which made the IPC and Team decoders refuse the whole role list. The host cuts each name to the limit without splitting a surrogate pair. The E2E test covers a name of 60 emoji. - The E2E script takes the Gateway payload type from DiscordState, so the root package does not need discord-api-types. InboundQuote is not exported. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the Signal Discord helper within the exactOptionalPropertyTypes ratchet discordAuthorName takes its own parameter type, which accepts the optional fields of a REST message as zod reads them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Use one orchestrator for each messaging platform One Slack Orchestrator answers every Slack workspace, and one Discord Orchestrator answers every Discord server, as one Telegram Orchestrator already answers every Telegram chat. - A workspace or server connected later gets the orchestrator that exists. "Add agent" gives it to each place that has none, and makes one only when the platform has none. - An orchestrator that an earlier build gave one workspace stays with it. - Disconnect deletes the orchestrator only with the last place that uses it. - The page shows one orchestrator section, and one "Who can use OpenBot" section with a row for each Discord server. - The orchestrator memories no longer name one workspace. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Name one orchestrator in the summary of many workspaces The summary of two or more Slack workspaces or Discord servers names the one orchestrator that answers them. Remove the notes of the deleted per-workspace title key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Ask for the Discord Message Content intent by default Signal asks for the intent unless DISCORD_MESSAGE_CONTENT is false. When the Developer Portal has it off, Discord refuses it, and Signal logs one line and connects without it, as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Stop the connect retries of a Discord Gateway manager that the fallback replaced When Discord refuses the Message Content intent, the first connect of the manager fails too. Its retries then connected the released manager again, which asked for the refused intent again. A connect attempt now runs only while its manager is the current one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> | 24 days ago | |
Run Signal on two machines at the same time (#4209) * Run Signal on two machines at the same time The account service gives each server a home Signal machine (`REMOTE_SIGNAL_HOMES`). When the home stops, the server and its devices ask for a new home and move to the other machine. Auth events go to each Signal, and only failed targets get a retry. A cron checks the entry name `signal.openbot.run` and moves it to a healthy machine. TURN relays spread over more than one machine. All of this stays off until the production settings are set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Do not export the entry check types that only its file uses Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep device peers when no other Signal can take the host - The host and its devices ask for a new Signal machine only when their ticket names a home. The entry Signal moves by DNS, so a new ticket for it names the same URL, and the host kept its device peers before. - When the account service gives the same home again, the host keeps its device peers and lets the hidden window connect again. - A released host build sends no signalHome. Its ticket request now removes the stored home, so its members do not wait on the old home. Ingress and the webhook relay send signalHome false and keep it. - A REMOTE_SIGNAL_URL that is not a ws or wss URL fails closed, so the entry check does not throw. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Wait longer between host checks while a device waits - A device that waits for an offline host doubles the wait after each ticket check that finds no move, up to 5 minutes, and starts again at 10 s after `ready` or a move. - The deployment note now says that a released host build removes its stored home. - The entry check e2e passes an empty zone instead of undefined. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> | 13 days ago | |
Run Signal on two machines at the same time (#4209) * Run Signal on two machines at the same time The account service gives each server a home Signal machine (`REMOTE_SIGNAL_HOMES`). When the home stops, the server and its devices ask for a new home and move to the other machine. Auth events go to each Signal, and only failed targets get a retry. A cron checks the entry name `signal.openbot.run` and moves it to a healthy machine. TURN relays spread over more than one machine. All of this stays off until the production settings are set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Do not export the entry check types that only its file uses Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep device peers when no other Signal can take the host - The host and its devices ask for a new Signal machine only when their ticket names a home. The entry Signal moves by DNS, so a new ticket for it names the same URL, and the host kept its device peers before. - When the account service gives the same home again, the host keeps its device peers and lets the hidden window connect again. - A released host build sends no signalHome. Its ticket request now removes the stored home, so its members do not wait on the old home. Ingress and the webhook relay send signalHome false and keep it. - A REMOTE_SIGNAL_URL that is not a ws or wss URL fails closed, so the entry check does not throw. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Wait longer between host checks while a device waits - A device that waits for an offline host doubles the wait after each ticket check that finds no move, up to 5 minutes, and starts again at 10 s after `ready` or a move. - The deployment note now says that a released host build removes its stored home. - The entry check e2e passes an empty zone instead of undefined. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> | 13 days ago | |
Start a sleeping hosted server when a webhook routine gets a delivery (#7232) * Start a sleeping hosted server when a webhook routine gets a delivery Signal answers 503 when the host is not connected, as before, and now also asks the account service to start a sleeping hosted server. The sender's retry then reaches the server. A per-host wake interval of 30 minutes and a per-address lookup limit stop abuse. An older account service rejects the new route platform, so nothing starts there. * Let a failed webhook wake try again and limit all webhook lookups A start that the account service did not confirm no longer blocks the host for 30 minutes. All addresses together ask the account service at most the message limit a minute. A route of a host ID that another owner registered again does not start that host. The docs say that a later retry, not the next one, reaches the server. * Ask again to start a hosted server that stays starting after a failed resume A failed resume keeps the server row running, so the account service answers starting. A webhook now asks for the start again in that state, at most once in the same 30-minute interval for each host. * Count each webhook wake request against the lookup limits After a failed wake, the cached sleeping answer let each request send a new wake request with no limit. Each wake request now passes the per-address and total lookup limits too. | 2 days ago | |
Keep the phone connected across returns and network moves (#5913) * Keep the phone connected across returns and network moves Users say the phone often disconnects and comes back online slowly after a return to the app. Each return after about 2.5 minutes made a new connection with all of its steps in a row and loaded the whole workspace again. - Signal keeps a client connection of a multiplexing host for 10 minutes after its socket closes (30 s before), and names the grace in `ready` (`reconnectGraceMs`, optional). The phone replaces its connection only after that time; with an older Signal it keeps the 160 s rule. - A return with the kept connection checks the path and reads the open chats; it does not load the workspace again. A stopped read, an event reset, a refresh or a failed check still load everything. - A move between Wi-Fi and mobile data (expo-network), also one seen at a return, ends the connection, and the recovery makes a new one on the same session at once. In support logs an ICE restart after such a move did not bring the path back within 6 s, and a new connection was up in 1.5-3 s. - The peer counts its ICE restarts. After 10 it makes a new connection on the same session, because the host drops the connection at the 11th. A second restart while one runs is not sent, and a probe waits up to 6 s for a running restart before it calls the path dead. - A new connection to a known host opens its Signal socket during the ticket request and gathers ICE candidates before `ready`. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Refresh TURN credentials of a prepared connection from their age A connection made before `ready` gathers its relay candidates with the cached ICE servers, up to 30 minutes old. `setConfiguration` does not replace them until the next gathering, but the TURN refresh was scheduled 45 minutes after `ready`, so a relay-only path could lose its allocation before the refresh. The refresh is now due 45 minutes after the cached servers arrived. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> | 4 days ago | |
Start a sleeping hosted server when a webhook routine gets a delivery (#7232) * Start a sleeping hosted server when a webhook routine gets a delivery Signal answers 503 when the host is not connected, as before, and now also asks the account service to start a sleeping hosted server. The sender's retry then reaches the server. A per-host wake interval of 30 minutes and a per-address lookup limit stop abuse. An older account service rejects the new route platform, so nothing starts there. * Let a failed webhook wake try again and limit all webhook lookups A start that the account service did not confirm no longer blocks the host for 30 minutes. All addresses together ask the account service at most the message limit a minute. A route of a host ID that another owner registered again does not start that host. The docs say that a later retry, not the next one, reaches the server. * Ask again to start a hosted server that stays starting after a failed resume A failed resume keeps the server row running, so the account service answers starting. A webhook now asks for the start again in that state, at most once in the same 30-minute interval for each host. * Count each webhook wake request against the lookup limits After a failed wake, the cached sleeping answer let each request send a new wake request with no limit. Each wake request now passes the per-address and total lookup limits too. | 2 days ago | |
Answer in Telegram with one shared OpenBot bot (#1448) * Answer in Telegram with one shared OpenBot bot People mention the OpenBot bot in a Telegram group, or reply to it, and the Telegram Orchestrator asks the right agent, as in Slack. - Signal holds the bot token. It receives the webhook, routes each update to the host of its chat over the ingress socket, and makes the host's Bot API calls from a fixed list, only for chats routed to that host. - The Worker links a chat to a host with a one-use code (D1 0026) and signs the Telegram route ticket. - The host adds a Telegram driver, the Telegram Orchestrator and a settings page under Connectors. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Fix Telegram link, disconnect and removed chats - Hold the ingress socket while a link code is open, so Signal can route the first chat when no connection runs. - Link a chat only on a `/start` that Signal marks `linked`: a made-up code in a routed chat no longer resumes a paused chat. - Validate Telegram route tickets by bot, chat and link time, so a revoked route of one bot does not come back on the chat ID of another. - Hold the socket until the bot leaves the chat on disconnect. - Keep a chat that removed the bot removed across reconnects and restarts. - Remove unused exports that knip found. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Wait for Signal before a Telegram link, and end rate limits - Open the `t.me` link only when the socket is ready with a Signal that has Telegram, so the chat's `/start` always finds this host. - Allow 64 chats in the Telegram overview, as the account service does. - Send an answer as plain text when its HTML is over the call text limit that Signal checks, so Signal does not close the shared socket. - Retry a rate-limited Telegram call like the Slack client, and restore the connection state when the wait ends, for Slack too. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Fix four Telegram review findings - Retry a failed Telegram route ticket with its own backoff, as for webhooks. - Mark a paused chat as removed, and unlink it, when the bot leaves it. - Look up the bot's username again when the link could not get it. - Let a reply to the bot start a conversation in a group. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hold the Telegram socket while a chat looks up the bot's username After a restart, no transport holds the socket before identify() ends, so the getMe call waited for a socket that did not open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add the OpenBot Telegram bot settings, and deploy them to the Worker - Encrypt TELEGRAM_BOT_ID and TELEGRAM_BOT_USERNAME into the auth-api .env.production and .env.dev, and the bot token, webhook secret and webhook origin into remote/.env.production. - api:deploy now sends TELEGRAM_BOT_ID and TELEGRAM_BOT_USERNAME to the Worker, as it does the Slack and Discord settings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the Telegram bot token away from the dev app The dev stack passed TELEGRAM_* shell values to every child. The bot token, the webhook secret and the webhook origin now go only to Signal (and the account API, as for Discord); the bot ID and username only to the account API. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Use the new OpenBot Telegram bot, @meetOpenBot Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Document the OpenBot Telegram bot settings Add apps/telegram-app/README.md, as for the Discord and Slack apps: the BotFather settings and texts of @meetOpenBot, its secrets, and the limits of Telegram. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> | 1 month ago | |
Start workflows from GitHub events and change GitHub from workflows (#4288) * Fix workflow node fades and ports in browsers without scroll timelines Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add the GitHub workflow contract and the workflows-github-v1 capability GitHub is a trigger type, an output target and a run source. The new capability carries the GitHub catalog, repository options, event history and a run with the last event. A client shows a workflow with a trigger type or an output target that it does not know as read-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add migration 49 for GitHub workflow runs, deliveries and actions Migration 49 rebuilds workflow_runs to accept the github run source and keeps every run id. It adds three tables: - workflow_github_runs: the item of each run that a GitHub event started. - workflow_github_deliveries: the event history of each GitHub trigger, and the per-item queue (a waiting row keeps its payload until it starts). - workflow_github_actions: each change that a GitHub output made, so a retry does not repeat it and the loop guard can find its own events. The latest schema takes the same run source line and tables. Tests cover schemas 46 to 48, a late failure and retry, newer and missing histories, constraint refusals and cascades. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Route GitHub App events through Signal to the hosts that watch them Signal gets POST /v1/github/events. It checks the App signature, reads only the installation and repository IDs, and sends the exact body to every host whose GitHub route ticket names the repository. It keeps no body. The account service signs the 5-minute route ticket after it checks, with the host's GitHub sign-in, which watched repositories that sign-in can see. D1 keeps no GitHub route. The host ingress socket holds a GitHub route through the new GitHubRelay, answers github-delivery frames, and records the offline gaps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Start workflow runs from GitHub events, one run per item - Match GitHub events to triggers by repository, event and filters. - Queue an event when a run of its item is open; start it when that run ends. Runs of other items start at the same time. - Skip echoes of the workflow's own actions (self) and the fourth run in 10 minutes that OpenBot's bot caused on one item (chain). - Keep the newest 50 events per trigger and record offline gaps. - Add the refused skip reason and caused_by_bot to the unreleased v49 table. - Add scripts/github-workflow-e2e.ts (host level). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Make the changes of GitHub outputs as OpenBot's bot A GitHub output makes one of the 10 changes through the GitHub REST API with the App's installation token. "Agent chooses" asks a model once and keeps only the repository's own labels and people. Each change writes a `sending` row before the call and a `done` row after it, so a retry does not post twice and the loop guard knows the change's events. A restart sends again only a change that a second call does not repeat. "Run with last event" starts a run with the newest matching item. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show GitHub triggers and outputs on the workflow canvas The trigger and output cards get GitHub rows: repository, event, filters, action, labels and people, with "Agent chooses". The Events row lists what GitHub sent. Access and event alerts open GitHub, and Connect opens the connect dialog of the GitHub settings page. The run bar lists the open runs and the waiting events, and the canvas shows the steps of the open run that the user views. The renderer reads the catalog, labels, people and event history from the host through new IPC reads and Team API routes. GitHub shows only for an owner or admin on a host with workflows-github-v1. Stories replace the prototype stories. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Translate the GitHub workflow text into 12 languages Name the GitHub event and action labels as literal catalog keys, and remove two keys that no code uses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Test the redaction of GitHub errors, and document GitHub workflows Add a Vitest that checks that GitHub's error text and a failed request put no token into a step's failure. Document the GitHub trigger path, the delivery outcomes and the Team API routes, and add release notes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Remove unused GitHub exports, and fix an optional field in the e2e Knip and the exactOptionalPropertyTypes ratchet failed the Check job. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Send not_planned to GitHub when an output closes an issue as not planned The saved close reason is notPlanned. GitHub refused it with "Please specify a valid state reason." The adapter now maps each saved reason to the state_reason that GitHub accepts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep trigger events off GitHub, and add repository search and loading rows - A GitHub output removes the framed trigger event from its text. A comment that has only the event fails with a clear error and posts nothing. - The repository menus have a search field. - The Labels and Person menus show "Loading…" while the host reads them. - The log says that the GitHub output failed, not that it made no change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Make each loop pass change GitHub, and keep Telegram when a ticket fails - A GitHub output keys its change by run, node and pass. A loop pass makes its own change. A retry or a restart of the same pass does not make the change again. - When the trigger event comes back in a loop, the output also removes the empty "Input N:" names of the event. - A failed GitHub or webhook ticket does not stop Telegram or the other routes on the shared socket. - The connector reads the App events from GITHUB_ROUTE_EVENTS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Let Signal pass GitHub events of up to 512 KiB An issue_comment or pull_request event can hold two texts of 65,536 characters each. Signal refused such an event with 413, and GitHub does not send it again. - GITHUB_DELIVERY_BODY_BYTES_LIMIT is 512 KiB. - The pending budget for each host is 768 KiB, and the socket backpressure limit is 1 MiB, so the largest event fits. - nginx gets a /v1/github/events location with the same body limit, no access log, and the 10-second wait of GitHub. - The Signal e2e sends the largest event and one above the limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep an end marker in a comment inside its event, and stop loading after a failed options read The event frame ends only at the marker on its own line. The JSON of the event keeps no line break, so a commenter cannot end the frame early and get text posted as the bot. A failed read of repository labels and people now stores empty options. The menus stop showing "Loading". A change on GitHub reads them again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> | 12 days ago | |
Run Signal on two machines at the same time (#4209) * Run Signal on two machines at the same time The account service gives each server a home Signal machine (`REMOTE_SIGNAL_HOMES`). When the home stops, the server and its devices ask for a new home and move to the other machine. Auth events go to each Signal, and only failed targets get a retry. A cron checks the entry name `signal.openbot.run` and moves it to a healthy machine. TURN relays spread over more than one machine. All of this stays off until the production settings are set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Do not export the entry check types that only its file uses Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep device peers when no other Signal can take the host - The host and its devices ask for a new Signal machine only when their ticket names a home. The entry Signal moves by DNS, so a new ticket for it names the same URL, and the host kept its device peers before. - When the account service gives the same home again, the host keeps its device peers and lets the hidden window connect again. - A released host build sends no signalHome. Its ticket request now removes the stored home, so its members do not wait on the old home. Ingress and the webhook relay send signalHome false and keep it. - A REMOTE_SIGNAL_URL that is not a ws or wss URL fails closed, so the entry check does not throw. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Wait longer between host checks while a device waits - A device that waits for an offline host doubles the wait after each ticket check that finds no move, up to 5 minutes, and starts again at 10 s after `ready` or a move. - The deployment note now says that a released host build removes its stored home. - The entry check e2e passes an empty zone instead of undefined. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> | 13 days ago | |
Run Signal on two machines at the same time (#4209) * Run Signal on two machines at the same time The account service gives each server a home Signal machine (`REMOTE_SIGNAL_HOMES`). When the home stops, the server and its devices ask for a new home and move to the other machine. Auth events go to each Signal, and only failed targets get a retry. A cron checks the entry name `signal.openbot.run` and moves it to a healthy machine. TURN relays spread over more than one machine. All of this stays off until the production settings are set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Do not export the entry check types that only its file uses Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep device peers when no other Signal can take the host - The host and its devices ask for a new Signal machine only when their ticket names a home. The entry Signal moves by DNS, so a new ticket for it names the same URL, and the host kept its device peers before. - When the account service gives the same home again, the host keeps its device peers and lets the hidden window connect again. - A released host build sends no signalHome. Its ticket request now removes the stored home, so its members do not wait on the old home. Ingress and the webhook relay send signalHome false and keep it. - A REMOTE_SIGNAL_URL that is not a ws or wss URL fails closed, so the entry check does not throw. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Wait longer between host checks while a device waits - A device that waits for an offline host doubles the wait after each ticket check that finds no move, up to 5 minutes, and starts again at 10 s after `ready` or a move. - The deployment note now says that a released host build removes its stored home. - The entry check e2e passes an empty zone instead of undefined. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> | 13 days ago |
| Files | Last commit | Last update |
|---|---|---|
| 2 days ago | ||
| 7 days ago | ||
| 12 days ago | ||
| 4 days ago | ||
| 9 days ago | ||
| 24 days ago | ||
| 13 days ago | ||
| 13 days ago | ||
| 2 days ago | ||
| 4 days ago | ||
| 2 days ago | ||
| 1 month ago | ||
| 12 days ago | ||
| 13 days ago | ||
| 13 days ago |