client

package
v1.0.3 Latest Latest
Warning

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

Go to latest
Published: Jul 29, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseSSE

func ParseSSE(r io.Reader, fn func(Event) error) error

ParseSSE reads an event-stream from r and calls fn for every complete event. It returns when the stream ends (io.EOF) or fn returns a non-nil error.

SSE frames are separated by a blank line. Within a frame, lines beginning with "event:" set the event name and lines beginning with "data:" append to the payload. Multiple data lines are joined with newlines per the spec. Lines starting with ":" are comments and ignored.

Types

type APIError

type APIError struct {
	StatusCode int
	Message    string
}

APIError is a decoded non-2xx response. The Tabstack endpoints return a flat {"error": "..."} body, which we surface alongside the status code.

func (*APIError) Error

func (e *APIError) Error() string

type AutomateInputFieldValue

type AutomateInputFieldValue struct {
	Ref   string `json:"ref"`
	Value any    `json:"value"`
}

AutomateInputFieldValue is a single field submission for an interactive form request. Ref matches the field identifier from the SSE event; Value is the user-supplied answer.

type AutomateInputRequest

type AutomateInputRequest struct {
	Fields    []AutomateInputFieldValue `json:"fields,omitempty"`
	Cancelled bool                      `json:"cancelled,omitempty"`
}

AutomateInputRequest is the body for POST /automate/{requestID}/input. Supply Fields with values when answering a form request, or set Cancelled to true to decline without providing data.

type AutomateRequest

type AutomateRequest struct {
	Task                  string     `json:"task"`
	Data                  any        `json:"data,omitempty"`
	GeoTarget             *GeoTarget `json:"geo_target,omitempty"`
	Guardrails            string     `json:"guardrails,omitempty"`
	Interactive           bool       `json:"interactive,omitempty"`
	MaxIterations         int        `json:"maxIterations,omitempty"`
	MaxValidationAttempts int        `json:"maxValidationAttempts,omitempty"`
	URL                   string     `json:"url,omitempty"`
}

AutomateRequest is the body for POST /automate. The endpoint always streams Server-Sent Events. Task is the only required field; everything else tunes the run. Data is freeform context (e.g. form values) so it stays as any and is omitted when nil.

type Citation

type Citation struct {
	Number int    `json:"number,omitempty"`
	Title  string `json:"title,omitempty"`
	URL    string `json:"url,omitempty"`
}

Citation is a single source backing a research report. The report text refers to sources by number ([1], [2], ...); Number carries that key when the API supplies it, otherwise the renderer falls back to list position.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a thin wrapper around http.Client that knows how to talk to the Tabstack API: it attaches the bearer token, points at the right base URL, and centralises request building and error decoding. There is deliberately no generated code here, we map each endpoint by hand so the streaming behaviour stays under our control.

func New

func New(apiKey, baseURL string, opts ...Option) *Client

New constructs a Client. baseURL should not carry a trailing slash; we normalise it anyway to keep path joining predictable.

func (*Client) Automate

func (c *Client) Automate(ctx context.Context, req AutomateRequest, fn func(Event) error) error

Automate runs an AI browser-automation task, invoking fn for each streamed event (task:setup, task:trace_context, task:started, agent:processing, browser:navigated, agent:extracted, task:completed, complete, done). Cancellation flows through ctx.

func (*Client) AutomateInput

func (c *Client) AutomateInput(ctx context.Context, requestID string, req AutomateInputRequest) error

AutomateInput submits an input response for a running automation task. This endpoint is a plain request/response, not a stream.

func (*Client) ExtractJSON

func (c *Client) ExtractJSON(ctx context.Context, req ExtractJSONRequest) (json.RawMessage, error)

ExtractJSON fetches a URL and extracts structured data per the schema. The response shape is dictated by the caller's schema, so we return the raw JSON.

func (*Client) ExtractMarkdown

ExtractMarkdown fetches a URL and converts it to clean Markdown.

func (*Client) GenerateJSON

func (c *Client) GenerateJSON(ctx context.Context, req GenerateJSONRequest) (json.RawMessage, error)

GenerateJSON fetches and transforms content into the caller's schema. As with extract/json, the response shape is caller-defined so we return raw JSON.

func (*Client) Research

func (c *Client) Research(ctx context.Context, req ResearchRequest, fn func(Event) error) error

Research runs an AI research query, invoking fn for each streamed event (phase, progress, complete, error).

type DebugInfo added in v1.0.3

type DebugInfo struct {
	Method  string
	URL     string
	Status  int           // 0 when the round trip failed before a response
	Elapsed time.Duration // request sent -> response headers received
	TraceID string        // x-trace-id, the id to quote in a support request

	RateLimitLimit     string    // x-ratelimit-limit
	RateLimitRemaining string    // x-ratelimit-remaining
	RateLimitReset     time.Time // x-ratelimit-reset, parsed from unix seconds; zero if absent
}

DebugInfo is what a single API round trip reveals when --debug is on: the request line, the response status, how long the server took to send headers, and the trace and rate-limit headers the API returns. It carries no bodies and no credentials.

type Effort

type Effort string

Effort controls the speed/capability tradeoff on fetch-based endpoints.

  • "min": fastest, no fallback (1-5s)
  • "standard": balanced, default (3-15s)
  • "max": full browser rendering for JS-heavy sites (15-60s)
const (
	EffortMin      Effort = "min"
	EffortStandard Effort = "standard"
	EffortMax      Effort = "max"
)

type Event

type Event struct {
	Name string
	Data json.RawMessage
}

Event is a single Server-Sent Event. The Tabstack streaming endpoints emit frames shaped like:

event: agent:processing
data: {"operation": "Creating task plan"}

We capture the event name and the raw data payload. Data is kept as json.RawMessage because the shape varies per event type, and for the automate endpoint some fields are themselves JSON encoded as strings.

func (Event) DataString

func (e Event) DataString() string

DataString returns the data payload as a plain string. Handy when the data is not JSON, or when you want the raw text before decoding.

func (Event) Decode

func (e Event) Decode(v any) error

Decode unmarshals the event data into v.

type ExtractJSONRequest

type ExtractJSONRequest struct {
	JSONSchema json.RawMessage `json:"json_schema"`
	URL        string          `json:"url"`
	Effort     Effort          `json:"effort,omitempty"`
	GeoTarget  *GeoTarget      `json:"geo_target,omitempty"`
	NoCache    bool            `json:"nocache,omitempty"`
}

ExtractJSONRequest is the body for POST /extract/json. JSONSchema is an arbitrary JSON schema object describing the data to pull out, so we keep it as json.RawMessage and let the caller supply it verbatim from a file.

type ExtractMarkdownRequest

type ExtractMarkdownRequest struct {
	URL       string     `json:"url"`
	Effort    Effort     `json:"effort,omitempty"`
	GeoTarget *GeoTarget `json:"geo_target,omitempty"`
	Metadata  bool       `json:"metadata,omitempty"`
	NoCache   bool       `json:"nocache,omitempty"`
}

ExtractMarkdownRequest is the body for POST /extract/markdown.

type ExtractMarkdownResponse

type ExtractMarkdownResponse struct {
	Content  string    `json:"content"`
	URL      string    `json:"url"`
	Metadata *Metadata `json:"metadata,omitempty"`
}

ExtractMarkdownResponse is the body for a successful /extract/markdown call.

type GenerateJSONRequest

type GenerateJSONRequest struct {
	Instructions string          `json:"instructions"`
	JSONSchema   json.RawMessage `json:"json_schema"`
	URL          string          `json:"url"`
	Effort       Effort          `json:"effort,omitempty"`
	GeoTarget    *GeoTarget      `json:"geo_target,omitempty"`
	NoCache      bool            `json:"nocache,omitempty"`
}

GenerateJSONRequest is the body for POST /generate/json. It fetches a URL, extracts content, then transforms it with AI per the instructions. The output is shaped by JSONSchema. Instructions caps at 20,000 characters server side, so we let the command layer validate length and just pass it through.

type GeoTarget

type GeoTarget struct {
	Country string `json:"country,omitempty"`
}

GeoTarget is the optional geotargeting block shared by several endpoints. Country is an ISO 3166-1 alpha-2 code, e.g. "US", "GB", "JP".

type Metadata

type Metadata struct {
	Author      string   `json:"author,omitempty"`
	CreatedAt   string   `json:"created_at,omitempty"`
	Creator     string   `json:"creator,omitempty"`
	Description string   `json:"description,omitempty"`
	Image       string   `json:"image,omitempty"`
	Keywords    []string `json:"keywords,omitempty"`
	ModifiedAt  string   `json:"modified_at,omitempty"`
	PageCount   int      `json:"page_count,omitempty"`
	PDFVersion  string   `json:"pdf_version,omitempty"`
	Producer    string   `json:"producer,omitempty"`
	Publisher   string   `json:"publisher,omitempty"`
	SiteName    string   `json:"site_name,omitempty"`
	Subject     string   `json:"subject,omitempty"`
	Title       string   `json:"title,omitempty"`
	Type        string   `json:"type,omitempty"`
	URL         string   `json:"url,omitempty"`
}

Metadata is the optional page metadata block returned when Metadata is requested. Every field is optional and absent fields stay zero valued.

type Option

type Option func(*Client)

Option configures a Client.

func WithDebug added in v1.0.3

func WithDebug(sink func(DebugInfo)) Option

WithDebug wraps the client's transport so each round trip is timed and its trace/rate-limit headers are reported to sink. A nil sink is a no-op.

It measures to response headers, not to end of body: for a streaming endpoint that is time-to-first-byte (the stream then continues), and for a JSON endpoint it is the server's latency without the body download. Pass it after WithHTTPClient so it wraps whatever transport that installed.

func WithHTTPClient

func WithHTTPClient(h *http.Client) Option

WithHTTPClient swaps the underlying http.Client. Mostly useful for tests.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets a request timeout on the default http.Client. Note that for streaming endpoints a hard timeout will cut the stream off, so the streaming methods build their own request context rather than relying on this.

type ResearchMode

type ResearchMode string

ResearchMode selects how much work the research endpoint does.

  • "fast": quick answers, minimal searches (default)
  • "balanced": standard multi-iteration research
const (
	ResearchFast     ResearchMode = "fast"
	ResearchBalanced ResearchMode = "balanced"
)

type ResearchRequest

type ResearchRequest struct {
	Query        string       `json:"query"`
	FetchTimeout int          `json:"fetch_timeout,omitempty"`
	Mode         ResearchMode `json:"mode,omitempty"`
	NoCache      bool         `json:"nocache,omitempty"`
}

ResearchRequest is the body for POST /research. Always streams SSE.

Jump to

Keyboard shortcuts

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