Files
noema/web/templates/pages/prompts.html
T
Andy Dixon d9c6ffa30f feat: add provider-neutral LLM layer with secrets, budgets, recording and prompts
Phase 7 (ADR-0004). Cognitive code asks the router for a role; the
router maps roles to configured models with ordered fallbacks, applies
global and per-mind daily token budgets and a concurrency limit, records
every call (request, response, usage, latency, cost, seed, request hash)
and can serve recordings back for exact replay. Providers are raw HTTP
clients for OpenAI-compatible, Anthropic and Ollama endpoints, with
embedding support for the embed role wired into memory retrieval.

Secrets are references only: env:, file:, or enc: values encrypted with
AES-256-GCM under NOEMA_MASTER_KEY; keys are resolved at call time and
never rendered, logged or exported. Outbound HTTP refuses private and
loopback addresses at dial time unless a provider explicitly allows it,
bounds redirects and caps bodies. Provider errors are scrubbed.

Prompts are named, versioned rows with system and user templates and an
optional JSON schema; untrusted text enters only through delimited data
blocks. Six defaults are seeded and never overwritten. The UI adds the
LLM page (providers, models, role matrix, usage, errors, budgets), a
provider page with connectivity test, and a prompt manager with editor,
test runner, history, restore, clone and diff. CLI: provider, prompt.
2026-06-23 23:43:33 +01:00

24 lines
1.4 KiB
HTML

{{define "content"}}
<div class="pagehead"><h1>Prompts</h1><p class="muted">Named, versioned templates. Structured data is injected; untrusted text always travels inside data blocks.</p></div>
<section class="grid cols-3-1">
<div class="card">
<table class="table compact">
<thead><tr><th>Name</th><th>Role</th><th>Description</th><th>Version</th><th>Updated</th></tr></thead>
<tbody>{{range .Data.Prompts}}<tr><td><a href="/prompts/{{.Name}}"><code>{{.Name}}</code></a></td><td><span class="badge">{{.Role}}</span></td><td class="small">{{.Description}}</td><td class="small">v{{.CurrentVersion}}{{if .Schema}} · JSON{{end}}</td><td class="small muted">{{ago .UpdatedAt}}</td></tr>{{else}}<tr><td colspan="5" class="muted">No prompts.</td></tr>{{end}}</tbody>
</table>
</div>
{{if .Principal.User.Role.AtLeast "administrator"}}
<div class="card">
<h2>New prompt</h2>
<form method="post" action="/prompts" class="stack">
<input type="hidden" name="_csrf" value="{{.CSRF}}">
<label>Name <input name="name" required pattern="[A-Za-z0-9._-]+" placeholder="respond.terse"></label>
<label>Role <select name="role">{{range llmRoles}}<option value="{{.Role}}">{{.Role}}</option>{{end}}</select></label>
<label>Description <input name="description"></label>
<button class="btn btn-primary" type="submit">Create (then edit)</button>
</form>
</div>
{{end}}
</section>
{{end}}