Help us shape the future of Go! Take the 2026 Go Developer Survey

model

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// AgentPhaseStarting — a new ACP subprocess is being launched and the
	// session initialized (cold start; skipped when reusing a cached agent).
	AgentPhaseStarting = "starting"
	// AgentPhaseReconnecting — the subprocess died (OOM / crash / idle reap)
	// and is being relaunched, restoring the session.
	AgentPhaseReconnecting = "reconnecting"
	// AgentPhaseThinking — the prompt has been submitted; waiting for the
	// model's first token (TTFT). Maps to the default "thinking" label.
	AgentPhaseThinking = "thinking"
)
View Source
const (
	MessageQueuePauseUserStopped = "user_stopped"
	MessageQueuePauseBlocked     = "blocked"
)
View Source
const (
	UserInputSourceIM  = "im"
	UserInputSourceWeb = "web"
)

UserInput source values.

View Source
const (
	UserInputPlatformLark   = "lark"
	UserInputPlatformWeChat = "wechat"
	UserInputPlatformWeb    = "web"
)

UserInput platform values. Mirrors messaging.Platform strings so IM entries stay round-trippable; Web entries use UserInputPlatformWeb.

View Source
const ACPProbeCacheVersion = 2
View Source
const AgentCatalogVersion = 1
View Source
const CustomNameAgentPhase = "agent_phase"

Agent phase custom event — a transient, non-persisted progress hint published while an agent run is in the "silent" preparation window (before the first message/thought/tool event reaches the UI). The frontend maps these phases to the loading-indicator label so the user sees what the agent is doing instead of a fixed "thinking..." string. Delivered via PublishTransient: it never enters the event buffer and vanishes on page refresh, matching its ephemeral "current status" semantics.

View Source
const MessagePresetSchemaVersion = 1
View Source
const (
	UserInputKindMessage = "message"
)

UserInput kind values. Entries without an explicit kind (older rows) are implicitly "message".

Variables

This section is empty.

Functions

func DeterministicWeChatOutboxTaskID

func DeterministicWeChatOutboxTaskID(idempotencyKey, toUserID string) string

func NewGraphEventID

func NewGraphEventID() string

func NewGraphRunID

func NewGraphRunID() string

func NewGraphWorkflowID

func NewGraphWorkflowID() string

func NewScheduleID

func NewScheduleID() string

func NewWeChatOutboxTaskID

func NewWeChatOutboxTaskID() string

func RandomWorkspaceColor

func RandomWorkspaceColor() string

RandomWorkspaceColor returns a hex string (#rrggbb) with a random hue and pinned saturation/lightness so every workspace sits in a visually consistent band while still being distinct from its neighbours.

Types

type ACPConfigState

type ACPConfigState struct {
	Models        *SessionModelState        `json:"models,omitempty"`
	Modes         *SessionModeState         `json:"modes,omitempty"`
	ThoughtLevels *SessionThoughtLevelState `json:"thoughtLevels,omitempty"`
}

ACPConfigState is the response of an ACP live-config switch. Each selector list is populated only when the underlying ACP response carried a refreshed list for it: switching model or thought_level returns the full linked ConfigOptions (so both may refresh together), while switching mode carries no ConfigOptions and leaves all three nil. The frontend refreshes the non-nil lists and keeps its current values for the nil ones.

type ACPConfigTarget

type ACPConfigTarget string

ACPConfigTarget names which selector an ACP live-config switch changes.

const (
	ACPConfigTargetModel        ACPConfigTarget = "model"
	ACPConfigTargetMode         ACPConfigTarget = "mode"
	ACPConfigTargetThoughtLevel ACPConfigTarget = "thoughtLevel"
)

type ACPEnvVarEntry

type ACPEnvVarEntry struct {
	Key     string `json:"key"`
	Value   string `json:"value"`
	Enabled bool   `json:"enabled"`
}

ACPEnvVarEntry is one persisted environment-variable setting for an ACP Agent. It lives in the shared model layer because both the HTTP API and the settings service exchange this value; repository only owns its persistence.

type ACPProbeCacheEntry

type ACPProbeCacheEntry struct {
	AgentID                string                    `json:"agent_id"`
	Revision               string                    `json:"revision"`
	RuntimeKey             string                    `json:"runtime_key"`
	EnvVersion             int64                     `json:"env_version"`
	Success                bool                      `json:"success"`
	Error                  string                    `json:"error,omitempty"`
	AuthenticationRequired bool                      `json:"authentication_required,omitempty"`
	Refreshing             bool                      `json:"refreshing,omitempty"`
	RefreshedAt            int64                     `json:"refreshed_at,omitempty"`
	Models                 *SessionModelState        `json:"models,omitempty"`
	Modes                  *SessionModeState         `json:"modes,omitempty"`
	ThoughtLevels          *SessionThoughtLevelState `json:"thoughtLevels,omitempty"`
}

ACPProbeCacheEntry is the persisted validation and selector state for one stable AgentID. Revision and EnvVersion make stale results unusable without deleting the diagnostic record.

func (ACPProbeCacheEntry) Availability

func (e ACPProbeCacheEntry) Availability() string

Availability separates an installed runtime needing credentials from a broken runtime. Callers still gate execution on Success, never on installation.

type ACPProbeCacheSnapshot

type ACPProbeCacheSnapshot struct {
	Version     int                           `json:"version"`
	RefreshedAt int64                         `json:"refreshed_at"`
	Entries     map[string]ACPProbeCacheEntry `json:"entries"`
}

ACPProbeCacheSnapshot is the last complete in-memory ACP cache written to disk. RefreshedAt is Unix milliseconds and controls the disk write interval.

type ACPSessionMode

type ACPSessionMode struct {
	Description *string `json:"description,omitempty"`
	Id          string  `json:"id"`
	Name        string  `json:"name"`
}

type ACPThoughtLevel

type ACPThoughtLevel struct {
	Description *string `json:"description,omitempty"`
	Id          string  `json:"id"`
	Name        string  `json:"name"`
}

type AgentAuthAttempt

type AgentAuthAttempt struct {
	ID         string          `json:"id"`
	AgentID    string          `json:"agent_id"`
	Revision   string          `json:"revision"`
	MethodID   string          `json:"method_id"`
	Status     string          `json:"status"`
	Output     string          `json:"output,omitempty"`
	Error      string          `json:"error,omitempty"`
	Links      []AgentAuthLink `json:"links,omitempty"`
	StartedAt  int64           `json:"started_at"`
	FinishedAt int64           `json:"finished_at,omitempty"`
}
type AgentAuthLink struct {
	URL     string `json:"url"`
	Message string `json:"message,omitempty"`
}

type AgentAuthMethod

type AgentAuthMethod struct {
	ID          string   `json:"id"`
	Name        string   `json:"name"`
	Description string   `json:"description,omitempty"`
	Type        string   `json:"type"`
	Command     string   `json:"command,omitempty"`
	Environment []string `json:"environment,omitempty"`
}

AgentAuthMethod is the authentication surface advertised by an ACP agent. The generic authentication flow leaves credentials with the agent or the ACP environment settings. Codex account profiles use a separate opt-in API.

type AgentAuthRequest

type AgentAuthRequest struct {
	Revision string `json:"revision"`
	MethodID string `json:"method_id"`
}

type AgentAuthResponse

type AgentAuthResponse struct {
	Code     int               `json:"code"`
	AgentID  string            `json:"agent_id"`
	Revision string            `json:"revision"`
	Methods  []AgentAuthMethod `json:"methods"`
	Attempt  *AgentAuthAttempt `json:"attempt,omitempty"`
}

type AgentCatalogDetailResponse

type AgentCatalogDetailResponse struct {
	Code      int                    `json:"code"`
	Agent     AgentCatalogItem       `json:"agent"`
	Revisions []AgentRuntimeRevision `json:"revisions"`
}

type AgentCatalogIdentifier

type AgentCatalogIdentifier struct {
	Kind  string `json:"kind"`
	Value string `json:"value"`
}

type AgentCatalogItem

type AgentCatalogItem struct {
	AgentID               string                   `json:"agent_id"`
	Source                AgentCatalogSource       `json:"source"`
	DisplayName           string                   `json:"display_name"`
	IconURL               string                   `json:"icon_url"`
	Definition            AgentRuntimeDefinition   `json:"definition"`
	CLIExecutableEnv      string                   `json:"cli_executable_env,omitempty"`
	HistoricalIdentifiers []AgentCatalogIdentifier `json:"historical_identifiers,omitempty"`
	SupportsHeadlessPrint bool                     `json:"supports_headless_print"`
	Deprecated            bool                     `json:"deprecated"`
	Lifecycle             AgentLifecycle           `json:"lifecycle"`
	CurrentRevision       string                   `json:"current_revision,omitempty"`
	InstallMethod         string                   `json:"install_method,omitempty"`
	InstallCommands       []string                 `json:"install_commands,omitempty"`
	UninstallCommands     []string                 `json:"uninstall_commands,omitempty"`
	InstallInstructions   string                   `json:"install_instructions,omitempty"`
	AutoInstallable       bool                     `json:"auto_installable,omitempty"`
	AutoUninstallable     bool                     `json:"auto_uninstallable,omitempty"`
	Installed             bool                     `json:"installed"`
	Availability          string                   `json:"availability"`
	AvailabilityError     string                   `json:"availability_error,omitempty"`
	LastValidationStatus  string                   `json:"last_validation_status,omitempty"`
	LastValidationError   string                   `json:"last_validation_error,omitempty"`
	LastValidationAt      int64                    `json:"last_validation_at,omitempty"`
	DeleteError           string                   `json:"delete_error,omitempty"`
	Refreshing            bool                     `json:"refreshing,omitempty"`
}

AgentCatalogItem is the ordinary management-directory projection. Custom historical revisions stay in the persisted record and are returned only by the single-Agent detail endpoint.

type AgentCatalogResponse

type AgentCatalogResponse struct {
	Code   int                `json:"code"`
	Agents []AgentCatalogItem `json:"agents"`
}

type AgentCatalogSnapshot

type AgentCatalogSnapshot struct {
	Version          int                               `json:"version"`
	Agents           []CustomAgent                     `json:"agents"`
	BuiltinRevisions map[string][]AgentRuntimeRevision `json:"builtin_revisions,omitempty"`
}

type AgentCatalogSource

type AgentCatalogSource string
const (
	AgentCatalogSourceBuiltin AgentCatalogSource = "builtin"
	AgentCatalogSourceCustom  AgentCatalogSource = "custom"
)

type AgentDeleteImpact

type AgentDeleteImpact struct {
	AgentID           string   `json:"agent_id"`
	ClearedSettings   []string `json:"cleared_settings"`
	RetainedWorkflows []string `json:"retained_workflows"`
	RetainedSchedules []string `json:"retained_schedules"`
	RetainedJobs      []string `json:"retained_jobs"`
	RetainedSessions  []string `json:"retained_sessions"`
	BlockingJobIDs    []string `json:"blocking_job_ids"`
}

type AgentDeleteImpactResponse

type AgentDeleteImpactResponse struct {
	Code   int               `json:"code"`
	Impact AgentDeleteImpact `json:"impact"`
}

type AgentDeleteRequest

type AgentDeleteRequest struct {
	Force bool `json:"force,omitempty"`
}

type AgentDeleteResponse

type AgentDeleteResponse struct {
	Code   int               `json:"code"`
	Result AgentDeleteResult `json:"result"`
}

type AgentDeleteResult

type AgentDeleteResult struct {
	Status      string                  `json:"status"`
	StopResults []AgentDeleteStopResult `json:"stop_results,omitempty"`
	Impact      AgentDeleteImpact       `json:"impact"`
}

type AgentDeleteStopResult

type AgentDeleteStopResult struct {
	JobID      string `json:"job_id"`
	GraphRunID string `json:"graph_run_id,omitempty"`
	Stopped    bool   `json:"stopped"`
	Error      string `json:"error,omitempty"`
}

type AgentDisplayInfo

type AgentDisplayInfo struct {
	AgentID     string `json:"agentId"`
	DisplayName string `json:"displayName"`
	IconURL     string `json:"iconUrl"`
	Deleted     bool   `json:"deleted"`
}

AgentDisplayInfo is the minimal display projection of an Agent record, resolved on demand for historical references (session serve commands, graph node snapshot agent types) so old jobs keep rendering after the Agent was renamed or deleted. It deliberately excludes runtime definitions, revisions, install data and availability errors.

type AgentEnvironmentItem

type AgentEnvironmentItem struct {
	Key     string `json:"key"`
	Value   string `json:"value"`
	Enabled bool   `json:"enabled"`
}

type AgentInfo

type AgentInfo struct {
	AgentID       string                    `json:"agent_id"`
	Revision      string                    `json:"revision,omitempty"`
	Type          string                    `json:"type"`
	EnvKey        string                    `json:"env_key,omitempty"`
	ModelID       string                    `json:"model_id"`
	DisplayName   string                    `json:"display_name"`
	IconURL       string                    `json:"icon_url"`
	Availability  string                    `json:"availability,omitempty"`
	Available     bool                      `json:"available"`
	Refreshing    bool                      `json:"refreshing,omitempty"`
	Error         string                    `json:"error,omitempty"`
	Capabilities  []string                  `json:"capabilities,omitempty"`
	Models        *SessionModelState        `json:"models,omitempty"`
	Modes         *SessionModeState         `json:"modes,omitempty"`
	ThoughtLevels *SessionThoughtLevelState `json:"thoughtLevels,omitempty"`
}

type AgentInstallCandidate

type AgentInstallCandidate struct {
	AgentID         string   `json:"agent_id"`
	Bin             string   `json:"bin"`
	ACPProgram      string   `json:"acp_program"`
	Command         string   `json:"command"`
	DisplayName     string   `json:"display_name"`
	IconURL         string   `json:"icon_url"`
	InstallMethod   string   `json:"install_method"`
	InstallCommands []string `json:"install_commands,omitempty"`
	Instructions    string   `json:"instructions,omitempty"`
	AutoInstallable bool     `json:"auto_installable"`
}

AgentInstallCandidate describes one not-yet-installed built-in agent shown in the add-agent form. Manual-only entries carry Instructions and no InstallCommands.

type AgentInstallCandidatesResponse

type AgentInstallCandidatesResponse struct {
	Code       int                     `json:"code"`
	Candidates []AgentInstallCandidate `json:"candidates"`
}

type AgentInstallRequest

type AgentInstallRequest struct {
	AgentID string `json:"agent_id"`
}

AgentInstallRequest installs a built-in agent by its catalog AgentID. The backend only ever runs the preset catalog flow for that AgentID — clients cannot supply commands.

type AgentInstallResponse

type AgentInstallResponse struct {
	Code   int                 `json:"code"`
	Result *AgentInstallResult `json:"result"`
}

type AgentInstallResult

type AgentInstallResult struct {
	AgentID string                   `json:"agent_id"`
	Steps   []AgentInstallStepResult `json:"steps"`
	// Installed is the unified install recheck after the steps ran. A zero
	// exit status with the binaries still missing from the backend PATH
	// leaves this false.
	Installed    bool                   `json:"installed"`
	InstallError string                 `json:"install_error,omitempty"`
	Validation   *AgentValidationResult `json:"validation,omitempty"`
}

AgentInstallResult carries the full install attempt: every executed step's output, the post-install recheck, and the ACP validation result.

type AgentInstallStepResult

type AgentInstallStepResult struct {
	Display    string `json:"display"`
	Stdout     string `json:"stdout"`
	Stderr     string `json:"stderr"`
	ExitCode   int    `json:"exit_code"`
	TimedOut   bool   `json:"timed_out"`
	Error      string `json:"error,omitempty"`
	DurationMs int64  `json:"duration_ms"`
}

AgentInstallStepResult is the complete outcome of one executed install step. Stdout/Stderr are returned verbatim.

type AgentLifecycle

type AgentLifecycle string
const (
	AgentLifecycleActive   AgentLifecycle = "active"
	AgentLifecycleDeleting AgentLifecycle = "deleting"
	AgentLifecycleDeleted  AgentLifecycle = "deleted"
)

type AgentListResponse

type AgentListResponse struct {
	Code      int         `json:"code"`
	AgentList []AgentInfo `json:"agent_list"`
	Workdir   string      `json:"workdir"`
	JobEnable bool        `json:"job_enable"`
}

type AgentPhaseValue

type AgentPhaseValue struct {
	Phase  string `json:"phase"`
	Detail string `json:"detail,omitempty"`
}

AgentPhaseValue is the payload of a CustomNameAgentPhase event.

type AgentPrefs

type AgentPrefs struct {
	FavoriteModelIDs    []string `json:"favorite_model_ids,omitempty"`
	DefaultModelID      string   `json:"default_model_id,omitempty"`
	DefaultMode         string   `json:"default_mode,omitempty"`
	DefaultThoughtLevel string   `json:"default_thought_level,omitempty"`
}

AgentPrefs holds per-Agent UI defaults edited in Settings.

type AgentRevalidateRequest

type AgentRevalidateRequest struct {
	Revision string `json:"revision,omitempty"`
}

type AgentRoleConfig

type AgentRoleConfig struct {
	AgentID         string `json:"agent_id"`
	ModelID         string `json:"model_id,omitempty"`
	ACPThoughtLevel string `json:"acp_thought_level,omitempty"`
}

AgentRoleConfig identifies an Agent used by a one-shot role. The runtime definition is resolved from the Agent catalog when the role is executed. ModelID/ACPThoughtLevel are honored by headless agents that accept them (eino-cli: `-p --model/--thought`; CodeBuddy/Claude: `--model/--effort`; cursor-agent: `--model`). Empty values fall back to the agent's own defaults.

type AgentRuntimeBinding

type AgentRuntimeBinding struct {
	AgentID    string                 `json:"agent_id"`
	Revision   string                 `json:"revision"`
	RuntimeKey string                 `json:"runtime_key"`
	Definition AgentRuntimeDefinition `json:"definition"`
}

type AgentRuntimeDefinition

type AgentRuntimeDefinition struct {
	Bin        string   `json:"bin"`
	ACPProgram string   `json:"acp_program"`
	ACPArgs    []string `json:"acp_args"`
}

AgentRuntimeDefinition is the structured, shell-free command used to start an ACP server. Args are ordered and each element is passed as one argv value.

type AgentRuntimeRevision

type AgentRuntimeRevision struct {
	Revision   string                 `json:"revision"`
	Definition AgentRuntimeDefinition `json:"definition"`
}

AgentRuntimeRevision is persisted even when it is no longer current if a session or unfinished execution still references it.

type AgentUsageResponse

type AgentUsageResponse struct {
	Code        int               `json:"code"`
	Type        string            `json:"type"` // "codex" | "claude" | "antigravity" | "kimi" | "qoder" | "cursor" | "codebuddy"
	Codex       *CodexUsage       `json:"codex,omitempty"`
	Claude      *ClaudeUsage      `json:"claude,omitempty"`
	Antigravity *AntigravityUsage `json:"antigravity,omitempty"`
	Kimi        *KimiUsage        `json:"kimi,omitempty"`
	Qoder       *QoderUsage       `json:"qoder,omitempty"`
	Cursor      *CursorUsage      `json:"cursor,omitempty"`
	CodeBuddy   *CodeBuddyUsage   `json:"codebuddy,omitempty"`
}

AgentUsageResponse is the envelope for GET /api/v1/agent/usage. Exactly one of Codex / Claude / Antigravity / Kimi / Qoder / Cursor / CodeBuddy is populated, matching the requested Type.

type AgentValidationResult

type AgentValidationResult struct {
	OK                     bool   `json:"ok"`
	Error                  string `json:"error,omitempty"`
	AuthenticationRequired bool   `json:"authentication_required,omitempty"`
}

AgentValidationResult is the outcome of the full ACP validation run after a successful install recheck.

type AgentVersionCheckResponse

type AgentVersionCheckResponse struct {
	Code      int                `json:"code"`
	CheckedAt int64              `json:"checked_at"`
	Agents    []AgentVersionInfo `json:"agents"`
}

type AgentVersionComponent

type AgentVersionComponent struct {
	Name            string `json:"name"`
	Kind            string `json:"kind"` // "npm" | "binary"
	CurrentVersion  string `json:"current_version,omitempty"`
	LatestVersion   string `json:"latest_version,omitempty"`
	UpdateAvailable bool   `json:"update_available"`
	Error           string `json:"error,omitempty"`
}

AgentVersionComponent is one versioned part of an Agent installation. NPM components carry both current and latest versions; binary components may only expose a current local version when no authoritative remote version source exists.

type AgentVersionInfo

type AgentVersionInfo struct {
	AgentID          string                  `json:"agent_id"`
	Components       []AgentVersionComponent `json:"components"`
	UpdateAvailable  bool                    `json:"update_available"`
	UpgradeSupported bool                    `json:"upgrade_supported"`
}

AgentVersionInfo is the aggregate version state for one installed Agent. UpgradeSupported means the built-in catalog has a controlled preset flow; it never permits the client to supply an arbitrary command.

type AgentVersionResponse

type AgentVersionResponse struct {
	Code    int    `json:"code"`
	Version string `json:"version,omitempty"`
}

AgentVersionResponse is the envelope for GET /api/v1/agent/version. It reports the installed CLI version of a built-in or custom ACP agent (e.g. "v1.17.18"). Version is empty when the binary advertises no parseable version.

type AntigravityUsage

type AntigravityUsage struct {
	Version      string       `json:"version,omitempty"`       // agy CLI version, e.g. "v1.1.1"
	ClaudeWeekly *UsageWindow `json:"claude_weekly,omitempty"` // Claude/GPT group, 7-day  (bucketId 3p-weekly)
	Claude5h     *UsageWindow `json:"claude_5h,omitempty"`     // Claude/GPT group, 5-hour (bucketId 3p-5h)
	GeminiWeekly *UsageWindow `json:"gemini_weekly,omitempty"` // Gemini group, 7-day  (bucketId gemini-weekly)
	Gemini5h     *UsageWindow `json:"gemini_5h,omitempty"`     // Gemini group, 5-hour (bucketId gemini-5h)
}

AntigravityUsage is the Antigravity (agy) built-in plan snapshot: the agy CLI version plus the two model groups' quota windows, each with a 7-day (weekly) and a 5-hour bucket. Each window reuses UsageWindow — its UsedPercent is derived from the API's remaining fraction, and ResetAt from the bucket's reset time. A window is nil when the corresponding bucket is absent.

type AuthPrincipal

type AuthPrincipal struct {
	User        UserView `json:"user"`
	Permissions []string `json:"permissions"`
	CSRFToken   string   `json:"csrfToken"`
}

type AuthSession

type AuthSession struct {
	TokenHash string    `json:"tokenHash"`
	UserID    string    `json:"userId"`
	CSRFToken string    `json:"csrfToken"`
	CreatedAt time.Time `json:"createdAt"`
}

type AuthSystem

type AuthSystem struct {
	SchemaVersion int       `json:"schemaVersion"`
	Initialized   bool      `json:"initialized"`
	UpdatedAt     time.Time `json:"updatedAt"`
}

type BaseEvent

type BaseEvent struct {
	Type      EventType      `json:"type"`
	SessionID string         `json:"sessionId"`
	RunID     string         `json:"runId"`
	StepID    string         `json:"stepId,omitempty"`
	Timestamp int64          `json:"timestamp"`
	External  map[string]any `json:"external,omitempty"`

	JobID string `json:"jobId,omitempty"`
}

type ChangePasswordRequest

type ChangePasswordRequest struct {
	CurrentPassword string `json:"currentPassword"`
	NewPassword     string `json:"newPassword"`
}

type ClaudeExtraUsage

type ClaudeExtraUsage struct {
	Enabled      bool     `json:"is_enabled"`
	MonthlyLimit *float64 `json:"monthly_limit,omitempty"`
	UsedCredits  *float64 `json:"used_credits,omitempty"`
	Currency     string   `json:"currency,omitempty"`
}

ClaudeExtraUsage describes the optional monthly pay-as-you-go allowance.

type ClaudeScopedUsageWindow

type ClaudeScopedUsageWindow struct {
	Label string `json:"label"`
	UsageWindow
}

ClaudeScopedUsageWindow is a model-specific weekly limit returned through the generic limits array (for example, Fable).

type ClaudeUsage

type ClaudeUsage struct {
	PlanType      string                    `json:"plan_type,omitempty"`
	RateLimitTier string                    `json:"rate_limit_tier,omitempty"`
	Version       string                    `json:"version,omitempty"` // effective Claude Code version used by claude-agent-acp, e.g. "v2.1.202"
	FiveHour      *UsageWindow              `json:"five_hour,omitempty"`
	SevenDay      *UsageWindow              `json:"seven_day,omitempty"`
	SevenDayOpus  *UsageWindow              `json:"seven_day_opus,omitempty"`
	WeeklyScoped  []ClaudeScopedUsageWindow `json:"weekly_scoped,omitempty"`
	ExtraUsage    *ClaudeExtraUsage         `json:"extra_usage,omitempty"`
}

ClaudeUsage is the current Claude Code subscription and rate-limit snapshot returned by Anthropic's OAuth usage endpoint.

type ClientMessageReceipt

type ClientMessageReceipt struct {
	State       ClientMessageState `json:"state"`
	PayloadHash string             `json:"payloadHash"`
	AcceptedAt  int64              `json:"acceptedAt"`
	FinishedAt  int64              `json:"finishedAt,omitempty"`
}

ClientMessageReceipt is the persistent idempotency record for a clientMessageId. PayloadHash prevents one key from silently being reused for a different logical request.

type ClientMessageState

type ClientMessageState string

ClientMessageState records the durable disposition of one idempotent interactive message submission. A processing receipt is written before the Agent goroutine starts. Once written, the same clientMessageId is never executed again; callers that intentionally retry a failed/stopped message must submit it with a new ID.

const (
	ClientMessageStateQueued      ClientMessageState = "queued"
	ClientMessageStateBlocked     ClientMessageState = "blocked"
	ClientMessageStateProcessing  ClientMessageState = "processing"
	ClientMessageStateCompleted   ClientMessageState = "completed"
	ClientMessageStateFailed      ClientMessageState = "failed"
	ClientMessageStateStopped     ClientMessageState = "stopped"
	ClientMessageStateInterrupted ClientMessageState = "interrupted"
	ClientMessageStateDeleted     ClientMessageState = "deleted"
)

type CodeBuddyUsage

type CodeBuddyUsage struct {
	Version     string   `json:"version,omitempty"` // CodeBuddy CLI version, e.g. "v2.6.0"
	Username    string   `json:"username,omitempty"`
	QuotaText   string   `json:"quota_text"`
	CostText    string   `json:"cost_text"`
	Quota       *float64 `json:"quota,omitempty"`
	Cost        *float64 `json:"cost,omitempty"`
	Remaining   *float64 `json:"remaining,omitempty"`
	UsedPercent *float64 `json:"used_percent,omitempty"` // 0–100
}

CodeBuddyUsage is the CodeBuddy quota snapshot: the CodeBuddy CLI version, plus the monthly quota and the current calendar-month spend in CNY from the company Token 看板 OpenAPI (openapi.token.woa.com). QuotaText/CostText keep the API's raw string values; Quota is nil when the API reports a non-numeric quota ("-" — special states such as unlimited), in which case Remaining and UsedPercent are nil too and must not be derived numerically.

type CodexAccount

type CodexAccount struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Note        string `json:"note"`
	AuthType    string `json:"auth_type"`
	Email       string `json:"email,omitempty"`
	AccountID   string `json:"account_id,omitempty"`
	WorkspaceID string `json:"workspace_id,omitempty"`
	HasConfig   bool   `json:"has_config"`
	Model       string `json:"model,omitempty"`
	Provider    string `json:"provider,omitempty"`
	CreatedAt   int64  `json:"created_at"`
	UpdatedAt   int64  `json:"updated_at"`
	LastUsedAt  int64  `json:"last_used_at,omitempty"`
}

CodexAccount contains display information only. Credential files never leave the backend through the management API.

type CodexAccountCurrent

type CodexAccountCurrent struct {
	Availability    string        `json:"availability"`
	ValidationError string        `json:"validation_error,omitempty"`
	ValidatedAt     int64         `json:"validated_at,omitempty"`
	Home            string        `json:"home"`
	Account         *CodexAccount `json:"account,omitempty"`
	ManagedID       string        `json:"managed_id,omitempty"`
	Status          string        `json:"status"`
	HasAuth         bool          `json:"has_auth"`
	HasConfig       bool          `json:"has_config"`
	ConfigApplied   bool          `json:"config_applied"`
	Error           string        `json:"error,omitempty"`
	BlockedReason   string        `json:"blocked_reason,omitempty"`
}

type CodexAccountLogin

type CodexAccountLogin struct {
	ID        string `json:"id"`
	Name      string `json:"name"`
	Status    string `json:"status"`
	Output    string `json:"output"`
	Error     string `json:"error,omitempty"`
	AccountID string `json:"account_id,omitempty"`
}

type CodexAccountLoginResponse

type CodexAccountLoginResponse struct {
	Code  int               `json:"code"`
	Login CodexAccountLogin `json:"login"`
}

type CodexAccountMutation

type CodexAccountMutation struct {
	Revision     string  `json:"revision"`
	LiveRevision string  `json:"live_revision"`
	OperationID  string  `json:"operation_id"`
	Name         string  `json:"name"`
	Note         string  `json:"note"`
	AuthJSON     *string `json:"auth_json,omitempty"`
	ConfigTOML   *string `json:"config_toml,omitempty"`
	RemoveConfig bool    `json:"remove_config,omitempty"`
	ApplyConfig  bool    `json:"apply_config,omitempty"`
}

File contents are accepted only on writes. Pointers distinguish omitted files from empty uploads and allow updating just one member of a profile.

type CodexAccountOperation

type CodexAccountOperation struct {
	ID         string `json:"id"`
	Action     string `json:"action"`
	AccountID  string `json:"account_id,omitempty"`
	Status     string `json:"status"`
	Error      string `json:"error,omitempty"`
	FinishedAt int64  `json:"finished_at"`
}

type CodexAccountResponse

type CodexAccountResponse struct {
	Code         int                     `json:"code"`
	Revision     string                  `json:"revision"`
	LiveRevision string                  `json:"live_revision"`
	Accounts     []CodexAccount          `json:"accounts"`
	Current      CodexAccountCurrent     `json:"current"`
	HasBackup    bool                    `json:"has_backup"`
	Operations   []CodexAccountOperation `json:"operations"`
	ActiveLogin  *CodexAccountLogin      `json:"active_login,omitempty"`
	Warning      string                  `json:"warning,omitempty"`
}

type CodexUsage

type CodexUsage struct {
	Email           string       `json:"email,omitempty"`
	PlanType        string       `json:"plan_type,omitempty"`
	Version         string       `json:"version,omitempty"` // effective Codex CLI version used by codex-acp, e.g. "v0.144.0"
	PrimaryWindow   *UsageWindow `json:"primary_window,omitempty"`
	SecondaryWindow *UsageWindow `json:"secondary_window,omitempty"`
	ResetCredits    int          `json:"reset_credits"` // count of available rate-limit reset credits
	// ResetCreditExpiries lists the expiry (unix seconds) of each available reset
	// credit, ascending. Sourced from the rate-limit-reset-credits endpoint;
	// empty when that supplementary call fails.
	ResetCreditExpiries []int64 `json:"reset_credit_expiries,omitempty"`
}

CodexUsage is the Codex/ChatGPT plan + rate-limit snapshot pulled from the ChatGPT usage endpoint.

type CommandAction

type CommandAction struct {
	Type            string `json:"type,omitempty"`
	WorkspaceID     string `json:"workspaceId,omitempty"`
	JobID           string `json:"jobId,omitempty"`
	ClientMessageID string `json:"clientMessageId,omitempty"`
}

CommandAction is the frontend-visible shape of services/command.Action. Kept separate so the types/model package stays free of the command service dependency.

type CommandReceipt

type CommandReceipt struct {
	PayloadHash string                     `json:"payloadHash"`
	Event       *CommandSystemMessageEvent `json:"event"`
}

CommandReceipt records a completed slash-command dispatch. Commands use a separate receipt type because they execute synchronously and must never leave an Agent-style processing receipt behind. Event is persisted so retries can replay the original response without repeating side effects.

type CommandSystemMessageEvent

type CommandSystemMessageEvent struct {
	BaseEvent
	// ClientMessageID is the caller-provided idempotency key. It lets clients
	// deduplicate the inline response and transient SSE copy without relying on
	// command text or a short time window.
	ClientMessageID string `json:"clientMessageId,omitempty"`
	// Command is the canonical command name (e.g. "/help", "/ws").
	Command string `json:"command"`
	// Text is what the user sees.
	Text string `json:"text"`
	// Present is a hint for renderer placement: "inline" (system bubble) or
	// "toast".
	Present string `json:"present,omitempty"`
	// Action mirrors services/command.Action when the command wants the
	// frontend to apply a side effect. Nil for display-only commands (e.g.
	// /help, /status) so the JSON payload drops the field entirely —
	// `omitempty` on a non-pointer struct is a no-op in encoding/json, so
	// without the pointer we'd always emit `"action":{}`.
	Action *CommandAction `json:"action,omitempty"`
}

CommandSystemMessageEvent carries a slash-command execution result for the Web chat page. Includes the rendered message text plus the structured Action so the frontend can additionally apply state changes (e.g. switch workspace / reload job) on top of rendering the inline bubble.

type ConfigureJobShareRequest

type ConfigureJobShareRequest struct {
	ShowWorkspaceName *bool `json:"showWorkspaceName,omitempty"`
}

type ConfigureJobShareResponse

type ConfigureJobShareResponse struct {
	ShareToken        string `json:"shareToken"`
	ShowWorkspaceName bool   `json:"showWorkspaceName"`
}

type CreateEinoModelRequest

type CreateEinoModelRequest struct {
	ModelClass   string               `json:"model_class"`
	DisplayName  string               `json:"display_name"`
	Connection   *EinoModelConnection `json:"connection"`
	ThinkingType string               `json:"thinking_type,omitempty"`
}

CreateEinoModelRequest is the payload for adding a model to eino-cli.

type CreateGraphWorkflowRequest

type CreateGraphWorkflowRequest struct {
	Name        string            `json:"name"`
	Description string            `json:"description,omitempty"`
	Type        GraphWorkflowType `json:"type,omitempty"`
	WorkspaceID string            `json:"workspaceId,omitempty"`
	Config      GraphConfig       `json:"config"`
}

type CreateJobRequest

type CreateJobRequest struct {
	ModelID   string `json:"modelId"`
	AgentType string `json:"agentType"`
	// ClientMessageID makes Job creation retry-safe. For a /new command this
	// is a command-action key derived from (source Job, command message ID), not
	// the message-send key itself.
	ClientMessageID string  `json:"clientMessageId,omitempty"`
	ACPMode         string  `json:"acpMode,omitempty"`
	ACPThoughtLevel string  `json:"acpThoughtLevel,omitempty"`
	Mode            JobMode `json:"mode,omitempty"`
	Workdir         string  `json:"workdir,omitempty"`
	WorkspaceID     string  `json:"workspaceId"`
}

type CreateJobResponse

type CreateJobResponse struct {
	JobID     string `json:"jobId"`
	CreatedAt int64  `json:"createdAt"`
	Status    string `json:"status,omitempty"`
}

type CreateRoleRequest

type CreateRoleRequest struct {
	Name        string   `json:"name"`
	Description string   `json:"description"`
	Permissions []string `json:"permissions"`
}

type CreateScheduleRequest

type CreateScheduleRequest struct {
	Name            string `json:"name"`
	CronExpr        string `json:"cronExpr"`
	GraphWorkflowID string `json:"graphWorkflowId,omitempty"`
	WorkspaceID     string `json:"workspaceId,omitempty"`
	Workdir         string `json:"workdir,omitempty"`
	MaxConcurrent   int    `json:"maxConcurrent,omitempty"`
	Timeout         int    `json:"timeout,omitempty"`
	// Enabled controls activation on the current machine. nil keeps the
	// historical "enabled by default on the creating machine" behavior.
	Enabled *bool `json:"enabled,omitempty"`
}

type CreateScheduleResponse

type CreateScheduleResponse struct {
	Schedule ScheduleInfo `json:"schedule"`
}

type CreateUserRequest

type CreateUserRequest struct {
	Username    string   `json:"username"`
	DisplayName string   `json:"displayName"`
	Password    string   `json:"password"`
	RoleIDs     []string `json:"roleIds"`
}

type CreateWorkspaceRequest

type CreateWorkspaceRequest struct {
	Title        string `json:"title"`
	Description  string `json:"description"`
	Workdir      string `json:"workdir"`
	DefaultAgent string `json:"defaultAgent,omitempty"`
	DefaultModel string `json:"defaultModel,omitempty"`
}

type CursorUsage

type CursorUsage struct {
	Version         string       `json:"version,omitempty"`          // cursor-agent CLI version, e.g. "v2026.09.08"
	MembershipType  string       `json:"membership_type,omitempty"`  // e.g. "pro" | "team" | "enterprise"
	PrimaryWindow   *UsageWindow `json:"primary_window,omitempty"`   // plan total usage (Auto + API lanes)
	SecondaryWindow *UsageWindow `json:"secondary_window,omitempty"` // Auto lane usage
	TertiaryWindow  *UsageWindow `json:"tertiary_window,omitempty"`  // API lane usage
	GrokBotWindow   *UsageWindow `json:"grok_bot_window,omitempty"`  // Grok Bot usage, nil when unavailable
}

CursorUsage is the Cursor plan snapshot from cursor.com's usage-summary endpoint plus the Cursor Bot (internal codename "Sand") usage RPC, using the cursor-agent CLI's locally stored login token. The three plan windows share the monthly billing cycle (reset at billingCycleEnd, LimitWindowSeconds = cycle length): PrimaryWindow is the plan total, SecondaryWindow the Auto lane, TertiaryWindow the API lane. GrokBotWindow is only reported when the account has Grok Bot access and the RPC returns a usable percent and reset time; otherwise it is nil. A window is nil when the API reports no usable percent for it.

type CustomAgent

type CustomAgent struct {
	AgentID               string                 `json:"agent_id"`
	DisplayName           string                 `json:"display_name"`
	IconURL               string                 `json:"icon_url"`
	SupportsHeadlessPrint bool                   `json:"supports_headless_print"`
	Lifecycle             AgentLifecycle         `json:"lifecycle"`
	DeleteCleanupStarted  bool                   `json:"delete_cleanup_started,omitempty"`
	DeleteError           string                 `json:"delete_error,omitempty"`
	CurrentRevision       string                 `json:"current_revision"`
	Revisions             []AgentRuntimeRevision `json:"revisions"`
}

CustomAgent is the durable custom portion of the Agent directory. Management workflows own validation and revision creation; the catalog preserves their result without flattening structured argv values.

type CustomAgentResponse

type CustomAgentResponse struct {
	Code    int              `json:"code"`
	Agent   AgentCatalogItem `json:"agent"`
	Warning string           `json:"warning,omitempty"`
}

type CustomAgentUpsertRequest

type CustomAgentUpsertRequest struct {
	DisplayName           string                 `json:"display_name"`
	IconURL               string                 `json:"icon_url"`
	SupportsHeadlessPrint bool                   `json:"supports_headless_print"`
	Definition            AgentRuntimeDefinition `json:"definition"`
	Environment           []AgentEnvironmentItem `json:"environment,omitempty"`
}

type CustomEvent

type CustomEvent struct {
	BaseEvent
	Name  string `json:"name"`
	Value any    `json:"value"`
}

type DailyStatsEntry

type DailyStatsEntry struct {
	TotalMs   int64 `json:"totalMs"`
	TurnCount int   `json:"turnCount"`
}

DailyStatsEntry is the per-day total exposed alongside the job list. Kept intentionally small so it can be sent on every list request without bloating the response.

type DeleteAuthRecordRequest

type DeleteAuthRecordRequest struct {
	Version int64 `json:"version"`
}

type DeleteGraphWorkflowRequest

type DeleteGraphWorkflowRequest struct {
	UpdatedAt *time.Time `json:"updatedAt,omitempty"`
}

type EffectiveMessagePresetsResponse

type EffectiveMessagePresetsResponse struct {
	Code        int                      `json:"code"`
	WorkspaceID string                   `json:"workspaceId"`
	Project     []MessagePreset          `json:"project"`
	Global      []MessagePreset          `json:"global"`
	Errors      []MessagePresetLoadError `json:"errors,omitempty"`
}

type EinoModel

type EinoModel struct {
	ID           string               `json:"id"`
	ModelClass   string               `json:"model_class"`
	DisplayName  string               `json:"display_name"`
	Connection   *EinoModelConnection `json:"connection"`
	ThinkingType string               `json:"thinking_type,omitempty"`
	CreatedAt    int64                `json:"created_at,omitempty"`
	UpdatedAt    int64                `json:"updated_at,omitempty"`
}

EinoModel is the quartet-side view of one model entry in eino-cli's own persistent model catalog. The API key only ever appears masked here — it is written to eino-cli at creation and never read back.

type EinoModelConnection

type EinoModelConnection struct {
	APIKey  string `json:"api_key,omitempty"`
	BaseURL string `json:"base_url,omitempty"`
	Model   string `json:"model"`
}

EinoModelConnection carries provider connection fields for an eino model.

type EventType

type EventType string
const (
	EventTypeTextMessageStart   EventType = "TEXT_MESSAGE_START"
	EventTypeTextMessageContent EventType = "TEXT_MESSAGE_CONTENT"
	EventTypeTextMessageEnd     EventType = "TEXT_MESSAGE_END"
	EventTypeToolCallStart      EventType = "TOOL_CALL_START"
	EventTypeToolCallArgs       EventType = "TOOL_CALL_ARGS"
	EventTypeToolCallResult     EventType = "TOOL_CALL_RESULT"
	EventTypeToolCallEnd        EventType = "TOOL_CALL_END"
	// EventTypeToolCallStitched is emitted when a tool call's terminal
	// status arrives AFTER the round was eagerly flushed and the bubble
	// closed as Placeholder. The payload carries the real content and
	// final status so the live UI can rewrite the bubble in place; the
	// frontend must accept this event even when the message is already
	// in the Finished state (Placeholder), unlike TOOL_CALL_RESULT /
	// TOOL_CALL_END which are gated against late updates.
	EventTypeToolCallStitched EventType = "TOOL_CALL_STITCHED"
	EventTypeCustom           EventType = "CUSTOM"
	EventTypeRunStarted       EventType = "RUN_STARTED"
	EventTypeRunFinished      EventType = "RUN_FINISHED"
	EventTypeRunError         EventType = "RUN_ERROR"

	// Job-level events
	EventTypeJobStarted   EventType = "JOB_STARTED"
	EventTypeJobCompleted EventType = "JOB_COMPLETED"
	EventTypeJobStopped   EventType = "JOB_STOPPED"
	EventTypeJobFailed    EventType = "JOB_FAILED"

	// Command feedback — pushed by the chat-page message handler after a
	// slash command (e.g. /help, /ws N) runs successfully. Transient: not
	// persisted to the Job's message history, so refreshing the page drops
	// it.
	EventTypeCommandSystemMessage EventType = "COMMAND_SYSTEM_MESSAGE"
)

type FileAttachment

type FileAttachment struct {
	Path     string `json:"path"`
	Name     string `json:"name"`
	MIMEType string `json:"mimeType,omitempty"`
	Size     int64  `json:"size,omitempty"`
}

FileAttachment is a file uploaded with a user message. Path is the local absolute path the Agent can read; Name, MIMEType and Size preserve the user-facing metadata because uploaded files have generated disk names.

type FileShare

type FileShare struct {
	Token     string `json:"token"`
	Path      string `json:"path"`
	CreatedAt int64  `json:"createdAt"`
}

FileShare is the durable token-to-path binding used by public file previews.

type GetMessagesResponse

type GetMessagesResponse struct {
	ModelID         string           `json:"modelId"`
	Type            string           `json:"type,omitempty"`
	Messages        []HistoryMessage `json:"messages"`
	TokenUsage      *TokenUsage      `json:"tokenUsage,omitempty"`
	Workdir         string           `json:"workdir,omitempty"`
	ACPMode         string           `json:"acpMode,omitempty"`
	ACPThoughtLevel string           `json:"acpThoughtLevel,omitempty"`
	Page            *MessagePageInfo `json:"page,omitempty"`
}

type GetPromptRequest

type GetPromptRequest struct {
	Key string `json:"key"`
}

type GetPromptResponse

type GetPromptResponse struct {
	Code   int    `json:"code"`
	Prompt string `json:"prompt"`
	// Path is the on-disk source file for file-backed prompt keys (SOUL /
	// USER / MEMORY). Empty when the key is stored in the prompt DB.
	Path string `json:"path,omitempty"`
}

type GraphAgentSnapshot

type GraphAgentSnapshot struct {
	AgentType       string                 `json:"agentType"`
	AgentID         string                 `json:"agentId,omitempty"`
	Revision        string                 `json:"revision,omitempty"`
	RuntimeKey      string                 `json:"runtimeKey,omitempty"`
	Definition      AgentRuntimeDefinition `json:"definition,omitempty"`
	ModelID         string                 `json:"modelId,omitempty"`
	ACPMode         string                 `json:"acpMode,omitempty"`
	ACPThoughtLevel string                 `json:"acpThoughtLevel,omitempty"`
}

type GraphCanvasState

type GraphCanvasState struct {
	Viewport GraphCanvasViewport `json:"viewport,omitempty"`
}

type GraphCanvasViewport

type GraphCanvasViewport struct {
	X    float64 `json:"x"`
	Y    float64 `json:"y"`
	Zoom float64 `json:"zoom"`
}

type GraphConfig

type GraphConfig struct {
	Nodes        []GraphNode       `json:"nodes"`
	Edges        []GraphEdge       `json:"edges"`
	Variables    map[string]string `json:"variables,omitempty"`
	DisabledVars []string          `json:"disabledVars,omitempty"`
	Canvas       GraphCanvasState  `json:"canvas,omitempty"`
	RunConfig    GraphRunConfig    `json:"runConfig,omitempty"`
	WorkspaceID  string            `json:"workspaceId,omitempty"`
	Workdir      string            `json:"workdir,omitempty"`
}

type GraphEdge

type GraphEdge struct {
	ID           string            `json:"id"`
	SourceNodeID string            `json:"sourceNodeId"`
	TargetNodeID string            `json:"targetNodeId"`
	SourcePort   GraphEdgePort     `json:"sourcePort,omitempty"`
	TargetPort   string            `json:"targetPort,omitempty"`
	Metadata     map[string]string `json:"metadata,omitempty"`
}

type GraphEdgePort

type GraphEdgePort string
const (
	GraphEdgePortDefault GraphEdgePort = "default"
	GraphEdgePortYes     GraphEdgePort = "yes"
	GraphEdgePortNo      GraphEdgePort = "no"
)

type GraphEdgeState

type GraphEdgeState struct {
	EdgeID            string           `json:"edgeId"`
	SourceInstanceKey GraphInstanceKey `json:"sourceInstanceKey"`
	TargetInstanceKey GraphInstanceKey `json:"targetInstanceKey"`
	Status            GraphEdgeStatus  `json:"status"`
	ResolvedAt        int64            `json:"resolvedAt,omitempty"`
	Reason            string           `json:"reason,omitempty"`
}

type GraphEdgeStatus

type GraphEdgeStatus string
const (
	GraphEdgeStatusPending GraphEdgeStatus = "pending"
	GraphEdgeStatusActive  GraphEdgeStatus = "active"
	GraphEdgeStatusPruned  GraphEdgeStatus = "pruned"
)

type GraphEndHookMode

type GraphEndHookMode string

GraphEndHookMode selects an End node's hook behavior. Empty is treated as GraphEndHookModeDefault.

const (
	GraphEndHookModeDefault GraphEndHookMode = "default" // run the global settings script
	GraphEndHookModeCustom  GraphEndHookMode = "custom"  // run the node's own HookScript
	GraphEndHookModeOff     GraphEndHookMode = "off"     // disable the hook
)

type GraphEvent

type GraphEvent struct {
	ID          string             `json:"id"`
	RunID       string             `json:"runId"`
	Type        GraphEventType     `json:"type"`
	InstanceKey *GraphInstanceKey  `json:"instanceKey,omitempty"`
	NodeID      string             `json:"nodeId,omitempty"`
	EdgeID      string             `json:"edgeId,omitempty"`
	Message     string             `json:"message,omitempty"`
	Payload     map[string]string  `json:"payload,omitempty"`
	Error       *GraphRuntimeError `json:"error,omitempty"`
	CreatedAt   int64              `json:"createdAt"`
}

type GraphEventType

type GraphEventType string
const (
	GraphEventTypeInstanceStarted   GraphEventType = "instanceStarted"
	GraphEventTypeInstanceCompleted GraphEventType = "instanceCompleted"
	GraphEventTypeInstanceFailed    GraphEventType = "instanceFailed"
	GraphEventTypeInstanceSkipped   GraphEventType = "instanceSkipped"
	GraphEventTypeEdgeResolved      GraphEventType = "edgeResolved"
	GraphEventTypeVariableWritten   GraphEventType = "variableWritten"
	GraphEventTypeLoopIteration     GraphEventType = "loopIteration"
	GraphEventTypeProgressUpdated   GraphEventType = "progressUpdated"
	GraphEventTypeAgentMessageStart GraphEventType = "agentMessageStart"
	GraphEventTypeAgentMessageDelta GraphEventType = "agentMessageDelta"
	GraphEventTypeAgentMessageEnd   GraphEventType = "agentMessageEnd"
	GraphEventTypeAgentThoughtStart GraphEventType = "agentThoughtStart"
	GraphEventTypeAgentThoughtDelta GraphEventType = "agentThoughtDelta"
	GraphEventTypeAgentThoughtEnd   GraphEventType = "agentThoughtEnd"
	GraphEventTypeAgentToolStart    GraphEventType = "agentToolStart"
	GraphEventTypeAgentToolArgs     GraphEventType = "agentToolArgs"
	GraphEventTypeAgentToolResult   GraphEventType = "agentToolResult"
	GraphEventTypeAgentToolEnd      GraphEventType = "agentToolEnd"
	GraphEventTypeAgentTokenUsage   GraphEventType = "agentTokenUsage"
	GraphEventTypeLog               GraphEventType = "log"
	GraphEventTypeError             GraphEventType = "error"
	// GraphEventTypeHookCompleted / GraphEventTypeHookFailed (§ 节点 Hook) carry a
	// node hook's execution result (exit code, truncated stdout/stderr, origin) so
	// the run-view node-detail panel can surface what a side-effect script did. A
	// hook NEVER affects node status or the run; these are the ONLY signal a user
	// gets that a configured hook ran and how it ended. Both persist to events.jsonl.
	GraphEventTypeHookCompleted GraphEventType = "hookCompleted"
	GraphEventTypeHookFailed    GraphEventType = "hookFailed"
)

type GraphHookResult

type GraphHookResult struct {
	NodeID     string        `json:"nodeId"`
	NodeTitle  string        `json:"nodeTitle,omitempty"`
	NodeType   GraphNodeType `json:"nodeType,omitempty"`
	Source     string        `json:"source,omitempty"` // "prompt" | "end"
	Status     string        `json:"status"`           // "completed" | "failed"
	ExitCode   *int          `json:"exitCode,omitempty"`
	Stdout     string        `json:"stdout,omitempty"`
	Stderr     string        `json:"stderr,omitempty"`
	Message    string        `json:"message,omitempty"`
	FinishedAt int64         `json:"finishedAt"`
}

GraphHookResult is one node hook's execution result, derived from a hookCompleted/hookFailed event for the run-view node-detail panel. NodeTitle / NodeType are carried in the event payload (captured at fire time from the run's own config) so the panel needs no access to the editor node list. FinishedAt is the event's CreatedAt, used to keep the latest result per node when a resume rollback re-fires a hook.

type GraphHookResultsResponse

type GraphHookResultsResponse struct {
	Results []GraphHookResult `json:"results"`
}

type GraphInstanceKey

type GraphInstanceKey struct {
	NodeID     string               `json:"nodeId"`
	Iterations []GraphLoopIteration `json:"iterations,omitempty"`
}

type GraphInstanceState

type GraphInstanceState struct {
	Key       GraphInstanceKey    `json:"key"`
	NodeID    string              `json:"nodeId"`
	NodeTitle string              `json:"nodeTitle,omitempty"`
	NodeType  GraphNodeType       `json:"nodeType"`
	Status    GraphInstanceStatus `json:"status"`
	Version   int                 `json:"version"`
	BatchID   string              `json:"batchId,omitempty"`
	// SessionID is the instance's outflow session for §3 会话血缘: the session a
	// downstream `inherit` Agent forks from. Agent nodes set it to their own
	// created/forked session; non-Agent nodes pass the inflow session through.
	SessionID string `json:"sessionId,omitempty"`
	// DisplaySessionID is the session whose conversation the UI lists/opens for
	// this instance. Agent nodes leave it empty (their SessionID is the display
	// session). Shell nodes set it to their own recording session — the script +
	// output transcript — which is intentionally kept out of SessionID so it
	// never becomes a lineage parent for downstream `inherit` Agents.
	DisplaySessionID string             `json:"displaySessionId,omitempty"`
	VisibleVariables map[string]string  `json:"visibleVariables,omitempty"`
	OutputVariables  map[string]string  `json:"outputVariables,omitempty"`
	VariableWriters  map[string]string  `json:"variableWriters,omitempty"`
	StartedAt        int64              `json:"startedAt,omitempty"`
	FinishedAt       int64              `json:"finishedAt,omitempty"`
	DurationMs       int64              `json:"durationMs,omitempty"`
	Error            *GraphRuntimeError `json:"error,omitempty"`
	BlockedReason    string             `json:"blockedReason,omitempty"`
}

type GraphInstanceStatus

type GraphInstanceStatus string
const (
	GraphInstanceStatusPending     GraphInstanceStatus = "pending"
	GraphInstanceStatusRunning     GraphInstanceStatus = "running"
	GraphInstanceStatusSucceeded   GraphInstanceStatus = "succeeded"
	GraphInstanceStatusFailed      GraphInstanceStatus = "failed"
	GraphInstanceStatusSkipped     GraphInstanceStatus = "skipped"
	GraphInstanceStatusInterrupted GraphInstanceStatus = "interrupted"
	// GraphInstanceStatusAwaitingInput marks a clarify instance that ran its turn
	// and is holding its out-edges, waiting for the user to discuss in its session
	// and continue. It is a non-terminal hold (not resettable on resume): a
	// continue finalizes it (capture结论 → succeeded → resolve out-edges).
	GraphInstanceStatusAwaitingInput GraphInstanceStatus = "awaitingInput"
)

type GraphListWorkflowsResponse

type GraphListWorkflowsResponse struct {
	Workflows []GraphWorkflowSummary `json:"workflows"`
	// Warnings surfaces workflow files that could not be read or parsed during a
	// list. They are skipped from Workflows (so one bad file does not break the
	// whole page) but reported here so the UI can show the offending file and the
	// raw error instead of letting the workflow silently vanish from the list.
	Warnings []GraphWorkflowWarning `json:"warnings,omitempty"`
}

type GraphLoopIteration

type GraphLoopIteration struct {
	LoopNodeID string `json:"loopNodeId"`
	Index      int    `json:"index"`
}

type GraphLoopMode

type GraphLoopMode string
const (
	GraphLoopModeFixed GraphLoopMode = "fixed"
	GraphLoopModeUntil GraphLoopMode = "until"
)

type GraphLoopState

type GraphLoopState struct {
	LoopNodeID       string            `json:"loopNodeId"`
	InstanceKey      GraphInstanceKey  `json:"instanceKey"`
	CurrentIteration int               `json:"currentIteration"`
	Completed        bool              `json:"completed"`
	Variables        map[string]string `json:"variables,omitempty"`
	VariableWriters  map[string]string `json:"variableWriters,omitempty"`
	// EntrySession is the session flowing into the current round (the loop
	// scope's roundEntrySession). Persisted so resume can rebuild the in-flight
	// round's inflow session and a session-inheriting first body Agent forks the
	// correct upstream session rather than minting a new one.
	EntrySession string `json:"entrySession,omitempty"`
}

type GraphNode

type GraphNode struct {
	ID       string            `json:"id"`
	Type     GraphNodeType     `json:"type"`
	Title    string            `json:"title,omitempty"`
	ParentID string            `json:"parentId,omitempty"`
	Config   GraphNodeConfig   `json:"config,omitempty"`
	Layout   GraphNodeLayout   `json:"layout,omitempty"`
	Metadata map[string]string `json:"metadata,omitempty"`
}

type GraphNodeConfig

type GraphNodeConfig struct {
	Script             string               `json:"script,omitempty"`
	Prompt             string               `json:"prompt,omitempty"`
	AgentType          string               `json:"agentType,omitempty"`
	ModelID            string               `json:"modelId,omitempty"`
	ACPMode            string               `json:"acpMode,omitempty"`
	ACPThoughtLevel    string               `json:"acpThoughtLevel,omitempty"`
	SessionStrategy    GraphSessionStrategy `json:"sessionStrategy,omitempty"`
	OutputVariables    []string             `json:"outputVariables,omitempty"`
	LastAssistantAlias string               `json:"lastAssistantAlias,omitempty"`
	TimeoutSeconds     *int                 `json:"timeoutSeconds,omitempty"`
	Condition          string               `json:"condition,omitempty"`
	LoopMode           GraphLoopMode        `json:"loopMode,omitempty"`
	FixedCount         int                  `json:"fixedCount,omitempty"`
	UntilCondition     string               `json:"untilCondition,omitempty"`
	MaxIterations      int                  `json:"maxIterations,omitempty"`
	// HookScript is a side-effect shell script run AFTER a node completes
	// (notifications / logging / marking). Used by Prompt nodes (run when
	// non-empty) and by End nodes whose EndHookMode is "custom". It never
	// produces variables, never changes node status, and never fails the run —
	// a non-zero exit / timeout is logged and ignored.
	HookScript string `json:"hookScript,omitempty"`
	// EndHookMode selects an End node's hook behavior: "default" runs the global
	// settings script (settings.EndHookScript), "custom" runs this node's HookScript,
	// "off" disables it. Empty is treated as "default". End nodes only.
	EndHookMode GraphEndHookMode `json:"endHookMode,omitempty"`
}

type GraphNodeLayout

type GraphNodeLayout struct {
	X      float64 `json:"x"`
	Y      float64 `json:"y"`
	Width  float64 `json:"width,omitempty"`
	Height float64 `json:"height,omitempty"`
}

type GraphNodeType

type GraphNodeType string
const (
	GraphNodeTypeStart   GraphNodeType = "start"
	GraphNodeTypeEnd     GraphNodeType = "end"
	GraphNodeTypeShell   GraphNodeType = "shell"
	GraphNodeTypePrompt  GraphNodeType = "prompt"
	GraphNodeTypeClarify GraphNodeType = "clarify"
	GraphNodeTypeIfElse  GraphNodeType = "ifElse"
	GraphNodeTypeLoop    GraphNodeType = "loop"
)

type GraphProgress

type GraphProgress struct {
	TotalCount       int                           `json:"totalCount"`
	CompletedCount   int                           `json:"completedCount"`
	FailedCount      int                           `json:"failedCount"`
	SkippedCount     int                           `json:"skippedCount"`
	InterruptedCount int                           `json:"interruptedCount"`
	RunningCount     int                           `json:"runningCount"`
	CurrentKeys      []GraphInstanceKey            `json:"currentKeys,omitempty"`
	Instances        map[string]GraphInstanceState `json:"instances,omitempty"`
	LastError        string                        `json:"lastError,omitempty"`
}

type GraphReadyBatch

type GraphReadyBatch struct {
	ID        string                           `json:"id"`
	Version   int                              `json:"version"`
	Members   map[string]GraphReadyBatchMember `json:"members"`
	CreatedAt int64                            `json:"createdAt"`
}

type GraphReadyBatchMember

type GraphReadyBatchMember struct {
	Key    GraphInstanceKey    `json:"key"`
	Status GraphInstanceStatus `json:"status"`
}

type GraphResumeState

type GraphResumeState struct {
	ReadyKeys           []GraphInstanceKey             `json:"readyKeys,omitempty"`
	EdgeStates          map[string]GraphEdgeState      `json:"edgeStates,omitempty"`
	LoopState           map[string]GraphLoopState      `json:"loopState,omitempty"`
	VariablesByKey      map[string]map[string]string   `json:"variablesByKey,omitempty"`
	SessionLineageByKey map[string]GraphSessionLineage `json:"sessionLineageByKey,omitempty"`
	FrozenBatch         *GraphReadyBatch               `json:"frozenBatch,omitempty"`
}

type GraphRun

type GraphRun struct {
	ID             string             `json:"id"`
	WorkflowID     string             `json:"workflowId,omitempty"`
	JobID          string             `json:"jobId"`
	WorkspaceID    string             `json:"workspaceId,omitempty"`
	Status         GraphRunStatus     `json:"status"`
	BaseSnapshot   GraphRunSnapshot   `json:"baseSnapshot"`
	Versions       []GraphRunVersion  `json:"versions,omitempty"`
	Progress       *GraphProgress     `json:"progress,omitempty"`
	Resume         *GraphResumeState  `json:"resume,omitempty"`
	CurrentVersion int                `json:"currentVersion"`
	StartedAt      int64              `json:"startedAt,omitempty"`
	FinishedAt     int64              `json:"finishedAt,omitempty"`
	CreatedAt      time.Time          `json:"createdAt"`
	UpdatedAt      time.Time          `json:"updatedAt"`
	LastError      *GraphRuntimeError `json:"lastError,omitempty"`
	// ArchivedInstances preserves instances that a resume reset removed from the
	// live instance set but that carried a session (their conversation still
	// exists on disk). Resume drops failed/interrupted instances — and wholesale
	// resets every instance inside a touched loop, including already-succeeded
	// siblings — so without this the Chat session sidebar (which derives its list
	// from live instances) would lose those prior-attempt conversations the
	// instant a run is resumed. Keyed by instance-key string; accumulates across
	// resumes. Live instances always take precedence when a key reappears.
	ArchivedInstances map[string]GraphInstanceState `json:"archivedInstances,omitempty"`
	// RetryInstanceVersions preserves the execution version selected before an
	// instance was reset for retry/resume, including failures that happened
	// before a session was created. The next dispatch uses the same version so
	// an Agent revision cannot change silently during recovery.
	RetryInstanceVersions map[string]int `json:"retryInstanceVersions,omitempty"`
}

type GraphRunActionRequest

type GraphRunActionRequest struct {
	Reason string `json:"reason,omitempty"`
}

type GraphRunConfig

type GraphRunConfig struct {
	ConcurrencyLimit      int   `json:"concurrencyLimit,omitempty"`
	DefaultNodeTimeoutSec int   `json:"defaultNodeTimeoutSec,omitempty"`
	JobTimeoutSec         int   `json:"jobTimeoutSec,omitempty"`
	DefaultLoopMaxIters   int   `json:"defaultLoopMaxIters,omitempty"`
	InstanceLimit         int   `json:"instanceLimit,omitempty"`
	SnapshotByteLimit     int64 `json:"snapshotByteLimit,omitempty"`
}

type GraphRunEventsResponse

type GraphRunEventsResponse struct {
	Events    []GraphEvent `json:"events"`
	NextLine  int          `json:"nextLine"`
	LastEvent string       `json:"lastEventId,omitempty"`
}

type GraphRunResponse

type GraphRunResponse struct {
	Run    *GraphRun              `json:"run,omitempty"`
	Errors []GraphValidationError `json:"errors,omitempty"`
}

type GraphRunSnapshot

type GraphRunSnapshot struct {
	WorkflowID     string                        `json:"workflowId,omitempty"`
	WorkflowName   string                        `json:"workflowName,omitempty"`
	Config         GraphConfig                   `json:"config"`
	ModelSnapshots map[string]string             `json:"modelSnapshots,omitempty"`
	AgentSnapshots map[string]GraphAgentSnapshot `json:"agentSnapshots,omitempty"`
	CapturedAt     int64                         `json:"capturedAt"`
}

type GraphRunStatus

type GraphRunStatus string
const (
	GraphRunStatusPending      GraphRunStatus = "pending"
	GraphRunStatusRunning      GraphRunStatus = "running"
	GraphRunStatusCompleted    GraphRunStatus = "completed"
	GraphRunStatusFailed       GraphRunStatus = "failed"
	GraphRunStatusStepStopping GraphRunStatus = "stepStopping"
	GraphRunStatusStepStopped  GraphRunStatus = "stepStopped"
	// Session stops let inherited Agent turns finish before opening a new session.
	GraphRunStatusSessionStopping GraphRunStatus = "sessionStopping"
	GraphRunStatusSessionStopped  GraphRunStatus = "sessionStopped"
	GraphRunStatusStopped         GraphRunStatus = "stopped"
	GraphRunStatusTimedOut        GraphRunStatus = "timedOut"
	GraphRunStatusRecovering      GraphRunStatus = "recovering"
	// GraphRunStatusAwaitingInput is a resumable terminal: a clarify node ran its
	// turn and the run settled here waiting for the user to discuss in its session
	// and then continue. The scheduler has exited (like stopped); the bound
	// Job is non-running so the Chat append-message path accepts new turns. A
	// continue (ContinueRun) finalizes the awaiting clarify instances and resumes.
	GraphRunStatusAwaitingInput GraphRunStatus = "awaitingInput"
)

type GraphRunStatusResponse

type GraphRunStatusResponse struct {
	Run       *GraphRun            `json:"run,omitempty"`
	Progress  *GraphProgress       `json:"progress,omitempty"`
	Instances []GraphInstanceState `json:"instances,omitempty"`
	Edges     []GraphEdgeState     `json:"edges,omitempty"`
	// EventCount is the number of persisted event lines for this run. The
	// client uses it only as the initial SSE resume cursor seed; it never
	// needs the event bodies in the status response (the SSE stream and
	// per-session message history carry those). Lets GetRunStatus stop
	// serialising the whole event log into the status payload.
	EventCount int `json:"eventCount,omitempty"`
	// Agents carries the minimal display projection of the Agents this run
	// actually references (node snapshots across all versions, plus the main
	// session when cheap to reach), keyed by the reference string held by the
	// run. Populated only on public share responses; private clients resolve
	// display info through the agent display-info endpoint.
	Agents map[string]AgentDisplayInfo `json:"agents,omitempty"`
}

type GraphRunVersion

type GraphRunVersion struct {
	Version        int                           `json:"version"`
	Config         GraphConfig                   `json:"config"`
	ModelSnapshots map[string]string             `json:"modelSnapshots,omitempty"`
	AgentSnapshots map[string]GraphAgentSnapshot `json:"agentSnapshots,omitempty"`
	Reason         string                        `json:"reason,omitempty"`
	CreatedAt      int64                         `json:"createdAt"`
	CreatedBy      string                        `json:"createdBy,omitempty"`
}

type GraphRuntimeError

type GraphRuntimeError struct {
	RunID       string            `json:"runId,omitempty"`
	InstanceKey *GraphInstanceKey `json:"instanceKey,omitempty"`
	NodeID      string            `json:"nodeId,omitempty"`
	NodeTitle   string            `json:"nodeTitle,omitempty"`
	NodeType    GraphNodeType     `json:"nodeType,omitempty"`
	Message     string            `json:"message"`
	RetryCount  int               `json:"retryCount,omitempty"`
	CanResume   bool              `json:"canResume"`
	Stdout      string            `json:"stdout,omitempty"`
	Stderr      string            `json:"stderr,omitempty"`
	ExitCode    *int              `json:"exitCode,omitempty"`
	ModelOutput string            `json:"modelOutput,omitempty"`
	Details     map[string]string `json:"details,omitempty"`
}

type GraphSessionLineage

type GraphSessionLineage struct {
	Strategy          GraphSessionStrategy `json:"strategy"`
	SessionID         string               `json:"sessionId,omitempty"`
	ParentSessionID   string               `json:"parentSessionId,omitempty"`
	ParentInstanceKey *GraphInstanceKey    `json:"parentInstanceKey,omitempty"`
}

type GraphSessionStrategy

type GraphSessionStrategy string
const (
	GraphSessionStrategyNew     GraphSessionStrategy = "new"
	GraphSessionStrategyInherit GraphSessionStrategy = "inherit"
)

type GraphValidationError

type GraphValidationError struct {
	Type      GraphValidationErrorType `json:"type"`
	Message   string                   `json:"message"`
	NodeID    string                   `json:"nodeId,omitempty"`
	EdgeID    string                   `json:"edgeId,omitempty"`
	Variable  string                   `json:"variable,omitempty"`
	ConfigKey string                   `json:"configKey,omitempty"`
}

type GraphValidationErrorType

type GraphValidationErrorType string
const (
	GraphValidationErrorTypeStructure GraphValidationErrorType = "structure"
	GraphValidationErrorTypeNode      GraphValidationErrorType = "node"
	GraphValidationErrorTypeEdge      GraphValidationErrorType = "edge"
	GraphValidationErrorTypeVariable  GraphValidationErrorType = "variable"
	GraphValidationErrorTypeConfig    GraphValidationErrorType = "config"
	GraphValidationErrorTypeSession   GraphValidationErrorType = "session"
)

type GraphValidationResponse

type GraphValidationResponse struct {
	Valid  bool                   `json:"valid"`
	Errors []GraphValidationError `json:"errors,omitempty"`
}

type GraphWorkflow

type GraphWorkflow struct {
	ID          string            `json:"id"`
	WorkspaceID string            `json:"workspaceId,omitempty"`
	Name        string            `json:"name"`
	Description string            `json:"description,omitempty"`
	Type        GraphWorkflowType `json:"type,omitempty"`
	Config      GraphConfig       `json:"config"`
	CreatedAt   time.Time         `json:"createdAt"`
	UpdatedAt   time.Time         `json:"updatedAt"`
	Deleted     bool              `json:"deleted,omitempty"`
}

type GraphWorkflowResponse

type GraphWorkflowResponse struct {
	Workflow *GraphWorkflow         `json:"workflow,omitempty"`
	Errors   []GraphValidationError `json:"errors,omitempty"`
}

type GraphWorkflowSummary

type GraphWorkflowSummary struct {
	ID          string            `json:"id"`
	WorkspaceID string            `json:"workspaceId,omitempty"`
	Name        string            `json:"name"`
	Description string            `json:"description,omitempty"`
	Type        GraphWorkflowType `json:"type,omitempty"`
	CreatedAt   time.Time         `json:"createdAt"`
	UpdatedAt   time.Time         `json:"updatedAt"`
	NodeCount   int               `json:"nodeCount"`
	EdgeCount   int               `json:"edgeCount"`
}

type GraphWorkflowType

type GraphWorkflowType string

GraphWorkflowType distinguishes the two workflow libraries: workflows a user hand-authored in the Web UI ("user") versus workflows created/managed by a model through the CLI ("agent"). An empty type on disk (legacy data) is normalized to "user" at read time.

const (
	GraphWorkflowTypeUser  GraphWorkflowType = "user"
	GraphWorkflowTypeAgent GraphWorkflowType = "agent"
)

type GraphWorkflowWarning

type GraphWorkflowWarning struct {
	File  string `json:"file"`
	Error string `json:"error"`
}

GraphWorkflowWarning describes a workflow file that was skipped during a list because it was unreadable or malformed. File is the on-disk path; Error is the full underlying error text (per the repo convention of never hiding errors).

type HistoryMessage

type HistoryMessage struct {
	ID               string           `json:"id"`
	Role             MessageRole      `json:"role"`
	Content          string           `json:"content"`
	ReasoningContent string           `json:"reasoningContent,omitempty"`
	ToolCallID       string           `json:"toolCallId,omitempty"`
	ToolCalls        []ToolCallInfo   `json:"toolCalls,omitempty"`
	ImageUrls        []string         `json:"imageUrls,omitempty"`
	FileAttachments  []FileAttachment `json:"fileAttachments,omitempty"`
	IsShellOutput    bool             `json:"isShellOutput,omitempty"`
	IsThinking       bool             `json:"isThinking,omitempty"`
	// Failed is true for role=tool messages whose stored content carries
	// the "[failed] " prefix. The server detects the prefix once and
	// surfaces this flag so the frontend can paint the tool bubble with
	// the correct error status on history reload without re-parsing the
	// content itself.
	Failed bool `json:"failed,omitempty"`
	// Placeholder is true for role=tool messages the round builder
	// synthesised as a placeholder when a round was flushed without its
	// tool result arriving (cancellation / interruption / superseded).
	// Placeholders have the stored content "[placeholder] <reason>" and
	// are NOT "[failed]". Separate from Failed so the frontend can pick
	// a distinct icon / tooltip — rendering a placeholder as a green
	// "completed" bubble (the pre-fix behaviour) contradicts what the
	// user last saw on-screen before the run was interrupted.
	Placeholder       bool   `json:"placeholder,omitempty"`
	PlaceholderReason string `json:"placeholderReason,omitempty"`
	// Duration tracking timestamps (unix millis)
	StartedAt         int64 `json:"startedAt,omitempty"`
	FinishedAt        int64 `json:"finishedAt,omitempty"`
	ThoughtStartedAt  int64 `json:"thoughtStartedAt,omitempty"`
	ThoughtFinishedAt int64 `json:"thoughtFinishedAt,omitempty"`
}

type IMJobMapping

type IMJobMapping struct {
	Platform    string `json:"platform"`
	ChatID      string `json:"chatId"`
	WorkspaceID string `json:"workspaceId"`
	JobID       string `json:"jobId"`
}

IMJobMapping binds one external chat to its current Quartet workspace and Job. It is a domain model shared by the IM service and persistence layer.

type IMMessage

type IMMessage struct {
	MessageID   string `json:"messageId"`
	Platform    string `json:"platform"`
	ChatID      string `json:"chatId"`
	ChatType    string `json:"chatType"`
	SenderID    string `json:"senderId"`
	MessageType string `json:"messageType"`
	Content     string `json:"content"`
	ReceivedAt  int64  `json:"receivedAt"`
}

func NewIMMessage

func NewIMMessage(platform, messageID, chatID, chatType, senderID, messageType, content string) *IMMessage

type IMSessionAgentConfig

type IMSessionAgentConfig struct {
	AgentID         string `json:"agent_id"`
	ModelID         string `json:"model_id,omitempty"`
	ACPMode         string `json:"acp_mode,omitempty"`
	ACPThoughtLevel string `json:"acp_thought_level,omitempty"`
}

IMSessionAgentConfig is the ACP configuration used when an IM private chat creates or continues an interactive Job.

type InitAdminRequest

type InitAdminRequest struct {
	Username        string `json:"username"`
	DisplayName     string `json:"displayName"`
	Password        string `json:"password"`
	ConfirmPassword string `json:"confirmPassword"`
}

type Job

type Job struct {
	// --- Immutable after creation ---
	ID        string    `json:"id"`
	CreatedAt time.Time `json:"createdAt"`

	// --- Handler-owned ---
	Title      string    `json:"title"`
	UpdatedAt  time.Time `json:"updatedAt"`
	Deleted    bool      `json:"deleted,omitempty"`
	PinnedAt   int64     `json:"pinnedAt,omitempty"` // unix ms; 0 means not pinned
	Mode       JobMode   `json:"mode"`
	Workdir    string    `json:"workdir,omitempty"`
	ShareToken string    `json:"shareToken,omitempty"`
	// ShareShowWorkspaceName controls whether the public share projection may
	// include the workspace's display name. It never permits the workspace ID
	// or workdir to leave the authenticated API.
	ShareShowWorkspaceName bool   `json:"shareShowWorkspaceName,omitempty"`
	TitleGenerationError   string `json:"titleGenerationError,omitempty"`

	// --- Immutable after creation ---
	WorkspaceID    string `json:"workspaceId"`
	ScheduleID     string `json:"scheduleId,omitempty"`
	TimeoutMinutes int    `json:"timeoutMinutes,omitempty"`
	// Initial* preserves the configuration chosen when an interactive Job is
	// created. A Job has no Session yet at that point, so session metadata cannot
	// recover these values for list rendering or the first send after a client
	// reload. Once a Session exists, its metadata remains authoritative.
	InitialAgentID         string `json:"initialAgentId,omitempty"`
	InitialACPMode         string `json:"initialAcpMode,omitempty"`
	InitialACPThoughtLevel string `json:"initialAcpThoughtLevel,omitempty"`

	// --- Run-owned ---
	Status     JobStatus `json:"status"`
	StartedAt  int64     `json:"startedAt,omitempty"`  // unix ms; set when execution begins
	FinishedAt int64     `json:"finishedAt,omitempty"` // unix ms; set when terminal state reached
	// TotalTurnDurationMs is the persisted sum of every interactive turn's
	// server-side wall-clock duration. The active turn is excluded until it
	// reaches a terminal state.
	TotalTurnDurationMs int64    `json:"totalTurnDurationMs"`
	GraphRunID          string   `json:"graphRunId,omitempty"`
	SessionIDs          []string `json:"sessionIds"`
	// GraphSessionIDs lists the sessions opened by Agent nodes of this job's
	// graph run, kept separate from SessionIDs so they never pollute the
	// linear chat/archive semantics of SessionIDs (e.g. the
	// "last entry is the active session" assumption in resolveSessionID, or
	// SessionCount = len(SessionIDs)). It exists purely as an authorization
	// whitelist: an interactive message may target any session in here so a
	// user can keep chatting in a finished graph node's session after the run
	// stops. Graph nodes run concurrently, so order here is non-linear and must
	// not be read as an iteration sequence.
	GraphSessionIDs []string     `json:"graphSessionIds,omitempty"`
	Progress        *JobProgress `json:"progress,omitempty"`

	// LastRunOutcome records the actual outcome of the most recent interactive
	// send. For interactive sends on an
	// already-terminal job, job.Status is the restored prior status while
	// LastRunOutcome reflects what actually happened in the send. Frontends
	// that recover from a missed terminal SSE event should use this field
	// instead of job.Status to finalize in-flight UI state.
	LastRunOutcome RunOutcome `json:"lastRunOutcome,omitempty"`

	// Idempotency metadata is persisted by repository.JobRepo but hidden from
	// ordinary/public Job JSON responses. Message receipts provide durable
	// at-most-once Agent execution; command receipts replay synchronous command
	// results; creation fields make downstream actions such as /new retry-safe.
	ActiveClientMessageID   string                          `json:"-"`
	TurnDurationPending     bool                            `json:"-"`
	ClientMessageReceipts   map[string]ClientMessageReceipt `json:"-"`
	CommandReceipts         map[string]CommandReceipt       `json:"-"`
	MessageQueue            []QueuedJobMessage              `json:"-"`
	MessageQueueVersion     int64                           `json:"-"`
	MessageQueuePaused      bool                            `json:"-"`
	MessageQueuePauseReason string                          `json:"-"`
	CreationClientMessageID string                          `json:"-"`
	CreationPayloadHash     string                          `json:"-"`

	// FirstModelID initially records the model selected for an empty interactive
	// Job, then represents the first non-deleted session's ModelID for listing.
	// Denormalized on the write path so JobList does not
	// need to open every session file (avoids an O(jobs * sessions) I/O hit
	// on the list endpoint). An empty value means "not cached yet" — the
	// lister may lazily fill it and persist.
	FirstModelID string `json:"firstModelId,omitempty"`
}

Job represents a single execution unit: an interactive chat or graph run.

Field ownership model

The in-memory *Job pointer is shared between the handler goroutine and the run goroutine. To prevent data races, fields are split by ownership and ALL access MUST be protected by service.mu:

Immutable after creation (safe to read without lock):

ID, WorkspaceID, CreatedAt, ScheduleID, TimeoutMinutes, InitialAgentID,
InitialACPMode, InitialACPThoughtLevel

Handler-owned (written by handler through targeted service mutators):

Title, Mode, Workdir, ShareToken, ShareShowWorkspaceName, Deleted, PinnedAt, UpdatedAt

Run-owned (written by the run goroutine):

Status, StartedAt, FinishedAt, GraphRunID, Progress, SessionIDs

Creation-initialized and service-maintained state:

FirstModelID, ActiveClientMessageID, ClientMessageReceipts, CommandReceipts,
CreationClientMessageID, CreationPayloadHash

func NewJob

func NewJob(workdir, workspaceID string) *Job

func (*Job) DeepCopy

func (j *Job) DeepCopy() *Job

DeepCopy returns a deep copy of the Job, safe for use across goroutines. When adding new slice/map/pointer fields to Job, update this method accordingly.

type JobCompletedEvent

type JobCompletedEvent struct {
	BaseEvent
	RunOutcome          RunOutcome `json:"runOutcome,omitempty"`
	TotalTurnDurationMs int64      `json:"totalTurnDurationMs"`
}

type JobFailedEvent

type JobFailedEvent struct {
	BaseEvent
	Message             string     `json:"message"`
	RunOutcome          RunOutcome `json:"runOutcome,omitempty"`
	TotalTurnDurationMs int64      `json:"totalTurnDurationMs"`
}

type JobMessageRequest

type JobMessageRequest struct {
	Messages        []RequestMessage `json:"messages,omitempty"`
	ModelID         string           `json:"modelId,omitempty"`
	AgentType       string           `json:"agentType,omitempty"`
	SessionID       string           `json:"sessionId,omitempty"`
	ClientMessageID string           `json:"clientMessageId,omitempty"`
	ACPMode         string           `json:"acpMode,omitempty"`
	ACPThoughtLevel string           `json:"acpThoughtLevel,omitempty"`
	// BypassCommand forces the message to go through the regular Job message
	// flow even when the text starts with a known slash command. Set by the
	// Web home page when it builds a new Job from the user's first input:
	// the home page is a pure "message" surface and never executes commands.
	BypassCommand bool `json:"bypassCommand,omitempty"`
}

type JobMode

type JobMode string
const (
	JobModeInteractive JobMode = "interactive"
	JobModeGraph       JobMode = "graph"
)

type JobObservationEvent

type JobObservationEvent struct {
	EventID            string     `json:"eventId"`
	Job                JobSummary `json:"job"`
	PreviousState      JobStatus  `json:"previousStatus,omitempty"`
	GraphRunID         string     `json:"graphRunId,omitempty"`
	GraphStatus        string     `json:"graphStatus,omitempty"`
	PreviousGraphState string     `json:"previousGraphStatus,omitempty"`
	GraphSessionID     string     `json:"graphSessionId,omitempty"`
	RunOutcome         RunOutcome `json:"runOutcome,omitempty"`
	OccurredAt         int64      `json:"occurredAt"`
}

JobObservationEvent identifies one lifecycle change independently of the Job's current display ordering. EventID is stable across page retries and is suitable for client-side notification de-duplication.

type JobObservationResponse

type JobObservationResponse struct {
	ActiveJobs []JobSummary          `json:"activeJobs"`
	Changes    []JobObservationEvent `json:"changes"`
	Cursor     string                `json:"cursor"`
	HasMore    bool                  `json:"hasMore"`
	Reset      bool                  `json:"reset"`
}

JobObservationResponse is a lightweight, global Job projection for clients that watch lifecycle transitions. ActiveJobs is a complete current snapshot across workspaces; Changes is a stable, cursor-ordered page of mutations. Reset tells a client to establish a fresh baseline instead of replaying the returned state as historical notifications.

type JobProgress

type JobProgress struct {
	// LastError is the most recent failure reason. Persisted so refreshes still
	// surface it.
	LastError string `json:"lastError,omitempty"`
	// PersistWarnings records best-effort persistence failures without clobbering
	// LastError. Persistence warnings describe disk/state divergence, while
	// LastError remains reserved for the user-visible run failure reason.
	PersistWarnings []string `json:"persistWarnings,omitempty"`
}

JobProgress stores durable diagnostics for a Job run. When adding new slice/map/pointer fields, update Job.DeepCopy accordingly.

type JobStartedEvent

type JobStartedEvent struct {
	BaseEvent
}

type JobStatus

type JobStatus string
const (
	JobStatusPending   JobStatus = "pending"
	JobStatusRunning   JobStatus = "running"
	JobStatusCompleted JobStatus = "completed"
	JobStatusFailed    JobStatus = "failed"
	JobStatusStopped   JobStatus = "stopped"
)

type JobStoppedEvent

type JobStoppedEvent struct {
	BaseEvent
	RunOutcome          RunOutcome `json:"runOutcome,omitempty"`
	TotalTurnDurationMs int64      `json:"totalTurnDurationMs"`
}

type JobSummary

type JobSummary struct {
	ID              string    `json:"id"`
	Title           string    `json:"title"`
	AgentID         string    `json:"agentId,omitempty"`
	ModelID         string    `json:"modelId,omitempty"`
	ACPMode         string    `json:"acpMode,omitempty"`
	ACPThoughtLevel string    `json:"acpThoughtLevel,omitempty"`
	Status          JobStatus `json:"status"`
	Mode            JobMode   `json:"mode"`
	WorkspaceID     string    `json:"workspaceId,omitempty"`
	Workdir         string    `json:"workdir,omitempty"`
	CreatedAt       int64     `json:"createdAt"`
	UpdatedAt       int64     `json:"updatedAt"`
	PinnedAt        int64     `json:"pinnedAt,omitempty"`
	SessionCount    int       `json:"sessionCount"`
	ScheduleID      string    `json:"scheduleId,omitempty"`
	ShareToken      string    `json:"shareToken,omitempty"`
}

JobSummary is the compact DTO used by the job list endpoint. It deliberately excludes the job's large nested payloads (config trees, per-step result arrays, which can each be hundreds of KB on long-lived jobs) so the list stays cheap to serialize and transfer. Callers that need those fields must hit the detail endpoint (GET /api/v1/job/:jobId) which returns the full Job.

type JobViewerStateRequest

type JobViewerStateRequest struct {
	ViewerID string `json:"viewerId"`
	Visible  bool   `json:"visible"`
}

JobViewerStateRequest reports whether a Job's live event stream is actually on screen. A browser keeps an SSE connection alive in a hidden tab, so the connection alone cannot tell "watching" from "left open" — the client posts this on visibility changes. ViewerID is the per-connection id the client passed when it opened the stream.

type KimiUsage

type KimiUsage struct {
	Version       string       `json:"version,omitempty"`        // kimi CLI version, e.g. "v0.1.0"
	ParallelLimit int64        `json:"parallel_limit,omitempty"` // max concurrent sessions
	Weekly        *UsageWindow `json:"weekly,omitempty"`         // 7-day quota (the API's "usage" field)
	FiveHour      *UsageWindow `json:"five_hour,omitempty"`      // 5-hour quota (limits[0].detail)
	Total         *UsageWindow `json:"total,omitempty"`          // cumulative quota (totalQuota), no reset
}

KimiUsage is the Kimi Code plan snapshot from the kimi coding usages endpoint: the kimi CLI version plus the three quota windows. Weekly and FiveHour are rate-limit windows with a reset time; Total is the cumulative quota pool (e.g. purchased credits) and has no reset. A window is nil when the API does not report a usable limit for it.

type ListJobsResponse

type ListJobsResponse struct {
	Jobs       []JobSummary `json:"jobs"`
	NextCursor string       `json:"nextCursor,omitempty"`
	HasMore    bool         `json:"hasMore"`
	Version    int64        `json:"version,omitempty"`
	// DailyStats is keyed by YYYY-MM-DD and carries the per-day total of
	// duration (ms) and turn count for the workspace this list belongs
	// to. Only the days that appear in the current page are populated;
	// days with no data are absent (the frontend treats absence as "no
	// statistics").
	DailyStats map[string]DailyStatsEntry `json:"dailyStats,omitempty"`
}

type ListOrphanMessagePresetsResponse

type ListOrphanMessagePresetsResponse struct {
	Code    int                      `json:"code"`
	Configs []OrphanMessagePreset    `json:"configs"`
	Errors  []MessagePresetLoadError `json:"errors,omitempty"`
}

type ListSchedulesResponse

type ListSchedulesResponse struct {
	Schedules []ScheduleInfo `json:"schedules"`
}

type ListSessionsResponse

type ListSessionsResponse struct {
	Sessions []SessionInfo `json:"sessions"`
}

type ListWorkspacesResponse

type ListWorkspacesResponse struct {
	Workspaces []WorkspaceInfo `json:"workspaces"`
}

type LoginRequest

type LoginRequest struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

type MessagePageInfo

type MessagePageInfo struct {
	HasMoreBefore bool   `json:"hasMoreBefore"`
	BeforeCursor  string `json:"beforeCursor,omitempty"`
}

type MessagePreset

type MessagePreset struct {
	ID      string `json:"id"`
	Name    string `json:"name,omitempty"`
	Content string `json:"content"`
}

type MessagePresetConfig

type MessagePresetConfig struct {
	SchemaVersion    int             `json:"schemaVersion"`
	WorkspaceID      string          `json:"workspaceId,omitempty"`
	WorkspaceTitle   string          `json:"workspaceTitle,omitempty"`
	WorkspaceWorkdir string          `json:"workspaceWorkdir,omitempty"`
	Messages         []MessagePreset `json:"messages"`
}

type MessagePresetLoadError

type MessagePresetLoadError struct {
	Scope string `json:"scope"`
	File  string `json:"file"`
	Error string `json:"error"`
}

type MessagePresetScopeResponse

type MessagePresetScopeResponse struct {
	Code     int                 `json:"code"`
	Revision string              `json:"revision"`
	Config   MessagePresetConfig `json:"config"`
}

type MessageQueueSnapshot

type MessageQueueSnapshot struct {
	JobID        string             `json:"jobId"`
	Version      int64              `json:"version"`
	Paused       bool               `json:"paused"`
	PauseReason  string             `json:"pauseReason,omitempty"`
	WillContinue bool               `json:"willContinue"`
	Active       *QueuedJobMessage  `json:"active,omitempty"`
	Items        []QueuedJobMessage `json:"items"`
}

type MessageRole

type MessageRole string
const (
	MessageRoleUser      MessageRole = "user"
	MessageRoleAssistant MessageRole = "assistant"
	MessageRoleSystem    MessageRole = "system"
	MessageRoleTool      MessageRole = "tool"
	MessageRoleCustom    MessageRole = "custom"
)

type ModelInfoACP

type ModelInfoACP struct {
	Description *string `json:"description,omitempty"`
	ModelId     string  `json:"modelId"`
	Name        string  `json:"name"`
}

type OrphanMessagePreset

type OrphanMessagePreset struct {
	Revision string              `json:"revision"`
	Config   MessagePresetConfig `json:"config"`
}

type PermissionInfo

type PermissionInfo struct {
	ID          string `json:"id"`
	Description string `json:"description"`
}

type ProjectToolsInstallResponse

type ProjectToolsInstallResponse struct {
	Code   int                        `json:"code"`
	Result *ProjectToolsInstallResult `json:"result"`
}

type ProjectToolsInstallResult

type ProjectToolsInstallResult struct {
	Command    string `json:"command"`
	Output     string `json:"output"`
	ExitCode   int    `json:"exit_code"`
	DurationMs int64  `json:"duration_ms"`
}

ProjectToolsInstallResult is the complete result of installing the repository-owned quartet-cli binary and all skills shipped by this project.

type PublicGetMessagesResponse

type PublicGetMessagesResponse struct {
	Type     string                      `json:"type,omitempty"`
	Messages []HistoryMessage            `json:"messages"`
	Agents   map[string]AgentDisplayInfo `json:"agents,omitempty"`
	Page     *MessagePageInfo            `json:"page,omitempty"`
}

PublicGetMessagesResponse contains only the conversation and the Agent identity needed to render it. Runtime selections, token usage and workdir remain private even when the Job itself is shared.

type PublicJobProgress

type PublicJobProgress struct {
	LastError string `json:"lastError,omitempty"`
}

type PublicJobResponse

type PublicJobResponse struct {
	ID                  string                      `json:"id"`
	Title               string                      `json:"title"`
	Mode                JobMode                     `json:"mode"`
	Status              JobStatus                   `json:"status"`
	StartedAt           int64                       `json:"startedAt,omitempty"`
	FinishedAt          int64                       `json:"finishedAt,omitempty"`
	TotalTurnDurationMs int64                       `json:"totalTurnDurationMs,omitempty"`
	GraphRunID          string                      `json:"graphRunId,omitempty"`
	SessionIDs          []string                    `json:"sessionIds"`
	Progress            *PublicJobProgress          `json:"progress,omitempty"`
	LastRunOutcome      RunOutcome                  `json:"lastRunOutcome,omitempty"`
	LastEventSeq        uint64                      `json:"lastEventSeq"`
	ServerTime          int64                       `json:"serverTime"`
	Agents              map[string]AgentDisplayInfo `json:"agents,omitempty"`
	ShareContext        PublicShareContext          `json:"shareContext"`
}

PublicJobResponse is the deliberately small snapshot served to anonymous share viewers. Keep this separate from Job: adding an internal Job field must never make that field public by accident.

type PublicShareContext

type PublicShareContext struct {
	WorkspaceName string `json:"workspaceName,omitempty"`
}

type QoderUsage

type QoderUsage struct {
	Version       string  `json:"version,omitempty"`    // qoderclicn CLI version, e.g. "v1.0.48"
	PlanType      string  `json:"plan_type,omitempty"`  // API userType, e.g. "personal_professional_trial"
	Unit          string  `json:"unit,omitempty"`       // quota unit, always "credits"
	Total         float64 `json:"total"`                // total credits in the pool
	Used          float64 `json:"used"`                 // credits consumed
	Remaining     float64 `json:"remaining"`            // credits left
	UsedPercent   float64 `json:"used_percent"`         // 0–100
	ExpiresAt     int64   `json:"expires_at,omitempty"` // unix seconds when the plan/quota expires
	QuotaExceeded bool    `json:"quota_exceeded"`       // true when the pool is exhausted
}

QoderUsage is the QoderCN credits quota snapshot from the openapi quota endpoint. Credits are a single cumulative pool (no rate-limit window reset); the pool expires wholesale at ExpiresAt (unix ms from the API, stored here as unix seconds). UsedPercent mirrors the API's totalUsagePercentage (0–100).

type QueuedJobMessage

type QueuedJobMessage struct {
	ID              string             `json:"id"`
	Messages        []RequestMessage   `json:"messages"`
	SessionID       string             `json:"sessionId,omitempty"`
	AgentType       string             `json:"agentType,omitempty"`
	AgentID         string             `json:"agentId,omitempty"`
	AgentRevision   string             `json:"agentRevision,omitempty"`
	ModelID         string             `json:"modelId,omitempty"`
	ACPMode         string             `json:"acpMode,omitempty"`
	ACPThoughtLevel string             `json:"acpThoughtLevel,omitempty"`
	BypassCommand   bool               `json:"bypassCommand,omitempty"`
	Source          string             `json:"source,omitempty"`
	ActorID         string             `json:"actorId,omitempty"`
	State           QueuedMessageState `json:"state"`
	Error           string             `json:"error,omitempty"`
	CreatedAt       int64              `json:"createdAt"`
	UpdatedAt       int64              `json:"updatedAt"`
}

QueuedJobMessage is a durable, not-yet-started interactive message. It is hidden from ordinary Job JSON and exposed only through the queue API.

type QueuedMessageState

type QueuedMessageState string
const (
	QueuedMessageStateQueued     QueuedMessageState = "queued"
	QueuedMessageStateBlocked    QueuedMessageState = "blocked"
	QueuedMessageStateProcessing QueuedMessageState = "processing"
)

type RebindMessagePresetRequest

type RebindMessagePresetRequest struct {
	Revision          string `json:"revision"`
	TargetWorkspaceID string `json:"targetWorkspaceId"`
}

type ReorderWorkspacesRequest

type ReorderWorkspacesRequest struct {
	WorkspaceIDs []string `json:"workspaceIds"`
}

type RequestMessage

type RequestMessage struct {
	ID              string           `json:"id"`
	Type            string           `json:"type"`
	Content         string           `json:"content"`
	Timestamp       int64            `json:"timestamp"`
	Role            string           `json:"role"`
	ImageUrls       []string         `json:"imageUrls,omitempty"`
	FileAttachments []FileAttachment `json:"fileAttachments,omitempty"`
}

func (RequestMessage) AgentContent

func (m RequestMessage) AgentContent() string

AgentContent returns the text prompt sent through ACP. Attachments remain structured on RequestMessage for clients and history, while their local paths are also made explicit in the prompt so filesystem-capable Agents can consume them without requiring a binary ACP transport.

func (RequestMessage) FileAttachmentPromptPrefix

func (m RequestMessage) FileAttachmentPromptPrefix() string

FileAttachmentPromptPrefix returns the exact prefix AgentContent emits for files. History projection uses it only as a fallback for records that have structured attachment metadata but predate original_user_content.

type ResetPasswordRequest

type ResetPasswordRequest struct {
	Version  int64  `json:"version"`
	Password string `json:"password"`
}

type ResolveAgentDisplayInfoRequest

type ResolveAgentDisplayInfoRequest struct {
	IDs []string `json:"ids"`
}

type ResolveAgentDisplayInfoResponse

type ResolveAgentDisplayInfoResponse struct {
	Agents map[string]AgentDisplayInfo `json:"agents"`
}

type Role

type Role struct {
	ID          string    `json:"id"`
	Name        string    `json:"name"`
	Description string    `json:"description,omitempty"`
	Permissions []string  `json:"permissions"`
	BuiltIn     bool      `json:"builtIn"`
	Version     int64     `json:"version"`
	CreatedAt   time.Time `json:"createdAt"`
	UpdatedAt   time.Time `json:"updatedAt"`
	CreatedBy   string    `json:"createdBy"`
	UpdatedBy   string    `json:"updatedBy"`
}

type RunErrorEvent

type RunErrorEvent struct {
	BaseEvent
	Message string `json:"message"`
	Code    string `json:"code,omitempty"`
}

type RunFinishedEvent

type RunFinishedEvent struct {
	BaseEvent
}

type RunOutcome

type RunOutcome string

RunOutcome describes the actual result of the run that just ended (an interactive send). Distinct from the job's overall status because an interactive send on an already-terminal job restores the prior status on the Job record — but the run itself may have completed/stopped/failed independently. Consumers that want to finalise in-flight UI state (tool bubbles, streaming messages) should use RunOutcome; consumers that display job-level status should use the event type as before.

const (
	RunOutcomeCompleted RunOutcome = "completed"
	RunOutcomeStopped   RunOutcome = "stopped"
	RunOutcomeFailed    RunOutcome = "failed"
)

type RunStartedEvent

type RunStartedEvent struct {
	BaseEvent
	// ClientMessageID identifies the interactive user message that opened this
	// round. Empty for non-interactive runs. Clients use it to reconcile their
	// optimistic user bubble as soon as the round starts.
	ClientMessageID string `json:"clientMessageId,omitempty"`
}

type SaveEinoSystemPromptRequest

type SaveEinoSystemPromptRequest struct {
	SystemPrompt string `json:"system_prompt"`
}

SaveEinoSystemPromptRequest updates eino-cli's system prompt.

type SaveMessagePresetScopeRequest

type SaveMessagePresetScopeRequest struct {
	Revision string          `json:"revision"`
	Messages []MessagePreset `json:"messages"`
}

type SavePromptRequest

type SavePromptRequest struct {
	Key    string `json:"key"`
	Prompt string `json:"prompt"`
}

type SavePromptResponse

type SavePromptResponse struct {
	Code int `json:"code"`
}

type ScheduleDefinition

type ScheduleDefinition struct {
	ID              string    `json:"id"`
	Name            string    `json:"name"`
	CronExpr        string    `json:"cronExpr"`
	CreatedAt       time.Time `json:"createdAt"`
	UpdatedAt       time.Time `json:"updatedAt"`
	GraphWorkflowID string    `json:"graphWorkflowId,omitempty"`
	WorkspaceID     string    `json:"workspaceId,omitempty"`
	Workdir         string    `json:"workdir,omitempty"`
	MaxConcurrent   int       `json:"maxConcurrent,omitempty"`
	Timeout         int       `json:"timeout,omitempty"`
}

ScheduleDefinition is the human-maintained portion stored under quartet/config/schedules. Scheduler executions never modify this shape.

type ScheduleInfo

type ScheduleInfo struct {
	ID   string `json:"id"`
	Name string `json:"name"`
	// Enabled is the effective activation state on the responding machine.
	Enabled          bool      `json:"enabled"`
	CronExpr         string    `json:"cronExpr"`
	GraphWorkflowID  string    `json:"graphWorkflowId,omitempty"`
	WorkspaceID      string    `json:"workspaceId,omitempty"`
	Workdir          string    `json:"workdir,omitempty"`
	MaxConcurrent    int       `json:"maxConcurrent,omitempty"`
	Timeout          int       `json:"timeout,omitempty"`
	LastRunAt        *int64    `json:"lastRunAt,omitempty"`
	LastRunJobID     string    `json:"lastRunJobID,omitempty"`
	LastStatus       JobStatus `json:"lastStatus,omitempty"`
	LastTriggerError string    `json:"lastTriggerError,omitempty"`
	NextRunAt        *int64    `json:"nextRunAt,omitempty"`
	RunCount         int       `json:"runCount"`
	CreatedAt        int64     `json:"createdAt"`
	UpdatedAt        int64     `json:"updatedAt"`
}

type ScheduleState

type ScheduleState struct {
	ID               string     `json:"id"`
	Enabled          bool       `json:"enabled"`
	LastRunAt        *time.Time `json:"lastRunAt,omitempty"`
	LastRunJobID     string     `json:"lastRunJobID,omitempty"`
	LastStatus       JobStatus  `json:"lastStatus,omitempty"`
	LastTriggerError string     `json:"lastTriggerError,omitempty"`
	NextRunAt        *time.Time `json:"nextRunAt,omitempty"`
	RunCount         int        `json:"runCount"`
	UpdatedAt        time.Time  `json:"updatedAt"`
}

ScheduleState is the machine-local portion stored under var/quartet/state/schedules. Enabled deliberately lives here instead of in the Git-managed definition so each machine can activate the same schedule independently. A missing state file means disabled and not run yet.

type ScheduledTask

type ScheduledTask struct {
	ID   string `json:"id"`
	Name string `json:"name"`
	// Enabled is the effective activation state on the current machine.
	Enabled   bool      `json:"enabled"`
	CronExpr  string    `json:"cronExpr"`
	CreatedAt time.Time `json:"createdAt"`
	UpdatedAt time.Time `json:"updatedAt"`

	// GraphWorkflowID references the saved Graph workflow this schedule runs.
	// The trigger re-reads the live workflow at run time, so workflow schedules
	// keep no config snapshot.
	GraphWorkflowID string `json:"graphWorkflowId,omitempty"`

	// Workspace & working directory. WorkspaceID is optional: scheduled tasks
	// are conceptually independent automation rules and do not have to belong
	// to a workspace. Empty means the trigger falls back to the default
	// workspace at run time.
	WorkspaceID string `json:"workspaceId,omitempty"`
	Workdir     string `json:"workdir,omitempty"`

	// Execution policy
	MaxConcurrent int `json:"maxConcurrent,omitempty"` // default 1: skip trigger if previous run still active
	Timeout       int `json:"timeout,omitempty"`       // minutes, 0 = unlimited

	// Run status (updated by scheduler)
	LastRunAt    *time.Time `json:"lastRunAt,omitempty"`
	LastRunJobID string     `json:"lastRunJobID,omitempty"`
	LastStatus   JobStatus  `json:"lastStatus,omitempty"`
	// LastTriggerError stores the full error text for failures that happen while
	// trying to create/start the scheduled run, before the run can report its own
	// terminal error.
	LastTriggerError string     `json:"lastTriggerError,omitempty"`
	NextRunAt        *time.Time `json:"nextRunAt,omitempty"`
	RunCount         int        `json:"runCount"`
	StateUpdatedAt   time.Time  `json:"-"`
}

type Session

type Session struct {
	ID              string                 `json:"id"`
	Title           string                 `json:"title"`
	CreatedAt       time.Time              `json:"created_at"`
	UpdatedAt       time.Time              `json:"updated_at"`
	Deleted         bool                   `json:"deleted,omitempty"`
	ModelID         string                 `json:"model_id,omitempty"`
	Type            string                 `json:"type,omitempty"` // legacy ACP serve command / runtime key
	AgentID         string                 `json:"agent_id,omitempty"`
	AgentRevision   string                 `json:"agent_revision,omitempty"`
	AgentRuntimeKey string                 `json:"agent_runtime_key,omitempty"`
	AgentDefinition AgentRuntimeDefinition `json:"agent_definition,omitempty"`
	Workdir         string                 `json:"workdir,omitempty"`      // working directory for ACP agents
	JobID           string                 `json:"job_id,omitempty"`       // associated job
	WorkspaceID     string                 `json:"workspace_id,omitempty"` // associated workspace
	ACPSessionID    string                 `json:"acp_session_id,omitempty"`
	ACPMode         string                 `json:"acp_mode,omitempty"`
	// ACPThoughtLevel is the thought_level config selection (e.g. "high")
	// last applied to the ACP subprocess session. Like ACPMode it is
	// persisted so a Run re-applies it after reconnect / restart.
	ACPThoughtLevel string `json:"acp_thought_level,omitempty"`
	// ACPLastSyncedMessageCount and ACPLastSyncedMessageHash record the
	// state of messages.jsonl at the end of the most recent ACP Run on
	// this session. Used by the ACP agent to detect cross-path drift —
	// if either field disagrees with the on-disk fingerprint at the
	// start of a new Run (e.g. a late ReplacePlaceholderToolResult rewrote
	// a row in place), the
	// subprocess's internal conversation state no longer matches disk
	// and the ACPSessionID is replaced with a fresh one rather than
	// continuing to prompt a stale view.
	//
	// Hash is the primary signal — count alone misses in-place row
	// rewrites that keep the row count stable but change content. Count
	// stays for diagnostic logging and so the persisted state still
	// carries a human-readable "we were at N messages" datum that's
	// useful even without a way to interpret the hash.
	ACPLastSyncedMessageCount int    `json:"acp_last_synced_message_count,omitempty"`
	ACPLastSyncedMessageHash  string `json:"acp_last_synced_message_hash,omitempty"`
}

func NewSession

func NewSession() *Session

type SessionInfo

type SessionInfo struct {
	ID        string `json:"id"`
	Title     string `json:"title"`
	CreatedAt int64  `json:"createdAt"`
	UpdatedAt int64  `json:"updatedAt"`
}

type SessionModeState

type SessionModeState struct {
	AvailableModes []ACPSessionMode `json:"availableModes"`
	CurrentModeId  string           `json:"currentModeId"`
}

type SessionModelState

type SessionModelState struct {
	AvailableModels []ModelInfoACP `json:"availableModels"`
	CurrentModelId  string         `json:"currentModelId"`
}

type SessionOverrides

type SessionOverrides struct {
	AgentType       string
	AgentBinding    *AgentRuntimeBinding
	ModelID         string
	ACPMode         string
	ACPThoughtLevel string
}

SessionOverrides carries optional agent/model overrides for session creation. Zero/empty values mean "use job-level defaults".

type SessionThoughtLevelState

type SessionThoughtLevelState struct {
	AvailableThoughtLevels []ACPThoughtLevel `json:"availableThoughtLevels"`
	CurrentThoughtLevelId  string            `json:"currentThoughtLevelId"`
	// ConfigId is the ACP config option id used to set this value (e.g.
	// "reasoning_effort"). Unlike mode, thought_level has no dedicated RPC,
	// so the setter goes through SetSessionConfigOption with this id.
	ConfigId string `json:"configId,omitempty"`
}

type SessionTokenUsageResponse

type SessionTokenUsageResponse struct {
	TokenUsage TokenUsage `json:"tokenUsage"`
}

type SetACPConfigRequest

type SetACPConfigRequest struct {
	SessionID    string          `json:"sessionId,omitempty"`
	AgentType    string          `json:"agentType,omitempty"`
	Target       ACPConfigTarget `json:"target"`
	Model        string          `json:"model,omitempty"`
	Mode         string          `json:"mode,omitempty"`
	ThoughtLevel string          `json:"thoughtLevel,omitempty"`
}

SetACPConfigRequest switches an ACP selector (model / mode / thought_level) and asks for the refreshed selector lists back. When SessionID is set the switch applies to that session's live agent; otherwise it is a Home (session-less) cache selection on AgentType. Cached model-linked state is returned immediately and refreshed asynchronously; cache misses probe synchronously.

Model / Mode / ThoughtLevel carry the current selection. For the session path only the Target's value is applied to the live agent.

type SetACPConfigResponse

type SetACPConfigResponse struct {
	Code int `json:"code"`
	ACPConfigState
}

SetACPConfigResponse returns the refreshed selector lists after a switch. Each list is populated only when the ACP response carried a refreshed list for it (see ACPConfigState); the frontend keeps its current values for nil lists.

type Settings

type Settings struct {
	Username  string `json:"username"`
	AvatarURL string `json:"avatar_url"`

	// Language is the interface language preference ("zh" or "en"). It is
	// persisted so every client that reaches this instance shares one choice
	// instead of each browser origin keeping its own.
	Language string `json:"language,omitempty"`

	TitleGenerationAgent   *AgentRoleConfig            `json:"title_generation_agent,omitempty"`
	GroupReplyAgent        *AgentRoleConfig            `json:"group_reply_agent,omitempty"`
	IMSessionAgent         *IMSessionAgentConfig       `json:"im_session_agent,omitempty"`
	ACPEnvVars             map[string][]ACPEnvVarEntry `json:"acp_env_vars,omitempty"`
	ACPEnvVersions         map[string]int64            `json:"acp_env_versions,omitempty"`
	AgentPrefs             map[string]AgentPrefs       `json:"agent_prefs,omitempty"`
	LarkAppID              string                      `json:"lark_app_id,omitempty"`
	LarkAppSecret          string                      `json:"lark_app_secret,omitempty"`
	LarkIMAdminSenderID    string                      `json:"lark_im_admin_sender_id,omitempty"`
	LarkIMSophiaSenderID   string                      `json:"lark_im_sophia_sender_id,omitempty"`
	IMWorkspaceID          string                      `json:"im_workspace_id,omitempty"`
	WeChatAdminIDs         []string                    `json:"wechat_admin_ids,omitempty"`
	EndHookScript          string                      `json:"end_hook_script,omitempty"`
	EndHookSkipWhenWatched *bool                       `json:"end_hook_skip_when_watched,omitempty"`
}

Settings is the shared settings contract used by the API and config service. The repository persists this model but does not own its schema.

func (*Settings) EndHookSkipsWatchedJob

func (s *Settings) EndHookSkipsWatchedJob() bool

EndHookSkipsWatchedJob reports whether an interactive end hook should stay quiet while the Job has a visible live viewer. Missing config keeps the historical default of suppressing the hook.

func (*Settings) UnmarshalJSON

func (s *Settings) UnmarshalJSON(data []byte) error

UnmarshalJSON adopts the legacy graph_end_hook_script key when the current end_hook_script is absent.

type SkillAddRequest

type SkillAddRequest struct {
	Package string `json:"package"`
	Global  bool   `json:"global"`
	// WorkspaceID selects the directory used for project-scope installs. It is
	// required whenever Global is false: project-scope skills only reach an
	// agent when they are installed into the workspace the agent runs in.
	WorkspaceID string   `json:"workspaceId"`
	Agents      []string `json:"agents"`
	Skills      []string `json:"skills"`
}

SkillAddRequest is the request body for POST /api/v1/skills/add.

type SkillCommandResponse

type SkillCommandResponse struct {
	Code   int    `json:"code"`
	Msg    string `json:"msg,omitempty"`
	Output string `json:"output"`
}

SkillCommandResponse is the reply for the skill mutation endpoints.

type SkillFindResponse

type SkillFindResponse struct {
	Code    int               `json:"code"`
	Results []SkillFindResult `json:"results"`
}

SkillFindResponse is the reply for GET /api/v1/skills/find.

type SkillFindResult

type SkillFindResult struct {
	Name     string `json:"name"`
	Installs string `json:"installs"`
	URL      string `json:"url"`
}

SkillFindResult is one entry of the skills registry search.

type SkillInfo

type SkillInfo struct {
	Name  string `json:"name"`
	Path  string `json:"path"`
	Scope string `json:"scope"`
	// Agents holds the CLI's human-readable agent labels ("Claude Code",
	// "Trae CN"), not the slugs accepted by `skills add -a`.
	Agents     []string `json:"agents"`
	Source     string   `json:"source,omitempty"`
	SourceURL  string   `json:"sourceUrl,omitempty"`
	SourceType string   `json:"sourceType,omitempty"`
}

SkillInfo is one installed skill as reported by the skills CLI (`skills ls --json`).

type SkillListResponse

type SkillListResponse struct {
	Code   int         `json:"code"`
	Skills []SkillInfo `json:"skills"`
	Ready  bool        `json:"ready"`
	Error  string      `json:"error,omitempty"`
}

SkillListResponse is the reply for GET /api/v1/skills/list.

Ready reports whether the backend cache already holds a completed skills-CLI listing for the requested scope. Callers must not render an empty Skills as "nothing installed" while Ready is false — the first listing is still in flight. Error carries the full failure text of the last listing attempt so the UI can show it instead of silently rendering an empty list.

type SkillRemoveRequest

type SkillRemoveRequest struct {
	Name        string `json:"name"`
	Global      bool   `json:"global"`
	WorkspaceID string `json:"workspaceId"`
}

SkillRemoveRequest is the request body for POST /api/v1/skills/remove.

type SkillUpdateRequest

type SkillUpdateRequest struct {
	Global      bool   `json:"global"`
	WorkspaceID string `json:"workspaceId"`
}

SkillUpdateRequest is the request body for POST /api/v1/skills/update.

The skills CLI has no read-only "check for updates" mode — its `check` verb is a plain alias of `update` — so this endpoint is the only update entry point and always writes.

type StartGraphRunRequest

type StartGraphRunRequest struct {
	WorkflowID        string     `json:"workflowId,omitempty"`
	WorkflowUpdatedAt *time.Time `json:"workflowUpdatedAt,omitempty"`
	// ClientMessageID makes a fresh Graph Job launch retry-safe. A client must
	// keep this value stable while retrying an outcome-unknown request and use a
	// new value after changing any launch input.
	ClientMessageID string       `json:"clientMessageId,omitempty"`
	JobID           string       `json:"jobId,omitempty"`
	WorkspaceID     string       `json:"workspaceId,omitempty"`
	Workdir         string       `json:"workdir,omitempty"`
	Config          *GraphConfig `json:"config,omitempty"`
}

type SystemCPUStats

type SystemCPUStats struct {
	Model        string  `json:"model"`
	LogicalCores int     `json:"logicalCores"`
	UsagePercent float64 `json:"usagePercent"`
}

type SystemDiskStats

type SystemDiskStats struct {
	Path           string  `json:"path"`
	TotalBytes     uint64  `json:"totalBytes"`
	UsedBytes      uint64  `json:"usedBytes"`
	AvailableBytes uint64  `json:"availableBytes"`
	UsagePercent   float64 `json:"usagePercent"`
}

type SystemMemoryStats

type SystemMemoryStats struct {
	TotalBytes     uint64  `json:"totalBytes"`
	UsedBytes      uint64  `json:"usedBytes"`
	AvailableBytes uint64  `json:"availableBytes"`
	UsagePercent   float64 `json:"usagePercent"`
}

type SystemStats

type SystemStats struct {
	Hostname  string             `json:"hostname"`
	SampledAt time.Time          `json:"sampledAt"`
	CPU       *SystemCPUStats    `json:"cpu"`
	Memory    *SystemMemoryStats `json:"memory"`
	Disk      *SystemDiskStats   `json:"disk"`
	Errors    []string           `json:"errors"`
}

SystemStats describes the machine running the Quartet backend. Disk usage refers to the filesystem containing LOCAL_MEMORY, including space used by other applications on that filesystem.

type TextMessageContentEvent

type TextMessageContentEvent struct {
	BaseEvent
	MessageID   string      `json:"messageId"`
	Role        MessageRole `json:"role"`
	Name        string      `json:"name,omitempty"`
	Description string      `json:"description,omitempty"`
	Delta       string      `json:"delta"`
}

type TextMessageEndEvent

type TextMessageEndEvent struct {
	BaseEvent
	MessageID   string      `json:"messageId"`
	Role        MessageRole `json:"role"`
	Name        string      `json:"name,omitempty"`
	Description string      `json:"description,omitempty"`
}

type TextMessageStartEvent

type TextMessageStartEvent struct {
	BaseEvent
	MessageID   string      `json:"messageId"`
	Role        MessageRole `json:"role"`
	Name        string      `json:"name,omitempty"`
	Description string      `json:"description,omitempty"`
}

type TokenUsage

type TokenUsage struct {
	TotalTokens int `json:"totalTokens"`
	// Estimated distinguishes Quartet's local tokenizer fallback from a value
	// pushed by the Agent CLI. It describes this live context gauge, not billing.
	Estimated bool `json:"estimated"`
}

type ToolCallArgsEvent

type ToolCallArgsEvent struct {
	BaseEvent
	ToolCallID      string         `json:"toolCallId"`
	ToolCallName    string         `json:"toolCallName,omitempty"`
	ParentMessageID string         `json:"parentMessageId,omitempty"`
	Delta           string         `json:"delta"`
	Replace         bool           `json:"replace,omitempty"`
	ToolCallStatus  ToolCallStatus `json:"toolCallStatus,omitempty"`
}

type ToolCallEndEvent

type ToolCallEndEvent struct {
	BaseEvent
	ToolCallID      string         `json:"toolCallId"`
	ToolCallName    string         `json:"toolCallName,omitempty"`
	ParentMessageID string         `json:"parentMessageId,omitempty"`
	ToolCallStatus  ToolCallStatus `json:"toolCallStatus,omitempty"`
}

type ToolCallInfo

type ToolCallInfo struct {
	ID        string `json:"id"`
	Name      string `json:"name"`
	Arguments string `json:"arguments"`
}

type ToolCallResultEvent

type ToolCallResultEvent struct {
	BaseEvent
	ToolCallID      string         `json:"toolCallId"`
	ToolCallName    string         `json:"toolCallName,omitempty"`
	ParentMessageID string         `json:"parentMessageId,omitempty"`
	Delta           string         `json:"delta"`
	ToolCallStatus  ToolCallStatus `json:"toolCallStatus"`
}

type ToolCallStartEvent

type ToolCallStartEvent struct {
	BaseEvent
	ToolCallID      string         `json:"toolCallId"`
	ToolCallName    string         `json:"toolCallName"`
	ParentMessageID string         `json:"parentMessageId,omitempty"`
	ToolCallStatus  ToolCallStatus `json:"toolCallStatus,omitempty"`
}

type ToolCallStatus

type ToolCallStatus string
const (
	ToolCallStatusProcessing ToolCallStatus = "Processing"
	ToolCallStatusSuccess    ToolCallStatus = "Success"
	ToolCallStatusError      ToolCallStatus = "Error"
	// ToolCallStatusPlaceholder marks the bubble as interrupted /
	// superseded — the surrounding run ended before the tool ever
	// produced a real terminal status. Visually distinct from Error
	// (which signals a real failure) and matches the placeholder flag
	// written to history, so live UI and reload stay consistent.
	ToolCallStatusPlaceholder ToolCallStatus = "Placeholder"
)

type ToolCallStitchedEvent

type ToolCallStitchedEvent struct {
	BaseEvent
	ToolCallID      string         `json:"toolCallId"`
	ToolCallName    string         `json:"toolCallName,omitempty"`
	ParentMessageID string         `json:"parentMessageId,omitempty"`
	Delta           string         `json:"delta"`
	ToolCallStatus  ToolCallStatus `json:"toolCallStatus"`
	SupersededAgoMs int64          `json:"supersededAgoMs,omitempty"`
}

ToolCallStitchedEvent rewrites a Placeholder tool bubble with the real terminal payload after a late-arriving terminal. The frontend handles this event by replacing the bubble's content and flipping toolCallStatus to Success/Error even if the message is already Finished. SupersededAgoMs is the gap between the eager flush that turned the bubble into a Placeholder and the late terminal that produced this stitch — useful for observability tooltips.

type UpdateGraphRunVersionRequest

type UpdateGraphRunVersionRequest struct {
	Config                     GraphConfig `json:"config"`
	Reason                     string      `json:"reason,omitempty"`
	UpdateAgentRevisionNodeIDs []string    `json:"updateAgentRevisionNodeIds,omitempty"`
}

type UpdateGraphWorkflowRequest

type UpdateGraphWorkflowRequest struct {
	Name        *string      `json:"name,omitempty"`
	Description *string      `json:"description,omitempty"`
	WorkspaceID *string      `json:"workspaceId,omitempty"`
	Config      *GraphConfig `json:"config,omitempty"`
	UpdatedAt   *time.Time   `json:"updatedAt,omitempty"`
}

type UpdateProfileRequest

type UpdateProfileRequest struct {
	DisplayName string `json:"displayName"`
}

type UpdateRoleRequest

type UpdateRoleRequest struct {
	Version     int64    `json:"version"`
	Name        string   `json:"name"`
	Description string   `json:"description"`
	Permissions []string `json:"permissions"`
}

type UpdateScheduleRequest

type UpdateScheduleRequest struct {
	Name            *string `json:"name,omitempty"`
	CronExpr        *string `json:"cronExpr,omitempty"`
	Enabled         *bool   `json:"enabled,omitempty"`
	GraphWorkflowID *string `json:"graphWorkflowId,omitempty"`
	WorkspaceID     *string `json:"workspaceId,omitempty"`
	Workdir         *string `json:"workdir,omitempty"`
	MaxConcurrent   *int    `json:"maxConcurrent,omitempty"`
	Timeout         *int    `json:"timeout,omitempty"`
}

type UpdateUserRequest

type UpdateUserRequest struct {
	Version     int64    `json:"version"`
	Username    *string  `json:"username,omitempty"`
	DisplayName *string  `json:"displayName,omitempty"`
	RoleIDs     []string `json:"roleIds,omitempty"`
	Status      *string  `json:"status,omitempty"`
}

type UpdateWorkspaceFavoriteRequest

type UpdateWorkspaceFavoriteRequest struct {
	Favorite bool `json:"favorite"`
}

type UpdateWorkspaceRequest

type UpdateWorkspaceRequest struct {
	ExpectedVersion uint64  `json:"expectedVersion"`
	Title           *string `json:"title,omitempty"`
	Description     *string `json:"description,omitempty"`
	Workdir         *string `json:"workdir,omitempty"`
	DefaultAgent    *string `json:"defaultAgent,omitempty"`
	DefaultModel    *string `json:"defaultModel,omitempty"`
}

type UsageWindow

type UsageWindow struct {
	UsedPercent        float64 `json:"used_percent"`
	LimitWindowSeconds int64   `json:"limit_window_seconds"`
	ResetAfterSeconds  int64   `json:"reset_after_seconds"`
	ResetAt            int64   `json:"reset_at"` // unix seconds
}

UsageWindow is one rate-limit window. LimitWindowSeconds is the source of truth for its duration; upstream field names do not imply a fixed period.

type User

type User struct {
	ID                 string    `json:"id"`
	Username           string    `json:"username"`
	DisplayName        string    `json:"displayName"`
	PasswordHash       string    `json:"passwordHash"`
	RoleIDs            []string  `json:"roleIds"`
	Status             string    `json:"status"`
	MustChangePassword bool      `json:"mustChangePassword"`
	Version            int64     `json:"version"`
	CreatedAt          time.Time `json:"createdAt"`
	UpdatedAt          time.Time `json:"updatedAt"`
	CreatedBy          string    `json:"createdBy"`
	UpdatedBy          string    `json:"updatedBy"`
}

type UserInput

type UserInput struct {
	MessageID  string `json:"messageId"`
	ReceivedAt int64  `json:"receivedAt"`

	Source   string `json:"source"`
	Platform string `json:"platform"`

	ChatID      string `json:"chatId,omitempty"`
	SenderID    string `json:"senderId,omitempty"`
	JobID       string `json:"jobId,omitempty"`
	WorkspaceID string `json:"workspaceId,omitempty"`

	Content         string           `json:"content"`
	ImageUrls       []string         `json:"imageUrls,omitempty"`
	FileAttachments []FileAttachment `json:"fileAttachments,omitempty"`

	// Kind distinguishes entry shapes in the single flat stream. Empty means
	// "message" for backward compatibility with entries written before the
	// kind field existed.
	Kind string `json:"kind,omitempty"`
}

UserInput is the narrow-spec "真实用户输入" record persisted to {LOCAL_MEMORY}/quartet/data/user-input/YYYY-MM-DD.jsonl. IM and Web both write into this single flat stream; per-source fields are populated when relevant and left empty otherwise (no per-source subtypes — keeps reader logic single-shape).

func NewIMUserInput

func NewIMUserInput(receivedAt time.Time, platform, messageID, chatID, senderID, jobID, workspaceID, content string) *UserInput

NewIMUserInput builds a UserInput for an IM-sourced message. jobID and workspaceID are best-effort: empty when the chat has no prior IM->Job mapping (the very first message on a new chat), filled from the existing mapping otherwise (see docs/feature-2026-05-03-user-input-logging.md §3.5).

receivedAt must be sampled by the caller at the handler's entry point (before any synchronous work that could push the timestamp past a midnight boundary and land the entry in the wrong daily file).

func NewWebUserInput

func NewWebUserInput(receivedAt time.Time, messageID, jobID, workspaceID, content string, imageUrls []string, fileAttachments []FileAttachment) *UserInput

NewWebUserInput builds a UserInput for a Web-sourced message.

receivedAt must be sampled by the caller at the handler's entry point (before prepareJobSend's potentially slow image reads / base64 work), so the timestamp reflects "when the server received" the request and stays on the correct side of a midnight boundary.

type UserView

type UserView struct {
	ID                 string    `json:"id"`
	Username           string    `json:"username"`
	DisplayName        string    `json:"displayName"`
	RoleIDs            []string  `json:"roleIds"`
	Status             string    `json:"status"`
	MustChangePassword bool      `json:"mustChangePassword"`
	Version            int64     `json:"version"`
	CreatedAt          time.Time `json:"createdAt"`
	UpdatedAt          time.Time `json:"updatedAt"`
	CreatedBy          string    `json:"createdBy"`
	UpdatedBy          string    `json:"updatedBy"`
}

type ValidateGraphWorkflowRequest

type ValidateGraphWorkflowRequest struct {
	Config GraphConfig `json:"config"`
}

type WeChatOutboxResultResponse

type WeChatOutboxResultResponse struct {
	Result *WeChatSendResult `json:"result,omitempty"`
}

type WeChatOutboxStatus

type WeChatOutboxStatus string
const (
	WeChatOutboxStatusQueued   WeChatOutboxStatus = "queued"
	WeChatOutboxStatusSending  WeChatOutboxStatus = "sending"
	WeChatOutboxStatusRetrying WeChatOutboxStatus = "retrying"
	WeChatOutboxStatusSent     WeChatOutboxStatus = "sent"
)

type WeChatOutboxTask

type WeChatOutboxTask struct {
	ID             string             `json:"id"`
	IdempotencyKey string             `json:"idempotencyKey,omitempty"`
	ToUserID       string             `json:"toUserId"`
	Content        string             `json:"content"`
	Status         WeChatOutboxStatus `json:"status"`
	NextChunk      int                `json:"nextChunk"`
	TotalChunks    int                `json:"totalChunks"`
	Attempt        int                `json:"attempt"`
	LastError      string             `json:"lastError,omitempty"`
	NextAttemptAt  *time.Time         `json:"nextAttemptAt,omitempty"`
	LastSentAt     *time.Time         `json:"lastSentAt,omitempty"`
	CreatedAt      time.Time          `json:"createdAt"`
	UpdatedAt      time.Time          `json:"updatedAt"`
	SentAt         *time.Time         `json:"sentAt,omitempty"`
}

WeChatOutboxTask is one durable recipient delivery. Content remains intact; the worker derives deterministic UTF-8 chunks and advances NextChunk only after the corresponding WeChat call succeeds.

type WeChatOutboxTaskResponse

type WeChatOutboxTaskResponse struct {
	Task *WeChatOutboxTask `json:"task,omitempty"`
}

type WeChatSendMessageRequest

type WeChatSendMessageRequest struct {
	Content        string   `json:"content"`
	ToUserIDs      []string `json:"toUserIds"`
	IdempotencyKey string   `json:"idempotencyKey,omitempty"`
}

WeChatSendMessageRequest is the payload of POST /api/v1/wechat/send, the proactive (not reply-driven) WeChat push used by scheduled jobs. When ToUserIDs is empty the backend fans out to the configured WeChat admin whitelist (settings.wechat_admin_ids).

type WeChatSendMessageResponse

type WeChatSendMessageResponse struct {
	Results []WeChatSendResult `json:"results"`
}

WeChatSendMessageResponse aggregates the per-recipient results.

type WeChatSendResult

type WeChatSendResult struct {
	TaskID      string             `json:"taskId"`
	ToUserID    string             `json:"toUserId"`
	Status      WeChatOutboxStatus `json:"status"`
	Chunks      int                `json:"chunks"`
	TotalChunks int                `json:"totalChunks"`
	Error       string             `json:"error,omitempty"`
}

WeChatSendResult reports the durable outbox task created or reused for one recipient. Chunks is the number already acknowledged by WeChat.

type Workspace

type Workspace struct {
	ID           string    `json:"id"`
	Version      uint64    `json:"version"`
	Title        string    `json:"title"`
	Description  string    `json:"description"`
	Workdir      string    `json:"workdir"`
	DefaultAgent string    `json:"defaultAgent,omitempty"`
	DefaultModel string    `json:"defaultModel,omitempty"`
	Color        string    `json:"color,omitempty"`
	Favorite     bool      `json:"favorite,omitempty"`
	SortOrder    int       `json:"sortOrder,omitempty"`
	CreatedAt    time.Time `json:"createdAt"`
	UpdatedAt    time.Time `json:"updatedAt"`
	Deleted      bool      `json:"deleted,omitempty"`
}

func NewWorkspace

func NewWorkspace(title, description, workdir string) *Workspace

type WorkspaceInfo

type WorkspaceInfo struct {
	ID           string `json:"id"`
	Version      uint64 `json:"version"`
	Title        string `json:"title"`
	Description  string `json:"description"`
	Workdir      string `json:"workdir"`
	DefaultAgent string `json:"defaultAgent"`
	DefaultModel string `json:"defaultModel"`
	Color        string `json:"color,omitempty"`
	Favorite     bool   `json:"favorite"`
	SortOrder    int    `json:"sortOrder"`
	CreatedAt    int64  `json:"createdAt"`
	UpdatedAt    int64  `json:"updatedAt"`
}

Jump to

Keyboard shortcuts

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