# golem15.golem The shared AI plugin for SummerCMS applications: provider adapters for the Anthropic Messages API and the OpenAI-compatible chat completions API, prompts and AI responses, and an AI service that sends them through the framework's guarded outbound client. ```go import _ "git.golem15.com/golem15/sm-golem-plugin" ``` Module `git.golem15.com/golem15/sm-golem-plugin`, package `golem`, plugin ID `golem15.golem`. ## Overview The plugin is a compiled SummerCMS plugin ported from the WinterCMS `Golem15.Golem` plugin. Its `init` registers it with the framework, so an application loads it by listing it in `summer.yaml`; `summer build` then emits the blank import above into the application's `plugins.gen.go`. Another plugin that sends AI requests lists `golem15.golem` in its `Requires()` and imports the `classes/...` packages. The adapters are hand-written JSON mappings with no vendor SDK. Every request goes through a `fetchguard.Client`: a config marked `Trusted` (a model an operator configured) runs in `fetchguard.TrustedMode`, every other config (a key a user or an organisation supplied) in `fetchguard.PublicOnlyMode`, which refuses private and reserved addresses at dial time. The plugin's config keys, lang namespace and plugin ID are a contract shared by every application that mounts it: change them only in a backwards-compatible way. ## Features - **Prompts.** `valueobjects.Prompt` is an immutable request: a system prompt, user and assistant messages, messages with base64 images (`AddUserMessageWithImage`, `AddUserMessageWithImages`) or an uploaded file id (`AddUserMessageWithFileID`), a model override and extra options in insertion order. `ToAPIPayload` builds the OpenAI chat completions body as a `valueobjects.Payload`, a JSON object that keeps its key order. - **Responses.** `valueobjects.AIResponse` carries the content, token usage and the provider's decoded answer (`Raw`, which keeps `finish_reason` and `stop_reason`) or the failure message. `Err` holds the Go error behind a failure for logs and tests and is never shown to a user. - **OpenAI-compatible adapter.** `providers.OpenAIAdapter` posts to `/chat/completions` with `Authorization: Bearer`, drops `response_format`, maps `max_tokens` to `max_completion_tokens` and adds `reasoning_effort: low` for o-series and gpt-5 models. It also serves compatible providers through their base URL. `providers.ForName` picks the adapter by name. - **AI service.** `services.AIService.Send` applies the model's system prompt when the prompt has none and posts the prompt to the config's chat endpoint. It returns the WinterCMS plugin's failure messages: no model configured, no API key, no connection, and an answer that is not JSON. `services.ForApp` returns the application's shared service. ## Usage Mount the plugin in an application as a git submodule at `plugins/golem15/golem`: ```sh git submodule add git@git.golem15.com:golem15/sm-golem-plugin.git plugins/golem15/golem ``` Add it to the application's `go.work` and `go.mod`: ```text use ./plugins/golem15/golem require git.golem15.com/golem15/sm-golem-plugin v0.0.0 replace git.golem15.com/golem15/sm-golem-plugin => ./plugins/golem15/golem ``` List it in `summer.yaml` before the plugins that require it and run `summer build`: ```yaml module: git.golem15.com/golem15/acme binary: acme plugins: - id: golem15.golem module: git.golem15.com/golem15/sm-golem-plugin - id: acme.blog module: git.golem15.com/golem15/acme/plugins/acme/blog ``` The plugin's own `go.mod` replaces the framework with `../../../../summercms.go`, so it expects the framework checkout next to the application checkout. A plugin sends a prompt with a user's own key: ```go svc := services.ForApp(app) prompt := valueobjects.NewPrompt(). WithSystem("You catalog physical items."). AddUserMessage("List the items.") res := svc.Send(ctx, prompt, &services.ModelConfig{ Adapter: "openai", APIKey: key, Model: "gpt-4o-mini", }) if !res.Success { return errors.New(res.Error) } ``` ## API reference - `golem`: `Plugin`, the `golem15.golem` plugin. - `classes/valueobjects`: `Prompt`, `NewPrompt`, `Message`, `ContentPart`, `ImageURL`, `FileRef`, `Image`, `Payload`, `NewPayload`, `AIResponse`, `Success`, `Failure`. - `classes/providers`: `Adapter`, `OpenAIAdapter`, `ForName`, `OpenAIBaseURL`, `AnthropicBaseURL`. - `classes/services`: `ModelConfig`, `DefaultModelID`, `AIService`, `NewAIService`, `ForApp`, `ConfigTimeoutSeconds`, `DefaultTimeout`. ## Configuration Defaults live in `config/config.yaml` and are merged under `golem15.golem.*`. | Key | Default | Meaning | |-----|---------|---------| | `golem15.golem.ssrf.allowed_hosts` | `oaidalleapiprodscus.blob.core.windows.net`, `.openai.com` | Hosts an untrusted base URL or an AI-returned image URL may use. A leading dot matches any subdomain. | | `golem15.golem.ai.timeout_seconds` | `120` | Timeout of every AI provider request. | ## Dependencies - The SummerCMS framework, `git.golem15.com/golem15/summercms` (modules `backpack`, `compass`, `fetchguard`, `pact`, `party`). - GORM, as pinned in `go.mod`. ## Testing ```sh go test ./... ```