@tansr/sdk 0.4.0 → 0.5.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 +10 -1
- package/dist/index.d.ts +169 -55
- package/dist/index.js +423 -52
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,12 +49,21 @@ for await (const event of session.events) {
|
|
|
49
49
|
——环2 内置本地工具(read/glob/grep/shell/…)、环3 平台托管能力(imageGen 图像
|
|
50
50
|
生成,平台代调按张计费)、环1 `defineTool` 业务函数(注册即说明书,JSON 参数表/
|
|
51
51
|
zod 双档);
|
|
52
|
+
- **联网搜索双位双门**:webSearch 工具本体是内置 `WebSearch`(写在 `tools.builtin`,
|
|
53
|
+
旧写法 `tools.platform` 报迁移错),后端恒平台通道(按次计费归 App,SDK 恒无 BYO
|
|
54
|
+
径)——装配需双位齐开(`tools.webSearch` 工具位 + `platform.webSearch` 通道位)且
|
|
55
|
+
令牌档在场;缺席选择时门不备静默不装,显式选择即 fail-fast 分因可读错(详见手册
|
|
56
|
+
§5.3);
|
|
52
57
|
- **skills**:`defineSkill` 内联 + `dirs` 目录装载(`<name>/SKILL.md`),按需装载零
|
|
53
58
|
发现(恒不扫用户目录);
|
|
54
59
|
- **MCP 外接**:`createMcpHost({ servers })` 应用级共享 / `mcp: { servers }` 会话级,
|
|
55
60
|
配置与业界 `mcpServers` 同形;
|
|
56
61
|
- **渲染管道**:`createSessionView`(事件流 → 不可变视图快照,structuredClone-safe,
|
|
57
|
-
Electron IPC 直传)+ `createNarrator`(人类可读日志行)
|
|
62
|
+
Electron IPC 直传)+ `createNarrator`(人类可读日志行);恒不用手拼事件;呈现档
|
|
63
|
+
开发者可选:`{ delivery: { text: 'stream'|'final', thinking: 'stream'|'final'|'off' } }`
|
|
64
|
+
——文本/思考各自选流式或整段一次性,思考可整体关显(状态派生与工具卡恒不受影响,
|
|
65
|
+
缺省全流式零漂移);且可**动态切换**:`view.setDelivery(delivery)` 块粒度即时生效,
|
|
66
|
+
切 off 自动追溯剔除既有思考(详见手册 §9.1);
|
|
58
67
|
- **权限**:`permission: { mode?, rules?, askUser? }`——ask 裁决桥到你的 UI,缺席
|
|
59
68
|
fail-closed 降级 deny;
|
|
60
69
|
- **计量**:`cost.usage.updated` 逐请求;终端自查 `/v1/my-usage` 恒无金额字段,
|
package/dist/index.d.ts
CHANGED
|
@@ -10087,6 +10087,50 @@ interface Tool<Args = unknown> {
|
|
|
10087
10087
|
execute(args: Args, ctx: ToolContext): Promise<ToolResult>;
|
|
10088
10088
|
}
|
|
10089
10089
|
|
|
10090
|
+
/**
|
|
10091
|
+
* T-D6 — 会话待办台账(内存态,不做持久化)。
|
|
10092
|
+
*
|
|
10093
|
+
* 设计要点:
|
|
10094
|
+
* - `TodoItem` 形状与 protocol `plan.todo.updated` 事件的 items 对齐
|
|
10095
|
+
* (id/content/status 三字段;status 在事件侧是宽松 string,本侧收窄为枚举);
|
|
10096
|
+
* - 依赖注入:`onChange` 由工厂(内核会话装配处)注入,store 本身不发事件、
|
|
10097
|
+
* 不落盘——外部在回调里接线 `plan.todo.updated` 事件与(未来的)持久化;
|
|
10098
|
+
* - 所有对外暴露的数组/对象均为副本,防止调用方或回调持引用后污染内部状态。
|
|
10099
|
+
*/
|
|
10100
|
+
/** 待办状态全集(as const 元组,供 zod enum 与类型共用一份事实源) */
|
|
10101
|
+
declare const TODO_STATUSES: readonly ["pending", "in_progress", "completed", "cancelled"];
|
|
10102
|
+
type TodoStatus = (typeof TODO_STATUSES)[number];
|
|
10103
|
+
interface TodoItem {
|
|
10104
|
+
id: string;
|
|
10105
|
+
content: string;
|
|
10106
|
+
status: TodoStatus;
|
|
10107
|
+
}
|
|
10108
|
+
/**
|
|
10109
|
+
* merge 输入:按 id 定位,已知 id 只覆盖给定字段(未给字段保留原值);
|
|
10110
|
+
* 未知 id 追加为新项,此时 content 与 status 必须齐全(TodoWrite 工具
|
|
10111
|
+
* 的 schema 恒为全量,不会触发缺字段路径;此约束仅防御其他内部调用方)。
|
|
10112
|
+
*/
|
|
10113
|
+
type TodoPatch = {
|
|
10114
|
+
id: string;
|
|
10115
|
+
} & Partial<Omit<TodoItem, 'id'>>;
|
|
10116
|
+
interface TodoStoreOptions {
|
|
10117
|
+
/** 变更回调:replace/merge 每次调用后触发一次,载荷为变更后完整列表的独立副本 */
|
|
10118
|
+
onChange?: (items: TodoItem[]) => void;
|
|
10119
|
+
}
|
|
10120
|
+
declare class TodoStore {
|
|
10121
|
+
#private;
|
|
10122
|
+
constructor(options?: TodoStoreOptions);
|
|
10123
|
+
/** 当前列表(副本;修改返回值不影响内部状态) */
|
|
10124
|
+
list(): TodoItem[];
|
|
10125
|
+
/** 全量替换(含替换为空 = 清空台账),返回变更后快照 */
|
|
10126
|
+
replace(items: readonly TodoItem[]): TodoItem[];
|
|
10127
|
+
/**
|
|
10128
|
+
* 按 id 合并:已知 id 原位覆盖给定字段;未知 id 按提交顺序追加到尾部。
|
|
10129
|
+
* 返回变更后快照。未知 id 缺 content/status 视为调用方契约错误,抛 TypeError。
|
|
10130
|
+
*/
|
|
10131
|
+
merge(patches: readonly TodoPatch[]): TodoItem[];
|
|
10132
|
+
}
|
|
10133
|
+
|
|
10090
10134
|
/**
|
|
10091
10135
|
* T-C1 — 测试用顺序工具执行器(ToolExecutor 的最小实现)。
|
|
10092
10136
|
*
|
|
@@ -10820,50 +10864,6 @@ type OnToolDecision = (record: ToolDecisionRecord) => void;
|
|
|
10820
10864
|
*/
|
|
10821
10865
|
type CaptureFileCheckpoints = (paths: readonly string[]) => Promise<void> | void;
|
|
10822
10866
|
|
|
10823
|
-
/**
|
|
10824
|
-
* T-D6 — 会话待办台账(内存态,不做持久化)。
|
|
10825
|
-
*
|
|
10826
|
-
* 设计要点:
|
|
10827
|
-
* - `TodoItem` 形状与 protocol `plan.todo.updated` 事件的 items 对齐
|
|
10828
|
-
* (id/content/status 三字段;status 在事件侧是宽松 string,本侧收窄为枚举);
|
|
10829
|
-
* - 依赖注入:`onChange` 由工厂(内核会话装配处)注入,store 本身不发事件、
|
|
10830
|
-
* 不落盘——外部在回调里接线 `plan.todo.updated` 事件与(未来的)持久化;
|
|
10831
|
-
* - 所有对外暴露的数组/对象均为副本,防止调用方或回调持引用后污染内部状态。
|
|
10832
|
-
*/
|
|
10833
|
-
/** 待办状态全集(as const 元组,供 zod enum 与类型共用一份事实源) */
|
|
10834
|
-
declare const TODO_STATUSES: readonly ["pending", "in_progress", "completed", "cancelled"];
|
|
10835
|
-
type TodoStatus = (typeof TODO_STATUSES)[number];
|
|
10836
|
-
interface TodoItem {
|
|
10837
|
-
id: string;
|
|
10838
|
-
content: string;
|
|
10839
|
-
status: TodoStatus;
|
|
10840
|
-
}
|
|
10841
|
-
/**
|
|
10842
|
-
* merge 输入:按 id 定位,已知 id 只覆盖给定字段(未给字段保留原值);
|
|
10843
|
-
* 未知 id 追加为新项,此时 content 与 status 必须齐全(TodoWrite 工具
|
|
10844
|
-
* 的 schema 恒为全量,不会触发缺字段路径;此约束仅防御其他内部调用方)。
|
|
10845
|
-
*/
|
|
10846
|
-
type TodoPatch = {
|
|
10847
|
-
id: string;
|
|
10848
|
-
} & Partial<Omit<TodoItem, 'id'>>;
|
|
10849
|
-
interface TodoStoreOptions {
|
|
10850
|
-
/** 变更回调:replace/merge 每次调用后触发一次,载荷为变更后完整列表的独立副本 */
|
|
10851
|
-
onChange?: (items: TodoItem[]) => void;
|
|
10852
|
-
}
|
|
10853
|
-
declare class TodoStore {
|
|
10854
|
-
#private;
|
|
10855
|
-
constructor(options?: TodoStoreOptions);
|
|
10856
|
-
/** 当前列表(副本;修改返回值不影响内部状态) */
|
|
10857
|
-
list(): TodoItem[];
|
|
10858
|
-
/** 全量替换(含替换为空 = 清空台账),返回变更后快照 */
|
|
10859
|
-
replace(items: readonly TodoItem[]): TodoItem[];
|
|
10860
|
-
/**
|
|
10861
|
-
* 按 id 合并:已知 id 原位覆盖给定字段;未知 id 按提交顺序追加到尾部。
|
|
10862
|
-
* 返回变更后快照。未知 id 缺 content/status 视为调用方契约错误,抛 TypeError。
|
|
10863
|
-
*/
|
|
10864
|
-
merge(patches: readonly TodoPatch[]): TodoItem[];
|
|
10865
|
-
}
|
|
10866
|
-
|
|
10867
10867
|
/**
|
|
10868
10868
|
* T-D6 — 交互通道抽象:AskUser 工具与表面层之间的依赖注入缝。
|
|
10869
10869
|
*
|
|
@@ -16293,6 +16293,35 @@ declare class TansrSdkError extends Error {
|
|
|
16293
16293
|
|
|
16294
16294
|
/** 会话即时状态(状态机推导见 deriveStatus;'error' = 最近终态轮以模型错误收场) */
|
|
16295
16295
|
type SessionViewStatus = 'idle' | 'thinking' | 'responding' | 'tooling' | 'awaiting_permission' | 'compacting' | 'error';
|
|
16296
|
+
/** 文本呈现档:'stream' 流式增量(缺省)| 'final' 块定稿整段一次性落 part */
|
|
16297
|
+
type TextDeliveryMode = 'stream' | 'final';
|
|
16298
|
+
/** 思考呈现档:'stream'(缺省)| 'final' | 'off' 恒不物化(状态派生仍见 thinking) */
|
|
16299
|
+
type ThinkingDeliveryMode = 'stream' | 'final' | 'off';
|
|
16300
|
+
/**
|
|
16301
|
+
* 呈现档选项(用户拍板 2026-09-01「呈现方式做成会话选项交给开发者选」):
|
|
16302
|
+
* 恒只影响 text/thinking part 的物化时机与在场性——状态机派生(thinking/
|
|
16303
|
+
* responding 等)与工具卡(本就一次性整卡)恒不受档位影响。缺省全 'stream'
|
|
16304
|
+
* = 既有行为零漂移。
|
|
16305
|
+
*/
|
|
16306
|
+
interface SessionViewDeliveryOptions {
|
|
16307
|
+
/** 文本:'stream'(缺省)边收边显 | 'final' 整段生成完一次性显示 */
|
|
16308
|
+
readonly text?: TextDeliveryMode;
|
|
16309
|
+
/**
|
|
16310
|
+
* 思考:'stream'(缺省)| 'final' 整段定稿一次性 | 'off' 恒不落视图
|
|
16311
|
+
* (宿主仍可据 status==='thinking' 做「正在思考」占位)。此为呈现面开关;
|
|
16312
|
+
* 生成面(是否产生思考/预算)走请求选项 thinking:{budget/off},两旋钮正交。
|
|
16313
|
+
*/
|
|
16314
|
+
readonly thinking?: ThinkingDeliveryMode;
|
|
16315
|
+
}
|
|
16316
|
+
/** SessionView 构造选项(initialSessionViewState / createSessionView / viewStateFromHistory 同形) */
|
|
16317
|
+
interface SessionViewOptions {
|
|
16318
|
+
readonly delivery?: SessionViewDeliveryOptions;
|
|
16319
|
+
}
|
|
16320
|
+
/** 解析后的呈现档(随 internal 落状态,resume 重建径同一份配置继续生效) */
|
|
16321
|
+
interface DeliveryConfig {
|
|
16322
|
+
readonly text: TextDeliveryMode;
|
|
16323
|
+
readonly thinking: ThinkingDeliveryMode;
|
|
16324
|
+
}
|
|
16296
16325
|
/** 工具调用 part 全生命周期状态('aborted' = 轮终态时仍未收口的残留工具) */
|
|
16297
16326
|
type ToolCallPartStatus = 'proposed' | 'awaiting_permission' | 'running' | 'completed' | 'failed' | 'denied' | 'aborted';
|
|
16298
16327
|
interface UITextPart {
|
|
@@ -16384,6 +16413,11 @@ interface BlockTracking {
|
|
|
16384
16413
|
readonly open: boolean;
|
|
16385
16414
|
/** tool_call 块定稿后由 tool.proposed 回填 */
|
|
16386
16415
|
readonly toolCallId?: string;
|
|
16416
|
+
/**
|
|
16417
|
+
* 'final' 呈现档的块内缓冲(delta 恒入此不落 part,块定稿一次性物化;
|
|
16418
|
+
* 键在场 = 本块走 final 档;定稿/撤销后恒清)
|
|
16419
|
+
*/
|
|
16420
|
+
readonly buffer?: string;
|
|
16387
16421
|
}
|
|
16388
16422
|
/** 当前流式 assistant 消息追踪(null = 下一个块开新消息) */
|
|
16389
16423
|
interface CurrentMessageTracking {
|
|
@@ -16394,6 +16428,8 @@ interface CurrentMessageTracking {
|
|
|
16394
16428
|
readonly sealed: boolean;
|
|
16395
16429
|
}
|
|
16396
16430
|
interface ViewInternalState {
|
|
16431
|
+
/** 呈现档配置(构造期定格;turn/settle 恒不重置) */
|
|
16432
|
+
readonly delivery: DeliveryConfig;
|
|
16397
16433
|
readonly running: boolean;
|
|
16398
16434
|
/** session.compacted/microcompacted 置位,下一个被处理事件清位(status 往返) */
|
|
16399
16435
|
readonly compacting: boolean;
|
|
@@ -16416,7 +16452,7 @@ interface SessionViewReducerState {
|
|
|
16416
16452
|
}
|
|
16417
16453
|
/** 工具输出尾部聚合上限(与 TUI OUTPUT_TAIL_MAX_CHARS 同值同语义) */
|
|
16418
16454
|
declare const OUTPUT_TAIL_MAX_CHARS = 4000;
|
|
16419
|
-
declare function initialSessionViewState(): SessionViewReducerState;
|
|
16455
|
+
declare function initialSessionViewState(options?: SessionViewOptions): SessionViewReducerState;
|
|
16420
16456
|
/**
|
|
16421
16457
|
* 纯函数投影:reduce(state, event) => state。
|
|
16422
16458
|
* 未消费的事件(未知 kind / 与视图无关的 kind / 乱序孤儿)返回原引用
|
|
@@ -16429,6 +16465,23 @@ declare function reduceSessionView(state: SessionViewReducerState, event: Kernel
|
|
|
16429
16465
|
* 恒不合成 user 消息——本函数是唯一补充入口,由宿主决定是否使用。
|
|
16430
16466
|
*/
|
|
16431
16467
|
declare function appendUserMessage(state: SessionViewReducerState, text: string): SessionViewReducerState;
|
|
16468
|
+
/**
|
|
16469
|
+
* 动态切换呈现档(纯函数;用户拍板 2026-09-01「留切换入口随时切换」):
|
|
16470
|
+
* 恒**块粒度**生效——已开启的块沿其 block.start 时捕获的形态收尾(缓冲/
|
|
16471
|
+
* 占位/不物化已定格在块登记,恒不中途变形),新块即用新档。恒不追溯已
|
|
16472
|
+
* 物化 part;切 thinking:'off' 要既有思考即刻消失用 stripThinkingParts 配套。
|
|
16473
|
+
* 档位相同恒返回原引用(泵壳零通知)。
|
|
16474
|
+
*/
|
|
16475
|
+
declare function setSessionViewDelivery(state: SessionViewReducerState, delivery: SessionViewDeliveryOptions): SessionViewReducerState;
|
|
16476
|
+
/**
|
|
16477
|
+
* 思考 part 全量剔除(纯函数,追溯型配套件):切到 thinking:'off' 时宿主
|
|
16478
|
+
* 调用本函数让**既有**思考即刻从视图消失(内核历史恒不动,仅视图面;切回
|
|
16479
|
+
* 后恒不能从视图自身复原——宿主自持历史者可经 viewStateFromHistory 重建)。
|
|
16480
|
+
* 滤后空 parts 的非当前消息整条移除;当前流式消息恒保留(空壳与既有同律,
|
|
16481
|
+
* 块登记 partIndex 随删位重映射,被删思考块失联 partIndex 后续 delta 恒
|
|
16482
|
+
* 原引用跳过)。无思考 part 时恒返回原引用。
|
|
16483
|
+
*/
|
|
16484
|
+
declare function stripThinkingParts(state: SessionViewReducerState): SessionViewReducerState;
|
|
16432
16485
|
/**
|
|
16433
16486
|
* 泵壳专用:事件源自身故障(自定义 AsyncIterable 抛错)时的终局错误面
|
|
16434
16487
|
* ——比静默悬挂诚实。AgentSession.events 不抛,本路径只对自定义源可达。
|
|
@@ -16452,7 +16505,7 @@ declare function markSourceFailure(state: SessionViewReducerState, error: unknow
|
|
|
16452
16505
|
* 新增消息恒不撞 id;其余内部簿记与视图字段取初始态(status='idle')。
|
|
16453
16506
|
*/
|
|
16454
16507
|
|
|
16455
|
-
declare function viewStateFromHistory(messages: readonly IRMessage[]): SessionViewReducerState;
|
|
16508
|
+
declare function viewStateFromHistory(messages: readonly IRMessage[], options?: SessionViewOptions): SessionViewReducerState;
|
|
16456
16509
|
|
|
16457
16510
|
/**
|
|
16458
16511
|
* S-B7 — 事件泵(view 内部共享;session-view 与 narrator 同用)。
|
|
@@ -16485,10 +16538,16 @@ interface SessionView {
|
|
|
16485
16538
|
* dispose 后为无害空操作。
|
|
16486
16539
|
*/
|
|
16487
16540
|
appendUserMessage(text: string): void;
|
|
16541
|
+
/**
|
|
16542
|
+
* 动态切换呈现档(块粒度生效:开启中的块按其起始档收尾,新块即用新档)。
|
|
16543
|
+
* 切 thinking:'off' 时既有思考 part 一并即刻剔除(视图不变量:off ⇒ 视图
|
|
16544
|
+
* 恒无思考;内核历史不动,切回后仅影响后续块)。dispose 后为无害空操作。
|
|
16545
|
+
*/
|
|
16546
|
+
setDelivery(delivery: SessionViewDeliveryOptions): void;
|
|
16488
16547
|
/** 停泵并清空订阅(幂等);state 冻结在最后快照 */
|
|
16489
16548
|
dispose(): void;
|
|
16490
16549
|
}
|
|
16491
|
-
declare function createSessionView(source: SessionViewSource): SessionView;
|
|
16550
|
+
declare function createSessionView(source: SessionViewSource, options?: SessionViewOptions): SessionView;
|
|
16492
16551
|
|
|
16493
16552
|
type NarratorVerbosity = 'quiet' | 'normal' | 'verbose';
|
|
16494
16553
|
interface NarratorOptions {
|
|
@@ -16572,9 +16631,15 @@ declare function assemblePlatformModel(options: AssemblePlatformModelOptions): P
|
|
|
16572
16631
|
* 2026-08-29「开 imageGen」)。
|
|
16573
16632
|
*
|
|
16574
16633
|
* 环3 语义(区别于环1 defineTool 函数、环2 内置本地工具):执行不在终端本地
|
|
16575
|
-
* ——工具 execute 经令牌档 fetch 打平台网关
|
|
16576
|
-
* (
|
|
16577
|
-
*
|
|
16634
|
+
* ——工具 execute 经令牌档 fetch 打平台网关(鉴权头 x-tansr-app-token),
|
|
16635
|
+
* 平台代调图像上游(百炼 wan/qwen-image 系),**按成功张数计量计费归 App**
|
|
16636
|
+
* (开发者对终端如何转售自主,计量计费分离)。
|
|
16637
|
+
*
|
|
16638
|
+
* 任务径先行(异步化拍板 2026-09-01,media-task-client.ts;videogen 同构):
|
|
16639
|
+
* POST {baseUrl}/t1/imagegen/tasks 提交即返 taskId → 短请求轮询至终态——预算
|
|
16640
|
+
* 耗尽/中断时 taskId 随错返出,产出可找回(服务端照跑照扣,断连语义 A 不亏)。
|
|
16641
|
+
* 旧版生产无任务端点(404)自动回落 POST {baseUrl}/t1/imagegen 同步径
|
|
16642
|
+
* (0.4.1 逐字同款),判定按工具实例缓存。
|
|
16578
16643
|
*
|
|
16579
16644
|
* 装配面:tools.platform: ['imageGen'] 且 bundle 能力位 platform.imageGen=true
|
|
16580
16645
|
* 时由 buildSdkToolSet 装配(位关 fail-fast 可读错,三环裁剪同例);材料
|
|
@@ -16588,6 +16653,15 @@ declare function assemblePlatformModel(options: AssemblePlatformModelOptions): P
|
|
|
16588
16653
|
|
|
16589
16654
|
/** 生成张数 wire 帽(与网关 TwpImagegenRequestSchema 同值;超模型帽由网关再钳)。 */
|
|
16590
16655
|
declare const IMAGEGEN_TOOL_MAX_N = 4;
|
|
16656
|
+
/**
|
|
16657
|
+
* 客户端硬超时缺省(毫秒;kernel Tool.timeoutMs 位)= 服务端生成预算 120s
|
|
16658
|
+
* (tansr-api IMAGEGEN_DEFAULT_TIMEOUT_MS,解出层全模型恒用此值——含 classic
|
|
16659
|
+
* 万相异步任务与 mj_task midjourney 任务轮询长径)+ 60s 余量(videogen 同口径:
|
|
16660
|
+
* 请求上行/网关前置/响应回传)。kernel 统一档同为 120s、对服务端预算零余量——
|
|
16661
|
+
* 任务径跑满预算时客户端恒先掐(同 videogen 的有扣无产形态,窗口更短),故
|
|
16662
|
+
* 显式声明盖过。
|
|
16663
|
+
*/
|
|
16664
|
+
declare const IMAGEGEN_TOOL_TIMEOUT_MS = 180000;
|
|
16591
16665
|
declare const ImageGenArgsSchema: z.ZodObject<{
|
|
16592
16666
|
model: z.ZodOptional<z.ZodString>;
|
|
16593
16667
|
prompt: z.ZodEffects<z.ZodString, string, string>;
|
|
@@ -16623,6 +16697,12 @@ interface ImageGenData {
|
|
|
16623
16697
|
imageCount: number;
|
|
16624
16698
|
/** 网关错误码(如 forbidden/imagegen_not_configured/model_not_authorized;成功缺席)。 */
|
|
16625
16699
|
errorCode?: string;
|
|
16700
|
+
/**
|
|
16701
|
+
* 异步任务号(异步化拍板 2026-09-01;任务径在场时恒携)。预算耗尽/中断时
|
|
16702
|
+
* 凭此找回产出:GET /t1/imagegen/tasks/{taskId}(服务端照跑照扣,7 天可查)。
|
|
16703
|
+
* 同步回落径(旧版生产)缺席。
|
|
16704
|
+
*/
|
|
16705
|
+
taskId?: string;
|
|
16626
16706
|
}
|
|
16627
16707
|
interface CreateImageGenToolOptions {
|
|
16628
16708
|
/** 平台 API 基址(令牌档会话档;/t1 前缀由本工具追加)。 */
|
|
@@ -16639,6 +16719,12 @@ interface CreateImageGenToolOptions {
|
|
|
16639
16719
|
* 直构/旧径),描述回落通用指引。
|
|
16640
16720
|
*/
|
|
16641
16721
|
models?: readonly AppBundleImageModel[];
|
|
16722
|
+
/**
|
|
16723
|
+
* 客户端硬超时覆盖(毫秒;透传 kernel Tool.timeoutMs)。缺省
|
|
16724
|
+
* IMAGEGEN_TOOL_TIMEOUT_MS(服务端 120s 预算 + 60s 余量)——恒不回落
|
|
16725
|
+
* kernel 120s 统一档(与服务端预算零余量,任务轮询径必先掐)。
|
|
16726
|
+
*/
|
|
16727
|
+
timeoutMs?: number;
|
|
16642
16728
|
}
|
|
16643
16729
|
/**
|
|
16644
16730
|
* 环3 平台图像生成工具(kernel Tool 形态;name 'ImageGen' 沿 kernel PascalCase
|
|
@@ -16652,9 +16738,15 @@ declare function createImageGenTool(options: CreateImageGenToolOptions): Tool<Im
|
|
|
16652
16738
|
* 平台托管能力)。
|
|
16653
16739
|
*
|
|
16654
16740
|
* 环3 语义:执行不在终端本地——工具 execute 经令牌档 fetch 打平台网关
|
|
16655
|
-
*
|
|
16656
|
-
*
|
|
16657
|
-
*
|
|
16741
|
+
* (鉴权头 x-tansr-app-token),平台代调视频上游(百炼 wan 视频系),**按成功
|
|
16742
|
+
* 生成的视频秒数计量计费归 App**(per_second 系上游官方计费单位;开发者对
|
|
16743
|
+
* 终端如何转售自主,计量计费分离)。
|
|
16744
|
+
*
|
|
16745
|
+
* 任务径先行(异步化拍板 2026-09-01,media-task-client.ts):POST
|
|
16746
|
+
* {baseUrl}/t1/videogen/tasks 提交即返 taskId → 短请求轮询至终态——预算耗尽/
|
|
16747
|
+
* 中断时 taskId 随错返出,产出可找回(服务端照跑照扣,断连语义 A 不亏)。
|
|
16748
|
+
* 旧版生产无任务端点(404)自动回落 POST {baseUrl}/t1/videogen 同步长等径
|
|
16749
|
+
* (0.4.1 逐字同款),判定按工具实例缓存。
|
|
16658
16750
|
*
|
|
16659
16751
|
* 装配面:tools.platform: ['videoGen'] 且 bundle 能力位 platform.videoGen=true
|
|
16660
16752
|
* 时由 buildSdkToolSet 装配(位关 fail-fast 可读错);材料(baseUrl/token)
|
|
@@ -16667,6 +16759,16 @@ declare function createImageGenTool(options: CreateImageGenToolOptions): Tool<Im
|
|
|
16667
16759
|
|
|
16668
16760
|
/** 时长 wire 帽(秒;与网关 TwpVideogenRequestSchema 同值;超模型帽由网关再钳)。 */
|
|
16669
16761
|
declare const VIDEOGEN_TOOL_MAX_DURATION = 30;
|
|
16762
|
+
/**
|
|
16763
|
+
* 客户端硬超时缺省(毫秒;kernel Tool.timeoutMs 位)= 服务端轮询预算 600s
|
|
16764
|
+
* (tansr-api VIDEOGEN_DEFAULT_TIMEOUT_MS,解出层全模型恒用此值)+ 60s 余量
|
|
16765
|
+
* (请求上行/网关前置[认证/限流/配额/预扣]/响应回传)。/t1/videogen 系服务端
|
|
16766
|
+
* 同步长等——客户端必须等到服务端先出结论(成功或 upstream_timeout 退款),
|
|
16767
|
+
* 恒不先掐:客户端先超时会复现「服务端成功结算而智能体无产出」的有扣无产
|
|
16768
|
+
* (2026-09-01 定谳:kling-v3 实测 122-185s,kernel 120s 缺省档下结构性必超时,
|
|
16769
|
+
* 三笔 ¥2.40 计 ¥7.20 有扣无产)。
|
|
16770
|
+
*/
|
|
16771
|
+
declare const VIDEOGEN_TOOL_TIMEOUT_MS = 660000;
|
|
16670
16772
|
declare const VideoGenArgsSchema: z.ZodObject<{
|
|
16671
16773
|
model: z.ZodOptional<z.ZodString>;
|
|
16672
16774
|
prompt: z.ZodEffects<z.ZodString, string, string>;
|
|
@@ -16704,6 +16806,12 @@ interface VideoGenData {
|
|
|
16704
16806
|
billedSeconds: number;
|
|
16705
16807
|
/** 网关错误码(如 forbidden/videogen_not_configured/model_not_authorized;成功缺席)。 */
|
|
16706
16808
|
errorCode?: string;
|
|
16809
|
+
/**
|
|
16810
|
+
* 异步任务号(异步化拍板 2026-09-01;任务径在场时恒携)。预算耗尽/中断时
|
|
16811
|
+
* 凭此找回产出:GET /t1/videogen/tasks/{taskId}(服务端照跑照扣,7 天可查)。
|
|
16812
|
+
* 同步回落径(旧版生产)缺席。
|
|
16813
|
+
*/
|
|
16814
|
+
taskId?: string;
|
|
16707
16815
|
}
|
|
16708
16816
|
interface CreateVideoGenToolOptions {
|
|
16709
16817
|
/** 平台 API 基址(令牌档会话档;/t1 前缀由本工具追加)。 */
|
|
@@ -16720,6 +16828,12 @@ interface CreateVideoGenToolOptions {
|
|
|
16720
16828
|
* (注入档直构/旧径),描述回落通用指引。
|
|
16721
16829
|
*/
|
|
16722
16830
|
models?: readonly AppBundleVideoModel[];
|
|
16831
|
+
/**
|
|
16832
|
+
* 客户端硬超时覆盖(毫秒;透传 kernel Tool.timeoutMs)。缺省
|
|
16833
|
+
* VIDEOGEN_TOOL_TIMEOUT_MS(服务端 600s 预算 + 60s 余量)——恒不回落
|
|
16834
|
+
* kernel 120s 统一档(视频生成分钟级,120s 帽结构性必超时)。
|
|
16835
|
+
*/
|
|
16836
|
+
timeoutMs?: number;
|
|
16723
16837
|
}
|
|
16724
16838
|
/**
|
|
16725
16839
|
* 环3 平台视频生成工具(kernel Tool 形态;name 'VideoGen' 沿 kernel PascalCase
|
|
@@ -16795,5 +16909,5 @@ declare function attachSdkTaskTool(toolset: SdkToolsetRef, config: AttachSdkTask
|
|
|
16795
16909
|
*/
|
|
16796
16910
|
declare function subagentModelResolverOf(registry: ProviderRegistry | null): SubagentModelResolver | undefined;
|
|
16797
16911
|
|
|
16798
|
-
export { APP_SDK_CONTRACT_VERSION, APP_TOKEN_PLACEHOLDER_ENV, AgentSession, AppCapabilitiesSchema, AppTokenRequestSchema, AppTokenResponseSchema, DEFAULT_APP_CAPABILITIES, DEFAULT_MAX_TOKENS, DEFAULT_MAX_TURNS, EndUserIdSchema, HEADER_APP_TOKEN, IMAGEGEN_TOOL_MAX_N, ImageGenArgsSchema, McpHost, OUTPUT_TAIL_MAX_CHARS, PLATFORM_SEARCH_PROVIDER_NAME, QueueChannel, SequentialToolExecutor, TANSR_PROVIDER_ID, TOOL_GUIDE_LABEL, TansrSdkError, UnavailableChannel, VIDEOGEN_TOOL_MAX_DURATION, VideoGenArgsSchema, accumulateUsage, appBundleRegistryConfig, appendUserMessage, assembleManagedModel, assemblePlatformModel, assembleSdkSkills, assembleTooling, attachSdkMcp, attachSdkTaskTool, buildClientFromRegistry, buildSdkToolSet, buildToolGuideSegment, createAppTokenFetch, createFileSessionStore, createImageGenTool, createMcpHost, createNarrator, createPlatformSearchProvider, createSdkPermissionGate, createSession, createSessionView, createVideoGenTool, defineSkill, defineTool, initialSessionViewState, markSourceFailure, parseAppBundle, providerSwitchedBody, query, reduceSessionView, resolveBuiltinSelection, resolveInitialMessages, resolvePlatformSelection, runAgent, subagentModelResolverOf, toToolDef, viewStateFromHistory };
|
|
16799
|
-
export type { ActiveToolStatus, Answer, AppBundle, AppBundleImageModel, AppBundleMediaModel, AppBundleModel, AppBundlePlatformModels, AppBundleVideoModel, AppCapabilities, AppTokenRequest, AppTokenResponse, AskUserCallback, AssembleManagedModelOptions, AssemblePlatformModelOptions, AssembleToolingOptions, AssembledManagedModel, AssembledPlatformModel, AssembledSkills, AssembledTooling, AttachSdkTaskToolConfig, BuildSdkToolSetOptions, BuiltinToolName, Capability, CompactNowOptions, CompactNowResult, ConfigDiagnostic, CreateFileSessionStoreOptions, CreateImageGenToolOptions, CreatePlatformSearchProviderOptions, CreateSdkPermissionGateOptions, CreateSessionOptions, CreateVideoGenToolOptions, DecisionSource, DefineSkillOptions, DefineToolOptions, DefinedSkill, DefinedTool, ErrorView, EventBody, EventEnvelope, GateDecision, HistoryCommitMeta, HookOutcomeStatus, IRBlock, IRErrorKind, IRMessage, IRRequest, IRRole, IRStreamEvent, IRSystemSegment, IRToolContent, IRToolDef, IRToolResultBlock, IRUsage, ImageGenArgs, ImageGenData, ImageModelConstraints, Integrity, JournalKind, JournalRecord, KernelEvent, KernelState, LoadConfigOptions, LoadedConfig, ManagedQueryOptions, McpClientEvent, McpConnectFactory, McpConnection, McpEventObserver, McpHostOptions, McpServerConfig, McpSessionOption, ModelCallOptions, ModelClient, Narrator, NarratorOptions, NarratorVerbosity, PermissionDecision, PermissionGate, PermissionMode, PermissionOptions, PermissionRules, PlatformCapabilityName, PlatformToolContext, Pricing, PromptCachingMode, PromptChannel, ProposedToolCall, ProtocolKind, ProviderProfile, QueryCompactionOptions, QueryCounters, QueryHandle, QueryOptions, QueryResult, Question, QuestionOption, ResolvedModel, RunAgentOptions, SdkErrorCode, SdkSkillsOptions, SdkToolSet, SdkToolsOptions, SdkToolsetRef, SequentialToolHandler, SequentialToolResult, SessionEventSource, SessionRecord, SessionRecordMeta, SessionStore, SessionStoreCommitMeta, SessionStoreCreateInit, SessionView, SessionViewReducerState, SessionViewSource, SessionViewState, SessionViewStatus, SetModelBinding, SkillsFileSystem, TansrConfig, TerminalReason, TodoView, Tool, ToolCallPartStatus, ToolCallView, ToolContext, ToolErrorType, ToolExecutionContext, ToolExecutionOutcome, ToolExecutor, ToolExecutorYield, ToolParameterSpec, ToolResult, ToolResultContent, UIMessage, UIMessagePart, UITextPart, UIThinkingPart, UIToolCallPart, UsageView, VideoGenArgs, VideoGenData, VideoModelConstraints, Visibility };
|
|
16912
|
+
export { APP_SDK_CONTRACT_VERSION, APP_TOKEN_PLACEHOLDER_ENV, AgentSession, AppCapabilitiesSchema, AppTokenRequestSchema, AppTokenResponseSchema, DEFAULT_APP_CAPABILITIES, DEFAULT_MAX_TOKENS, DEFAULT_MAX_TURNS, EndUserIdSchema, HEADER_APP_TOKEN, IMAGEGEN_TOOL_MAX_N, IMAGEGEN_TOOL_TIMEOUT_MS, ImageGenArgsSchema, McpHost, OUTPUT_TAIL_MAX_CHARS, PLATFORM_SEARCH_PROVIDER_NAME, QueueChannel, SequentialToolExecutor, TANSR_PROVIDER_ID, TOOL_GUIDE_LABEL, TansrSdkError, UnavailableChannel, VIDEOGEN_TOOL_MAX_DURATION, VIDEOGEN_TOOL_TIMEOUT_MS, VideoGenArgsSchema, accumulateUsage, appBundleRegistryConfig, appendUserMessage, assembleManagedModel, assemblePlatformModel, assembleSdkSkills, assembleTooling, attachSdkMcp, attachSdkTaskTool, buildClientFromRegistry, buildSdkToolSet, buildToolGuideSegment, createAppTokenFetch, createFileSessionStore, createImageGenTool, createMcpHost, createNarrator, createPlatformSearchProvider, createSdkPermissionGate, createSession, createSessionView, createVideoGenTool, defineSkill, defineTool, initialSessionViewState, markSourceFailure, parseAppBundle, providerSwitchedBody, query, reduceSessionView, resolveBuiltinSelection, resolveInitialMessages, resolvePlatformSelection, runAgent, setSessionViewDelivery, stripThinkingParts, subagentModelResolverOf, toToolDef, viewStateFromHistory };
|
|
16913
|
+
export type { ActiveToolStatus, Answer, AppBundle, AppBundleImageModel, AppBundleMediaModel, AppBundleModel, AppBundlePlatformModels, AppBundleVideoModel, AppCapabilities, AppTokenRequest, AppTokenResponse, AskUserCallback, AssembleManagedModelOptions, AssemblePlatformModelOptions, AssembleToolingOptions, AssembledManagedModel, AssembledPlatformModel, AssembledSkills, AssembledTooling, AttachSdkTaskToolConfig, BuildSdkToolSetOptions, BuiltinToolName, Capability, CompactNowOptions, CompactNowResult, ConfigDiagnostic, CreateFileSessionStoreOptions, CreateImageGenToolOptions, CreatePlatformSearchProviderOptions, CreateSdkPermissionGateOptions, CreateSessionOptions, CreateVideoGenToolOptions, DecisionSource, DefineSkillOptions, DefineToolOptions, DefinedSkill, DefinedTool, DeliveryConfig, ErrorView, EventBody, EventEnvelope, GateDecision, HistoryCommitMeta, HookOutcomeStatus, IRBlock, IRErrorKind, IRMessage, IRRequest, IRRole, IRStreamEvent, IRSystemSegment, IRToolContent, IRToolDef, IRToolResultBlock, IRUsage, ImageGenArgs, ImageGenData, ImageModelConstraints, Integrity, JournalKind, JournalRecord, KernelEvent, KernelState, LoadConfigOptions, LoadedConfig, ManagedQueryOptions, McpClientEvent, McpConnectFactory, McpConnection, McpEventObserver, McpHostOptions, McpServerConfig, McpSessionOption, ModelCallOptions, ModelClient, Narrator, NarratorOptions, NarratorVerbosity, PermissionDecision, PermissionGate, PermissionMode, PermissionOptions, PermissionRules, PlatformCapabilityName, PlatformToolContext, Pricing, PromptCachingMode, PromptChannel, ProposedToolCall, ProtocolKind, ProviderProfile, QueryCompactionOptions, QueryCounters, QueryHandle, QueryOptions, QueryResult, Question, QuestionOption, ResolvedModel, RunAgentOptions, SdkErrorCode, SdkSkillsOptions, SdkToolSet, SdkToolsOptions, SdkToolsetRef, SequentialToolHandler, SequentialToolResult, SessionEventSource, SessionRecord, SessionRecordMeta, SessionStore, SessionStoreCommitMeta, SessionStoreCreateInit, SessionView, SessionViewDeliveryOptions, SessionViewOptions, SessionViewReducerState, SessionViewSource, SessionViewState, SessionViewStatus, SetModelBinding, SkillsFileSystem, TansrConfig, TerminalReason, TextDeliveryMode, ThinkingDeliveryMode, TodoView, Tool, ToolCallPartStatus, ToolCallView, ToolContext, ToolErrorType, ToolExecutionContext, ToolExecutionOutcome, ToolExecutor, ToolExecutorYield, ToolParameterSpec, ToolResult, ToolResultContent, UIMessage, UIMessagePart, UITextPart, UIThinkingPart, UIToolCallPart, UsageView, VideoGenArgs, VideoGenData, VideoModelConstraints, Visibility };
|
package/dist/index.js
CHANGED
|
@@ -30850,7 +30850,116 @@ var AppQuotaSchema = z41.object({
|
|
|
30850
30850
|
|
|
30851
30851
|
// src/platform/imagegen-tool.ts
|
|
30852
30852
|
import { z as z42 } from "zod";
|
|
30853
|
+
|
|
30854
|
+
// src/platform/media-task-client.ts
|
|
30855
|
+
var POLL_INTERVAL_MIN_MS = 1;
|
|
30856
|
+
var POLL_INTERVAL_MAX_MS = 6e4;
|
|
30857
|
+
var DEADLINE_MARGIN_MS = 1e4;
|
|
30858
|
+
function sleep(ms, signal) {
|
|
30859
|
+
return new Promise((resolve2) => {
|
|
30860
|
+
if (signal.aborted || ms <= 0) {
|
|
30861
|
+
resolve2();
|
|
30862
|
+
return;
|
|
30863
|
+
}
|
|
30864
|
+
const timer = setTimeout(done, ms);
|
|
30865
|
+
function done() {
|
|
30866
|
+
clearTimeout(timer);
|
|
30867
|
+
signal.removeEventListener("abort", done);
|
|
30868
|
+
resolve2();
|
|
30869
|
+
}
|
|
30870
|
+
signal.addEventListener("abort", done, { once: true });
|
|
30871
|
+
});
|
|
30872
|
+
}
|
|
30873
|
+
function clampPollMs(v, fallback) {
|
|
30874
|
+
if (typeof v !== "number" || !Number.isFinite(v) || v <= 0) return fallback;
|
|
30875
|
+
return Math.min(Math.max(Math.floor(v), POLL_INTERVAL_MIN_MS), POLL_INTERVAL_MAX_MS);
|
|
30876
|
+
}
|
|
30877
|
+
function envelopeCode(raw, status) {
|
|
30878
|
+
const envelope = raw ?? {};
|
|
30879
|
+
const code = typeof envelope.error?.code === "string" ? envelope.error.code : `http_${status}`;
|
|
30880
|
+
const message = typeof envelope.error?.message === "string" ? envelope.error.message : "request rejected";
|
|
30881
|
+
return { code, message };
|
|
30882
|
+
}
|
|
30883
|
+
async function runMediaTask(options) {
|
|
30884
|
+
const { base, face, payload, headers, fetchImpl, signal, budgetMs, defaultPollMs } = options;
|
|
30885
|
+
const startMs = Date.now();
|
|
30886
|
+
const deadlineMs = startMs + Math.max(budgetMs - DEADLINE_MARGIN_MS, Math.floor(budgetMs * 0.8));
|
|
30887
|
+
let response;
|
|
30888
|
+
try {
|
|
30889
|
+
response = await fetchImpl(`${base}/t1/${face}/tasks`, {
|
|
30890
|
+
method: "POST",
|
|
30891
|
+
headers: { "content-type": "application/json", accept: "application/json", ...headers },
|
|
30892
|
+
body: JSON.stringify(payload),
|
|
30893
|
+
signal
|
|
30894
|
+
});
|
|
30895
|
+
} catch (err) {
|
|
30896
|
+
if (signal.aborted) return { kind: "aborted", taskId: null };
|
|
30897
|
+
return { kind: "transport_error", message: err instanceof Error ? err.message : String(err) };
|
|
30898
|
+
}
|
|
30899
|
+
if (response.status === 404) return { kind: "fallback_sync" };
|
|
30900
|
+
let raw = null;
|
|
30901
|
+
try {
|
|
30902
|
+
raw = await response.json();
|
|
30903
|
+
} catch {
|
|
30904
|
+
raw = null;
|
|
30905
|
+
}
|
|
30906
|
+
if (!response.ok) return { kind: "submit_error", status: response.status, raw };
|
|
30907
|
+
const submitted = raw ?? {};
|
|
30908
|
+
if (typeof submitted.taskId !== "string" || submitted.taskId === "") {
|
|
30909
|
+
return { kind: "transport_error", message: "platform accepted the task but returned no taskId (unexpected response)" };
|
|
30910
|
+
}
|
|
30911
|
+
const taskId = submitted.taskId;
|
|
30912
|
+
let pollMs = clampPollMs(submitted.pollIntervalMs, defaultPollMs);
|
|
30913
|
+
const taskUrl = `${base}/t1/${face}/tasks/${taskId}`;
|
|
30914
|
+
for (; ; ) {
|
|
30915
|
+
if (signal.aborted) return { kind: "aborted", taskId };
|
|
30916
|
+
const now = Date.now();
|
|
30917
|
+
if (now >= deadlineMs) return { kind: "deadline", taskId };
|
|
30918
|
+
await sleep(Math.min(pollMs, deadlineMs - now), signal);
|
|
30919
|
+
if (signal.aborted) return { kind: "aborted", taskId };
|
|
30920
|
+
let poll;
|
|
30921
|
+
try {
|
|
30922
|
+
poll = await fetchImpl(taskUrl, { method: "GET", headers: { accept: "application/json", ...headers }, signal });
|
|
30923
|
+
} catch {
|
|
30924
|
+
if (signal.aborted) return { kind: "aborted", taskId };
|
|
30925
|
+
continue;
|
|
30926
|
+
}
|
|
30927
|
+
let body = null;
|
|
30928
|
+
try {
|
|
30929
|
+
body = await poll.json();
|
|
30930
|
+
} catch {
|
|
30931
|
+
body = null;
|
|
30932
|
+
}
|
|
30933
|
+
if (poll.status === 401 || poll.status === 403 || poll.status === 404) {
|
|
30934
|
+
const { code, message } = envelopeCode(body, poll.status);
|
|
30935
|
+
return { kind: "failed", taskId, errorCode: code, message };
|
|
30936
|
+
}
|
|
30937
|
+
if (!poll.ok) continue;
|
|
30938
|
+
const state = body ?? {};
|
|
30939
|
+
if (state.status === "succeeded") {
|
|
30940
|
+
return {
|
|
30941
|
+
kind: "succeeded",
|
|
30942
|
+
taskId,
|
|
30943
|
+
result: state.result,
|
|
30944
|
+
...typeof state.cost === "string" ? { cost: state.cost } : {},
|
|
30945
|
+
...typeof state.currency === "string" ? { currency: state.currency } : {}
|
|
30946
|
+
};
|
|
30947
|
+
}
|
|
30948
|
+
if (state.status === "failed") {
|
|
30949
|
+
return {
|
|
30950
|
+
kind: "failed",
|
|
30951
|
+
taskId,
|
|
30952
|
+
errorCode: typeof state.error?.code === "string" ? state.error.code : "upstream_error",
|
|
30953
|
+
message: typeof state.error?.message === "string" ? state.error.message : "media generation failed"
|
|
30954
|
+
};
|
|
30955
|
+
}
|
|
30956
|
+
pollMs = clampPollMs(state.pollIntervalMs, pollMs);
|
|
30957
|
+
}
|
|
30958
|
+
}
|
|
30959
|
+
|
|
30960
|
+
// src/platform/imagegen-tool.ts
|
|
30853
30961
|
var IMAGEGEN_TOOL_MAX_N = 4;
|
|
30962
|
+
var IMAGEGEN_TOOL_TIMEOUT_MS = 18e4;
|
|
30854
30963
|
var ImageGenArgsSchema = z42.object({
|
|
30855
30964
|
// S-G1(媒体池化顺位取用):Optional——缺席即不发 model 位,网关按授权集顺位
|
|
30856
30965
|
// 第一生效(与 bundle platformModels.imageGen 首行恒同);点名限集内(工具描述自列)。
|
|
@@ -30868,10 +30977,43 @@ var ImageGenArgsSchema = z42.object({
|
|
|
30868
30977
|
"Input images for image editing or reference-conditioned generation (public http(s) URLs or data:image/*;base64 URIs). Only pass this for models whose bracketed note in this description lists imageUrls support; other models reject it."
|
|
30869
30978
|
)
|
|
30870
30979
|
});
|
|
30871
|
-
function errorResult13(text, model, errorCode2) {
|
|
30872
|
-
const data = {
|
|
30980
|
+
function errorResult13(text, model, errorCode2, taskId) {
|
|
30981
|
+
const data = {
|
|
30982
|
+
model,
|
|
30983
|
+
images: [],
|
|
30984
|
+
imageCount: 0,
|
|
30985
|
+
...errorCode2 !== void 0 ? { errorCode: errorCode2 } : {},
|
|
30986
|
+
...taskId !== void 0 ? { taskId } : {}
|
|
30987
|
+
};
|
|
30873
30988
|
return { content: [{ t: "text", text }], isError: true, data };
|
|
30874
30989
|
}
|
|
30990
|
+
function gatewayError(raw, status) {
|
|
30991
|
+
const envelope = raw ?? {};
|
|
30992
|
+
const code = typeof envelope.error?.code === "string" ? envelope.error.code : `http_${status}`;
|
|
30993
|
+
const message = typeof envelope.error?.message === "string" ? envelope.error.message : "request rejected";
|
|
30994
|
+
return { code, message };
|
|
30995
|
+
}
|
|
30996
|
+
function successResult(raw, modelRef, taskId) {
|
|
30997
|
+
const body = raw ?? {};
|
|
30998
|
+
const images = Array.isArray(body.images) ? body.images.map((item) => typeof item.url === "string" ? { url: item.url } : null).filter((item) => item !== null) : [];
|
|
30999
|
+
const imageCount = typeof body.imageCount === "number" ? body.imageCount : images.length;
|
|
31000
|
+
if (images.length === 0) {
|
|
31001
|
+
return errorResult13("Image generation returned no image URL (unexpected platform response).", modelRef, void 0, taskId);
|
|
31002
|
+
}
|
|
31003
|
+
const resolvedModel = typeof body.model === "string" && body.model !== "" ? body.model : modelRef;
|
|
31004
|
+
const data = {
|
|
31005
|
+
model: resolvedModel,
|
|
31006
|
+
images,
|
|
31007
|
+
imageCount,
|
|
31008
|
+
...taskId !== void 0 ? { taskId } : {}
|
|
31009
|
+
};
|
|
31010
|
+
const lines = [
|
|
31011
|
+
`Generated ${imageCount} image(s) with model ${resolvedModel} (billed per image).`,
|
|
31012
|
+
"Image URLs (valid ~24h; surface or persist promptly):",
|
|
31013
|
+
...images.map((img, i) => `${i + 1}. ${img.url}`)
|
|
31014
|
+
];
|
|
31015
|
+
return { content: [{ t: "text", text: lines.join("\n") }], data };
|
|
31016
|
+
}
|
|
30875
31017
|
function hintOf(code) {
|
|
30876
31018
|
if (code === "forbidden") {
|
|
30877
31019
|
return " The app platform capability imageGen is disabled; the app developer can enable it in console → app → capabilities.";
|
|
@@ -30923,13 +31065,18 @@ function createImageGenTool(options) {
|
|
|
30923
31065
|
const base = options.baseUrl.replace(/\/+$/, "");
|
|
30924
31066
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
30925
31067
|
const token = options.token;
|
|
31068
|
+
const budgetMs = options.timeoutMs ?? IMAGEGEN_TOOL_TIMEOUT_MS;
|
|
31069
|
+
let taskRouteMissing = false;
|
|
30926
31070
|
return {
|
|
30927
31071
|
name: "ImageGen",
|
|
30928
|
-
description: "Generates images from a text prompt via the tansr platform (ring-3 hosted capability; the platform calls the image provider and bills the app per generated image). Returns image URLs that stay valid for roughly 24 hours — surface them to the user promptly. Requires the app to have the imageGen platform capability enabled." + authorizedModelsNote(options.models),
|
|
31072
|
+
description: "Generates images from a text prompt via the tansr platform (ring-3 hosted capability; the platform calls the image provider and bills the app per generated image). Some models run as polled tasks and can take a minute or two — client-side wait cap is ~3 minutes. If the cap is ever reached, the error carries a taskId: generation continues server-side (billed on success) and the result stays retrievable for ~7 days — do not resubmit blindly. Returns image URLs that stay valid for roughly 24 hours — surface them to the user promptly. Requires the app to have the imageGen platform capability enabled." + authorizedModelsNote(options.models),
|
|
30929
31073
|
shortDescription: "Generate images from a prompt via the tansr platform (billed per image). Args: model?, prompt, negativePrompt?, size?, n?, seed?, imageUrls?.",
|
|
30930
31074
|
inputSchema: ImageGenArgsSchema,
|
|
30931
31075
|
isReadOnly: false,
|
|
30932
31076
|
isConcurrencySafe: false,
|
|
31077
|
+
// 2026-09-01 定谳修(videogen 同批):服务端预算 120s 与 kernel 120s 缺省档
|
|
31078
|
+
// 零余量,classic/mj_task 任务轮询径跑满预算时客户端恒先掐——声明 180s 盖过。
|
|
31079
|
+
timeoutMs: budgetMs,
|
|
30933
31080
|
async execute(args, ctx) {
|
|
30934
31081
|
const modelRef = args.model ?? "(default)";
|
|
30935
31082
|
if (ctx.signal.aborted) {
|
|
@@ -30944,6 +31091,53 @@ function createImageGenTool(options) {
|
|
|
30944
31091
|
...args.seed !== void 0 ? { seed: args.seed } : {},
|
|
30945
31092
|
...args.imageUrls !== void 0 ? { imageUrls: args.imageUrls } : {}
|
|
30946
31093
|
};
|
|
31094
|
+
if (!taskRouteMissing) {
|
|
31095
|
+
const outcome = await runMediaTask({
|
|
31096
|
+
base,
|
|
31097
|
+
face: "imagegen",
|
|
31098
|
+
payload,
|
|
31099
|
+
headers: { [HEADER_APP_TOKEN]: token },
|
|
31100
|
+
fetchImpl,
|
|
31101
|
+
signal: ctx.signal,
|
|
31102
|
+
budgetMs,
|
|
31103
|
+
defaultPollMs: 2e3
|
|
31104
|
+
});
|
|
31105
|
+
if (outcome.kind === "succeeded") {
|
|
31106
|
+
return successResult(outcome.result, modelRef, outcome.taskId);
|
|
31107
|
+
}
|
|
31108
|
+
if (outcome.kind === "failed") {
|
|
31109
|
+
return errorResult13(
|
|
31110
|
+
`Image generation failed (${outcome.errorCode}): ${outcome.message}.${hintOf(outcome.errorCode)} (taskId: ${outcome.taskId})`,
|
|
31111
|
+
modelRef,
|
|
31112
|
+
outcome.errorCode,
|
|
31113
|
+
outcome.taskId
|
|
31114
|
+
);
|
|
31115
|
+
}
|
|
31116
|
+
if (outcome.kind === "submit_error") {
|
|
31117
|
+
const { code, message } = gatewayError(outcome.raw, outcome.status);
|
|
31118
|
+
return errorResult13(`Image generation failed (${code}): ${message}.${hintOf(code)}`, modelRef, code);
|
|
31119
|
+
}
|
|
31120
|
+
if (outcome.kind === "transport_error") {
|
|
31121
|
+
return errorResult13(`Image generation request failed to reach the platform: ${outcome.message}`, modelRef);
|
|
31122
|
+
}
|
|
31123
|
+
if (outcome.kind === "deadline") {
|
|
31124
|
+
return errorResult13(
|
|
31125
|
+
`Image generation is still running server-side (taskId: ${outcome.taskId}) — the client-side wait cap was reached. The task keeps running and is billed only on success; do not resubmit blindly. Retrieve the result later via GET ${base}/t1/imagegen/tasks/${outcome.taskId} (task retrievable ~7 days; image URLs expire ~24h after completion).`,
|
|
31126
|
+
modelRef,
|
|
31127
|
+
"task_pending",
|
|
31128
|
+
outcome.taskId
|
|
31129
|
+
);
|
|
31130
|
+
}
|
|
31131
|
+
if (outcome.kind === "aborted") {
|
|
31132
|
+
return errorResult13(
|
|
31133
|
+
outcome.taskId === null ? "Tool execution was aborted." : `Tool execution was aborted. Image generation may still complete server-side (billed on success) — retrieve via GET ${base}/t1/imagegen/tasks/${outcome.taskId} (retrievable ~7 days). (taskId: ${outcome.taskId})`,
|
|
31134
|
+
modelRef,
|
|
31135
|
+
void 0,
|
|
31136
|
+
outcome.taskId ?? void 0
|
|
31137
|
+
);
|
|
31138
|
+
}
|
|
31139
|
+
taskRouteMissing = true;
|
|
31140
|
+
}
|
|
30947
31141
|
let response;
|
|
30948
31142
|
try {
|
|
30949
31143
|
response = await fetchImpl(`${base}/t1/imagegen`, {
|
|
@@ -30968,25 +31162,10 @@ function createImageGenTool(options) {
|
|
|
30968
31162
|
raw = null;
|
|
30969
31163
|
}
|
|
30970
31164
|
if (!response.ok) {
|
|
30971
|
-
const
|
|
30972
|
-
const code = typeof envelope.error?.code === "string" ? envelope.error.code : `http_${response.status}`;
|
|
30973
|
-
const message = typeof envelope.error?.message === "string" ? envelope.error.message : "request rejected";
|
|
31165
|
+
const { code, message } = gatewayError(raw, response.status);
|
|
30974
31166
|
return errorResult13(`Image generation failed (${code}): ${message}.${hintOf(code)}`, modelRef, code);
|
|
30975
31167
|
}
|
|
30976
|
-
|
|
30977
|
-
const images = Array.isArray(body.images) ? body.images.map((item) => typeof item.url === "string" ? { url: item.url } : null).filter((item) => item !== null) : [];
|
|
30978
|
-
const imageCount = typeof body.imageCount === "number" ? body.imageCount : images.length;
|
|
30979
|
-
if (images.length === 0) {
|
|
30980
|
-
return errorResult13("Image generation returned no image URL (unexpected platform response).", modelRef);
|
|
30981
|
-
}
|
|
30982
|
-
const resolvedModel = typeof body.model === "string" && body.model !== "" ? body.model : modelRef;
|
|
30983
|
-
const data = { model: resolvedModel, images, imageCount };
|
|
30984
|
-
const lines = [
|
|
30985
|
-
`Generated ${imageCount} image(s) with model ${resolvedModel} (billed per image).`,
|
|
30986
|
-
"Image URLs (valid ~24h; surface or persist promptly):",
|
|
30987
|
-
...images.map((img, i) => `${i + 1}. ${img.url}`)
|
|
30988
|
-
];
|
|
30989
|
-
return { content: [{ t: "text", text: lines.join("\n") }], data };
|
|
31168
|
+
return successResult(raw, modelRef);
|
|
30990
31169
|
}
|
|
30991
31170
|
};
|
|
30992
31171
|
}
|
|
@@ -30994,6 +31173,7 @@ function createImageGenTool(options) {
|
|
|
30994
31173
|
// src/platform/videogen-tool.ts
|
|
30995
31174
|
import { z as z43 } from "zod";
|
|
30996
31175
|
var VIDEOGEN_TOOL_MAX_DURATION = 30;
|
|
31176
|
+
var VIDEOGEN_TOOL_TIMEOUT_MS = 66e4;
|
|
30997
31177
|
var VideoGenArgsSchema = z43.object({
|
|
30998
31178
|
// S-G1(媒体池化顺位取用):Optional——缺席即不发 model 位,网关按授权集顺位
|
|
30999
31179
|
// 第一生效(与 bundle platformModels.videoGen 首行恒同);点名限集内(工具描述自列)。
|
|
@@ -31014,16 +31194,46 @@ var VideoGenArgsSchema = z43.object({
|
|
|
31014
31194
|
'First-frame image(s) for image-to-video generation (public http(s) URL or data:image/*;base64 URI). REQUIRED for models marked "image-to-video ONLY" in this description (generate or obtain an image first, e.g. via the ImageGen tool); rejected by text-to-video-only models.'
|
|
31015
31195
|
)
|
|
31016
31196
|
});
|
|
31017
|
-
function errorResult14(text, model, errorCode2) {
|
|
31197
|
+
function errorResult14(text, model, errorCode2, taskId) {
|
|
31018
31198
|
const data = {
|
|
31019
31199
|
model,
|
|
31020
31200
|
videos: [],
|
|
31021
31201
|
videoCount: 0,
|
|
31022
31202
|
billedSeconds: 0,
|
|
31023
|
-
...errorCode2 !== void 0 ? { errorCode: errorCode2 } : {}
|
|
31203
|
+
...errorCode2 !== void 0 ? { errorCode: errorCode2 } : {},
|
|
31204
|
+
...taskId !== void 0 ? { taskId } : {}
|
|
31024
31205
|
};
|
|
31025
31206
|
return { content: [{ t: "text", text }], isError: true, data };
|
|
31026
31207
|
}
|
|
31208
|
+
function gatewayError2(raw, status) {
|
|
31209
|
+
const envelope = raw ?? {};
|
|
31210
|
+
const code = typeof envelope.error?.code === "string" ? envelope.error.code : `http_${status}`;
|
|
31211
|
+
const message = typeof envelope.error?.message === "string" ? envelope.error.message : "request rejected";
|
|
31212
|
+
return { code, message };
|
|
31213
|
+
}
|
|
31214
|
+
function successResult2(raw, modelRef, taskId) {
|
|
31215
|
+
const body = raw ?? {};
|
|
31216
|
+
const videos = Array.isArray(body.videos) ? body.videos.map((item) => typeof item.url === "string" ? { url: item.url } : null).filter((item) => item !== null) : [];
|
|
31217
|
+
if (videos.length === 0) {
|
|
31218
|
+
return errorResult14("Video generation returned no video URL (unexpected platform response).", modelRef, void 0, taskId);
|
|
31219
|
+
}
|
|
31220
|
+
const videoCount = typeof body.videoCount === "number" ? body.videoCount : videos.length;
|
|
31221
|
+
const billedSeconds = typeof body.billedSeconds === "number" ? body.billedSeconds : 0;
|
|
31222
|
+
const resolvedModel = typeof body.model === "string" && body.model !== "" ? body.model : modelRef;
|
|
31223
|
+
const data = {
|
|
31224
|
+
model: resolvedModel,
|
|
31225
|
+
videos,
|
|
31226
|
+
videoCount,
|
|
31227
|
+
billedSeconds,
|
|
31228
|
+
...taskId !== void 0 ? { taskId } : {}
|
|
31229
|
+
};
|
|
31230
|
+
const lines = [
|
|
31231
|
+
`Generated ${videoCount} video(s) with model ${resolvedModel} (${billedSeconds}s billed, per-second pricing).`,
|
|
31232
|
+
"Video URLs (valid ~24h; surface or persist promptly):",
|
|
31233
|
+
...videos.map((v, i) => `${i + 1}. ${v.url}`)
|
|
31234
|
+
];
|
|
31235
|
+
return { content: [{ t: "text", text: lines.join("\n") }], data };
|
|
31236
|
+
}
|
|
31027
31237
|
function hintOf2(code) {
|
|
31028
31238
|
if (code === "forbidden") {
|
|
31029
31239
|
return " The app platform capability videoGen is disabled; the app developer can enable it in console → app → capabilities.";
|
|
@@ -31082,13 +31292,19 @@ function createVideoGenTool(options) {
|
|
|
31082
31292
|
const base = options.baseUrl.replace(/\/+$/, "");
|
|
31083
31293
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
31084
31294
|
const token = options.token;
|
|
31295
|
+
const budgetMs = options.timeoutMs ?? VIDEOGEN_TOOL_TIMEOUT_MS;
|
|
31296
|
+
let taskRouteMissing = false;
|
|
31085
31297
|
return {
|
|
31086
31298
|
name: "VideoGen",
|
|
31087
|
-
description: "Generates a short video from a text prompt via the tansr platform (ring-3 hosted capability; the platform calls the video provider and bills the app per second of generated video). Generation is a long-running task (often minutes). Returns a video URL that stays valid for roughly 24 hours — surface it to the user promptly. Requires the app to have the videoGen platform capability enabled." + authorizedModelsNote2(options.models),
|
|
31299
|
+
description: "Generates a short video from a text prompt via the tansr platform (ring-3 hosted capability; the platform calls the video provider and bills the app per second of generated video). Generation is a long-running task (often minutes). This call waits for the result — client-side wait cap is ~11 minutes; do not abort or retry early. If the cap is ever reached, the error carries a taskId: generation continues server-side (billed on success) and the result stays retrievable for ~7 days — do not resubmit blindly. Returns a video URL that stays valid for roughly 24 hours — surface it to the user promptly. Requires the app to have the videoGen platform capability enabled." + authorizedModelsNote2(options.models),
|
|
31088
31300
|
shortDescription: "Generate a video from a prompt via the tansr platform (billed per second). Args: model?, prompt, negativePrompt?, duration?, ratio?, seed?, imageUrls?.",
|
|
31089
31301
|
inputSchema: VideoGenArgsSchema,
|
|
31090
31302
|
isReadOnly: false,
|
|
31091
31303
|
isConcurrencySafe: false,
|
|
31304
|
+
// 2026-09-01 定谳修:/t1/videogen 系服务端同步长等(600s 轮询预算),kernel
|
|
31305
|
+
// 120s 缺省档下分钟级任务结构性必超时且有扣无产——工具级声明盖过缺省档
|
|
31306
|
+
// (kernel 全局档恒不动;dispatching-tool-executor timeoutMs>0 即生效)。
|
|
31307
|
+
timeoutMs: budgetMs,
|
|
31092
31308
|
async execute(args, ctx) {
|
|
31093
31309
|
const modelRef = args.model ?? "(default)";
|
|
31094
31310
|
if (ctx.signal.aborted) {
|
|
@@ -31103,6 +31319,53 @@ function createVideoGenTool(options) {
|
|
|
31103
31319
|
...args.seed !== void 0 ? { seed: args.seed } : {},
|
|
31104
31320
|
...args.imageUrls !== void 0 ? { imageUrls: args.imageUrls } : {}
|
|
31105
31321
|
};
|
|
31322
|
+
if (!taskRouteMissing) {
|
|
31323
|
+
const outcome = await runMediaTask({
|
|
31324
|
+
base,
|
|
31325
|
+
face: "videogen",
|
|
31326
|
+
payload,
|
|
31327
|
+
headers: { [HEADER_APP_TOKEN]: token },
|
|
31328
|
+
fetchImpl,
|
|
31329
|
+
signal: ctx.signal,
|
|
31330
|
+
budgetMs,
|
|
31331
|
+
defaultPollMs: 5e3
|
|
31332
|
+
});
|
|
31333
|
+
if (outcome.kind === "succeeded") {
|
|
31334
|
+
return successResult2(outcome.result, modelRef, outcome.taskId);
|
|
31335
|
+
}
|
|
31336
|
+
if (outcome.kind === "failed") {
|
|
31337
|
+
return errorResult14(
|
|
31338
|
+
`Video generation failed (${outcome.errorCode}): ${outcome.message}.${hintOf2(outcome.errorCode)} (taskId: ${outcome.taskId})`,
|
|
31339
|
+
modelRef,
|
|
31340
|
+
outcome.errorCode,
|
|
31341
|
+
outcome.taskId
|
|
31342
|
+
);
|
|
31343
|
+
}
|
|
31344
|
+
if (outcome.kind === "submit_error") {
|
|
31345
|
+
const { code, message } = gatewayError2(outcome.raw, outcome.status);
|
|
31346
|
+
return errorResult14(`Video generation failed (${code}): ${message}.${hintOf2(code)}`, modelRef, code);
|
|
31347
|
+
}
|
|
31348
|
+
if (outcome.kind === "transport_error") {
|
|
31349
|
+
return errorResult14(`Video generation request failed to reach the platform: ${outcome.message}`, modelRef);
|
|
31350
|
+
}
|
|
31351
|
+
if (outcome.kind === "deadline") {
|
|
31352
|
+
return errorResult14(
|
|
31353
|
+
`Video generation is still running server-side (taskId: ${outcome.taskId}) — the client-side wait cap was reached. The task keeps running and is billed only on success; do not resubmit blindly. Retrieve the result later via GET ${base}/t1/videogen/tasks/${outcome.taskId} (task retrievable ~7 days; video URLs expire ~24h after completion).`,
|
|
31354
|
+
modelRef,
|
|
31355
|
+
"task_pending",
|
|
31356
|
+
outcome.taskId
|
|
31357
|
+
);
|
|
31358
|
+
}
|
|
31359
|
+
if (outcome.kind === "aborted") {
|
|
31360
|
+
return errorResult14(
|
|
31361
|
+
outcome.taskId === null ? "Tool execution was aborted." : `Tool execution was aborted. Video generation may still complete server-side (billed on success) — retrieve via GET ${base}/t1/videogen/tasks/${outcome.taskId} (retrievable ~7 days). (taskId: ${outcome.taskId})`,
|
|
31362
|
+
modelRef,
|
|
31363
|
+
void 0,
|
|
31364
|
+
outcome.taskId ?? void 0
|
|
31365
|
+
);
|
|
31366
|
+
}
|
|
31367
|
+
taskRouteMissing = true;
|
|
31368
|
+
}
|
|
31106
31369
|
let response;
|
|
31107
31370
|
try {
|
|
31108
31371
|
response = await fetchImpl(`${base}/t1/videogen`, {
|
|
@@ -31127,26 +31390,10 @@ function createVideoGenTool(options) {
|
|
|
31127
31390
|
raw = null;
|
|
31128
31391
|
}
|
|
31129
31392
|
if (!response.ok) {
|
|
31130
|
-
const
|
|
31131
|
-
const code = typeof envelope.error?.code === "string" ? envelope.error.code : `http_${response.status}`;
|
|
31132
|
-
const message = typeof envelope.error?.message === "string" ? envelope.error.message : "request rejected";
|
|
31393
|
+
const { code, message } = gatewayError2(raw, response.status);
|
|
31133
31394
|
return errorResult14(`Video generation failed (${code}): ${message}.${hintOf2(code)}`, modelRef, code);
|
|
31134
31395
|
}
|
|
31135
|
-
|
|
31136
|
-
const videos = Array.isArray(body.videos) ? body.videos.map((item) => typeof item.url === "string" ? { url: item.url } : null).filter((item) => item !== null) : [];
|
|
31137
|
-
if (videos.length === 0) {
|
|
31138
|
-
return errorResult14("Video generation returned no video URL (unexpected platform response).", modelRef);
|
|
31139
|
-
}
|
|
31140
|
-
const videoCount = typeof body.videoCount === "number" ? body.videoCount : videos.length;
|
|
31141
|
-
const billedSeconds = typeof body.billedSeconds === "number" ? body.billedSeconds : 0;
|
|
31142
|
-
const resolvedModel = typeof body.model === "string" && body.model !== "" ? body.model : modelRef;
|
|
31143
|
-
const data = { model: resolvedModel, videos, videoCount, billedSeconds };
|
|
31144
|
-
const lines = [
|
|
31145
|
-
`Generated ${videoCount} video(s) with model ${resolvedModel} (${billedSeconds}s billed, per-second pricing).`,
|
|
31146
|
-
"Video URLs (valid ~24h; surface or persist promptly):",
|
|
31147
|
-
...videos.map((v, i) => `${i + 1}. ${v.url}`)
|
|
31148
|
-
];
|
|
31149
|
-
return { content: [{ t: "text", text: lines.join("\n") }], data };
|
|
31396
|
+
return successResult2(raw, modelRef);
|
|
31150
31397
|
}
|
|
31151
31398
|
};
|
|
31152
31399
|
}
|
|
@@ -32050,7 +32297,7 @@ function toolCallIds(message) {
|
|
|
32050
32297
|
function toolResultIds(message) {
|
|
32051
32298
|
return message.blocks.flatMap((b) => b.t === "tool_result" ? [b.callId] : []);
|
|
32052
32299
|
}
|
|
32053
|
-
function
|
|
32300
|
+
function repairHistoryPairing2(messages) {
|
|
32054
32301
|
const open4 = /* @__PURE__ */ new Set();
|
|
32055
32302
|
let cleanEnd = 0;
|
|
32056
32303
|
for (let i = 0; i < messages.length; i++) {
|
|
@@ -32409,7 +32656,7 @@ async function createSession(options = {}) {
|
|
|
32409
32656
|
`createSession: session "${options.resume.sessionId}" was not found in the given store; list() the store or create a fresh session instead.`
|
|
32410
32657
|
);
|
|
32411
32658
|
}
|
|
32412
|
-
initialMessages =
|
|
32659
|
+
initialMessages = repairHistoryPairing2(record.messages).messages;
|
|
32413
32660
|
}
|
|
32414
32661
|
const platformSessionId = tokenTier ? ulid() : void 0;
|
|
32415
32662
|
let sessionRef = null;
|
|
@@ -32821,8 +33068,14 @@ function createFileSessionStore(options) {
|
|
|
32821
33068
|
}
|
|
32822
33069
|
|
|
32823
33070
|
// src/view/reducer.ts
|
|
33071
|
+
function resolveDelivery(options) {
|
|
33072
|
+
return {
|
|
33073
|
+
text: options?.delivery?.text ?? "stream",
|
|
33074
|
+
thinking: options?.delivery?.thinking ?? "stream"
|
|
33075
|
+
};
|
|
33076
|
+
}
|
|
32824
33077
|
var OUTPUT_TAIL_MAX_CHARS = 4e3;
|
|
32825
|
-
function initialSessionViewState() {
|
|
33078
|
+
function initialSessionViewState(options) {
|
|
32826
33079
|
return {
|
|
32827
33080
|
view: {
|
|
32828
33081
|
status: "idle",
|
|
@@ -32832,6 +33085,7 @@ function initialSessionViewState() {
|
|
|
32832
33085
|
usage: { turnTokens: 0, sessionTokens: 0, requests: 0 }
|
|
32833
33086
|
},
|
|
32834
33087
|
internal: {
|
|
33088
|
+
delivery: resolveDelivery(options),
|
|
32835
33089
|
running: false,
|
|
32836
33090
|
compacting: false,
|
|
32837
33091
|
lastTurnFailed: false,
|
|
@@ -33065,6 +33319,22 @@ function reduceBody(draft, event) {
|
|
|
33065
33319
|
}
|
|
33066
33320
|
const tracking = next.internal.current;
|
|
33067
33321
|
if (event.blockType === "text" || event.blockType === "thinking") {
|
|
33322
|
+
const mode = event.blockType === "thinking" ? next.internal.delivery.thinking : next.internal.delivery.text;
|
|
33323
|
+
if (mode === "off") {
|
|
33324
|
+
return {
|
|
33325
|
+
...next,
|
|
33326
|
+
internal: {
|
|
33327
|
+
...next.internal,
|
|
33328
|
+
current: {
|
|
33329
|
+
...tracking,
|
|
33330
|
+
blocks: {
|
|
33331
|
+
...tracking.blocks,
|
|
33332
|
+
[event.index]: { blockType: event.blockType, open: true }
|
|
33333
|
+
}
|
|
33334
|
+
}
|
|
33335
|
+
}
|
|
33336
|
+
};
|
|
33337
|
+
}
|
|
33068
33338
|
const appended = appendPart(next, messageId, { type: event.blockType, text: "" });
|
|
33069
33339
|
next = appended.draft;
|
|
33070
33340
|
return {
|
|
@@ -33078,7 +33348,8 @@ function reduceBody(draft, event) {
|
|
|
33078
33348
|
[event.index]: {
|
|
33079
33349
|
blockType: event.blockType,
|
|
33080
33350
|
partIndex: appended.partIndex,
|
|
33081
|
-
open: true
|
|
33351
|
+
open: true,
|
|
33352
|
+
...mode === "final" ? { buffer: "" } : {}
|
|
33082
33353
|
}
|
|
33083
33354
|
}
|
|
33084
33355
|
}
|
|
@@ -33104,7 +33375,23 @@ function reduceBody(draft, event) {
|
|
|
33104
33375
|
const current = draft.internal.current;
|
|
33105
33376
|
if (current === null) return null;
|
|
33106
33377
|
const tracking = current.blocks[event.index];
|
|
33107
|
-
if (tracking === void 0
|
|
33378
|
+
if (tracking === void 0) return null;
|
|
33379
|
+
if (tracking.buffer !== void 0) {
|
|
33380
|
+
return {
|
|
33381
|
+
...draft,
|
|
33382
|
+
internal: {
|
|
33383
|
+
...draft.internal,
|
|
33384
|
+
current: {
|
|
33385
|
+
...current,
|
|
33386
|
+
blocks: {
|
|
33387
|
+
...current.blocks,
|
|
33388
|
+
[event.index]: { ...tracking, buffer: tracking.buffer + event.text }
|
|
33389
|
+
}
|
|
33390
|
+
}
|
|
33391
|
+
}
|
|
33392
|
+
};
|
|
33393
|
+
}
|
|
33394
|
+
if (tracking.partIndex === void 0) return null;
|
|
33108
33395
|
const view = withPartAt(
|
|
33109
33396
|
draft.view,
|
|
33110
33397
|
current.messageId,
|
|
@@ -33119,9 +33406,22 @@ function reduceBody(draft, event) {
|
|
|
33119
33406
|
const tracking = current.blocks[event.index];
|
|
33120
33407
|
if (tracking === void 0) return null;
|
|
33121
33408
|
let next = draft;
|
|
33409
|
+
if (tracking.buffer !== void 0 && tracking.buffer !== "" && tracking.partIndex !== void 0) {
|
|
33410
|
+
const text = tracking.buffer;
|
|
33411
|
+
next = {
|
|
33412
|
+
...next,
|
|
33413
|
+
view: withPartAt(
|
|
33414
|
+
next.view,
|
|
33415
|
+
current.messageId,
|
|
33416
|
+
tracking.partIndex,
|
|
33417
|
+
(part) => part.type === "text" || part.type === "thinking" ? { ...part, text } : part
|
|
33418
|
+
)
|
|
33419
|
+
};
|
|
33420
|
+
}
|
|
33421
|
+
const { buffer: _buffered, ...trackingRest } = tracking;
|
|
33122
33422
|
let blocks = {
|
|
33123
33423
|
...current.blocks,
|
|
33124
|
-
[event.index]: { ...
|
|
33424
|
+
[event.index]: { ...trackingRest, open: false }
|
|
33125
33425
|
};
|
|
33126
33426
|
if (tracking.partIndex !== void 0) {
|
|
33127
33427
|
const mi = messageIndexById(next.view.messages, current.messageId);
|
|
@@ -33406,6 +33706,62 @@ function appendUserMessage(state, text) {
|
|
|
33406
33706
|
internal: { ...state.internal, nextMessageSeq: state.internal.nextMessageSeq + 1 }
|
|
33407
33707
|
};
|
|
33408
33708
|
}
|
|
33709
|
+
function setSessionViewDelivery(state, delivery) {
|
|
33710
|
+
const prev = state.internal.delivery;
|
|
33711
|
+
const next = {
|
|
33712
|
+
text: delivery.text ?? prev.text,
|
|
33713
|
+
thinking: delivery.thinking ?? prev.thinking
|
|
33714
|
+
};
|
|
33715
|
+
if (next.text === prev.text && next.thinking === prev.thinking) return state;
|
|
33716
|
+
return { view: state.view, internal: { ...state.internal, delivery: next } };
|
|
33717
|
+
}
|
|
33718
|
+
function stripThinkingParts(state) {
|
|
33719
|
+
const current = state.internal.current;
|
|
33720
|
+
let changed = false;
|
|
33721
|
+
let nextBlocks = current?.blocks ?? null;
|
|
33722
|
+
const messages = [];
|
|
33723
|
+
for (const message of state.view.messages) {
|
|
33724
|
+
const removed = [];
|
|
33725
|
+
const parts = message.parts.filter((part, index) => {
|
|
33726
|
+
if (part.type === "thinking") {
|
|
33727
|
+
removed.push(index);
|
|
33728
|
+
return false;
|
|
33729
|
+
}
|
|
33730
|
+
return true;
|
|
33731
|
+
});
|
|
33732
|
+
if (removed.length === 0) {
|
|
33733
|
+
messages.push(message);
|
|
33734
|
+
continue;
|
|
33735
|
+
}
|
|
33736
|
+
changed = true;
|
|
33737
|
+
const isCurrent = current !== null && message.id === current.messageId;
|
|
33738
|
+
if (isCurrent && nextBlocks !== null) {
|
|
33739
|
+
const remapped = {};
|
|
33740
|
+
for (const [key2, tracking] of Object.entries(nextBlocks)) {
|
|
33741
|
+
if (tracking.partIndex === void 0) {
|
|
33742
|
+
remapped[Number(key2)] = tracking;
|
|
33743
|
+
continue;
|
|
33744
|
+
}
|
|
33745
|
+
if (removed.includes(tracking.partIndex)) {
|
|
33746
|
+
const { partIndex: _gone, buffer: _buf, ...rest } = tracking;
|
|
33747
|
+
remapped[Number(key2)] = rest;
|
|
33748
|
+
continue;
|
|
33749
|
+
}
|
|
33750
|
+
const shift = removed.filter((r) => r < tracking.partIndex).length;
|
|
33751
|
+
remapped[Number(key2)] = shift > 0 ? { ...tracking, partIndex: tracking.partIndex - shift } : tracking;
|
|
33752
|
+
}
|
|
33753
|
+
nextBlocks = remapped;
|
|
33754
|
+
}
|
|
33755
|
+
if (parts.length > 0 || isCurrent) {
|
|
33756
|
+
messages.push({ ...message, parts });
|
|
33757
|
+
}
|
|
33758
|
+
}
|
|
33759
|
+
if (!changed) return state;
|
|
33760
|
+
return {
|
|
33761
|
+
view: { ...state.view, messages },
|
|
33762
|
+
internal: current !== null && nextBlocks !== null && nextBlocks !== current.blocks ? { ...state.internal, current: { ...current, blocks: nextBlocks } } : state.internal
|
|
33763
|
+
};
|
|
33764
|
+
}
|
|
33409
33765
|
function markSourceFailure(state, error) {
|
|
33410
33766
|
const message = error instanceof Error ? error.message : String(error);
|
|
33411
33767
|
return finalize({
|
|
@@ -33418,7 +33774,8 @@ function markSourceFailure(state, error) {
|
|
|
33418
33774
|
}
|
|
33419
33775
|
|
|
33420
33776
|
// src/view/history.ts
|
|
33421
|
-
function viewStateFromHistory(messages) {
|
|
33777
|
+
function viewStateFromHistory(messages, options) {
|
|
33778
|
+
const thinkingMode = options?.delivery?.thinking ?? "stream";
|
|
33422
33779
|
const results = /* @__PURE__ */ new Map();
|
|
33423
33780
|
for (const message of messages) {
|
|
33424
33781
|
for (const block of message.blocks) {
|
|
@@ -33435,7 +33792,9 @@ function viewStateFromHistory(messages) {
|
|
|
33435
33792
|
if (block.text !== "") parts.push({ type: "text", text: block.text });
|
|
33436
33793
|
break;
|
|
33437
33794
|
case "thinking":
|
|
33438
|
-
if (block.text !== ""
|
|
33795
|
+
if (block.text !== "" && thinkingMode !== "off") {
|
|
33796
|
+
parts.push({ type: "thinking", text: block.text });
|
|
33797
|
+
}
|
|
33439
33798
|
break;
|
|
33440
33799
|
case "tool_call": {
|
|
33441
33800
|
const result = results.get(block.id);
|
|
@@ -33462,7 +33821,7 @@ function viewStateFromHistory(messages) {
|
|
|
33462
33821
|
uiMessages.push({ id: `msg-${nextSeq}`, role: message.role, parts });
|
|
33463
33822
|
nextSeq += 1;
|
|
33464
33823
|
}
|
|
33465
|
-
const initial = initialSessionViewState();
|
|
33824
|
+
const initial = initialSessionViewState(options);
|
|
33466
33825
|
return {
|
|
33467
33826
|
view: { ...initial.view, messages: uiMessages },
|
|
33468
33827
|
internal: { ...initial.internal, nextMessageSeq: nextSeq }
|
|
@@ -33502,13 +33861,15 @@ function startEventPump(source, handlers) {
|
|
|
33502
33861
|
}
|
|
33503
33862
|
|
|
33504
33863
|
// src/view/session-view.ts
|
|
33505
|
-
function createSessionView(source) {
|
|
33506
|
-
let current = initialSessionViewState();
|
|
33864
|
+
function createSessionView(source, options) {
|
|
33865
|
+
let current = initialSessionViewState(options);
|
|
33507
33866
|
const listeners = /* @__PURE__ */ new Set();
|
|
33508
33867
|
let disposed = false;
|
|
33509
33868
|
const commit = (next) => {
|
|
33510
33869
|
if (next === current) return;
|
|
33870
|
+
const viewChanged = next.view !== current.view;
|
|
33511
33871
|
current = next;
|
|
33872
|
+
if (!viewChanged) return;
|
|
33512
33873
|
for (const listener of [...listeners]) {
|
|
33513
33874
|
try {
|
|
33514
33875
|
listener(next.view);
|
|
@@ -33538,6 +33899,12 @@ function createSessionView(source) {
|
|
|
33538
33899
|
if (disposed) return;
|
|
33539
33900
|
commit(appendUserMessage(current, text));
|
|
33540
33901
|
},
|
|
33902
|
+
setDelivery(delivery) {
|
|
33903
|
+
if (disposed) return;
|
|
33904
|
+
let next = setSessionViewDelivery(current, delivery);
|
|
33905
|
+
if (delivery.thinking === "off") next = stripThinkingParts(next);
|
|
33906
|
+
commit(next);
|
|
33907
|
+
},
|
|
33541
33908
|
dispose() {
|
|
33542
33909
|
if (disposed) return;
|
|
33543
33910
|
disposed = true;
|
|
@@ -33699,6 +34066,7 @@ export {
|
|
|
33699
34066
|
EndUserIdSchema,
|
|
33700
34067
|
HEADER_APP_TOKEN,
|
|
33701
34068
|
IMAGEGEN_TOOL_MAX_N,
|
|
34069
|
+
IMAGEGEN_TOOL_TIMEOUT_MS,
|
|
33702
34070
|
ImageGenArgsSchema,
|
|
33703
34071
|
McpHost,
|
|
33704
34072
|
OUTPUT_TAIL_MAX_CHARS,
|
|
@@ -33710,6 +34078,7 @@ export {
|
|
|
33710
34078
|
TansrSdkError,
|
|
33711
34079
|
UnavailableChannel,
|
|
33712
34080
|
VIDEOGEN_TOOL_MAX_DURATION,
|
|
34081
|
+
VIDEOGEN_TOOL_TIMEOUT_MS,
|
|
33713
34082
|
VideoGenArgsSchema,
|
|
33714
34083
|
accumulateUsage,
|
|
33715
34084
|
appBundleRegistryConfig,
|
|
@@ -33745,6 +34114,8 @@ export {
|
|
|
33745
34114
|
resolveInitialMessages,
|
|
33746
34115
|
resolvePlatformSelection,
|
|
33747
34116
|
runAgent,
|
|
34117
|
+
setSessionViewDelivery,
|
|
34118
|
+
stripThinkingParts,
|
|
33748
34119
|
subagentModelResolverOf,
|
|
33749
34120
|
toToolDef,
|
|
33750
34121
|
viewStateFromHistory
|
package/package.json
CHANGED