adapterkit

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Apr 30, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package adapterkit holds the helpers shared by every brainjar Platform adapter: marker constants, brainjar brand strings, atomic file / JSON I/O, hook-entry identity, and the managed-section merge algorithm. Adapters stay small and schema-local — everything here is orthogonal to any specific agent runtime.

Index

Constants

View Source
const (
	// MarkerBegin and MarkerEnd delimit brainjar's managed section
	// inside text-based target files (CLAUDE.md, AGENTS.md, a Cursor
	// rules file, etc.). HTML comments render invisibly in every
	// markdown viewer, are copy-paste safe, and greppable.
	MarkerBegin = "<!-- brainjar:begin -->"
	MarkerEnd   = "<!-- brainjar:end -->"

	// HookCommand is the command string every adapter installs as
	// its hook. Stored unqualified so the user's PATH resolves it —
	// switching between brew / go install / manual drops doesn't
	// require re-running hooks install.
	HookCommand = "brainjar sync"

	// MCPCommand is the binary path registered as the MCP server.
	MCPCommand = "brainjar"

	// MCPServerName is the key brainjar occupies in every adapter's
	// server map (JSON `mcpServers.brainjar` or TOML
	// `[mcp_servers.brainjar]`).
	MCPServerName = "brainjar"
)

Variables

This section is empty.

Functions

func ArgsEqual

func ArgsEqual(a, b []string) bool

ArgsEqual reports whether two string slices hold identical elements in the same order. Used by MCPStatus implementations to detect drift between a stored entry and a fresh build.

func BrainjarMCPArgs

func BrainjarMCPArgs(home string) []string

BrainjarMCPArgs returns the args slice to register alongside MCPCommand. An empty home yields just ["mcp"]; a non-empty home is baked in as a leading --home flag so the spawned brainjar targets the workspace the user installed against.

func BrainjarMCPEntry

func BrainjarMCPEntry(home string) map[string]any

BrainjarMCPEntry builds the {command, args} object every JSON-driven adapter writes under mcpServers.brainjar. Args are returned as []any so a round-trip through encoding/json compares equal to a fresh build (the unmarshaled shape is always []any). Adapters that need extra fields (e.g. Codex's enabled) can mutate the returned map.

func CopyMap

func CopyMap(m map[string]any) map[string]any

CopyMap returns a shallow clone of m. Used by adapters when they need to compare a proposed entry against an existing one without mutating either.

func EnsureMap

func EnsureMap(parent map[string]any, key string) map[string]any

EnsureMap returns parent[key] as a map, creating and inserting a fresh empty map if the key is absent or holds a non-map value. Callers receive a stable reference safe to mutate in place.

func IsBrainjarHookEntry

func IsBrainjarHookEntry(entry map[string]any) bool

IsBrainjarHookEntry reports whether a hook entry's command belongs to brainjar. Identity is exact match on HookCommand, or HookCommand followed by a space (future flags). The trailing-space requirement prevents a user wrapper named "brainjar sync-audit" from being silently claimed and removed on uninstall.

func MergeManagedSection

func MergeManagedSection(existing, prompt, kind string) (string, error)

MergeManagedSection returns the file contents that should be written, given the existing file and the prompt destined for brainjar's managed section. Returns existing unchanged when the managed section already matches — callers short-circuit the write for idempotency.

Errors on an unpaired or reversed marker — silently reconstructing the section risks eating user content between a stray marker and the end of the file.

The `kind` argument names the target file in error messages so the hint points at the right path (e.g. "CLAUDE.md", "AGENTS.md").

func PickFileMode

func PickFileMode(path string) os.FileMode

PickFileMode returns the permissions to stamp on a fresh write. Existing files keep their mode (rename with an already-existing target replaces inode, so the temp file's mode becomes the new file mode — we preserve by reading the target's mode first). For fresh creation, files under the user's home default to 0o600 (may hold credentials in sibling keys — e.g. ~/.claude.json holds oauth tokens), everything else defaults to 0o644 so committable project files stay readable by collaborators.

func ReadFileIfExists

func ReadFileIfExists(path string) (string, error)

ReadFileIfExists returns file contents as a string, or the empty string when the file is absent. Any other stat/read error is returned unchanged so callers can wrap it with path context.

func ReadJSONFile

func ReadJSONFile(path string) (map[string]any, error)

ReadJSONFile decodes a JSON file into a map[string]any. A missing file is not an error — an empty map is returned, since adapters universally treat "file absent" as "no settings."

func ReadStringSlice

func ReadStringSlice(v any) []string

ReadStringSlice coerces a JSON/TOML-decoded args value into []string. []any (from JSON / JSON-in-TOML) is the common case; []string (from in-memory builds) is accepted too so symmetric equality checks work regardless of which side the caller is on. Non-string elements are stringified best-effort.

func WriteFileAtomic

func WriteFileAtomic(path string, payload []byte, mode os.FileMode) error

WriteFileAtomic writes payload to path via a PID-suffixed sibling temp file then os.Rename. The PID suffix keeps two concurrent brainjar processes from colliding on the same tmp path; rename is atomic on POSIX so a crash mid-write can never leave path truncated.

func WriteJSONFile

func WriteJSONFile(path string, settings map[string]any) error

WriteJSONFile marshals settings with a stable 2-space indent and writes atomically via WriteFileAtomic.

Types

This section is empty.

Jump to

Keyboard shortcuts

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