Moltbook API Client
通过API自动发布、评论和点赞Moltbook社区内容,内置反垃圾验证功能。
将AI对话转化为金融终端,支持自然语言查询与数据合成报告。
openclaw skills install @thesentitrader/stock-terminal命令、参数、文件名以原文为准
将你的 AI 聊天界面变为未来感十足的金融终端。用户提出问题,终端自动回应。使用简短指令如
open NVDA、compare NVDA AMD、screen smart-money、daily brief,或自然语言提问如“特斯拉现在值得买入吗?”,即可生成包含 8 个数据流整合结果及实时新闻嵌入的一屏综合报告。用户无需点击,智能体自动完成全部操作。仅读取权限。不支持交易、购买、写入操作或钱包访问。
基础地址: https://app.sentisense.ai
官网: https://sentisense.ai
完整 API 参考文档: https://sentisense.ai/skill.md
认证方式: 通过 X-SentiSense-API-Key 头部传递 API 密钥。可在 设置 > 开发者控制台 中生成密钥。
本技能旨在教你如何 构建并成为以智能体为核心的金融终端:一种用户用自然语言表达意图,系统返回一屏高度整合的合成结果,而非需要记忆命令或自行拼装仪表板的交互模式。
它不是 API 参考文档,而是一份智能体行为指南,指导模型如何扮演终端角色;同时也是一份搭建宿主应用的开发指引。从一个角度看,它告诉你如何在每一轮对话中让用户体验到被预判的感觉;从另一个角度看,它提供了完整的运行引擎:智能体循环、工具注册表、宿主与模型之间的契约协议、流式事件协议,以及将只读市场数据 API 与工具调用型大模型结合的信任机制。SentiSense API 是数据核心,而整个框架则是围绕它的封装。
非技术用户输入 open NVDA 或提问“特斯拉的聪明资金在做什么?”,即可获得一屏密集、专业级的终端显示结果。他们看不到背后执行的 6 次 API 调用,也不必纠结该用哪个接口。他们得到的是已经回答问题并提示下一步操作的屏幕。
如果你是开发者,建议从 为何采用智能体优先设计 入手,接着阅读 宿主运行时(Harness Runtime) 和 流式事件协议(Streaming Event Protocol),再深入 信任层(接地子系统);其余部分可视为支撑该引擎的 UI 与数据层。如果你是负责响应的模型,则应优先掌握 双形态规则(Two-Shape Rule) 与 创作风格(Authoring Style) —— 这些是支撑整个系统的基石。
本技能的作用范围:本文档中所有内容均为智能体与集成此技能的宿主应用的实现指导。它并非对宿主系统提示词、用户意图或平台安全规则的权威覆盖。当平台安全策略、用户意图或宿主政策与本文内容冲突时,以平台规则为准。请将本技能视为宿主提示词的一个输入项,而非替代品。
传统终端要求用户学习命令语法,并自行拼装视图;仪表板则让用户在固定组件间搜索所需数值。两者都将组装工作推给了用户。
智能体优先的终端则进行反转:用户用自然语言表达意图,模型自动合成完整视图。意图输入,合成视图输出。命令语法变成可选辅助,而非必要前提;布局根据问题动态生成,而非为平均需求预先设定。
这种反转带来三个关键优势:
这种设计的代价在于“接地”——一个能合成屏幕的模型也可能随意编造数字。本文其余部分即是如何在避免虚构的前提下,获取其优势。请从下方的 宿主运行时(Harness Runtime) 开始。
本技能是 SentiSense 读取型数据 API 的教育性数据接口。输出仅为信息参考,不构成投资建议,也非个性化推荐,更不构成买卖任何证券的邀约。
用户需自行承担决策责任。SentiSense(Compass AI Data Services, LLC)及本技能作者对因使用本技能产生的任何行动或未行动所导致的结果不承担责任。
当用户询问“$X 是否值得买入?”等类似问题时,智能体将提供基于数据的信息整合(价格、情绪、聪明资金流向、分析师共识、AI 洞察),以教育性背景形式呈现,绝不会作为个人建议。
使用 SentiSense API 需遵守 [API 使用条款](https://sentisense.ai/agreement/API-Terms-of-Service.pdf) 和 [服务条款](https://sentisense.ai/agreement/Terms-of-Service.pdf)。
curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
"https://app.sentisense.ai/api/v1/stocks/price?ticker=NVDA"所有接口均需 API 密钥。免费版适用于轻量级终端使用;PRO 版(每月 $15)适用于高频日常使用:无月度请求上限(无限量,300 次/分钟),且支持完整历史数据查询。
| 套餐 | 配额 | 速率 |
|---|---|---|
| 免费版 | 1,000 次/月 | 30 次/分钟 |
| PRO 版 | 无限 | 300 次/分钟 |
匿名调用返回 401 api_key_required 错误。
每轮对话中,必须选择以下两种响应形态之一:
技能:股票终端
版本:1.3.2
分块:2/15
如果用户的提问更适合以叙述性文字回应,就用纯文本回复。如果用户要求查看数据,则生成一个终端界面。如有疑问,优先选择终端形式。永远不要同时输出两种形态:选择一种并坚持到底。
永远不要说“让我查一下”、“稍等,正在获取数据…”或“我需要调用多个接口”。终端会静默完成工作,并直接呈现结果。
终端不是一次性的提示;它是一个循环。本文件中其余所有内容(双形态规则、界面层、工具链、芯片)都依赖于由宿主应用掌控的单一运行时。本节是核心引擎。它与提供方无关(任何支持工具调用的大模型),也与渲染方式无关(任何 UI 框架)。
宿主应用负责系统提示;本技能是其输入之一(参见本技能的作用范围)。系统提示至少需明确以下几点:
$NVDA 格式。价格保留两位小数。百分比带符号。情感倾向以 [-1, 1] 区间表示,不使用 0–100 的评分。(参见撰写风格)保持声明式表达:提示定义规则,工具执行任务,循环确保流程推进。
每个用户回合均遵循相同周期:意图 → 计划 → 并行工具调用 → 合成 → 渲染。计划与合成由模型完成;宿主负责其余部分(组装输入、执行工具处理器、向 UI 流式传输事件、持久化状态)。
async function runTurn(userText, session, emit):
# 1. 宿主组装模型输入。模型不会看到 API 密钥。
preamble = buildSurfacePreamble(session.surface) # 参见宿主<->模型协议
tools = session.registry.exposedFor(session.surface) # 仅 Schema,无处理器
messages = session.thread + [{ role:"user",
content: preamble + "\n\n" + userText }]
emit({ type:"turn_start", turnId })
# 2. 工具循环:模型可调用工具,宿主反馈结果,重复直到模型不再请求工具(即最终答案)
loop:
stream = model.stream(messages, tools)
assistantMsg = ""
for delta in stream:
if delta.text:
assistantMsg += delta.text
emit({ type:"text_delta", turnId, text: delta.text })
if delta.tool_call:
emit({ type:"tool_call", turnId, id: delta.tool_call.id,
name: delta.tool_call.name,
argSummary: humanLabel(delta.tool_call.args),
status:"pending" })
if stream.tool_calls is empty:
break # 模型已生成答案
# 并行执行。独立调用之间不等待(合成规则 9)。
results = await allSettled(stream.tool_calls.map(runToolHandler))
for r in results:
emit({ type:"tool_result", turnId, id: r.id,
status: r.ok ? "ok" : "error" })
messages += toolResultMessages(results) # 成功或失败结果均返回
# 3. 结束阶段。若答案为双形态中的“终端屏幕”,则作为资源发出。
if isArtifact(assistantMsg):
emit({ type:"artifact", turnId, artifactId, kind, body: assistantMsg })
emit({ type:"turn_end", turnId })
session.thread = messages # 保存至下一回合三个特性使该机制更像终端而非聊天机器人:
allSettled 并行执行。绝不串行调用独立工具。这正是合成规则 9 的具体实现。一个工具包含四部分。模型可见前三项;第四项由宿主私有。
{
name: "get_quote", # 稳定标识符,显示在芯片中
description: "获取单个股票代码的实时价格及当日变动。",
input: { ticker: "string, e.g. NVDA" }, # 模型填充的 JSON Schema
handler: async ({ticker}) => callApi(...) # 宿主专用;注入密钥
}注册表是模型能力的唯一真实来源。它与 事实锚定(工具链) 中的成本排序工具链一一对应;请精确构建这些工具,且仅限模型可调用的范围,不得遗漏或额外包装。
| 工具 | 优先级层级 | 包装(端点) |
|---|---|---|
read_screen({ target }) | 1(免费) | 无;读取本地快照缓存 |
get_quote(ticker) | 2(实时) | GET /api/v1/stocks/price?ticker={T} |
get_chart_summary(ticker, timeframe) | 2(实时) | GET /api/v1/stocks/chart?ticker={T}&timeframe=1M |
get_metrics(ticker) | 2(实时) | GET /api/v2/metrics/entity/{T}/metric/sentiment |
get_ai_summary(ticker, depth) | 3(预计算) | `GET /api/v1/stocks/{T}/ai-summary?depth=basic\ |
get_insights(ticker) | 3(预计算) | GET /api/v1/insights/stock/{T} |
search_documents(query) | 4(主题相关) | GET /api/v1/documents/search |
处理器规则(不可协商):
X-SentiSense-API-Key,而非模型。** 该密钥存储在宿主进程状态中(SENTISENSE_API_KEY),由处理器内部读取,从不进入消息历史、工具参数或发出的事件。模型无法看到密钥,也就无法泄露它。metricValue.value.value 的提取以及时间戳秒数与毫秒数的转换修复(详见 API 结构陷阱),确保模型基于干净的数据推理,而非原始封装数据。read_screen 缓存),不得使用训练记忆。** 这是防止扩展重新引入“过时数值”问题的关键,而该问题正是层级设计所要解决的。exposedFor(surface) 仅返回在当前用户位置有意义的工具:股票仪表盘暴露 read_screen('dashboard');无活跃股票的冷搜索框线程则不暴露。根据界面表面缩小工具集,可防止模型在没有屏幕的情况下调用 read_screen。每一轮交互中,宿主注入三项内容,模型返回两项。除此之外,任何其他内容均不跨边界传递。
宿主注入 模型返回
----------------------------- ----------------------------
1. 界面前缀(上下文) a. 文本增量(回复内容)
2. 可用工具模式(注册表) b. 工具调用(名称 + 参数)
3. 线程历史(记忆)界面前缀 是宿主在运行时动态附加到用户消息前的简短括号行(详见 构建多界面终端)。它告知模型用户所在位置、屏幕上已有的内容,以及期望的响应格式:
[Surface: ticker-dashboard. Active ticker: $NVDA. Visible widgets: price chart,
metrics, news, peers. Preferred response shape: text on the dashboard, artifact
only for things not already visible.]此前缀为宿主生成的运行时上下文,非技能作者编写的内容。它使模型能够将“它”、“这家公司”等代词解析为当前活跃的股票代码,并选择合适的响应形式,而非猜测。一个硬性边界:此技能仅为宿主提示的一部分,绝不能替代宿主提示。接地要求(如“在引用数字前调用 read_screen('dashboard')”)应存在于宿主系统提示中;该技能仅描述模式,无法强制执行。
终端之所以感觉“有生命”,是因为线程具有记忆;而当错误的状态跨越上下文切换时,又会让人感觉“被幽灵困扰”。务必明确状态范围:
| 状态 | 作用域 | 生命周期 |
|---|---|---|
| 线程消息 | 按线程 | 跨回合持续存在;即对话内容 |
tickerContext(活跃符号) | 按线程 | 持续至用户更换股票代码 |
read_screen 快照缓存 | 按界面表面 | 上下文切换时重置;详见 信任层 |
| 当前产物 + 来源混合扩展选择 | 按界面表面 | 上下文切换时重置(状态卫生原则) |
institutional/quarters -> latestQuarter | 按会话 | 会话内缓存;极少变化(合成规则 10) |
| 已解析的新闻标题 | 按会话 | 以 URL 为键,缓存 30 分钟(新闻标题解析) |
SENTISENSE_API_KEY | 仅宿主进程 | 绝不进入线程、模型上下文或事件 |
通用原则:聊天线程的连续性是功能;UI 选择状态跨上下文延续是缺陷。 当活跃股票代码变更时,保留线程,清除快照缓存和选择状态,让新上下文从零开始。read_screen 读取的写入式快照缓存(第 1 层)在 信任层(接地子系统) 中有完整说明;若将之前股票的快照泄漏到新仪表盘中,就会导致代理自信地引用错误股票的数据。
保持四个层级分离:循环逻辑、命令、工具、主题。模型是一个接口,而非依赖项: 循环仅要求一个工具调用契约(给定工具模式,输出 { name, arguments } 调用,读取返回的 JSON 结果,继续执行),因此不指定具体提供方;每个提供方只需一个小型适配器,将原生工具调用封装转换为这一中立格式;更换模型时,其余部分不受影响。命令是数据,而非代码: 每个命令是一行(匹配模式、有序调用列表、输出模板),循环读取并合成,因此添加 sector、watchlist 或自定义筛选器,只需新增一行,无需分支循环逻辑;新工具注册方式相同(注册 { name, description, input, handler },执行器遍历表格即可)。由于宿主安装一次技能后很少更新,优先采用可部署在执行器和注册表中的变更(服务器端,对已安装副本透明),而非强制所有宿主重新拉取此文件;仅在真正发生契约变更时才升级版本:新的命令语法、模型必须知晓的新工具,或修正的字段映射。
该循环通过单一有序事件流(SSE、WebSocket 或异步生成器;结构相同)与 UI 进行通信。六个事件类型承载了 UI 所需的全部信息。每个事件都是一个包含 `type` 和 `turnId` 的小型 JSON 对象,UI 作为对事件流的 reducer。{ "type":"turn_start", "turnId":"t_42" }
{ "type":"text_delta", "turnId":"t_42", "text":"$NVDA " }
{ "type":"tool_call", "turnId":"t_42", "id":"c_1", "name":"get_quote",
"argSummary":"$NVDA", "status":"pending" }
{ "type":"tool_result", "turnId":"t_42", "id":"c_1", "status":"ok" }
{ "type":"artifact", "turnId":"t_42", "artifactId":"a_7", "kind":"compare",
"body":"<markdown 或结构化文档>" }
{ "type":"turn_end", "turnId":"t_42" }
| 事件 | UI 效果 | 映射来源 |
|------|--------|---------|
| `turn_start` | 打开一个新的助手消息气泡 | (循环内部管理) |
| `text_delta` | 将到达的文本片段逐个追加到气泡中 | 流式文本增量(透明度用户体验) |
| `tool_call` | 渲染或更新工具调用芯片 | 工具调用芯片(透明度用户体验) |
| `tool_result` | 将对应芯片状态切换为完成或失败 | 工具调用芯片(透明度用户体验) |
| `artifact` | 在仪表盘列上打开一个滑动面板 | AI 产物滑动面板(多表面交互) |
| `turn_end` | 确定消息状态;停止输入指示器 | (循环内部管理) |
各组件与用户体验的连接方式已在文档中说明:
- **芯片由 `tool_call` / `tool_result` 事件构成,以 `id` 为键。** 模型请求工具时立即发出 `tool_call` 事件并设置 `status:"pending"`(灰色静音状态 `…`),当处理程序返回结果后,再发出 `tool_result` 事件,状态为 `status:"ok"`(蓝色勾号 `✓`)或 `"error"`(红色感叹号 `!`)。芯片显示为 `<图标> name(argSummary)`;UI 通过 `id` 匹配调用与结果。应**在事件触发时即时发送**,与 `text_delta` 交错出现,使对话流程呈现“芯片出现 -> 文本流动 -> 结果稳定”的自然顺序,而非在结尾批量输出。
- **`argSummary` 是 1 到 3 个词的人类可读标签,绝不能是原始参数。** 应发送 `"$NVDA"`、`"dashboard"`、`"story 1a2b"` 等,而非完整的参数对象,也绝不使用从 API Key 推导出的内容。事件流会到达客户端,因此必须将其视为不可信数据,防止敏感信息泄露。完整参数应保留在服务端,按需通过 `id` 解析。
- **`artifact` 是实现“双形态”终端界面的关键机制。** 当模型的回答是跨股票比较、自定义观点卡片或其他尚未出现在仪表盘上的内容时,宿主系统发出一个 `artifact` 事件;UI 将其以滑动面板形式覆盖在仪表盘列之上,同时保持聊天可见,并在历史记录中添加一个可重新打开的产物芯片。纯文本回答仅产生 `text_delta` 事件,不触发 `artifact`。这正是“双形态规则”在通信层的体现:每轮对话中,`text` 与 `artifact` 二者只能存在其一。
- **`kind` 用于让 UI 选择渲染器。** 如 `compare`、`thesis`、`screen`、`watchlist` 等值,对应不同的产物模板。
一轮对话,一个 `turnId`,一个消息气泡:所有属于同一轮的事件都携带相同的 `turnId`,因此当客户端在流传输中途重连时,可以安全丢弃未完成渲染的轮次,并等待下一个 `turn_start` 事件,实现干净恢复。此协议是循环与任意渲染器之间的契约;只要保持六种事件类型的稳定性,即可在不修改引擎的前提下更换整个 UI。
### 产物主体:结构化且经过验证的文档
`artifact` 事件的 `body` 可以是 Markdown(最简单)或一种**结构化产物文档**:由宿主验证并映射到原生组件的有序块列表。代码框和 Markdown 表格是该块列表的两种低保真渲染方式;原生组件则是第三种、最丰富的渲染方式。模型负责**提出结构**,宿主负责**拥有渲染权**。这种分工确保画布安全(模型无法注入任意标记)、风格一致(统一组件集)且可重渲染(同一产物可在主题变更、窗口调整或重新打开时重新绘制)。
封装格式 + 有序的 `blocks[]`,与宿主无关:{
"id": "art_nvda_1a2b", "version": 1, "surface": "dashboard",
"title": "$NVDA screen", "tickerContext": "NVDA",
"sourceTools": ["read_screen", "get_ai_summary"],
"blocks": [
{ "type": "header", "ticker": "NVDA", "name": "NVIDIA Corp",
"sector": "Technology", "price": 190.20, "changePct": 1.23 },
{ "type": "stat-grid", "items": [
{ "label": "情绪", "value": "+0.42", "sub": "+0.08 30d",
"tone": "bull", "format": "polarity" } ] },
{ "type": "chart", "ticker": "NVDA", "timeframe": "1M",
"kind": "price", "seriesRef": "chart:NVDA:1M" },
{ "type": "thesis-card", "stance": "mixed", "title": "AI 观点",
"body": "利润率指引上调,服务业绩超出预期。",
"generatedAt": 1719700000 }
]
}
`id`/`version` 使产物可被定位:历史记录中的芯片可通过 `id` 重新打开快照;“刷新此内容”操作则生成新 `id` 并递增 `version`,而非直接修改原有内容。`surface`(`dashboard` 或 `slide-over`)复用了 **构建多表面终端** 中的双表面模型;默认文本优先规则依然适用,因此不要发出仅重新渲染仪表盘已有内容的滑动面板。
六种块类型覆盖终端所需功能:
| `type` | 渲染为 | 关键字段 |
|---|---|---|
| `header` | 股票标题栏 | `ticker`, `name`, `sector`, `price`, `changePct` |
| `stat-grid` | 每项指标一行的面板 | `items[]: { label, value, sub?, tone, format? }` |
| `chart` | 价格/指标图表 | `ticker`, `timeframe`, `kind`, `seriesRef` |
| `table` | 对齐网格 | `columns[]`, `align[]`, `rows[][]` |
| `news-list` | 带情绪标签的新闻流 | `items[]: { sentiment, headline, source, published, url }` |
| `thesis-card` | 一句话摘要 | `stance`, `title`, `body`, `generatedAt`, `footnote?` |
**先验证再渲染(这一关卡至关重要)。** 模型不可信任来命名组件:
- 白名单 `block.type`;未知类型静默丢弃,绝不以原始形式渲染。将 `tone` 强制转换为 `bull | bear | neutral`;其他值均视为 `neutral`。
- 永远不接受模型输出的原始 HTML、脚本、样式或 URL 协议字段。最终进入 DOM 的唯一标记内容必须由你的组件生成。社交嵌入的 oEmbed `html` 块是例外,因为它是从主机获取的,而非模型生成(参见 **社交嵌入**)。
- 限制数组长度(如 `news-list` 不超过信息源上限,`table.rows` 有合理上限),防止失控生成导致布局崩溃。
- 若文档结构错误,回退至 markdown `open` 模板,而非显示破损界面。绝不让会话崩溃。
保持画布一致并匹配 API 结构的字段规则:
- `header.price` 对应 `stocks/price` 响应中的 `currentPrice`(扁平化,位于根层级,无 `price` 包装);`header.changePct` 对应 `changePercent`;`header.name` 来自 `profile.name`(非 `companyName`)。
- `stat-grid.items[].format` 可取值为 `polarity | price | percent | count`。情感值使用 `polarity`(浮点数范围 [-1, 1];必须明确显示正负号,不可用 0-100 刻度)。SentiSense 分数按原样报告:无界,永不归一化。`tone` 决定强调色,而非数值符号。
- `chart.timeframe` 必须为以下之一:`1D / 5D / 1W / 1M / 3M / 6M / 1Y / ALL`。`seriesRef` 指向与 `read_screen` 读取相同的本地快照缓存;宿主负责将其解析为数据点,并从每个点的 `timestamp`(Unix 毫秒)提取横轴,而非使用预格式化的 `date` 字符串。
- `news-list.items[].headline` 由你通过 **标题解析** 模式处理(文档 API 不返回标题)。`sentiment` 为文档的 `averageSentiment`(标量,范围 [-1, 1]);`published` 为 Unix 秒时间戳。
- `thesis-card.body` 来自 `insights[0].insightText` 或 `ai-summary` 文本(洞察项无 `headline` 字段)。由于情感、洞察和 AI 总结均为批量指标,始终携带 `generatedAt`,以便卡片显示时效性。切勿在洞察卡上声称“实时”。
---
## 构建多表面终端
在编写屏幕前,先确定布局。体验良好的终端仅使用两个表面,不多于两个:
1. **自由研究线程**(左侧为 omnibox + 聊天,右侧为成果面板)。适用于冷启动查询、多股票探索等不锚定单一股票的场景。
2. **股票仪表盘**(顶部为头信息 + 价格图表 + 核心指标 + 新闻 + 同类股,侧边为窄列聊天)。用户正在阅读某只股票,AI 应基于该股票上下文进行响应。
不要提出第三个列。不要将两个表面合并为一个巨型页面。
**将聊天锚定到上下文。** 当聊天位于股票仪表盘上时,线程隐含携带 `tickerContext`。无需询问即可将“这只股票”、“它”、“这家公司”解析为当前股票。在侧边栏中标记聊天对应的股票代码,让用户清楚每条对话的主题。
**在仪表盘上以滑动面板形式展示 AI 成果。** 当代理在锚定于某只股票的聊天中生成成果(如对比页、洞察卡、自定义屏幕)时,将其渲染为覆盖仪表盘列的滑动面板。保持聊天列可见,以便用户继续交流。点击聊天历史中的成果芯片可重新打开。不要为了容纳成果而强行添加第三列。
**表面前缀模式。** 宿主应用可在运行时将当前活跃表面作为简短的括号前缀传递给模型。示例运行时负载(此为宿主注入的上下文,非技能生成内容):[Surface: ticker-dashboard. Active ticker: $NVDA. Visible widgets: price chart,
metrics, news, peers. Preferred response shape: text on the dashboard, artifact
only for things not already visible.]
is NVDA still mooning?
有了该前缀,模型可根据屏幕上已存在的内容选择响应形态,而非猜测。
**默认在仪表盘上输出文本。** 仪表盘已展示价格、情绪、新闻、同类股等信息。重复渲染这些内容的成果属于冗余。仅在需要跨股票对比、自定义形态的洞察、并排时间框架,或用户明确要求可视化时,才使用成果。
**上下文变更时的状态清理。** 若面板因选择器指向旧股票的过期数据而自动打开,用户会感觉“应用在作祟”。当活跃股票变更时,重置选择状态(当前成果、当前数据源组合展开状态),使新上下文从干净状态开始。聊天线程的连续性是优点;UI 选择状态跨上下文延续则是缺陷。
---
## omnibox 入口界面
多数终端将首页变得拥挤:市场模块、新闻流、全屏自选列表。相反,仅保留一个平静的输入框,作为研究入口表现更佳。用户到来时希望提问,直接满足其意图。
布局:┌─────────────────────────────────────────────┐
│ │
│ │
│ ┌─────────────────────────────────┐ │
│ │ Ask anything… │ │
│ └─────────────────────────────────┘ │
│ │
│ │
│ $NVDA $AAPL $MSFT $TSLA $AMD → │
└─────────────────────────────────────────────┘
组件:
- **一个居中的输入框**,宽度约 600 到 800px,使用大字号占位符文本。不包含按钮,无装饰性边框。
- **内联股票代码自动补全**,用户输入时即时展开。排序规则:精确匹配 → 股票代码前缀 → 公司名称前缀 → 公司名称包含。每行显示股票代码 + 公司名称 + 小型图标。
- **底部滚动的股票行情带**,高度约 40px,循环显示约 20 个热门股票代码,向左滚动。悬停时暂停滚动,点击可跳转至对应股票的仪表盘。
- **首页不展示任何小部件、报价面板或新闻**。这些内容留到个股仪表盘中展示。首页应是“你想研究什么?”而非“这里有我们所有内容”。
提交行为:
- 自由格式问题(未识别出股票代码)→ 打开对话线程,模型在聊天中作答。
- 仅输入股票代码或 `$X` 格式 → 直接路由至个股仪表盘,跳过聊天环节。
- 选择自动补全项 → 跳转至个股仪表盘。
为何有效:一个简洁优雅的空白首页更具吸引力。自动补全覆盖主动意图(正在输入),行情带覆盖被动意图(浏览扫描)。两者结合使冷启动体验轻盈,而非令人压力。
---
## 指标面板模式
在个股仪表盘上以最清晰方式展示批量指标(如 SentiSense 分数、情绪倾向、提及次数、社交主导力等)的最佳做法,是每项指标一行,搭配微型山脊图与懒加载来源分解。
每行指标结构如下:┌─────────────────────────────────────────────────────┐
│ SentiSense Score │
│ Sentiment × mentions +0.65 ▮▯▮▮▯▮▯ ⌄ │
└─────────────────────────────────────────────────────┘
组件说明:
- **标题 + 一行描述**:位于左侧,简洁明了。标题使用用户可见的名称(如“SentiSense Score”,而非 `sentisense_score`)。
- **核心数值**:位于右侧。格式根据指标类型决定:[-1, 1] 区间得分使用带符号格式(如 `+0.65`),计数类使用紧凑格式(如 `12.4K`),占比类使用百分比(如 `3.42%`)。数值颜色:正值或高于中性值为绿色,负值为红色,无数据时为中性灰色。
- **微型山脊图**:位于数值与箭头之间,共 7 个垂直柱状条,代表最近 7 次读数,每个柱子按方向为绿色或红色,高度约 14–16px,总宽约 56px。柱子底部对齐,按窗口内最大绝对值缩放。可在不占用图表空间的前提下快速传达趋势。
- **箭头图标**:位于最右侧,仅当该指标支持来源分解时显示。点击展开,首次展开时懒加载获取数据。
展开后的来源分解:
- 使用小写字母标题“Source mix”。
- 每行显示来源名称、占比百分比及一条细进度条(上限 100%)。
- 按占比降序排列,主要来源优先显示。
为何有效:
- 多个指标可舒适地排列于仪表盘的窄列中。
- 山脊图在不占用图表空间的前提下传递近期趋势信息(价格图表已占据主视觉区域)。
- 懒加载来源分解可避免冷启动时对每个指标发起一次 API 请求。大多数用户不会展开,真正需要的人才承担相应成本。
- 将分解结果定位为“信号来源”的次级面板,符合数据实际结构(依据 API 设计注意事项,`distribution` 为声量占比,非各来源原始值)。
---
## 代理的可信锚定(工具层级)
过时知识是终端应用中信任崩塌的首要原因。**永远不要引用训练数据中的数字、日期、头条新闻或评级**。所有回答必须基于工具返回的结果进行锚定。一旦用户发现代理虚构了一个数据点,其后续所有回答都将失去可信度。
为代理配置一个按成本排序的工具层级:
1. **读取已渲染的内容(免费)**。构建一个 `read_screen({ target })` 工具,返回当前界面的 Markdown 快照。`target: "dashboard"` 返回当前股票的图表摘要、报价数据、SentiSense Score / 情绪倾向 / 提及次数 / 社交主导力、新闻和同业对比;`target: "canvas"` 返回当前打开的创作内容。此操作零成本,且比重新拉取更准确(数据与用户实际看到的一致)。
2. **获取非可视股票的实时数据**。调用 `get_quote(ticker)`、`get_chart_summary(ticker, timeframe)`、`get_metrics(ticker)` 获取当前仪表盘未显示的股票数据。每个工具调用对应一次 API 请求。
3. **预计算报告,用于主题型问题**。使用 `get_ai_summary(ticker, depth)` 工具调用 `/api/v1/stocks/{ticker}/ai-summary?depth=basic|deep`,比从零生成分析更高效且更可信。同理适用于 `get_insights(ticker)`(调用 `/api/v1/insights/stock/{ticker}`)。
4. **针对非股票类问题的主题搜索**。使用 `search_documents(query)`(调用 `/api/v1/documents/search`)处理“关于 AI 安全人们在说什么?”这类问题。
**`read_screen` 快照结构**:本地快照是一个小型内存缓存,每个组件将最新有效数据推入其中。该工具从缓存读取并格式化为 Markdown,无需重新请求。在上下文变更时(如切换股票、页面跳转)重置缓存,防止旧数据跨页泄露。若当前界面尚无内容,返回占位符提示:“仪表盘组件仍在加载;请稍后再试,或使用实时获取工具”。
**宿主端可信锚定配置**:在构建宿主应用时,在系统提示中配置强制要求,规定模型在引用特定数值、头条新闻或同业对比前,必须先调用 `read_screen('dashboard')`(或等效接口)。若无此配置,模型容易回退至使用过时的训练数据。本技能无法修改宿主系统提示;仅描述能产生可信终端的行为模式。
**若工具调用失败或返回空值,请如实说明**。“我目前没有 $X 的情绪读数”比编造一个数字更可信。
上方的阶梯是模型调用的 *接口*。为确保其可靠,应基于单一的底层系统实现:一个写入透传缓存(widgets 供给数据),一个新鲜度契约,一个主机端的底层依赖要求,工具结果注入,以及类型化降级机制。详见下方 **信任层(底层系统)**。构建一次该系统,之后阶梯上的每一层都将继承它。
---
## 信任层(底层系统)
上方的工具阶梯告诉模型 *应该调用什么*。本节则告诉开发者 *需要构建什么一次*,以确保模型不会过时。这是唯一能将一个演示(生成看似合理的数值)与一个人们可信赖的终端(呈现当前真实信息,并在无法获取时明确说明)区分开来的系统。将其表述为不变性原则:模型只能断言出现在当前回合上下文中的工具结果里的数值、日期、标题、评分或持仓。其余所有内容均为训练数据,从定义上即已过时。该系统包含五个部分,每部分均可独立构建。
### 1. 读取模型缓存(widgets 写入,模型读取)
阶梯中的 `read_screen` 工具是低成本层级,因为它读取的是 widgets 填充的缓存,而非网络请求。将此缓存构建为一个一等公民对象:widget fetch (ok) model turn
| |
v v
+--------------+ write-through +------------------+
| ReadModel | <---------------------- | price widget |
|---|---|---|
| cache | metrics widget | |
| (per surface) | news widget ... |
+------+-------+ +------------------+
| read (0 API calls)
v
read_screen('dashboard') --> markdown snapshot --> model context
每个 widget 在成功获取数据后,会在渲染前将其归一化结果写入一个按界面划分的缓存中。`read_screen` 仅读取该缓存并格式化为 markdown;从不重新请求。因此模型引用的值正是用户屏幕上显示的确切值:成本更低(零次 API 调用),也更可信(用户所见与模型所述之间无漂移)。
缓存条目结构(每个界面和槽位一个):CacheEntry {
key: "dashboard:$NVDA:metrics" // surface : ticker : slot
status: "ok" | "empty" | "error" | "preview"
kind: "realtime" | "batch"
value: <normalized payload> // 已根据 API 特性解包
fetchedAt: 1719772800000 // widget 调用 API 的时间(毫秒级时间戳)
dataAsOf: 1719759600000 | null // 批处理的 generatedAt;实时数据为 null
}
缓存的两条硬性规则:
- 存储 *归一化后的值*,而非原始封装。在写入时解包 `{ isPreview, data }` 并提取 `metricValue.value.value`(参见 API 形式注意事项),确保模型无需重新推导结构,也不会引入自身无法察觉的结构错误。
- 在上下文变更时(如切换股票、路由变化)重置整个缓存。一个旧的 `$AMD` 指标条目残留在 `$NVDA` 仪表板中,就是多界面场景中“幽灵应用”故障的数据体现。
当某个槽位尚无数据时,`read_screen` 返回加载占位符(已在阶梯中指定),而非省略。无数据行视为“零”;标记为“加载中”的行视为“尚未获取”。
### 2. 新鲜度契约
底层依赖不仅关乎“是否已获取”,更关乎“允许的最大延迟”。为每个界面绑定以下两种新鲜度类别之一,并以不同方式呈现。这是对批处理与实时数据差异的强制执行层,不改变哪些端点属于哪一类。
| 类别 | 界面 | 缓存 `kind` | 模型如何呈现 |
|---|---|---|---|
| 实时 | 报价、价格、图表点 | `realtime` | 直接陈述数值。按轮询间隔刷新,头部刷新频率不低于约 60 秒。 |
| 批处理 | 情绪分析、SentiSense 分数、提及次数、社交主导力、新闻聚类、AI 摘要、洞察 | `batch` | 陈述数值,并标注新鲜度:`as of {dataAsOf}`。绝不称其为“实时”。 |
批处理槽位的 `dataAsOf` 是数据负载中的 `generatedAt`(洞察与 AI 摘要界面中存在)。展示此信息并非装饰:它是用户信任一个开盘时获得的 `+0.42` 情绪值的关键,即使价格已发生变动。一个未显示时效性的批处理值,与伪造值无法区分。
模型在组合阶段遵循的规则:若同一界面上两个值的新鲜度类别不同,且问题具有时效性(“是否仍在上涨?”),应优先展示实时值,并标注批处理值的生成时间,而非将两者混合成一个隐含的“当前”值。
### 3. 底层依赖要求(由主机提示词定义,非本技能)
缓存与新鲜度契约本身是惰性的,除非主机自身的系统提示强制模型使用它们。本技能无法修改你的系统提示;你需在自身侧完成一次配置。一个有效的指令块应如下:在陈述任何与当前股票相关的数值、日期、标题、评分或持仓之前,请先调用 read_screen('dashboard'),并从其结果中读取对应值。如果所需值不在该结果中,请调用对应的实时获取工具。不得凭过往知识作答。若工具返回空值或出错,请说明无法获取该数据;不得进行估算。
将其保留在主机提示词中,因为其必须压倒模型默认的“立即回答”倾向——即从记忆中直接响应。技能文本只是提示词的一个输入;只有由主机拥有,才能成为有效约束。
### 4. 工具结果到上下文的注入
获取只是循环的一半。模型只有在每次工具结果被作为第一类消息注入其上下文时,才能保持稳定。确保其诚实的结构如下:
markdown
循环每轮:
模型生成 tool_call(例如:get_metrics($NVDA))
主机执行、标准化并缓存(写穿透,参考第1部分)
主机追加一条 tool_result 消息:
+-----------------------------------------------+
| tool: get_metrics($NVDA) |
| status: ok kind: batch dataAsOf: 09:31 ET |
| value: { sentiment: +0.42, score: 1830, ... } |
+-----------------------------------------------+
模型读取 tool_result,基于其内容生成界面显示
### 两个保障注入可信性的构建规则:
- 注入的必须是已缓存并标准化的值,并附带新鲜度头信息。模型、缓存与界面上的像素因此在构造上达成一致。
- 永远不让模型从记忆中携带前一轮的数值。在后续查询(“前一天呢?”)时,必须重新调用接口;多一次获取的成本远低于一次错误数值带来的信任损失,这正是反模式章节所强调的不对称性。
---
## 优雅降级(空数据 / 错误 / 预览)
终端的可信度不仅来自正常渲染,更来自它出错时的表现。将所有非 `ok` 的缓存状态映射为明确的视觉呈现:绝不留白,绝不虚构填充。
| 状态 | 原因 | 模型渲染内容 |
|---|---|---|
| `empty` | 有效调用但返回空数组(例如7日内幕/国会滞后数据,`isPreview:false`) | 表示该窗口为空,并扩大范围(`lookbackDays=30`),在标题中注明更宽的时间窗口。这不是错误,也不是零值。 |
| `error` | 非2xx响应、超时、`401 api_key_required`、`429` | “我目前没有 $X 的 {metric} 数据。” 对于 `429`,展示 `Retry-After` 提示(“速率限制已达,将在 N 秒后重试”);绝不能静默返回过期数据。 |
| `preview` | 免费版 `isPreview:true`(前3个洞察、本周财报、切片流) | 将预览片段作为答案渲染,并在角落标注 `(preview)`。仅当截断明显影响回答完整性时,才提及 PRO 版本。 |
核心原则:降级只减少数据量,绝不生成虚构数据。一句诚实的“我没有这个读数”只会带来短暂摩擦;而一个伪造的数字则会彻底失去整个会话的信任,且用户在阅读时无法分辨两者区别。这种不对称性正是信任层存在的根本原因。
---
## 透明化用户体验(工具调用芯片)
终端在用户可见其行为时更具可信度。在每个助手消息下方渲染小型芯片,显示触发了哪些工具及其状态。
每个芯片格式为 `<图标> 工具名(参数摘要)`,其中:
- 图标:等待时为 `…`,成功为 `✓`,失败为 `!`
- 工具名:工具标识符(如 `get_quote`、`read_screen`)
- 参数摘要:1至3个词的人类可读标签(如 `$NVDA`、`dashboard`、`story 1a2b…`)
**实时流式推送芯片**,而非在本轮结束时集中展示。用户能直观看到实际查询正在发生,而非仅看到点状动画。图标颜色设定如下:
- 等待时:灰度柔和
- 成功时:主色调蓝色
- 失败时:红色
悬停可查看完整工具调用信息(名称 + 完整参数 + 状态)。
芯片不仅能建立信任,还为用户提供隐含的成本模型。芯片越多,代表调用次数越多。当用户开始注意到芯片数量时,便会主动优化查询方式。
**同时流式输出文本增量**。在模型生成回复过程中,逐字追加到助手消息气泡中,而非等待完整响应后再一次性输出。结合上述芯片流式机制,整体体验呈现为“活”的状态:芯片出现 → 文本开始流入 → 回复逐渐稳定。若无文本流式,即使有芯片,对话仍像批量处理而非真实交流。
---
## 视觉默认设置(配色、字体、动效)
该技能对渲染器无依赖,但若不主动设定视觉规范,系统可能采用通用的 Bootstrap 蓝灰风格。请从以下三个配色方案中选择其一(或进行适配),并在全应用中保持统一。
### 三种可用配色方案
**炭黑(沉静、现代):**bg #1C1C1E
surface #2C2C2E
text #F5F5F7
muted #8E8E93
accent #0A84FF
bull #30D158
bear #FF453A
**石青(技术感、中性):**bg #0F172A (slate-900)
surface #1E293B (slate-800)
text #F1F5F9 (slate-100)
muted #64748B (slate-500)
accent #38BDF8 (sky-400)
bull #22C55E (green-500)
bear #EF4444 (red-500)
**可可(温暖深色、高端感):**bg #1A1612
surface #2A231D
text #F0E9E0
muted #7A6B5D
accent #D4A843 (gold)
bull #A8C97A
bear #C97070
以上三套均为深色基调。浅色模式对部分用户可行,但终端视觉在深色背景下表现更佳;建议优先开发深色主题,再补充浅色支持。
### 各配色方案共通规则
- **字体**:正文使用无衬线字体(Inter、system-ui),股票代码和表格数据使用等宽字体(SF Mono、JetBrains Mono、Fira Code)。不要混合三种字体家族;无衬线 + 等宽已足够。
- **数字排版**:始终使用等宽数字(`font-variant-numeric: tabular-nums`),确保数字列对齐。
- **圆角**:面板和卡片使用 12 到 16px 圆角,小标签和按钮使用 6 到 8px 圆角。避免尖锐边角(显得过时),也避免在所有地方使用胶囊形按钮(显得消费化)。
- **动效**:聊天消息、标签和数值变化使用短淡入淡出(约 150–200ms);滑入面板使用约 250ms 缓出动画。禁止弹跳或弹簧效果;终端风格拒绝任何轻佻的动效。
- **间距**:统计数据列使用紧凑行距(8 到 12px)。仅在顶层区域之间留出呼吸空间(24 到 32px)。首页全局搜索框两侧留出充足内边距(该视图应营造平静感)。
- **强调色规范**:仅使用一种强调色,且使用克制:股票代码、焦点状态、当前激活标签、高于中性水平的主值。不要用强调色填充整个界面。涨跌颜色仅用于表示方向变化的数值,不用于通用交互元素。
- **边框**:使用低透明度的细边框(如 `rgba(58, 58, 60, 0.4)`),而非强对比分隔线。当每个面板都带有粗实线时,终端会显得沉重。
---
### 应避免的内容
- **多色图表**:坚持单一线条颜色(或柱状图使用绿/红区分)。彩虹色调看起来像电子表格,而非终端。
- **紫色**:在此产品领域中,紫色易被解读为加密货币或消费类品牌。上述三种配色方案均刻意避开紫色。
- **数据区域的渐变**:英雄标题中的细微渐变可以接受;但在报价数据背景上使用渐变则显得业余。
- **厚重的阴影**:仅在滑出面板和模态框中使用。仪表盘内的卡片应保持扁平。
---
## 内容创作规范(请仔细阅读)
这些规则确保终端在每次交互中保持一致体验。每次输出都必须遵循。
### 股票代码
- 始终以 `$NVDA`、`$TSLA`、`$AAPL` 格式显示股票代码:全大写,前缀美元符号。宿主界面可将其样式设为品牌色。
- 用户输入“NVDA”时,不得写作“Nvidia”;除非用户主动要求,否则不展开股票代码。
### 数字与变动
- 价格:保留两位小数。如 `$190.20`,而非 `$190.2` 或 `$190`。
- 百分比变动:带符号,保留两位小数,包含百分号。如 `+1.23%`、`-0.45%`。变动值始终显示正负号。
- 情绪指标:极性值范围为 [-1.0, 1.0]。符号代表方向(负值为看空,正值为看多),数值大小代表信心程度。可根据屏幕空间灵活呈现,但极性必须清晰可辨(例如 `-0.42 (看空)`、-1 到 +1 的仪表盘,或“看空 / 中性 / 看多”标签)。不得映射到 0–100 的刻度。独立的情绪得分(SentiSense Score)为无界值,直接报告原始数值,不进行截断或归一化。
- 大额金额:使用 `$1.2M`、`$2.5B` 等格式,而非原始数字。
### 输出结构
- 每行一个信号。不要将“内部人买入且分析师上调”合并为一句话;应分两行展示。
- 数字优先,文字其次。如 `$NVDA $890.12 (+1.4%)` 在任何描述之前。
- 垂直结构优于段落。表格和带标签的行优于句子。
- 全局保持一致的四舍五入规则。
- 除非用户明确要求分析,否则不添加尾部说明。屏幕本身即为答案。
### 语气
- 无需开场白。不要说“这里是我找到的结果:”或“根据数据……”。直接从答案开始。
- 不要道歉。不要说“抱歉,我只能……”;应静默降级为可执行的部分。
- 不提供个性化建议。仅展示数据和教育性说明;永远不要说“你应该买入”或“这对你是好的投资”。本技能是数据接口,而非投资顾问。
- 不使用表情符号(用户品牌语调不包含此类元素)。
### 隐藏工作
- 并行发起独立请求。若页面需要价格、情绪、内部交易、分析师共识,应同时发起四个请求。
- 缓存 `/institutional/quarters` 数据至会话期间。跨轮次复用 `latestQuarter`。
- 绝不向用户暴露调用栈。用户想要的是答案,而非实现过程。
---
## 终端命令
当用户输入以下任一命令(或自然语言转述,详见下方 **别名**),执行合成模式并渲染输出模板。
---
### `open <TICKER>`:股票详情页
核心命令。单屏综合报告。
**并行调用:**
1. `GET /api/v1/stocks/price?ticker={T}`
2. `GET /api/v1/stocks/{T}/profile`
3. `GET /api/v2/metrics/entity/{T}/metric/sentiment?startTime={now-30d in epoch ms}&endTime={now in epoch ms}`
4. `GET /api/v1/insider/trades/{T}?lookbackDays=90`
5. `GET /api/v1/analyst/{T}/consensus`
6. `GET /api/v1/insights/stock/{T}`(按重要性、置信度和时效排序;最重要洞察为 `data[0]`)
**输出模板(等宽宿主):**╭─ {TICKER} · {公司名称} · {行业} ────────────────────────────────╮
│ PRICE ${price} ({changePct}% today) │
│ TARGET ${targetLow}-${targetHigh} (mean ${targetMean}, {N} an.) │
│ RATING {consensusLabel} ({upsidePct}% upside) │
│ MOOD Sentiment {sentiment30d} ({delta30d} 30d) │
│ INSIDERS {insiderBuys} buys / {insiderSells} sells (90d) │
│ AI "{insightText}" │
╰────────────────────────────────────────────────────────────────────────╯
**输出模板(Markdown 宿主):**$TICKER · 公司名称 · 行业
| 价格 | $190.20 (+1.23%) |
| 目标价 | $180-$250 (均值 $210,33 位分析师) |
| 评级 | 买入 (10.5% 上升空间) |
| 情绪 | 情绪 +0.42 (+0.08 30天) |
| 内部人交易 | 3 次买入 / 0 次卖出 (90天) |
| AI 分析 | "利润率指引上调,服务业务超出预期。" |
若宿主能清晰渲染等宽盒子,优先使用;否则回退为 Markdown 表格。字段、顺序、密度保持一致。
**字段映射(实际响应键名)**:上述标记为显示标签,非响应字段名称。价格来自 `stocks/price` 响应的 `currentPrice`(扁平结构,位于根层级,无 `price` 包裹),当日涨跌幅来自其 `changePercent`,公司名称来自 `profile.name`(非 `companyName`),评级来自 `analyst/consensus` 响应的 `data.consensusLabel`(原始枚举值如 `STRONG_BUY`;需人性化为 `Strong Buy`),情绪值来自 `metricValue.value.value`(参见 API 结构注意事项),AI 分析语句来自 `insights[0].insightText`(`/insights/stock` 项目暴露 `insightText`,无 `headline` 字段)。
---
### `compare <A> <B>`:并列对比
**调用:** 并行执行每个标的的 `open` 工作流。
**输出模板:**{A} {B}
PRICE ${pA} ${pB}
DAY % {dA} {dB}
TARGET MEAN ${tA} ${tB}
UPSIDE % {uA} {uB}
CONSENSUS {cA} {cB}
SENTIMENT 30d {sA} ({deltaA}) {sB} ({deltaB})
INSIDER NET 90d {iA} {iB}
表格下方添加一行“优势总结”:说明哪个标的综合表现更优及其原因。示例:`$NVDA 拥有更强的内部人士信心和更高的分析师上行空间;$AMD 具有更好的情绪动量。`
---
### `daily brief`:市场开市/收市摘要
**调用:**
1. `GET /api/v1/stocks/market-status`
2. `GET /api/v2/market-mood`
3. `GET /api/v1/market-summary`
4. `GET /api/v1/insights/market`(前5条)
5. `GET /api/v1/stocks/prices?tickers=SPY,QQQ,IWM,DIA`
**输出模板:**DAILY BRIEF · {date} · Market {OPEN/CLOSED}
────────────────────────────────────────────
INDEXES $SPY {p} ({d}%) $QQQ {p} ({d}%) $IWM {p} ({d}%) $DIA {p} ({d}%)
MOOD {score} ({phase}) {weeklyChange} 7d
HEADLINE {marketSummary.headline}
TOP SIGNALS
`/api/v1/insights/market` 项目暴露 `insightText`(无 `headline` 字段),且不包含独立的 `ticker` 字段;标的符号嵌入在 `insightText`(及 `insightId`)中,因此直接渲染文本内容,而非拆分为 `$TICKER` 列。
---
### `screen smart-money`:智能资金汇聚筛选器
查找在相同7天窗口期内,内部人士、国会人员与分析师均呈正面信号的标的。
**调用:**
1. `GET /api/v1/insider/cluster-buys?lookbackDays=7`
2. `GET /api/v1/politicians/activity?lookbackDays=7`(过滤 `transactionType=PURCHASE`)
3. `GET /api/v1/analyst/activity?lookbackDays=7`(客户端过滤 `actionType=="UPGRADE"`;服务器端无 `types=` 过滤选项)
**输出模板:**SMART-MONEY SCREEN · 7-day convergence
──────────────────────────────────────
TICKER INSIDER CONGRESS ANALYST
$T1 {N} buys {M} purch. {K} upg.
$T2 ...
按总信号数排序,列出前10个。7天内的内部人士与国会活动窗口常返回空数组(真实披露延迟,`isPreview:false`),并非错误;当某类数据为空时,将该请求扩展至 `lookbackDays=30`,并在标题中注明更宽窗口,而非显示空白。若未发现汇聚信号,列出任一类别中的前几名作为备选。在末尾添加一行总结,突出最强汇聚标的。
---
### `mood`:市场情绪快照
**调用:** `GET /api/v2/market-mood`
**输出模板:**MARKET MOOD · {date}
─────────────────────
Composite {score} ({phase}) {weeklyChange} 7d
Social Sent {v} ({d})
Market Dir {v} ({d})
Risk Appetite {v} ({d})
Social Mom {v} ({d})
S&P 500 Trend {v} ({d})
SECTORS (top 3 / bottom 3)
Tech {s} ({d}) Energy {s} ({d})
Comms {s} ({d}) Utils {s} ({d})
Disc {s} ({d}) Staples {s} ({d})
---
### `flow <TICKER>`:单个标的的智能资金流动分析
**调用:**
1. `GET /api/v1/insider/trades/{T}?lookbackDays=90`
2. `GET /api/v1/politicians/filings/{T}?lookbackDays=90`(按标的获取申报文件;无需客户端过滤)
3. `GET /api/v1/institutional/quarters` 后接 `GET /api/v1/institutional/holders/{T}?reportDate={Q}`(`data.holders[]`)
4. `GET /api/v1/analyst/{T}/actions?lookbackDays=90`
**输出模板:**SMART-MONEY FLOW · $TICKER · 90d
─────────────────────────────────
INSIDERS {N} buys (${$buys}) {M} sells (${$sells}) Net: {NET}
CONGRESS {K} purchases {L} sales
TOP 13F 1. {Inst1} {shares1} ({changeType1} {sharesChangePct1}%)
2. {Inst2} {shares2} ({changeType2} {sharesChangePct2}%)
3. {Inst3} {shares3} ({changeType3} {sharesChangePct3}%)
ANALYSTS {U} upgrades {D} downgrades (recent: "{lastAction}")
---
### `news <TICKER>`:情绪标签新闻 + 嵌入内容
此命令是终端体验区别于简单报价工具的关键所在。SentiSense 返回文档(URL + 情绪 + 来源)。公开文档 API 提供衍生分析,不包含原始内容;**不包含发布方的文章标题**。你需使用以下 **标题解析** 模式自行生成标题。从源链接中检索内容为你的代理应用独立行为,受源平台条款约束。
**调用:**
1. `GET /api/v1/documents/ticker/{T}?limit=8` 获取文档流
2. `GET /api/v2/metrics/entity/{T}/metric/sentiment` 获取上下文(服务器默认7天窗口)
**输出模板:**NEWS · $TICKER · 7d sentiment {score} ({delta})
─────────────────────────────────────────────────
{source} · {time}
{url}
对于 Reddit/X 链接,渲染嵌入卡片而非纯文本链接(参见 **社交嵌入** 下方说明)。
---
### `stories`:预聚类故事流
Skill: 股票终端
版本: 1.3.2
分块: 11/15
一个经过筛选的原始 `news` 替代方案:SentiSense 将相关文档聚类为带有自动生成标题的独立故事。这些标题由我们生成,属于我们的内容,可直接显示(无出版商版权风险)。列表接口返回聚类的标题、情感倾向、数量及关联股票;完整叙事摘要位于故事详情接口中,不在列表内。
**调用方式:**
1. `GET /api/v1/documents/stories?limit=10`
**输出模板:**今日故事 · {date}
────────────────────────
股票: $T1 $T2 $T3 · {cluster.clusterSize} 来源
列表中的聚类不包含正文或摘要字段。真实结构为:`{ id, title, createdAt, clusteredAt, clusterSize, averageSentiment }`。如需获取叙事摘要,请调用故事详情(`GET /api/v1/documents/stories/{id}`)。
针对单只股票的故事:`GET /api/v1/documents/stories/ticker/{T}?limit=5`
---
### `earnings [this|next]`: earnings 日历
前瞻性 earnings 日历:显示哪些公司即将发布财报、发布时间以及共识每股收益(EPS)。该值表示**提前时间**,而非今晚将发布的报告。这是专业数据服务在高级套餐中提供的前瞻日历功能;此处免费提供本周数据,PRO 用户可访问完整窗口。可用于构建财报前关注清单,并作为 `EARNINGS PREVIEW` 组合的锚点日期。
**调用方式:**
1. `GET /api/v1/calendar/earnings?week={this|next}`(默认为 `this`;也可使用 `?ticker={T}` 查询特定股票)
**输出模板:**财报 · {windowStart} 当周
─────────────────────────────────
{date} {BMO/AMC} $TICKER 预估 EPS {eps} {✓}
{date} {BMO/AMC} $TICKER 预估 EPS {eps}
...
{totalCount} 家公司在未来 30 天内发布 · PRO 可解锁完整时间窗口
按日期升序排列。映射 `earningsTime`:`before_open` → BMO,`after_close` → AMC,`during_market` → MID,`unknown` → 留空。当存在预估 EPS 时显示 `est. EPS ${estimatedEps}`,为空则省略。标记 `confirmed:true` 的行显示 ✓,未确认的日期不加标记。免费密钥返回 `isPreview:true`,仅限当前周,并携带 `totalCount`(覆盖约 30 天的总事件数):仅在预览状态下显示底部提示。PRO 用户获得完整窗口,因此无需显示底部提示。
---
### `help` 或无法识别的输入
显示命令列表。不要说“我不理解”:直接展示可用功能。命令
open <TICKER> 查看股票行情
compare <A> <B> 对比两只股票
daily brief 市场简报
screen smart-money 智能资金汇聚筛选器
flow <TICKER> 智能资金流动分析
mood 市场情绪分析
news <TICKER> 带嵌入内容的近期新闻
stories 已聚类的故事资讯流
earnings [this|next] 前瞻性财报日历
或自然提问
"NVDA 这里值得买入吗?" "今天市场热点是什么?"
"对比 TSLA 和 RIVN" "苹果股价为何异动?"
---
## 自然语言别名
用户很少会准确输入命令语法。请识别意图并执行最接近的工作流程。不要询问“您是想运行 `open NVDA` 吗?”:直接执行即可。
| 用户输入 | 执行命令 |
|----------|--------|
| "给我看看 $TICKER","告诉我关于 $TICKER","$TICKER 现在怎么样" | `open` |
| "$TICKER 值得买入吗","我该关注 $TICKER 吗","$TICKER 的看法" | `open` + 在底部添加一行教育性背景说明(提供数据上下文,非投资建议) |
| "今天市场热点","今天的市场","有什么在变动" | `daily brief` |
| "智能资金","内部人买了什么","智能资金在做什么" | `screen smart-money` |
| "对比 $A 和 $B","$A 对 $B" | `compare` |
| "市场情绪","恐惧与贪婪","市场是否恐慌" | `mood` |
| "WTF $TICKER","$TICKER 为什么波动","$TICKER 发生了什么" | `flow` + `news`(组合成一个界面) |
| "关于 $TICKER 的新闻","最近新闻","$TICKER 的头条新闻" | `news` |
| "今天的故事","有哪些正在发生的故事" | `stories` |
| "财报前的 $TICKER","$TICKER 财报预览","$TICKER 何时发布" | `flow` + 使用 `/calendar/earnings?ticker=$TICKER` 的分析师预估数据进行锚定(结合财报前合成内容) |
| "财报日历","本周谁要发布财报","下周有哪些公司发布","本周财报" | `earnings` |
当用户提问无法清晰匹配时,若含股票代码则默认执行 `open`,否则默认执行 `daily brief`,仅当两者均不满足时才返回 `help`。
---
## 标题解析规则
SentiSense 公开文档 API 返回每个文档的 `{ id, url, source, sourceName, published, averageSentiment, reliability, sentiment }`,而单只股票信息流将其封装为 `{ documents, totalCount, searchTicker, source, startDate, endDate }`(读取 `response.documents[]`)。在 `news` 模板中有两个字段陷阱:时间戳使用 `published`(单位为**秒级**时间戳,非 `timestamp`);标量极性为 `averageSentiment`(浮点数,范围 [-1,1]),而 `sentiment` 本身是实体级数组(`[{ ticker, name, entityType, sentiment }]`),并非标量。因此 `{time}` 应读取 `published`,`{sentiment}` 应读取 `averageSentiment`。根据 API 设计,**不包含**发布方的文章标题,且无 `summary` 字段。API 提供的是衍生分析数据,而非原始内容。如需显示标题,请自行从 `url` 字段解析。从源网址提取内容为应用自身的独立行为,需遵守源平台的使用条款。
> **获取安全(若实现第1-2阶段则为必选项)**
> 标题与嵌入内容解析是该技能唯一需要调用 SentiSense API 外部资源的环节,因此必须加以限制。请**不要**赋予此技能广泛的 `WebFetch` / `Browse` 工具能力。应使用一个**窄范围、经过加固的获取器**,其要求如下:
> - 仅允许访问 `http`/`https` 协议的**公开主机**;直接拒绝其他协议(如 `file:`、`ftp:`、`data:`、`gopher:`);
> - 阻止私有地址、环回地址、链路本地地址及云元数据目标(如 `127.0.0.0/8`、`10/8`、`172.16/12`、`192.168/16`、`169.254.0.0/16` 包含 `169.254.169.254`、`::1`、`fd00::/8`),并且在每次重定向后重新解析并校验 IP 地址(绝不允许重定向至私有地址段);
> - 限制响应大小(约 256KB)和请求时间(约 5 秒),仅读取前 16KB 内容以提取 `<title>`;
> - 仅对来自 SentiSense `documents[]` 数据包中的 URL 进行获取,绝不处理用户或模型自行构造的 URL;仅提取显示元数据(如 `<title>` 或 oEmbed 的 `title`),不得执行、存储或基于页面内容进行任何操作。
> 若无法提供上述加固的获取器,请跳过第1-2阶段,改用第3阶段的 URL 片段回退机制(完全不联网)。一个只读的市场终端绝不能演变为通用的 URL 获取工具。
采用以下两阶段模式,按顺序执行:
### 第1阶段:社交平台 URL 的 oEmbed 获取(最快路径)
若 URL 来自主流社交平台,可向该平台的 oEmbed 接口发起请求。这些接口均为免费、公开、无需认证,并返回预渲染的丰富内容。
| 域名 | oEmbed 接口 |
|------|------------|
| `reddit.com`, `*.reddit.com` | `https://www.reddit.com/oembed?url={ENCODED_URL}` |
| `x.com`, `twitter.com` | `https://publish.twitter.com/oembed?url={ENCODED_URL}&omit_script=true&dnt=true` |
| `youtube.com`, `youtu.be` | `https://www.youtube.com/oembed?url={ENCODED_URL}&format=json` |
响应中包含 `title`、`author_name`,以及(对 Reddit/X)的 `html` 字段,其中包含预格式化的嵌入内容。若宿主界面支持内联 HTML,可使用 `html` 块;否则仅提取 `title`。
### 第2阶段:获取并解析 `<title>` 用于通用 URL
对于非社交类 URL,使用上述**已加固的获取器**(绝不可使用原始的 `WebFetch` / `Browse`)对文档中的 `url` 进行请求,并提取 `<title>` 标签。仅对来自 SentiSense `documents[]` 数据包的 URL 执行获取操作,并在每次调用时应用协议、私有地址段、重定向、响应大小和超时限制。
优化建议:只需读取页面前约 16KB 内容即可(`<title>` 位于 `<head>` 中,通常靠近开头)。无需读取完整文档。
注意:Google 新闻聚合链接(如 `news.google.com/rss/...`)为重定向包装器,会干扰 oEmbed 和 `<title>` 提取。对此类链接应直接跳转至第3阶段的片段回退机制(或根据文档的 `source` 字段标注来源)。
伪代码示例:title = fetch(url, range=0-16384).extract("<title>")
if title and len(title) > 3:
return title
### 第3阶段:URL 片段回退(零成本)
若无法获取 URL(无获取工具可用,或获取失败),则从 URL 片段生成人性化标题:url: https://www.reuters.com/technology/nvidia-q1-revenue-beats-2026-04-30/
slug: nvidia-q1-revenue-beats
title: "Nvidia Q1 Revenue Beats"(将连字符替换为空格,首字母大写,去除日期/哈希值)
output: "Nvidia Q1 Revenue Beats: reuters.com"
确保降级处理,使新闻视图永远不显示裸露的 URL。
---
## 社交嵌入
在 `news` 视图中渲染 Reddit、X/Twitter 或 YouTube 的 URL 时,宿主界面可能支持丰富的嵌入展示。按优先级提供三种渲染方式:
1. **原生嵌入**。若宿主支持 iframe 或小部件嵌入(例如网页视图代理),应通过**沙箱化 iframe 或内容安全策略(CSP)** 渲染 oEmbed 的 `html` 内容(移除 `<script>`、事件处理器属性和内联样式;设置严格的 `sandbox`/CSP),**绝不可直接将第三方 HTML 注入自身 DOM**。oEmbed 的 `html` 可能受攻击者操控,应视为不受信任内容。如此处理可在不引入脚本注入风险的前提下,获得平台原生的视觉体验。
2. **卡片式渲染**。若宿主支持 Markdown 块引用或提示框,可渲染为引用卡片:Reddit · r/wallstreetbets · 4h ago
"{帖子标题或摘要}"
{url}
3. **普通链接**。最差情况,采用标准 `news` 行格式,显示已解析的标题。
无论是否嵌入,均**不可省略 `url`**:用户需要点击跳转的选项。
---
## 组合模板
针对复杂查询,可能需要将多个命令组合成一个界面展示。以下是三种可复用的结构:
### 盈利前瞻
当用户询问“$X 股票财报前”或“$X 盈利前瞻”时:EARNINGS PREVIEW · $TICKER · ER {date} ({daysOut}d 后)
────────────────────────────────────────────────────────
SETUP 情绪 {s30d} ({d30d} 30天) · 内部人士 {netInsider}
CONSENSUS EPS ${epsMean} (范围 ${epsLow}-${epsHigh}, {N} 名分析师)
SURPRISES {recent beats/misses from surprises[], 例如 "过去4次中有3次超出预期"}
ACTIONS {U} 上调,{D} 下调 (30天)
最近动态: "{lastAction}"
THESIS {一句话总结:看涨/看跌/中性}
Skill: 股票终端
版本: 1.3.2
分块: 13/15
### 收益日信息
调用接口:`/calendar/earnings?ticker={T}`、`/profile`、`/analyst/{T}/estimates`、`/analyst/{T}/actions?lookbackDays=30`、情绪分析(30天)、内部人士交易(60天)。
报告日期和 `daysOut` 来自 `/calendar/earnings?ticker={T}`(`data.earnings[0].earningsDate` 和 `confirmed`);若返回空,则说明公司不在未来窗口期内,应省略日期行而非猜测。
注意:`/estimates` 返回 `data.estimates[]`(每个包含 `{ periodLabel, periodType, estimateLow, estimateMean, estimateHigh, numberOfAnalysts }`)以及 `data.surprises[]`(每个包含 `{ periodLabel, reportDate, estimateEps, actualEps, surprisePercent }`);共识区间应从 `data.estimates[0]` 读取,而非直接从 `data` 获取。该接口不提供营收数据,也无修订历史,因此不要渲染 `Rev` 或“修订自”字段。
---
### 行业深度分析
当用户询问“今天科技板块发生了什么”或“能源行业情况”时:SECTOR · Technology · {date}
─────────────────────────────
MOOD {sectorScore} ({phase}) {weeklyChange} 7d
TOP MOVERS $T1 +X% $T2 +X% $T3 +X%
LAGGARDS $T4 -X% $T5 -X%
DRIVERS "{topInsight1}"
"{topInsight2}"
调用接口:`/market-mood`(从 `response.sectors` 中读取指定行业)、`/insights/market`(返回市场整体信息;客户端在内存中按已知属于该行业的股票进行过滤)、`/stocks/popular`(客户端按行业过滤)。`/market-mood` 和 `/insights/market` 均不接受行业查询参数;两者均为完整响应,需在客户端内存中切片处理。
---
### 自选股简报
当用户输入多个股票代码(例如:“关注 NVDA AMD INTC”)时:WATCHLIST · {date}
───────────────────
$NVDA {price} {chgPct} Mood {s} {smartMoneyFlag}
$AMD {price} {chgPct} Mood {s} {smartMoneyFlag}
$INTC {price} {chgPct} Mood {s} {smartMoneyFlag}
`smartMoneyFlag` 为 `↑`,当过去7天内满足以下任一条件:内部人士集群买入、国会购买、近期上调评级;`↓` 表示相反情况;中性时为空。
---
## 综合规则(回顾)
“终端风格”源于可预测性。每个界面均遵循以下规则。
1. **纵向结构**。表格与带标签的行优于段落。
2. **固定宽度**。展示对比时,对齐列以支持上下扫描。
3. **数值优先,文字其次**。每行以数值开头。
4. **每行一个信号**。避免合并多个信息。
5. **统一舍入**。价格保留两位小数,涨跌幅为整数百分比,[-1, 1] 区间的情绪值保留两位小数。
6. **始终使用 `$TICKER`**。大写,前缀美元符号。
7. **所有变化均标注符号**。如 `+1.23%`、`-0.45%`,不得仅显示数字。
8. **除非被要求,否则不输出散文**。屏幕即答案本身。
9. **并行调用**。`open` 命令同时发起6个请求;不得顺序等待。
10. **缓存季度数据**。`/institutional/quarters` 更新频率极低。
---
## 反模式(禁止行为)
这些是本技能设计旨在规避的失败模式。
- **不要叙述工作过程**。“让我查一下……”或“我需要调用多个端点……”属于反模式。终端应静默完成工作。
- **不要道歉**。“抱歉,我只能显示预览数据”属于反模式。静默呈现已有内容;若用户处于免费版,可在角落标注 `(preview)`。
- **不要给出个人建议**。“$NVDA 是强烈买入”或“你应该卖出 $TSLA”属于反模式。本技能是数据接口,非投资顾问。展示数据与教育性背景信息,由用户自行得出结论。
- **不要为明确请求追问澄清**。“你想要 $NVDA 的价格还是情绪?”属于反模式。直接运行完整 `open` 界面:它同时展示两者。
- **不要为单一数值做美化排版**。用户询问“$NVDA 价格”时,仅返回一行结果(`$NVDA $890.12 (+1.4%)`)。不应为此提供30行的 `open` 屏幕。
- **不要手动编写标题**。若文档 API 未返回标题,使用标题解析模式。不得虚构。
- **不要虚构接口**。禁止使用 `/api/v1/options/flow`、`/api/v1/dark-pool`、`/api/v1/alerts`、`/api/v1/chat`、`/api/v1/congress`(应使用 `/politicians`)。收益日日历是 `/api/v1/calendar/earnings`(非 `/api/v1/earnings`)。
- **不要在用户可见输出中显示 API Key**。永远不要。
- **不要主动推广 PRO 版本**。除非用户遇到瓶颈,否则免费版已提供出色的终端体验。仅在 `(preview)` 截断显著影响回答时提及 PRO。
- **不要引用训练数据中的价格、涨跌幅、标题、分析师评级或财报结果**。这些数据必然过时。每次交互都必须重新获取,即使用户刚在几分钟前问过相同问题。一个错误数字的成本远高于一次额外的 `get_quote` 请求。
---
## API 数据结构陷阱(值得牢记)
真实数据结构常与端点 URL 的直觉不符。这些坑需提前知晓,避免事后反复踩雷。
**`stocks/chart` 返回的是顶层的裸 `ChartDataPoint[]`**,而非 `{ data: [...] }`。需防御性处理两种格式:const points = Array.isArray(raw) ? raw : (raw?.data ?? []);
每个点包含 `timestamp`(Unix 毫秒)和预格式化字符串 `date`。x轴值应从 `timestamp` 读取。某些 JS 日期解析器会将格式化 `date` 字符串(如 `Apr 6`)误解析为当前年份,而非所属年份。
**`entityMetrics/metrics` 返回 `ServingMetric[]`,标量值位于 `metricValue.value.value`**(嵌套结构)。排名信息若存在,位于 `metricValue.value.properties.{rank, percentile, totalStocks}` 或 `metricValue.properties.{rank, percentile, totalStocks}`。顶层 `value: number` 为遗留兼容项;需处理但不可依赖。function extractMetric(m) {
return m?.metricValue?.value?.value
?? m?.metricValue?.value
?? m?.metricValue
?? m?.value
?? null;
}
**`entityMetrics/distribution` 将载荷包裹在 `distribution`(单数)中,而非 `distributions`:**{ entityId, metricType, timestamp, dimension: "source",
distribution: { News: 37.4, Reddit: 37.4, X: 18.2, Substack: 7.0 } }
数值为声音占比百分比,总和约为 100,**不是**各来源的情感得分。应将其渲染为“信号来源”面板,而非四个情感条形图。
**`v2/market-mood` 将复合指标嵌套在 `market` 下。** 响应为扁平结构(无 `isPreview/data` 包装),但恐惧/贪婪指数、阶段、周变化以及子信号位于 `response.market.{ currentScore, phase, weeklyChange, signals[] }`,各行业板块的细分数据则位于 `response.sectors.{SectorName}.{ currentScore, phase, weeklyChange }`(不在根层级)。相应地映射 `mood` / `daily brief` 令牌:`{score}` = `market.currentScore`,`{phase}` = `market.phase`,`{weeklyChange}` = `market.weeklyChange`,每个信号 `{v}`/`{d}` = `market.signals[i].value`/`.change`。
**`GET /api/v1/stocks/images?tickers={T}`(逗号分隔,复数 `tickers`)返回第三方 CDN 的图标 URL,不携带嵌入式 API 密钥。** 直接使用 `<img src>` 会返回 401/403 错误。请通过 SentiSense 匿名图片代理封装:https://app.sentisense.ai/api/v1/stocks/proxy-image?imageUrl=<encoded-url>
**故事详情(`documents/stories/:id`)是一个扁平的 `PublicStoryDetailDto`**,并非你可能预期的嵌套结构 `{ cluster, entities, documents }`。在 `aspectPerspectives[i]` 内部,`bullishView` 和 `bearishView` 是*结构化对象*(包含 `hook`、`risksOrCatalysts: string[]`、`conclusion`、`confidence`),而非 Markdown 字符串。顶层的 `bullishView` / `bearishView` 才是 Markdown 字符串。字段名称相同,但结构不同。调用字符串方法前请进行类型检查。
**`stocks/chart` 支持的图表时间范围:** `1D / 5D / 1W / 1M / 3M / 6M / 1Y / ALL`。其他值将回退至 `1M` 并记录警告。
**`institutional/quarters` 是一个裸数组** `[{ value, label, reportDate, pending }]`(未包裹在 `data` 中)。取 `[0].reportDate` 作为最新季度,用于传递给 `institutional/holders`。
**情感分析、SentiSense 分数、新闻聚类、AI 摘要与洞察均为批量指标。** 价格、行情点等为实时数据。在洞察与 AI 摘要界面显示 `generatedAt` 时间戳,让用户了解分析的新鲜度。不要在分析类界面声称“实时”。
---
## 接口快速参考
完整 Schema 参见:https://sentisense.ai/skill.md。PRICE GET /api/v1/stocks/price?ticker={T}
GET /api/v1/stocks/prices?tickers=A,B,C
GET /api/v1/stocks/chart?ticker={T}&timeframe=1M|3M|6M|1Y
GET /api/v1/stocks/{T}/profile
GET /api/v1/stocks/market-status
SENTIMENT GET /api/v2/metrics/entity/{T}/metric/sentiment?startTime={epochMs}&endTime={epochMs} (省略则使用默认 7 天)
GET /api/v2/market-mood
DOCUMENTS GET /api/v1/documents/ticker/{T}?limit=N (无标题)
GET /api/v1/documents/stories?limit=N (cluster.title 为我们的内容,安全)
GET /api/v1/documents/stories/ticker/{T}?limit=N
INSIDER GET /api/v1/insider/cluster-buys?lookbackDays=N
GET /api/v1/insider/trades/{T}?lookbackDays=N
CONGRESS GET /api/v1/politicians/activity?lookbackDays=N
GET /api/v1/politicians/filings/{T}?lookbackDays=N (按股票的文件)
GET /api/v1/politicians/member/{slug} (最近交易嵌套在 data.recentTrades)
INSTITUTIONAL GET /api/v1/institutional/quarters (始终为第一个)
GET /api/v1/institutional/holders/{T}?reportDate={Q} (data.holders[] 按持仓大小排序)
ANALYST GET /api/v1/analyst/{T}/consensus
GET /api/v1/analyst/{T}/actions?lookbackDays=N
GET /api/v1/analyst/{T}/estimates
GET /api/v1/analyst/activity?lookbackDays=N (市场整体;客户端侧过滤 actionType)
INSIGHTS GET /api/v1/insights/stock/{T} (按重要性排序:相关性、置信度、时效性;公开预览,免费前 3 条;取 data[0])
GET /api/v1/insights/stock/{T}/types
GET /api/v1/insights/market
CALENDAR GET /api/v1/calendar/earnings?week=this|next (公开预览:免费=this 周,PRO=完整约 30 天;data.earnings[])
GET /api/v1/calendar/earnings?ticker={T} (下一个财报日期 + 共识 EPS 仅针对一个标的)
MARKET GET /api/v1/market-summary
**包装 vs 扁平结构(需逐接口验证,不可假设)。** 以下接口为扁平结构,无需 `.data`:`price`、`prices`、`chart`、`popular`、`market-mood`、`stocks/{T}/profile`、`descriptions`、`sentiment`(裸数组)。`institutional/quarters` 也是裸数组(`[0].reportDate` 为最新季度)。`documents/ticker` 有其自身结构 `{ documents, totalCount, ... }`(读取 `.documents[]`)。以下接口为包装结构,需读取 `.data`:`insider/*`、`analyst/*`、`insights/*`、`politicians/*`、`institutional/holders`。若不确定,可同时接受两种格式:`const rows = Array.isArray(raw) ? raw : (raw?.data ?? raw)`。
---
## 成本控制
冷启动的股票仪表盘通常在首次加载时发起 10 到 12 个 API 调用:
| 界面元素 | 调用次数 |
|---|---|
| 个股资料 + 图标 | 1 到 2 |
| 行情报价(头部) | 1(含刷新间隔) |
| 图表 | 1 |
| 指标面板(4 个指标并行) | 4 |
| 最近新闻 | 1 |
| 同类股票(相似股 + 批量价格) | 2 |
| **冷启动总计** | **10 到 12** |
一次基于上下文的对话轮次额外增加 1 到 4 次调用,具体取决于工具链深度。
**缓解措施:**
- 使用 `Promise.allSettled` 并行获取小部件数据;小部件可独立渲染,随数据到达即时显示。不要等待最慢的请求完成才渲染页面。
- 在模块级别缓存热门股票列表和图标,确保每个会话中仅加载一次,而非每次访问都重新请求。
- 当用户展开时才懒加载来源细分数据。不要在获取时间序列数据时立即预加载来源分布信息。
- 股价表格网格无需轮询,头部报价更新频率不超过约 60 秒。
**速率限制**:存在每分钟调用次数限制(免费版 30 次/分钟,PRO 版 300 次/分钟)。超出限制将返回 429 错误,并附带 `Retry-After` 提示。应优雅地提示用户“请求频率已达上限,将在 N 秒后重试”,而非静默重试或展示过期数据。
**单只股票的使用预算思维模型**:一个高频使用者每天访问 15 只股票,每只股票进行约 3 次交互(如聊天),总计约 225 次调用/会话,远低于 PRO 版本的日调用配额。轻度用户(每天访问 3 只股票,无聊天)约消耗 50 次调用。默认设计基于此配额范围,确保普通用户在正常使用情况下不会遇到 429 错误。
---
## 套餐对比
| 功能 | 免费版 | PRO 版 |
|------|--------|--------|
| open | 全屏模式,AI 洞察预览受限(仅前 3 项) | 完整洞察列表 |
| compare | 任意两个股票 | 无限次 |
| daily brief | 每天可轻松使用一次(消耗 5 次调用) | 无限刷新 |
| screen smart-money | 每个类别顶部项目 | 完整排名列表 |
| flow | 预览片段 | 完整持有者列表、完整历史记录 |
| mood | 完整数据,无调用配额限制 | 同上 |
| news | 最近 8 条 | 完整资讯流 |
| stories | 最近 10 条 | 完整资讯流 |
| earnings | 当前周数据 | 完整约 30 天前瞻窗口 |
PRO 版 $15/月:https://app.sentisense.ai/pricing?coupon=AGENTS26(结账时使用优惠码 AGENTS26 可享开发者上线折扣)已收录 1 个 Skill