tutorials

package
v0.0.15 Latest Latest
Warning

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

Go to latest
Published: May 8, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrRepoUnavailable = errors.New("repo unavailable")

ErrRepoUnavailable is returned when a GitHub API request returns 403 or 404.

Functions

func ExtractLevel

func ExtractLevel(tags []string) string

ExtractLevel derives the experience level from tutorial tags.

func IndexCacheAge

func IndexCacheAge(cacheDir string) time.Duration

IndexCacheAge returns the age of the index cache file, or a negative duration if missing.

func LoadProgress

func LoadProgress(dataDir string) (map[string]TutorialProgress, error)

LoadProgress reads all tutorial progress from the data directory.

func ResolveImageURLs

func ResolveImageURLs(content, repo, branch, slug string) string

ResolveImageURLs replaces relative image paths with full GitHub raw content URLs rendered as markdown links so glamour doesn't word-wrap the URL.

func ResolveImageURLsKeepMarkdown

func ResolveImageURLsKeepMarkdown(content, repo, branch, slug string) string

ResolveImageURLsKeepMarkdown resolves relative image paths to full GitHub raw URLs but preserves the ![alt](url) markdown image syntax. Use this for MCP responses where the agent should see image markdown, not link markdown.

func SaveContent

func SaveContent(cacheDir string, tut *Tutorial) error

SaveContent writes a parsed tutorial to the content cache.

func SaveIndex

func SaveIndex(cacheDir string, index []TutorialMeta) error

SaveIndex writes the tutorial index to the cache.

func SaveProgress

func SaveProgress(dataDir string, progress map[string]TutorialProgress) error

SaveProgress writes all tutorial progress to the data directory.

func SaveRepoInfo

func SaveRepoInfo(cacheDir string, repos []RepoInfo) error

SaveRepoInfo writes cached repo metadata.

func UpdateProgress

func UpdateProgress(dataDir, slug string, currentStep, totalSteps int, markDone bool) error

UpdateProgress updates progress for a tutorial, creating a new entry if needed.

Types

type Client

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

Client handles GitHub API interactions for tutorials.

func NewClient

func NewClient(cfg ClientConfig) *Client

NewClient creates a new tutorial GitHub client.

func (*Client) FetchDefaultBranch

func (c *Client) FetchDefaultBranch(repo string) (string, error)

FetchDefaultBranch returns the default branch for a repo.

func (*Client) FetchRawMarkdown

func (c *Client) FetchRawMarkdown(repo, branch, slug string) (string, error)

FetchRawMarkdown fetches the raw markdown content for a tutorial.

func (*Client) FetchRepoList

func (c *Client) FetchRepoList() ([]string, error)

FetchRepoList fetches the list of tutorial repo names.

func (*Client) FetchRepoTree

func (c *Client) FetchRepoTree(repo, branch string) (slugs []string, sha string, err error)

FetchRepoTree fetches the tree for a repo and returns tutorial slugs + tree SHA.

type ClientConfig

type ClientConfig struct {
	RepoListURL string
	APIBaseURL  string
	RawBaseURL  string
	Token       string
	UserAgent   string
}

ClientConfig allows overriding base URLs for testing.

type CommandAnnotation

type CommandAnnotation struct {
	Command     string `json:"command"`
	Description string `json:"description,omitempty"`
	WorkingDir  string `json:"working_dir,omitempty"`
}

type FetchedImage

type FetchedImage struct {
	Alt      string `json:"alt"`
	URL      string `json:"url"`
	Data     string `json:"data"`
	MIMEType string `json:"mime_type"`
}

FetchedImage holds base64-encoded image data ready for MCP ImageContent.

func FetchImage

func FetchImage(rawURL, cacheDir, slug string) (*FetchedImage, error)

FetchImage downloads an image from url, caches it locally, and returns the base64-encoded data with MIME type. Returns cached data on subsequent calls.

func FetchStepImages

func FetchStepImages(refs []ImageRef, cacheDir, slug string) []FetchedImage

FetchStepImages fetches all images from the given refs, skipping any that fail.

type FileCreateAnnotation

type FileCreateAnnotation struct {
	Filename string `json:"filename"`
	Language string `json:"language"`
	Content  string `json:"content"`
}

type ImageRef

type ImageRef struct {
	Alt          string `json:"alt"`
	OriginalPath string `json:"original_path"`
	URL          string `json:"url"`
}

ImageRef represents a parsed image reference from tutorial markdown.

func ExtractImageRefs

func ExtractImageRefs(content, repo, branch, slug string) []ImageRef

ExtractImageRefs finds all markdown image references and resolves relative paths to full GitHub raw URLs. Absolute URLs and path traversals are left as-is.

type RepoInfo

type RepoInfo struct {
	Name          string `json:"name"`
	DefaultBranch string `json:"default_branch"`
	TreeSHA       string `json:"tree_sha,omitempty"`
}

RepoInfo stores cached metadata about a sap-tutorials repo.

func LoadRepoInfo

func LoadRepoInfo(cacheDir string) ([]RepoInfo, error)

LoadRepoInfo reads cached repo metadata.

type StepAnnotations

type StepAnnotations struct {
	Commands          []CommandAnnotation      `json:"commands,omitempty"`
	FileCreates       []FileCreateAnnotation   `json:"file_creates,omitempty"`
	Verifications     []VerificationAnnotation `json:"verifications,omitempty"`
	PrerequisiteTools []string                 `json:"prerequisite_tools,omitempty"`
}

func AnnotateStep

func AnnotateStep(md string) StepAnnotations

type Tutorial

type Tutorial struct {
	TutorialMeta
	Prerequisites string         `json:"prerequisites,omitempty"`
	YouWillLearn  []string       `json:"you_will_learn,omitempty"`
	Steps         []TutorialStep `json:"steps"`
}

Tutorial is a fully parsed tutorial with step content.

func LoadContent

func LoadContent(cacheDir, slug string) (*Tutorial, error)

LoadContent reads a parsed tutorial from the content cache.

func Parse

func Parse(md, slug, repo string) (*Tutorial, error)

Parse parses a full tutorial markdown into a Tutorial struct.

type TutorialMeta

type TutorialMeta struct {
	Slug        string   `json:"slug"`
	Title       string   `json:"title"`
	Description string   `json:"description"`
	Time        int      `json:"time"`
	Level       string   `json:"level"`
	Tags        []string `json:"tags"`
	PrimaryTag  string   `json:"primary_tag"`
	Author      string   `json:"author,omitempty"`
	Repo        string   `json:"repo"`
	URL         string   `json:"url"`
	Parser      string   `json:"parser"`
}

TutorialMeta is a resolved tutorial in the full index (cached from GitHub).

func Enrich

func Enrich(index []TutorialMeta, userAgent string) []TutorialMeta

Enrich attempts to augment the index with data from developers.sap.com. Returns the original index unchanged if the API is unavailable (403, timeout, etc.).

func EnrichWithURL

func EnrichWithURL(index []TutorialMeta, userAgent, baseURL string) []TutorialMeta

EnrichWithURL is the testable variant of Enrich with a custom base URL.

func FilterByLevel

func FilterByLevel(index []TutorialMeta, level string) []TutorialMeta

FilterByLevel returns tutorials matching the given level.

func FilterByTags

func FilterByTags(index []TutorialMeta, tags []string) []TutorialMeta

FilterByTags returns tutorials with at least one tag matching (OR, case-insensitive, substring).

func FindBySlug

func FindBySlug(index []TutorialMeta, slug string) *TutorialMeta

FindBySlug returns the first tutorial matching slug, or nil.

func LoadIndex

func LoadIndex(cacheDir string) ([]TutorialMeta, error)

LoadIndex reads the tutorial index from the cache and deduplicates by slug.

func ParseFrontmatterOnly

func ParseFrontmatterOnly(md, slug, repo string) (*TutorialMeta, error)

ParseFrontmatterOnly extracts metadata without parsing steps.

func Search(index []TutorialMeta, query string) []TutorialMeta

Search returns tutorials matching query against title, description, slug, and tags. Multi-word queries use AND semantics: every word must appear somewhere in the combined text. Results are ranked: title matches first, then others.

type TutorialProgress

type TutorialProgress struct {
	Slug           string     `json:"slug"`
	CurrentStep    int        `json:"current_step"`
	CompletedSteps []int      `json:"completed_steps"`
	TotalSteps     int        `json:"total_steps"`
	StartedAt      time.Time  `json:"started_at"`
	LastAccessed   time.Time  `json:"last_accessed"`
	CompletedAt    *time.Time `json:"completed_at,omitempty"`
}

TutorialProgress tracks a user's position within a tutorial.

func GetProgress

func GetProgress(dataDir, slug string) (*TutorialProgress, error)

GetProgress returns progress for a single tutorial, or nil if not started.

func MergeCompletedSteps

func MergeCompletedSteps(dataDir, slug string, completedSteps []int, currentStep, totalSteps int) (*TutorialProgress, error)

MergeCompletedSteps merges a batch of completed step indices into the stored progress for a tutorial. Steps are deduplicated and sorted. currentStep is set explicitly if > 0, otherwise inferred from the last completed step. If all steps are completed, CompletedAt is stamped.

type TutorialStep

type TutorialStep struct {
	Number  int    `json:"number"`
	Title   string `json:"title"`
	Content string `json:"content"`
}

TutorialStep is a single step within a tutorial.

type VerificationAnnotation

type VerificationAnnotation struct {
	Command      string `json:"command,omitempty"`
	ExpectOutput string `json:"expect_output,omitempty"`
	Description  string `json:"description,omitempty"`
	Confidence   string `json:"confidence,omitempty"`
}

Jump to

Keyboard shortcuts

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