mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-07-09 17:08:29 +00:00
Disable What's New cards
Move active What's New content into an empty slide list so the startup modal stays quiet until new cards are added. Keep manual Open available with an empty state, and update the static test plus DOX contract for dormant periods.
This commit is contained in:
parent
bcdc99e6cc
commit
0a9e15be87
7 changed files with 64 additions and 81 deletions
|
|
@ -93,5 +93,5 @@ Direct child DOX files:
|
|||
| [_text_editor/AGENTS.md](_text_editor/AGENTS.md) | Native text read, write, and patch tool. |
|
||||
| [_time_travel/AGENTS.md](_time_travel/AGENTS.md) | Workspace history, diff, travel, snapshot, and revert flows. |
|
||||
| [_whatsapp_integration/AGENTS.md](_whatsapp_integration/AGENTS.md) | WhatsApp Baileys bridge integration. |
|
||||
| [_whats_new/AGENTS.md](_whats_new/AGENTS.md) | Version-gated What's New showcase modal and startup trigger. |
|
||||
| [_whats_new/AGENTS.md](_whats_new/AGENTS.md) | Version-gated What's New showcase modal, card list, and startup trigger. |
|
||||
| [_whisper_stt/AGENTS.md](_whisper_stt/AGENTS.md) | Whisper speech-to-text integration. |
|
||||
|
|
|
|||
|
|
@ -2,20 +2,22 @@
|
|||
|
||||
## Purpose
|
||||
|
||||
- Own the built-in version-gated "What's New" modal for showcasing Agent Zero features after updates.
|
||||
- Own the built-in version-gated "What's New" modal for showcasing Agent Zero features after updates, dormant when no cards are configured.
|
||||
|
||||
## Ownership
|
||||
|
||||
- `plugin.yaml` owns metadata and always-enabled status.
|
||||
- `webui/main.html` owns the canonical modal opened by startup and the Builtin Plugins `Open` button.
|
||||
- `webui/whats-new.html` is a compatibility redirect to `webui/main.html`.
|
||||
- `webui/whats-new-slides.js` owns the current card list; an empty list disables automatic display.
|
||||
- `webui/` owns the Alpine store, copy, and showcase media assets.
|
||||
- `extensions/webui/initFw_end/` owns the startup trigger that opens the modal once per newer installed version unless the user has permanently opted out.
|
||||
- `extensions/webui/initFw_end/` owns the startup trigger that opens the modal once per newer installed version when cards exist unless the user has permanently opted out.
|
||||
|
||||
## Local Contracts
|
||||
|
||||
- Closing, Skip, or Done records only the current installed version as seen.
|
||||
- Future updates should auto-open the modal again unless the user checks the modal's permanent opt-out checkbox.
|
||||
- Future updates with cards should auto-open the modal again unless the user checks the modal's permanent opt-out checkbox.
|
||||
- Do not auto-open the modal when `webui/whats-new-slides.js` exports no cards.
|
||||
- The permanent opt-out is stored in browser-local state under `a0_whats_new_never_show`.
|
||||
- Honor the legacy `a0_whats_new_seen_version` browser-local marker as the last seen version.
|
||||
- Keep the modal copy concise, left-aligned, and paired with feature media.
|
||||
|
|
@ -24,7 +26,7 @@
|
|||
|
||||
## Work Guidance
|
||||
|
||||
- Add showcase assets under `webui/assets/` and reference them through `/plugins/_whats_new/webui/assets/...`.
|
||||
- Add showcase cards in `webui/whats-new-slides.js`; add assets under `webui/assets/` and reference them through `/plugins/_whats_new/webui/assets/...`.
|
||||
- Keep the startup extension idempotent and tolerant of missing or non-comparable version labels.
|
||||
- Prefer release-line comparisons over development commit-distance comparisons so local development builds do not reopen the modal on every commit.
|
||||
- Preserve `webui/main.html` so the plugin list exposes the standard `Open` action.
|
||||
|
|
@ -32,7 +34,8 @@
|
|||
## Verification
|
||||
|
||||
- Run `pytest tests/test_whats_new_static.py` after changing the modal, trigger, or assets.
|
||||
- Smoke-test startup display, slide navigation, dismissal, same-version reload behavior, newer-version display behavior, opt-out behavior, and manual Builtin Plugins `Open` behavior in the WebUI.
|
||||
- When the card list is empty, smoke-test no startup modal and the manual Builtin Plugins `Open` empty state when practical.
|
||||
- When cards exist, smoke-test startup display, slide navigation, dismissal, same-version reload behavior, newer-version display behavior, opt-out behavior, and manual Builtin Plugins `Open` behavior in the WebUI.
|
||||
|
||||
## Child DOX Index
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { getModalStack, isModalOpen, openModal } from "/js/modals.js";
|
||||
import { slides } from "/plugins/_whats_new/webui/whats-new-slides.js";
|
||||
|
||||
const MODAL_PATH = "/plugins/_whats_new/webui/main.html";
|
||||
const LEGACY_MODAL_PATH = "/plugins/_whats_new/webui/whats-new.html";
|
||||
|
|
@ -109,6 +110,7 @@ function shouldNeverShow() {
|
|||
}
|
||||
|
||||
function shouldShowWhatsNew(version = currentVersion()) {
|
||||
if (!slides.length) return false;
|
||||
if (shouldNeverShow()) return false;
|
||||
if (!version) return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,11 @@
|
|||
<div x-data>
|
||||
<template x-if="$store.whatsNew">
|
||||
<div class="whats-new-shell" x-init="$store.whatsNew.onOpen()" x-destroy="$store.whatsNew.cleanup()">
|
||||
<section class="whats-new-media-panel" :aria-label="$store.whatsNew.currentSlide.mediaLabel">
|
||||
<section
|
||||
class="whats-new-media-panel"
|
||||
x-show="$store.whatsNew.hasSlides()"
|
||||
:aria-label="$store.whatsNew.currentSlide.mediaLabel"
|
||||
>
|
||||
<template x-if="$store.whatsNew.currentSlide.mediaType === 'video'">
|
||||
<video
|
||||
class="whats-new-media"
|
||||
|
|
@ -35,7 +39,10 @@
|
|||
<div class="whats-new-eyebrow" x-text="$store.whatsNew.currentSlide.eyebrow"></div>
|
||||
<h3 x-text="$store.whatsNew.currentSlide.title"></h3>
|
||||
<p class="whats-new-summary" x-text="$store.whatsNew.currentSlide.summary"></p>
|
||||
<ul class="whats-new-bullets">
|
||||
<ul
|
||||
class="whats-new-bullets"
|
||||
x-show="$store.whatsNew.currentSlide.bullets.length"
|
||||
>
|
||||
<template x-for="item in $store.whatsNew.currentSlide.bullets" :key="item">
|
||||
<li x-text="item"></li>
|
||||
</template>
|
||||
|
|
@ -44,7 +51,7 @@
|
|||
|
||||
<div class="modal-footer whats-new-footer" data-modal-footer>
|
||||
<div class="whats-new-footer-left">
|
||||
<div class="whats-new-footer-progress">
|
||||
<div class="whats-new-footer-progress" x-show="$store.whatsNew.hasSlides()">
|
||||
<span class="whats-new-progress-label" x-text="$store.whatsNew.progressLabel()"></span>
|
||||
<div class="whats-new-progress-dots" role="tablist" aria-label="What's New slides">
|
||||
<template x-for="(slide, index) in $store.whatsNew.slides" :key="slide.id">
|
||||
|
|
@ -60,7 +67,7 @@
|
|||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<label class="whats-new-never-show">
|
||||
<label class="whats-new-never-show" x-show="$store.whatsNew.hasSlides()">
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="$store.whatsNew.neverShowAgain"
|
||||
|
|
@ -70,7 +77,14 @@
|
|||
</label>
|
||||
</div>
|
||||
<div class="whats-new-footer-actions">
|
||||
<button type="button" class="btn btn-cancel" @click="$store.whatsNew.skip()">Skip</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-cancel"
|
||||
x-show="$store.whatsNew.hasSlides()"
|
||||
@click="$store.whatsNew.skip()"
|
||||
>
|
||||
Skip
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-field"
|
||||
|
|
|
|||
1
plugins/_whats_new/webui/whats-new-slides.js
Normal file
1
plugins/_whats_new/webui/whats-new-slides.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
export const slides = [];
|
||||
|
|
@ -1,59 +1,18 @@
|
|||
import { createStore } from "/js/AlpineStore.js";
|
||||
import { closeModal } from "/js/modals.js";
|
||||
import { slides } from "/plugins/_whats_new/webui/whats-new-slides.js";
|
||||
|
||||
const ASSET_BASE = "/plugins/_whats_new/webui/assets";
|
||||
const NEVER_SHOW_STORAGE_KEY = "a0_whats_new_never_show";
|
||||
|
||||
const slides = [
|
||||
{
|
||||
id: "parallel-tools",
|
||||
eyebrow: "Parallel execution",
|
||||
title: "Parallel tool calls and subagents",
|
||||
summary:
|
||||
"Agent Zero can now split work across parallel tool and subagents calls and combine concurrent steps results.",
|
||||
mediaType: "video",
|
||||
media: `${ASSET_BASE}/parallel-subs.webm`,
|
||||
mediaLabel:
|
||||
"Four Agent Zero subagents working in parallel while the parent agent coordinates the result.",
|
||||
bullets: [
|
||||
"Launch coordinated subagents to explore separate paths at the same time.",
|
||||
"Run mixed batches together: search queries, code execution, file reads, writes, and more.",
|
||||
"Merge the results back into one answer without waiting through every call in sequence.",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "mcp-configuration",
|
||||
eyebrow: "MCP configuration",
|
||||
title: "Redesigned MCP configuration UI",
|
||||
summary:
|
||||
"Global Settings and Projects now share a cleaner MCP setup flow for command and Remote URL transports.",
|
||||
mediaType: "image",
|
||||
media: `${ASSET_BASE}/mcp-servers.png`,
|
||||
mediaLabel:
|
||||
"The redesigned MCP servers screen showing server cards, transport controls, and raw JSON mode.",
|
||||
bullets: [
|
||||
"Configure npx, uvx, or custom command servers with clearer fields.",
|
||||
"Connect Remote URL transports from the same accessible editor.",
|
||||
"Switch to Raw JSON when you want to paste or move configurations between clients.",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "skills-scanner",
|
||||
eyebrow: "Agent security",
|
||||
title: "Skills Scanner powered by Snyk Agent Scan",
|
||||
summary:
|
||||
"Scan your agent skills and MCP-connected surfaces for prompt injections and vulnerabilities.",
|
||||
mediaType: "image",
|
||||
media: `${ASSET_BASE}/skills-scanner.png`,
|
||||
mediaLabel:
|
||||
"The Skills Scanner screen showing Snyk Agent Scan controls and scan guidance.",
|
||||
bullets: [
|
||||
"Review skills with the same scanning flow you already use for plugins.",
|
||||
"Find prompt-injection risks and vulnerable instructions before they reach runtime.",
|
||||
"Catch risky skill instructions early, before they become part of an agent workflow.",
|
||||
],
|
||||
},
|
||||
];
|
||||
const emptySlide = {
|
||||
eyebrow: "What's New",
|
||||
title: "No new updates right now",
|
||||
summary: "New highlights will appear here when there are fresh Agent Zero updates.",
|
||||
mediaType: "none",
|
||||
media: "",
|
||||
mediaLabel: "No new updates right now.",
|
||||
bullets: [],
|
||||
};
|
||||
|
||||
function storageValue(key) {
|
||||
try {
|
||||
|
|
@ -109,7 +68,11 @@ export const store = createStore("whatsNew", {
|
|||
},
|
||||
|
||||
get currentSlide() {
|
||||
return this.slides[this.currentIndex] || this.slides[0];
|
||||
return this.slides[this.currentIndex] || emptySlide;
|
||||
},
|
||||
|
||||
hasSlides() {
|
||||
return this.slides.length > 0;
|
||||
},
|
||||
|
||||
isFirst() {
|
||||
|
|
@ -121,6 +84,7 @@ export const store = createStore("whatsNew", {
|
|||
},
|
||||
|
||||
progressLabel() {
|
||||
if (!this.hasSlides()) return "";
|
||||
return `${this.currentIndex + 1} of ${this.slides.length}`;
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,12 @@ PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
|||
WHATS_NEW_PLUGIN = PROJECT_ROOT / "plugins/_whats_new"
|
||||
|
||||
|
||||
def test_whats_new_modal_uses_showcase_assets_and_branded_footer():
|
||||
def test_whats_new_modal_handles_empty_showcase_state():
|
||||
html = (WHATS_NEW_PLUGIN / "webui/main.html").read_text(encoding="utf-8")
|
||||
store = (WHATS_NEW_PLUGIN / "webui/whats-new-store.js").read_text(encoding="utf-8")
|
||||
slide_data = (WHATS_NEW_PLUGIN / "webui/whats-new-slides.js").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
|
||||
assert "What's New in Agent Zero" in html
|
||||
assert "data-modal-footer" in html
|
||||
|
|
@ -16,25 +19,19 @@ def test_whats_new_modal_uses_showcase_assets_and_branded_footer():
|
|||
assert "type=\"checkbox\"" in html
|
||||
assert "Don't show automatically again" in html
|
||||
assert "/plugins/_whats_new/webui/whats-new-store.js" in html
|
||||
assert "/plugins/_whats_new/webui/assets" in store
|
||||
assert "/plugins/_whats_new/webui/whats-new-slides.js" in store
|
||||
assert "a0_whats_new_never_show" in store
|
||||
assert "No new updates right now" in store
|
||||
assert "hasSlides()" in html + store
|
||||
assert "export const slides = [];" in slide_data
|
||||
|
||||
for asset in ["parallel-subs.webm", "mcp-servers.png", "skills-scanner.png"]:
|
||||
assert asset in html + store
|
||||
assert (PROJECT_ROOT / "plugins/_whats_new/webui/assets" / asset).exists()
|
||||
|
||||
assert "Parallel tool calls and subagents" in store
|
||||
assert (
|
||||
"Agent Zero can now split work across parallel tool and subagents calls and combine concurrent steps results."
|
||||
in store
|
||||
)
|
||||
assert "Redesigned MCP configuration UI" in store
|
||||
assert "Skills Scanner powered by Snyk Agent Scan" in store
|
||||
assert "Remote URL transports" in store
|
||||
assert "Raw JSON" in store
|
||||
assert "prompt-injection risks" in store
|
||||
assert "Catch risky skill instructions early" in store
|
||||
assert "Include MCP servers in the same pass" not in store
|
||||
old_cards = html + store + slide_data
|
||||
assert "Parallel tool calls and subagents" not in old_cards
|
||||
assert "Redesigned MCP configuration UI" not in old_cards
|
||||
assert "Skills Scanner powered by Snyk Agent Scan" not in old_cards
|
||||
assert "parallel-subs.webm" not in old_cards
|
||||
assert "mcp-servers.png" not in old_cards
|
||||
assert "skills-scanner.png" not in old_cards
|
||||
|
||||
|
||||
def test_whats_new_legacy_modal_path_redirects_to_main_screen():
|
||||
|
|
@ -53,6 +50,8 @@ def test_whats_new_startup_trigger_is_version_gated_with_opt_out():
|
|||
assert "globalThis.gitinfo?.version" in content
|
||||
assert "a0_whats_new_seen_version" in content
|
||||
assert "a0_whats_new_never_show" in content
|
||||
assert "/plugins/_whats_new/webui/whats-new-slides.js" in content
|
||||
assert "slides.length" in content
|
||||
assert "/plugins/_whats_new/webui/main.html" in content
|
||||
assert "/plugins/_whats_new/webui/whats-new.html" in content
|
||||
assert "compareVersions" in content
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue