vfs

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2026 License: Apache-2.0 Imports: 51 Imported by: 0

Documentation

Overview

Package vfs is Tacklr's virtual filesystem: session mounts, path I/O, and content IR.

Public surface (hosts)

  • Tree / At / Union / OpenVFS — host builds one /workspace tree per turn (agent-visible). Union merges Opens at one alias. Skill catalogs use a second host-only Tree (AgentSpec.OpenSkills); they are not a workspace member.
  • MountSession — path I/O, ReadText / WriteDocument, ReadLines, FuseMount / Close, HostDir
  • FuseAvailable — process can mount a kernel tree (/dev/fuse or /dev/macfuse*)
  • ContentRev / ContentHash — session-visible content identity (for tools)
  • SessionAuth + TokenHolder + Binding — session-scoped user-owned credentials (never on MountSpec)
  • MountSpec — durable mount description (checkpoint-safe; Members = /workspace aliases)
  • WorkspacePoint — /workspace (the only top-level mount)
  • Provider / Open / S3API / DriveAPI / GraphAPI — custom backends (Blob uses S3API). Hosts construct default backends from package builtins (Local, S3, Blob, Drive, Graph, Memory, NewGoogleDrive, NewGraph).
  • File, FileInfo, DirEntry — I/O types (File is Close+Stat; io.Reader / io.ReaderAt / io.Writer via comma-ok)
  • Document / Textual / Structured / TextDocument — content IR
  • Block / StyleMeta / Span / FindBlock / BlockReplaceSpan — structured view
  • ContentRegistry + Codec + TextCodec + IdentityCodec — optional custom decode (Register is first-wins; Lookup is exported; overwrite returns ErrAlreadyRegistered)
  • DetectMediaType, size-cap constants, sentinel errors (including ErrFuseNotMounted, ErrAuthExpired, ErrAmbiguous, ErrPermission, ErrAlreadyRegistered)

Providers own IR translation and persist immediately on WriteDocument. MountSession routes; it does not encode or hold a dirty document cache.

Optimistic edit policy lives in harness tools (read, write) that wrap ReadText / TextDocument / WriteDocument. ContentRev is the stable token those tools pass — not a large MountSession surface.

This package never imports brain. Brain implements Provider in package brain (Engrams as Markdown files). Optional artifact IndexPath lives in package vfsindex (imports both; skips Profile=="brain"). FUSE / host rg read ReadText (provider IR plaintext). This package does not ship a grep tool.

Hosts should not need anything else. Mount tables, host roots, and bucket details stay inside providers and the unexported mount table.

Path I/O

Absolute virtual paths only, via MountSession:

Stat, Open, ReadFile, WriteFile, ReadDir, Remove, MkdirAll, FuseMount, Close
File is Close + Stat. Read / ReadAt / Write are optional (comma-ok).
FuseMount is explicit (host kernel tree). The only mount point is /workspace.
If ReadText succeeds, the kernel sees that plaintext
(read-only unless IdentityCodec). Otherwise Stat + io.ReaderAt. Close
unmounts. HostDir is the last FuseMount directory.

Read-only mounts reject mutating ops with ErrReadOnly. Local paths are jailed under the provider root (including symlink evaluation). S3 and Azure Blob use key prefixes and delimiter listing for virtual directories (MinIO/AWS/Azurite).

Content IR

Raw ops stay byte-oriented. Content access:

// Progressive page (large files OK; EOF/NextStart for paging)
win, err := ms.ReadLines(ctx, "/workspace/work/main.go", 1, 51)
// win.Rev.Hash is the session-visible content identity when available

// Full IR for edit; WriteDocument persists through the provider now
text, err := ms.ReadText(ctx, "/workspace/work/main.go") // Textual
rev := vfs.ContentRev{Path: text.Path(), Hash: vfs.ContentHash(text.Text())}
_ = text.SetLine(2, "changed")
_ = ms.WriteDocument(ctx, text)
_ = rev // tools compare expected rev before WriteDocument

Longer guide: docs/vfs.md in the repo root.

Index

Constants

View Source
const (
	ProviderGoogleDrive = "gdrive"
	ProviderMicrosoft   = "msgraph"
	ParamFolderID       = "folderId"
	ParamName           = "name"
	ParamDriveID        = "driveId"
	ParamItemID         = "itemId"
	ParamSiteID         = "siteId"
	// ParamAccount selects a Microsoft account kind on a bind ("organization" or "personal").
	ParamAccount = "account"
)

ProviderGoogleDrive is the bind kind for Drive. ProviderMicrosoft is the bind kind for OneDrive and SharePoint libraries.

View Source
const (
	AccountOrganization = "organization"
	AccountPersonal     = "personal"
)

Microsoft account kinds for Graph / ParamAccount. Organization (SharePoint / OneDrive for Business) is the default.

View Source
const (
	BlockKindPreamble  = "preamble"
	BlockKindHeading   = "heading"
	BlockKindParagraph = "paragraph"
	BlockKindListItem  = "list_item"
	BlockKindTable     = "table"
	BlockKindImage     = "image"
	BlockKindSheet     = "sheet"
)

Block kind vocabulary (stable for tools and brain props). Grow carefully.

View Source
const (
	MarkBold   = "bold"
	MarkItalic = "italic"
	MarkStrike = "strike"
	MarkHref   = "href"
)
View Source
const DefaultTokenRefreshSkew = time.Minute

DefaultTokenRefreshSkew refreshes a short-lived token before its hard expiry.

View Source
const (

	// MaxDocsExportBytes is the Drive files.export limit.
	MaxDocsExportBytes = 10 << 20
)
View Source
const MaxLineBytes = 1 << 20 // 1 MiB

MaxLineBytes caps a single line when streaming (ReadLines) or scanning.

View Source
const MaxLineScanBytes = 64 << 20 // 64 MiB

MaxLineScanBytes caps how many bytes a single streaming ReadLines call may read from the start of a file (or from a seek point later). Distinct from MaxReadFileBytes (full IR materialize).

View Source
const MaxLinesPerWindow = 500

MaxLinesPerWindow caps how many lines one ReadLines call may return.

View Source
const MaxReadFileBytes = 32 << 20 // 32 MiB

MaxReadFileBytes caps full-file reads and writes.

View Source
const (

	// MaxSheetCells is the hard cap on loaded cells in one workbook.
	MaxSheetCells = 200_000
)
View Source
const WorkspacePoint = "/workspace"

WorkspacePoint is the only top-level mount. Backends live at /workspace/<name> via Tree(At(...)).

Variables

View Source
var (
	ErrInvalidPath     = errors.New("vfs: invalid path")
	ErrAlreadyMounted  = errors.New("vfs: already mounted")
	ErrNotMounted      = errors.New("vfs: not mounted")
	ErrInvalidProvider = errors.New("vfs: invalid provider")
	ErrNotSupported    = errors.New("vfs: not supported")
	ErrReadOnly        = errors.New("vfs: read-only mount")
	ErrNotExist        = errors.New("vfs: not found")
	ErrNotDir          = errors.New("vfs: not a directory")
	ErrIsDir           = errors.New("vfs: is a directory")
	ErrExist           = errors.New("vfs: already exists")
	ErrFuseNotMounted  = errors.New("vfs: fuse not mounted")
	ErrAuthExpired     = errors.New("vfs: auth expired")
	ErrAmbiguous       = errors.New("vfs: ambiguous path")
	ErrPermission      = errors.New("vfs: permission denied")

	// Content IR
	ErrNoCodec = errors.New("vfs: no codec for media type")
	// ErrAlreadyRegistered is returned when Register is called for a media type
	// that already has a codec. First registration wins.
	ErrAlreadyRegistered = errors.New("vfs: media type already registered")
	ErrNotTextual        = errors.New("vfs: not a textual document")
	ErrLineOutOfRange    = errors.New("vfs: line out of range")
	ErrInvalidUTF8       = errors.New("vfs: invalid utf-8")
	ErrInvalidLine       = errors.New("vfs: line contains newline")
	ErrLineTooLong       = errors.New("vfs: line too long")
	ErrTooLarge          = errors.New("vfs: file too large")
	// ErrProjected is returned when a line/HTML/SetText mutation is applied to a
	// projected spreadsheet. Docs/Word accept HTML line and full-content writes.
	ErrProjected = errors.New("that write is not supported on this file type")
	// ErrConflict is a provider-level compare-and-swap failure.
	// Apply retries Docs/Word persist once; leftover conflict becomes ErrInvalidWrite.
	ErrConflict = errors.New("the file changed on the server since it was last read")
	// ErrStaleContent is tool/host optimistic concurrency (expected hash ≠ current).
	ErrStaleContent = errors.New("the file changed since last read")
	// ErrInvalidWrite is a persist that cannot apply (bad insert location, etc.).
	// Never wrap provider SDK errors in this; the agent should retry the write.
	ErrInvalidWrite = errors.New("the document was not saved; read it and write the HTML again")
	// ErrUseHTML is a non-HTML full replace on an existing Docs/Word path.
	ErrUseHTML = errors.New("write HTML, not plain text")
	// ErrEmptyReplace is HTML or blocks that decoded to no headings, paragraphs, lists, or tables.
	ErrEmptyReplace = errors.New("that HTML had no headings, paragraphs, lists, or tables; put the text in <p> or <h1> tags")
	// ErrTabIDRequired is a replace on a multi-tab Doc/Word file without tab_id.
	ErrTabIDRequired = errors.New("this document has more than one tab; pass tab_id for the tab you want to replace")
)

Sentinel errors for mount-table and path I/O outcomes. Prefer bare sentinels or a single plain "vfs: …" message — never wrap sentinels in sentinels.

Functions

func BlockReplaceSpan

func BlockReplaceSpan(b Block, includeHeading bool) (start, end int, err error)

BlockReplaceSpan returns half-open 1-based lines to replace for a block. For headings, includeHeading false skips the heading line (body only).

func CleanPath

func CleanPath(s string) (string, error)

CleanPath requires an absolute virtual path with no backslash or NUL. It returns path.Clean(s).

func ContentHash

func ContentHash(body string) string

ContentHash returns hex SHA-256 of body.

func ContentToken

func ContentToken(t Textual) string

ContentToken is the single rev helper. Used by ContentRev, lineWindowFromDoc, readStructured, loadMatching, and stage. IR uses the representation fingerprint so HTML reproject does not change the token.

func DetectMediaType

func DetectMediaType(virtualPath string, sample []byte) string

DetectMediaType is a helper for providers filling FileInfo.MediaType. OpenDocument does not call this — it trusts the provider.

Order:

  1. Well-known extension map (source code and text formats)
  2. If sample is non-empty: http.DetectContentType (+ UTF-8 text fallback)
  3. application/octet-stream

func EncodeDocument

func EncodeDocument(ctx context.Context, doc Document) ([]byte, error)

func EncodeHTMLBlocks

func EncodeHTMLBlocks(blocks []Block) string

EncodeHTMLBlocks writes pretty HTML: one heading, paragraph, list item, or table per line. Color style is emitted only when stored on the IR.

func EncodeTextual

func EncodeTextual(t Textual) ([]byte, error)

EncodeTextual returns UTF-8 bytes for a Textual document. Backend providers call this when their native form is a file or object. MountSession does not encode.

func ExcelARGB

func ExcelARGB(s string) string

ExcelARGB is the 8-digit AARRGGBB form used by Office XML.

func FormatA1

func FormatA1(row, col int) string

FormatA1 is the 1-based cell address (A1, B2, AA10).

func FormatInline

func FormatInline(runs []Run) string

FormatInline is the canonical agent spelling. Italic is always _text_.

func FormatRGB

func FormatRGB(r, g, b uint8) string

FormatRGB writes #rrggbb.

func FuseAvailable

func FuseAvailable() bool

FuseAvailable reports whether this process can mount a FUSE tree. Probes /dev/fuse and /dev/macfuse* only (not /dev/osxfuse*).

func HexColor

func HexColor(s string) string

HexColor normalizes a CSS/Office color to #rrggbb. Empty if not hex.

func IsProjected

func IsProjected(mediaType string) bool

IsProjected reports whether mediaType is a registered rich/grid codec. Projected bodies are not FUSE raw-byte writes; identity/text bodies are.

func IsTextLike

func IsTextLike(mediaType string) bool

IsTextLike reports whether mediaType is treated as text for IR/index routing.

func ParseA1

func ParseA1(s string) (r1, c1, r2, c2 int, err error)

ParseA1 parses A1 or A1:C3 (1-based inclusive).

func ParseRGB

func ParseRGB(s string) (r, g, b uint8, ok bool)

ParseRGB reads #rrggbb or #aarrggbb / rrggbb / aarrggbb.

func PlainInline

func PlainInline(s string) string

PlainInline is Block.Text with mark delimiters removed.

func Slugify

func Slugify(s string) string

Slugify lowers, keeps alnum, collapses other runs to '-', and trims dashes.

func SplitSheetAddr

func SplitSheetAddr(blockID string) (sheet, a1 string)

SplitSheetAddr splits block_id into sheet key and optional A1 (Sheet!B2).

func ValidMountPoint

func ValidMountPoint(point string) error

ValidMountPoint reports whether point is a single-segment virtual path (/workspace). FUSE and client binds require this shape.

func ValidateBinding

func ValidateBinding(b Binding) error

ValidateBinding checks provider, alias, and access token. Optional backend params (gdrive folderId, Graph site/drive) are applied when the factory opens; omitted gdrive folderId is My Drive. Point may be empty when params["name"] is set; leftover "/contracts" becomes alias contracts.

Types

type AWSS3

type AWSS3 struct {
	Client *s3.Client
}

AWSS3 implements S3API with the AWS SDK v2 client (MinIO, R2, and real S3).

func (AWSS3) Delete

func (a AWSS3) Delete(ctx context.Context, bucket, key string) error

Delete implements S3API.

func (AWSS3) Get

func (a AWSS3) Get(ctx context.Context, bucket, key string) (io.ReadCloser, int64, time.Time, error)

Get implements S3API.

func (AWSS3) Head

func (a AWSS3) Head(ctx context.Context, bucket, key string) (int64, time.Time, string, error)

Head implements S3API.

func (AWSS3) List

func (a AWSS3) List(ctx context.Context, bucket, prefix string) (keys []string, dirs []string, err error)

List implements S3API with delimiter "/" for virtual directories.

func (AWSS3) Put

func (a AWSS3) Put(ctx context.Context, bucket, key string, body io.Reader, size int64) error

Put implements S3API.

type AfterPersistFunc

type AfterPersistFunc func(ctx context.Context, virtualPath string) error

AfterPersistFunc is called after content is successfully written to a backend (WriteFile or WriteDocument). Used by optional bridges (e.g. vfsindex) without importing them. Errors from the hook are ignored so persist never rolls back.

type ApplyResult

type ApplyResult struct {
	Path         string
	Rev          string
	LineCount    int
	Replacements int
	Outline      []Block
}

ApplyResult is the post-write identity of the document.

func (ApplyResult) String

func (r ApplyResult) String() string

type AzureBlob

type AzureBlob struct {
	Client *azblob.Client
}

AzureBlob implements S3API with the Azure Blob SDK (Azurite and real Blob Storage).

func (AzureBlob) Delete

func (a AzureBlob) Delete(ctx context.Context, bucket, key string) error

Delete implements S3API.

func (AzureBlob) Get

func (a AzureBlob) Get(ctx context.Context, bucket, key string) (io.ReadCloser, int64, time.Time, error)

Get implements S3API.

func (AzureBlob) Head

func (a AzureBlob) Head(ctx context.Context, bucket, key string) (int64, time.Time, string, error)

Head implements S3API.

func (AzureBlob) List

func (a AzureBlob) List(ctx context.Context, bucket, prefix string) (keys []string, dirs []string, err error)

List implements S3API with delimiter "/" for virtual directories.

func (AzureBlob) Put

func (a AzureBlob) Put(ctx context.Context, bucket, key string, body io.Reader, _ int64) error

Put implements S3API. UploadStream reads body in blocks; size is unused.

type Binding

type Binding struct {
	Provider string            `json:"provider"`
	Point    string            `json:"point,omitempty"`
	Auth     Credential        `json:"auth,omitempty"`
	Params   map[string]string `json:"params,omitempty"`
	Writable bool              `json:"writable,omitempty"`
	// Live is the process token bag for this bind (not serialized). OpenVFS
	// copies it so 401 refresh shares the holder.
	Live *TokenHolder `json:"-"`
}

Binding is one user-owned cloud folder under /workspace/<alias>. Alias is params["name"] or a leftover single-segment Point (not /workspace). Provider is the bind kind (gdrive, msgraph). Writable is opt-in; the Go zero value stays read-only.

func BindingByName

func BindingByName(binds []Binding, name string) (Binding, bool)

BindingByName returns the bind whose alias or provider matches name.

type Block

type Block struct {
	ID    string
	Kind  string
	Text  string
	Runs  []Run
	Style StyleMeta
}

Block is a structural unit (heading region, paragraph, …). For Markdown, blocks are a projected view over the textual body (not a second body).

Text is what tools show the agent. On RichDocument, inline marks in Text are **bold**, _italic_ (also *italic* on input), ~~strike~~, and [label](url). kind/level carry structure — do not put # or - lists in Text. Runs is the decoded form; callers set Text and leave Runs empty.

func DecodeHTMLBlocks

func DecodeHTMLBlocks(data []byte) ([]Block, error)

DecodeHTMLBlocks maps pretty HTML to Block IR (headings, paragraphs, lists, tables, marks, existing images). It does not assign stable block IDs.

func FindBlock

func FindBlock(blocks []Block, idOrPath string) (Block, bool)

FindBlock looks up by ID or Style.Attributes["heading_path"] (exact).

func (Block) PlainText

func (b Block) PlainText() string

type BlockCodec

type BlockCodec struct {
	Types      []string
	Normalizer BlockNormalizer
}

BlockCodec adapts a BlockNormalizer to the VFS codec registry. Decode yields a RichDocument. Encode writes native bytes (DOCX, …). Not an IdentityCodec — FUSE is EROFS; persist via WriteDocument.

func (BlockCodec) Create

func (c BlockCodec) Create(path, mediaType string, mut Mutation) (Document, error)

Create lifts plaintext or blocks into a rich checkout.

func (BlockCodec) Decode

func (c BlockCodec) Decode(ctx context.Context, path, mediaType string, data []byte) (Document, error)

func (BlockCodec) Encode

func (c BlockCodec) Encode(ctx context.Context, doc Document) ([]byte, error)

func (BlockCodec) MediaTypes

func (c BlockCodec) MediaTypes() []string

type BlockNormalizer

type BlockNormalizer interface {
	DecodeBlocks(ctx context.Context, path, mediaType string, data []byte) ([]Block, error)
	EncodeBlocks(ctx context.Context, blocks []Block) ([]byte, error)
}

BlockNormalizer converts a source format to and from []Block.

type Cell

type Cell struct {
	Input  string
	Value  string
	Format CellFormat
}

Cell is one grid value. Input is what the agent writes ("Acme", "42", "=A1+1"). Value is the provider's formatted/computed text; empty when unknown. Zero Format means unspecified (do not send on write).

func (Cell) Display

func (c Cell) Display() string

Display is the agent-visible cell: formula if present, else formatted value.

type CellBorder

type CellBorder struct {
	Style string `json:"style,omitempty"`
	Color string `json:"color,omitempty"`
	Edges string `json:"edges,omitempty"`
}

CellBorder is one named-style bag. Empty Edges means all four sides.

type CellFormat

type CellFormat struct {
	Number    string      `json:"number,omitempty"`
	Bold      bool        `json:"bold,omitempty"`
	Italic    bool        `json:"italic,omitempty"`
	Strike    bool        `json:"strike,omitempty"`
	Underline bool        `json:"underline,omitempty"`
	Fill      string      `json:"fill,omitempty"`
	Color     string      `json:"color,omitempty"`
	Align     string      `json:"align,omitempty"`
	VAlign    string      `json:"valign,omitempty"`
	Wrap      string      `json:"wrap,omitempty"`
	Border    *CellBorder `json:"border,omitempty"`
	// contains filtered or unexported fields
}

CellFormat is the stored portable bag on a cell (absolute state). Mutation uses FormatPatch so agents can clear fields (bold=false).

func ParseCellFormat

func ParseCellFormat(s string) (CellFormat, error)

ParseCellFormat reads the String() bag (number=...,bold,bold=false,border=thin:bottom).

func (*CellFormat) ApplyPatch

func (f *CellFormat) ApplyPatch(p FormatPatch)

ApplyPatch writes each set field, including false and empty.

func (CellFormat) IsZero

func (f CellFormat) IsZero() bool

IsZero reports whether no format fields are set (do not send on write).

func (*CellFormat) Normalize

func (f *CellFormat) Normalize()

Normalize maps align, valign, wrap, and border style onto the portable bag.

func (*CellFormat) Overlay

func (f *CellFormat) Overlay(src CellFormat)

Overlay copies src fields that are known or non-zero onto f.

func (CellFormat) String

func (f CellFormat) String() string

String is the tool format bag: number=$#,##0.00,bold,border=thin:bottom

type Codec

type Codec interface {
	MediaTypes() []string
	Decode(ctx context.Context, path, mediaType string, data []byte) (Document, error)
}

Codec decodes raw bytes into a Document IR. mediaType is chosen by the caller (typically DetectMediaType); codecs must not re-sniff.

type ContentRegistry

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

ContentRegistry maps media type → Codec (process-scoped).

func DefaultContentRegistry

func DefaultContentRegistry() *ContentRegistry

DefaultContentRegistry returns the process-wide registry with TextCodec registered.

func NewContentRegistry

func NewContentRegistry() *ContentRegistry

NewContentRegistry returns an empty content registry.

func (*ContentRegistry) Decode

func (r *ContentRegistry) Decode(ctx context.Context, path, mediaType string, data []byte) (Document, error)

Decode looks up a codec for mediaType and decodes data.

func (*ContentRegistry) Lookup

func (r *ContentRegistry) Lookup(mediaType string) (Codec, bool)

Lookup returns the codec bound to mediaType, if any.

func (*ContentRegistry) Register

func (r *ContentRegistry) Register(c Codec) error

Register binds c for each of c.MediaTypes(). It does not replace an existing binding; first registration wins.

type ContentRev

type ContentRev struct {
	Path string
	Hash string
}

ContentRev identifies session-visible file content for optimistic concurrency. Hash is hex SHA-256 of the UTF-8 body (same policy as vfsindex content_hash). vfs does not enforce edits; harness tools compare expected Hash before write.

type Creator

type Creator interface {
	Create(path, mediaType string, mut Mutation) (Document, error)
}

Creator builds a new document from a create-mode Mutation. Codecs that own a representation (blocks, grid) implement this. MountSession looks up the codec by media type; it does not switch on vendors.

type Credential

type Credential struct {
	Token     string    `json:"token,omitempty"`
	ExpiresAt time.Time `json:"expiresAt,omitempty"`
}

Credential is a session-scoped access token. Never store this on MountSpec or in a checkpoint / SnapshotStore. Work-item payloads (Prompt/Resume) may carry it; backends must not persist it with recipes.

type DirEntry

type DirEntry struct {
	Name  string
	IsDir bool
	// Type is the file mode bits (same as fs.DirEntry.Type).
	Type fs.FileMode
}

DirEntry is a single directory entry.

type DirectProjection

type DirectProjection struct{}

DirectProjection attaches VFS in-process with no kernel mount.

func (DirectProjection) Attach

Attach is a no-op: the MountSession is already the agent-facing tree.

func (DirectProjection) Available

func (DirectProjection) Available() bool

Available is always true.

type DocTab

type DocTab struct {
	ID    string
	Title string
	Index int
}

DocTab is one document tab (Docs includeTabsContent).

type DocsAPI

type DocsAPI interface {
	Get(ctx context.Context, documentID string) (DocsSnapshot, error)
	BatchUpdate(ctx context.Context, documentID string, req DocsBatch) (DocsBatchResult, error)
}

DocsAPI is the Docs subset used by the provider. Tests inject a fake.

func NewGoogleDocs

func NewGoogleDocs(ctx context.Context, holder *TokenHolder) (DocsAPI, error)

NewGoogleDocs builds a DocsAPI from a user token holder.

type DocsBatch

type DocsBatch struct {
	RequiredRevisionID string
	TabID              string
	Requests           []DocsRequest
}

DocsBatch is one documents.batchUpdate call.

type DocsBatchResult

type DocsBatchResult struct {
	RevisionID string
}

DocsBatchResult is writeControl.requiredRevisionId after apply.

type DocsCell

type DocsCell struct {
	Row, Col             int
	StartIndex, EndIndex int
	Text                 string
}

DocsCell is one table cell's first paragraph.

type DocsCodec

type DocsCodec struct{}

DocsCodec decodes Google Docs HTML (unzipped export or canonical projection) into *RichDocument. It does not implement IdentityCodec.

func (DocsCodec) Create

func (DocsCodec) Create(path, mediaType string, mut Mutation) (Document, error)

Create lifts plaintext or blocks into a rich checkout.

func (DocsCodec) Decode

func (DocsCodec) Decode(ctx context.Context, virtualPath, mediaType string, data []byte) (Document, error)

Decode requires valid UTF-8 and rejects payloads larger than MaxReadFileBytes.

func (DocsCodec) MediaTypes

func (DocsCodec) MediaTypes() []string

MediaTypes implements Codec.

type DocsListProps

type DocsListProps struct {
	Ordered    bool
	GlyphTypes []string
}

DocsListProps is list metadata from documents.get.

type DocsRequest

type DocsRequest struct {
	DeleteContentRange     *docs.DeleteContentRangeRequest
	InsertText             *docs.InsertTextRequest
	UpdateParagraphStyle   *docs.UpdateParagraphStyleRequest
	CreateParagraphBullets *docs.CreateParagraphBulletsRequest
	InsertTable            *docs.InsertTableRequest
	UpdateTextStyle        *docs.UpdateTextStyleRequest
}

DocsRequest fields are the real batchUpdate request names.

type DocsSnapshot

type DocsSnapshot struct {
	DocumentID string
	RevisionID string
	Title      string
	Tabs       []DocTab
	Body       []DocsSpan
	Lists      map[string]DocsListProps
}

DocsSnapshot is the checkout used to build IR and persistHint.

type DocsSpan

type DocsSpan struct {
	TabID      string
	StartIndex int
	EndIndex   int
	Kind       string
	ObjectID   string
	Level      int
	NamedStyle string
	ListID     string
	Nesting    int
	Text       string
	Cells      []DocsCell
}

DocsSpan is one IR-mapped (or structural) span from a tab body.

type Document

type Document interface {
	Path() string
	MediaType() string
}

Document is the general content IR. Codecs produce Document values that are independent of storage backends (local, S3, Drive, …).

Path is always a virtual path — never a host filesystem path or bucket key.

type DriveAPI

type DriveAPI interface {
	GetMeta(ctx context.Context, fileID string) (DriveMeta, error)
	GetMedia(ctx context.Context, fileID string) (io.ReadCloser, int64, error)
	List(ctx context.Context, folderID string) ([]DriveMeta, error)
	Export(ctx context.Context, fileID, mimeType string) (io.ReadCloser, int64, error)
	PutMedia(ctx context.Context, fileID, mediaMIME string, r io.Reader, size int64) (DriveMeta, error)
	Create(ctx context.Context, parentID, name, metadataMIME, mediaMIME string, r io.Reader, size int64) (DriveMeta, error)
	Trash(ctx context.Context, fileID string) error
	Mkdir(ctx context.Context, parentID, name string) (DriveMeta, error)
}

DriveAPI is the Drive subset used by the provider. Tests inject a fake.

func NewGoogleDrive

func NewGoogleDrive(ctx context.Context, holder *TokenHolder) (DriveAPI, error)

NewGoogleDrive builds a DriveAPI from a user token holder. Call from OpenVFS when a drive bind arrives, then pass the result to Drive.

type DriveMeta

type DriveMeta struct {
	ID         string
	Name       string
	MimeType   string
	Size       int64
	ModTime    time.Time
	Version    string
	IsDir      bool
	TargetID   string
	TargetMime string
}

DriveMeta is one Drive file or folder (IDs stay inside the provider).

type Encoder

type Encoder interface {
	Encode(ctx context.Context, doc Document) ([]byte, error)
}

Encoder is the optional write side of a Codec. Rich document codecs use it to encode the edited canonical projection back to source bytes.

type File

type File interface {
	io.Closer
	Stat() (FileInfo, error)
}

File is an open handle. Close and Stat always work.

Extra capabilities are optional interfaces — comma-ok, not dummy methods:

r, ok := f.(io.Reader)   // sequential read
ra, ok := f.(io.ReaderAt) // offset read (FUSE)
w, ok := f.(io.Writer)    // sequential write

type FileInfo

type FileInfo struct {
	Name      string
	Size      int64
	Mode      fs.FileMode
	ModTime   time.Time
	IsDir     bool
	MediaType string
}

FileInfo describes a file or directory (agent-safe: no host paths).

MediaType is the provider's classification of a file (never a host path). Empty on directories. On files, providers must set it: a concrete type (text/markdown, image/png, …) or application/octet-stream when unknown. OpenDocument does not sniff; it only looks up a codec for this value.

type FormatPatch

type FormatPatch struct {
	Number    *string     `json:"number,omitempty"`
	Bold      *bool       `json:"bold,omitempty"`
	Italic    *bool       `json:"italic,omitempty"`
	Strike    *bool       `json:"strike,omitempty"`
	Underline *bool       `json:"underline,omitempty"`
	Fill      *string     `json:"fill,omitempty"`
	Color     *string     `json:"color,omitempty"`
	Align     *string     `json:"align,omitempty"`
	VAlign    *string     `json:"valign,omitempty"`
	Wrap      *string     `json:"wrap,omitempty"`
	Border    *CellBorder `json:"border,omitempty"`
}

FormatPatch is an explicit format write. Nil pointer = leave; set pointer = write (including false / empty). Zero Border clears the border.

type FuseProjection

type FuseProjection struct{}

FuseProjection mounts the session via MountSession.FuseMount.

func (FuseProjection) Attach

func (FuseProjection) Attach(ms *MountSession, sessionID string) error

Attach projects ms under /tmp/tacklr-fuse/<sessionID>.

func (FuseProjection) Available

func (FuseProjection) Available() bool

Available reports whether this process can mount a FUSE tree.

type GraphAPI

type GraphAPI interface {
	ResolveRoot(ctx context.Context, driveID, itemID, siteID, account string) (driveIDOut, itemIDOut string, err error)
	GetItem(ctx context.Context, driveID, itemID string) (graphItem, error)
	GetByPath(ctx context.Context, driveID, itemID, rel string) (graphItem, error)
	ListChildren(ctx context.Context, driveID, itemID string) ([]graphItem, error)
	GetContent(ctx context.Context, driveID, itemID string) (io.ReadCloser, int64, error)
	PutContent(ctx context.Context, driveID, itemID, name, parentID string, r io.Reader, size int64) (graphItem, error)
	CreateFolder(ctx context.Context, driveID, parentID, name string) (graphItem, error)
	Delete(ctx context.Context, driveID, itemID string) error
}

GraphAPI is the OneDrive/SharePoint subset. Tests inject a fake; hosts call NewGraph (no Microsoft SDK import).

func NewGraph

func NewGraph(holder *TokenHolder, base string, httpClient *http.Client) (GraphAPI, error)

NewGraph builds a GraphAPI from a user token holder. Hosts pass the result to Graph. base and httpClient are for tests; production: NewGraph(holder, "", nil).

type Grid

type Grid interface {
	Sheets() []Sheet
	NamedRanges() []NamedRange
	Cell(key, a1 string) (Cell, error)
	ReadRows(key string, start, end int) (Sheet, []string, error)
	ReadCell(key, a1 string) (string, error)
	ReadRangeTSV(key, a1 string) (string, error)
}

Grid is the spreadsheet representation of a Document (Sheets / Excel).

func AsGrid

func AsGrid(doc Document) (Grid, bool)

AsGrid reports whether doc is represented as a spreadsheet grid.

type IR

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

ir is the one document checkout. Codecs pick a body (text, blocks, or grid). MountSession and tools see Path, MediaType, Textual, Structured, and optional AsGrid / AsRich — not backends or concrete file types.

func NewRichDocument

func NewRichDocument(path, mediaType string, blocks []Block) *IR

func NewTabularDocument

func NewTabularDocument(path, mediaType string, sheets []Sheet, named []NamedRange) (*IR, error)

NewTabularDocument builds a grid checkout, trims trailing empty rows/cols, and rejects grids larger than MaxSheetCells.

func NewTextDocument

func NewTextDocument(path, mediaType, encoding, text string) *IR

NewTextDocument builds a plaintext checkout (identity body).

func (*IR) Blocks

func (d *IR) Blocks() []Block

func (*IR) ContentFingerprint

func (d *IR) ContentFingerprint() string

func (*IR) Encoding

func (d *IR) Encoding() string

func (*IR) Line

func (d *IR) Line(n int) (string, error)

func (*IR) LineCount

func (d *IR) LineCount() int

func (*IR) Lines

func (d *IR) Lines(start, end int) ([]string, error)

func (*IR) MediaType

func (d *IR) MediaType() string

func (*IR) Path

func (d *IR) Path() string

func (*IR) ReplaceLines

func (d *IR) ReplaceLines(start, end int, replacement []string) error

func (*IR) SetLine

func (d *IR) SetLine(n int, line string) error

func (*IR) SetText

func (d *IR) SetText(text string) error

func (*IR) Text

func (d *IR) Text() string

type IdentityCodec

type IdentityCodec interface {
	Codec
	Identity()
}

IdentityCodec is a Codec whose persist form is the UTF-8 payload itself (no container). TextCodec implements it. Office/cloud codecs (Word, Notion, Google Docs) must not — FUSE then returns EROFS and the write tool uses WriteDocument. Register those codecs under their native media types; do not steal text/markdown.

type LineWindow

type LineWindow struct {
	Path      string
	Start     int
	End       int
	Lines     []string
	Returned  int
	EOF       bool
	NextStart int
	Rev       ContentRev
}

LineWindow is one progressive page of lines from a virtual path.

Start/End are the half-open 1-based range requested (End may be clamped by MaxLinesPerWindow). EOF is true when the file ended at or before the last returned line. NextStart is Start+Returned (useful when !EOF for paging).

Rev is set when the window is served from a full textual body (cheap hash). Stream reads leave Rev empty; callers use ContentRev when needed.

type Member

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

Member is one /workspace/<name> backend.

func At

func At(name string, open Open) Member

At names a backend under /workspace. name is the first path segment (/workspace/scratch/…).

func (Member) Indexed

func (m Member) Indexed(policy string) Member

Indexed sets MountSpec.IndexPolicy on this member (none|selective|prefix|watch).

func (Member) Profile

func (m Member) Profile(profile string) Member

Profile sets MountSpec.Profile. Empty keeps the At name. Tree still sets Profile "brain" when name is "engram".

func (Member) ReadOnly

func (m Member) ReadOnly() Member

ReadOnly marks a host-owned member read-only. User-owned members use Binding.Writable instead.

type MemorySheets

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

MemorySheets is an in-memory SheetsAPI. Tests and local harnesses use it instead of the Google service.

func NewMemorySheets

func NewMemorySheets() *MemorySheets

NewMemorySheets returns an empty in-memory workbook store.

func (*MemorySheets) BatchUpdate

func (m *MemorySheets) BatchUpdate(ctx context.Context, spreadsheetID string, req SheetsBatch) error

func (*MemorySheets) BatchUpdateValues

func (m *MemorySheets) BatchUpdateValues(ctx context.Context, spreadsheetID string, req SheetsValuesBatch) error

func (*MemorySheets) Get

func (m *MemorySheets) Get(ctx context.Context, spreadsheetID string) (SheetsSnapshot, error)

func (*MemorySheets) Seed

func (m *MemorySheets) Seed(id string, snap SheetsSnapshot)

Seed replaces the snapshot for id (deep-copied).

type MountSession

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

MountSession is one isolated virtual filesystem: mount table + path I/O. It routes document I/O to the provider; it does not encode IR or cache dirty documents. Tree (or an embedder) creates it, Attachs /workspace, optionally FuseMounts, and Closes it. The agent harness only borrows the pointer.

func NewMountSession

func NewMountSession(sessionID string) (*MountSession, error)

NewMountSession binds a session id. Hosts use Tree; FuseMount is optional.

func (*MountSession) Apply

func (ms *MountSession) Apply(ctx context.Context, virtualPath string, mut Mutation) (ApplyResult, error)

Apply persists one mutation. Empty Rev uses the harness lastRev or a live read.

func (*MountSession) Attach

func (m *MountSession) Attach(ctx context.Context, spec MountSpec, p Provider) error

Attach puts an already-opened Provider at spec.Point. Tree uses this.

func (*MountSession) Classify

func (m *MountSession) Classify(ctx context.Context, virtualPath string, sample []byte) (string, error)

Classify returns the media type for virtualPath. Existing files use Stat.MediaType. New names use DetectMediaType.

func (*MountSession) Close

func (m *MountSession) Close() error

Close unmounts the host FUSE tree.

func (*MountSession) ContentRev

func (m *MountSession) ContentRev(ctx context.Context, virtualPath string) (ContentRev, error)

ContentRev hashes the session-visible body: ReadText when textual (same bytes FUSE and the read tool show), otherwise ReadFile.

func (*MountSession) FuseMount

func (m *MountSession) FuseMount(dir string) error

FuseMount projects the session as a host tree at dir. If ReadText succeeds (Textual), the kernel sees that plaintext: size and Read use the projection. Kernel writes stay EROFS unless kernelWritable (IdentityCodec). Otherwise Open uses Stat + ReaderAt (binaries). session.Mount attaches a provider; FuseMount is the host kernel mount. Every live Specs() point must be a single path segment (/work, /engram).

func (*MountSession) GetAfterPersist

func (m *MountSession) GetAfterPersist() AfterPersistFunc

GetAfterPersist returns the current AfterPersist hook, or nil.

func (*MountSession) HostDir

func (m *MountSession) HostDir() string

HostDir is the directory last passed to FuseMount, or "". Hosts and run_command use this as cwd. Harness tool results, errors, Specs, and checkpoints must never print it. The child process can still observe it via pwd until a later jail.

func (*MountSession) MkdirAll

func (m *MountSession) MkdirAll(ctx context.Context, virtualPath string) error

MkdirAll creates a directory and parents.

func (*MountSession) Open

func (m *MountSession) Open(ctx context.Context, virtualPath string) (File, error)

Open opens a virtual path for reading.

func (*MountSession) OpenDocument

func (m *MountSession) OpenDocument(ctx context.Context, virtualPath string, reg *ContentRegistry) (Document, error)

OpenDocument loads a virtual path into a Document IR via the mount's provider. The returned Textual is a fresh decode (safe to edit). reg nil uses DefaultContentRegistry().

func (*MountSession) ReadDir

func (m *MountSession) ReadDir(ctx context.Context, virtualPath string) ([]DirEntry, error)

ReadDir lists a directory.

func (*MountSession) ReadFile

func (m *MountSession) ReadFile(ctx context.Context, virtualPath string) ([]byte, error)

ReadFile reads an entire file (capped at MaxReadFileBytes).

When File.Stat reports a size, the buffer is allocated once and oversize files are rejected without reading the body. Unknown sizes fall back to a limited streaming read.

func (*MountSession) ReadLines

func (m *MountSession) ReadLines(ctx context.Context, virtualPath string, start, end int) (LineWindow, error)

ReadLines streams virtualPath and returns a line window for the half-open 1-based range [start, end).

Large files are allowed: unlike ReadFile/ReadText there is no full-object size reject. Only MaxLineScanBytes (bytes read this call), MaxLineBytes (per line), and MaxLinesPerWindow apply.

If the file ends before end, the available lines are returned with EOF=true (not ErrLineOutOfRange). ErrLineOutOfRange only when start is past EOF.

func (*MountSession) ReadText

func (m *MountSession) ReadText(ctx context.Context, virtualPath string) (Textual, error)

ReadText opens a virtual path as Textual IR (clone; safe to edit).

func (*MountSession) Remove

func (m *MountSession) Remove(ctx context.Context, virtualPath string) error

Remove removes a file or empty directory.

func (*MountSession) SetAfterPersist

func (m *MountSession) SetAfterPersist(fn AfterPersistFunc)

SetAfterPersist registers a hook after successful backend writes. Pass nil to clear. Safe to call at any time; concurrent with I/O. Compose with GetAfterPersist when layering (e.g. host hook + vfsindex).

func (*MountSession) SpecAt

func (m *MountSession) SpecAt(virtualPath string) (MountSpec, error)

SpecAt returns the durable MountSpec for the mount that owns virtualPath (longest matching point). Under /workspace, the alias member spec is returned so IndexPolicy is per backend. Clone is safe to retain; no secrets.

func (*MountSession) Specs

func (m *MountSession) Specs() []MountSpec

Specs returns the durable mount table (checkpoint-safe; no host paths or secrets).

func (*MountSession) Stat

func (m *MountSession) Stat(ctx context.Context, virtualPath string) (FileInfo, error)

Stat returns info for a virtual path.

func (*MountSession) Unmount

func (m *MountSession) Unmount(point string) error

Unmount detaches the mount at point.

func (*MountSession) WriteDocument

func (m *MountSession) WriteDocument(ctx context.Context, doc Document) error

WriteDocument asks the mount's provider to translate IR and persist now.

func (*MountSession) WriteFile

func (m *MountSession) WriteFile(ctx context.Context, virtualPath string, data []byte) error

WriteFile creates or truncates a file (fails on read-only mounts). Write-through to the backend.

type MountSpec

type MountSpec struct {
	Point    string            `json:"point"`
	Profile  string            `json:"profile"`
	ReadOnly bool              `json:"readOnly,omitempty"`
	Params   map[string]string `json:"params,omitempty"`
	// IndexPolicy controls when the optional vfsindex pipeline runs for paths
	// under this mount: none | selective | prefix | watch. Empty means selective
	// when the harness bridge is enabled. vfs stores the string only; interpretation
	// lives in vfsindex/harness.
	IndexPolicy string `json:"indexPolicy,omitempty"`
	// Members are /workspace aliases (params["name"]). The only top-level Point
	// is /workspace. Duplicate aliases → ErrAmbiguous.
	Members []MountSpec `json:"members,omitempty"`
}

MountSpec is the durable, secret-free description of a mount. Safe to JSON into session checkpoints. Never store credentials here.

type Mutation

type Mutation struct {
	Rev            string
	Content        *string
	Old            *string
	New            *string
	ReplaceAll     bool
	Start, End     *int
	Lines          []string
	Body           *string
	BlockID        string
	IncludeHeading bool
	Blocks         []Block
	TabID          string
	MediaType      string
	Format         *FormatPatch
}

Mutation is one write against a virtual path. Addresses are replace-whole (Content) or replace-span (line Start/End, or BlockID including Sheet!A1). Old/New finds a span; Blocks is create/replace of structured IR on Apply.

type NamedRange

type NamedRange struct {
	Name, SheetID, A1 string
}

NamedRange is a workbook named range.

type Open

type Open func(ctx context.Context, sessionID string, b Binding) (Provider, error)

Open opens a Provider. Close over clients in the function. Binding carries this turn's user token and params (folderId, subpath, …). A nil Provider and nil error means skip (no token for a user-scoped backend).

func Blob

func Blob(client S3API, defaultContainer string) Open

Blob opens Azure Blob providers that share one S3API client (HTTP pool). The object model matches S3: a container is the bucket, blob names are keys, and delimiter "/" listing gives virtual directories.

func Drive

func Drive(api DriveAPI) Open

Drive opens a Google Drive folder. api is required (host-built SDK or a test fake). folderId and writable come from this turn's Binding.

func DriveWith

func DriveWith(api DriveAPI, docs DocsAPI, sheets SheetsAPI) Open

DriveWith is Drive plus Docs/Sheets clients for native Google files.

func Graph

func Graph(api GraphAPI, holder *TokenHolder, account string) Open

Graph opens OneDrive / SharePoint. api is a NewGraph result or a test fake.

func Local

func Local(base string) Open

Local opens providers under a fixed jail. Params: "subpath" (optional), "session_scoped=true" (optional). The jail stays in the closure; providers never expose host roots.

func Memory

func Memory() Open

Memory is an ephemeral, session-scoped backend. Hosts At("memory", Memory()); WriteFile stores bytes under /workspace/memory. It is not a durable store.

func S3

func S3(client S3API, defaultBucket string) Open

S3 opens providers that share one S3API client (HTTP pool). defaultBucket is used when the spec omits params["bucket"].

func Union

func Union(opens ...Open) Open

Union merges backends into one read-only Open. Skill packs use AgentSpec.OpenSkills: Tree(At("skills", Union(...))).

type OpenVFS

type OpenVFS func(ctx context.Context, sessionID string, req Request) (*MountSession, error)

OpenVFS builds a turn-scoped MountSession. Nil OpenVFS means no VFS.

func Tree

func Tree(members ...Member) OpenVFS

Tree mounts every member under /workspace — the only top-level mount. Hosts omit user-cloud members they did not construct from this turn's bind.

type Projection

type Projection interface {
	Available() bool
	Attach(ms *MountSession, sessionID string) error
}

Projection publishes a MountSession to the host.

Production uses FuseProjection (kernel tree). Tests use DirectProjection (in-process only; no /dev/fuse). If Available is false, Runtime does not inject a MountSession and VFS tools are not added.

type Provider

type Provider interface {
	Validate(ctx context.Context) error

	Stat(ctx context.Context, name string) (FileInfo, error)
	OpenFile(ctx context.Context, name string, flag int, perm fs.FileMode) (File, error)
	ReadDir(ctx context.Context, name string) ([]DirEntry, error)
	Remove(ctx context.Context, name string) error
	MkdirAll(ctx context.Context, name string, perm fs.FileMode) error
}

Provider is a backend attached at a virtual mount point.

One interface covers mount validation and path I/O relative to the provider root. Paths use slash-separated relative names ("" = root). Backends that do not support I/O yet return ErrNotSupported from I/O methods.

Treat provider values as immutable after a successful FS.Mount.

func NewLocalProvider

func NewLocalProvider(dir string) (Provider, error)

NewLocalProvider returns a Provider rooted at a canonical absolute directory.

type Request

type Request struct {
	Bindings []Binding
}

Request is this turn's user-owned bind list (tokens + params). Host-owned At members ignore it. User-owned backends (Drive, Graph) match Binding params["name"] to the At name.

type Rich

type Rich interface {
	Tabs() []DocTab
	Blocks() []Block
	ReplaceBlock(id, text string, includeHeading bool) error
	SetBlocks(blocks []Block)
}

Rich is the block-tree representation of a Document (Docs / Word).

func AsRich

func AsRich(doc Document) (Rich, bool)

AsRich reports whether doc is represented as a block tree (Docs / Word).

type Run

type Run struct {
	Text  string
	Marks map[string]string
}

Run is one contiguous marked slice of a block. Marks keys are MarkBold, MarkItalic, MarkStrike, MarkHref. Agents never send Runs; they write markdown in Block.Text (**bold**, _italic_, ~~strike~~, [label](url)).

func ParseInline

func ParseInline(s string) []Run

ParseInline turns the agent markdown subset into runs.

type S3API

type S3API interface {
	// Head returns size, mtime, and optional Content-Type (empty if unknown).
	Head(ctx context.Context, bucket, key string) (size int64, mod time.Time, contentType string, err error)
	Get(ctx context.Context, bucket, key string) (body io.ReadCloser, size int64, mod time.Time, err error)
	Put(ctx context.Context, bucket, key string, body io.Reader, size int64) error
	Delete(ctx context.Context, bucket, key string) error
	// List returns object keys and "directory" prefixes under prefix (delimiter "/").
	// prefix should end with "/" when listing a directory, or be the full key prefix.
	List(ctx context.Context, bucket, prefix string) (keys []string, dirs []string, err error)
}

S3API is the subset of an S3-compatible API used by the S3 provider. Hosts typically pass *s3.Client via AWSS3 (or any adapter).

type SessionAuth

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

SessionAuth is the in-memory store of user-owned backend credentials. Tokens live on TokenHolder only; Binding.Auth is not the live copy.

func NewSessionAuth

func NewSessionAuth() *SessionAuth

NewSessionAuth returns an empty store.

func (*SessionAuth) Bind

func (s *SessionAuth) Bind(sessionID string, b Binding) error

Bind records a folder mount and its access token. Cloud binds attach under /workspace/<alias>. A second bind to the same alias replaces it. A new token for the same provider updates the shared holder.

func (*SessionAuth) Bindings

func (s *SessionAuth) Bindings(sessionID string) []Binding

Bindings returns a copy of the session bindings (no tokens).

func (*SessionAuth) Clear

func (s *SessionAuth) Clear(sessionID string)

Clear drops every binding and token for the session.

func (*SessionAuth) Credential

func (s *SessionAuth) Credential(sessionID, provider string) (Credential, bool)

Credential returns the current credential for provider, or false.

func (*SessionAuth) HasBindings

func (s *SessionAuth) HasBindings(sessionID string) bool

HasBindings reports whether the session has at least one user-owned binding.

func (*SessionAuth) Holder

func (s *SessionAuth) Holder(sessionID, provider string) *TokenHolder

Holder returns the shared token holder, or nil.

func (*SessionAuth) Refresh

func (s *SessionAuth) Refresh(sessionID, provider string, c Credential) error

Refresh replaces the access token for provider on the session.

func (*SessionAuth) Unbind

func (s *SessionAuth) Unbind(sessionID, point string) error

Unbind removes the binding for alias. point may be leftover "/contracts" or the alias itself. The provider token is dropped when no binding remains for that provider. Unbind("/workspace") is invalid — pass the alias.

func (*SessionAuth) UnbindProvider

func (s *SessionAuth) UnbindProvider(sessionID, provider string) error

UnbindProvider removes every binding for provider on the session.

type Sheet

type Sheet struct {
	ID    string
	Title string
	Index int
	Rows  int
	Cols  int
	Cells [][]Cell
	// contains filtered or unexported fields
}

Sheet is one used rectangle. Cells[r][c] is 0-based; agent rows/cols are 1-based.

func WithMerge

func WithMerge(sh Sheet, startRow, startCol, endRow, endCol int) Sheet

WithMerge records a 0-based half-open merge rectangle from a provider checkout.

type SheetNormalizer

type SheetNormalizer interface {
	DecodeSheets(ctx context.Context, path, mediaType string, data []byte) ([]Sheet, []NamedRange, error)
	EncodeSheets(ctx context.Context, sheets []Sheet, named []NamedRange) ([]byte, error)
}

SheetNormalizer converts a workbook format to and from []Sheet.

type SheetsAPI

type SheetsAPI interface {
	Get(ctx context.Context, spreadsheetID string) (SheetsSnapshot, error)
	BatchUpdateValues(ctx context.Context, spreadsheetID string, req SheetsValuesBatch) error
	BatchUpdate(ctx context.Context, spreadsheetID string, req SheetsBatch) error
}

SheetsAPI is the Sheets subset used by the provider. MemorySheets is the in-memory implementation; GoogleSheets talks to the service.

func NewGoogleSheets

func NewGoogleSheets(ctx context.Context, holder *TokenHolder) (SheetsAPI, error)

NewGoogleSheets builds a SheetsAPI from a user token holder.

type SheetsBatch

type SheetsBatch struct {
	Requests []SheetsRepeatCell
}

SheetsBatch is one spreadsheets.batchUpdate (repeatCell userEnteredFormat).

type SheetsCodec

type SheetsCodec struct{}

SheetsCodec is the default-registry codec for Google Sheets HTML export.

func (SheetsCodec) Create

func (SheetsCodec) Create(path, mediaType string, mut Mutation) (Document, error)

func (SheetsCodec) Decode

func (SheetsCodec) Decode(ctx context.Context, virtualPath, mediaType string, data []byte) (Document, error)

func (SheetsCodec) MediaTypes

func (SheetsCodec) MediaTypes() []string

type SheetsHTML

type SheetsHTML struct{}

SheetsHTML decodes Google Sheets HTML ZIP export (Drive RO).

func (SheetsHTML) DecodeSheets

func (SheetsHTML) DecodeSheets(_ context.Context, _, _ string, data []byte) ([]Sheet, []NamedRange, error)

func (SheetsHTML) EncodeSheets

func (SheetsHTML) EncodeSheets(context.Context, []Sheet, []NamedRange) ([]byte, error)

type SheetsRepeatCell

type SheetsRepeatCell struct {
	SheetID            int64
	StartRow, StartCol int // 0-based inclusive
	EndRow, EndCol     int // 0-based exclusive
	Format             CellFormat
}

SheetsRepeatCell is one repeatCell of a format bag.

type SheetsSnapshot

type SheetsSnapshot struct {
	SpreadsheetID string
	RevisionID    string
	Sheets        []Sheet
	Named         []NamedRange
}

SheetsSnapshot is the checkout used to build TabularDocument.

type SheetsValueRange

type SheetsValueRange struct {
	Range  string
	Values [][]string
}

SheetsValueRange is one A1 range of string cells (USER_ENTERED).

type SheetsValuesBatch

type SheetsValuesBatch struct {
	Data []SheetsValueRange
}

SheetsValuesBatch is one spreadsheets.values.batchUpdate call.

type Span

type Span struct {
	StartLine int
	EndLine   int
}

Span is a line-based content address (1-based half-open).

type Structured

type Structured interface {
	Document
	Blocks() []Block
}

Structured is optional for documents with a block tree (Markdown headings, Word, Google Docs, …). Callers use Blocks(); empty means no structure.

type StyleMeta

type StyleMeta struct {
	Kind       string
	Level      int
	Span       Span
	Attributes map[string]string
}

StyleMeta is optional presentation/structure for rich documents.

type TabularCodec

type TabularCodec struct {
	Types      []string
	Normalizer SheetNormalizer
}

TabularCodec adapts a SheetNormalizer to the VFS codec registry. Decode yields a grid checkout. Encode writes native bytes (xlsx, …).

func (TabularCodec) Create

func (c TabularCodec) Create(virtualPath, mediaType string, mut Mutation) (Document, error)

func (TabularCodec) Decode

func (c TabularCodec) Decode(ctx context.Context, virtualPath, mediaType string, data []byte) (Document, error)

func (TabularCodec) Encode

func (c TabularCodec) Encode(ctx context.Context, doc Document) ([]byte, error)

func (TabularCodec) MediaTypes

func (c TabularCodec) MediaTypes() []string

type TextCodec

type TextCodec struct{}

TextCodec decodes UTF-8 text and text-like media types into *TextDocument. Identity: persist form is the UTF-8 payload (no container).

func (TextCodec) Decode

func (TextCodec) Decode(ctx context.Context, path, mediaType string, data []byte) (Document, error)

Decode builds a TextDocument from data. mediaType is the caller's detection result.

data is taken over as the document body (no extra content copy). Callers must not mutate data after Decode returns.

func (TextCodec) Identity

func (TextCodec) Identity()

Identity marks TextCodec as an IdentityCodec. FUSE may accept kernel writes.

func (TextCodec) MediaTypes

func (TextCodec) MediaTypes() []string

MediaTypes is the set of extension-map types this codec claims at registration.

type Textual

type Textual interface {
	Document
	Encoding() string
	Text() string
	LineCount() int
	Line(n int) (string, error)
	Lines(start, end int) ([]string, error)
	SetText(text string) error
	SetLine(n int, line string) error
	ReplaceLines(start, end int, replacement []string) error
}

Textual is document content that has a plaintext form (source, Markdown, Engrams, later Word/Docs/PDF extracts). Images and other binaries do not implement it — callers use a comma-ok assert.

Text() is that plaintext (FUSE / encode). Line numbers are 1-based. Lines(start, end) is half-open [start, end). SetText / SetLine / ReplaceLines mutate this value; persist with WriteDocument. SetText on Docs/Word applies HTML then SetBlocks; spreadsheets return ErrProjected.

type TokenHolder

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

TokenHolder is the live access token for one (session, provider). All folder mounts for that pair share the same holder. Refresh updates every mount.

func NewTokenHolder

func NewTokenHolder(c Credential) *TokenHolder

NewTokenHolder returns a holder with the initial credential.

func (*TokenHolder) Current

func (h *TokenHolder) Current() Credential

Current returns a copy of the credential. Token is present; callers must not log it.

func (*TokenHolder) EnsureValid

func (h *TokenHolder) EnsureValid(ctx context.Context) error

EnsureValid proactively refreshes a token that is expired or near expiry. A zero ExpiresAt selects reactive refresh after a provider 401.

func (*TokenHolder) RefreshIfCurrent

func (h *TokenHolder) RefreshIfCurrent(ctx context.Context, staleToken string) error

RefreshIfCurrent refreshes only when staleToken is still installed. Parallel callers that observed the same rejected token wait for one shared refresh.

func (*TokenHolder) RefreshOnce

func (h *TokenHolder) RefreshOnce(ctx context.Context) error

RefreshOnce calls the refresh func once and stores the new token. Returns ErrAuthExpired when no refresh func is set or the client fails.

func (*TokenHolder) Set

func (h *TokenHolder) Set(c Credential)

Set replaces the current credential.

func (*TokenHolder) SetRefresh

func (h *TokenHolder) SetRefresh(fn TokenRefreshFunc)

SetRefresh installs the optional client token callback used after a 401.

func (*TokenHolder) Token

func (h *TokenHolder) Token() (*oauth2.Token, error)

Token implements oauth2.TokenSource. Expiry is left zero so the SDK always sends the current holder token; 401 handling lives in the Drive adapter.

type TokenRefreshFunc

type TokenRefreshFunc func(ctx context.Context) (Credential, error)

TokenRefreshFunc fetches a new access token (IdP or host callback).

Directories

Path Synopsis
Package adapters contains source-format codecs for rich text documents.
Package adapters contains source-format codecs for rich text documents.
Package testhttp hosts an httptest server for official SDK adapters.
Package testhttp hosts an httptest server for official SDK adapters.

Jump to

Keyboard shortcuts

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