@tansr/sdk 0.4.1 → 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 +94 -11
- package/dist/index.js +412 -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
|
@@ -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 可读错,三环裁剪同例);材料
|
|
@@ -16632,6 +16697,12 @@ interface ImageGenData {
|
|
|
16632
16697
|
imageCount: number;
|
|
16633
16698
|
/** 网关错误码(如 forbidden/imagegen_not_configured/model_not_authorized;成功缺席)。 */
|
|
16634
16699
|
errorCode?: string;
|
|
16700
|
+
/**
|
|
16701
|
+
* 异步任务号(异步化拍板 2026-09-01;任务径在场时恒携)。预算耗尽/中断时
|
|
16702
|
+
* 凭此找回产出:GET /t1/imagegen/tasks/{taskId}(服务端照跑照扣,7 天可查)。
|
|
16703
|
+
* 同步回落径(旧版生产)缺席。
|
|
16704
|
+
*/
|
|
16705
|
+
taskId?: string;
|
|
16635
16706
|
}
|
|
16636
16707
|
interface CreateImageGenToolOptions {
|
|
16637
16708
|
/** 平台 API 基址(令牌档会话档;/t1 前缀由本工具追加)。 */
|
|
@@ -16667,9 +16738,15 @@ declare function createImageGenTool(options: CreateImageGenToolOptions): Tool<Im
|
|
|
16667
16738
|
* 平台托管能力)。
|
|
16668
16739
|
*
|
|
16669
16740
|
* 环3 语义:执行不在终端本地——工具 execute 经令牌档 fetch 打平台网关
|
|
16670
|
-
*
|
|
16671
|
-
*
|
|
16672
|
-
*
|
|
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 逐字同款),判定按工具实例缓存。
|
|
16673
16750
|
*
|
|
16674
16751
|
* 装配面:tools.platform: ['videoGen'] 且 bundle 能力位 platform.videoGen=true
|
|
16675
16752
|
* 时由 buildSdkToolSet 装配(位关 fail-fast 可读错);材料(baseUrl/token)
|
|
@@ -16729,6 +16806,12 @@ interface VideoGenData {
|
|
|
16729
16806
|
billedSeconds: number;
|
|
16730
16807
|
/** 网关错误码(如 forbidden/videogen_not_configured/model_not_authorized;成功缺席)。 */
|
|
16731
16808
|
errorCode?: string;
|
|
16809
|
+
/**
|
|
16810
|
+
* 异步任务号(异步化拍板 2026-09-01;任务径在场时恒携)。预算耗尽/中断时
|
|
16811
|
+
* 凭此找回产出:GET /t1/videogen/tasks/{taskId}(服务端照跑照扣,7 天可查)。
|
|
16812
|
+
* 同步回落径(旧版生产)缺席。
|
|
16813
|
+
*/
|
|
16814
|
+
taskId?: string;
|
|
16732
16815
|
}
|
|
16733
16816
|
interface CreateVideoGenToolOptions {
|
|
16734
16817
|
/** 平台 API 基址(令牌档会话档;/t1 前缀由本工具追加)。 */
|
|
@@ -16826,5 +16909,5 @@ declare function attachSdkTaskTool(toolset: SdkToolsetRef, config: AttachSdkTask
|
|
|
16826
16909
|
*/
|
|
16827
16910
|
declare function subagentModelResolverOf(registry: ProviderRegistry | null): SubagentModelResolver | undefined;
|
|
16828
16911
|
|
|
16829
|
-
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, subagentModelResolverOf, toToolDef, viewStateFromHistory };
|
|
16830
|
-
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,6 +30850,114 @@ 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;
|
|
30854
30962
|
var IMAGEGEN_TOOL_TIMEOUT_MS = 18e4;
|
|
30855
30963
|
var ImageGenArgsSchema = z42.object({
|
|
@@ -30869,10 +30977,43 @@ var ImageGenArgsSchema = z42.object({
|
|
|
30869
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."
|
|
30870
30978
|
)
|
|
30871
30979
|
});
|
|
30872
|
-
function errorResult13(text, model, errorCode2) {
|
|
30873
|
-
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
|
+
};
|
|
30874
30988
|
return { content: [{ t: "text", text }], isError: true, data };
|
|
30875
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
|
+
}
|
|
30876
31017
|
function hintOf(code) {
|
|
30877
31018
|
if (code === "forbidden") {
|
|
30878
31019
|
return " The app platform capability imageGen is disabled; the app developer can enable it in console → app → capabilities.";
|
|
@@ -30924,16 +31065,18 @@ function createImageGenTool(options) {
|
|
|
30924
31065
|
const base = options.baseUrl.replace(/\/+$/, "");
|
|
30925
31066
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
30926
31067
|
const token = options.token;
|
|
31068
|
+
const budgetMs = options.timeoutMs ?? IMAGEGEN_TOOL_TIMEOUT_MS;
|
|
31069
|
+
let taskRouteMissing = false;
|
|
30927
31070
|
return {
|
|
30928
31071
|
name: "ImageGen",
|
|
30929
|
-
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. 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),
|
|
30930
31073
|
shortDescription: "Generate images from a prompt via the tansr platform (billed per image). Args: model?, prompt, negativePrompt?, size?, n?, seed?, imageUrls?.",
|
|
30931
31074
|
inputSchema: ImageGenArgsSchema,
|
|
30932
31075
|
isReadOnly: false,
|
|
30933
31076
|
isConcurrencySafe: false,
|
|
30934
31077
|
// 2026-09-01 定谳修(videogen 同批):服务端预算 120s 与 kernel 120s 缺省档
|
|
30935
31078
|
// 零余量,classic/mj_task 任务轮询径跑满预算时客户端恒先掐——声明 180s 盖过。
|
|
30936
|
-
timeoutMs:
|
|
31079
|
+
timeoutMs: budgetMs,
|
|
30937
31080
|
async execute(args, ctx) {
|
|
30938
31081
|
const modelRef = args.model ?? "(default)";
|
|
30939
31082
|
if (ctx.signal.aborted) {
|
|
@@ -30948,6 +31091,53 @@ function createImageGenTool(options) {
|
|
|
30948
31091
|
...args.seed !== void 0 ? { seed: args.seed } : {},
|
|
30949
31092
|
...args.imageUrls !== void 0 ? { imageUrls: args.imageUrls } : {}
|
|
30950
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
|
+
}
|
|
30951
31141
|
let response;
|
|
30952
31142
|
try {
|
|
30953
31143
|
response = await fetchImpl(`${base}/t1/imagegen`, {
|
|
@@ -30972,25 +31162,10 @@ function createImageGenTool(options) {
|
|
|
30972
31162
|
raw = null;
|
|
30973
31163
|
}
|
|
30974
31164
|
if (!response.ok) {
|
|
30975
|
-
const
|
|
30976
|
-
const code = typeof envelope.error?.code === "string" ? envelope.error.code : `http_${response.status}`;
|
|
30977
|
-
const message = typeof envelope.error?.message === "string" ? envelope.error.message : "request rejected";
|
|
31165
|
+
const { code, message } = gatewayError(raw, response.status);
|
|
30978
31166
|
return errorResult13(`Image generation failed (${code}): ${message}.${hintOf(code)}`, modelRef, code);
|
|
30979
31167
|
}
|
|
30980
|
-
|
|
30981
|
-
const images = Array.isArray(body.images) ? body.images.map((item) => typeof item.url === "string" ? { url: item.url } : null).filter((item) => item !== null) : [];
|
|
30982
|
-
const imageCount = typeof body.imageCount === "number" ? body.imageCount : images.length;
|
|
30983
|
-
if (images.length === 0) {
|
|
30984
|
-
return errorResult13("Image generation returned no image URL (unexpected platform response).", modelRef);
|
|
30985
|
-
}
|
|
30986
|
-
const resolvedModel = typeof body.model === "string" && body.model !== "" ? body.model : modelRef;
|
|
30987
|
-
const data = { model: resolvedModel, images, imageCount };
|
|
30988
|
-
const lines = [
|
|
30989
|
-
`Generated ${imageCount} image(s) with model ${resolvedModel} (billed per image).`,
|
|
30990
|
-
"Image URLs (valid ~24h; surface or persist promptly):",
|
|
30991
|
-
...images.map((img, i) => `${i + 1}. ${img.url}`)
|
|
30992
|
-
];
|
|
30993
|
-
return { content: [{ t: "text", text: lines.join("\n") }], data };
|
|
31168
|
+
return successResult(raw, modelRef);
|
|
30994
31169
|
}
|
|
30995
31170
|
};
|
|
30996
31171
|
}
|
|
@@ -31019,16 +31194,46 @@ var VideoGenArgsSchema = z43.object({
|
|
|
31019
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.'
|
|
31020
31195
|
)
|
|
31021
31196
|
});
|
|
31022
|
-
function errorResult14(text, model, errorCode2) {
|
|
31197
|
+
function errorResult14(text, model, errorCode2, taskId) {
|
|
31023
31198
|
const data = {
|
|
31024
31199
|
model,
|
|
31025
31200
|
videos: [],
|
|
31026
31201
|
videoCount: 0,
|
|
31027
31202
|
billedSeconds: 0,
|
|
31028
|
-
...errorCode2 !== void 0 ? { errorCode: errorCode2 } : {}
|
|
31203
|
+
...errorCode2 !== void 0 ? { errorCode: errorCode2 } : {},
|
|
31204
|
+
...taskId !== void 0 ? { taskId } : {}
|
|
31029
31205
|
};
|
|
31030
31206
|
return { content: [{ t: "text", text }], isError: true, data };
|
|
31031
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
|
+
}
|
|
31032
31237
|
function hintOf2(code) {
|
|
31033
31238
|
if (code === "forbidden") {
|
|
31034
31239
|
return " The app platform capability videoGen is disabled; the app developer can enable it in console → app → capabilities.";
|
|
@@ -31087,9 +31292,11 @@ function createVideoGenTool(options) {
|
|
|
31087
31292
|
const base = options.baseUrl.replace(/\/+$/, "");
|
|
31088
31293
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
31089
31294
|
const token = options.token;
|
|
31295
|
+
const budgetMs = options.timeoutMs ?? VIDEOGEN_TOOL_TIMEOUT_MS;
|
|
31296
|
+
let taskRouteMissing = false;
|
|
31090
31297
|
return {
|
|
31091
31298
|
name: "VideoGen",
|
|
31092
|
-
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. 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),
|
|
31093
31300
|
shortDescription: "Generate a video from a prompt via the tansr platform (billed per second). Args: model?, prompt, negativePrompt?, duration?, ratio?, seed?, imageUrls?.",
|
|
31094
31301
|
inputSchema: VideoGenArgsSchema,
|
|
31095
31302
|
isReadOnly: false,
|
|
@@ -31097,7 +31304,7 @@ function createVideoGenTool(options) {
|
|
|
31097
31304
|
// 2026-09-01 定谳修:/t1/videogen 系服务端同步长等(600s 轮询预算),kernel
|
|
31098
31305
|
// 120s 缺省档下分钟级任务结构性必超时且有扣无产——工具级声明盖过缺省档
|
|
31099
31306
|
// (kernel 全局档恒不动;dispatching-tool-executor timeoutMs>0 即生效)。
|
|
31100
|
-
timeoutMs:
|
|
31307
|
+
timeoutMs: budgetMs,
|
|
31101
31308
|
async execute(args, ctx) {
|
|
31102
31309
|
const modelRef = args.model ?? "(default)";
|
|
31103
31310
|
if (ctx.signal.aborted) {
|
|
@@ -31112,6 +31319,53 @@ function createVideoGenTool(options) {
|
|
|
31112
31319
|
...args.seed !== void 0 ? { seed: args.seed } : {},
|
|
31113
31320
|
...args.imageUrls !== void 0 ? { imageUrls: args.imageUrls } : {}
|
|
31114
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
|
+
}
|
|
31115
31369
|
let response;
|
|
31116
31370
|
try {
|
|
31117
31371
|
response = await fetchImpl(`${base}/t1/videogen`, {
|
|
@@ -31136,26 +31390,10 @@ function createVideoGenTool(options) {
|
|
|
31136
31390
|
raw = null;
|
|
31137
31391
|
}
|
|
31138
31392
|
if (!response.ok) {
|
|
31139
|
-
const
|
|
31140
|
-
const code = typeof envelope.error?.code === "string" ? envelope.error.code : `http_${response.status}`;
|
|
31141
|
-
const message = typeof envelope.error?.message === "string" ? envelope.error.message : "request rejected";
|
|
31393
|
+
const { code, message } = gatewayError2(raw, response.status);
|
|
31142
31394
|
return errorResult14(`Video generation failed (${code}): ${message}.${hintOf2(code)}`, modelRef, code);
|
|
31143
31395
|
}
|
|
31144
|
-
|
|
31145
|
-
const videos = Array.isArray(body.videos) ? body.videos.map((item) => typeof item.url === "string" ? { url: item.url } : null).filter((item) => item !== null) : [];
|
|
31146
|
-
if (videos.length === 0) {
|
|
31147
|
-
return errorResult14("Video generation returned no video URL (unexpected platform response).", modelRef);
|
|
31148
|
-
}
|
|
31149
|
-
const videoCount = typeof body.videoCount === "number" ? body.videoCount : videos.length;
|
|
31150
|
-
const billedSeconds = typeof body.billedSeconds === "number" ? body.billedSeconds : 0;
|
|
31151
|
-
const resolvedModel = typeof body.model === "string" && body.model !== "" ? body.model : modelRef;
|
|
31152
|
-
const data = { model: resolvedModel, videos, videoCount, billedSeconds };
|
|
31153
|
-
const lines = [
|
|
31154
|
-
`Generated ${videoCount} video(s) with model ${resolvedModel} (${billedSeconds}s billed, per-second pricing).`,
|
|
31155
|
-
"Video URLs (valid ~24h; surface or persist promptly):",
|
|
31156
|
-
...videos.map((v, i) => `${i + 1}. ${v.url}`)
|
|
31157
|
-
];
|
|
31158
|
-
return { content: [{ t: "text", text: lines.join("\n") }], data };
|
|
31396
|
+
return successResult2(raw, modelRef);
|
|
31159
31397
|
}
|
|
31160
31398
|
};
|
|
31161
31399
|
}
|
|
@@ -32830,8 +33068,14 @@ function createFileSessionStore(options) {
|
|
|
32830
33068
|
}
|
|
32831
33069
|
|
|
32832
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
|
+
}
|
|
32833
33077
|
var OUTPUT_TAIL_MAX_CHARS = 4e3;
|
|
32834
|
-
function initialSessionViewState() {
|
|
33078
|
+
function initialSessionViewState(options) {
|
|
32835
33079
|
return {
|
|
32836
33080
|
view: {
|
|
32837
33081
|
status: "idle",
|
|
@@ -32841,6 +33085,7 @@ function initialSessionViewState() {
|
|
|
32841
33085
|
usage: { turnTokens: 0, sessionTokens: 0, requests: 0 }
|
|
32842
33086
|
},
|
|
32843
33087
|
internal: {
|
|
33088
|
+
delivery: resolveDelivery(options),
|
|
32844
33089
|
running: false,
|
|
32845
33090
|
compacting: false,
|
|
32846
33091
|
lastTurnFailed: false,
|
|
@@ -33074,6 +33319,22 @@ function reduceBody(draft, event) {
|
|
|
33074
33319
|
}
|
|
33075
33320
|
const tracking = next.internal.current;
|
|
33076
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
|
+
}
|
|
33077
33338
|
const appended = appendPart(next, messageId, { type: event.blockType, text: "" });
|
|
33078
33339
|
next = appended.draft;
|
|
33079
33340
|
return {
|
|
@@ -33087,7 +33348,8 @@ function reduceBody(draft, event) {
|
|
|
33087
33348
|
[event.index]: {
|
|
33088
33349
|
blockType: event.blockType,
|
|
33089
33350
|
partIndex: appended.partIndex,
|
|
33090
|
-
open: true
|
|
33351
|
+
open: true,
|
|
33352
|
+
...mode === "final" ? { buffer: "" } : {}
|
|
33091
33353
|
}
|
|
33092
33354
|
}
|
|
33093
33355
|
}
|
|
@@ -33113,7 +33375,23 @@ function reduceBody(draft, event) {
|
|
|
33113
33375
|
const current = draft.internal.current;
|
|
33114
33376
|
if (current === null) return null;
|
|
33115
33377
|
const tracking = current.blocks[event.index];
|
|
33116
|
-
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;
|
|
33117
33395
|
const view = withPartAt(
|
|
33118
33396
|
draft.view,
|
|
33119
33397
|
current.messageId,
|
|
@@ -33128,9 +33406,22 @@ function reduceBody(draft, event) {
|
|
|
33128
33406
|
const tracking = current.blocks[event.index];
|
|
33129
33407
|
if (tracking === void 0) return null;
|
|
33130
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;
|
|
33131
33422
|
let blocks = {
|
|
33132
33423
|
...current.blocks,
|
|
33133
|
-
[event.index]: { ...
|
|
33424
|
+
[event.index]: { ...trackingRest, open: false }
|
|
33134
33425
|
};
|
|
33135
33426
|
if (tracking.partIndex !== void 0) {
|
|
33136
33427
|
const mi = messageIndexById(next.view.messages, current.messageId);
|
|
@@ -33415,6 +33706,62 @@ function appendUserMessage(state, text) {
|
|
|
33415
33706
|
internal: { ...state.internal, nextMessageSeq: state.internal.nextMessageSeq + 1 }
|
|
33416
33707
|
};
|
|
33417
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
|
+
}
|
|
33418
33765
|
function markSourceFailure(state, error) {
|
|
33419
33766
|
const message = error instanceof Error ? error.message : String(error);
|
|
33420
33767
|
return finalize({
|
|
@@ -33427,7 +33774,8 @@ function markSourceFailure(state, error) {
|
|
|
33427
33774
|
}
|
|
33428
33775
|
|
|
33429
33776
|
// src/view/history.ts
|
|
33430
|
-
function viewStateFromHistory(messages) {
|
|
33777
|
+
function viewStateFromHistory(messages, options) {
|
|
33778
|
+
const thinkingMode = options?.delivery?.thinking ?? "stream";
|
|
33431
33779
|
const results = /* @__PURE__ */ new Map();
|
|
33432
33780
|
for (const message of messages) {
|
|
33433
33781
|
for (const block of message.blocks) {
|
|
@@ -33444,7 +33792,9 @@ function viewStateFromHistory(messages) {
|
|
|
33444
33792
|
if (block.text !== "") parts.push({ type: "text", text: block.text });
|
|
33445
33793
|
break;
|
|
33446
33794
|
case "thinking":
|
|
33447
|
-
if (block.text !== ""
|
|
33795
|
+
if (block.text !== "" && thinkingMode !== "off") {
|
|
33796
|
+
parts.push({ type: "thinking", text: block.text });
|
|
33797
|
+
}
|
|
33448
33798
|
break;
|
|
33449
33799
|
case "tool_call": {
|
|
33450
33800
|
const result = results.get(block.id);
|
|
@@ -33471,7 +33821,7 @@ function viewStateFromHistory(messages) {
|
|
|
33471
33821
|
uiMessages.push({ id: `msg-${nextSeq}`, role: message.role, parts });
|
|
33472
33822
|
nextSeq += 1;
|
|
33473
33823
|
}
|
|
33474
|
-
const initial = initialSessionViewState();
|
|
33824
|
+
const initial = initialSessionViewState(options);
|
|
33475
33825
|
return {
|
|
33476
33826
|
view: { ...initial.view, messages: uiMessages },
|
|
33477
33827
|
internal: { ...initial.internal, nextMessageSeq: nextSeq }
|
|
@@ -33511,13 +33861,15 @@ function startEventPump(source, handlers) {
|
|
|
33511
33861
|
}
|
|
33512
33862
|
|
|
33513
33863
|
// src/view/session-view.ts
|
|
33514
|
-
function createSessionView(source) {
|
|
33515
|
-
let current = initialSessionViewState();
|
|
33864
|
+
function createSessionView(source, options) {
|
|
33865
|
+
let current = initialSessionViewState(options);
|
|
33516
33866
|
const listeners = /* @__PURE__ */ new Set();
|
|
33517
33867
|
let disposed = false;
|
|
33518
33868
|
const commit = (next) => {
|
|
33519
33869
|
if (next === current) return;
|
|
33870
|
+
const viewChanged = next.view !== current.view;
|
|
33520
33871
|
current = next;
|
|
33872
|
+
if (!viewChanged) return;
|
|
33521
33873
|
for (const listener of [...listeners]) {
|
|
33522
33874
|
try {
|
|
33523
33875
|
listener(next.view);
|
|
@@ -33547,6 +33899,12 @@ function createSessionView(source) {
|
|
|
33547
33899
|
if (disposed) return;
|
|
33548
33900
|
commit(appendUserMessage(current, text));
|
|
33549
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
|
+
},
|
|
33550
33908
|
dispose() {
|
|
33551
33909
|
if (disposed) return;
|
|
33552
33910
|
disposed = true;
|
|
@@ -33756,6 +34114,8 @@ export {
|
|
|
33756
34114
|
resolveInitialMessages,
|
|
33757
34115
|
resolvePlatformSelection,
|
|
33758
34116
|
runAgent,
|
|
34117
|
+
setSessionViewDelivery,
|
|
34118
|
+
stripThinkingParts,
|
|
33759
34119
|
subagentModelResolverOf,
|
|
33760
34120
|
toToolDef,
|
|
33761
34121
|
viewStateFromHistory
|
package/package.json
CHANGED