feat(admin): rename /admin/welcome to /admin/agent-prompt (Agent Setup Prompt)
Rename the welcome prompt editor from /admin/welcome to /admin/agent-prompt and update all UI labels to "Agent Setup Prompt". API endpoint URLs are unchanged (PUT/GET/DELETE /api/admin/welcome-template, GET /api/welcome). - Nav menu: "Welcome prompt" → "Agent Setup Prompt", href updated - Page title and h2 updated in admin_welcome.html - Error message hint in app/api/welcome.py updated to /admin/agent-prompt - Dashboard: replace inline <details> preview of _claude_setup_instructions with a simple link to /setup (Task C) - docs/welcome-template.md renamed to docs/agent-setup-prompt.md; internal references to /admin/welcome updated - OpenAPI snapshot path updated - Tests updated to reflect new route and removed inline preview
This commit is contained in:
parent
c7b14fb120
commit
ecb6c35ad5
8 changed files with 21 additions and 33 deletions
|
|
@ -81,7 +81,7 @@ async def get_welcome(
|
||||||
logger.warning("Welcome render failed: %s", e, exc_info=True)
|
logger.warning("Welcome render failed: %s", e, exc_info=True)
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=500,
|
status_code=500,
|
||||||
detail="Welcome template render failed. An admin can fix it at /admin/welcome.",
|
detail="Welcome template render failed. An admin can fix it at /admin/agent-prompt.",
|
||||||
)
|
)
|
||||||
return WelcomeResponse(content=rendered)
|
return WelcomeResponse(content=rendered)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
<a class="app-nav-link {% if _path.startswith('/setup') or _path.startswith('/install') %}is-active{% endif %}" href="/setup">Setup local agent</a>
|
<a class="app-nav-link {% if _path.startswith('/setup') or _path.startswith('/install') %}is-active{% endif %}" href="/setup">Setup local agent</a>
|
||||||
{% if session.user.is_admin %}
|
{% if session.user.is_admin %}
|
||||||
<a class="app-nav-link {% if _path.startswith('/admin/marketplaces') %}is-active{% endif %}" href="/admin/marketplaces">Marketplaces</a>
|
<a class="app-nav-link {% if _path.startswith('/admin/marketplaces') %}is-active{% endif %}" href="/admin/marketplaces">Marketplaces</a>
|
||||||
{% set _admin_active = _path.startswith('/admin/tables') or _path.startswith('/admin/tokens') or _path.startswith('/admin/users') or _path.startswith('/admin/groups') or _path.startswith('/admin/access') or _path.startswith('/admin/server-config') or _path.startswith('/admin/welcome') or _path.startswith('/admin/setup-banner') %}
|
{% set _admin_active = _path.startswith('/admin/tables') or _path.startswith('/admin/tokens') or _path.startswith('/admin/users') or _path.startswith('/admin/groups') or _path.startswith('/admin/access') or _path.startswith('/admin/server-config') or _path.startswith('/admin/agent-prompt') %}
|
||||||
<div class="app-nav-menu" id="adminNavMenu">
|
<div class="app-nav-menu" id="adminNavMenu">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="app-nav-link app-nav-menu-trigger {% if _admin_active %}is-active{% endif %}"
|
class="app-nav-link app-nav-menu-trigger {% if _admin_active %}is-active{% endif %}"
|
||||||
|
|
@ -32,8 +32,7 @@
|
||||||
<a class="app-nav-menu-item {% if _path.startswith('/admin/groups') %}is-active{% endif %}" role="menuitem" href="/admin/groups">Groups</a>
|
<a class="app-nav-menu-item {% if _path.startswith('/admin/groups') %}is-active{% endif %}" role="menuitem" href="/admin/groups">Groups</a>
|
||||||
<a class="app-nav-menu-item {% if _path.startswith('/admin/access') %}is-active{% endif %}" role="menuitem" href="/admin/access">Resource access</a>
|
<a class="app-nav-menu-item {% if _path.startswith('/admin/access') %}is-active{% endif %}" role="menuitem" href="/admin/access">Resource access</a>
|
||||||
<a class="app-nav-menu-item {% if _path.startswith('/admin/server-config') %}is-active{% endif %}" role="menuitem" href="/admin/server-config">Server config</a>
|
<a class="app-nav-menu-item {% if _path.startswith('/admin/server-config') %}is-active{% endif %}" role="menuitem" href="/admin/server-config">Server config</a>
|
||||||
<a class="app-nav-menu-item {% if _path.startswith('/admin/welcome') %}is-active{% endif %}" role="menuitem" href="/admin/welcome">Welcome prompt</a>
|
<a class="app-nav-menu-item {% if _path.startswith('/admin/agent-prompt') %}is-active{% endif %}" role="menuitem" href="/admin/agent-prompt">Agent Setup Prompt</a>
|
||||||
<a class="app-nav-menu-item {% if _path.startswith('/admin/setup-banner') %}is-active{% endif %}" role="menuitem" href="/admin/setup-banner">Setup banner</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}Welcome Prompt — {{ config.INSTANCE_NAME }}{% endblock %}
|
{% block title %}Agent Setup Prompt — {{ config.INSTANCE_NAME }}{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css"
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css"
|
||||||
|
|
@ -202,8 +202,8 @@
|
||||||
<div class="welcome-page">
|
<div class="welcome-page">
|
||||||
<div class="welcome-toolbar">
|
<div class="welcome-toolbar">
|
||||||
<div>
|
<div>
|
||||||
<h2 class="welcome-title">Analyst Welcome Prompt</h2>
|
<h2 class="welcome-title">Agent Setup Prompt</h2>
|
||||||
<p class="welcome-sub">Customise the CLAUDE.md generated for analysts on <code>da analyst setup</code>.</p>
|
<p class="welcome-sub">Customise the <code>CLAUDE.md</code> generated for analysts on <code>da analyst setup</code>.</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="status-chip">
|
<div id="status-chip">
|
||||||
{% if is_override %}
|
{% if is_override %}
|
||||||
|
|
|
||||||
|
|
@ -2046,20 +2046,7 @@
|
||||||
<a href="/setup" class="env-setup-link">Or open the full setup page →</a>
|
<a href="/setup" class="env-setup-link">Or open the full setup page →</a>
|
||||||
</div>
|
</div>
|
||||||
<div id="setupClaudeError" class="setup-error" role="alert" style="display:none;"></div>
|
<div id="setupClaudeError" class="setup-error" role="alert" style="display:none;"></div>
|
||||||
<details class="setup-preview-card" aria-label="Preview of the clipboard payload">
|
<a href="/setup" class="env-setup-link" style="display: block; margin-top: 8px;">View what Claude Code will receive on /setup →</a>
|
||||||
<summary class="setup-preview-summary">
|
|
||||||
<span class="setup-preview-chevron" aria-hidden="true">▸</span>
|
|
||||||
<span class="setup-preview-title">What Claude Code will receive</span>
|
|
||||||
</summary>
|
|
||||||
<p class="setup-preview-sub">
|
|
||||||
Read-only preview. The real token is generated the moment
|
|
||||||
you click the button above and is placed directly in your
|
|
||||||
clipboard — never shown on this page.
|
|
||||||
</p>
|
|
||||||
{% with preview_mode=True %}
|
|
||||||
{% include "_claude_setup_instructions.jinja" %}
|
|
||||||
{% endwith %}
|
|
||||||
</details>
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Welcome prompt customization
|
# Agent Setup Prompt
|
||||||
|
|
||||||
The welcome prompt is the `CLAUDE.md` file generated in an analyst's local
|
The agent setup prompt is the `CLAUDE.md` file generated in an analyst's local
|
||||||
workspace by `da analyst setup`. It instructs Claude Code on how to behave in
|
workspace by `da analyst setup`. It instructs Claude Code on how to behave in
|
||||||
that workspace — which commands to use, where to read schema metadata, what
|
that workspace — which commands to use, where to read schema metadata, what
|
||||||
metrics exist, what plugins are available.
|
metrics exist, what plugins are available.
|
||||||
|
|
@ -15,7 +15,7 @@ no admin action is required.
|
||||||
|
|
||||||
Admins can override the template via:
|
Admins can override the template via:
|
||||||
|
|
||||||
- **Admin UI:** `/admin/welcome` — textarea editor with placeholder cheatsheet
|
- **Admin UI:** `/admin/agent-prompt` — textarea editor with placeholder cheatsheet
|
||||||
and live preview button. Save sends a `PUT` to `/api/admin/welcome-template`.
|
and live preview button. Save sends a `PUT` to `/api/admin/welcome-template`.
|
||||||
- **REST API:**
|
- **REST API:**
|
||||||
- `GET /api/admin/welcome-template` — returns `{content, default, updated_at, updated_by}`. `content` is `null` when no override is set.
|
- `GET /api/admin/welcome-template` — returns `{content, default, updated_at, updated_by}`. `content` is `null` when no override is set.
|
||||||
|
|
@ -32,7 +32,7 @@ audit trail (`updated_at`, `updated_by`) is preserved.
|
||||||
[Jinja2](https://jinja.palletsprojects.com/) with `StrictUndefined`. Any
|
[Jinja2](https://jinja.palletsprojects.com/) with `StrictUndefined`. Any
|
||||||
typo in a placeholder name raises an error at render time rather than
|
typo in a placeholder name raises an error at render time rather than
|
||||||
silently emitting an empty string. Server returns HTTP 500 with a hint
|
silently emitting an empty string. Server returns HTTP 500 with a hint
|
||||||
pointing at `/admin/welcome`; the admin UI rejects syntax errors AND
|
pointing at `/admin/agent-prompt`; the admin UI rejects syntax errors AND
|
||||||
undefined-placeholder errors with HTTP 400 on save (validated by rendering
|
undefined-placeholder errors with HTTP 400 on save (validated by rendering
|
||||||
the template against a stub context before persisting).
|
the template against a stub context before persisting).
|
||||||
|
|
||||||
|
|
@ -3358,9 +3358,9 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/admin/welcome": {
|
"/admin/agent-prompt": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "admin_welcome_page_admin_welcome_get",
|
"operationId": "admin_agent_prompt_page_admin_agent_prompt_get",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"in": "header",
|
"in": "header",
|
||||||
|
|
|
||||||
|
|
@ -233,14 +233,16 @@ class TestClaudeSetupPreview:
|
||||||
assert "da diagnose" in body
|
assert "da diagnose" in body
|
||||||
assert "da auth whoami" in body
|
assert "da auth whoami" in body
|
||||||
|
|
||||||
def test_dashboard_preview_visible(self, web_client, admin_cookie):
|
def test_dashboard_setup_cta_links_to_setup(self, web_client, admin_cookie):
|
||||||
|
"""Dashboard setup CTA shows env-setup-cta and a link to /setup instead
|
||||||
|
of an inline collapsed preview."""
|
||||||
resp = web_client.get("/dashboard", cookies=admin_cookie)
|
resp = web_client.get("/dashboard", cookies=admin_cookie)
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
body = resp.text
|
body = resp.text
|
||||||
assert "env-setup-cta" in body
|
assert "env-setup-cta" in body
|
||||||
assert "setup-preview-pre" in body
|
assert "View what Claude Code will receive on /setup" in body
|
||||||
assert "What Claude Code will receive" in body
|
# inline <details> preview block must no longer appear
|
||||||
assert "<will be generated on click>" in body
|
assert 'aria-label="Preview of the clipboard payload"' not in body
|
||||||
|
|
||||||
def test_install_mcp_card_removed(self, web_client):
|
def test_install_mcp_card_removed(self, web_client):
|
||||||
"""The stale 'Use with Claude Code / MCP' card on /setup has been
|
"""The stale 'Use with Claude Code / MCP' card on /setup has been
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ def test_put_rejects_undefined_placeholder(seeded_app):
|
||||||
|
|
||||||
def test_get_welcome_500_includes_reset_hint_on_render_failure(seeded_app, monkeypatch):
|
def test_get_welcome_500_includes_reset_hint_on_render_failure(seeded_app, monkeypatch):
|
||||||
"""If an override slips through validation and fails at render time, the
|
"""If an override slips through validation and fails at render time, the
|
||||||
user-visible 500 must point at /admin/welcome rather than leaking a
|
user-visible 500 must point at /admin/agent-prompt rather than leaking a
|
||||||
Jinja stack trace."""
|
Jinja stack trace."""
|
||||||
# Stub render_welcome to raise a TemplateError so we exercise the
|
# Stub render_welcome to raise a TemplateError so we exercise the
|
||||||
# exception path without needing a malformed override (PUT validation
|
# exception path without needing a malformed override (PUT validation
|
||||||
|
|
@ -123,7 +123,7 @@ def test_get_welcome_500_includes_reset_hint_on_render_failure(seeded_app, monke
|
||||||
headers=admin,
|
headers=admin,
|
||||||
)
|
)
|
||||||
assert r.status_code == 500
|
assert r.status_code == 500
|
||||||
assert "/admin/welcome" in r.json()["detail"]
|
assert "/admin/agent-prompt" in r.json()["detail"]
|
||||||
|
|
||||||
|
|
||||||
def test_admin_preview_renders_arbitrary_content(seeded_app):
|
def test_admin_preview_renders_arbitrary_content(seeded_app):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue