用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/ginlix-ai/LangAlpha --skill inline-widget命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Search X (Twitter) posts, pull user profiles, fetch specific tweets, and read reply threads for sentiment, news, and event research. Triggers on 'X', 'Twitter', 'tweets about', 'sentiment on', 'what are people saying about', 'historical tweets', or any request to read public X content.
Web scraping: scrape_page / scrape_pages MCP tools for fetching pages as markdown, HTML, or text (fast HTTP, browser rendering, anti-bot stealth), plus the direct Scrapling Python API for selectors, sessions, and spiders
Orchestrate parallel subagent pipelines from a JavaScript workflow script — fan out work across many items (tickers, filings, findings) then synthesize, or run a saved workflow by name. Unlocks the RunWorkflow tool.
基于 SOC 职业分类
正在显示 SKILL.md
| name | inline-widget |
| description | Inline HTML widgets: charts, dashboards, data tables rendered directly in the chat via ShowWidget |
Render interactive HTML/SVG widgets directly inside the chat conversation using ShowWidget. Widgets appear inline between text — no sandbox, no preview URL, no side panel. They run JavaScript, so lean into making them interactive and explorable where it helps — something the user can sort, filter, toggle, and hover over, not just a static picture.
Use interactive-dashboard instead if: User needs a multi-page web app, server-side data, live data refresh, or complex interactivity requiring React/FastAPI.
Read .agents/skills/ui-design/SKILL.md for design quality — its color discipline, chart restraint, and anti-slop principles apply here too. Its font pairings and type scale, though, are for full documents; a widget sits on the chat surface, so use the host-font typography rules below instead.
ShowWidget(html: str, title: str | None = None, data_files: list[str] | None = None)
html: Raw HTML fragment — no <!DOCTYPE>, <html>, <head>, or <body> tagstitle: Optional metadata (not displayed to user)data_files: Optional list of sandbox file paths to make available as window.__WIDGET_DATA__The HTML is rendered in a sandboxed iframe with:
cdnjs.cloudflare.com, cdn.jsdelivr.net, unpkg.com, esm.shsendPrompt('text'): global function to trigger follow-up chat messageswindow.__WIDGET_DATA__: dict of filename→content for files passed via data_filesfetch() / XMLHttpRequest to arbitrary URLs are blocked by CSP — only CDN domains (cdnjs, jsdelivr, unpkg, esm.sh) are allowed. Use data_files for sandbox files, or embed small data directly in HTMLThe widget sits directly on the chat surface inside a transparent iframe. Follow these rules for seamless integration:
The outermost HTML element must have:
background: transparent)<!-- CORRECT: transparent outer shell -->
<div>
<div style="background: var(--color-bg-card, #ffffff); border-radius: 8px; padding: 16px; ...">
...inner card content...
</div>
</div>
<!-- WRONG: styled outer wrapper — will be rejected -->
<div style="background: var(--color-bg-page); border: 1px solid ...; border-radius: 8px; padding: 20px;">
...content...
</div>
Inner cards, sections, and components should use CSS variables for styling, always in the fallback form:
/* Card */
background: var(--color-bg-card, #ffffff);
border: 0.5px solid var(--color-border-muted, #e4e1dc);
border-radius: 8px;
padding: 16px;
/* Metric card */
background: var(--color-bg-subtle, #f4f2ee);
border: 0.5px solid var(--color-border-muted, #e4e1dc);
border-radius: 8px;
In chat the variables are always injected, so the fallback never shows there — it is what renders when the widget is saved as a workspace .html file and previewed before theme injection or opened standalone. Use the light literals from the html-report skill's table.
position: fixed — breaks iframe auto-sizing (elements collapse to 0 height)position: relative for chart containersThese CSS variables are automatically injected and resolve correctly in both light and dark mode:
| Variable | Purpose |
|---|---|
--color-bg-page | Page background |
--color-bg-card | Card/panel background |
--color-bg-elevated | Elevated surface |
--color-bg-subtle | Subtle/muted background |
--color-bg-hover | Hover state background |
--color-text-primary | Primary text |
--color-text-secondary | Secondary/muted text |
--color-text-tertiary | Hint/label text |
--color-border-muted | Default border (use with 0.5px) |
--color-accent-primary | Brand/accent color |
--color-profit | Positive/gain (green) |
--color-loss | Negative/loss (red) |
--color-warning | Warning (amber) |
--color-info | Info (blue) |
--color-success | Success (green) |
Never hardcode colors like #333 or rgb(...) for text, backgrounds, or borders — they break in dark mode. Author every color as var(--color-x, #lightLiteral): the injected variable always wins in chat, and the fallback keeps the widget legible on its secondary surfaces. The only exception is chart canvas colors — Chart.js canvas cannot read CSS variables; resolve them via getComputedStyle with a literal fallback.
Load Chart.js from CDN and follow these rules:
<!-- Wrapper div with explicit height — REQUIRED -->
<div style="position: relative; height: 200px;">
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
// Read CSS variables for chart colors (canvas can't use var());
// the literal fallback covers the widget opened outside the chat surface.
var cs = getComputedStyle(document.documentElement);
function pick(name, fallback) { return cs.getPropertyValue(name).trim() || fallback; }
var accent = pick('--color-accent-primary', '#1f5fb4');
var border = pick('--color-border-muted', '#e4e1dc');
new Chart(document.getElementById('myChart'), {
type: 'line',
data: {
labels: [...],
datasets: [{
: [...],
: accent,
: accent + ,
: ,
:
}]
},
: {
: ,
: ,
: { : { : } },
: {
: { : { : border } },
: { : { : } }
}
}
});
Key rules:
responsive: true, maintainAspectRatio: falsewindow.Chart global)getComputedStyle with a literal fallback (pick()) for chart colors-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif)A widget runs JavaScript, so prefer something the user can poke at, not just read. When the data supports it, reach for:
It all runs client-side over the embedded data — never fetch() a non-CDN origin (CSP blocks it; use data_files for anything large). Keep a meaningful default state so the widget reads correctly before any interaction. Use sendPrompt() only when the next step genuinely belongs back in the chat (a new query, a deeper analysis) — handle exploration the widget can do itself in-place.
Call sendPrompt('text') from buttons to trigger a follow-up chat message:
<button onclick="sendPrompt('Show detailed revenue breakdown')"
style="padding: 8px 16px; background: var(--color-accent-primary); color: white;
border: none; border-radius: 6px; cursor: pointer;">
Revenue Details ↗
</button>
Add a ↗ arrow on buttons that call sendPrompt() to signal they trigger a chat action.
setInterval and requestAnimationFrame work normally for animations and live tickers:
setInterval(function() {
// Update prices, rotate data, animate
updateDisplay();
}, 3000);
Use data_files to load data from sandbox files instead of inlining everything in the HTML string. This is especially useful for larger datasets.
ShowWidget via data_fileswindow.__WIDGET_DATA__["filename"]# Step 1: Generate data
import json
data = {"labels": ["Q1", "Q2", "Q3"], "values": [100, 150, 200]}
with open("work/<task_name>/chart_data.json", "w") as f:
json.dump(data, f)
# Step 2: Agent calls ShowWidget with data_files
ShowWidget(
html='<div id="chart">...</div><script>var d = JSON.parse(__WIDGET_DATA__["chart_data.json"]); ...</script>',
data_files=["work/<task_name>/chart_data.json"]
)
// Text files (json, csv, txt, etc.) — returned as strings
var data = JSON.parse(window.__WIDGET_DATA__["chart_data.json"]);
var csvText = window.__WIDGET_DATA__["results.csv"];
// Binary files (png, jpg, etc.) — returned as data URLs
document.getElementById("img").src = window.__WIDGET_DATA__["chart.png"];
.json, .csv, .txt, .html, .xml, .svg, .md, .yaml, .yml, .tsv, .geojson, .topojson.png, .jpg, .jpeg, .gif, .webp, .icoTotal inline data is capped at 500KB across all files. Keep datasets concise — aggregate or sample large files before passing them.
The following will cause ShowWidget to reject your HTML with an error. Fix and retry:
| Pattern | Why blocked |
|---|---|
new ResizeObserver(...) | Host handles iframe sizing — your observer creates infinite resize loops |
parent.postMessage(...) | Use sendPrompt() instead — direct postMessage bypasses the bridge |
window.top.* / window.parent.* | Sandboxed iframe — parent access is blocked |
position: fixed | Breaks iframe auto-sizing |
| Background/border on outermost element | Breaks seamless integration with chat surface |
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 16px;">
<div style="background: var(--color-bg-subtle); padding: 14px 16px; border-radius: 8px; border: 0.5px solid var(--color-border-muted);">
<div style="font-size: 11px; color: var(--color-text-tertiary); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 6px;">Revenue</div>
<div style="font-size: 24px; font-weight: 500;">$2.4M</div>
<div style="font-size: 12px; color: var(--color-profit);">+12.5%</div>
</div>
<!-- more cards... -->
</div>
<table style="width: 100%; border-collapse: collapse; font-size: 14px;">
<thead>
<tr style="border-bottom: 0.5px solid var(--color-border-muted);">
<th style="text-align: left; padding: 8px; color: var(--color-text-secondary); font-weight: 500; font-size: 12px;">Symbol</th>
<th style="text-align: right; padding: 8px; color: var(--color-text-secondary); font-weight: 500; font-size: 12px;">Price</th>
</tr>
</thead>
<tbody>
<tr style="border-bottom: 0.5px solid var(--color-border-muted);">
<td style="padding: 8px; font-weight: 500;">AAPL</td>
<td style="text-align: right; padding: 8px;">$213.18</td>
</tr>
</tbody>
</table>
<div style="background: var(--color-bg-card); border-radius: 8px; border: 0.5px solid var(--color-border-muted); padding: 16px; margin-bottom: 16px;">
<div style="font-size: 16px; font-weight: 500; margin-bottom: 12px;">Performance</div>
<div style="position: relative; height: 200px;">
<canvas id="perfChart"></canvas>
</div>
</div>