Skip to content

zidane/channels

Slack and GitHub channels for zidane hosts, with the config types, providers, presenters and the runner. Experimental.

import { … } from 'zidane/channels'src/channels/index.ts

Use zidane/channels to type a channels config with defineChannels, or to build your own provider or presenter. zidane-server and zidane-daemon load it only when their data dir holds a channels config. The entry point is experimental: its API can change in any release. Channels covers the setup, the access levels and the commands.

TypeScript
import { defineChannels } from 'zidane/channels'

export default defineChannels({
  channels: {
    me: {
      provider: 'slack',
      team: 'T0123ABCD',
      botToken: { env: 'SLACK_BOT_TOKEN' },
      appToken: { env: 'SLACK_APP_TOKEN' },
      owners: ['U0123ABCD'],
      bindings: [{ match: { dm: true }, folder: '/home/me/code/app' }],
    },
  },
})

Functions#

accessLayersFunction#

The channels config: types, defineChannels, validation, access resolution, loading, channels check and the file watcher.

appJwtFunction#

The App JWT: RS256 over { iat: now - 60, exp: now + 540, iss: appId } (seconds; iat backdated against clock drift, exp under GitHub's 10-minute cap).

channelsDisabledFunction#

The kill switch is set.

channelWarningsFunction#

The risky combinations in a validated config: members who may read the host's secrets, members whose tool calls nobody approves, members whose approvals never time out. Access set by a function is not inspected.

checkChannelsFunction#

Check the channels config in dataDir without starting anything.

conversationIdFunction#

A conversation's stable id: ch- + 24 hex of sha256(channel NUL key).

createBranchPublisherFunction#

A branch publisher for one channel.

createGithubClientFunction#

A GitHub client for one channel.

createGithubPresenterFunction#

The built-in presenter for one channel.

createGithubProviderFunction#

A GitHub provider.

createPresenterFunction#

A provider's or a module's presenter, built for one channel.

createSlackClientFunction#

A Slack client for one channel.

createSlackPresenterFunction#

The built-in presenter for one channel.

createSlackProviderFunction#

A Slack provider.

daemonRefusalsFunction#

Why the laptop daemon refuses config (design: owners only, no webhooks), each naming its key path. Empty when it may run it.

defineChannelProviderFunction#

Returns provider unchanged: a typed anchor for provider modules.

defineChannelsFunction#

Returns config unchanged: a typed anchor for channels.config.ts. Validation happens in the loader.

definePresenterFunction#

A presenter for a provider or a channel's presenter module (its default export).

effectiveAccessFunction#

The channels config: types, defineChannels, validation, access resolution, loading, channels check and the file watcher.

expandLevelFunction#

The channels config: types, defineChannels, validation, access resolution, loading, channels check and the file watcher.

findChannelsConfigFunction#

The config file in dataDir, or null when there is none.

githubPresenterFunction#

The built-in presenter as a definition (the provider's default).

githubSignatureFunction#

The sha256=<hex> signature of a body.

hostChannelsFunction#

Host the channels configured in options.dataDir. Never throws into the host: a config that does not load is logged with its key paths and reported by status(); channels then stay off until a reload succeeds.

intakePathFunction#

Where the intake file lives.

isPresenterDefinitionFunction#

Whether value came from definePresenter.

jsonErrorPositionFunction#

The first error in text, or null when it is valid JSON.

limitsOfFunction#

The channels config: types, defineChannels, validation, access resolution, loading, channels check and the file watcher.

loadChannelsConfigFunction#

The host's channels config: null when channels are off (no file, or the kill switch).

mentionsBotFunction#

Whether text mentions the bot: @<login without [bot]> or @<login>.

normalizeWebhookFunction#

One webhook delivery as an inbound message, or null when it is not for the runner (another event or action, a bot, a comment that does not address the bot).

parsePrivateKeyFunction#

The App's private key, parsed.

readChannelsConfigFunction#

Read and validate one config file, secrets included.

resolveAccessFunction#

The channels config: types, defineChannels, validation, access resolution, loading, channels check and the file watcher.

resolveSecretsFunction#

Read every { env } secret of a validated config.

roleOfFunction#

The channels config: types, defineChannels, validation, access resolution, loading, channels check and the file watcher.

runChannelsFunction#

Start the channels of config against the host client talks to. Never throws into the host: a channel that cannot start shows 'failed' on its integration, and an intake store that cannot open fails them all.

secretValueFunction#

A resolved secret's value.

slackPresenterFunction#

The built-in presenter as a definition (the provider's default).

slackSignatureFunction#

The v0=<hex> signature of a request.

toSessionPolicyFunction#

The channels config: types, defineChannels, validation, access resolution, loading, channels check and the file watcher.

validateChannelsConfigFunction#

Check a channels config read from JSON or exported by a TS file.

verifyGithubSignatureFunction#

Check a delivery's signature.

verifySlackSignatureFunction#

Check a request's signature.

watchChannelsConfigFunction#

Watch dataDir for changes to its channels config. A missing dir watches nothing (a config created later is picked up at the next start).

worktreeBranchFunction#

The worktree branch of a conversation's session: zidane/<provider>-<first 8 hex>.

Classes#

ChannelProviderErrorClass#

An error a provider throws (from start, or reports with ctx.fail) to say whether retrying can help. Any other error counts as 'transient'.

ChannelsConfigErrorClass#

A config that does not load: every problem, each naming its key path.

GithubApiErrorClass#

A REST call that failed.

SlackApiErrorClass#

A Web API call that failed: Slack's error code, and whether retrying can help.

Constants#

BUILTIN_CHANNEL_PROVIDERSConstant#

Built-in providers by name (slack, github).

CHANNEL_SECRET_KEYSConstant#

The config keys that hold secrets, per provider.

CHANNELS_JSONConstant#

The JSON config's file name in the data dir.

CHANNELS_KILL_SWITCHConstant#

Set to 1, true, yes or on: channels stay off whatever the config says.

CHANNELS_ROUTE_PREFIXConstant#

Where webhook routes are mounted: /channels/<channel name><route path>.

CHANNELS_TSConstant#

The TS config's file name in the data dir.

DEFAULT_LIMITSConstant#

Default throttles (owners are never throttled).

GITHUB_API_BASEConstant#

Where the REST API lives. Tests point it at a fake (createGithubProvider({ apiBase })).

githubProviderConstant#

The GitHub provider the hosts register.

READONLY_AGENTConstant#

The read-only level's agent profile.

slackProviderConstant#

The Slack provider the hosts register.

Interfaces#

AccessContextInterface#

What a function access rule is called with (channels.config.ts only).

AccessPolicyInterface#

A level with some of its rules changed.

ApprovalViewInterface#

A tool call waiting for an owner's decision.

BackoffOptionsInterface#

Retry delays of a channel whose provider failed: doubling from baseMs, capped at maxMs.

BindingInterface#

Where a channel's conversations go: the folder, agent and environment of their sessions.

BindingSummaryInterface#

One binding, as channels check shows it.

BranchPublisherInterface#

Pushes a conversation's branch and opens its pull request.

ChannelAuditEventInterface#

One audit record: who did what through a channel. Carries provider ids, never message text.

ChannelCommonInterface#

Fields every channel has.

ChannelLoggerInterface#

Where a channel writes what it does. Never given message text from strangers.

ChannelProviderInterface#

A channel provider.

ChannelRouteInterface#

An HTTP route a provider serves (a webhook). The host mounts it at /channels/<channelName><path>.

ChannelsCheckInterface#

The outcome of checkChannels.

ChannelsConfigInterface#

The whole file.

ChannelsConfigChangeInterface#

A changed (written, created or deleted) config file.

ChannelsConfigFileInterface#

The config file in use.

ChannelsConfigWatcherInterface#

Stops watching.

ChannelsHostInterface#

Channels hosted by a zidane-server or the laptop daemon.

ChannelsHostStatusInterface#

What the host knows about its channels.

ChannelsReloadResultInterface#

The outcome of a (re)load.

ChannelsRunnerInterface#

A running channels runner.

ChannelStatusInterface#

One channel's state.

ChannelSummaryInterface#

One channel, as channels check shows it.

ChannelsWarningInterface#

One finding, at a key path.

DeliveryViewInterface#

What became of one message. 'queued' also covers a message the runner holds back (a limit); 'context' a message kept as context only.

EffectiveAccessInterface#

A level with every rule spelled out.

GithubChannelInterface#

A GitHub App (server only).

GithubClientInterface#

The GitHub client a channel's presenter gets (PresenterContext.client).

GithubClientOptionsInterface#

Options of createGithubClient.

GithubMatchInterface#

A GitHub repository, as owner/name.

GithubMessageRefInterface#

One comment: what reactions go on.

GithubProviderOptionsInterface#

Test seams of createGithubProvider. Not user config: a channel always talks to GitHub itself.

GithubPullInterface#

A pull request opened or updated.

GithubRefInterface#

Where a conversation lives: the issue or pull request the presenter answers on.

HostChannelsOptionsInterface#

Options of hostChannels.

InboundMessageInterface#

One message a provider received.

InteractionViewInterface#

A question or plan waiting for an answer.

JsonErrorPositionInterface#

A 1-based line and column, and what was wrong there.

LimitsInterface#

Throttles per channel. Owners are never throttled.

LoadedChannelsInterface#

A loaded config.

LoadOptionsInterface#

Options of loadChannelsConfig.

NoticeViewInterface#

Something the runner tells the conversation (a command's result, a refusal).

PresenterInterface#

Hooks that map host activity to provider calls. Ref is the conversation's ref from the provider's inbound messages.

PresenterContextInterface#

What a presenter is built with when its channel starts.

PresenterDefinitionInterface#

Builds a channel's presenter once its provider has started.

PresenterStoreInterface#

A channel presenter's persistent values (PresenterContext.store).

ProviderContextInterface#

What a provider gets when its channel starts.

ProviderInstanceInterface#

A started channel.

ResolvedAccessInterface#

What a sender's message runs under.

ResolvedSecretsInterface#

The config with every secret read, and what it took.

RespondResultInterface#

The outcome of a click: ok: false when the clicker may not answer, or the request is gone.

RoleAccessInterface#

Access per role at one layer (defaults, channel or binding).

RunChannelsOptionsInterface#

Options of runChannels.

RunnerTimersInterface#

The clock and timers the runner uses (backoff, hourly limits).

RunSummaryInterface#

What a run cost, when known.

SettledViewInterface#

An approval or question that stopped waiting without this presenter's respond (answered in another window, timed out, its run ended).

SlackChannelInterface#

A Slack workspace app.

SlackClientInterface#

The Slack client a channel's presenter gets (PresenterContext.client), so a custom presenter can post, react and stream like the built-in one.

SlackClientOptionsInterface#

Options of createSlackClient.

SlackMessageRefInterface#

One Slack message: what reactions go on.

SlackProviderOptionsInterface#

Test seams of createSlackProvider. Not user config: a channel always talks to Slack itself.

SlackRefInterface#

Where a conversation lives: what the presenter answers into.

ValidateOptionsInterface#

Options of validateChannelsConfig.

WatchOptionsInterface#

Options of watchChannelsConfig.

Types#

AccessType#

A level, a policy, or (TS config only) a function of the sender picking one.

AccessLevelType#

Named access presets; each expands to a session policy and session options (./access).

ChannelApprovalsType#

Approval modes a channel session may run under.

ChannelAuditSinkType#

Receives audit records.

ChannelConfigType#

One configured channel.

ChannelFailureKindType#

How a provider classifies a failure: 'auth' and 'config' stop the channel (its integration shows 'failed'), anything else is retried with backoff.

ChannelRoleType#

Who a provider user is to a channel. Anyone else is a stranger and is ignored.

ChannelsHostFlavorType#

Which host runs the channels. The laptop daemon has no public port and serves its user only: socket transports, owners only.

ChannelsReloadTriggerType#

What started a (re)load.

GithubAuthType#

How a call authenticates: as the App (JWT) or as an installation.

GithubChannelClientType#

The client a GitHub channel's presenter gets: the REST client and, for the built-in presenter, the branch publisher.

GithubReactionType#

A reaction GitHub accepts.

PublishResultType#

What publishing did.

RunViewType#

One step of a run.

SecretType#

A secret: inline, or the name of an environment variable holding it.

SlackMatchType#

A Slack conversation: a channel (C…, or G… for private ones) or the bot's DMs.

SpawnLikeType#

node:child_process spawn, or a spy around it (tests).

ValidationResultType#

The outcome: a typed config, or every problem found.