@tansr/sdk
v0.17.0
Published
Tansr public TypeScript SDK: headless agent API (query / createSession / runAgent) + pure protocol type re-exports (public, MIT).
Readme
@tansr/sdk
Tansr 对外 TypeScript SDK:在自己的程序里以 headless 方式驱动 Tansr 智能体—— prompt 进、事件流出,零 UI 依赖。查询环、工具调度、权限引擎、上下文压缩与模型接入 全部来自 tansr 内核(已编译内联进发布产物),你拿到的是与 tansr CLI 同一套 harness, 以库的形态嵌进你的应用。
npm install @tansr/sdk运行时要求:Node ≥ 22.19(Electron ≥ 39,SDK 跑主进程);ESM only;TypeScript
target ≥ ES2022。发布产物 = 单文件 ESM bundle + 单文件 d.ts(未压缩可读);第三方
运行时依赖仅 undici / zod / zod-to-json-schema(+可选 @vscode/ripgrep 检索
加速,装不上自动降级)。
一分钟上手(平台令牌档,终端分发形态)
import { createSession } from '@tansr/sdk';
// 令牌从你的服务端换发(appkey 恒在服务端;终端只持短期令牌)
const session = await createSession({ token, baseUrl: 'https://api.example.com' });
session.send('帮我总结这份合同');
for await (const event of session.events) {
if (event.type === 'msg.text.delta') process.stdout.write(event.text);
}模型目录与授权能力由平台 App 配置下发。系统媒体工具须在 tools.builtin 中显式选择;仅开启平台授权不会让缺省 SDK 会话自动装入收费媒体工具。
应用系统提示词(AP-SP)
平台管理 API 的 systemPrompt 是应用业务角色,systemPromptPolicy 控制与 SDK system 的关系:
| 平台策略 | 未传 system | system 有内容 | system: [] | | --- | --- | --- | --- | | fallback(默认) | 平台 P | SDK S | 无业务段 | | prepend(保留) | 平台 P | P → S | 平台 P |
平台正文未配置时,仅使用 SDK 段。systemAppend 在业务段选定后追加宿主使用指南,不触发覆盖;工具、Skills、MCP 指南仍按已装配能力追加。不要把平台正文再复制进 SDK 参数。session.applicationPrompt 提供实际装配的只读 source/policy,不包含正文。
PUT /v1/apps/{appId}/config 写入 { systemPrompt, systemPromptPolicy },GET /v1/apps/{appId} 的 config 回读;组织管理另传 x-tansr-org。正文最多 16000 Unicode 码点,null/空白清空;策略不接受 null,字段缺席均保留。
P 和 S 同为模型 system 输入,拼接次序不保证冲突指令谁胜出。平台适合公共角色集中维护,SDK 适合动态或版本化场景;有矛盾应修改正文或选择 fallback。权限/裁决/额度不靠提示词强制,正文不能存密钥。
已有令牌档会话在下一新轮前自动核验平台 P/策略,不需重建。每轮 ETag 条件请求绕过装配缓存,工具多步保持同轮快照;先应用新段再计算上下文预算。失败发 application_prompt_refresh_failed 并中止本轮,保留历史、可原会话重试;预检30秒上限且可取消。宿主 S/A、模型和工具权限仍沿原装配生命周期。BYOK/注入 client 不读平台默认,runAgent 需宿主显式调用 resolveApplicationSystem。
完整三档 SDK、Windows Electron、serve、Android/iOS 示例见提示词指南与仓内 doc/90 §4.12。此能力仍须发布包含 AP-SP 的 API 与 SDK/serve,旧版本不识别保留策略。
模型、上下文和图文输入
开发中的新接口须使用包含它们的 SDK 构建;旧 npm 包没有这些接口时,宿主应提示升级。
session.contextState() 和 session.subscribeContext(listener) 提供可序列化快照:
selected 是下一轮模型,active 是运行轮冻结的模型;lastObserved 仅在收到模型用量证据后存在。
currentModel({ active: true }) 查询执行轮模型,空闲时返回当前选择。fallback 只报告已观测到的提供方变化。
budget 包含物理与有效窗口、输入估算、输出/思考预留、剩余量、压缩阈值及设置来源。
未知值为 null;本地输入估算与平台累计计费用量分别展示。
大窗口降到小窗口时,在空闲状态 await session.switchModel(next)。
SDK 保留迁移前原文备份,必要时用源模型分段摘要,核验目标预算并落盘后再提交切换;
图片、工具配对及其前后顺序保留,无法容纳即拒绝。失败或取消不静默截断历史。
modelTransitionBackup() 可取回最近一次迁移备份;需要跨进程恢复时配置 checkpoint/store。
外部压缩管理器需要通过 switchModel(next, { compaction }) 显式提供与目标匹配的配置。
摘要调用可能产生用量;备份不代表摘要语义必然完整,业务关键事实仍应核对。
sendBlocks([{ t: 'image', mime: 'image/png', data: base64 }, { t: 'text', text: '描述图片' }])
提交同一轮图文,返回 started 或带原因的 rejected。忙时由宿主保留整份草稿,不能自动去图重发。
图片需满足格式魔数、单图 3.75 MiB、最多 20 张、总图片 30 MiB 和上下文预算限制;
模型与传输通道都需支持图片。Read 产生的像素随工具结果发送到支持视觉的模型,元数据读取成功不等于模型已看见图片。
planSpeechInput(text, { maxCharacters, segment }) 使用授权模型 maxChars 规划朗读;
汉字按 2、其他 Unicode 码点按 1 估算。超出单次限制须显式允许分段,总上限 32000、最多 32 段。
宿主负责逐段执行、取消和保留产物,已成功或结果不明的收费请求不自动重放。
应用提示词刷新失败提供 reason、stage、retry,继续中止该轮;由宿主换发开发者凭据并决定重试。
The new interfaces above require a build that includes them. contextState() separates the next selected
model, the active turn's frozen model, observed usage, and local context estimates. Unknown values are
null. Await switchModel() while idle to prepare and validate a smaller context before committing;
failure keeps the original history. sendBlocks() submits image and text together and rejects busy
submissions without removing images. Speech planning requires the authorized model's character limit
and explicit segmentation; completed or uncertain paid requests must not be replayed automatically.
三档 API × 三档模型来源
| API | 形态 | 适用 |
|---|---|---|
| query(options) | AsyncGenerator<KernelEvent, QueryResult> | 单轮一问一答,return 值携终值(finalText/usage/历史) |
| createSession(options) | Promise<AgentSession> | 多轮会话:send / events / interrupt / messages / setModel / close |
| runAgent(options) | QueryHandle | 低阶直通:自带 client/executor/tools,零装配 |
| 模型来源 | 传什么 | 适用 |
|---|---|---|
| 令牌档 | { token, baseUrl } | 终端分发(Electron/桌面);能力位由平台治理 |
| 托管档(BYOK) | model: '别名' + 本地 .tansr/settings.json | 自己的服务器/脚本,自带模型 key |
| 注入档 | { client, model } 对象成对 | 测试(scripted client)/自定义接入 |
能力面一览
- 系统工具与业务工具统一入口:
tools: { builtin: [...], custom: [...] }。 系统工具包括文件、命令、网络及多媒体;imageGen、videoGen、speechToText、textToSpeech与其他系统工具一起从tools.builtin选择,执行骨架统一在内核。 SDK 媒体后端由平台提供,受应用授权、模型范围和计量约束。defineTool注册业务函数, 接受 JSON 参数表或 zod schema。旧tools.platform仅为四媒体的弃用兼容别名, 会并入同一内置工具集合并去重,不代表另一层工具; - 联网搜索双位双门:webSearch 工具本体是内置
WebSearch(写在tools.builtin, 旧写法tools.platform报迁移错),后端恒平台通道(按次计费归 App,SDK 恒无 BYO 径)——装配需双位齐开(tools.webSearch工具位 +platform.webSearch通道位)且 令牌档在场;缺席选择时门不备静默不装,显式选择即 fail-fast 分因可读错(详见手册 §5.3); - skills:
defineSkill内联 +dirs目录装载(<name>/SKILL.md),按需装载零 发现(恒不扫用户目录); - MCP 外接:
createMcpHost({ servers })应用级共享 /mcp: { servers }会话级, 配置与业界mcpServers同形; - 渲染管道:
createSessionView(事件流 → 不可变视图快照,structuredClone-safe, Electron IPC 直传)+createNarrator(人类可读日志行);恒不用手拼事件;呈现档 开发者可选:{ delivery: { text: 'stream'|'final', thinking: 'stream'|'final'|'off' } }——文本/思考各自选流式或整段一次性,思考可整体关显(状态派生与工具卡恒不受影响, 缺省全流式零漂移);且可动态切换:view.setDelivery(delivery)块粒度即时生效, 切 off 自动追溯剔除既有思考;生成面思考(产不产/预算)走createSession({ thinking: { budget } })+session.setThinking(…)(下一轮生效), 与呈现档正交(详见手册 §9.1); - 权限:
permission: { mode?, rules?, askUser? }——ask 裁决桥到你的 UI,缺席 fail-closed 降级 deny;令牌档缺省装配控制台任命的裁决人(adjudication?: { posture?, callBudget?, enabled?, endUser? },模式由 kernel 按姿态 × 资格档推导):显式permission.mode即视为自管模式—— 裁决人不装并通报adjudicator_skipped_by_mode(0.12 兼容径);例外:显式adjudication: { … }与permission.mode同现即 throwinvalid_options(真矛盾,fail-fast),静默自管请传adjudication: { enabled: false };变更登记见CHANGELOG.md; - 计量:
cost.usage.updated逐请求;终端自查/v1/my-usage恒无金额字段, 开发者对账/v1/app-usage/by-end-user含金额(恒不代理给终端)。
工具与扩展授权以及平台服务授权均在控制台按 App 配置;字段分别为 capabilities.tools
与 capabilities.platform,键集合由 CAPABILITY_TOOL_KEYS / CAPABILITY_PLATFORM_KEYS
提供。授权合同仍为 17 工具位 + 5 平台位;后者控制平台搜索及四媒体服务的使用权,
不是工具归属分类。位关而显式选择得到
capability_disabled,不静默缺工具。
系统媒体工具示例 / System media tools
const session = await createSession({
token,
baseUrl: 'https://api.example.com',
tools: { builtin: ['imageGen', 'videoGen', 'speechToText', 'textToSpeech'] },
});先在应用配置中授权所需媒体服务与模型。示例只选择四个媒体工具;需要文件、网络等工具时,
也应显式加入同一个 builtin 列表。权限确认、预算与平台计费继续适用。用户主动录音转写或朗读
可以调用 session.platform.transcribe() / .speak();这些是直连操作,不会伪造模型工具事件或自动写入聊天历史。
All four media tools are built-in system tools selected through tools.builtin. The platform supplies
their backend and enforces app permissions, model access, quotas, and billing. The retained
capabilities.platform fields describe service authorization, not a separate tool category.
Media tools require explicit selection; the default SDK tool set does not enable them automatically.
The deprecated tools.platform selection remains an equivalent alias. User-triggered transcription
and speech through session.platform are direct operations, separate from model tool calls.
文档与示例
可等待生命周期(ARC-07,当前源码能力,待配套发布)
idle()、close()、session.ended 维持原有业务语义;它们不证明异步存储、生成器的 finally 或 MCP 传输已经完成。离开页面或退出应用时,检查新的回执:
const result = await session.closeAsync({ timeoutMs: 30_000, flushStore: true });
if (result.status !== 'completed') {
// 保留 session;显示状态/数量即可,不把原始 cause 直接写日志或发给 renderer。
console.warn({ status: result.status, pending: result.pending, failureCount: result.failureCount });
// 稍后继续观察:await session.drain({ timeoutMs: 30_000 });
}drain() 不关闭会话;closeAsync() 先逻辑关闭再等待。超时或 signal 取消的是本次观察,底层清理继续,其他等待者不受影响。默认观察上限 30 秒,0 读取当前状态,Infinity 只用于宿主明确管理的真实依赖链。flushStore 缺省关闭;借用的 store 永不由 SDK 自动 close()。retryPersistence: true 显式重试待修复历史提交,不重放业务回调;不要在自己的 onHistoryCommit 内等待本会话的 drain()。
会话内 mcp: { servers } 由 SDK 所有;传入应用级 McpHost 是借用。共享 host 必须等全部使用它的会话完成后,再由应用 await host.dispose()。cleanupEvidence 中 transport-completion 指本地传输完成层,第三方连接没有 settleClose 时只提供 connector-close-promise,不是任意操作系统子进程或 HTTP 远端退出证明。
query() 提前 break 仍发送中止,并等待真实收尾到 cleanupTimeoutMs(默认 30 秒)。用 onLifecycleError(error) 保留 SdkLifecycleError.cleanup,随后可继续 error.cleanup?.drain();消费者自己抛错时,JavaScript 可能优先保留消费者异常,因此第二条回调通道不可省略。托管/令牌档 query 现可显式传 skills、mcp,能力位及所有权规则与 createSession 相同;注入档仍不隐式装配工具或读取技能目录。
完整规则见 doc/90-SDK技术手册.md §4.13。Electron 真正使用 closeAsync,外层 30 秒观察超时可再次等待;Android/iOS 继续现有 serve 会话协议,手机断线不等于删除会话,真实资源收尾由 Node 宿主负责。
- 技术手册(完整):仓内
doc/90-SDK技术手册.md——安装、三方闭环令牌接入、三档 API、能力位、defineTool/skills/MCP、渲染管道、权限、计量、imageGen、错误码排障、 安全须知; - 官方示例:
examples/token-server(开发者服务端令牌换发样板)、examples/electron-chat(Electron 全形态样板:权限弹框桥 + SessionView 投影 + imageGen 产图渲染); - 平台契约:仓内
doc/89-SDK平台契约v1.md(wire 形态事实源)。
安全一句话
appkey 恒不出你的服务端;终端只持短期令牌(TTL + 平台定向吊销 = 止损面);Electron 里 SDK 与令牌恒在主进程,renderer 只见投影状态。完整安全须知见手册第十四章。
License
MIT(发布产物内联了 tansr 内部 workspace 包的编译产物,同以 MIT 随包分发;见 dist 文件头 NOTICE)。
MEDIA-03 历史媒体恢复
媒体产物随工具回执保存,恢复后的 result 可复用现有媒体组件;artifactUnavailable 单独表示预览不可恢复,不代表工具失败。首次写产物会启用存储版本 2,请统一升级写者并先备份。配置、TS 示例及英文说明见媒体历史恢复 / Media history recovery。本能力已随 @tansr/[email protected] 发布,须同时升级消费端。
