Add AllowStale field to ListArgs struct to support resilient hook detection. When set, callers signal they accept potentially stale data rather than failing on staleness check errors. This enables gastown checkSlungWork() to fall back gracefully when the beads database is out of sync with JSONL (common after concurrent agent syncs). - Add AllowStale bool to ListArgs in internal/rpc/protocol.go - Pass --allow-stale flag through to RPC in cmd/bd/list.go Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Executed-By: beads/crew/dave Rig: beads Role: crew
639 lines
27 KiB
Go
639 lines
27 KiB
Go
package rpc
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"github.com/steveyegge/beads/internal/types"
|
|
)
|
|
|
|
// Operation constants for all bd commands
|
|
const (
|
|
OpPing = "ping"
|
|
OpStatus = "status"
|
|
OpHealth = "health"
|
|
OpMetrics = "metrics"
|
|
OpCreate = "create"
|
|
OpUpdate = "update"
|
|
OpClose = "close"
|
|
OpList = "list"
|
|
OpCount = "count"
|
|
OpShow = "show"
|
|
OpReady = "ready"
|
|
OpBlocked = "blocked"
|
|
OpStale = "stale"
|
|
OpStats = "stats"
|
|
OpDepAdd = "dep_add"
|
|
OpDepRemove = "dep_remove"
|
|
OpDepTree = "dep_tree"
|
|
OpLabelAdd = "label_add"
|
|
OpLabelRemove = "label_remove"
|
|
OpCommentList = "comment_list"
|
|
OpCommentAdd = "comment_add"
|
|
OpBatch = "batch"
|
|
OpResolveID = "resolve_id"
|
|
|
|
OpCompact = "compact"
|
|
OpCompactStats = "compact_stats"
|
|
OpExport = "export"
|
|
OpImport = "import"
|
|
OpEpicStatus = "epic_status"
|
|
OpGetMutations = "get_mutations"
|
|
OpGetMoleculeProgress = "get_molecule_progress"
|
|
OpShutdown = "shutdown"
|
|
OpDelete = "delete"
|
|
OpGetWorkerStatus = "get_worker_status"
|
|
OpGetConfig = "get_config"
|
|
OpMolStale = "mol_stale"
|
|
|
|
// Gate operations
|
|
OpGateCreate = "gate_create"
|
|
OpGateList = "gate_list"
|
|
OpGateShow = "gate_show"
|
|
OpGateClose = "gate_close"
|
|
OpGateWait = "gate_wait"
|
|
)
|
|
|
|
// Request represents an RPC request from client to daemon
|
|
type Request struct {
|
|
Operation string `json:"operation"`
|
|
Args json.RawMessage `json:"args"`
|
|
Actor string `json:"actor,omitempty"`
|
|
RequestID string `json:"request_id,omitempty"`
|
|
Cwd string `json:"cwd,omitempty"` // Working directory for database discovery
|
|
ClientVersion string `json:"client_version,omitempty"` // Client version for compatibility checks
|
|
ExpectedDB string `json:"expected_db,omitempty"` // Expected database path for validation (absolute)
|
|
}
|
|
|
|
// Response represents an RPC response from daemon to client
|
|
type Response struct {
|
|
Success bool `json:"success"`
|
|
Data json.RawMessage `json:"data,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
// CreateArgs represents arguments for the create operation
|
|
type CreateArgs struct {
|
|
ID string `json:"id,omitempty"`
|
|
Parent string `json:"parent,omitempty"` // Parent ID for hierarchical issues
|
|
Title string `json:"title"`
|
|
Description string `json:"description,omitempty"`
|
|
IssueType string `json:"issue_type"`
|
|
Priority int `json:"priority"`
|
|
Design string `json:"design,omitempty"`
|
|
AcceptanceCriteria string `json:"acceptance_criteria,omitempty"`
|
|
Notes string `json:"notes,omitempty"`
|
|
Assignee string `json:"assignee,omitempty"`
|
|
ExternalRef string `json:"external_ref,omitempty"` // Link to external issue trackers
|
|
EstimatedMinutes *int `json:"estimated_minutes,omitempty"` // Time estimate in minutes
|
|
Labels []string `json:"labels,omitempty"`
|
|
Dependencies []string `json:"dependencies,omitempty"`
|
|
// Waits-for dependencies
|
|
WaitsFor string `json:"waits_for,omitempty"` // Spawner issue ID to wait for
|
|
WaitsForGate string `json:"waits_for_gate,omitempty"` // Gate type: all-children or any-children
|
|
// Messaging fields
|
|
Sender string `json:"sender,omitempty"` // Who sent this (for messages)
|
|
Ephemeral bool `json:"ephemeral,omitempty"` // If true, not exported to JSONL; bulk-deleted when closed
|
|
RepliesTo string `json:"replies_to,omitempty"` // Issue ID for conversation threading
|
|
// ID generation
|
|
IDPrefix string `json:"id_prefix,omitempty"` // Override prefix for ID generation (mol, eph, etc.)
|
|
CreatedBy string `json:"created_by,omitempty"` // Who created the issue
|
|
// Molecule type (for swarm coordination)
|
|
MolType string `json:"mol_type,omitempty"` // swarm, patrol, or work (default)
|
|
// Agent identity fields (only valid when IssueType == "agent")
|
|
RoleType string `json:"role_type,omitempty"` // polecat|crew|witness|refinery|mayor|deacon
|
|
Rig string `json:"rig,omitempty"` // Rig name (empty for town-level agents)
|
|
// Event fields (only valid when IssueType == "event")
|
|
EventCategory string `json:"event_category,omitempty"` // Namespaced category (e.g., patrol.muted, agent.started)
|
|
EventActor string `json:"event_actor,omitempty"` // Entity URI who caused this event
|
|
EventTarget string `json:"event_target,omitempty"` // Entity URI or bead ID affected
|
|
EventPayload string `json:"event_payload,omitempty"` // Event-specific JSON data
|
|
// Time-based scheduling fields (GH#820)
|
|
DueAt string `json:"due_at,omitempty"` // Relative or ISO format due date
|
|
DeferUntil string `json:"defer_until,omitempty"` // Relative or ISO format defer date
|
|
}
|
|
|
|
// UpdateArgs represents arguments for the update operation
|
|
type UpdateArgs struct {
|
|
ID string `json:"id"`
|
|
Title *string `json:"title,omitempty"`
|
|
Description *string `json:"description,omitempty"`
|
|
Status *string `json:"status,omitempty"`
|
|
Priority *int `json:"priority,omitempty"`
|
|
Design *string `json:"design,omitempty"`
|
|
AcceptanceCriteria *string `json:"acceptance_criteria,omitempty"`
|
|
Notes *string `json:"notes,omitempty"`
|
|
Assignee *string `json:"assignee,omitempty"`
|
|
ExternalRef *string `json:"external_ref,omitempty"` // Link to external issue trackers
|
|
EstimatedMinutes *int `json:"estimated_minutes,omitempty"` // Time estimate in minutes
|
|
IssueType *string `json:"issue_type,omitempty"` // Issue type (bug|feature|task|epic|chore)
|
|
AddLabels []string `json:"add_labels,omitempty"`
|
|
RemoveLabels []string `json:"remove_labels,omitempty"`
|
|
SetLabels []string `json:"set_labels,omitempty"`
|
|
// Messaging fields
|
|
Sender *string `json:"sender,omitempty"` // Who sent this (for messages)
|
|
Ephemeral *bool `json:"ephemeral,omitempty"` // If true, not exported to JSONL; bulk-deleted when closed
|
|
RepliesTo *string `json:"replies_to,omitempty"` // Issue ID for conversation threading
|
|
// Graph link fields
|
|
RelatesTo *string `json:"relates_to,omitempty"` // JSON array of related issue IDs
|
|
DuplicateOf *string `json:"duplicate_of,omitempty"` // Canonical issue ID if duplicate
|
|
SupersededBy *string `json:"superseded_by,omitempty"` // Replacement issue ID if obsolete
|
|
// Pinned field
|
|
Pinned *bool `json:"pinned,omitempty"` // If true, issue is a persistent context marker
|
|
// Reparenting field
|
|
Parent *string `json:"parent,omitempty"` // New parent issue ID (reparents the issue)
|
|
// Agent slot fields
|
|
HookBead *string `json:"hook_bead,omitempty"` // Current work on agent's hook (0..1)
|
|
RoleBead *string `json:"role_bead,omitempty"` // Role definition bead for agent
|
|
// Agent state fields
|
|
AgentState *string `json:"agent_state,omitempty"` // Agent state (idle|running|stuck|stopped|dead)
|
|
LastActivity *bool `json:"last_activity,omitempty"` // If true, update last_activity to now
|
|
// Agent identity fields
|
|
RoleType *string `json:"role_type,omitempty"` // polecat|crew|witness|refinery|mayor|deacon
|
|
Rig *string `json:"rig,omitempty"` // Rig name (empty for town-level agents)
|
|
// Event fields (only valid when IssueType == "event")
|
|
EventCategory *string `json:"event_category,omitempty"` // Namespaced category (e.g., patrol.muted, agent.started)
|
|
EventActor *string `json:"event_actor,omitempty"` // Entity URI who caused this event
|
|
EventTarget *string `json:"event_target,omitempty"` // Entity URI or bead ID affected
|
|
EventPayload *string `json:"event_payload,omitempty"` // Event-specific JSON data
|
|
// Work queue claim operation
|
|
Claim bool `json:"claim,omitempty"` // If true, atomically claim issue (set assignee+status, fail if already claimed)
|
|
// Time-based scheduling fields (GH#820)
|
|
DueAt *string `json:"due_at,omitempty"` // Relative or ISO format due date
|
|
DeferUntil *string `json:"defer_until,omitempty"` // Relative or ISO format defer date
|
|
// Gate fields
|
|
AwaitID *string `json:"await_id,omitempty"` // Condition identifier for gates (run ID, PR number, etc.)
|
|
Waiters []string `json:"waiters,omitempty"` // Mail addresses to notify when gate clears
|
|
// Slot fields
|
|
Holder *string `json:"holder,omitempty"` // Who currently holds the slot (for type=slot beads)
|
|
}
|
|
|
|
// CloseArgs represents arguments for the close operation
|
|
type CloseArgs struct {
|
|
ID string `json:"id"`
|
|
Reason string `json:"reason,omitempty"`
|
|
Session string `json:"session,omitempty"` // Claude Code session ID that closed this issue
|
|
SuggestNext bool `json:"suggest_next,omitempty"` // Return newly unblocked issues (GH#679)
|
|
}
|
|
|
|
// CloseResult is returned when SuggestNext is true (GH#679)
|
|
// When SuggestNext is false, just the closed issue is returned for backward compatibility
|
|
type CloseResult struct {
|
|
Closed *types.Issue `json:"closed"` // The issue that was closed
|
|
Unblocked []*types.Issue `json:"unblocked,omitempty"` // Issues newly unblocked by closing
|
|
}
|
|
|
|
// DeleteArgs represents arguments for the delete operation
|
|
type DeleteArgs struct {
|
|
IDs []string `json:"ids"` // Issue IDs to delete
|
|
Force bool `json:"force,omitempty"` // Force deletion without confirmation
|
|
DryRun bool `json:"dry_run,omitempty"` // Preview mode
|
|
Cascade bool `json:"cascade,omitempty"` // Recursively delete dependents
|
|
Reason string `json:"reason,omitempty"` // Reason for deletion
|
|
}
|
|
|
|
// ListArgs represents arguments for the list operation
|
|
type ListArgs struct {
|
|
Query string `json:"query,omitempty"`
|
|
Status string `json:"status,omitempty"`
|
|
Priority *int `json:"priority,omitempty"`
|
|
IssueType string `json:"issue_type,omitempty"`
|
|
Assignee string `json:"assignee,omitempty"`
|
|
Label string `json:"label,omitempty"` // Deprecated: use Labels
|
|
Labels []string `json:"labels,omitempty"` // AND semantics
|
|
LabelsAny []string `json:"labels_any,omitempty"` // OR semantics
|
|
IDs []string `json:"ids,omitempty"` // Filter by specific issue IDs
|
|
Limit int `json:"limit,omitempty"`
|
|
|
|
// Pattern matching
|
|
TitleContains string `json:"title_contains,omitempty"`
|
|
DescriptionContains string `json:"description_contains,omitempty"`
|
|
NotesContains string `json:"notes_contains,omitempty"`
|
|
|
|
// Date ranges (ISO 8601 format)
|
|
CreatedAfter string `json:"created_after,omitempty"`
|
|
CreatedBefore string `json:"created_before,omitempty"`
|
|
UpdatedAfter string `json:"updated_after,omitempty"`
|
|
UpdatedBefore string `json:"updated_before,omitempty"`
|
|
ClosedAfter string `json:"closed_after,omitempty"`
|
|
ClosedBefore string `json:"closed_before,omitempty"`
|
|
|
|
// Empty/null checks
|
|
EmptyDescription bool `json:"empty_description,omitempty"`
|
|
NoAssignee bool `json:"no_assignee,omitempty"`
|
|
NoLabels bool `json:"no_labels,omitempty"`
|
|
|
|
// Priority range
|
|
PriorityMin *int `json:"priority_min,omitempty"`
|
|
PriorityMax *int `json:"priority_max,omitempty"`
|
|
|
|
// Pinned filtering
|
|
Pinned *bool `json:"pinned,omitempty"`
|
|
|
|
// Template filtering
|
|
IncludeTemplates bool `json:"include_templates,omitempty"`
|
|
|
|
// Parent filtering
|
|
ParentID string `json:"parent_id,omitempty"`
|
|
|
|
// Ephemeral filtering
|
|
Ephemeral *bool `json:"ephemeral,omitempty"`
|
|
|
|
// Molecule type filtering
|
|
MolType string `json:"mol_type,omitempty"`
|
|
|
|
// Status exclusion (for default non-closed behavior, GH#788)
|
|
ExcludeStatus []string `json:"exclude_status,omitempty"`
|
|
|
|
// Type exclusion (for hiding internal types like gates, bd-7zka.2)
|
|
ExcludeTypes []string `json:"exclude_types,omitempty"`
|
|
|
|
// Time-based scheduling filters (GH#820)
|
|
Deferred bool `json:"deferred,omitempty"` // Filter issues with defer_until set
|
|
DeferAfter string `json:"defer_after,omitempty"` // ISO 8601 format
|
|
DeferBefore string `json:"defer_before,omitempty"` // ISO 8601 format
|
|
DueAfter string `json:"due_after,omitempty"` // ISO 8601 format
|
|
DueBefore string `json:"due_before,omitempty"` // ISO 8601 format
|
|
Overdue bool `json:"overdue,omitempty"` // Filter issues where due_at < now
|
|
|
|
// Staleness control (bd-dpkdm)
|
|
AllowStale bool `json:"allow_stale,omitempty"` // Skip staleness check, return potentially stale data
|
|
}
|
|
|
|
// CountArgs represents arguments for the count operation
|
|
type CountArgs struct {
|
|
// Supports all the same filters as ListArgs
|
|
Query string `json:"query,omitempty"`
|
|
Status string `json:"status,omitempty"`
|
|
Priority *int `json:"priority,omitempty"`
|
|
IssueType string `json:"issue_type,omitempty"`
|
|
Assignee string `json:"assignee,omitempty"`
|
|
Labels []string `json:"labels,omitempty"`
|
|
LabelsAny []string `json:"labels_any,omitempty"`
|
|
IDs []string `json:"ids,omitempty"`
|
|
|
|
// Pattern matching
|
|
TitleContains string `json:"title_contains,omitempty"`
|
|
DescriptionContains string `json:"description_contains,omitempty"`
|
|
NotesContains string `json:"notes_contains,omitempty"`
|
|
|
|
// Date ranges
|
|
CreatedAfter string `json:"created_after,omitempty"`
|
|
CreatedBefore string `json:"created_before,omitempty"`
|
|
UpdatedAfter string `json:"updated_after,omitempty"`
|
|
UpdatedBefore string `json:"updated_before,omitempty"`
|
|
ClosedAfter string `json:"closed_after,omitempty"`
|
|
ClosedBefore string `json:"closed_before,omitempty"`
|
|
|
|
// Empty/null checks
|
|
EmptyDescription bool `json:"empty_description,omitempty"`
|
|
NoAssignee bool `json:"no_assignee,omitempty"`
|
|
NoLabels bool `json:"no_labels,omitempty"`
|
|
|
|
// Priority range
|
|
PriorityMin *int `json:"priority_min,omitempty"`
|
|
PriorityMax *int `json:"priority_max,omitempty"`
|
|
|
|
// Grouping option (only one can be specified)
|
|
GroupBy string `json:"group_by,omitempty"` // "status", "priority", "type", "assignee", "label"
|
|
}
|
|
|
|
// ShowArgs represents arguments for the show operation
|
|
type ShowArgs struct {
|
|
ID string `json:"id"`
|
|
}
|
|
|
|
// ResolveIDArgs represents arguments for the resolve_id operation
|
|
type ResolveIDArgs struct {
|
|
ID string `json:"id"`
|
|
}
|
|
|
|
// ReadyArgs represents arguments for the ready operation
|
|
type ReadyArgs struct {
|
|
Assignee string `json:"assignee,omitempty"`
|
|
Unassigned bool `json:"unassigned,omitempty"`
|
|
Priority *int `json:"priority,omitempty"`
|
|
Type string `json:"type,omitempty"`
|
|
Limit int `json:"limit,omitempty"`
|
|
SortPolicy string `json:"sort_policy,omitempty"`
|
|
Labels []string `json:"labels,omitempty"`
|
|
LabelsAny []string `json:"labels_any,omitempty"`
|
|
ParentID string `json:"parent_id,omitempty"` // Filter to descendants of this bead/epic
|
|
MolType string `json:"mol_type,omitempty"` // Filter by molecule type: swarm, patrol, or work
|
|
IncludeDeferred bool `json:"include_deferred,omitempty"` // Include issues with future defer_until (GH#820)
|
|
}
|
|
|
|
// BlockedArgs represents arguments for the blocked operation
|
|
type BlockedArgs struct {
|
|
ParentID string `json:"parent_id,omitempty"` // Filter to descendants of this bead/epic
|
|
}
|
|
|
|
// StaleArgs represents arguments for the stale command
|
|
type StaleArgs struct {
|
|
Days int `json:"days,omitempty"`
|
|
Status string `json:"status,omitempty"`
|
|
Limit int `json:"limit,omitempty"`
|
|
}
|
|
|
|
// DepAddArgs represents arguments for adding a dependency
|
|
type DepAddArgs struct {
|
|
FromID string `json:"from_id"`
|
|
ToID string `json:"to_id"`
|
|
DepType string `json:"dep_type"`
|
|
}
|
|
|
|
// DepRemoveArgs represents arguments for removing a dependency
|
|
type DepRemoveArgs struct {
|
|
FromID string `json:"from_id"`
|
|
ToID string `json:"to_id"`
|
|
DepType string `json:"dep_type,omitempty"`
|
|
}
|
|
|
|
// DepTreeArgs represents arguments for the dep tree operation
|
|
type DepTreeArgs struct {
|
|
ID string `json:"id"`
|
|
MaxDepth int `json:"max_depth,omitempty"`
|
|
}
|
|
|
|
// LabelAddArgs represents arguments for adding a label
|
|
type LabelAddArgs struct {
|
|
ID string `json:"id"`
|
|
Label string `json:"label"`
|
|
}
|
|
|
|
// LabelRemoveArgs represents arguments for removing a label
|
|
type LabelRemoveArgs struct {
|
|
ID string `json:"id"`
|
|
Label string `json:"label"`
|
|
}
|
|
|
|
// CommentListArgs represents arguments for listing comments on an issue
|
|
type CommentListArgs struct {
|
|
ID string `json:"id"`
|
|
}
|
|
|
|
// CommentAddArgs represents arguments for adding a comment to an issue
|
|
type CommentAddArgs struct {
|
|
ID string `json:"id"`
|
|
Author string `json:"author"`
|
|
Text string `json:"text"`
|
|
}
|
|
|
|
// EpicStatusArgs represents arguments for the epic status operation
|
|
type EpicStatusArgs struct {
|
|
EligibleOnly bool `json:"eligible_only,omitempty"`
|
|
}
|
|
|
|
// PingResponse is the response for a ping operation
|
|
type PingResponse struct {
|
|
Message string `json:"message"`
|
|
Version string `json:"version"`
|
|
}
|
|
|
|
// StatusResponse represents the daemon status metadata
|
|
type StatusResponse struct {
|
|
Version string `json:"version"` // Server/daemon version
|
|
WorkspacePath string `json:"workspace_path"` // Absolute path to workspace root
|
|
DatabasePath string `json:"database_path"` // Absolute path to database file
|
|
SocketPath string `json:"socket_path"` // Path to Unix socket
|
|
PID int `json:"pid"` // Process ID
|
|
UptimeSeconds float64 `json:"uptime_seconds"` // Time since daemon started
|
|
LastActivityTime string `json:"last_activity_time"` // ISO 8601 timestamp of last request
|
|
ExclusiveLockActive bool `json:"exclusive_lock_active"` // Whether an exclusive lock is held
|
|
ExclusiveLockHolder string `json:"exclusive_lock_holder,omitempty"` // Lock holder name if active
|
|
// Daemon configuration
|
|
AutoCommit bool `json:"auto_commit"` // Whether auto-commit is enabled
|
|
AutoPush bool `json:"auto_push"` // Whether auto-push is enabled
|
|
AutoPull bool `json:"auto_pull"` // Whether auto-pull is enabled (periodic remote sync)
|
|
LocalMode bool `json:"local_mode"` // Whether running in local-only mode (no git)
|
|
SyncInterval string `json:"sync_interval"` // Sync interval (e.g., "5s")
|
|
DaemonMode string `json:"daemon_mode"` // Sync mode: "poll" or "events"
|
|
}
|
|
|
|
// HealthResponse is the response for a health check operation
|
|
type HealthResponse struct {
|
|
Status string `json:"status"` // "healthy", "degraded", "unhealthy"
|
|
Version string `json:"version"` // Server/daemon version
|
|
ClientVersion string `json:"client_version,omitempty"` // Client version from request
|
|
Compatible bool `json:"compatible"` // Whether versions are compatible
|
|
Uptime float64 `json:"uptime_seconds"`
|
|
DBResponseTime float64 `json:"db_response_ms"`
|
|
ActiveConns int32 `json:"active_connections"`
|
|
MaxConns int `json:"max_connections"`
|
|
MemoryAllocMB uint64 `json:"memory_alloc_mb"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
// BatchArgs represents arguments for batch operations
|
|
type BatchArgs struct {
|
|
Operations []BatchOperation `json:"operations"`
|
|
}
|
|
|
|
// BatchOperation represents a single operation in a batch
|
|
type BatchOperation struct {
|
|
Operation string `json:"operation"`
|
|
Args json.RawMessage `json:"args"`
|
|
}
|
|
|
|
// BatchResponse contains the results of a batch operation
|
|
type BatchResponse struct {
|
|
Results []BatchResult `json:"results"`
|
|
}
|
|
|
|
// BatchResult represents the result of a single operation in a batch
|
|
type BatchResult struct {
|
|
Success bool `json:"success"`
|
|
Data json.RawMessage `json:"data,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
// CompactArgs represents arguments for the compact operation
|
|
type CompactArgs struct {
|
|
IssueID string `json:"issue_id,omitempty"` // Empty for --all
|
|
Tier int `json:"tier"` // 1 or 2
|
|
DryRun bool `json:"dry_run"`
|
|
Force bool `json:"force"`
|
|
All bool `json:"all"`
|
|
APIKey string `json:"api_key,omitempty"`
|
|
Workers int `json:"workers,omitempty"`
|
|
BatchSize int `json:"batch_size,omitempty"`
|
|
}
|
|
|
|
// CompactStatsArgs represents arguments for compact stats operation
|
|
type CompactStatsArgs struct {
|
|
Tier int `json:"tier,omitempty"`
|
|
}
|
|
|
|
// CompactResponse represents the response from a compact operation
|
|
type CompactResponse struct {
|
|
Success bool `json:"success"`
|
|
IssueID string `json:"issue_id,omitempty"`
|
|
Results []CompactResult `json:"results,omitempty"` // For batch operations
|
|
Stats *CompactStatsData `json:"stats,omitempty"` // For stats operation
|
|
OriginalSize int `json:"original_size,omitempty"`
|
|
CompactedSize int `json:"compacted_size,omitempty"`
|
|
Reduction string `json:"reduction,omitempty"`
|
|
Duration string `json:"duration,omitempty"`
|
|
DryRun bool `json:"dry_run,omitempty"`
|
|
}
|
|
|
|
// CompactResult represents the result of compacting a single issue
|
|
type CompactResult struct {
|
|
IssueID string `json:"issue_id"`
|
|
Success bool `json:"success"`
|
|
Error string `json:"error,omitempty"`
|
|
OriginalSize int `json:"original_size,omitempty"`
|
|
CompactedSize int `json:"compacted_size,omitempty"`
|
|
Reduction string `json:"reduction,omitempty"`
|
|
}
|
|
|
|
// CompactStatsData represents compaction statistics
|
|
type CompactStatsData struct {
|
|
Tier1Candidates int `json:"tier1_candidates"`
|
|
Tier2Candidates int `json:"tier2_candidates"`
|
|
TotalClosed int `json:"total_closed"`
|
|
Tier1MinAge string `json:"tier1_min_age"`
|
|
Tier2MinAge string `json:"tier2_min_age"`
|
|
EstimatedSavings string `json:"estimated_savings,omitempty"`
|
|
}
|
|
|
|
// ExportArgs represents arguments for the export operation
|
|
type ExportArgs struct {
|
|
JSONLPath string `json:"jsonl_path"` // Path to export JSONL file
|
|
}
|
|
|
|
// ImportArgs represents arguments for the import operation
|
|
type ImportArgs struct {
|
|
JSONLPath string `json:"jsonl_path"` // Path to import JSONL file
|
|
}
|
|
|
|
// GetMutationsArgs represents arguments for retrieving recent mutations
|
|
type GetMutationsArgs struct {
|
|
Since int64 `json:"since"` // Unix timestamp in milliseconds (0 for all recent)
|
|
}
|
|
|
|
// Gate operations
|
|
|
|
// GateCreateArgs represents arguments for creating a gate
|
|
type GateCreateArgs struct {
|
|
Title string `json:"title"`
|
|
AwaitType string `json:"await_type"` // gh:run, gh:pr, timer, human, mail
|
|
AwaitID string `json:"await_id"` // ID/value for the await type
|
|
Timeout time.Duration `json:"timeout"` // Timeout duration
|
|
Waiters []string `json:"waiters"` // Mail addresses to notify when gate clears
|
|
}
|
|
|
|
// GateCreateResult represents the result of creating a gate
|
|
type GateCreateResult struct {
|
|
ID string `json:"id"` // Created gate ID
|
|
}
|
|
|
|
// GateListArgs represents arguments for listing gates
|
|
type GateListArgs struct {
|
|
All bool `json:"all"` // Include closed gates
|
|
}
|
|
|
|
// GateShowArgs represents arguments for showing a gate
|
|
type GateShowArgs struct {
|
|
ID string `json:"id"` // Gate ID (partial or full)
|
|
}
|
|
|
|
// GateCloseArgs represents arguments for closing a gate
|
|
type GateCloseArgs struct {
|
|
ID string `json:"id"` // Gate ID (partial or full)
|
|
Reason string `json:"reason,omitempty"` // Close reason
|
|
}
|
|
|
|
// GateWaitArgs represents arguments for adding waiters to a gate
|
|
type GateWaitArgs struct {
|
|
ID string `json:"id"` // Gate ID (partial or full)
|
|
Waiters []string `json:"waiters"` // Additional waiters to add
|
|
}
|
|
|
|
// GateWaitResult represents the result of adding waiters
|
|
type GateWaitResult struct {
|
|
AddedCount int `json:"added_count"` // Number of new waiters added
|
|
}
|
|
|
|
// GetWorkerStatusArgs represents arguments for retrieving worker status
|
|
type GetWorkerStatusArgs struct {
|
|
// Assignee filters to a specific worker (optional, empty = all workers)
|
|
Assignee string `json:"assignee,omitempty"`
|
|
}
|
|
|
|
// WorkerStatus represents the status of a single worker and their current work
|
|
type WorkerStatus struct {
|
|
Assignee string `json:"assignee"` // Worker identifier
|
|
MoleculeID string `json:"molecule_id,omitempty"` // Parent molecule/epic ID (if working on a step)
|
|
MoleculeTitle string `json:"molecule_title,omitempty"` // Parent molecule/epic title
|
|
CurrentStep int `json:"current_step,omitempty"` // Current step number (1-indexed)
|
|
TotalSteps int `json:"total_steps,omitempty"` // Total number of steps in molecule
|
|
StepID string `json:"step_id,omitempty"` // Current step issue ID
|
|
StepTitle string `json:"step_title,omitempty"` // Current step issue title
|
|
LastActivity string `json:"last_activity"` // ISO 8601 timestamp of last update
|
|
Status string `json:"status"` // Current work status (in_progress, blocked, etc.)
|
|
}
|
|
|
|
// GetWorkerStatusResponse is the response for get_worker_status operation
|
|
type GetWorkerStatusResponse struct {
|
|
Workers []WorkerStatus `json:"workers"`
|
|
}
|
|
|
|
// GetMoleculeProgressArgs represents arguments for the get_molecule_progress operation
|
|
type GetMoleculeProgressArgs struct {
|
|
MoleculeID string `json:"molecule_id"` // The ID of the molecule (parent issue)
|
|
}
|
|
|
|
// MoleculeStep represents a single step within a molecule
|
|
type MoleculeStep struct {
|
|
ID string `json:"id"`
|
|
Title string `json:"title"`
|
|
Status string `json:"status"` // "done", "current", "ready", "blocked"
|
|
StartTime *string `json:"start_time"` // ISO 8601 timestamp when step was created
|
|
CloseTime *string `json:"close_time"` // ISO 8601 timestamp when step was closed (if done)
|
|
}
|
|
|
|
// MoleculeProgress represents the progress of a molecule (parent issue with steps)
|
|
type MoleculeProgress struct {
|
|
MoleculeID string `json:"molecule_id"`
|
|
Title string `json:"title"`
|
|
Assignee string `json:"assignee"`
|
|
Steps []MoleculeStep `json:"steps"`
|
|
}
|
|
|
|
// GetConfigArgs represents arguments for getting daemon config
|
|
type GetConfigArgs struct {
|
|
Key string `json:"key"` // Config key to retrieve (e.g., "issue_prefix")
|
|
}
|
|
|
|
// GetConfigResponse represents the response from get_config operation
|
|
type GetConfigResponse struct {
|
|
Key string `json:"key"`
|
|
Value string `json:"value"`
|
|
}
|
|
|
|
// MolStaleArgs represents arguments for the mol stale operation
|
|
type MolStaleArgs struct {
|
|
BlockingOnly bool `json:"blocking_only"` // Only show molecules blocking other work
|
|
UnassignedOnly bool `json:"unassigned_only"` // Only show unassigned molecules
|
|
ShowAll bool `json:"show_all"` // Include molecules with 0 children
|
|
}
|
|
|
|
// StaleMolecule holds info about a stale molecule (for RPC response)
|
|
type StaleMolecule struct {
|
|
ID string `json:"id"`
|
|
Title string `json:"title"`
|
|
TotalChildren int `json:"total_children"`
|
|
ClosedChildren int `json:"closed_children"`
|
|
Assignee string `json:"assignee,omitempty"`
|
|
BlockingIssues []string `json:"blocking_issues,omitempty"`
|
|
BlockingCount int `json:"blocking_count"`
|
|
}
|
|
|
|
// MolStaleResponse holds the result of the mol stale operation
|
|
type MolStaleResponse struct {
|
|
StaleMolecules []*StaleMolecule `json:"stale_molecules"`
|
|
TotalCount int `json:"total_count"`
|
|
BlockingCount int `json:"blocking_count"`
|
|
}
|