Skip to content

mirasoth/soothe-client-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

71 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

soothe-client-go

Talk to a running soothe-daemon over WebSocket — send prompts, stream agent turns, run jobs.

go get github.com/mirasoth/soothe-client-go@latest

Requires a local daemon (default ws://127.0.0.1:8765).

Quick start

package main

import (
	"context"
	"fmt"

	"github.com/mirasoth/soothe-client-go/appkit"
)

func main() {
	ctx := context.Background()
	session := appkit.NewDaemonSession("ws://127.0.0.1:8765", nil)
	defer session.Close()

	if _, err := session.Connect(ctx, ""); err != nil {
		panic(err)
	}
	if err := session.SendTurn(ctx, "Summarize this in one sentence: agents need tools.", nil); err != nil {
		panic(err)
	}
	chunks, errCh := session.IterTurnChunks(ctx, 0)
	for chunk := range chunks {
		fmt.Println(chunk.Mode, chunk.Data)
	}
	if err := <-errCh; err != nil {
		panic(err)
	}
}

More patterns: examples/ (hello → streaming → multi-turn → pool → jobs).

What you get

Need Use
One conversation, stream replies appkit.DaemonSession
Jobs / cron one-shots soothe.CommandClient
Raw WebSocket / custom RPCs soothe.Client
Many users / HTTP backend appkit.ConnectionPool + TurnRunner

DaemonSession uses a dual-socket layout (stream + RPC sidecar): peels leftover prior-goal terminals, ignores premature soothe.stream.end until the turn has progress, drains a short post-idle window, and sends delivery_ack on terminal frames for daemon drain gating.

import (
	"time"
	soothe "github.com/mirasoth/soothe-client-go"
)

cc := soothe.NewCommandClient("ws://127.0.0.1:8765", 30*time.Second)
created, err := cc.JobCreate(ctx, "Echo: smoke job", "/tmp/workspace")
// … JobStatus / JobCancel / CronAdd / CronList …

Package layout

soothe-client-go/
├── client.go, protocol.go, session.go, …  — transport + Client RPCs
├── command_client.go, stream_terminal.go  — CommandClient + turn helpers
└── appkit/                                — DaemonSession, pool, TurnRunner, …

appkit — pool & TurnRunner

Product backends that map chat sessions to daemon loops use ConnectionPool + QueryGate + TurnRunner + EventClassifier + SessionStore.

Knob Default Notes
IdleTimeout off Silence watchdog between events
MinIdleTimeoutWithAttachments off Floor when attachments are present
OnIdleTimeout / OnQueryTimeout / OnStreamClose fail Or soft-complete
CompactAttachmentsBeforeSend false Optional image downscale
TreatStatusIdleAsComplete (classifier) false Opt-in idle deliverable

SessionStore methods take context.Context as the first parameter so cancellation and deadlines reach the storage backend. See docs/impl/sessionstore-context.md and docs/impl/turn-lifecycle.md.

Limitations

Autopilot control is WebSocket-only (protocol-1 autopilot_* / job_* request RPCs). Prefer CommandClient for job/cron/autopilot one-shots so they do not share a streaming socket. Worker event streams use Client.AutopilotSubscribe on a long-lived connection.

Develop

go test ./...                       # unit + example tests (mock daemon)
go test ./examples/progressive/     # 01–06 ladder (offline)
go test -short ./...                # skip live-daemon integration

Compatibility

Same protocol-1 WebSocket contract as soothe-client-python and @mirasoth/soothe-client.

License

MIT — see LICENSE.

About

❯❯❯❯ WebSocket client in Go for soothe-daemon

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors