journal

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package journal is the CLI's local action journal: a SQLite database under the CLI home that records what the tool did, in three linked tables. An operations row groups the one-or-more API calls a single logical operation makes (a place reconcile sends and then looks up; a history walk pages); an api_calls row records each underlying HTTP call (linked to its operation, with a 1-based sequence within it); and an orders row holds a dedicated record per placed order (minted at clientOrderId time and updated with the server order id once the placement resolves, linked to its operation).

It exists for two audiences. First, the AI agents this CLI is built for: an agent can make mistakes, so the CLI keeps an automatic, durable source of truth of what it actually did — when a human asks "what did you do?", the agent can read the journal back instead of guessing. Second, support: when a user hits a problem, the journal (or a redacted `debug bundle` of it) is the diagnostic record to send to Korbit.

It never stores secrets — only the public API-key id and the pre-signing request parameters (the ED25519 signature and private key never reach here).

Index

Constants

View Source
const FileName = "korbit-cli.db"

FileName is the journal database file under the CLI home.

Variables

This section is empty.

Functions

func DefaultPath

func DefaultPath(home string) string

DefaultPath returns the journal database path under home.

func Disabled

func Disabled(getenv func(string) string) bool

Disabled reports whether journaling has been turned off via the environment (KORBIT_CLI_NO_JOURNAL=1/true/yes). The escape hatch lets a caller run against a read-only home, or opt out of local logging entirely.

Types

type CallRecord

type CallRecord struct {
	OperationID  int64 // the operations row this call belongs to (0 => NULL)
	Seq          int   // 1-based within the operation; 0 for ad-hoc calls
	StartedAtMs  int64
	FinishedAtMs int64
	Method       string
	Path         string
	BaseURL      string
	Auth         bool
	KeyName      string
	APIKeyID     string
	ParamsJSON   string
	HTTPStatus   *int // nil when no HTTP response was received (network failure / success)
	Success      bool
	ErrorCode    string
	ErrorMessage string
	RetryCount   int
	DurationMs   int64
	CLIVersion   string
}

CallRecord is one API-call outcome to record in api_calls. OperationID links the call to the operation that issued it (0 ⇒ a NULL link, for an ad-hoc call), and Seq is its 1-based position within that operation (0 for ad-hoc).

type CallRow

type CallRow struct {
	ID           int64           `json:"id"`
	OperationID  *int64          `json:"operationId,omitempty"`
	Seq          int             `json:"seq"`
	StartedAtMs  int64           `json:"startedAtMs"`
	FinishedAtMs *int64          `json:"finishedAtMs,omitempty"`
	Method       string          `json:"method"`
	Path         string          `json:"path"`
	BaseURL      string          `json:"baseUrl"`
	Auth         bool            `json:"auth"`
	KeyName      string          `json:"keyName,omitempty"`
	APIKeyID     string          `json:"apiKeyId,omitempty"`
	Params       json.RawMessage `json:"params,omitempty"`
	HTTPStatus   *int            `json:"httpStatus,omitempty"`
	Success      bool            `json:"success"`
	ErrorCode    string          `json:"errorCode,omitempty"`
	ErrorMessage string          `json:"errorMessage,omitempty"`
	RetryCount   int             `json:"retryCount"`
	DurationMs   *int64          `json:"durationMs,omitempty"`
	CLIVersion   string          `json:"cliVersion,omitempty"`
}

CallRow is a recorded api_calls row, shaped for JSON output and the support bundle. Absent/empty fields are omitted.

type Logger

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

Logger is a handle to the journal database.

func Open

func Open(path string, noFsync bool, log *slog.Logger) (*Logger, error)

Open opens (creating if needed) the journal database at path and ensures the schema exists. It enables WAL so concurrent korbit-cli invocations can read while one writes, and a busy_timeout so a writer waits for the lock instead of failing with SQLITE_BUSY. A single pooled connection (SetMaxOpenConns(1)) serializes all in-process access, so no additional application-level locking is needed; WAL + busy_timeout cover the cross-process case.

noFsync sets PRAGMA synchronous=OFF: writes are not flushed to disk, which is faster but means a power loss or OS crash may lose or corrupt recent writes. The pre-send ordering guarantee (a journaled row is written before the request proceeds) is unaffected — only crash-durability is traded for speed.

log receives operational diagnostics (the path, pragmas, schema-version reconciliation, and an Info milestone once opened); nil is silent (logging.Or).

func (*Logger) Close

func (l *Logger) Close() error

Close closes the database handle.

func (*Logger) FinishOperation

func (l *Logger) FinishOperation(id int64, f OperationFinish) error

FinishOperation updates the operations row identified by id with the result.

func (*Logger) FinishOrder

func (l *Logger) FinishOrder(id int64, f OrderFinish) error

FinishOrder updates the order row identified by id with the placement result. 'accepted' is positive proof the order landed, so it is sticky: a later result of 'failed' or 'unknown' never downgrades it, and the previously-recorded order_id is kept when the new result carries none. So reusing a clientOrderId to retry an order that already went through — which the server answers with DUPLICATE_CLIENT_ORDER_ID, or which a later ambiguous attempt can only call UNKNOWN — doesn't erase the truth that the order is live. The CASE clauses read the row's pre-update status, so the guard compares against the existing value. Every per-attempt outcome is still preserved in full in api_calls.

func (*Logger) LogCall

func (l *Logger) LogCall(r CallRecord) (int64, error)

LogCall inserts an api_calls row and returns its id.

func (*Logger) Path

func (l *Logger) Path() string

Path returns the database file path.

func (*Logger) RecentCalls

func (l *Logger) RecentCalls(limit int) ([]CallRow, error)

RecentCalls returns the most recent api_calls rows, newest first.

func (*Logger) RecentOperations

func (l *Logger) RecentOperations(limit int) ([]OperationRow, error)

RecentOperations returns the most recent operations rows, newest first.

func (*Logger) RecentOrders

func (l *Logger) RecentOrders(limit int) ([]OrderRow, error)

RecentOrders returns the most recent orders rows, newest first.

func (*Logger) StartOperation

func (l *Logger) StartOperation(o OperationStart) (int64, error)

StartOperation inserts an operations row with outcome 'running' and returns its id, to be folded with FinishOperation once the operation completes.

func (*Logger) StartOrder

func (l *Logger) StartOrder(o OrderStart) (int64, error)

StartOrder records (or, when the clientOrderId is being reused to retry the same order, refreshes) the order's mint-time row and returns its id. Reusing a clientOrderId bumps attempt_count and re-arms the row rather than inserting a duplicate — honoring both the UNIQUE(client_order_id) index and the documented idempotent-retry flow.

type OperationFinish

type OperationFinish struct {
	FinishedAtMs int64
	Outcome      string // ok|failed|unknown
	ErrorCode    string
	Attempts     int // total api_calls issued under this operation
}

OperationFinish is the result folded into an operations row once the operation completes.

type OperationRow

type OperationRow struct {
	ID           int64  `json:"id"`
	StartedAtMs  int64  `json:"startedAtMs"`
	FinishedAtMs *int64 `json:"finishedAtMs,omitempty"`
	OpID         string `json:"opId"`
	Surface      string `json:"surface"`
	Safety       string `json:"safety,omitempty"`
	Outcome      string `json:"outcome"`
	ErrorCode    string `json:"errorCode,omitempty"`
	Attempts     int    `json:"attempts"`
	KeyName      string `json:"keyName,omitempty"`
	APIKeyID     string `json:"apiKeyId,omitempty"`
	CLIVersion   string `json:"cliVersion,omitempty"`
}

OperationRow is a recorded operations row, shaped for JSON output and the support bundle. Absent/empty fields are omitted.

type OperationStart

type OperationStart struct {
	StartedAtMs int64
	OpID        string // dotted operation id, e.g. "order.place"
	Surface     string // cli|monitor|mcp|...
	Safety      string // read-only|idempotent|non-idempotent
	KeyName     string
	APIKeyID    string
	CLIVersion  string
}

OperationStart is the operations row written when an operation begins, before any of its calls are sent. outcome is set to 'running'; FinishOperation folds in the result.

type OrderFinish

type OrderFinish struct {
	FinishedAtMs int64
	Status       string
	OrderID      string
	ErrorCode    string
	RetryCount   int
}

OrderFinish is the outcome to fold into the order's row once the placement call has returned.

type OrderRow

type OrderRow struct {
	ID            int64           `json:"id"`
	OperationID   *int64          `json:"operationId,omitempty"`
	CreatedAtMs   int64           `json:"createdAtMs"`
	FinishedAtMs  *int64          `json:"finishedAtMs,omitempty"`
	ClientOrderID string          `json:"clientOrderId"`
	Symbol        string          `json:"symbol,omitempty"`
	Side          string          `json:"side,omitempty"`
	OrderType     string          `json:"type,omitempty"`
	Price         string          `json:"price,omitempty"`
	Qty           string          `json:"qty,omitempty"`
	Amt           string          `json:"amt,omitempty"`
	Tif           string          `json:"tif,omitempty"`
	Params        json.RawMessage `json:"params,omitempty"`
	KeyName       string          `json:"keyName,omitempty"`
	APIKeyID      string          `json:"apiKeyId,omitempty"`
	Status        string          `json:"status"`
	OrderID       string          `json:"orderId,omitempty"`
	ErrorCode     string          `json:"errorCode,omitempty"`
	AttemptCount  int             `json:"attemptCount"`
	RetryCount    int             `json:"retryCount"`
}

OrderRow is a recorded orders row, shaped for JSON output and the bundle.

type OrderStart

type OrderStart struct {
	CreatedAtMs   int64
	OperationID   int64 // the operations row this order belongs to (0 => NULL)
	ClientOrderID string
	Symbol        string
	Side          string
	OrderType     string
	Price         string
	Qty           string
	Amt           string
	Tif           string
	ParamsJSON    string
	KeyName       string
	APIKeyID      string
}

OrderStart is the mint-time order intent, recorded before the placement call is sent (so a crash mid-call still leaves a record of what was attempted). OperationID links the order to the operation that placed it.

Jump to

Keyboard shortcuts

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