feat: prompt template tech debt — tests, read-only endpoints, double-… (#67)

* feat: prompt template tech debt — tests, read-only endpoints, double-load fix, server creation modal

Close test coverage gaps for prompt templates:
- Resume with deleted template: verifies graceful degradation (template_content=None, warning logged)
- Threading safety: concurrent set_template/init_system_messages with no race conditions
- Factory passthrough: template kwarg propagation through WorkstreamManager.create()

Add read-only template listing endpoints (read scope, no content exposed):
- GET /v1/api/templates — prompt template summaries (name, category, is_default, origin)
- GET /v1/api/ws-templates — enabled workstream template summaries (name, description, model)
- Available on both server and console; Python + TypeScript SDK methods added
- Console creation modal switched from admin endpoint to read-scope endpoint

Eliminate double-load inefficiency in workstream creation:
- Template validation moved before mgr.create() (no create-then-rollback on invalid template)
- template kwarg plumbed through WorkstreamManager.create() and session factory
- _SessionFactory Protocol added for proper mypy typing

Add workstream creation modal to server web UI:
- Name, model, template dropdown, ws_template/profile dropdown
- Instrument panel aesthetic: gradient top border, blur backdrop, amber accent
- Focus trap, Escape/Enter keyboard handling, loading state, error display
- WCAG AA contrast compliance, reduced-motion support

* fix: add list_ws_templates SDK methods + regenerate OpenAPI snapshots

Add list_ws_templates() to Python SDK (async + sync) and listWsTemplates()
to TypeScript SDK for the new GET /v1/api/ws-templates server endpoint.
Add WsTemplateSummary + ListWsTemplateSummaryResponse TypeScript types.
Regenerate openapi-server.json and openapi-console.json snapshots.

Addresses Copilot review feedback on PR #67.

* fix: skip template pre-validation when resuming a workstream

When resume_ws is set, the request's template field is irrelevant —
resume() restores the template from workstream_config. Pre-validating
a stale template name would incorrectly return 400 before the resume
even runs.

Addresses Copilot review feedback on PR #67.
This commit is contained in:
Patrick Buckley
2026-03-15 02:09:31 -07:00
committed by GitHub
parent e2a199c9c3
commit 376da3d084
24 changed files with 961 additions and 39 deletions
+61
View File
@@ -618,6 +618,67 @@ Each saved workstream object:
---
### `GET /v1/api/templates`
Returns a summary list of all available prompt templates. This is a read-only
endpoint (requires `read` scope) that exposes template names and categories
without revealing template content. Useful for populating template selectors
in UIs or discovering available templates before creating a workstream.
**Response:**
```json
{
"templates": [
{"name": "safety-guidelines", "category": "safety", "is_default": true, "origin": "manual"},
{"name": "mcp__server__code", "category": "", "is_default": false, "origin": "mcp"}
]
}
```
Each template summary:
| Field | Type | Description |
|--------------|--------|------------------------------------------------------|
| `name` | string | Template name (used in `template` field on creation) |
| `category` | string | Template category |
| `is_default` | bool | Whether template is auto-applied to all sessions |
| `origin` | string | Template origin: `manual` or `mcp` |
> **Note:** For full template management (create, update, delete, view content),
> use the admin endpoints at `GET /v1/api/admin/templates` (requires `admin.templates` permission).
---
### `GET /v1/api/ws-templates`
Returns a summary list of enabled workstream templates. This is a read-only
endpoint (requires `read` scope) for populating template selectors in UIs.
**Response:**
```json
{
"ws_templates": [
{"name": "code-review", "description": "Code review profile", "model": "gpt-5"},
{"name": "ops-triage", "description": "On-call triage", "model": ""}
]
}
```
Each workstream template summary:
| Field | Type | Description |
|---------------|--------|-------------------------------------------------|
| `name` | string | Template name (used in `ws_template` on creation)|
| `description` | string | Human-readable description |
| `model` | string | Model alias override (empty = use default) |
> **Note:** For full workstream template management, use the admin endpoints at
> `GET /v1/api/admin/ws-templates` (requires `admin.templates` permission).
---
### `POST /v1/api/send`
Sends a user message to a workstream. Spawns a daemon worker thread that calls
@@ -85,6 +85,12 @@ tload --> trender : template content
trender --> tsys : rendered content
tset --> tload : name or None
note right of pt_db
Read-only listing:
GET /v1/api/templates
(read scope, summary only)
end note
govjs --> wt_db : /v1/api/admin/ws-templates
wtr --> wt_db : get_ws_template_by_name()
wtr --> wta : template settings
@@ -48,6 +48,14 @@ end note
Admin -> Server : GET /v1/api/admin/ws-templates
Server -> Storage : list_ws_templates()
Server <-- Server : GET /v1/api/ws-templates\n(read scope, summary only)
note right
**Read-only listing:**
name, description, model.
Used by creation UI dropdowns.
Available on both server + console.
end note
Admin -> Server : DELETE /v1/api/admin/ws-templates/{id}
Server -> Storage : delete_ws_template(id)
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f4dac4948d928b4705936d73b4d159aa1e89315ec0397616ca914bbf19e7a1ce
size 206479
oid sha256:3aaca1ae4c6c255dc9569f59e3ccc24f8b3bab0ac2a9b08c85e2af72d6a400c7
size 218575
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c06d7086d7965eb9fe333396f027133d42507cf120bfe8dc851c009a8768ec48
size 284926
oid sha256:fadf5b07f8230ecf97805a86b308eaa9eb30516dd26900e5c9f70e6fb7562bab
size 296339