Documentation
¶
Overview ¶
internal/adapter/engine.go
Index ¶
- func Detect(a Adapter) bool
- func EstimateTokens(s string) int
- func ExpandHome(path string) (string, error)
- func ExportFileAndClip(a Adapter, fullCtx string, opts Options) error
- func ExportToClipboard(content, instructions string, dryRun bool) error
- func HookConfigInstalled(settingsPath, key, command string) (bool, error)
- func ReadMCPConfig(settingsPath, key string) (map[string]interface{}, error)
- func RemoveHookConfig(settingsPath, key, command string, dryRun bool) error
- func RemoveSkillFile(basePath, skillID string, dryRun bool) error
- func ReplaceFile(filePath, preamble, content string, dryRun bool) error
- func ReplaceSection(filePath, section, content string, dryRun bool) error
- func SkillFileInstalled(basePath, skillID string) bool
- func WriteHookConfig(settingsPath, key, command string, dryRun bool) error
- func WriteMCPConfig(settingsPath, key string, server content.MCPServer, dryRun bool) error
- func WriteSkillFile(basePath, skillID, content string, dryRun bool) error
- type Adapter
- type DetectRule
- type Engine
- type HookConfig
- type MCPConfig
- type Options
- type RunResult
- type SectionInfo
- type SkillConfig
- type StatusRow
- type Target
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Detect ¶
Detect returns true if the adapter is present on this machine. It iterates the adapter's Detect rules and returns true on the first passing rule. A "command" rule passes if the command exits with code 0. A "path" rule passes if the expanded path exists on the filesystem. Returns false if Detect is empty or all rules fail.
func EstimateTokens ¶
EstimateTokens returns a rough token estimate: word count × 1.3. Exported for testing.
func ExpandHome ¶
ExpandHome replaces a leading ~ with the user's home directory.
func ExportFileAndClip ¶
ExportFileAndClip writes fullCtx (raw Markdown) to a.ExportPath and copies a trimmed, formatted short summary plus a guidance line to the clipboard. fullCtx must be raw Markdown — FormatOutput is NOT applied to the file, only to the clipboard payload.
func ExportToClipboard ¶
ExportToClipboard writes content to the system clipboard. If clipboard access is unavailable (headless, no display), it falls back to printing the content to stdout with usage instructions.
func HookConfigInstalled ¶
HookConfigInstalled reports whether the command appears in the settings JSON.
func ReadMCPConfig ¶
ReadMCPConfig reads the mcpServers map from a JSON settings file. Returns an empty map (not an error) if the file does not exist or the key is absent. Returns an error if the file exists but cannot be parsed, or if the key is not a JSON object.
func RemoveHookConfig ¶
RemoveHookConfig removes a hook command entry from the tool's settings JSON. No-op if the file does not exist or the entry is not present. When dryRun is true, prints what would happen and returns without writing.
func RemoveSkillFile ¶
RemoveSkillFile removes a skill file from the adapter's skill directory. Also removes the parent directory if it becomes empty.
func ReplaceFile ¶
ReplaceFile writes preamble + "\n" + content to filePath, overwriting any existing content. If preamble is empty, only content is written (no leading newline). Parent directories are created as needed. When dryRun is true the function prints what it would do but writes nothing.
func ReplaceSection ¶
ReplaceSection writes `content` into `filePath` between HTML comment markers for the named section. If the section already exists it is replaced in-place; otherwise it is appended. Parent directories are created as needed. When dryRun is true the function prints what it would do but writes nothing.
func SkillFileInstalled ¶
SkillFileInstalled reports whether the skill file exists at the expected location.
func WriteHookConfig ¶
WriteHookConfig adds a hook command entry to the tool's settings JSON. key is a dot-separated JSON path, e.g. "hooks.SessionStart". Idempotent: if the command is already present, it is a no-op. When dryRun is true, prints what would happen and returns without writing.
func WriteMCPConfig ¶
WriteMCPConfig merges an MCP server entry into the host's settings JSON file. The file is created if it does not exist. Existing keys are preserved. When dryRun is true, prints what would happen and returns without writing.
func WriteSkillFile ¶
WriteSkillFile writes a skill file to the adapter's skill directory. The skill is placed at <basePath>/<skillID>/SKILL.md. Idempotent: overwrites if content differs.
Types ¶
type Adapter ¶
type Adapter struct {
ID string `yaml:"id"`
Name string `yaml:"name"`
Type string `yaml:"type"` // file-inject | clipboard-export | mcp-wire
Targets []Target `yaml:"targets"`
Format string `yaml:"format,omitempty"` // "markdown" (default) | "plain-prose"
Template string `yaml:"template"`
Instructions string `yaml:"instructions"`
MaxTokens int `yaml:"max_tokens,omitempty"` // 0 = unconstrained
MaxBytes int `yaml:"max_bytes,omitempty"` // hard byte ceiling; 0 = unconstrained
Verbosity string `yaml:"verbosity,omitempty"` // "minimal" | "standard" | "full"; default "full"
ExportPath string `yaml:"export_path,omitempty"` // file-export: path to write full context
MCPConfig *MCPConfig `yaml:"mcp_config,omitempty"`
HookConfig *HookConfig `yaml:"hook_config,omitempty"`
SkillConfig *SkillConfig `yaml:"skill_config,omitempty"`
Detect []DetectRule `yaml:"detect"`
}
Adapter defines how to inject SAP context into a specific AI tool.
func LoadAdapters ¶
LoadAdapters reads all *.yaml files from dir and returns the parsed adapters. If dir does not exist, returns an empty slice without error.
type DetectRule ¶
type DetectRule struct {
Command string `yaml:"command,omitempty"`
Path string `yaml:"path,omitempty"`
}
DetectRule defines a detection method for whether the tool is installed.
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine runs injection for a set of adapters, rendering per-adapter with its own budget.
func NewEngine ¶
func NewEngine(adapters []Adapter, packs []*content.Pack, profile *content.Profile, opts Options) *Engine
NewEngine constructs an Engine. A nil Out is normalised to io.Discard.
func (*Engine) RenderSectionContentForTest ¶
RenderSectionContentForTest exposes renderSectionContent for white-box tests. Do not call this from production code.
type HookConfig ¶
type HookConfig struct {
Path string `yaml:"path"`
Format string `yaml:"format"` // "json" only for now
Key string `yaml:"key"` // dot-separated JSON path, e.g. "hooks.SessionStart"
}
HookConfig defines where to write hook command entries.
type MCPConfig ¶
type MCPConfig struct {
Path string `yaml:"path"`
Format string `yaml:"format"`
Key string `yaml:"key"`
}
MCPConfig defines where to write MCP server configuration.
type Options ¶
type Options struct {
Scope string // "global" | "project"
ToolFilter string // if non-empty, only run this adapter ID
DryRun bool
Stats bool
Out io.Writer // for stats/warning output; nil → io.Discard
Dynamic *content.DynamicContext // nil = no dynamic section
Uninstall bool
// Lang is the active language for i18n. Always use e.opts.Lang inside engine code.
Lang string
Verbosity string // CLI override; empty = use adapter default
}
Options controls inject scope, filtering, dry-run, and stats behaviour.
type RunResult ¶
type RunResult struct {
Found int // sections/files removed in live mode
DryFound int // sections/files that would be removed in dry-run mode
Err error
}
RunResult holds the outcome of an Engine.Run() call.
type SectionInfo ¶
SectionInfo describes a non-sap-devs fenced block found in a target file.
func ScanOtherSections ¶
func ScanOtherSections(content string) []SectionInfo
ScanOtherSections finds non-sap-devs HTML-comment fenced blocks in content. Returns []SectionInfo{} (never nil) so it marshals as [] in JSON. If the same prefix appears multiple times, each start marker produces a separate entry.
type SkillConfig ¶
type SkillConfig struct {
Path string `yaml:"path"` // base directory, e.g. "~/.claude/skills"
}
SkillConfig defines where to install skill files for this adapter.
type StatusRow ¶
type StatusRow struct {
AdapterName string `json:"name"`
AdapterID string `json:"adapter"`
Scope string `json:"scope"`
TargetPath string `json:"path"` // unexpanded (~-form)
FileExists bool `json:"file_exists"`
Injected bool `json:"injected"` // sap-devs section present and well-formed
Orphaned bool `json:"orphaned"` // markers found but mismatched/reversed
// Stale is true when the on-disk section content differs from what inject would write today.
// Always false when FileExists=false, Injected=false, or engine has no packs loaded.
Stale bool `json:"stale"`
// Stretch-goal fields — always populated when FileExists=true.
FileSizeBytes int `json:"file_size_bytes"`
FileTokenEst int `json:"file_token_est"` // word count × 1.3
SapDevsTokens int `json:"sap_devs_tokens"` // token estimate for sap-devs section only
OtherSections []SectionInfo `json:"other_sections"` // non-sap-devs fenced blocks
}
StatusRow is the result of inspecting one adapter target (one row per adapter+target pair). An adapter with both a global and a project target produces two StatusRows.
type Target ¶
type Target struct {
Scope string `yaml:"scope"` // global | project
Path string `yaml:"path"`
Mode string `yaml:"mode"` // replace-section | append | replace-file
Section string `yaml:"section"`
Preamble string `yaml:"preamble,omitempty"` // prepended before content; replace-file only
}
Target is a single file injection target.