builtin

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 4, 2026 License: MIT Imports: 82 Imported by: 0

Documentation

Overview

browserconsole_axcss.go — CSS computation for AX-listed elements.

The picker's AX rows historically carried only snapshot refs (e36): fine for an immediate panel click, poison for recorded skills (refs die with the session — "no snapshot taken"). This pass matches each AX row to its DOM element (by accessible name over the interactive-candidate pool) and computes the same selector ladder the DOM complement uses, so picking a row fills the target with `css;;text=name` — stable by construction.

browserconsole_domscan.go — DOM-level clickable candidates for the element picker, complementing the AX-tree listing.

Why: Vue/React component libraries (Naive-UI, MUI, Element-Plus) render "buttons" as <img>/<div>/<span> with listeners attached from JS. The accessibility tree gives them no interactive role (often no name at all), so the role-based listing is blind to them — a real send button was missing from the picker while the AX tree happily reported a page full of static text. The heuristic below is the browser-use approach: visible elements that are img/svg, carry an onclick, or have a button-ish class, plus the pointer-cursor signal restricted to img/svg/tabindex (pointer-only on generic divs is hover-effect noise).

browsermarkdown.go — browser_extract's format=markdown renderer.

AI-answer blocks, docs panels and rich previews carry structure (headings, bold, code, lists) that plain-text extraction flattens. This compact HTML→Markdown walk preserves the shapes ops flows actually reuse; it is deliberately not a full Turndown — tables are deferred to format=table, unknown tags recurse transparently.

browserscan — deep element scan for LONG and LAZY-LOADING pages.

Two different problems, two different answers:

  • Long static pages are already covered: the AX tree (ConsoleElements) spans the whole DOM including below-the-fold nodes, and click/highlight scrollIntoView their targets. No scan needed.
  • Lazy/infinite pages (瀑布流) only materialize rows as they scroll into view — "all elements" is undefined for a truly infinite stream, and no snapshot can list what the DOM doesn't contain yet. The honest approach is scroll-and-collect with explicit STOP CONDITIONS: scroll a viewport at a time, collect what materialized, stop when the page stops producing new elements (or a budget is hit), and report why it stopped.

Collected rows carry STABLE anchors (#id, tag[name="…"], text=可见文字), not snapshot refs — refs die with the AX snapshot that minted them, but a lazily materialized element from 3 screens down must stay clickable after the scan scrolls back up. Anchers are exactly the target vocabulary the panel's target input and persisted skills already accept.

document_preview.go — upgrade spec 3-8: PreviewFiles for the office writers (doc_write / csv_write / xlsx_write / mindmap_create).

These tools' new content comes from format-specific serialization that is too heavy to mirror twice, so their preview is a RESTORE POINT: the path being touched plus its current content. That is everything the checkpoint hook needs to snapshot and rewind (which is the point — office products were previously invisible to rewind), everything the parallel-writer partition needs for disjointness, and enough for an approval card to list the file. Diff stays empty: the card shows the file, not a diff it can't compute. doc_write additionally renders a full text diff for its plain-text outputs (.md/.txt with string content), the one case where the new text is cheap.

Package builtin provides fairpeer's compile-time built-in tools. Each tool self-registers via init(); main blank-imports this package to wire them in.

Index

Constants

View Source
const (
	ErrFileNotFound  = "file_not_found"
	ErrFileLocked    = "file_locked"
	ErrCorruptFile   = "corrupt_file"
	ErrDecompBomb    = "decompression_bomb"
	ErrCellOverflow  = "cell_overflow"
	ErrTableIndexOOB = "table_index_out_of_bounds"
	ErrRowIndexOOB   = "row_index_out_of_bounds"
	ErrColIndexOOB   = "col_index_out_of_bounds"
	ErrMergedCell    = "merged_cell_continuation"
	ErrPlaceholderNF = "placeholder_not_found"
	ErrInvalidArg    = "invalid_argument"
)

Stable error codes. LLMs match on these to decide retry vs. give up.

View Source
const MaxExcelCellChars = 32767

MaxExcelCellChars is Excel's hard per-cell limit. Writing more produces a file Excel refuses to open or silently truncates.

View Source
const TimeRangeFormat = timeRangeLayout + " - " + timeRangeLayout

TimeRangeFormat is the canonical output layout — exported so callers (panel preview, docs) can render placeholders consistently.

Variables

View Source
var ErrAuthExpired = errors.New("email credentials rejected or expired")

ErrAuthExpired signals that an email operation failed because the mailbox credentials were rejected — most commonly a 139 authorization code past its 90-day life. Detect with errors.Is so callers can prompt "re-enter your auth code" instead of showing an opaque network error.

View Source
var ErrNoBrowser = errors.New("no Chromium-based browser found")

ErrNoBrowser is returned when no Chromium-based browser can be found. The error message guides the user to install one or set CHROME_PATH, rather than surfacing the low-level chromedp launch failure.

Functions

func AutoSearch

func AutoSearch(ctx context.Context, query, collection string) string

AutoSearch performs a lightweight knowledge-base retrieval for auto-injection into the main chat. Returns a formatted context string (entities + snippets) or "" when there are no matches or the store is offline. This lets the controller prepend knowledge-base context to user messages without exposing the rag_search tool to the main agent loop.

collection is the knowledge-base collection to search (the user's Composer "知识库" dropdown selection). It MUST be non-empty — an empty collection means the user opted out ("不使用") and AutoSearch returns "" immediately. The controller gate enforces the same rule before calling, but AutoSearch defends in depth so direct callers stay correct. resolveRAGScope is NOT consulted here (that resolver serves the rag_search tool, not auto-injection) so a single active session collection can never trigger surprise injection.

func BrowserTools

func BrowserTools() []tool.Tool

BrowserTools returns the full set of browser automation tools, for registration when the cowork profile is active. Unlike the compile-time built-ins (which self-register via init() and are therefore in every tool list), browser tools are intentionally NOT in the global set — they are office-specific and should not appear in dev mode. boot.go calls this only under the cowork profile, so the dev tool list stays clean and the browser subprocess is never reachable from a coding session.

func CalendarTools

func CalendarTools() []tool.Tool

func CallSTT added in v0.2.0

func CallSTT(ctx context.Context, audioDataURL, language string) (string, error)

CallSTT sends audio (base64 data URL, e.g. "data:audio/wav;base64,...") to the configured voice model and returns the transcribed text. language hints the locale ("auto" lets the model decide). When no voice model is configured it returns a clear configuration error.

The audio is sent as an input_audio content part alongside a prompt asking the model to transcribe; the model's text response is the transcript. This works for any model that accepts input_audio — no per-vendor adapter.

func CallVLM

func CallVLM(ctx context.Context, imgDataURL string, prompt string) (string, error)

CallVLM sends an image (base64 data URL) + prompt to the configured vision model and returns its text response. This is the unified entry for screen_perceive and any other vision use. When no vision model is configured it returns a clear configuration error.

func CaptureFullScreen

func CaptureFullScreen() (*image.RGBA, error)

CaptureFullScreen captures the full primary screen on Linux. Tries scrot, gnome-screenshot, and grim in order. Returns an image.RGBA compatible with the Windows implementation.

func ConfiguredVoiceModel added in v0.2.0

func ConfiguredVoiceModel() string

ConfiguredVoiceModel returns the current voice model under the read lock. Exported so the desktop layer can report whether voice input is available (mic button enabled vs disabled-with-hint), and so boot.go can re-inject on profile switch without a rebuild race.

func ConfineBash

func ConfineBash(spec sandbox.Spec, timeout ...time.Duration) tool.Tool

ConfineBash returns the bash built-in bound to an OS-sandbox spec, overriding the unconfined instance registered at init. When the spec enforces, bash runs each command through the sandbox (see package sandbox).

func ConfineReaders

func ConfineReaders(roots []string) []tool.Tool

ConfineReaders returns read_file/grep bound to roots — the only directories they may read from. Unlike ConfineWriters (always on), this is OPT-IN: by default read tools are unconfined because an agent legitimately reads /etc, system headers, ~/.gitconfig, package caches, etc. A deployment that wants a read/data-isolation boundary (not just a write boundary) configures sandbox read_roots and boot wires these in to override the unconfined instances. An empty roots slice yields unconfined readers (no-op).

NOTE: even with this on, bash is NOT read-confined (it can cat any readable file), so this is a defense-in-depth measure, not a complete read isolation. glob is also left unconfined because a glob pattern isn't a single path to check. See security audit finding A7.

func ConfineSearch

func ConfineSearch(spec SearchSpec) tool.Tool

ConfineSearch returns the grep built-in bound to a resolved search engine, overriding the native instance registered at init.

func ConfineWebFetch

func ConfineWebFetch(proxySpec netclient.ProxySpec) tool.Tool

ConfineWebFetch returns the web_fetch built-in bound to fairpeer proxy settings while preserving its SSRF-guarded dialer.

func ConfineWriters

func ConfineWriters(roots []string) []tool.Tool

ConfineWriters returns the file-writing built-ins bound to roots — the only directories they may modify: write_file, edit_file, multi_edit, and the document writers (doc_write, csv_write, xlsx_write, doc_convert). The composition root adds these to the per-run registry to override the unconfined instances registered at init time, so writes stay inside the workspace by default. roots may be relative; they are resolved to absolute, symlink-free paths once here. An empty roots slice yields unconfined writers.

ConfineReaders is the read-side counterpart: when sandbox read_roots is configured, it returns read_file/grep AND the document readers (doc_read, csv_read, xlsx_read) bound to those roots so the agent can't read host files outside them. By default read tools are unconfined (see ConfineReaders note). This keeps the workspace boundary a WRITE boundary by default — read isolation is opt-in for high-security deployments. Audit A7.

func ConsoleBack added in v0.2.0

func ConsoleBack() (string, error)

ConsoleBack goes back one history entry in the console session.

func ConsoleClick added in v0.2.0

func ConsoleClick(target string) (string, error)

ConsoleClick accepts a snapshot ref ("e5") or a CSS selector.

func ConsoleClose added in v0.2.0

func ConsoleClose() error

ConsoleClose stops any active recording, then closes the session. For the PERSISTENT console browser (ownsBrowser) this truly CLOSES the browser — graceful CDP Browser.close: every tab plus the process, with the profile flushed to disk (login state survives for the next open). Explicit user attaches keep the old semantics: disconnect only, their browser lives.

func ConsoleDetectOnce added in v0.2.0

func ConsoleDetectOnce(condition string) (bool, string, error)

ConsoleDetectOnce checks a wait-style condition a single time WITHOUT blocking — the human-breakpoint auto-continue poll. Supported conditions: visible:<selector>, hidden:<selector>, url:<text> (location contains), title:<text> (title contains). Empty condition reports true.

func ConsoleDevTools added in v0.2.0

func ConsoleDevTools() ([]ConsoleLogEntry, []NetEntry, error)

ConsoleDevTools returns the console session's buffered logs + network entries (newest last) for the workbench's bottom pane.

func ConsoleEvaluate added in v0.2.0

func ConsoleEvaluate(expression string) (string, error)

func ConsoleExtract added in v0.2.0

func ConsoleExtract(selector string) (string, error)

func ConsoleExtractAs added in v0.2.0

func ConsoleExtractAs(selector, format string) (string, error)

ConsoleExtractAs extracts with an explicit format: "" plain text, "table" markdown tables, "markdown" structure-preserving render.

func ConsoleExtractTable added in v0.2.0

func ConsoleExtractTable(selector string) (string, error)

ConsoleExtractTable extracts every <table> under selector (or the page) as markdown — structure-preserving for log grids and result tables.

func ConsoleForward added in v0.2.0

func ConsoleForward() (string, error)

ConsoleForward goes forward one history entry in the console session.

func ConsoleHighlight added in v0.2.0

func ConsoleHighlight(target string, durationMs int) error

ConsoleHighlight marks a target in the page so the user can SEE which element a list row refers to — the mirror preview must catch it, so the mark is designed for screenshots:

durationMs > 0: transient flash (hover affordance), restored after the
  duration via the element's previous inline styles.
durationMs <= 0: PERSISTENT mark — a __fp-hl class backed by one injected
  style rule. Selecting another target replaces the mark; highlighting
  the SAME target toggles it off. Survives until then, so any poll cadence
  (sidebar frames, the workbench's 5s) catches it.

Both paths scroll the element into view and push a mirror frame right away — the preview refreshes the instant the mark lands, not on the next action.

func ConsoleHover added in v0.2.0

func ConsoleHover(target string) (string, error)

ConsoleHover hovers the pointer over a target (ref or CSS) — a real mousemove to the element center, so CSS :hover menus open.

func ConsoleKey added in v0.2.0

func ConsoleKey(key string) error

ConsoleKey presses a special key: enter | tab | escape.

func ConsoleNavigate added in v0.2.0

func ConsoleNavigate(url string) (string, error)

func ConsoleRecordStart added in v0.2.0

func ConsoleRecordStart() error

ConsoleRecordStart (re)arms the recorder on the console session: a CDP binding carries page events back, and the injected script persists across navigations (new-document hook) so a multi-page run records end-to-end. Installation is a handful of millisecond-level CDP calls — a 15s budget fails fast instead of piling onto a wedged session for a full minute.

func ConsoleScreenshot added in v0.2.0

func ConsoleScreenshot() (string, error)

ConsoleScreenshot captures the current viewport as a PNG data URL — the panel's visual check plus a potential verification artifact.

func ConsoleScroll added in v0.2.0

func ConsoleScroll(direction string, amount int) (string, error)

func ConsoleSelectOption added in v0.2.0

func ConsoleSelectOption(target, value string) (string, error)

ConsoleSelectOption picks an option on a <select> by value or label. Anchored targets (`;;` chains, bare text=) route through the flow runner — the picker's rows carry selector refs, and a raw "text=..." used to reach querySelector and SyntaxError.

func ConsoleSwitchTab added in v0.2.0

func ConsoleSwitchTab(index int) (string, error)

ConsoleSwitchTab switches the console session onto another tab (1-based index from ConsoleTabs); the current tab stays open.

func ConsoleSwitchTabByTitle added in v0.2.0

func ConsoleSwitchTabByTitle(title string) (string, error)

ConsoleSwitchTabByTitle switches by tab title (exact then contains) — users know tabs by name, and indexes drift as tabs open and close.

func ConsoleType added in v0.2.0

func ConsoleType(target, text string) (string, error)

ConsoleType types text into the element named by target (ref or CSS), clearing it first.

func ConsoleUploadFile added in v0.2.0

func ConsoleUploadFile(target string, files []string) (string, error)

func ConsoleWait added in v0.2.0

func ConsoleWait(condition string, timeoutSec int) (string, error)

func DocumentTools

func DocumentTools() []tool.Tool

DocumentTools returns the document tools for cowork registration.

func EmailTools

func EmailTools() []tool.Tool

EmailTools returns the email tools for cowork registration: send (SMTP) plus read/search (IMAP) when configured.

func EmitBrowserPanel added in v0.2.0

func EmitBrowserPanel(f BrowserPanelFrame)

EmitBrowserPanel forwards a frame when a sink is registered.

func ExpertTools

func ExpertTools() []tool.Tool

ExpertTools returns the expert-team tools for cowork registration.

func IMTools

func IMTools() []tool.Tool

IMTools returns the IM-push tools for cowork registration. Hidden from the dev main-loop schema (via reg.Hide in boot.go) but callable by subagents, matching EmailTools / CalendarTools / SchedulerTools.

func NetDevRAGTools added in v0.2.0

func NetDevRAGTools() []tool.Tool

NetDev knowledge-namespace tools (NETDEV_SPEC §7.1/§7.2). The ops tool set includes a rag_search scoped to the "netdev:" collection namespace (vendor docs, config backups). The boundary is bidirectional:

  • these tools are PINNED to the namespace — the agent cannot widen the scope, so an ops session never reads the office knowledge base;
  • the cowork rag_* tools refuse/namespace-filter the "netdev:" prefix and the store excludes the namespace from empty-scope searches, so dev/cowork sessions never read ops knowledge.

Import writes only to fairpeer's local knowledge store (never to a device), which is inside the netdev seal's intent — the seal removes network/exec write paths, not fairpeer's own local state (findings/proposals write locally the same way).

func ParseFlowParams added in v0.2.0

func ParseFlowParams(arguments string) map[string]string

ParseFlowParams turns run_skill arguments into the runtime parameter map: "工单号=A123 日期=2026-09-01" → {"工单号":"A123","日期":"2026-09-01"}. Quoted values ("k=a b") keep their spaces. A string with no '=' at all is stored under "问题" (the stream-query convention's ask bind).

func ProbeAccountIMAP

func ProbeAccountIMAP(account string) error

ProbeAccountIMAP cheaply verifies that account (default when empty) can connect + log in to IMAP, without fetching mail. Returns nil when the account has no IMAP host (a send-only setup) so it doesn't block send-only tasks. On an auth failure it returns a friendly error and fires the auth-expired toast. Used to surface an expired 139 authorization code (90-day life) up front, before a scheduled task burns tokens.

func ProbeIMAPConfig

func ProbeIMAPConfig(cfg config.IMAPConfig) error

ProbeIMAPConfig verifies a standalone IMAP config can connect + log in + select INBOX, without fetching mail. Exported so the desktop settings panel can probe a freshly saved mailbox WITHOUT going through the global emailAccounts slice (which is only refreshed on boot, not on every save). Returns a friendly error on auth failure. Caller sets the timeout.

func RAGTools

func RAGTools() []tool.Tool

RAGTools returns the knowledge-base tools for cowork registration.

func ReadWorkbookAsTable added in v0.2.0

func ReadWorkbookAsTable(path string, maxRows int) (string, int, error)

ReadWorkbookAsTable reads an exported workbook (.xlsx first sheet, or .csv) as a markdown pipe table for LLM alert triage. Streaming row iterator with a maxRows cap — a 50k-row SIEM export never materializes whole, the model gets the first maxRows rows plus the real total so truncation is explicit. Cells are clipped to cellClipRunes runes (wide log-message columns would otherwise drown the table). Legacy .xls is rejected with a hint.

func ResolveTimeRange added in v0.2.0

func ResolveTimeRange(now time.Time, s string) (string, bool)

ResolveTimeRange converts a relative time-range phrase into the literal "start - end" string. ok=false means the value is not a recognized phrase — callers pass it through untouched. now anchors the relative words.

func RunBrowserFlow added in v0.2.0

func RunBrowserFlow(ctx context.Context, body, arguments string) (string, error)

RunBrowserFlow executes a browser-flow skill body deterministically: parse the 步骤 table, validate bindings, open one browser session, run every step through the agent's own browser primitives, and return a per-step report. wired into run_skill by boot (skill.SetFlowRunner).

func SchedulerTools

func SchedulerTools() []tool.Tool

SchedulerTools returns the scheduled-task tools for cowork registration.

func ScreenTools

func ScreenTools() []tool.Tool

ScreenTools returns the desktop-automation tools available on macOS/Linux.

All tools work cross-platform:

  • screen_click/type/scroll/key: via cliclick (macOS) / xdotool (Linux)
  • screen_perceive: VLM-only (screenshot → vision model → coordinates, no UIA)

screenCapture is not included here; it's registered separately in the screenshot-hotkey pipeline (capture_darwin.go / capture_linux.go).

func SendPlainText

func SendPlainText(ctx context.Context, to, subject, body string) error

SendPlainText delivers a plain-text email using the Default account's SMTP settings. Exposed so non-tool callers (the scheduler's email delivery bridge) can reuse the same SMTP wiring without duplicating it. Returns an error if no account is configured. The ctx bounds dial/handshake and cancels a stalled send; pass context.Background() when no cancellation is needed.

func SendPlainTextAs

func SendPlainTextAs(ctx context.Context, account, to, subject, body string) error

SendPlainTextAs delivers a plain-text email using the named account's SMTP settings. An empty account selects the Default account. Used by the scheduler and calendar reminder engine to send via a user-chosen mailbox rather than always the default. The ctx bounds dial/handshake and cancels a stalled send.

func SetAuthNotifier

func SetAuthNotifier(n AuthNotifier)

SetAuthNotifier injects the credentials-expired notifier (desktop toast).

func SetBrowserAutoRuntime

func SetBrowserAutoRuntime(rt BrowserAutoRuntime)

SetBrowserAutoRuntime injects the boot-owned runtime. Called at each boot.Build, mirroring SetProviderChatRunner / SetBrowserLaunchOptions.

func SetBrowserLaunchOptions

func SetBrowserLaunchOptions(headless bool, userDataDir, proxyServer string)

SetBrowserLaunchOptions injects the browser launch config (headless toggle, persistent user-data-dir, proxy URL). boot.go calls this after resolving the cowork config and the proxy spec. Empty proxyServer means "no proxy" (the browser uses the system default), matching chromedp's behaviour.

func SetBrowserPanelSink added in v0.2.0

func SetBrowserPanelSink(fn func(BrowserPanelFrame))

SetBrowserPanelSink registers the desktop's mirror forwarder (Wails event emitter). Set once at startup; nil (CLI) disables emission entirely.

func SetBrowserRecordSink added in v0.2.0

func SetBrowserRecordSink(fn func(ConsoleRecordEvent))

SetBrowserRecordSink registers the desktop's event forwarder. Set once at startup; the listener no-ops on a nil sink.

func SetCalendarStore

func SetCalendarStore(s *calendar.Store)

func SetConfiguredBrowserPath

func SetConfiguredBrowserPath(p string)

SetConfiguredBrowserPath injects the config's [cowork] browser_path override. Called once at boot (per controller build). Empty means "auto-detect". This is the user-facing way to point at a non-standard browser location, surfaced via the agent when no browser is found.

func SetEmailAccounts

func SetEmailAccounts(accounts []config.EmailAccount)

SetEmailAccounts injects the multi-mailbox config. Called from boot.go at startup and from the desktop settings panel when the user saves a config change, so tools pick up new/edited accounts without a restart.

func SetExpertOrchestrator

func SetExpertOrchestrator(o *experts.Orchestrator)

SetExpertOrchestrator injects the app-level orchestrator the tool drives. Called once at cowork boot; nil disables the tool ("experts offline").

func SetExpertStore

func SetExpertStore(s *experts.Store)

SetExpertStore injects the team store so the tool can list teams for auto-selection (when team_id is omitted). nil disables that lookup.

func SetIMPusher

func SetIMPusher(p imPusher)

SetIMPusher injects the IM gateway (e.g. *bot.BotGateway). Called from desktop/bot_gateway_app.go after gw.Start succeeds, mirroring SetCalendarStore / SetScheduler. Passing nil (e.g. on stopBotGateway) disables the tool so it reports offline cleanly instead of nil-derefing.

func SetPostEditHook

func SetPostEditHook(fn func(ctx context.Context, path string) string)

SetPostEditHook installs the post-write diagnostics hook. boot.go calls this with a closure over the LSP manager; passing nil disables the hook.

func SetProviderChatRunner

func SetProviderChatRunner(fn func(ctx context.Context, model string, msgs []provider.Message) ([]provider.Message, error))

SetProviderChatRunner injects the provider chat runner from boot.go (which has access to the resolved provider config). Avoids a circular import between tool/builtin and provider/boot.

func SetRAGEmbedder

func SetRAGEmbedder(e rag.Embedder)

SetRAGEmbedder injects an embedder for hybrid (FTS5 + semantic) reranking. Called at boot when [cowork] embedding_model is configured; nil = FTS5-only.

func SetRAGLLM

func SetRAGLLM(l *rag.LLMSemantic)

SetRAGLLM injects the LLM semantic layer (SPEC v2 §3.6). Called at boot when a provider is available; nil = FTS5-only (graceful degradation). The layer is automatic — the user never configures it, it just improves recall/precision using the provider key they already set up.

func SetRAGSessionResolver

func SetRAGSessionResolver(fn func() []string)

SetRAGSessionResolver injects a callback that returns the session's active collections. This bridges the desktop UI's "activate collection" control to the agent's rag_search calls — without it, the UI selection has no effect on LLM-driven searches. Called once at cowork boot.

func SetRAGStore

func SetRAGStore(s *rag.Store)

SetRAGStore injects the knowledge-base store. Called once at cowork boot.

func SetScheduler

func SetScheduler(s *scheduler.Scheduler)

SetScheduler injects the app-level scheduler the tools drive. Called once at cowork boot; passing nil disables the tools (they return "scheduler offline").

func SetVLMModel

func SetVLMModel(model string)

SetVLMModel sets the vision model used by CallVLM. boot.go calls this after resolving config. An empty model is accepted; CallVLM will then return a "no VLM model configured" error, guiding the user to set a vision-capable model in Settings.

func SetVoiceModel added in v0.2.0

func SetVoiceModel(model string)

SetVoiceModel sets the STT model used by CallSTT. boot.go calls this after resolving config. An empty model is accepted; CallSTT then returns a "no voice model configured" error, guiding the user to set an audio-capable model in Settings.

func TimeRangeBounds added in v0.2.0

func TimeRangeBounds(s string) (start, end time.Time, ok bool)

TimeRangeBounds parses a literal "start - end" range back into instants — the watch uses the end to anchor contiguous coverage across rounds.

func TimeRangeFromSpan added in v0.2.0

func TimeRangeFromSpan(now time.Time, d time.Duration) string

TimeRangeFromSpan builds the literal range covering [now-d, now] — the rolling window a periodic watch round exports each interval.

func WindowTools

func WindowTools() []tool.Tool

WindowTools returns the window-management tool set. On non-Windows platforms there's no Win32 window API to drive, so it returns nil — cowork mode simply registers no window_* tools there, matching how ScreenTools behaves. The Windows build (window_windows.go) provides the real implementations.

func WrapUntrusted

func WrapUntrusted(source, content string) string

WrapUntrusted wraps externally-sourced content (web pages, browser DOM, RAG snippets) in an <untrusted_content> tag. The cowork system prompt instructs the model to treat anything inside this tag as DATA, never as instructions — the core defense against prompt injection from malicious web pages or documents that try to hijack the agent ("ignore previous instructions…").

source identifies where the content came from ("browser", "web", "rag") so the model can weigh trust and the user can audit the provenance in tool output. An empty content still gets wrapped so the boundary is always explicit — never let untrusted text bleed into the model's context without a clear fence around it.

SECURITY: content is sanitized so a literal </untrusted_content> inside it cannot close the fence early. The closing tag is split into HTML-entity- encoded pieces the model still reads as data but that no longer match the fence boundary. This is the ONLY defense against prompt injection from fetched content, so it must be airtight.

Exported so non-builtin packages (e.g. desktop expert-team injection, boot-time RAG auto-search) can share the same airtight fence instead of hand-rolling <untrusted_content> tags that forget to sanitize.

func XLSXWriteRows

func XLSXWriteRows(path string, rows [][]string) error

XLSXWriteRows writes rows to a .xlsx file at path via excelize (one sheet, "Sheet1"). Produces a fully-valid workbook openable in Excel/WPS/LibreOffice. The write is crash-atomic (temp + fsync + rename) so a crash mid-write can't leave a torn, unopenable .xlsx at the target.

func XLSXWriteStructured

func XLSXWriteStructured(wb XLSXWorkbook) (int, error)

XLSXWriteStructured writes a multi-sheet styled workbook via excelize. Produces a fully-valid .xlsx openable in Excel/WPS/LibreOffice. Returns the sheet count for the success message.

Types

type AuthNotifier

type AuthNotifier interface {
	NotifyAuthExpired(account string)
}

AuthNotifier is an optional sink for "email credentials expired" notices. The desktop app injects one that fires an in-app toast, so the user learns their 139 authorization code needs renewing even mid-task. Nil = silent (the error still surfaces in the tool result and conversation).

type BrowserAutoRunRequest

type BrowserAutoRunRequest struct {
	Goal     string
	URL      string
	MaxSteps int
}

BrowserAutoRunRequest is the goal-oriented request the runtime executes. The LLM model/base_url/proxy are resolved from config inside the runtime (runBrowserAuto), NOT carried here — this struct only holds the per-call goal.

type BrowserAutoRuntime

type BrowserAutoRuntime struct {
	// Available reports whether autonomous browsing is ready to use (sidecar up
	// + a browser can be found). Returns (ok, reason) where reason explains why
	// not (for a helpful tool error).
	Available func() (ok bool, reason string)
	// Run launches the shared browser, mirrors it to the in-app panel, drives
	// the sidecar loop, and returns the streamed steps. The context governs
	// cancellation (user Stop / turn cancel). It must close the browser when
	// done (or on error).
	Run func(ctx context.Context, req BrowserAutoRunRequest) (steps []BrowserAutoStep, finalSummary string, err error)
}

BrowserAutoRuntime is the injected dependency. Each field is a function the boot layer supplies; nil fields cause browser_auto to report that the feature is unavailable rather than crash.

type BrowserAutoStep

type BrowserAutoStep struct {
	Type string // thought | action | screenshot | done | error
	Step int
	Text string
	Done bool
}

BrowserAutoStep is one event from the sidecar's agentic loop. It's defined here (not imported from internal/browseruse) so builtin has no dependency on that package and the wiring closure does the conversion.

type BrowserPanelFrame added in v0.2.0

type BrowserPanelFrame struct {
	Kind   string `json:"kind"`
	Source string `json:"source"`          // "tool" (chromedp tools) | "auto" (browser-use sidecar)
	Phase  string `json:"phase,omitempty"` // status only: "start" | "end"
	Text   string `json:"text,omitempty"`
	URL    string `json:"url,omitempty"`
	Image  string `json:"image,omitempty"` // data URL (frame only)
	// SessionID tags every frame with the browser session that produced it,
	// so the frontend can keep per-session mirrors (the ops viewer shows the
	// console session AND agent-driven sessions side by side).
	SessionID string `json:"session_id,omitempty"`
}

BrowserPanelFrame is one update for the desktop's browser-mirror panel. Kind "frame" carries a screenshot (Image as data URL); kind "status" carries a lifecycle transition (Phase "start"|"end"). The frontend owns all labels — Text stays machine-ish (browser name, summary) rather than localized prose.

type ConsoleElement added in v0.2.0

type ConsoleElement struct {
	Ref   string `json:"ref"`
	Role  string `json:"role"`
	Name  string `json:"name"`
	Value string `json:"value,omitempty"`
	// CSS is the element's stable selector (computed at capture time). Picking
	// the row fills the target with `css;;text=name` — recorded skills stay
	// valid across sessions; the bare ref dies with the snapshot.
	CSS string `json:"css,omitempty"`
}

ConsoleElement is one interactive element from the page's accessibility tree — the panel's element picker. Refs are snapshot-transient: usable for immediate click/type, but persisted skills must use CSS selectors.

type ConsoleElementsResult added in v0.2.0

type ConsoleElementsResult struct {
	Elements []ConsoleElement `json:"elements"`
	Note     string           `json:"note,omitempty"`
}

ConsoleElementsResult is the picker's payload plus a degradation note: when the full AX-tree capture fails (huge pages, streaming renderers that starve the main thread past the 60s action timeout), the DOM-complement sweep still returns the interactive elements — selector-based rows work for click/type/highlight, only e-ref rows are unavailable.

func ConsoleElements added in v0.2.0

func ConsoleElements() (ConsoleElementsResult, error)

type ConsoleLogEntry added in v0.2.0

type ConsoleLogEntry struct {
	Type string `json:"type"` // log|warning|error|info|debug|exception
	Text string `json:"text"`
	Time int64  `json:"time"` // unix millis
}

ConsoleLogEntry is one page console message (or exception).

type ConsoleRecordEvent added in v0.2.0

type ConsoleRecordEvent struct {
	Type     string `json:"type"` // click|input|change|submit|navigate|scroll|effect
	Selector string `json:"selector,omitempty"`
	Role     string `json:"role,omitempty"`
	Name     string `json:"name,omitempty"`
	Value    string `json:"value,omitempty"` // scroll: "<direction> <screens>"
	URL      string `json:"url,omitempty"`
	Time     int64  `json:"time"` // unix millis
	// Effective (click only, merged from follow-up "effect" events): the
	// click observably changed the DOM. nil = unknown.
	Effective *bool `json:"effective,omitempty"`
	Password  bool  `json:"password,omitempty"`
}

ConsoleRecordEvent is one captured user interaction (or navigation) while recording. Password values are never captured — Password marks the field so the generated skill prompts at run time instead.

func ConsoleRecordStop added in v0.2.0

func ConsoleRecordStop() []ConsoleRecordEvent

ConsoleRecordStop disarms the recorder and returns the captured trace as-is (deterministic filtering is a separate, pure step — FilterRecordEvents; AI comprehension lives in the desktop layer).

func FilterRecordEvents added in v0.2.0

func FilterRecordEvents(events []ConsoleRecordEvent) (kept, dropped []ConsoleRecordEvent)

type ConsoleScanElement added in v0.2.0

type ConsoleScanElement struct {
	Role     string `json:"role"`
	Name     string `json:"name"`
	Selector string `json:"selector"` // #id | tag[name="…"] | text=可见文字
}

ConsoleScanElement is one row from a deep scan. Selector is a stable anchor usable as a click/type target (the ref slot in the panel list).

type ConsoleScanResult added in v0.2.0

type ConsoleScanResult struct {
	Elements []ConsoleScanElement `json:"elements"`
	Scrolls  int                  `json:"scrolls"`  // scroll steps performed
	Screens  int                  `json:"screens"`  // ≈ viewport heights traversed
	NewLast  int                  `json:"new_last"` // new elements found in the last step
	Stop     string               `json:"stop"`
}

ConsoleScanResult is the deep scan's payload plus the transparency the "infinite" case demands: how far it scrolled, how much it found, and WHY it stopped (no-new | bottom | max-scrolls | cap).

func ConsoleDeepScan added in v0.2.0

func ConsoleDeepScan(maxScrolls int) (ConsoleScanResult, error)

ConsoleDeepScan is the panel binding: scroll-collect over the console session's current tab.

func ScanPage added in v0.2.0

func ScanPage(ctx context.Context, maxScrolls int) (ConsoleScanResult, error)

ScanPage runs the scroll-collect loop against any chromedp tab context — exported so the console binding and headless verification harnesses share one implementation. Restores the original scroll position on return.

type ConsoleState added in v0.2.0

type ConsoleState struct {
	Open      bool   `json:"open"`
	SessionID string `json:"session_id"`
	Browser   string `json:"browser"`
	Attached  bool   `json:"attached"`
	URL       string `json:"url"`
	// Keep-alive (会话保活): a long-idle console session survives both the
	// kernel's idle reaper and the site's own session expiry.
	KeepAlive     bool   `json:"keep_alive"`
	KeepAliveMode string `json:"keep_alive_mode"` // ping|navigate|local
	KeepAliveURL  string `json:"keep_alive_url"`  // navigate-mode target ("" = current page)
	KeepAliveLast int64  `json:"keep_alive_last"` // unix millis of the last successful refresh
	KeepAliveErr  string `json:"keep_alive_err"`  // last refresh failure ("" = ok)
}

ConsoleState describes the console's browser session for the panel header.

func ConsoleOpen added in v0.2.0

func ConsoleOpen(cdpURL, startURL string) (ConsoleState, error)

ConsoleOpen ensures the console session exists — spawning a visible browser (independent tab, isolated from the agent's own sessions) or attaching to an external one when cdpURL is set — and optionally navigates to startURL.

func ConsoleSetKeepAlive added in v0.2.0

func ConsoleSetKeepAlive(enabled bool, intervalSec int, mode, url string) (ConsoleState, error)

ConsoleSetKeepAlive arms or disarms the console session's keep-alive loop (session-level machinery lives in browser.go — the same loop the browser_keepalive tool arms on agent sessions) and returns the resulting state. mode: "" or "ping" (page heartbeat fetch), "navigate" (periodic reload), "local" (reaper-side only). intervalSec clamps to [60, 3600] with a 300s default.

func ConsoleStateOf added in v0.2.0

func ConsoleStateOf() (ConsoleState, error)

ConsoleStateOf reports the current session, or a zero (closed) state.

type ConsoleTab added in v0.2.0

type ConsoleTab struct {
	Index   int    `json:"index"` // 1-based
	Title   string `json:"title"`
	URL     string `json:"url"`
	Current bool   `json:"current"`
}

ConsoleTab is one open tab of the console session's browser.

func ConsoleTabs added in v0.2.0

func ConsoleTabs() ([]ConsoleTab, error)

ConsoleTabs lists the console browser's tabs, marking the one the session drives — the panel's tab strip.

type DocError added in v0.1.5

type DocError struct {
	Code       string `json:"code"`
	Message    string `json:"message"`
	Suggestion string `json:"suggestion,omitempty"`
}

DocError is the LLM-facing error type for document operations. The Code is a stable machine-readable identifier the model can branch on; Suggestion tells it how to recover (close the file, fix the index, convert the image). Mirrors OfficeCLI's CliException { Code, Suggestion, ValidValues }.

func (DocError) Error added in v0.1.5

func (e DocError) Error() string

type DocInput

type DocInput struct {
	Path     string       `json:"path"`
	Title    string       `json:"title"` // optional document title (rendered as H1 if non-empty)
	Sections []DocSection `json:"sections"`
	Append   bool         `json:"append,omitempty"` // when true, insert sections into existing docx
}

DocInput is the top-level payload for writeDOCX.

type DocSection

type DocSection struct {
	Type    string     `json:"type"`    // "heading"|"paragraph"|"list"|"table"|"image"|"toc"
	Level   int        `json:"level"`   // heading level (1-6, default 1)
	Text    string     `json:"text"`    // heading/paragraph text; list single item (when Items empty)
	Items   []string   `json:"items"`   // list items (type=list)
	Ordered bool       `json:"ordered"` // list ordered? (type=list)
	Headers []string   `json:"headers"` // table header cells (type=table)
	Rows    [][]string `json:"rows"`    // table body rows (type=table)
	Style   DocStyle   `json:"style"`   // run styling (bold/italic/color/size/font/align)

	// Image fields (type=image). Supported: PNG/JPG/GIF. SVG is NOT supported
	// (Word needs a PNG raster fallback + asvg extension; convert SVG to PNG
	// first — writeDOCX returns an explicit error for .svg paths).
	ImagePath   string `json:"image_path,omitempty"`   // path to image file (PNG/JPG/GIF)
	ImageAlt    string `json:"image_alt,omitempty"`    // alt text for accessibility (→ wp:docPr descr)
	ImageWidth  int    `json:"image_width,omitempty"`  // image width in pixels (0 = default 400)
	ImageHeight int    `json:"image_height,omitempty"` // image height in pixels (0 = default 300)

	// TOC fields (type=toc)
	TOCLevel int `json:"toc_level,omitempty"` // depth of TOC (heading levels 1-N; default 3)
}

DocSection is one block of the document. Type selects the renderer; the shared Style applies to text runs within the section where relevant.

type DocStyle

type DocStyle struct {
	Bold        bool    `json:"bold"`
	Italic      bool    `json:"italic"`
	Color       string  `json:"color"`       // "#RRGGBB"
	Size        int     `json:"size"`        // half-points (24 = 12pt); 0 = default
	Font        string  `json:"font"`        // font family; "" = default
	Align       string  `json:"align"`       // "left"|"center"|"right" (paragraph-level)
	Bg          string  `json:"bg"`          // table cell shading "#RRGGBB"
	LineSpacing float64 `json:"lineSpacing"` // line spacing multiplier (1.5 = 1.5×); 0 = default
	Indent      int     `json:"indent"`      // first-line indent in characters; 0 = none
	HeaderBg    string  `json:"header_bg"`   // table header row shading "#RRGGBB"
}

DocStyle is the shared run/paragraph style vocabulary. Color is "#RRGGBB".

type DownloadInfo added in v0.2.0

type DownloadInfo struct {
	Name  string `json:"name"`
	Path  string `json:"path"`
	State string `json:"state"` // "completed"
}

DownloadInfo describes one finished browser download — the structured form of the "wait download" condition, for panel trial runs and watch rounds.

func ConsoleWaitDownload added in v0.2.0

func ConsoleWaitDownload(timeoutSec int) (DownloadInfo, error)

ConsoleWaitDownload blocks until a download triggered by an earlier action reaches a terminal state (SIEM exports run 20s–5min) and returns the file's verified full path. Structured sibling of the "download" wait condition.

type EmailAttachment

type EmailAttachment struct {
	Name string `json:"name"`
	Size int    `json:"size"`
}

EmailAttachment is metadata for one email attachment.

type EmailMessage

type EmailMessage struct {
	From        string            `json:"from"`
	To          string            `json:"to"`
	Subject     string            `json:"subject"`
	Date        string            `json:"date"` // RFC3339 ("2006-01-02T15:04:05Z07:00"), ISO 8601 so the JS frontend parses it reliably
	Preview     string            `json:"preview"`
	Attachments []EmailAttachment `json:"attachments,omitempty"`
	// contains filtered or unexported fields
}

EmailMessage is the read/search result: envelope fields + a body preview.

func ReadInboxFor

func ReadInboxFor(cfg config.IMAPConfig, mailbox string, limit int, unreadOnly bool) ([]EmailMessage, error)

ReadInboxFor reads the most recent `limit` messages from a mailbox (INBOX by default; "Sent" for the sent view). Unread-only when unreadOnly=true (ignored for non-INBOX). Exported so the cowork dock's "邮件" tab can preview mail WITHOUT going through the agent tool path. Same pattern as ProbeIMAPConfig: standalone config, own timeout, friendly error on auth/connection failure.

type FlowStep added in v0.2.0

type FlowStep struct {
	Type       string   `json:"type"`
	Target     string   `json:"target,omitempty"`
	URL        string   `json:"url,omitempty"`
	Text       string   `json:"text,omitempty"`
	Value      string   `json:"value,omitempty"`
	Direction  string   `json:"direction,omitempty"`
	Amount     int      `json:"amount,omitempty"`
	Condition  string   `json:"condition,omitempty"`
	TimeoutSec int      `json:"timeout_sec,omitempty"`
	Files      []string `json:"files,omitempty"`
	Expression string   `json:"expression,omitempty"`
}

FlowStep is one executable row of the 步骤 table (same grammar the ops editor serializes; JSON tags mirror the console step wire shape).

func ParseFlowTable added in v0.2.0

func ParseFlowTable(body string) ([]FlowStep, error)

ParseFlowTable extracts the 步骤 table from a skill body. Tolerant of the editor's exact dialect: `| # | 操作 | 目标 | 值 |` header, --- separator, backticked targets, trailing empty value cells.

type MMInput

type MMInput struct {
	Path     string   `json:"path"`     // output path; .md or .html decides format
	Title    string   `json:"title"`    // root node label
	Branches []MMNode `json:"branches"` // top-level branches off the root
	Format   string   `json:"format"`   // "md" | "html" (default: infer from path ext)
}

MMInput is the mindmap_create payload.

type MMNode

type MMNode struct {
	Text     string   `json:"text"`           // node label (required)
	Children []MMNode `json:"children"`       // sub-branches
	Note     string   `json:"note,omitempty"` // optional side note (md: italic; html: tooltip)
}

MMNode is one node in the mind-map tree.

type NetEntry added in v0.2.0

type NetEntry struct {
	Method  string `json:"method"`
	URL     string `json:"url"`
	Status  string `json:"status"` // "200" / "404" / "FAIL"
	ResType string `json:"res_type,omitempty"`
	Time    int64  `json:"time"`
}

NetEntry is one finished (or failed) network request.

type SearchCache added in v0.1.1

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

SearchCache provides an in-memory cache for web search results. This avoids repeated searches for the same query within a session. The cache is process- scoped (no SQLite, no files) so it never leaks credentials or stale results to disk, and it adds zero external dependencies (no CGO, no go-sqlite3).

func NewSearchCache added in v0.1.1

func NewSearchCache(_ string, ttl time.Duration) (*SearchCache, error)

NewSearchCache creates a new in-memory search cache with the given TTL. dbPath is accepted for API compatibility but ignored (in-memory only).

func (*SearchCache) Clear added in v0.1.1

func (c *SearchCache) Clear() error

Clear removes all cached results.

func (*SearchCache) Close added in v0.1.1

func (c *SearchCache) Close() error

Close is a no-op for in-memory cache (API compatibility).

func (*SearchCache) Get added in v0.1.1

func (c *SearchCache) Get(query string) ([]searchResultItem, string, bool)

Get retrieves cached search results for a query. Returns results, engine, and true if found and not expired.

func (*SearchCache) Prune added in v0.1.1

func (c *SearchCache) Prune() error

Prune removes expired entries (called opportunistically).

func (*SearchCache) Set added in v0.1.1

func (c *SearchCache) Set(query string, results []searchResultItem, engine string) error

Set stores search results in the cache.

type SearchSpec

type SearchSpec struct {
	RgPath string
}

SearchSpec configures the grep tool's engine. A non-empty RgPath makes grep delegate to that ripgrep binary; empty uses the native Go scanner.

func ResolveSearch

func ResolveSearch(engine, rgPath string, warn io.Writer) SearchSpec

ResolveSearch picks the grep engine from config. "native" forces the Go scanner; "rg" requires ripgrep (warns and falls back to native if absent); "auto"/"" uses ripgrep when found, else native. rgPath overrides the PATH lookup. warn (may be nil) receives the fall-back notice for engine="rg".

type Workspace

type Workspace struct {
	Dir         string
	WriteRoots  []string
	Bash        sandbox.Spec
	BashTimeout time.Duration
	Search      SearchSpec
	ProxySpec   netclient.ProxySpec
}

Workspace builds a built-in tool set bound to a working directory, so several agents can run concurrently with independent path roots — a desktop front-end opening one tab per project, say. The process working directory is global and cannot be made per-agent (os.Chdir is process-wide), so each tool instead resolves relative paths against this directory and bash runs in it.

Dir is that directory (empty yields process-cwd tools, byte-identical to the compile-time built-ins). WriteRoots confines the file-writers (as ConfineWriters); when empty and Dir is set, Dir itself becomes the sole write root, so writes stay inside the project by default. Bash is the OS-sandbox spec for the bash tool (as ConfineBash).

func (Workspace) Tools

func (w Workspace) Tools(enabled ...string) []tool.Tool

Tools returns the built-in tools bound to the workspace, ready to Add to a per-run tool.Registry. An empty enabled list yields every built-in; otherwise only the named ones are returned (unknown names are ignored). This is the per-workspace analogue of the cli's process-cwd assembly — a desktop driver calls it once per agent instead of relying on the global working directory.

type XLSXCell

type XLSXCell struct {
	Ref     string    `json:"ref"`     // A1 reference, e.g. "B3" (required)
	Value   *string   `json:"value"`   // literal value (string form; for text/labels)
	Number  *float64  `json:"number"`  // numeric value (stored as a real number cell)
	Formula *string   `json:"formula"` // e.g. "=SUM(B2:B5)" (overrides value/number when set)
	Format  string    `json:"format"`  // number format code, e.g. "#,##0", "0.00%", "yyyy-mm-dd"
	Style   XLSXStyle `json:"style"`
}

XLSXCell is one cell: a number, a value, or a formula, plus an optional style and number format. Ref is the A1 reference (e.g. "B3"); required. Precedence when more than one is set: Number > Formula > Value. Number is strongly typed so numeric cells stay numeric (formulas like =SUM() ignore text-stored numbers, so always use Number for numeric data you intend to sum).

type XLSXChart

type XLSXChart struct {
	Sheet         string `json:"sheet"`          // sheet name
	Type          string `json:"type"`           // "bar"|"line"|"pie"|"scatter"
	Title         string `json:"title"`          // chart title
	DataRange     string `json:"data_range"`     // value range (e.g., "B1:B10")
	CategoryRange string `json:"category_range"` // optional axis-label range (e.g., "A1:A10"); empty = positional
	Position      string `json:"position"`       // cell position for chart (e.g., "D2")
}

XLSXChart defines a chart to add to a sheet. DataRange is the VALUE range (the numbers to plot); CategoryRange (optional) is the axis-label range. When CategoryRange is empty the chart uses positional labels (1, 2, 3 …). Pass an explicit CategoryRange whenever you want named labels on the category axis (e.g. month names).

type XLSXColWidth

type XLSXColWidth struct {
	Col   string  `json:"col"`
	Width float64 `json:"width"`
}

XLSXColWidth sets a column's width by letter (e.g. {"A": 20}).

type XLSXCondFmt

type XLSXCondFmt struct {
	Range    string    `json:"range"`    // cell range (e.g., "A1:A10")
	Type     string    `json:"type"`     // "cell"|"data_bar"|"color_scale"
	Criteria string    `json:"criteria"` // cell type only: "greater_than"|"less_than"|"equal"|"between"
	Value    string    `json:"value"`    // threshold (for "between" use "min,max")
	Format   XLSXStyle `json:"format"`   // style to apply (bg drives bar/gradient color)
}

XLSXCondFmt defines conditional formatting for a range. Supported types are "cell", "data_bar", and "color_scale". For "cell", Format fills the matching cells; for "data_bar"/"color_scale", Format.Bg (or a sensible default) is used as the bar/gradient color.

type XLSXMerge

type XLSXMerge struct {
	Range string `json:"range"`
}

XLSXMerge is a merged range, A1 notation (e.g. "A1:C1").

type XLSXSheet

type XLSXSheet struct {
	Name      string         `json:"name"`  // sheet tab name (default "Sheet1")
	Cells     []XLSXCell     `json:"cells"` // sparse cells by ref
	Merges    []XLSXMerge    `json:"merges"`
	ColWidths []XLSXColWidth `json:"col_widths"`
	CondFmt   []XLSXCondFmt  `json:"cond_fmt,omitempty"` // conditional formatting
}

XLSXSheet is one worksheet.

type XLSXStyle

type XLSXStyle struct {
	Bold   bool   `json:"bold"`
	Italic bool   `json:"italic"`
	Color  string `json:"color"`  // font color "#RRGGBB"
	Bg     string `json:"bg"`     // cell fill "#RRGGBB"
	Size   int    `json:"size"`   // font size in points (not half-points; xlsx uses real pts)
	Font   string `json:"font"`   // font family
	Align  string `json:"align"`  // "left"|"center"|"right"
	Wrap   bool   `json:"wrap"`   // wrap text in cell
	Border bool   `json:"border"` // thin border all sides
}

XLSXStyle mirrors the run/cell style vocabulary shared with docx, plus a few xlsx-specifics (vertical align, border). Colors are "#RRGGBB" (we strip #).

type XLSXWorkbook

type XLSXWorkbook struct {
	Path   string      `json:"path"`
	Sheets []XLSXSheet `json:"sheets"`
	Charts []XLSXChart `json:"charts,omitempty"` // charts to add
}

XLSXWorkbook is the structured-write payload.

Jump to

Keyboard shortcuts

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