sokel-plugin-sdk

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2026 License: Apache-2.0

README

Sokel Plugin SDK

Go Reference License

English · 简体中文

Write a Sokel plugin as a small Go program. Declare what your operations take and return; the SDK handles registration, transport, credentials, file transfer, heartbeats and reconnects.

OnIssuesList(p, func(ctx sokel.Ctx, in *IssuesListIn) (*IssuesListOut, error) {
    issues, err := client.ListIssues(ctx, in.Project, in.State)
    if err != nil {
        return nil, err
    }
    return &IssuesListOut{Issues: issues, Count: len(issues)}, nil
})

That handler signature is generated from your declaration. There is no map[string]any anywhere in your code, and no second copy of the contract to keep in sync by hand.

Why plugins dial out

A plugin connects to the platform, not the other way round. No inbound port, no public IP, no firewall hole. A plugin running on a NAS in your basement is callable from the platform just like one running in the cloud — which is also why something inherently local, like a coding agent on your own laptop, can be a plugin at all.

Install

The library:

go get github.com/sokel-dev/sokel-plugin-sdk

The sokel-gen CLI — scaffolds plugins and generates the typed code from your declarations:

go install github.com/sokel-dev/sokel-plugin-sdk/cmd/sokel-gen@latest

Requires Go 1.25 or newer. You can skip the install and use go run github.com/sokel-dev/sokel-plugin-sdk/cmd/sokel-gen instead — that is the form used in //go:generate lines, so the version is pinned by your go.mod rather than by whatever you last installed.

How it works

Four steps, always in this order: declare → generate → implement → connect.

Start from a working skeleton rather than an empty directory:

sokel-gen init ./my-plugin
cd my-plugin && go mod tidy && sokel-gen && go build ./...

That scaffolds schema/, main.go, an embedded user-facing doc and both README files, with one real operation already wired end to end. The rest of this section is what init gave you — change it into your own plugin.

1. Declare the contract in a schema/ package — inputs, outputs, events, credential fields:

package schema

import (
	"github.com/sokel-dev/sokel-plugin-sdk/contract"
	"github.com/sokel-dev/sokel-plugin-sdk/contract/field"
)

type IssuesList struct{}

func (IssuesList) Meta() contract.Meta {
	return contract.Meta{ID: "issues_list", Label: "List issues"}
}

func (IssuesList) Inputs() []contract.FieldSpec {
	return []contract.FieldSpec{
		field.String("project").Label("Project"),
		field.Enum("state",
			field.Opt("opened", "Open"),
			field.Opt("closed", "Closed")).Default("opened"),
	}
}

func (IssuesList) Outputs() []contract.FieldSpec {
	return []contract.FieldSpec{
		field.Array("issues", []Issue{}).Label("Issues"),
		field.Int("count").Label("Count"),
	}
}

2. Generate the typed Go from that declaration:

//go:generate go run github.com/sokel-dev/sokel-plugin-sdk/cmd/sokel-gen
go generate ./...

This writes zz_types.go (the In/Out structs) and zz_register.go (an OnXxx function per operation). Don't hand-edit them.

The contract is produced at compile time, not by runtime reflection. A mistake in the declaration fails the build instead of surfacing on some later call. sokel-gen check verifies the generated files are current — wire it into CI, because forgetting to regenerate is the classic way codegen goes wrong.

3. Implement the handlers — the signatures are fully concrete, so the compiler checks your work.

4. Connect back to the platform:

p := sokel.New(sokel.Config{
	Endpoint: sokel.Env("ENDPOINT"),
	Token:    sokel.Env("TOKEN"),
	Name:     "my-plugin",
})
OnIssuesList(p, handleIssuesList)
log.Fatal(p.Run())

Configuration

The SDK reads everything from SOKEL_-prefixed environment variables:

Variable Required Meaning
SOKEL_ENDPOINT yes nats://broker:4222, or an https:// platform URL to discover the broker from
SOKEL_TOKEN yes Access-group token (skp_…) identifying plugin + workspace
SOKEL_NATS_TOKEN no Broker-level auth, if the broker requires it
SOKEL_NATS_CA no Custom CA bundle for tls:// brokers
SOKEL_INSTANCE_ID no Pin a replica identity across restarts
SOKEL_REGION no Region label for the replica

Credentials are never stored by the plugin. The platform injects the resolved fields with each call; read them typed with sokel.CredentialAs[T].

Packages

Package What it is
sokel The runtime: register, dispatch, emit results, files, events, webhooks
contract The contract types — field specs, metadata, credential and event shapes
contract/field Builders for declaring fields (field.String, field.Enum, …)
sokelgen The code generator behind sokel-gen
cmd/sokel-gen The CLI — see below
pluginenv Reads the SOKEL_ environment variables

The sokel-gen CLI

Command What it does
sokel-gen Generate for the current directory — the form used in //go:generate
sokel-gen init <dir> Scaffold a new plugin that builds and runs as-is
sokel-gen generate [dir...] Generate; a directory holding many plugins is walked automatically
sokel-gen check [dir...] Verify the generated files are current, write nothing — for CI
sokel-gen export <json|ts|python> [dir] Print the contract in another form
sokel-gen migrate [dir] Turn an old struct+tag plugin into a schema/ declaration

generate and check take -schema <name> when the declaration package isn't called schema.

Plugins are found by looking for a schema/ directory, not by reading //go:generate lines. That distinction matters: go generate ./... silently skips a plugin whose directive someone forgot to write, and a skipped plugin's contract drifts with nothing going red. Four first-party plugins were in exactly that state before this was checked.

sokel-gen check ./plugins        # every plugin under ./plugins, one command

check runs every plugin before reporting, so CI shows you all the stale ones at once instead of one per run.

Example

examples/sysinfo is a complete, runnable plugin: two operations, a file input, an embedded user-facing doc.

cd examples/sysinfo
SOKEL_ENDPOINT=nats://localhost:4222 SOKEL_TOKEN=skp_xxx go run .

One declaration, many targets

sokel-gen does not translate Go to Go. It parses your schema/ package into a language-neutral intermediate representation, then renders that IR through a backend of your choosing:

schema/ declaration ──▶ IR ──┬──▶ generate        zz_types.go / zz_register.go (typed Go)
                             ├──▶ export json    the contract itself, language-neutral
                             ├──▶ export ts      TypeScript contract table for a UI
                             └──▶ export python  pydantic models
sokel-gen export json    # feed this to any generator, in any language

The JSON deliberately omits Go type names — it carries the contract, not the Go implementation detail, so a generator for another language has nothing to work around.

This matters because the wire protocol is JSON over NATS with base64 bytes: no gob, no protobuf, nothing Go-specific. This SDK is one implementation of that protocol, not the definition of it. An SDK for another language does not reverse-engineer Go — it reads the same exported contract and generates its own types. Rust and Node.js backends are the intended next targets, and adding one is a renderer over the existing IR rather than a second parser.

Status

The Sokel platform itself is not open source yet. Until it is, this SDK is useful for reading the plugin model and preparing a plugin — but a plugin needs a running Sokel instance to dial into.

License

Apache-2.0. See LICENSE.

Directories

Path Synopsis
cmd
sokel-gen command
sokel-gen:Sokel 插件的契约工具链。
sokel-gen:Sokel 插件的契约工具链。
Package contract:插件契约的**唯一定义** —— 字段类型、声明、与 Go 类型之间的绑定。
Package contract:插件契约的**唯一定义** —— 字段类型、声明、与 Go 类型之间的绑定。
auth
Package auth 构造凭证的获取方式声明。
Package auth 构造凭证的获取方式声明。
field
Package field 提供声明插件契约的 builder。
Package field 提供声明插件契约的 builder。
examples
sysinfo command
sysinfo 插件:返回「插件运行系统」的基础信息。
sysinfo 插件:返回「插件运行系统」的基础信息。
Package plugin:插件实现与**传输**之间的接缝。
Package plugin:插件实现与**传输**之间的接缝。
Package pluginenv:插件侧环境变量的统一读法。
Package pluginenv:插件侧环境变量的统一读法。
Package sokel is the Sokel plugin SDK for Go.
Package sokel is the Sokel plugin SDK for Go.
field
Package field 是 plugin-core/contract/field 的转发。
Package field 是 plugin-core/contract/field 的转发。
Package sokelgen 从**源码**(AST)推导插件契约,取代运行时反射。
Package sokelgen 从**源码**(AST)推导插件契约,取代运行时反射。
internal/demoschema
Package demoschema 是生成器的验证语料:覆盖 builder 的主要形态。
Package demoschema 是生成器的验证语料:覆盖 builder 的主要形态。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL