feat(backend): generalized workbench endpoint + tool registry (#136) #218
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/136-workbench-endpoint-registry"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Final foundation item of v3.10.0 GM Workbench. Targets the integration branch. Builds on #134 + #138.
Closes #136.
What
The single extension point for the Workbench — adding a tool = adding one
ToolDefregistry entry, never touching the endpoint.generation_service.py:GENERATOR_TOOLSregistry +ToolDef(input model, system prompt, context builders, prompt/parse callables, or a customrunner;sync_allowed/prefetchable/json_modeflags).run_toolgeneric executor (build declared context → prompt →llm_service.generate_structured_text→ parse). Context builderscampaign_context(folds in #137's system context),lore_context,threads_context,recent_sessions_context. Eager-loadsgame_system_ref+ guards unloaded refs (sa_inspect().unloaded) against async lazy loads.POST /api/campaigns/{campaign_id}/workbench/{tool_id}/generate(GM-only): 404 unknown tool → 422 bad params → 503 if LLM unconfigured; sync tools run inline (row writtenready/failed), async tools enqueuerun_workbench_generationand returnpending(poll #138 history).tool_id="names"— a custom runner delegating toaudio_service.generate_name_options, so output (incl. #137 per-system hints) is byte-identical and existing name tests pass unmodified. Custom-prompt names no longer need an active session.Verification (Docker, py3.12)
test_workbench_generation.py: sync/async dispatch, GM-only 403, 404/422, GenerationResult written + visible in history, session-less custom prompt); existing name-generation tests pass unmodified.ruff check/formatclean. No migration; no bot API change.Deferred (noted)
planning_tasks.prefetch_name_optionsstays names-specific (it precomputes context then closes its DB session before 13 slow LLM calls; a generic worker needs an open session), withprefetchable=Trueas the declarative hook. Folds naturally into #155 (improv NPC "with prefetch"), the second prefetchable consumer, where a generalized worker can be designed + tested against two tools.🤖 Generated with Claude Code
The single extension point for the GM Workbench: a GENERATOR_TOOLS registry (ToolDef) + POST /api/campaigns/{campaign_id}/workbench/{tool_id}/generate (GM-only) that dispatches sync (inline) or async (Celery, run_workbench_generation) per the tool's sync_allowed flag, writing every run into the #138 GenerationResult scratchpad. Adding a tool = adding one registry entry. - generation_service.py: ToolDef registry, ToolResult, run_tool generic executor (build declared context -> prompt -> llm_service.generate_structured_text -> parse) + context builders campaign_context (folds in #137 system context) / lore_context / threads_context / recent_sessions_context. Eager-loads game_system_ref and guards unloaded refs (sa_inspect().unloaded) against async lazy loads. - Names migrated as the first tool (tool_id="names"): a custom runner delegating to audio_service.generate_name_options so output — incl. #137 per-system hints — stays byte-identical and existing name tests pass unmodified. Custom-prompt names no longer require an active session (campaign-scoped). - Old endpoints kept as thin wrappers into the registry (sessions name-options, planning names cache-miss); planning prefetch left delegating to the same name generator with prefetchable=True as the declarative hook (full generalization folds into #155, the second prefetchable consumer). Foundation for the six generator tools. No migration (uses #138's GenerationResult); no bot API change. Verified in Docker: 684 backend tests (+10), ruff clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>