@tansr/serve 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -10
- package/dist/index.d.ts +4591 -3742
- package/dist/index.js +3078 -1171
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -32,6 +32,44 @@ npm install @tansr/serve
|
|
|
32
32
|
(`@tansr/protocol`、`@tansr/i18n`、`@tansr/kernel`、`@tansr/providers`、
|
|
33
33
|
`@tansr/sdk`)已编译内联,恒不外泄安装面。
|
|
34
34
|
|
|
35
|
+
## 系统媒体工具 / System media tools
|
|
36
|
+
|
|
37
|
+
图像生成、视频生成、语音转文字和文字转语音均由内核系统工具执行,工具名为
|
|
38
|
+
`ImageGen`、`VideoGen`、`SpeechToText`、`TextToSpeech`。平台内置会话工厂根据应用能力
|
|
39
|
+
装配它们,并使用 SDK 的平台提供方调用授权模型;`capabilities.platform` 表示平台服务
|
|
40
|
+
授权,不表示独立的“平台工具”类别。平台令牌、模型权限、配额、计费及运行时权限继续生效。
|
|
41
|
+
|
|
42
|
+
Android/iOS 经 `/v2` 会话连接时,模型与系统媒体工具运行在开发者的 serve 进程中,
|
|
43
|
+
手机负责提交输入和展示真实工具事件/媒体产物,不因此取得服务端文件或终端命令权限。
|
|
44
|
+
用户主动录音转写、朗读使用既有音频直连端点;它们与模型调用媒体工具并存,不自动进入聊天历史。
|
|
45
|
+
SDK 进程内集成仍须通过 `tools.builtin` 显式选择四媒体;这与 serve 平台工厂按应用授权装配的入口不同。
|
|
46
|
+
|
|
47
|
+
Image generation, video generation, transcription, and speech synthesis are built-in system tools.
|
|
48
|
+
The platform session factory assembles the authorized tools with platform-backed providers.
|
|
49
|
+
`capabilities.platform` retains its service-authorization meaning. On Android and iOS, these tools
|
|
50
|
+
run in the serve process; the mobile client renders their events and artifacts. User-triggered audio
|
|
51
|
+
operations use the separate direct endpoints and do not fabricate model tool events or chat history.
|
|
52
|
+
|
|
53
|
+
## 会话元数据与开发者登录
|
|
54
|
+
|
|
55
|
+
新构建的 `GET /v2/sessions/:id` 可返回可选的 `meta.context` 和 `meta.media`。
|
|
56
|
+
前者区分下一轮/执行轮模型、真实观测用量及本地上下文预算;后者列出四类媒体的应用授权、
|
|
57
|
+
模型与限制、采样时间。字段缺席表示未知,客户端不能拿累计 token 用量当作当前上下文占用。
|
|
58
|
+
媒体快照是会话装配时的授权目录,实际工具是否装配及执行权限仍以服务端执行为准。
|
|
59
|
+
这次没有增加 HTTP 切模端点,也没有修改已冻结的内核事件协议。
|
|
60
|
+
|
|
61
|
+
`countSpeechCharacters`、`planSpeechInput` 和相关类型从本包公开导出,用于按授权模型的
|
|
62
|
+
`maxChars` 校验或显式分段朗读;示例遇到尚无新出口的已发布包时会提示升级。
|
|
63
|
+
开发者登录服务与平台 app_user 分离:客户端向开发者的 login/refresh 入口取短效访问票,
|
|
64
|
+
serve 的 `authenticate` 验证该票并返回 endUserId,平台 appkey 始终只留在服务端。
|
|
65
|
+
完整远程示例见 `examples/serve-demo`;有界续期不会自动重放音频或聊天 POST。
|
|
66
|
+
|
|
67
|
+
New builds may include optional `meta.context` and `meta.media` in session metadata. Missing fields
|
|
68
|
+
mean unknown. Context estimates and observed billing usage are separate; the media catalog reflects
|
|
69
|
+
the session's assembly-time authorization. Developer login and refresh credentials remain separate
|
|
70
|
+
from platform app_user tokens. The public speech planner uses the authorized model's limit and explicit
|
|
71
|
+
segmentation; authentication recovery never automatically replays paid POST requests.
|
|
72
|
+
|
|
35
73
|
## 集成骨架
|
|
36
74
|
|
|
37
75
|
```ts
|
|
@@ -183,18 +221,24 @@ SSE 连接 reset、在飞轮丢、无收口日志。
|
|
|
183
221
|
(`sse.drainRetryMs`,缺省 10 s,客户端换台后再连);② **等在飞轮**——`/v2` 运行中的
|
|
184
222
|
轮至多等 `timeoutMs` 到终态,到点剩余 `interrupt()`(轮末 store 提交照走,resume 可
|
|
185
223
|
续);③ **flush 落盘**——等全部 fire-and-forget 的 store 提交/建行 settle
|
|
186
|
-
(`createAgentSessionFactory` 的 `flush`);④
|
|
224
|
+
(`createAgentSessionFactory` 的 `flush`);④ **停机**——终结会话(**有界**:在飞 pump 至多等
|
|
225
|
+
`closeAllTimeoutMs`,缺省 5 s、`Infinity` 无界;到点记 `server.close_timeout{face,pending,timeoutMs}`
|
|
226
|
+
后照常继续,永不 settle 的 pump 不再能挂住停机;RF-03)、停监听、掐空闲连接、
|
|
187
227
|
有界等待在飞非 SSE 请求答完(≤ 5 s)再掐残余连接。回执
|
|
188
228
|
`{ completedTurns, abortedTurns, flushedCommits, durationMs }` 可入日志。
|
|
189
229
|
`server.close()` 保持**硬收口**语义(立即中止在飞轮、不等落盘;drain 进行中调用则等
|
|
190
230
|
drain 完成);`/v1` 会话无粗态读面,drain 不等其在飞轮。
|
|
191
231
|
|
|
192
|
-
最小接线——两枚信号共用一个 handler
|
|
232
|
+
最小接线——两枚信号共用一个 handler,幂等位防重复进入;**第二枚信号不要吞掉**,应立即硬退
|
|
233
|
+
(运维按两次 Ctrl+C / 两次 SIGTERM 强停的习惯,吞掉 = 只能等编排器 SIGKILL):
|
|
193
234
|
|
|
194
235
|
```ts
|
|
195
236
|
let stopping = false;
|
|
196
237
|
const shutdown = (signal: NodeJS.Signals): void => {
|
|
197
|
-
if (stopping)
|
|
238
|
+
if (stopping) {
|
|
239
|
+
console.error(`[my-service] ${signal} received again, exiting now`);
|
|
240
|
+
process.exit(2);
|
|
241
|
+
}
|
|
198
242
|
stopping = true;
|
|
199
243
|
console.error(`[my-service] ${signal} received, draining...`);
|
|
200
244
|
server
|
|
@@ -222,10 +266,16 @@ process.on('SIGINT', shutdown);
|
|
|
222
266
|
- **信号要能到达 node**:容器 `CMD`/`ENTRYPOINT` 用 exec 形(JSON 数组)或
|
|
223
267
|
`--init`(tini 作 PID 1 转发),不要 `sh -c "node …"`(sh 当 PID 1 不转发);
|
|
224
268
|
- **退出码由你定**:引擎恒不调 `process.exit`;示例里 `drain()` 成功 `exit(0)`、
|
|
225
|
-
失败 `exit(1)`,与你的进程监督器约定一致即可;`tansr serve`(CLI 形态)
|
|
226
|
-
drain
|
|
227
|
-
|
|
228
|
-
|
|
269
|
+
失败 `exit(1)`,与你的进程监督器约定一致即可;`tansr serve`(CLI 形态)订阅
|
|
270
|
+
SIGINT / SIGTERM / SIGHUP / SIGBREAK,首枚同走 drain(超时经 `TANSR_SERVE_DRAIN_TIMEOUT_MS`
|
|
271
|
+
可配,缺省 30 s),**第二枚立即 `exit(2)`**,整链 drain 超时 + 15 s 未收口亦 `exit(2)`,
|
|
272
|
+
两者都记 `process.hard_exit{signal,reason,budgetMs,elapsedMs,exitCode}`(RF-03;共享组件
|
|
273
|
+
`packages/cli/src/assembly/process-lifecycle.ts`);CLI 形态另把每轮墙钟缺省定为
|
|
274
|
+
`maxTurnWallClockMs = 1800000`(30 min;`TANSR_SERVE_TURN_WALL_CLOCK_MS=0` 停用;审查 #9)——
|
|
275
|
+
库缺省仍不设,嵌入宿主自行决定;
|
|
276
|
+
- **Windows 注记**:`process.on('SIGTERM')` 可注册但系统不会发出、`taskkill /F` 不发任何信号;
|
|
277
|
+
控制台关闭以 SIGHUP 到达且系统只留约 10 s(CLI 形态对 SIGHUP 收口预算恒 ≤ 3 s);SIGBREAK
|
|
278
|
+
(Ctrl+Break)与 SIGINT 同义。本机开发以 Ctrl+C(SIGINT)收束,Linux/容器上 SIGTERM / SIGHUP 都会到;
|
|
229
279
|
- **与 `onTurnEndNotify` 的关系**:优雅关闭期出站通知恒不发(见上文投递纪律),
|
|
230
280
|
客户端靠回连 `Last-Event-ID` / history / resume 追赶。
|
|
231
281
|
- **进程级兜底(十王修案 FX-C-02)**:引擎恒不替你挂 `unhandledRejection` / `uncaughtException`
|
|
@@ -283,7 +333,7 @@ doc/130 R-12 生成律:`pnpm env:example` 再生、`pnpm docs:check` 幂等门;
|
|
|
283
333
|
<!-- env:begin -->
|
|
284
334
|
<!-- 由 packages/server/src/runtime-options.ts 的 SERVE_RUNTIME_ENV 表生成(FX-C-41):`pnpm env:example` 再生,`pnpm docs:check` 幂等门;手改本区段会被门打回 -->
|
|
285
335
|
|
|
286
|
-
全表 **
|
|
336
|
+
全表 **31 键**(键序 = 表声明序;缺席 / 空串 = 库缺省,非法值忽略并告警):
|
|
287
337
|
|
|
288
338
|
| 变量 | 组 | 目标选项 | 形态 | 约束 | 单位 |
|
|
289
339
|
|---|---|---|---|---|---|
|
|
@@ -308,6 +358,7 @@ doc/130 R-12 生成律:`pnpm env:example` 再生、`pnpm docs:check` 幂等门;
|
|
|
308
358
|
| `TANSR_SERVE_UPSTREAM_IDLE_TIMEOUT_MS` | `session` | `session.timeouts.idleTimeoutMs` | int | integer >= 1 | ms |
|
|
309
359
|
| `TANSR_SERVE_UPSTREAM_TOTAL_TIMEOUT_MS` | `session` | `session.timeouts.totalTimeoutMs` | int | integer >= 1 | ms |
|
|
310
360
|
| `TANSR_SERVE_TURN_WALL_CLOCK_MS` | `session` | `session.maxTurnWallClockMs` | int | integer >= 1 | ms |
|
|
361
|
+
| `TANSR_SERVE_HOST_SHELL` | `session` | `session.hostShell` | enum | posix\|powershell | — |
|
|
311
362
|
| `TANSR_SERVE_SSE_MAX_BUFFER_BYTES` | `sse` | `sse.maxBufferBytes` | int | integer >= 1 | bytes |
|
|
312
363
|
| `TANSR_SERVE_SSE_SLOW_POLICY` | `sse` | `sse.onSlowSubscriber` | enum | disconnect\|drop-oldest | — |
|
|
313
364
|
| `TANSR_SERVE_SSE_RETRY_MS` | `sse` | `sse.retryMs` | int | integer >= 0 | ms |
|
|
@@ -318,7 +369,7 @@ doc/130 R-12 生成律:`pnpm env:example` 再生、`pnpm docs:check` 幂等门;
|
|
|
318
369
|
| `TANSR_SERVE_SESSION_MAX_AGE_DAYS` | `factory` | `factory.sessions.retention.maxAgeDays` | int | integer >= 1 | days |
|
|
319
370
|
| `TANSR_SERVE_SESSION_MAX_PER_END_USER` | `factory` | `factory.sessions.retention.maxPerEndUser` | int | integer >= 1 | — |
|
|
320
371
|
|
|
321
|
-
分组:`admission`(4) / `http`(1) / `observability`(2) / `ring`(1) / `governance`(5) / `v2`(1) / `notify`(2) / `upstream`(1) / `session`(
|
|
372
|
+
分组:`admission`(4) / `http`(1) / `observability`(2) / `ring`(1) / `governance`(5) / `v2`(1) / `notify`(2) / `upstream`(1) / `session`(5) / `sse`(3) / `log`(1) / `process`(2) / `factory`(3)。同表生成的部署样例:`packages/server/.env.example`。
|
|
322
373
|
<!-- env:end -->
|
|
323
374
|
|
|
324
375
|
`factory` 组三键语义(表内只列形态与约束):`TANSR_SERVE_CWD_ON_RESUME=current|stored` → `cwdOnResume`,
|
|
@@ -586,7 +637,7 @@ build.upstreamStats?.(); // { tokenMinter: { inflight, queued, mints,
|
|
|
586
637
|
同批铸出的令牌不再同刻进入刷新窗;某 endUser 铸造失败后窗内不再出网(直接回同一错),
|
|
587
638
|
刷新失败但旧令牌仍在时效内直接沿用旧令牌;`warm(endUserIds)` 可在启动期预热。
|
|
588
639
|
- **令牌失效反馈(十王修案 FX-C-15 / R-02)**:平台对携 `x-tansr-app-token` 的请求(模型 exchange / bundle /
|
|
589
|
-
|
|
640
|
+
系统工具的平台提供方)回 `401 { error: { code: 'unauthorized', detail: { reason } } }` 时,刷新 fetch 在**同一请求内**
|
|
590
641
|
`minter.invalidate`(仅当缓存现值仍是本次所携令牌)→ 重铸 → 重发**恰一次**;重试仍 401 则原样交回(每请求至多
|
|
591
642
|
一次重铸,恒不循环)。`reason === 'check_unavailable'`(平台校验依赖瞬态不可用)不失效、不重铸;其余码 /
|
|
592
643
|
403 / 无信封亦不触发。此前吊销令牌后 serve 拿旧令牌 ≈ 55 min 恒 401。计数:`stats().invalidations{reason}`
|