output

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Apr 23, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var APIDiscoverColumns = []Column{
	{Header: "NAME", Width: 30, Extract: func(row map[string]any) string {
		return getString(row, "name")
	}},
	{Header: "URL", Width: 60, Extract: func(row map[string]any) string {
		return getString(row, "url")
	}},
	{Header: "SCOPE", Width: 30, Extract: func(row map[string]any) string {
		return getString(row, "scope")
	}},
}

APIDiscoverColumns defines columns for discovered servers.

View Source
var APIServerColumns = []Column{
	{Header: "SERVICE", Width: 15, Extract: func(row map[string]any) string {
		return getString(row, "service")
	}},
	{Header: "SERVER", Width: 0, Extract: func(row map[string]any) string {
		return getString(row, "server")
	}},
}

APIServerColumns defines columns for the server list.

View Source
var APIServerProbeColumns = []Column{
	{Header: "SERVICE", Width: 15, Extract: func(row map[string]any) string {
		return getString(row, "service")
	}},
	{Header: "SERVER", Width: 30, Extract: func(row map[string]any) string {
		return getString(row, "server")
	}},
	{Header: "TOOLS", Width: 5, Extract: func(row map[string]any) string {
		return getString(row, "tools")
	}},
	{Header: "STATUS", Width: 0, Extract: func(row map[string]any) string {
		return getString(row, "status")
	}},
}

APIServerProbeColumns defines columns for the probed server list.

View Source
var APIToolColumns = []Column{
	{Header: "TOOL", Width: 40, Extract: func(row map[string]any) string {
		return getString(row, "name")
	}},
	{Header: "REQUIRED", Width: 30, Extract: func(row map[string]any) string {
		return getString(row, "required")
	}},
	{Header: "DESCRIPTION", Width: 60, Extract: func(row map[string]any) string {
		return truncate(getString(row, "description"), 60)
	}},
}

APIToolColumns defines columns for the tool list.

View Source
var CalendarColumns = []Column{
	{Header: "START", Width: 16, Extract: func(row map[string]any) string {
		start, ok := row["start"]
		if !ok || start == nil {
			return formatTime(getString(row, "startDateTime"))
		}
		sm, ok := start.(map[string]any)
		if !ok {
			return ""
		}
		return formatTime(getString(sm, "dateTime"))
	}},
	{Header: "SUBJECT", Width: 40, Extract: func(row map[string]any) string {
		return truncate(getString(row, "subject"), 40)
	}},
	{Header: "ORGANIZER", Width: 25, Extract: func(row map[string]any) string {
		org, ok := row["organizer"]
		if !ok || org == nil {
			return ""
		}
		om, ok := org.(map[string]any)
		if !ok {
			return ""
		}
		ea, ok := om["emailAddress"]
		if !ok || ea == nil {
			return ""
		}
		eam, ok := ea.(map[string]any)
		if !ok {
			return ""
		}
		name := getString(eam, "name")
		if name != "" {
			return truncate(name, 25)
		}
		return truncate(getString(eam, "address"), 25)
	}},
	{Header: "ID", Width: 0, Extract: func(row map[string]any) string {
		return getString(row, "id")
	}},
}

CalendarColumns defines display columns for calendar events.

View Source
var ChannelsColumns = []Column{
	{Header: "DISPLAY NAME", Width: 35, Extract: func(row map[string]any) string {
		return getString(row, "displayName")
	}},
	{Header: "ID", Width: 0, Extract: func(row map[string]any) string {
		return getString(row, "id")
	}},
	{Header: "TYPE", Width: 10, Extract: func(row map[string]any) string {
		return getString(row, "membershipType")
	}},
	{Header: "CREATED", Width: 10, Extract: func(row map[string]any) string {
		return formatTime(getString(row, "createdDateTime"))
	}},
}

ChannelsColumns defines display columns for channels list.

View Source
var ChatsColumns = []Column{
	{Header: "TOPIC", Width: 35, Extract: func(row map[string]any) string {
		topic := getString(row, "topic")
		if topic != "" {
			return topic
		}

		members, ok := row["members"]
		if !ok {
			return "(no topic)"
		}
		arr, ok := members.([]any)
		if !ok || len(arr) == 0 {
			return "(no topic)"
		}
		var names []string
		for _, m := range arr {
			if mm, ok := m.(map[string]any); ok {
				name := getString(mm, "displayName")
				if name != "" {
					names = append(names, name)
				}
			}
		}
		return strings.Join(names, ", ")
	}},
	{Header: "ID", Width: 0, Extract: func(row map[string]any) string {
		return getString(row, "id")
	}},
	{Header: "TYPE", Width: 10, Extract: func(row map[string]any) string {
		return getString(row, "chatType")
	}},
	{Header: "UPDATED", Width: 10, Extract: func(row map[string]any) string {
		return formatTime(getString(row, "lastUpdatedDateTime"))
	}},
}

ChatsColumns defines display columns for chats list.

View Source
var CopilotAgentColumns = []Column{
	{Header: "NAME", Width: 32, Extract: func(row map[string]any) string {
		return truncate(getString(row, "name"), 32)
	}},
	{Header: "SELECTOR", Width: 20, Extract: func(row map[string]any) string {
		selector := getString(row, "selector")
		if selector != "" {
			return selector
		}
		return getString(row, "agentId")
	}},
	{Header: "STATUS", Width: 10, Extract: func(row map[string]any) string {
		status := getString(row, "status")
		if status != "" {
			return status
		}
		if shared, ok := row["sharedSelector"].(bool); ok && shared {
			return "shared"
		}
		if targetable, ok := row["targetable"].(bool); ok && targetable {
			return "ok"
		}
		return ""
	}},
	{Header: "TITLE ID", Width: 0, Extract: func(row map[string]any) string {
		return getString(row, "titleId")
	}},
}

CopilotAgentColumns defines display columns for Copilot agent lists.

View Source
var MailColumns = []Column{
	{Header: "DATE", Width: 10, Extract: func(row map[string]any) string {
		return formatTime(getString(row, "receivedDateTime"))
	}},
	{Header: "FROM", Width: 25, Extract: func(row map[string]any) string {
		from, ok := row["from"]
		if !ok || from == nil {
			return ""
		}
		fm, ok := from.(map[string]any)
		if !ok {
			return ""
		}
		ea, ok := fm["emailAddress"]
		if !ok || ea == nil {
			return getString(fm, "name")
		}
		eam, ok := ea.(map[string]any)
		if !ok {
			return ""
		}
		name := getString(eam, "name")
		if name != "" {
			return truncate(name, 25)
		}
		return truncate(getString(eam, "address"), 25)
	}},
	{Header: "SUBJECT", Width: 50, Extract: func(row map[string]any) string {
		return truncate(getString(row, "subject"), 50)
	}},
	{Header: "READ", Width: 4, Extract: func(row map[string]any) string {
		v, ok := row["isRead"]
		if !ok {
			return ""
		}
		if b, ok := v.(bool); ok && b {
			return "yes"
		}
		return "no"
	}},
	{Header: "ID", Width: 0, Extract: func(row map[string]any) string {
		return getString(row, "id")
	}},
}

MailColumns defines display columns for email lists.

View Source
var MembersColumns = []Column{
	{Header: "DISPLAY NAME", Width: 30, Extract: func(row map[string]any) string {
		return getString(row, "displayName")
	}},
	{Header: "EMAIL", Width: 35, Extract: func(row map[string]any) string {
		return getString(row, "email")
	}},
	{Header: "ID", Width: 36, Extract: func(row map[string]any) string {
		return getString(row, "id")
	}},
	{Header: "ROLES", Width: 10, Extract: func(row map[string]any) string {
		roles, ok := row["roles"]
		if !ok || roles == nil {
			return ""
		}
		arr, ok := roles.([]any)
		if !ok {
			return ""
		}
		var rs []string
		for _, r := range arr {
			if s, ok := r.(string); ok {
				rs = append(rs, s)
			}
		}
		return strings.Join(rs, ",")
	}},
}

MembersColumns defines display columns for member lists.

View Source
var MessagesColumns = []Column{
	{Header: "DATE", Width: 10, Extract: func(row map[string]any) string {
		return formatTime(getString(row, "createdDateTime"))
	}},
	{Header: "FROM", Width: 20, Extract: func(row map[string]any) string {
		return truncate(getNestedString(row, "from", "displayName"), 20)
	}},
	{Header: "CONTENT", Width: 80, Extract: func(row map[string]any) string {
		body, ok := row["body"]
		if !ok || body == nil {
			return ""
		}
		bm, ok := body.(map[string]any)
		if !ok {
			return ""
		}
		content := getString(bm, "content")
		content = stripHTML(content)
		return truncate(content, 80)
	}},
	{Header: "ID", Width: 0, Extract: func(row map[string]any) string {
		return getString(row, "id")
	}},
}

MessagesColumns defines display columns for message lists.

View Source
var PlannerPlanColumns = []Column{
	{Header: "TITLE", Width: 40, Extract: func(row map[string]any) string {
		return truncate(getString(row, "title"), 40)
	}},
	{Header: "ID", Width: 36, Extract: func(row map[string]any) string {
		return getString(row, "id")
	}},
	{Header: "CREATED", Width: 10, Extract: func(row map[string]any) string {
		return formatTime(getString(row, "createdDateTime"))
	}},
}

PlannerPlanColumns defines display columns for planner plans.

View Source
var PlannerTaskColumns = []Column{
	{Header: "TITLE", Width: 40, Extract: func(row map[string]any) string {
		return truncate(getString(row, "title"), 40)
	}},
	{Header: "ID", Width: 36, Extract: func(row map[string]any) string {
		return getString(row, "id")
	}},
	{Header: "STATUS", Width: 12, Extract: func(row map[string]any) string {
		pct := row["percentComplete"]
		if pct == nil {
			return ""
		}
		switch v := pct.(type) {
		case float64:
			if v == 100 {
				return "completed"
			} else if v > 0 {
				return "in progress"
			}
			return "not started"
		default:
			return fmt.Sprintf("%v", v)
		}
	}},
	{Header: "PRIORITY", Width: 8, Extract: func(row map[string]any) string {
		p := row["priority"]
		if p == nil {
			return ""
		}
		switch v := p.(type) {
		case float64:
			switch int(v) {
			case 1:
				return "urgent"
			case 3:
				return "important"
			case 5:
				return "medium"
			case 9:
				return "low"
			default:
				return fmt.Sprintf("%d", int(v))
			}
		default:
			return fmt.Sprintf("%v", v)
		}
	}},
}

PlannerTaskColumns defines display columns for planner tasks.

View Source
var SearchColumns = []Column{
	{Header: "DATE", Width: 10, Extract: func(row map[string]any) string {
		return formatTime(getString(row, "createdDateTime"))
	}},
	{Header: "FROM", Width: 20, Extract: func(row map[string]any) string {
		return truncate(getNestedString(row, "from", "displayName"), 20)
	}},
	{Header: "PREVIEW", Width: 60, Extract: func(row map[string]any) string {

		summary := getString(row, "summary")
		if summary != "" {
			return truncate(stripHTML(summary), 60)
		}
		body, ok := row["body"]
		if !ok || body == nil {
			return ""
		}
		bm, ok := body.(map[string]any)
		if !ok {
			return ""
		}
		return truncate(stripHTML(getString(bm, "content")), 60)
	}},
}

SearchColumns defines display columns for search results.

View Source
var TeamsColumns = []Column{
	{Header: "DISPLAY NAME", Width: 40, Extract: func(row map[string]any) string {
		return getString(row, "displayName")
	}},
	{Header: "ID", Width: 36, Extract: func(row map[string]any) string {
		return getString(row, "id")
	}},
	{Header: "DESCRIPTION", Width: 50, Extract: func(row map[string]any) string {
		return truncate(getString(row, "description"), 50)
	}},
}

TeamsColumns defines display columns for teams list.

View Source
var UserColumns = []Column{
	{Header: "DISPLAY NAME", Width: 30, Extract: func(row map[string]any) string {
		return getString(row, "displayName")
	}},
	{Header: "UPN", Width: 35, Extract: func(row map[string]any) string {
		upn := getString(row, "userPrincipalName")
		if upn != "" {
			return upn
		}
		return getString(row, "mail")
	}},
	{Header: "JOB TITLE", Width: 25, Extract: func(row map[string]any) string {
		return truncate(getString(row, "jobTitle"), 25)
	}},
	{Header: "ID", Width: 36, Extract: func(row map[string]any) string {
		return getString(row, "id")
	}},
}

UserColumns defines display columns for user lists.

Functions

func ExtractContent

func ExtractContent(resp *mcp.JSONRPCResponse) (map[string]any, error)

ExtractContent unwraps the MCP JSON-RPC response to get the domain data. It parses Content[].Text JSON strings into a map[string]any.

func PrintError

func PrintError(format string, args ...any)

PrintError outputs an error message to stderr.

func RenderKeyValue

func RenderKeyValue(w io.Writer, item map[string]any)

RenderKeyValue writes an item as sorted key: value pairs.

func RenderTSV

func RenderTSV(w io.Writer, columns []Column, rows []map[string]any)

RenderTSV writes rows as tab-separated values with a header row. No alignment.

func RenderTable

func RenderTable(w io.Writer, columns []Column, rows []map[string]any)

RenderTable writes rows as an aligned table with headers using tabwriter.

For columns with Width > 0, the configured width acts as the minimum display width for alignment in addition to being the truncation width. Columns with Width == 0 are auto-sized from their observed content.

func ToRows

func ToRows(data map[string]any, key string) []map[string]any

ToRows extracts a named array from domain data as a slice of maps. e.g., ToRows(data, "teams") extracts data["teams"] as []map[string]any.

Types

type Column

type Column struct {
	Header  string                          // Display header, e.g. "DISPLAY NAME"
	Width   int                             // Max chars for table display (0 = unlimited)
	Extract func(row map[string]any) string // Pull value from row
}

Column defines a column for table/TSV output.

type Format

type Format int

Format represents the output format.

const (
	// FormatHuman is the default human-friendly table output.
	FormatHuman Format = iota
	// FormatJSON outputs clean JSON envelopes.
	FormatJSON
	// FormatPlain outputs tab-separated values for scripting.
	FormatPlain
)

type Formatter

type Formatter struct {
	Format Format
	Writer io.Writer // defaults to os.Stdout
}

Formatter handles output rendering in one of three modes.

func NewFormatter

func NewFormatter(format string) *Formatter

NewFormatter creates a new output formatter from a format string. "json" → FormatJSON, "tsv" or "plain" → FormatPlain, anything else → FormatHuman.

func (*Formatter) PrintDryRun

func (f *Formatter) PrintDryRun(action string, data map[string]any) error

PrintDryRun outputs what WOULD happen without executing.

func (*Formatter) PrintDryRunValidated added in v0.2.0

func (f *Formatter) PrintDryRunValidated(action string, data map[string]any, v *mcp.ValidationResult) error

PrintDryRunValidated outputs what WOULD happen, with optional schema validation results. If validation is nil, a "validation skipped" warning is shown. Returns an error when validation fails (for non-zero exit code).

func (*Formatter) PrintItem

func (f *Formatter) PrintItem(item map[string]any) error

PrintItem outputs a single item.

func (*Formatter) PrintList

func (f *Formatter) PrintList(entity string, columns []Column, rows []map[string]any) error

PrintList outputs a list of items with the given entity name and column definitions.

func (*Formatter) PrintMutation

func (f *Formatter) PrintMutation(msg string, data map[string]any) error

PrintMutation outputs the result of a write operation.

func (*Formatter) PrintRaw

func (f *Formatter) PrintRaw(resp *mcp.JSONRPCResponse) error

PrintRaw outputs a raw MCP response (fallback for unstructured content). Used when we can't parse the response into typed data.

Jump to

Keyboard shortcuts

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