Documentation
¶
Index ¶
- Constants
- Variables
- func CheckVersionResponse(resp *http.Response) bool
- func DeriveSlug(name string) string
- func HandleRedirect(projectRoot string, info *RedirectInfo) error
- func InviteForbiddenReason(err error) string
- func PrintDeprecationWarning(message string)
- func PrintUpgradeRequired(minVersion string)
- func RenameRepoMarker(projectRoot, oldID, newID string) error
- type CreateInviteRequest
- type DistillObservation
- type DistillRequest
- type DistillResponse
- type DoctorIssue
- type DoctorResponse
- type ForbiddenError
- type ImportNotification
- type ImportVideoURLRequest
- type ImportVideoURLResponse
- type InviteResponse
- type KB
- type KBClient
- func (c *KBClient) Endpoint() string
- func (c *KBClient) GetBubble(ctx context.Context, kbID string) (*KB, error)
- func (c *KBClient) ListBubbles(ctx context.Context, scope KBScope) ([]KB, error)
- func (c *KBClient) ResolveSlug(ctx context.Context, scope KBScope, slug string) (string, error)
- func (c *KBClient) WithAuthToken(token string) *KBClient
- type KBScope
- type KBType
- type LedgerStatusResponse
- type ListVideosResponse
- type MergeRepoRequest
- type MergeRepoResponse
- type MockRepoService
- func (m *MockRepoService) Endpoint() string
- func (m *MockRepoService) GetDoctorIssues(repoID string) (*DoctorResponse, error)
- func (m *MockRepoService) MergeRepo(repoID string, markers map[string]json.RawMessage) (*MergeRepoResponse, *RedirectInfo, error)
- func (m *MockRepoService) NotifyImport(teamID string, metadata any) (string, error)
- func (m *MockRepoService) NotifyUninstall(repoID, repoSalt string) error
- func (m *MockRepoService) RegisterRepo(req *RepoInitRequest) (*RepoInitResponse, error)
- func (m *MockRepoService) WithAuthToken(token string) *RepoClient
- type PRLinkMiss
- type PaginationResponse
- type PendingInvite
- type PlanActivityNotification
- type QueryLatency
- type QueryRequest
- type QueryResponse
- type QueryResult
- type RecordingListItem
- type RedirectConfig
- type RedirectInfo
- type RedirectMapping
- type RepoClient
- func (c *RepoClient) CreateTeamInvite(ctx context.Context, teamRef string, req CreateInviteRequest) (*InviteResponse, error)
- func (c *RepoClient) DistillMemory(teamID string, req *DistillRequest) (*DistillResponse, error)
- func (c *RepoClient) Endpoint() string
- func (c *RepoClient) GetCLISettings() (json.RawMessage, error)
- func (c *RepoClient) GetDoctorIssues(repoID string) (*DoctorResponse, error)
- func (c *RepoClient) GetLedgerStatus(repoID string) (*LedgerStatusResponse, error)
- func (c *RepoClient) GetRepoDetail(repoID string) (*RepoDetailResponse, error)
- func (c *RepoClient) GetRepos() (*ReposResponse, error)
- func (c *RepoClient) GetTeamContextContent(ctx context.Context, teamID string) (*TeamContextContentResponse, error)
- func (c *RepoClient) GetTeamInfo(teamID string) (*TeamInfoResponse, error)
- func (c *RepoClient) GetVideoStatus(contextType, contextID, recordingID string) (*VideoStatusResponse, error)
- func (c *RepoClient) ImportVideoURL(contextType, contextID string, req *ImportVideoURLRequest) (*ImportVideoURLResponse, error)
- func (c *RepoClient) ListTeamInvites(ctx context.Context, teamRef string) ([]PendingInvite, error)
- func (c *RepoClient) ListVideos(contextType, contextID string, limit, offset int) (*ListVideosResponse, error)
- func (c *RepoClient) MergeRepo(repoID string, markers map[string]json.RawMessage) (*MergeRepoResponse, *RedirectInfo, error)
- func (c *RepoClient) NotifyImport(teamID string, metadata any) (recordingID string, err error)
- func (c *RepoClient) NotifyPlanActivity(teamID, planID string, n PlanActivityNotification) error
- func (c *RepoClient) NotifySessionAborted(n SessionAbortedNotification) error
- func (c *RepoClient) NotifySessionStarted(n SessionStartedNotification) error
- func (c *RepoClient) NotifySessionUploaded(n SessionUploadedNotification) ([]PRLinkMiss, error)
- func (c *RepoClient) NotifyUninstall(repoID, repoSalt string) error
- func (c *RepoClient) Query(req *QueryRequest) (*QueryResponse, error)
- func (c *RepoClient) RegisterRepo(req *RepoInitRequest) (*RepoInitResponse, error)
- func (c *RepoClient) RevokeTeamInvite(ctx context.Context, teamRef, inviteID string) error
- func (c *RepoClient) WithAuthToken(token string) *RepoClient
- func (c *RepoClient) WithTimeout(d time.Duration) *RepoClient
- type RepoDetailLedger
- type RepoDetailResponse
- type RepoDetailTeamContext
- type RepoFingerprint
- type RepoInfo
- type RepoInitRequest
- type RepoInitResponse
- type RepoMarkerData
- type RepoService
- type RepoUninstallRequest
- type ReposResponse
- type SessionAbortedNotification
- type SessionStartedNotification
- type SessionUploadedNotification
- type TeamContextContentResponse
- type TeamContextDoc
- type TeamInfoResponse
- type TeamMembership
- type VideoStatusResponse
Constants ¶
const ( RoleOwner = "owner" RoleAdmin = "admin" RoleMember = "member" )
Team roles. The server rejects anything outside this set with a 400 whose message is load-bearing ("role must be owner, admin, or member").
const ( KBScopeTypeUser = "user" KBScopeTypeTeam = "team" )
KB scope types. Every bubble is owned by exactly one scope: a single user or a single team (ADR-073). scope_id carries the matching usr_/team_ id.
const ( InviteBlockedPersonalTeam = "personal_team" InviteBlockedRole = "insufficient_role" )
Invite-capability reasons reported by the server.
const ( // HeaderMinVersion is returned by the server to indicate the minimum CLI version required HeaderMinVersion = "X-SageOx-Min-Version" // HeaderDeprecated is returned by the server to warn of upcoming deprecation HeaderDeprecated = "X-SageOx-Deprecated" )
const (
ContextTypeTeam = "team"
)
Recording context types. Recordings are conversation content and live in team context only — Knowledge Bubbles are curated syntheses and take no recordings (ox ADR-028; the /api/v1/kb/{kb_id}/recordings client path was removed under epic ox-nsf7). The contextType parameter survives on the client methods so call sites stay explicit about what they target.
const RedirectHeader = "X-SageOx-Merge"
RedirectHeader is the HTTP header name for merge/redirect information
Variables ¶
var ( // ErrInviteExists is HTTP 409: an active invite for this address already // exists on this team. The desired end state already holds. ErrInviteExists = errors.New("an active invite already exists for this email") // ErrInviteForbidden is HTTP 403: the server refused this operation. // // The CLI deliberately does NOT model who is allowed to invite, list, or // cancel. That policy lives on the server and can change — today any // active member may invite, tomorrow it could be owner/admin only — and a // client that hardcodes today's rule would confidently give wrong advice // the day it changes. Callers wrap this sentinel around the SERVER's own // message and show that, rather than inventing an explanation. ErrInviteForbidden = errors.New("not permitted") // ErrInviteNotAMember is HTTP 404 carrying a JSON error body. The server // deliberately answers 404 rather than 403 for a team the caller is not a // member of, so team existence cannot be probed. Preserve that ambiguity // when rendering: never claim the team does or does not exist. ErrInviteNotAMember = errors.New("no such team, or you are not a member of it") // ErrPersonalTeam is HTTP 409 with code personal_team_immutable: private // per-user teams are structurally single-member and take no invitations. ErrPersonalTeam = errors.New("personal teams are single-member and cannot take invitations") // ErrInviteUnsupported is a bare 404 with no JSON error body — the route // is not registered, i.e. the server predates CLI invitations. Distinct // from ErrInviteNotAMember, which is a 404 that DOES carry a JSON body. ErrInviteUnsupported = errors.New("this SageOx server does not support CLI invitations yet") )
Invite-specific sentinels. Callers branch on these with errors.Is to render a per-recipient outcome; every one of them is a normal, expected answer rather than a failure worth a stack trace.
var ErrForbidden = errors.New("access denied: you are not a member of this team — request an invite URL from a team admin")
ErrForbidden is returned when the API returns 403 Forbidden
var ErrInvalidTeamRef = errors.New("invalid team reference")
ErrInvalidTeamRef is a team reference that cannot be placed in a URL path safely. Only dot segments qualify: everything else is escaped and handed to the server, which is the authority on whether a team exists.
ErrKBAPIUnavailable is the sentinel returned when the KB endpoint is not available to the caller (HTTP 403/404 — feature flag off, non-member scope, or endpoint missing). Non-fatal by design: callers should inspect with errors.Is and treat it as "no bubbles for this caller/scope".
var ErrLedgerNotFound = errors.New("ledger not found")
ErrLedgerNotFound is returned when the ledger doesn't exist for the given repo.
var ErrReadOnly = errors.New("read-only access: you are a viewer on this public repo")
ErrReadOnly is returned when the user has viewer (read-only) access to a public repo
ErrTeamContextEndpointUnavailable is returned when the cloud team-context endpoint responds with 404. This is a sentinel — callers in ephemeral mode treat it as "fall through to whatever was already there" rather than a hard error, because the endpoint may not be deployed yet.
ErrUnauthorized is returned when the API returns 401 Unauthorized
var ErrVersionUnsupported = errors.New("CLI version no longer supported by server")
ErrVersionUnsupported is returned when the server indicates the CLI version is no longer supported
Functions ¶
func CheckVersionResponse ¶
CheckVersionResponse inspects HTTP response for version deprecation signals. Returns true if the CLI should abort due to unsupported version (HTTP 426). For successful responses, checks for soft deprecation warning header.
func DeriveSlug ¶ added in v0.3.0
DeriveSlug generates a kebab-case slug from a display name. Used as fallback when the server doesn't provide a slug.
func HandleRedirect ¶
func HandleRedirect(projectRoot string, info *RedirectInfo) error
HandleRedirect processes redirect info and updates local config/markers This is best-effort: returns nil on success or if nothing to do, and logs but does not fail on non-critical errors
func InviteForbiddenReason ¶ added in v0.13.0
InviteForbiddenReason returns the server's own explanation for a 403, or "" when it sent none — letting the caller fall back to something generic rather than inventing a policy claim.
func PrintDeprecationWarning ¶
func PrintDeprecationWarning(message string)
PrintDeprecationWarning displays a warning that the CLI version is deprecated Uses yellow color semantically indicating a non-blocking warning
func PrintUpgradeRequired ¶
func PrintUpgradeRequired(minVersion string)
PrintUpgradeRequired displays a message indicating the CLI version is no longer supported Uses red color semantically indicating a blocking error
func RenameRepoMarker ¶ added in v0.3.0
RenameRepoMarker renames the .repo_* marker file from old ID to new ID using VCS and updates the repo_id value inside the marker file
Types ¶
type CreateInviteRequest ¶ added in v0.13.0
CreateInviteRequest is the body of POST /api/v1/teams/{team_id}/invites.
Role is REQUIRED despite the server's OpenAPI document claiming it is optional with a "member" default: validateInviteRole rejects an empty string with a 400. Never send this struct with a blank Role.
type DistillObservation ¶ added in v0.3.0
type DistillObservation struct {
Content string `json:"content"`
RecordedAt string `json:"recorded_at"` // RFC3339
}
DistillObservation is a single observation in a distill request.
type DistillRequest ¶ added in v0.3.0
type DistillRequest struct {
Observations []DistillObservation `json:"observations"`
DateRange [2]string `json:"date_range"` // [start, end] RFC3339
}
DistillRequest is the request body for POST /api/v1/teams/<teamID>/memory/distill.
type DistillResponse ¶ added in v0.3.0
type DistillResponse struct {
Summary string `json:"summary"`
UpdatedAt string `json:"updated_at"`
}
DistillResponse is the response from POST /api/v1/teams/<teamID>/memory/distill.
type DoctorIssue ¶
type DoctorIssue struct {
Type string `json:"type"` // e.g., "merge_pending", "team_invite_pending"
Severity string `json:"severity"` // "error", "warning", "info"
Title string `json:"title"` // short display title
Description string `json:"description"` // detailed explanation, supports Markdown
ActionURL string `json:"action_url,omitempty"` // URL to resolve the issue
ActionLabel string `json:"action_label,omitempty"` // button text, e.g., "Resolve merge"
}
DoctorIssue represents a single diagnostic issue from the cloud Cloud doctor detects things the local CLI cannot: - Pending merge conflicts (same repo registered twice) - requires cross-repo knowledge - Team invites pending acceptance - lives in cloud DB - Guidance updates available - version comparison server-side - Billing/quota warnings - enterprise only - Team-wide health (X repos need updates) - aggregate view
type DoctorResponse ¶
type DoctorResponse struct {
Issues []DoctorIssue `json:"issues"`
CheckedAt string `json:"checked_at"` // RFC3339 timestamp
}
DoctorResponse represents the GET /api/v1/repo/{repo_id}/doctor response
type ForbiddenError ¶ added in v0.13.0
type ForbiddenError struct {
Reason string
}
ForbiddenError is a 403 that carries the server's own explanation.
The reason is held as a field rather than being formatted into the message and parsed back out: string round-tripping would break the moment the wrapping text changed, and silently — the caller would just start showing a generic sentence instead of the server's.
It satisfies errors.Is(err, ErrInviteForbidden) so existing callers that only care about the class keep working.
func (*ForbiddenError) Error ¶ added in v0.13.0
func (e *ForbiddenError) Error() string
func (*ForbiddenError) Is ¶ added in v0.13.0
func (e *ForbiddenError) Is(target error) bool
type ImportNotification ¶ added in v0.3.0
type ImportNotification struct {
TeamID string `json:"team_id"`
Metadata json.RawMessage `json:"metadata"`
}
ImportNotification is the POST /api/v1/teams/{team_id}/context/import request body. Imports target a team context (not a project repo), so team_id is the primary identifier. The Metadata field is passed as-is (json.RawMessage) to avoid coupling the API package to the docMeta struct in cmd/ox.
type ImportVideoURLRequest ¶ added in v0.6.0
type ImportVideoURLRequest struct {
URL string `json:"source_url"`
Title string `json:"title,omitempty"`
}
ImportVideoURLRequest represents the POST request to import a video by URL
type ImportVideoURLResponse ¶ added in v0.6.0
type ImportVideoURLResponse struct {
ImportID string `json:"import_id"`
RecordingID string `json:"recording_id"`
Status string `json:"status"`
Title string `json:"title,omitempty"`
}
ImportVideoURLResponse represents the response from importing a video URL. import_id and recording_id are the same value — a stable ID assigned upfront that can be used with --status immediately, before processing completes.
type InviteResponse ¶ added in v0.13.0
type InviteResponse struct {
ID string `json:"id"`
Email string `json:"email"`
TeamID string `json:"team_id"`
TeamName string `json:"team_name"`
Role string `json:"role"`
ExpiresAt string `json:"expires_at"`
}
InviteResponse is the 201 body.
It deliberately OMITS the server's `token` field. The server returns the plaintext invite token in-band so the web composer can offer a copy-link fallback; ox has no such need, and an invite token is a live credential. Not declaring the field is what structurally guarantees ox cannot print it, log it, or leak it into --json output — a guarantee a "remember not to print it" convention could not make.
type KB ¶ added in v0.8.0
type KB struct {
KBID string `json:"id"`
KBType KBType `json:"kb_type"`
Slug string `json:"slug"`
Name string `json:"name"`
OwnerUserID string `json:"owner_user_id,omitempty"`
LifecycleState string `json:"lifecycle_state,omitempty"` // "provisioning", "active", "provision-failed"
ViewerRole string `json:"viewer_role,omitempty"` // "admin", "member", "viewer" (single reads only)
CreatedAt string `json:"created_at,omitempty"` // RFC3339 timestamp
// ScopeType/ScopeID locate the bubble: "user"|"team" + the usr_/team_
// owner id (ADR-073). Immutable after creation.
ScopeType string `json:"scope_type,omitempty"`
ScopeID string `json:"scope_id,omitempty"`
// Manager is the bubble admin — the single human in charge (a label,
// not an ACL; ADR-073 §2). Same value as owner_user_id today.
Manager string `json:"manager,omitempty"`
// Description is the bubble's free-text description.
Description string `json:"description,omitempty"`
// Steering is the free-text curator-steering value (ADR-097 C9).
// Unset ⇒ the bubble opted out of curator routing.
Steering string `json:"steering,omitempty"`
// Topics is the declared topic list (server sends [] when none).
Topics []string `json:"topics,omitempty"`
// GitPath is the host-relative git project path (e.g. "kb/kb_xxx").
// Combine with the endpoint's git host to build a clone URL; empty
// until the bubble's repo is provisioned.
GitPath string `json:"git_path,omitempty"`
// DefaultBranch is the bubble repo's default branch (almost always "main").
DefaultBranch string `json:"default_branch,omitempty"`
// LastActivityAt is GitLab's project last_activity_at — the only
// activity signal that reflects out-of-band pushes. RFC3339.
LastActivityAt string `json:"last_activity_at,omitempty"`
// RepoURL is a full git clone URL when the server supplies one
// (older response shapes). Prefer GitPath + endpoint-derived host.
RepoURL string `json:"repo_url,omitempty"`
// RepoID scopes a kb_type=repo bubble to a specific project. When set,
// the per-project symlink reconciler only links this bubble into the
// project whose ProjectConfig.RepoID matches.
RepoID string `json:"repo_id,omitempty"`
}
KB represents a knowledge bubble row from GET /api/v1/kb (list) or GET /api/v1/kb/{id} (detail). Field set tracks the sageox-mono KBResponse schema; new server fields can be added without breaking older clients because the JSON decoder ignores unknown keys by default.
Note ViewerRole: the server omits it from LIST responses (role is per-KB but the list is scope-wide); it is populated on single-bubble reads.
func (*KB) UnmarshalJSON ¶ added in v0.13.0
UnmarshalJSON accepts both the current server key ("id") and the older "kb_id" alias so fixtures and any transitional response shape decode to the same struct. All other fields use the standard decoder.
type KBClient ¶ added in v0.8.0
type KBClient struct {
// contains filtered or unexported fields
}
KBClient handles API communication with the SageOx kb endpoints. Mirrors the construction style of RepoClient (see repo.go).
func NewKBClient ¶ added in v0.8.0
func NewKBClient() *KBClient
NewKBClient creates a kb API client using the global default endpoint. Prefer NewKBClientForProject when called from a repo context so the project-configured endpoint is honored.
func NewKBClientForProject ¶ added in v0.8.0
NewKBClientForProject creates a kb API client using the endpoint resolved from project config (env var > project config > default), matching the canonical helper used elsewhere in the codebase.
func NewKBClientWithEndpoint ¶ added in v0.8.0
NewKBClientWithEndpoint creates a kb API client with an explicit base URL. Used by tests and code paths that already have the endpoint resolved.
func (*KBClient) Endpoint ¶ added in v0.8.0
Endpoint returns the base URL this client is configured for.
func (*KBClient) GetBubble ¶ added in v0.8.0
GetBubble calls GET /api/v1/kb/{id} for a single bubble by kb_id. 403/404 → sentinel. Slug resolution goes through ResolveSlug.
func (*KBClient) ListBubbles ¶ added in v0.8.0
ListBubbles calls GET /api/v1/kb?scope_type=&scope_id= to list one scope's bubbles. The scope is REQUIRED — the server 400s a bare request and 403s a non-member scope (which maps to ErrKBAPIUnavailable like a flag-off 404, since both mean "no bubbles visible here for this caller").
func (*KBClient) ResolveSlug ¶ added in v0.13.0
ResolveSlug calls GET /api/v1/kb/resolve to map a scoped slug to its kb_id, following server-side rename aliases. Members-only: not-found and no-access both surface as ErrKBAPIUnavailable (the server deliberately returns an identical 404 for both so slugs cannot be enumerated).
func (*KBClient) WithAuthToken ¶ added in v0.8.0
WithAuthToken sets the bearer token for authenticated requests and returns the client for fluent chaining.
type KBScope ¶ added in v0.13.0
type KBScope struct {
Type string // KBScopeTypeUser | KBScopeTypeTeam
ID string // usr_… | team_…
}
KBScope identifies one listable context.
type KBType ¶ added in v0.8.0
type KBType string
KBType matches the sageox-mono KBType enum. Six known kinds plus a client-side "unknown" fallback bucket for forward compatibility when the server rolls out a new type before the CLI knows about it.
const ( KBTypePersonal KBType = "personal" KBTypeProfile KBType = "profile" KBTypeTeam KBType = "team" KBTypeRepo KBType = "repo" KBTypeCustom KBType = "custom" KBTypeChannel KBType = "channel" // KBTypeUnknown is the client-side fallback bucket when the server // returns a kb_type the CLI doesn't recognize. Never sent by the server. KBTypeUnknown KBType = "unknown" )
type LedgerStatusResponse ¶
type LedgerStatusResponse struct {
Status string `json:"status"` // "ready", "pending", "error"
RepoURL string `json:"repo_url"` // git clone URL (empty if not ready)
RepoID int `json:"repo_id"` // GitLab project ID (internal use)
CreatedAt string `json:"created_at"` // RFC3339 timestamp
Message string `json:"message,omitempty"` // optional status message
Visibility string `json:"visibility,omitempty"` // "public" or "private" (new field, may be empty on older servers)
AccessLevel string `json:"access_level,omitempty"` // "member" or "viewer" (new field, may be empty on older servers)
}
LedgerStatusResponse represents the GET /api/v1/repos/{repo_id}/ledger-status response.
func (*LedgerStatusResponse) IsReadOnly ¶
func (r *LedgerStatusResponse) IsReadOnly() bool
IsReadOnly returns true if the user has viewer (read-only) access.
type ListVideosResponse ¶ added in v0.6.0
type ListVideosResponse struct {
Recordings []RecordingListItem `json:"recordings"`
Pagination PaginationResponse `json:"pagination"`
}
ListVideosResponse represents the paginated list of recordings
type MergeRepoRequest ¶ added in v0.3.0
type MergeRepoRequest struct {
RepoMarkers map[string]json.RawMessage `json:"repo_markers"` // filename -> marker JSON
}
MergeRepoRequest represents POST /api/v1/repo/{repo_id}/merge
type MergeRepoResponse ¶ added in v0.3.0
type MergeRepoResponse struct {
Canonical string `json:"canonical_repo_id"` // the winning repo_id
Merged []string `json:"merged_repo_ids"` // repo_ids that were marked as merged
Redirect *RedirectInfo `json:"redirect,omitempty"` // redirect info (also in header)
}
MergeRepoResponse represents the merge API response
type MockRepoService ¶ added in v0.6.0
type MockRepoService struct {
RegisterRepoFunc func(req *RepoInitRequest) (*RepoInitResponse, error)
GetDoctorIssuesFunc func(repoID string) (*DoctorResponse, error)
NotifyUninstallFunc func(repoID, repoSalt string) error
NotifyImportFunc func(teamID string, metadata any) (string, error)
MergeRepoFunc func(repoID string, markers map[string]json.RawMessage) (*MergeRepoResponse, *RedirectInfo, error)
EndpointFunc func() string
WithAuthTokenFunc func(token string) *RepoClient
}
MockRepoService implements RepoService with configurable function fields for testing.
func (*MockRepoService) Endpoint ¶ added in v0.6.0
func (m *MockRepoService) Endpoint() string
func (*MockRepoService) GetDoctorIssues ¶ added in v0.6.0
func (m *MockRepoService) GetDoctorIssues(repoID string) (*DoctorResponse, error)
func (*MockRepoService) MergeRepo ¶ added in v0.6.0
func (m *MockRepoService) MergeRepo(repoID string, markers map[string]json.RawMessage) (*MergeRepoResponse, *RedirectInfo, error)
func (*MockRepoService) NotifyImport ¶ added in v0.6.0
func (m *MockRepoService) NotifyImport(teamID string, metadata any) (string, error)
func (*MockRepoService) NotifyUninstall ¶ added in v0.6.0
func (m *MockRepoService) NotifyUninstall(repoID, repoSalt string) error
func (*MockRepoService) RegisterRepo ¶ added in v0.6.0
func (m *MockRepoService) RegisterRepo(req *RepoInitRequest) (*RepoInitResponse, error)
func (*MockRepoService) WithAuthToken ¶ added in v0.6.0
func (m *MockRepoService) WithAuthToken(token string) *RepoClient
type PRLinkMiss ¶ added in v0.12.0
PRLinkMiss is one linked PR whose body is missing the SageOx-Session trailer, as detected server-side (GitHub App) in response to the uploaded notification. The CLI surfaces each as a repair task in session-stop guidance — the agent fixes the PR with its own tooling; ox never mutates PR bodies and never requires gh on the machine.
type PaginationResponse ¶ added in v0.6.0
type PaginationResponse struct {
Total int `json:"total"`
Limit int `json:"limit"`
Offset int `json:"offset"`
HasMore bool `json:"has_more"`
}
PaginationResponse contains pagination metadata for list endpoints
type PendingInvite ¶ added in v0.13.0
type PendingInvite struct {
ID string `json:"id"`
Email string `json:"email"`
Role string `json:"role"`
InviterName string `json:"inviter_name"`
InvitedAt string `json:"invited_at"`
ExpiresAt string `json:"expires_at"`
Status string `json:"status"`
}
PendingInvite is one row of GET /api/v1/teams/{team_id}/invites.
The list endpoint never returns tokens (the server builds these responses with includeToken=false), so unlike the create path there is nothing sensitive to withhold here.
type PlanActivityNotification ¶ added in v0.13.0
type PlanActivityNotification struct {
Event string `json:"event"` // plan.EventKind value (approved/worked/realized/abandoned/superseded)
Status string `json:"status,omitempty"` // plan.PlanStatus, when the event carries one
}
PlanActivityNotification is the POST /api/v1/teams/{team_id}/plans/{plan_id}/activity request body — the client half of the caller-driven plan_id -> plan index (bead sageox-gqgkg). Deliberately minimal (a stub): the server currently accepts and drops it until a future change actually builds the index from it.
type QueryLatency ¶ added in v0.3.0
type QueryLatency struct {
Embed int64 `json:"embed"`
Search int64 `json:"search"`
Total int64 `json:"total"`
}
QueryLatency tracks latency of sub-operations.
type QueryRequest ¶ added in v0.3.0
type QueryRequest struct {
Query string `json:"query"`
Mode string `json:"mode,omitempty"` // "hybrid", "knn", "bm25" (default: hybrid)
K int `json:"k,omitempty"` // number of results (default: 10, max: 100)
Teams []string `json:"teams"` // team IDs to search team-context indexes
Repos []string `json:"repos"` // repo IDs to search ledger indexes
AgentID string `json:"agent_id,omitempty"` // querying agent instance (e.g. "Oxa7b3")
AgentType string `json:"agent_type,omitempty"` // querying agent type (e.g. "claude-code")
}
QueryRequest represents the POST /api/v1/query request body.
type QueryResponse ¶ added in v0.3.0
type QueryResponse struct {
Results []QueryResult `json:"results"`
LatencyMs QueryLatency `json:"latency_ms"`
}
QueryResponse represents the POST /api/v1/query response.
type QueryResult ¶ added in v0.3.0
type QueryResult struct {
Score float64 `json:"score"`
Text string `json:"text"`
DocType string `json:"doc_type"`
FilePath string `json:"file_path"`
SourceType string `json:"source_type"`
SourceID string `json:"source_id"`
CreatedAt string `json:"created_at,omitempty"`
HasVisual bool `json:"has_visual,omitempty"` // true if discussion has keyframe visual content
VisualTypes []string `json:"visual_types,omitempty"` // content types (e.g. "diagram", "code") when has_visual is true
}
QueryResult is a single search result.
type RecordingListItem ¶ added in v0.6.0
type RecordingListItem struct {
ID string `json:"id"`
Title string `json:"title"`
Status string `json:"status"`
MimeType string `json:"mime_type,omitempty"`
Duration *float64 `json:"duration,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
RecordingListItem represents a single recording in a list response
type RedirectConfig ¶
type RedirectConfig struct {
RepoID string `json:"repo_id,omitempty"`
TeamID string `json:"team_id,omitempty"`
}
RedirectConfig contains the new config values to apply
type RedirectInfo ¶
type RedirectInfo struct {
Repo *RedirectMapping `json:"repo,omitempty"`
Team *RedirectMapping `json:"team,omitempty"`
Config *RedirectConfig `json:"config,omitempty"`
}
RedirectInfo contains redirect information from the server when repos or teams have been merged
func ParseRedirectHeader ¶
func ParseRedirectHeader(header http.Header) *RedirectInfo
ParseRedirectHeader parses X-Sageox-Redirect header if present Returns nil if header is not present or cannot be parsed
type RedirectMapping ¶
RedirectMapping represents a from -> to ID mapping
type RepoClient ¶
type RepoClient struct {
// contains filtered or unexported fields
}
RepoClient handles API communication with the SageOx repo endpoints
func NewRepoClient ¶
func NewRepoClient() *RepoClient
NewRepoClient creates a new repo API client using the global default endpoint.
CAUTION: This should RARELY be used. It uses endpoint.Get() which ignores project config, so it will use the wrong endpoint for repos configured with non-default endpoints (e.g., enterprise or test environments).
Use NewRepoClientForProject(gitRoot) instead for operations within a repo context. Use NewRepoClientWithEndpoint(endpoint) when you have the endpoint explicitly.
func NewRepoClientForProject ¶
func NewRepoClientForProject(gitRoot string) *RepoClient
NewRepoClientForProject creates a new repo API client using the endpoint from project config. This is the recommended way to create a client for repo-bound operations. It checks: SAGEOX_ENDPOINT env var > project config > default endpoint.
func NewRepoClientWithEndpoint ¶
func NewRepoClientWithEndpoint(baseURL string) *RepoClient
NewRepoClientWithEndpoint creates a new repo API client with a specific endpoint. Use this when you already have the endpoint URL (e.g., from auth flow or config).
func (*RepoClient) CreateTeamInvite ¶ added in v0.13.0
func (c *RepoClient) CreateTeamInvite(ctx context.Context, teamRef string, req CreateInviteRequest) (*InviteResponse, error)
CreateTeamInvite sends one invitation and returns the created invite.
teamRef may be a team_id or a slug. One address per call — the server has no bulk form; callers invite several people by calling this repeatedly.
A nil error means the invite row was created, NOT that an email was delivered: the server dispatches the mail asynchronously and a send failure never fails the request.
func (*RepoClient) DistillMemory ¶ added in v0.3.0
func (c *RepoClient) DistillMemory(teamID string, req *DistillRequest) (*DistillResponse, error)
DistillMemory calls POST /api/v1/teams/<teamID>/memory/distill to run server-side LLM distillation of accumulated observations.
func (*RepoClient) Endpoint ¶
func (c *RepoClient) Endpoint() string
Endpoint returns the base URL this client is configured for
func (*RepoClient) GetCLISettings ¶ added in v0.6.2
func (c *RepoClient) GetCLISettings() (json.RawMessage, error)
GetCLISettings calls GET /api/v1/cli/settings to fetch server-evaluated feature flags. The server evaluates PostHog feature flags server-side (device_id + user_id) and returns pre-evaluated booleans. Requires authentication. Returns flags.CLISettingsResponse.
Called by the daemon on a background interval; the CLI reads the cached result from disk.
func (*RepoClient) GetDoctorIssues ¶
func (c *RepoClient) GetDoctorIssues(repoID string) (*DoctorResponse, error)
GetDoctorIssues calls GET /api/v1/repo/{repo_id}/doctor for cloud diagnostics Returns nil, nil if API unavailable (graceful degradation for offline mode)
Path probe order (ox-alh): try the authenticated path first; fall back to the legacy unauthenticated path only on 404 so the CLI keeps working against older servers that haven't shipped the auth move yet. Once every production endpoint has the authed path, the legacy fallback can be removed.
func (*RepoClient) GetLedgerStatus ¶
func (c *RepoClient) GetLedgerStatus(repoID string) (*LedgerStatusResponse, error)
GetLedgerStatus fetches ledger provisioning status from the cloud API.
Response status values:
- "ready": Ledger is provisioned and RepoURL is available for cloning
- "pending": Ledger is being provisioned, caller should retry later
- "error": Provisioning failed, check Message for details
The repoID parameter is the SageOx repo identifier (UUID) from project config. The returned RepoID is the GitLab project ID (used internally by server).
Returns ErrLedgerNotFound if no ledger exists for this repo. Returns ErrUnauthorized if authentication fails.
func (*RepoClient) GetRepoDetail ¶
func (c *RepoClient) GetRepoDetail(repoID string) (*RepoDetailResponse, error)
GetRepoDetail calls GET /api/v1/cli/repos/{repo_id} to fetch repo detail. Returns visibility, access level, ledger status, and accessible team contexts. Works for both members (full access) and non-members on public repos (viewer access).
Returns ErrForbidden if the user is not a member and the repo is private. Returns ErrUnauthorized if authentication fails. Returns nil, nil if the endpoint returns 404 (server hasn't implemented this endpoint yet).
func (*RepoClient) GetRepos ¶
func (c *RepoClient) GetRepos() (*ReposResponse, error)
GetRepos calls GET /api/v1/cli/repos to fetch user's team context repos. This is user-scoped and returns all team contexts the user has access to. For ledger URLs, use GetLedgerStatus() which is project-scoped. Requires authentication. Returns PAT, repo URLs, and token expiration.
func (*RepoClient) GetTeamContextContent ¶ added in v0.9.0
func (c *RepoClient) GetTeamContextContent(ctx context.Context, teamID string) (*TeamContextContentResponse, error)
GetTeamContextContent fetches the full team context for teamID over HTTP.
This is the ephemeral-mode fallback for environments where the daemon cannot keep a local git clone of the team-context repo in sync. The caller is responsible for writing the returned content to disk under paths.TeamContextDir(teamID, endpoint).
Returns ErrTeamContextEndpointUnavailable on 404 (endpoint not deployed or no team context). Returns ErrUnauthorized on 401, ErrForbidden on 403.
func (*RepoClient) GetTeamInfo ¶
func (c *RepoClient) GetTeamInfo(teamID string) (*TeamInfoResponse, error)
GetTeamInfo calls GET /api/v1/teams/{id} to fetch team information including the team context repo URL and credentials. Requires authentication. Returns nil, nil if team not found (404).
func (*RepoClient) GetVideoStatus ¶ added in v0.6.0
func (c *RepoClient) GetVideoStatus(contextType, contextID, recordingID string) (*VideoStatusResponse, error)
GetVideoStatus calls GET /api/v1/{teams|kb}/{id}/recordings/{recording_id} Returns nil, nil on 404 (graceful degradation); all other errors are returned.
func (*RepoClient) ImportVideoURL ¶ added in v0.6.0
func (c *RepoClient) ImportVideoURL(contextType, contextID string, req *ImportVideoURLRequest) (*ImportVideoURLResponse, error)
ImportVideoURL calls POST /api/v1/{teams|kb}/{id}/recordings/import/url Returns nil, nil if the endpoint returns 404 (graceful degradation)
func (*RepoClient) ListTeamInvites ¶ added in v0.13.0
func (c *RepoClient) ListTeamInvites(ctx context.Context, teamRef string) ([]PendingInvite, error)
ListTeamInvites returns the team's invitations that are still outstanding — not yet accepted, not revoked, not expired.
Whether the caller is allowed to see them is the server's decision; a refusal comes back as ErrInviteForbidden carrying the server's own reason.
func (*RepoClient) ListVideos ¶ added in v0.6.0
func (c *RepoClient) ListVideos(contextType, contextID string, limit, offset int) (*ListVideosResponse, error)
ListVideos calls GET /api/v1/{teams|kb}/{id}/recordings with pagination Returns nil, nil on 404 (graceful degradation)
func (*RepoClient) MergeRepo ¶ added in v0.3.0
func (c *RepoClient) MergeRepo(repoID string, markers map[string]json.RawMessage) (*MergeRepoResponse, *RedirectInfo, error)
MergeRepo calls POST /api/v1/repo/{repo_id}/merge to notify the server about duplicate registration resolution. This is best-effort for server-side visibility and bookkeeping — the local cleanup is authoritative. Gracefully handles 404 (endpoint not yet deployed) by returning nil, nil, nil.
func (*RepoClient) NotifyImport ¶ added in v0.3.0
func (c *RepoClient) NotifyImport(teamID string, metadata any) (recordingID string, err error)
NotifyImport sends a fire-and-forget notification about a new document import. Imports target a team context, so teamID identifies where the document lives. The metadata argument should be JSON-marshalable (typically the docMeta struct).
On 2xx the server may return a recording ID for media files it routes to transcription; that ID is returned so callers can poll `ox import --status`. The endpoint is fire-and-forget — a missing/empty body and network errors are not failures: recordingID is "" and err is nil. Only a non-404 4xx/5xx is an error, and even then it never invalidates the already-committed import.
func (*RepoClient) NotifyPlanActivity ¶ added in v0.13.0
func (c *RepoClient) NotifyPlanActivity(teamID, planID string, n PlanActivityNotification) error
NotifyPlanActivity best-effort-reports one appended plan lifecycle event to the server's caller-driven plan index (bead sageox-gqgkg). Callers treat this as strictly fire-and-forget, matching NotifySessionStarted/Aborted: any error here is advisory only and must never affect the local events.jsonl append that already succeeded. Not built on postSessionSignal because this path substitutes two ids (team_id, plan_id), not one.
func (*RepoClient) NotifySessionAborted ¶ added in v0.12.0
func (c *RepoClient) NotifySessionAborted(n SessionAbortedNotification) error
NotifySessionAborted marks a registered recording as discarded. Callers treat this as strictly fire-and-forget.
func (*RepoClient) NotifySessionStarted ¶ added in v0.12.0
func (c *RepoClient) NotifySessionStarted(n SessionStartedNotification) error
NotifySessionStarted registers a just-started recording so /c/<session_id> resolves immediately. Callers treat this as strictly fire-and-forget.
func (*RepoClient) NotifySessionUploaded ¶ added in v0.9.0
func (c *RepoClient) NotifySessionUploaded(n SessionUploadedNotification) ([]PRLinkMiss, error)
NotifySessionUploaded tells the SageOx server that a session's content has been uploaded and is viewable, so the (v2) GitHub App reconciler can refresh any PR sticky comment. The response may carry pr_link_misses — linked PRs whose bodies lack the SageOx-Session trailer — which the caller surfaces as agent repair tasks. An empty or non-JSON body is normal (older servers) and yields no misses.
func (*RepoClient) NotifyUninstall ¶
func (c *RepoClient) NotifyUninstall(repoID, repoSalt string) error
NotifyUninstall calls POST /api/v1/repo/{repo_id}/uninstall to notify server of local uninstall. Requires authentication - the server validates the user is a team member with permission to trigger uninstallation workflows. Returns errors so callers can provide user feedback. The repo_salt (first commit hash) provides additional verification.
func (*RepoClient) Query ¶ added in v0.3.0
func (c *RepoClient) Query(req *QueryRequest) (*QueryResponse, error)
Query calls POST /api/v1/query to perform semantic search over team context and ledger data. Requires authentication. Returns search results with relevance scores.
func (*RepoClient) RegisterRepo ¶
func (c *RepoClient) RegisterRepo(req *RepoInitRequest) (*RepoInitResponse, error)
RegisterRepo calls POST /api/v1/repo/init Returns (response, error) - error is nil if call succeeds (even for 4xx/5xx) Gracefully handles 404 (endpoint not yet deployed) by returning nil, nil
func (*RepoClient) RevokeTeamInvite ¶ added in v0.13.0
func (c *RepoClient) RevokeTeamInvite(ctx context.Context, teamRef, inviteID string) error
RevokeTeamInvite cancels a single pending invitation by its id — the id shown by ListTeamInvites, not the invite token. Answers 204 with no body.
func (*RepoClient) WithAuthToken ¶
func (c *RepoClient) WithAuthToken(token string) *RepoClient
WithAuthToken sets the auth token for authenticated requests
func (*RepoClient) WithTimeout ¶ added in v0.13.0
func (c *RepoClient) WithTimeout(d time.Duration) *RepoClient
WithTimeout overrides the default 10s HTTP timeout. Use it for advisory, fire-and-forget notifications that sit on a path a human or agent is waiting on — 10s of stall to deliver a best-effort hint is a worse outcome than not delivering it.
type RepoDetailLedger ¶
type RepoDetailLedger struct {
Status string `json:"status"` // "ready", "pending", "error"
RepoURL string `json:"repo_url"` // git clone URL (empty if not ready)
Message string `json:"message,omitempty"` // status message for pending/error
}
RepoDetailLedger is the ledger section of the repo detail response.
type RepoDetailResponse ¶
type RepoDetailResponse struct {
Visibility string `json:"visibility"` // "public" or "private"
AccessLevel string `json:"access_level"` // "member" or "viewer"
Ledger *RepoDetailLedger `json:"ledger"` // null if not provisioned
TeamContexts []RepoDetailTeamContext `json:"team_contexts"` // empty if none accessible
}
RepoDetailResponse represents GET /api/v1/cli/repos/{repo_id}. Returns repo visibility, user access level, ledger status, and accessible team contexts. Works for both members and non-members on public repos.
func (*RepoDetailResponse) IsReadOnly ¶
func (r *RepoDetailResponse) IsReadOnly() bool
IsReadOnly returns true if the user has viewer (read-only) access.
type RepoDetailTeamContext ¶
type RepoDetailTeamContext struct {
TeamID string `json:"team_id"` // team_xxx
Name string `json:"name"` // display name
Slug string `json:"slug,omitempty"` // kebab-case team slug
Visibility string `json:"visibility"` // "public" or "private"
AccessLevel string `json:"access_level"` // "member" or "viewer"
RepoURL string `json:"repo_url"` // git clone URL
}
RepoDetailTeamContext is a team context in the repo detail response.
func (RepoDetailTeamContext) StableID ¶
func (r RepoDetailTeamContext) StableID() string
StableID returns the stable team identifier (team_xxx) for path construction and lookups.
type RepoFingerprint ¶
type RepoFingerprint struct {
// FirstCommit is the hash of the initial commit (same as repo_salt).
FirstCommit string `json:"first_commit"`
// MonthlyCheckpoints maps "YYYY-MM" to the first commit hash of that month.
MonthlyCheckpoints map[string]string `json:"monthly_checkpoints"`
// AncestrySamples contains commit hashes at power-of-2 intervals.
AncestrySamples []string `json:"ancestry_samples"`
// RemoteHashes contains salted SHA256 hashes of normalized remote URLs.
RemoteHashes []string `json:"remote_hashes,omitempty"`
}
RepoFingerprint holds repository identity fingerprint data for detecting identical or related repositories across teams. Enables the API to suggest team merges when multiple teams are working on the same codebase.
type RepoInfo ¶
type RepoInfo struct {
Name string `json:"name"` // e.g., "acme-corp-team-context"
URL string `json:"url"` // git clone URL
Type string `json:"type"` // "team-context" (ledgers use separate API)
TeamID string `json:"team_id,omitempty"` // team_xxx (present for team-context repos)
Slug string `json:"slug,omitempty"` // kebab-case team slug (server-provided)
}
RepoInfo represents a single git repository from the server. NOTE: This API only returns team context repos, not ledgers. Use GetLedgerStatus() for ledger URLs (project-scoped).
type RepoInitRequest ¶
type RepoInitRequest struct {
RepoID string `json:"repo_id"` // Required: prefixed UUIDv7
Type string `json:"type"` // Required: "git" or "svn"
InitAt string `json:"init_at"` // Required: RFC3339 timestamp
Name string `json:"name,omitempty"` // Optional: display name (e.g. "sageox/ox")
Teams []string `json:"teams,omitempty"` // Optional: team IDs to associate repo with
RepoSalt string `json:"repo_salt,omitempty"` // Optional: initial commit hash
RepoRemoteHashes []string `json:"repo_remote_hashes,omitempty"` // Optional: salted hashes
Fingerprint *RepoFingerprint `json:"fingerprint,omitempty"` // Optional: repo identity fingerprint
Identities any `json:"identities,omitempty"` // Optional: resolved user identities (identity.ResolvedIdentities)
IsPublic bool `json:"is_public,omitempty"` // Optional: prevents fork merging
CreatedByEmail string `json:"created_by_email,omitempty"` // Optional: git user email (backward compat)
CreatedByName string `json:"created_by_name,omitempty"` // Optional: git user name (backward compat)
}
RepoInitRequest represents the POST /api/v1/repo/init request
type RepoInitResponse ¶
type RepoInitResponse struct {
RepoID string `json:"repo_id"`
TeamID string `json:"team_id"`
WebBaseURL string `json:"web_base_url,omitempty"` // web dashboard base URL (for enterprise endpoints)
ExistingRepoID string `json:"existing_repo_id,omitempty"` // set when dedup matched a different repo_id
DuplicateWarning string `json:"duplicate_warning,omitempty"` // human-readable warning for CLI display
}
RepoInitResponse represents the POST /api/v1/repo/init response
type RepoMarkerData ¶
type RepoMarkerData struct {
RepoID string `json:"repo_id"`
RepoSalt string `json:"repo_salt"`
Endpoint string `json:"endpoint"`
}
RepoMarkerData holds parsed data from a .repo_* marker file
func ReadFirstRepoMarker ¶
func ReadFirstRepoMarker(sageoxDir string) (*RepoMarkerData, error)
ReadFirstRepoMarker reads the first .repo_* marker file found in the sageox directory. Returns the parsed marker data or nil if no marker found. This is useful for getting repo_id and repo_salt before uninstall.
type RepoService ¶ added in v0.6.0
type RepoService interface {
RegisterRepo(req *RepoInitRequest) (*RepoInitResponse, error)
GetDoctorIssues(repoID string) (*DoctorResponse, error)
NotifyUninstall(repoID, repoSalt string) error
NotifyImport(teamID string, metadata any) (recordingID string, err error)
MergeRepo(repoID string, markers map[string]json.RawMessage) (*MergeRepoResponse, *RedirectInfo, error)
Endpoint() string
WithAuthToken(token string) *RepoClient
}
RepoService abstracts the SageOx repo API for testability.
type RepoUninstallRequest ¶
type RepoUninstallRequest struct {
RepoSalt string `json:"repo_salt"` // first commit hash for authentication
}
RepoUninstallRequest represents the POST /api/v1/repo/{repo_id}/uninstall request
type ReposResponse ¶
type ReposResponse struct {
Token string `json:"token"` // PAT for git operations
ServerURL string `json:"server_url"` // GitLab server URL
Username string `json:"username"` // GitLab username
ExpiresAt time.Time `json:"expires_at"` // Token expiration
Repos map[string]RepoInfo `json:"repos"` // Repos indexed by name
Teams []TeamMembership `json:"teams"` // User's team memberships
}
ReposResponse represents the GET /api/v1/cli/repos response. This API returns team context repos only (user-scoped). Ledger URLs are fetched separately via GET /api/v1/repos/{repo_id}/ledger-status (project-scoped).
func (*ReposResponse) TeamMembershipsFromRepos ¶
func (r *ReposResponse) TeamMembershipsFromRepos() []TeamMembership
TeamMembershipsFromRepos derives team memberships from the repos map. Each repo with type "team-context" represents a team the user belongs to. Falls back to the Teams array if populated.
type SessionAbortedNotification ¶ added in v0.12.0
type SessionAbortedNotification struct {
SessionID string `json:"session_id"`
RepoID string `json:"repo_id,omitempty"`
}
SessionAbortedNotification is the POST /api/v1/sessions/{session_id}/aborted request body. Flips a registered "in progress" page to "discarded" and lets the server drop any pending PR-link repair tasks for the session. Best-effort: the server also ages out stale registered-never-uploaded sessions on its own.
type SessionStartedNotification ¶ added in v0.12.0
type SessionStartedNotification struct {
SessionID string `json:"session_id"`
RepoID string `json:"repo_id"`
SessionName string `json:"session_name,omitempty"`
AgentID string `json:"agent_id,omitempty"`
Branch string `json:"branch,omitempty"`
StartedAt string `json:"started_at,omitempty"` // RFC3339
}
SessionStartedNotification is the POST /api/v1/sessions/{session_id}/started request body. Register-at-start: lets the universal conversation link (/c/<session_id>) resolve to a live "in progress" page from the moment a recording begins instead of only after stop+upload. Strictly fire-and-forget — the uploaded notification remains the authoritative signal.
type SessionUploadedNotification ¶ added in v0.9.0
type SessionUploadedNotification struct {
SessionID string `json:"session_id"`
RepoID string `json:"repo_id"`
SessionName string `json:"session_name,omitempty"` // ledger dir name — lets the server bind name↔id without waiting for ledger ingest
SessionURL string `json:"session_url,omitempty"`
LinkedPRs []string `json:"linked_prs,omitempty"`
LinkedIssues []string `json:"linked_issues,omitempty"`
ProducedCommits []string `json:"produced_commits,omitempty"`
}
SessionUploadedNotification is the POST /api/v1/sessions/{session_id}/uploaded request body. Tells the server a session's content has landed in the ledger and is viewable, so the (v2) GitHub App reconciler can refresh any PR sticky comment. See docs/specs/session-pr-issue-linkage.md (v1.5).
type TeamContextContentResponse ¶ added in v0.9.0
type TeamContextContentResponse struct {
TeamID string `json:"team_id"`
TeamName string `json:"team_name"`
Docs []TeamContextDoc `json:"docs"`
AgentsMD string `json:"agents_md"`
ClaudeMD string `json:"claude_md"`
Memory string `json:"memory"`
}
TeamContextContentResponse is the JSON payload returned by GET /api/v1/teams/{team_id}/context.
type TeamContextDoc ¶ added in v0.9.0
type TeamContextDoc struct {
Name string `json:"name"`
Title string `json:"title"`
Content string `json:"content"`
}
TeamContextDoc is a single team-context document fetched over HTTP. Name is a relative path under the team-context root (may include directory separators, e.g. "guides/architecture.md").
type TeamInfoResponse ¶
type TeamInfoResponse struct {
ID string `json:"id"` // team ID (team_xxx)
Name string `json:"name"` // display name
Slug string `json:"slug,omitempty"` // URL-friendly name
RepoURL string `json:"repo_url,omitempty"` // team context git repo URL
GitToken string `json:"git_token,omitempty"` // token for git operations
}
TeamInfoResponse represents the GET /api/v1/teams/{id} response
type TeamMembership ¶
type TeamMembership struct {
ID string `json:"id"` // team_xxx
Name string `json:"name"` // display name
Slug string `json:"slug,omitempty"` // kebab-case team slug
Role string `json:"role"` // "owner", "admin", "member"
// Personal marks a private per-user team. These are structurally
// single-member and can never receive invitations.
Personal bool `json:"personal,omitempty"`
// CanInvite is the SERVER's answer to "may this user invite anyone to this
// team right now". The CLI must not re-derive it from Role: invite policy
// lives on the server and can change, and a locally-computed answer would
// be confidently wrong the day it does.
//
// Older servers omit the field, which decodes as false. Treat "false with
// no reason given" as unknown rather than as a refusal — see
// InviteCapabilityKnown.
CanInvite bool `json:"can_invite,omitempty"`
// InviteBlockedReason explains a false CanInvite: "personal_team" or
// "insufficient_role". Empty when CanInvite is true, and also empty on
// servers that predate this field.
InviteBlockedReason string `json:"invite_blocked_reason,omitempty"`
}
TeamMembership represents a team the user belongs to
func (TeamMembership) InviteCapabilityKnown ¶ added in v0.13.0
func (t TeamMembership) InviteCapabilityKnown() bool
InviteCapabilityKnown reports whether the server actually told us about this team's invite capability.
A server that predates the field sends neither can_invite nor a reason, which is indistinguishable from "refused" if read naively. Callers use this to stay quiet instead of wrongly announcing that a team cannot be invited to.
type VideoStatusResponse ¶ added in v0.6.0
type VideoStatusResponse struct {
ID string `json:"id"`
Title string `json:"title"`
Status string `json:"status"`
MimeType string `json:"mime_type,omitempty"`
Duration *float64 `json:"duration,omitempty"`
ProcessingSteps map[string]map[string]any `json:"processing_steps,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
}
VideoStatusResponse represents the status of a single recording