test_agent / web /index.html
xusijie
add open storyline files
5c11d93
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta name="color-scheme" content="light dark" />
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)" />
<meta name="theme-color" content="#0b0b0c" media="(prefers-color-scheme: dark)" />
<title>OpenStoryline</title>
<link rel="icon" type="image/png" href="/static/logo.png">
<link rel="stylesheet" href="/static/style.css" />
<script defer src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js"></script>
</head>
<body class="sidebar-collapsed devbar-collapsed">
<!-- 左侧可收起侧边栏 -->
<aside id="sidebar" class="sidebar collapsed" aria-label="侧边栏">
<div class="sidebar-inner">
<!-- 顶部固定区:永远不被挤压 -->
<div class="sidebar-top">
<button id="sidebarToggle" class="sidebar-icon-btn" title="收起/展开侧边栏" aria-label="收起/展开侧边栏">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M4 7h16"></path>
<path d="M4 12h16"></path>
<path d="M4 17h16"></path>
</svg>
</button>
<button id="createDialogBtn" class="sidebar-action primary" title="创建新对话" aria-label="创建新对话">
<span class="sidebar-action-icon"></span>
<span class="sidebar-action-text">创建新对话</span>
</button>
</div>
<!-- 中间滚动区:长内容放这里 -->
<div class="sidebar-scroll" id="sidebarScroll" aria-label="侧边栏滚动区">
<div id="sidebarModel" class="sidebar-model" aria-label="对话模型选择">
<div class="sidebar-model-label">对话模型</div>
<select id="modelSelect" class="sidebar-model-select" aria-label="选择对话模型" data-os-persist="sidebar.model"></select>
</div>
<!-- 自定义模型配置(仅当选择“使用自定义模型”时显示) -->
<div id="customModelBox" class="sidebar-panel hidden" aria-label="自定义模型配置">
<div class="sidebar-panel-title">自定义模型</div>
<div class="sidebar-subtitle">LLM(对话/文案)</div>
<input id="customLlmModel" class="sidebar-input"
data-os-persist="sidebar.custom.llm.model"
placeholder="模型名称,例如 deepseek-chat / gpt-4o-mini" />
<input id="customLlmBaseUrl" class="sidebar-input"
data-os-persist="sidebar.custom.llm.base_url"
placeholder="Base URL,例如 https://api.xxx.com/v1" />
<input id="customLlmApiKey" class="sidebar-input" type="password"
data-os-persist="sidebar.custom.llm.api_key"
placeholder="API Key" autocomplete="off" />
<div class="sidebar-divider"></div>
<div class="sidebar-subtitle">VLM(素材理解)</div>
<input id="customVlmModel" class="sidebar-input"
data-os-persist="sidebar.custom.vlm.model"
placeholder="模型名称,例如 qwen-vl-plus / gpt-4o" />
<input id="customVlmBaseUrl" class="sidebar-input"
data-os-persist="sidebar.custom.vlm.base_url"
placeholder="Base URL,例如 https://api.xxx.com/v1" />
<input id="customVlmApiKey" class="sidebar-input" type="password"
data-os-persist="sidebar.custom.vlm.api_key"
placeholder="API Key" autocomplete="off" />
<div class="sidebar-hint">
提示:API Key 仅用于本会话的服务端调用;页面与 Tool trace 会自动脱敏,不会显示明文。
</div>
</div>
<!-- TTS 配置 -->
<div id="ttsBox" class="sidebar-panel" aria-label="TTS 服务配置">
<div class="sidebar-panel-title">TTS 配置</div>
<select id="ttsVendorSelect"
class="sidebar-model-select"
aria-label="选择 TTS 服务厂家"
data-os-persist="sidebar.tts.vendor">
<option value="">不配置</option>
<option value="bytedance">字节跳动</option>
</select>
<div id="ttsBytedanceFields" class="sidebar-tts-fields hidden" aria-label="字节跳动 TTS 参数">
<input id="ttsBytedanceUid" class="sidebar-input"
data-os-persist="sidebar.tts.bytedance.uid"
placeholder="uid" />
<input id="ttsBytedanceAppId" class="sidebar-input"
data-os-persist="sidebar.tts.bytedance.appid"
placeholder="appid" />
<input id="ttsBytedanceAccessToken" class="sidebar-input" type="password"
data-os-persist="sidebar.tts.bytedance.access_token"
placeholder="access_token" autocomplete="off" />
</div>
</div>
</div>
</div>
</aside>
<!-- 主内容区(用于给 sidebar 留出空间) -->
<div class="main">
<!-- 保留原有 topbar 结构(不破坏 JS),但 CSS 默认隐藏 -->
<header class="topbar">
<div class="brand">OpenStoryline <span class="ver">v1.0.0</span></div>
</header>
<!-- 对话区 -->
<main id="chat" class="chat" aria-live="polite"></main>
<!-- 空白页标题(ChatGPT 风格):仅在 #chat 为空时显示(纯 CSS 控制) -->
<section id="hero" class="hero" aria-hidden="true">
<h1 class="hero-title">🎬 你好,创作者!</h1>
</section>
<!-- Toast -->
<div id="toast" class="toast hidden" role="status" aria-live="polite"></div>
<!-- Scroll to bottom -->
<button id="scrollToBottomBtn" class="scroll-bottom hidden" aria-label="滚动到底部" title="滚动到底部">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 5v14"></path>
<path d="M7 14l5 5 5-5"></path>
</svg>
</button>
<!-- 输入区 -->
<footer class="composer" role="region" aria-label="消息输入区">
<input id="fileInput" class="file-input" type="file" multiple />
<div id="pendingBar" class="pending hidden" aria-label="待发送素材">
<div class="asset-bar-title">待发送素材</div>
<div id="pendingRow" class="asset-row"></div>
</div>
<div class="composer-top">
<textarea
id="promptInput"
class="prompt"
placeholder="提出任何剪辑需求(Enter 发送,shift + Enter 换行)"
></textarea>
</div>
<div class="composer-actions">
<button id="uploadBtn" class="icon-btn" title="上传素材" aria-label="上传素材">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 5v14M5 12h14"></path>
</svg>
</button>
<div class="composer-actions-spacer"></div>
<button id="sendBtn" class="send-btn" aria-label="发送">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 19V6"></path>
<path d="M7 11l5-5 5 5"></path>
</svg>
</button>
</div>
</footer>
<!-- 预览 Modal -->
<div id="modal" class="modal hidden" aria-hidden="true">
<div class="modal-backdrop" id="modalBackdrop"></div>
<div class="modal-body" role="dialog" aria-modal="true">
<button class="modal-close" id="modalClose" aria-label="关闭">×</button>
<div class="modal-content" id="modalContent"></div>
</div>
</div>
<!-- Tool UI 配置:必须在 app.js 之前 -->
<script>
window.OPENSTORYLINE_TOOL_UI = {
labels: {
"assets_index": "读取素材",
"split_shots": "镜头切分",
"filter_clips": "筛选片段",
"understand_clips": "理解素材",
"group_clips": "片段分组",
"generate_script": "生成文案",
"generate_voiceover": "生成配音",
"select_bgm": "推荐背景音乐",
"plan_timeline": "组织时间线",
"render_video": "渲染视频",
"split_shots_pro": "镜头切分—pro",
"filter_clips_pro": "筛选片段—pro",
"understand_clips_pro": "理解素材—pro",
"group_clips_pro": "片段分组—pro",
"generate_script_pro": "生成文案—pro",
"elementrec_texts_pro": "推荐花字—pro",
"elementrec_title_pro": "推荐标题—pro",
"elementrec_global_effects_pro": "推荐全局特效—pro",
"elementrec_local_effects_pro": "推荐局部特效—pro",
"elementrec_close_effects_pro": "推荐闭幕特效—pro",
"elementrec_filter_pro": "推荐滤镜—pro",
"elementrec_transition_pro": "推荐转场—pro",
"elementrec_text_animation_pro": "推荐花字动画—pro",
"elementrec_title_clip_pro": "推荐片头—pro",
"elementrec_tts_pro": "推荐配音音色—pro",
"tts_service_pro": "生成配音—pro",
"music_rec_service_pro": "推荐背景音乐—pro",
"timeline_pro": "组织时间线—pro",
"render_template_pro": "渲染视频—pro",
"read_node_history": "读取详细结果",
},
estimates_ms: {
"storyline.assets_index": 1000
},
default_estimate_ms: 5000,
tick_ms: 120,
cap_running_progress: 0.99,
hide_raw_tool_name: true,
show_raw_tool_name_in_dev: true
};
</script>
<script type="module" src="/static/app.js"></script>
</div>
<!-- 右侧开发者侧边栏(仅 developer_mode=true 时由 JS 显示) -->
<aside id="devbar" class="devbar hidden collapsed" aria-label="开发者侧边栏">
<div class="devbar-inner">
<button id="devbarToggle" class="devbar-icon-btn" title="收起/展开开发者侧边栏" aria-label="收起/展开开发者侧边栏">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M15 6l-6 6 6 6"></path>
</svg>
</button>
<div class="devbar-title">Tool summary trace</div>
<div class="devbar-sid" id="sidebarSid"></div>
<div id="devLog" class="devbar-log" aria-label="工具 summary 输出">
<!-- JS 追加 summary -->
</div>
</div>
</aside>
</body>
</html>