面向扩展作者的接口与信任边界
运行时与底层接口
先选运行时,再按对应契约实现。Wasm、声明式资源包、宿主管理模型和 Dart 集成拥有不同权限边界;它们不是一套可以互换的插件 API。
截至 2026-10-08,以下内容按当前源码核对。生产服务和已发布客户端支持版本尚未核验; 源码中的接口定义不能单独证明接口已在生产环境上线。
扩展中心的接口分属不同运行时
仓库中有 Wasm、资源包、宿主管理模型和 webApp 四种 Marketplace 运行时契约; webApp 与 managedModel 目前受限于 TradingAI Official。Dart API 与本地进程另列, 避免把 app 内接口误当成 Marketplace guest API。
Marketplace Wasm
runtime: wasm,入口为 main.wasm。 API v1 提供报价与 K 线快照;API v2 提供事件驱动视图和 29 个宿主服务命令。
资源扩展
runtime: resource,清单声明受限视图、预设和模板。 宿主负责读取、渲染与用户确认后的操作。
managedModel
当前契约只接受 TradingAI Official 签名的 TimesFM 包。模型在本机 Python 服务运行,并通过受限的 timesfm-http-v1 协议对接。
webApp
runtime: webApp 使用 tradingai-webapp-v1、apiVersion: 3 与静态资源清单。当前验证器要求 TradingAI Official 且 trust: verified;能力限于 browser、 network、openExternal、secrets 和 languageModel,不能视为第三方公开 API。
Wasm 导入函数
Guest 只能调用表中显式链接的 tradingai 导入。Manifest 的 API 版本和 Wasmtime 原生 ABI 版本是两个独立版本号:API v1/v2 使用 ABI v3,ABI v3 用 feature bits 声明交互事件与输出支持。
| 导入名 | Guest 签名 | 用途与边界 |
|---|---|---|
tradingai.has_capability | (i32) → i32 | 询问当前激活是否获得指定权限;v1 的 index 7 对应 tradingRead。 |
tradingai.log | (i32, i32) → () | 尽力写入 UTF-8 诊断文本,单条最多 64 KiB;当前宿主不持久化日志。 |
tradingai.market_get_candles | (i32, i32, i32, i32, i32, i32) → i32 | 读取宿主预载的 OHLCV 快照;最多 256 根、128 KiB JSON,要求 tradingRead。 |
tradingai.market_get_quote | (i32, i32, i32, i32) → i32 | 复制本次回调可用的报价快照;最多 16 KiB,不发起 guest 网络请求,要求 tradingRead。 |
tradingai.view_set_json | (i32, i32) → i32 | 发布单次 JSON 视图,最多 64 KiB;要求 tradingRead、签名声明 guestOutput 和 ABI v3 feature bit 2。 |
tradingai.event_get_json | (i32, i32) → i32 | 取出本次交互回调的宿主事件,最多 4 MiB;API v2 需要 ABI v3 feature bit 3。 |
tradingai.output_set_json | (i32, i32) → i32 | 提交一个交互输出信封,最多 2 MiB、32 条命令;宿主整批校验,API v2 需要 ABI v3 feature bit 4。 |
29 个异步宿主服务方法
API v2 的两项 Wasm 导入只负责取事件、提交一次输出。网络、存储、图表、 提醒和模型操作通过下表的命令方法执行;每条命令都有独立 id,完成后以 result 事件返回,宿主保留原 workspace 与安装上下文。
| 方法 | 参数形状 | 所需权限 | 结果与范围 |
|---|---|---|---|
storage.read | {} | 内建,仅扩展工作区命名空间 | value、resume_required |
storage.write | {value, acknowledge_resume_required?} | 内建,仅扩展工作区命名空间 | saved;权威工作区事务 |
charts.list | {} | tradingRead | charts[]:chart_id、symbol、timeframe 等 |
charts.open | {chart_id?, symbol, timeframe, source_id?} | chartWrite | 已打开图表的标识与上下文 |
market.read | {chart_id?, symbol, timeframe, source_id?} | tradingRead | 市场证据;已完成 K 线与可选形成中参考值分开 |
market.subscribe | {subscription_id, chart_id?, symbol, timeframe, source_id?} | tradingRead | subscribed;后续通过 market 事件送达 |
market.unsubscribe | {subscription_id} | tradingRead | unsubscribed |
alerts.create | {client_request_id, contribution_id, chart_id, symbol, timeframe, kind, price, second_price?, expires_at, title, message} | alertsWrite | 宿主确认、持久化并标注来源的规则 id |
alerts.list | {} | tradingRead | 仅返回当前扩展拥有的规则 |
alerts.adopt | {plan_id, ids:[...]} | alertsWrite | adopted_ids、rejected_ids;按原生规则定义验证所有权,不能仅凭 guest 提供的 id 接管 |
alerts.enable | {ids:[...], enabled} | alertsWrite | updated;只作用于拥有的规则 |
alerts.remove | {ids:[...]} | alertsWrite | removed;只作用于拥有的规则 |
notifications.publish | {id, title, body, symbol?, timeframe?, payload?} | alertsWrite | published;仅宿主本地通知通道 |
models.settings | {provider:"typesafe"} | languageModel | enabled、model、has_api_key;不返回密钥 |
models.configure | {provider:"typesafe", enabled?, model?, clear_api_key?} | languageModel + secrets | 设置状态;密钥由宿主对话框输入 |
models.test | {provider:"typesafe"} | languageModel + network | connected |
models.decide | {provider:"typesafe", state, questions} | languageModel + network | 宿主类型化决策 JSON |
models.recipe | {recipe, parameters} | languageModel | 关联的完成事件;临时不可信 recipe 在只读会话中运行并校验结果 |
feed.request | {kind, source_id, endpoint, operation?, request_id?, arguments?} | network;trading_economics / mcp 还需 secrets | 宿主控制传输与凭据后的响应;仅 rss、json、trading_economics、mcp 类型 |
feed.credentials | {action, source_id, kind, endpoint} | secrets | 凭据状态;密钥本身不跨宿主边界 |
news.legacy | {} | tradingRead;仅限 tradingai.market_intel | 一次性旧版新闻配置迁移投影;不是通用第三方 API |
news.read | {symbol?, limit?} | tradingRead | 权威工作区新闻投影 |
calendar.read | {from?, to?, country?, limit?} | tradingRead | 权威工作区日历事件投影 |
ui.confirm | {title, message} | 无额外 capability | 宿主确认对话框返回 confirmed |
ui.import | {kind:"market_intel_json"} | fileSystemRead | 宿主文件选择器返回取消状态或最多 1 MiB 的所选 JSON 数据 |
ui.openExternal | {url} | openExternal | 仅由宿主打开 HTTPS URL |
context.read | {} | tradingRead | 当前宿主上下文:symbol、timeframes、watchlist、foreground、now |
context.publish | {enabled, surface_id, title, status, captured_at?, context?} | 无额外 capability;字段按宿主 allow-list 校验 | published;宿主托管的 Workbench 快照 |
assistant.prompt | {prompt, surface_id:"news.overview"} | languageModel | 通过只读 Goose dispatch 路径 accepted |
用命令 id 对应异步结果
Guest 在一次成功 callback 中提交一个输出信封。宿主在后续事件中回传相同 id;若 callback 失败或 trap,输出会被丢弃。
output_set_json{
"api_version": 2,
"views": {
"tradingai.example.panel": {
"type": "column",
"children": [
{ "type": "label", "text": "Loading saved state…" }
]
}
},
"commands": [
{ "id": "load-state-1", "method": "storage.read", "params": {} }
]
}id: load-state-1{
"api_version": 2,
"type": "result",
"context": {
"workspace": "opaque-namespace",
"generation": "opaque-install-generation",
"locale": "zh",
"now": "2026-10-08T00:00:00Z"
},
"data": {
"id": "load-state-1",
"method": "storage.read",
"ok": true,
"result": { "value": null, "resume_required": false }
}
}生产 manifest 必须声明对应的签名 view id。此处示例使用扩展工作区存储; 宿主会检查 capability、数据结构和对象所有权,guest 不会在 Wasm 调用里等待 网络或模型请求完成。
九类声明式贡献
资源包没有入口程序或回调,只能提交受限 JSON 清单。模板描述可供用户发起的 工作流,不能直接代表用户创建对象或启动任意代码。
| 贡献类型 | 宿主行为 | 所需权限 |
|---|---|---|
| 静态视图 | 只包含受限 SDUI 布局和文本,不执行 guest 代码或任意动作。 | 无 |
| 报价视图 | 由宿主读取并渲染 quoteSymbol;扩展不能自行拉行情。 | tradingRead |
watchlistPresets | 用户预览后可导入个人自选列表;导入后成为用户自己的副本。 | 无 |
researchLinks | 用户主动打开经过校验的 HTTPS 地址;扩展不会抓取页面。 | 无 |
scannerPresets | 用户应用固定类型的 smc_watch 配置。 | tradingRead |
indicatorPresets | 对本地 OHLC 计算 SMA、EMA、RSI 或 MACD。 | tradingRead |
automationTemplates | 用户选择内置研究任务,经过工作区授权后创建计划;清单不能带 prompt、脚本或任意工具。 | tradingRead + languageModel |
alertTemplates | 声明固定价格条件模板;用户补齐标的、阈值并确认后才创建原生提醒。 | alertsWrite |
chartAnnotations | 声明 horizontalLine 或 trendLine 模板;用户选择图表坐标并确认后才创建。 | chartWrite |
最小自选列表预设
watchlist preset 只包含市场符号,不读取用户现有列表;预览不会修改账户。
runtime: resource{
"id": "tradingai.example.watchlist",
"name": "Example watchlist",
"version": "1.0.0",
"apiVersion": 1,
"description": "A declarative watchlist preset.",
"publisher": "example-publisher",
"runtime": "resource",
"capabilities": [],
"contributes": {
"watchlistPresets": [
{
"id": "tradingai.example.watchlist.market",
"name": "Market leaders",
"symbols": ["NASDAQ:AAPL", "NASDAQ:MSFT"]
}
]
}
}managedModel 是专用模型协议
源码中的 managedModel 契约不是任意 Python 插件 API。它固定模型、依赖、 哈希清单和本机服务入口,并由宿主管理安装与进程生命周期。
发行记录称该包已上传并获 live Marketplace 审批;完整 GUI 安装、运行时激活及 重启验收仍是独立检查。当前客户端是否支持此包仍需按生产版本核验。
- Publisher
- TradingAI Official
- Protocol
timesfm-http-v1- Transport
- 127.0.0.1 loopback · GET /health · POST /forecast
- 权限范围
- shell、network、tradingRead、chartWrite;宿主核验签名清单
- 研究限制
- 模型权重许可要求仅用于非商业、非生产研究
该 HTTP 服务绑定本机回环地址,不是公开互联网 API。Forecast 是研究证据,不是交易 信号或收益承诺;具体请求/响应字段请以 docs/extensions/timesfm-forecast.md 的 HTTP API 契约为准。
Dart API 与本地进程插件
app 内的 ExtensionApi 与受信任的本地 process 插件都是不同的集成模式; 它们的类型名不表示 Marketplace Wasm guest 可以调用这些对象。
编译进 App 的 ExtensionApi
ExtensionContext.api 提供下列 Dart namespace。这是 app 内扩展 接口;它不是下载包的 Wasm import 契约,也没有证据表明整套 namespace 已作为稳定、 面向第三方的 SDK 发布。
| Namespace | 接口范围 |
|---|---|
window | 消息、quick pick、tree view、状态栏和输出通道。 |
commands | 命令注册与执行。 |
workspace | 配置和扩展级存储。 |
env | 只读应用环境、剪贴板和外部 URL。 |
authentication | 交易所或经纪商凭据会话。 |
lm | AI 分析、情绪和策略评估。 |
trading | 行情、订单、持仓、风险和扫描等交易域接口。 |
automation | 内置 automation 客户端;另含 configuration、ai、tasks、events、artifacts、notifications、actions 七个子域。 |
本地 trusted Dart process
本地开发插件使用 plugin.yaml 与 JSON-RPC。Debug build 默认保留本地 发现;非 debug build 默认关闭,需要显式构建参数 --dart-define=TRADINGAI_TRUSTED_PROCESS_EXTENSIONS_ENABLED=true开启。进程继承当前 OS 用户权限,RPC 权限声明不会限制它直接使用 dart:io,因此只应运行可信代码。
Manifest 声明不等于授权
安装包先经过签名、清单和归档校验。宿主再按用户批准的 capability、当前安装代次、 workspace 和对象归属逐次验证服务命令。
只请求需要的权限
API v1 Wasm 限于 tradingRead。API v2 capability 有 tradingRead、chartWrite、alertsWrite、languageModel、network、secrets、 fileSystemRead 和 openExternal。用户批准范围与 guest 声明都必须通过宿主校验。
兼容目标写进清单
使用匹配的 apiVersion 和 minHostVersion。API 版本、 扩展自身版本、宿主版本和原生 ABI feature bits 含义不同;不要用一个版本号代替另一个。
服务结果始终可失败
快照可能缺失、权限可能被拒绝、上下文可能已切换。处理 error result;宿主会丢弃过期 workspace 结果并对输入、输出和对象所有权重新校验。
本页核对依据
这些是仓库中的实现与协议文档路径,供开发时对照。它们不是对生产部署状态的独立证明。
packages/tradingai_extension_sdk/README.mddocs/extensions/interactive-wasm-v2.mddocs/extensions/resource-packages.mddocs/extensions/architecture.mddocs/extensions/timesfm-forecast.mdlib/extensions/common/wasm_extension_contract.dartlib/extensions/common/interactive_wasm_contract.dartlib/extensions/common/managed_model_extension_contract.dartlib/extensions/common/web_app_extension_contract.dartlib/extensions/api/extension_api.dartAppFlowy-Cloud-main/src/api/marketplace.rs
如何理解“已发布”
Wasm API v2 文档标明 implementation contract;旧架构说明将 Marketplace Wasm API v1 视为第一个 public host API contract。TimesFM 分发文档记录了已审批的 live 版本,同时也列出尚未完成的客户端验收。其余接口应先在生产服务和目标客户端版本中 核验可用性,再对外承诺。