@tansr/sdk 0.3.0 → 0.4.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/dist/index.d.ts CHANGED
@@ -5644,8 +5644,9 @@ declare const TansrConfigSchema: z.ZodObject<{
5644
5644
  * TANSR_CLASSIFIER_TIGHTEN_OUTSIDE_AUTO / TANSR_CLASSIFIER_BUDGET 保留为
5645
5645
  * 最高优先覆盖(逐键接管)。仅 user/managed 层被尊重(T-K0:分类器属
5646
5646
  * 用户/企业的信任与成本决策,项目层声明整段忽略+示警)。
5647
- * 刻意不进配置:TANSR_CLASSIFIER_ALLOW_UNQUALIFIED(资格越过)——
5648
- * break-glass 性质,进配置文件即可分发可持久,恒 env-only
5647
+ * 史注:TANSR_CLASSIFIER_ALLOW_UNQUALIFIED(资格越过)曾刻意不进配置
5648
+ * (break-glass 性质恒 env-only),已随 UAA P4-C2 整体退役(2026-08-30,
5649
+ * 任命即授照后无「未达资格」可越)。
5649
5650
  */
5650
5651
  classifier: z.ZodOptional<z.ZodObject<{
5651
5652
  enabled: z.ZodOptional<z.ZodBoolean>;
@@ -7021,15 +7022,6 @@ interface PermissionClassifierConfig {
7021
7022
  classifier: PermissionClassifier;
7022
7023
  /** 咨询超时(毫秒),缺省 DEFAULT_CLASSIFIER_TIMEOUT_MS;超时维持 ask */
7023
7024
  timeoutMs?: number;
7024
- /**
7025
- * safe→allow 裁决人资格位(T-K12 止血,05 §10.2/INV-5)。
7026
- *
7027
- * @deprecated T-K23c 起由 resolveQualificationTier 三级档位解析闭包取代
7028
- * (16 §4.5);仅供过渡期测试。解析闭包缺席时按 `true→'high'` /
7029
- * `false|缺省→'none'` 派生;闭包在场时本位被忽略。W1 收口卡
7030
- * (T-K23g)将其移出生产装配路径。
7031
- */
7032
- qualifiedForAllow?: boolean;
7033
7025
  /**
7034
7026
  * 三级资格档动态解析闭包(T-K23c,16 §4.5):返回当前生效档
7035
7027
  * (= min(授格档, 天花板, 会话覆盖),合成在装配层)。引擎**每次咨询
@@ -10591,9 +10583,9 @@ declare class PermissionEngine {
10591
10583
  /**
10592
10584
  * 生效资格档解析(T-K23c,16 §4.5):解析闭包在场即**现算**(装配层合成
10593
10585
  * min(entry, ceiling, override);闭包抛错 → 'none',词表外脏值由
10594
- * softenRadiusAllows 安全查表兜底——T-INV-B 一切异常朝严);闭包缺席时
10595
- * @deprecated 布尔位派生 `true→'high'/false|缺省→'none'`(W1 过渡
10596
- * 兼容,16 §4.5;收口见 T-K23g)。
10586
+ * softenRadiusAllows 安全查表兜底——T-INV-B 一切异常朝严);闭包缺席
10587
+ * 'none'(无任命即无软化面;@deprecated 布尔位 qualifiedForAllow
10588
+ * 已随 P4-C3 拆除,2026-08-30)。
10597
10589
  */
10598
10590
  private resolveClassifierTier;
10599
10591
  /**
@@ -15542,22 +15534,79 @@ interface AppBundleModel {
15542
15534
  capabilities: Record<string, unknown>;
15543
15535
  contextWindow: number | null;
15544
15536
  }
15537
+ /**
15538
+ * 图像模型受理约束(bundle platformModels.imageGen 行 constraints 加法键,
15539
+ * 2026-09-01;网关侧单源 = /t1 运行时校验档同一 classify 词表)。工具描述
15540
+ * 逐模型拼注——智能体首发即中,不再靠拒收错误试错(用户实测连环拒收后追加)。
15541
+ */
15542
+ interface ImageModelConstraints {
15543
+ /** false = 模型定档分辨率,size 在场即拒。 */
15544
+ size: boolean;
15545
+ seed: boolean;
15546
+ negativePrompt: boolean;
15547
+ /** 单请求张数帽(n 超帽由网关钳)。 */
15548
+ maxImages: number;
15549
+ /** 富输入 imageUrls 受理域(null = 纯文生行,在场即拒)。 */
15550
+ imageInput: {
15551
+ min: number;
15552
+ max: number;
15553
+ urlOk: boolean;
15554
+ b64Ok: boolean;
15555
+ } | null;
15556
+ /** false = 动词行(引用既有任务),prompt 在场即拒。 */
15557
+ promptRequired: boolean;
15558
+ /** 动词行必携 action{taskId,actionId}。 */
15559
+ actionRequired?: boolean;
15560
+ }
15561
+ /** 视频模型受理约束(同上镜像;时长域/首帧受理/比例域是实测三大拒收源)。 */
15562
+ interface VideoModelConstraints {
15563
+ durations: {
15564
+ kind: 'set';
15565
+ values: number[];
15566
+ defaultSec: number;
15567
+ } | {
15568
+ kind: 'range';
15569
+ min: number;
15570
+ max: number;
15571
+ defaultSec: number;
15572
+ };
15573
+ /** 比例词形域(null = ratio 在场即拒;键缺席 = 透传上游,域未实录)。 */
15574
+ ratio?: string[] | null;
15575
+ negativePrompt: boolean;
15576
+ seed: boolean;
15577
+ /** 首帧图受理域(required = i2v 专用行必携 imageUrls;null = 纯文生行在场即拒)。 */
15578
+ imageInput: {
15579
+ required: boolean;
15580
+ max: number;
15581
+ urlOk: boolean;
15582
+ b64Ok: boolean;
15583
+ } | null;
15584
+ audioInput: boolean;
15585
+ }
15545
15586
  /**
15546
15587
  * 授权媒体模型条目(S-G1 媒体池化顺位取用,用户拍板 2026-08-30):`model` =
15547
15588
  * canonical handle(/t1/imagegen、/t1/videogen 的 model 位可直用)。网关契约
15548
- * 恒不下发价格/成本/供应商内部信息,本形态即全量。
15589
+ * 恒不下发价格/成本/供应商内部信息。constraints 加法键(2026-09-01)按 kind
15590
+ * 特化(下方两型);条目级容错:缺席/坏形状 = undefined(旧 api 回落通用
15591
+ * 描述,恒不臆造受理面)。
15549
15592
  */
15550
15593
  interface AppBundleMediaModel {
15551
15594
  model: string;
15552
15595
  displayName: string;
15553
15596
  }
15597
+ interface AppBundleImageModel extends AppBundleMediaModel {
15598
+ constraints?: ImageModelConstraints;
15599
+ }
15600
+ interface AppBundleVideoModel extends AppBundleMediaModel {
15601
+ constraints?: VideoModelConstraints;
15602
+ }
15554
15603
  /**
15555
15604
  * 授权媒体模型集(bundle platformModels 段):序 = 平台收敛稳定序,**顺位第一
15556
15605
  * 即工具/网关 model 缺省时的生效模型**;空数组 = 平台未配置(如实,恒不猜名)。
15557
15606
  */
15558
15607
  interface AppBundlePlatformModels {
15559
- imageGen: AppBundleMediaModel[];
15560
- videoGen: AppBundleMediaModel[];
15608
+ imageGen: AppBundleImageModel[];
15609
+ videoGen: AppBundleVideoModel[];
15561
15610
  }
15562
15611
  /** bundle-for-app 的 SDK 消费子集 */
15563
15612
  interface AppBundle {
@@ -16546,20 +16595,23 @@ declare const ImageGenArgsSchema: z.ZodObject<{
16546
16595
  size: z.ZodOptional<z.ZodString>;
16547
16596
  n: z.ZodOptional<z.ZodNumber>;
16548
16597
  seed: z.ZodOptional<z.ZodNumber>;
16598
+ imageUrls: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
16549
16599
  }, "strip", z.ZodTypeAny, {
16550
16600
  prompt: string;
16551
16601
  model?: string | undefined;
16552
16602
  size?: string | undefined;
16553
16603
  n?: number | undefined;
16554
- negativePrompt?: string | undefined;
16555
16604
  seed?: number | undefined;
16605
+ negativePrompt?: string | undefined;
16606
+ imageUrls?: string[] | undefined;
16556
16607
  }, {
16557
16608
  prompt: string;
16558
16609
  model?: string | undefined;
16559
16610
  size?: string | undefined;
16560
16611
  n?: number | undefined;
16561
- negativePrompt?: string | undefined;
16562
16612
  seed?: number | undefined;
16613
+ negativePrompt?: string | undefined;
16614
+ imageUrls?: string[] | undefined;
16563
16615
  }>;
16564
16616
  type ImageGenArgs = z.infer<typeof ImageGenArgsSchema>;
16565
16617
  /** 表面层渲染用结构化数据(ToolResult.data;错误时携错误码)。 */
@@ -16581,11 +16633,12 @@ interface CreateImageGenToolOptions {
16581
16633
  fetchImpl?: typeof fetch;
16582
16634
  /**
16583
16635
  * 授权图像模型集(S-G1;bundle platformModels.imageGen,装配循环自取):
16584
- * 工具描述自列(顺位第一 = model 缺省生效模型);空数组 = 平台未配置
16585
- * (描述如实注明,恒不猜名);缺席 = 集未知(注入档直构/旧径),描述回落
16586
- * 通用指引。
16636
+ * 工具描述自列(顺位第一 = model 缺省生效模型),constraints 在场时逐模型
16637
+ * 拼受理约束注记(2026-09-01——size/富输入/动词行,智能体首发即中);
16638
+ * 空数组 = 平台未配置(描述如实注明,恒不猜名);缺席 = 集未知(注入档
16639
+ * 直构/旧径),描述回落通用指引。
16587
16640
  */
16588
- models?: readonly AppBundleMediaModel[];
16641
+ models?: readonly AppBundleImageModel[];
16589
16642
  }
16590
16643
  /**
16591
16644
  * 环3 平台图像生成工具(kernel Tool 形态;name 'ImageGen' 沿 kernel PascalCase
@@ -16621,20 +16674,23 @@ declare const VideoGenArgsSchema: z.ZodObject<{
16621
16674
  duration: z.ZodOptional<z.ZodNumber>;
16622
16675
  ratio: z.ZodOptional<z.ZodString>;
16623
16676
  seed: z.ZodOptional<z.ZodNumber>;
16677
+ imageUrls: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
16624
16678
  }, "strip", z.ZodTypeAny, {
16625
16679
  prompt: string;
16626
16680
  model?: string | undefined;
16627
16681
  duration?: number | undefined;
16628
- negativePrompt?: string | undefined;
16629
16682
  seed?: number | undefined;
16683
+ negativePrompt?: string | undefined;
16630
16684
  ratio?: string | undefined;
16685
+ imageUrls?: string[] | undefined;
16631
16686
  }, {
16632
16687
  prompt: string;
16633
16688
  model?: string | undefined;
16634
16689
  duration?: number | undefined;
16635
- negativePrompt?: string | undefined;
16636
16690
  seed?: number | undefined;
16691
+ negativePrompt?: string | undefined;
16637
16692
  ratio?: string | undefined;
16693
+ imageUrls?: string[] | undefined;
16638
16694
  }>;
16639
16695
  type VideoGenArgs = z.infer<typeof VideoGenArgsSchema>;
16640
16696
  /** 表面层渲染用结构化数据(ToolResult.data;错误时携错误码)。 */
@@ -16658,11 +16714,12 @@ interface CreateVideoGenToolOptions {
16658
16714
  fetchImpl?: typeof fetch;
16659
16715
  /**
16660
16716
  * 授权视频模型集(S-G1;bundle platformModels.videoGen,装配循环自取):
16661
- * 工具描述自列(顺位第一 = model 缺省生效模型);空数组 = 平台未配置
16662
- * (描述如实注明,恒不猜名);缺席 = 集未知(注入档直构/旧径),描述回落
16663
- * 通用指引。
16717
+ * 工具描述自列(顺位第一 = model 缺省生效模型),constraints 在场时逐模型
16718
+ * 拼受理约束注记(2026-09-01——时长域/i2v 首帧/比例域,实测三大拒收源
16719
+ * 前置进描述);空数组 = 平台未配置(如实注明恒不猜名);缺席 = 集未知
16720
+ * (注入档直构/旧径),描述回落通用指引。
16664
16721
  */
16665
- models?: readonly AppBundleMediaModel[];
16722
+ models?: readonly AppBundleVideoModel[];
16666
16723
  }
16667
16724
  /**
16668
16725
  * 环3 平台视频生成工具(kernel Tool 形态;name 'VideoGen' 沿 kernel PascalCase
@@ -16739,4 +16796,4 @@ declare function attachSdkTaskTool(toolset: SdkToolsetRef, config: AttachSdkTask
16739
16796
  declare function subagentModelResolverOf(registry: ProviderRegistry | null): SubagentModelResolver | undefined;
16740
16797
 
16741
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 };
16742
- export type { ActiveToolStatus, Answer, AppBundle, AppBundleMediaModel, AppBundleModel, AppBundlePlatformModels, 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, 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, Visibility };
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 };
package/dist/index.js CHANGED
@@ -1455,8 +1455,9 @@ var PermissionsSectionSchema = z5.object({
1455
1455
  * TANSR_CLASSIFIER_TIGHTEN_OUTSIDE_AUTO / TANSR_CLASSIFIER_BUDGET 保留为
1456
1456
  * 最高优先覆盖(逐键接管)。仅 user/managed 层被尊重(T-K0:分类器属
1457
1457
  * 用户/企业的信任与成本决策,项目层声明整段忽略+示警)。
1458
- * 刻意不进配置:TANSR_CLASSIFIER_ALLOW_UNQUALIFIED(资格越过)——
1459
- * break-glass 性质,进配置文件即可分发可持久,恒 env-only
1458
+ * 史注:TANSR_CLASSIFIER_ALLOW_UNQUALIFIED(资格越过)曾刻意不进配置
1459
+ * (break-glass 性质恒 env-only),已随 UAA P4-C2 整体退役(2026-08-30,
1460
+ * 任命即授照后无「未达资格」可越)。
1460
1461
  */
1461
1462
  classifier: z5.object({
1462
1463
  enabled: z5.boolean().optional(),
@@ -11984,14 +11985,14 @@ var PermissionEngine = class {
11984
11985
  /**
11985
11986
  * 生效资格档解析(T-K23c,16 §4.5):解析闭包在场即**现算**(装配层合成
11986
11987
  * min(entry, ceiling, override);闭包抛错 → 'none',词表外脏值由
11987
- * softenRadiusAllows 安全查表兜底——T-INV-B 一切异常朝严);闭包缺席时
11988
- * @deprecated 布尔位派生 `true→'high'/false|缺省→'none'`(W1 过渡
11989
- * 兼容,16 §4.5;收口见 T-K23g)。
11988
+ * softenRadiusAllows 安全查表兜底——T-INV-B 一切异常朝严);闭包缺席
11989
+ * 'none'(无任命即无软化面;@deprecated 布尔位 qualifiedForAllow
11990
+ * 已随 P4-C3 拆除,2026-08-30)。
11990
11991
  */
11991
11992
  resolveClassifierTier(config) {
11992
11993
  const resolve2 = config.resolveQualificationTier;
11993
11994
  if (resolve2 === void 0) {
11994
- return config.qualifiedForAllow === true ? "high" : "none";
11995
+ return "none";
11995
11996
  }
11996
11997
  try {
11997
11998
  return resolve2();
@@ -12964,6 +12965,47 @@ function buildDecisionRecord(params) {
12964
12965
  }
12965
12966
 
12966
12967
  // ../kernel/src/tools/dispatch/dispatching-tool-executor.ts
12968
+ function suggestToolName(attempted, registered) {
12969
+ const norm = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
12970
+ const a = norm(attempted);
12971
+ if (a === "") return null;
12972
+ let prefixHit = null;
12973
+ let levHit = null;
12974
+ let levBest = 3;
12975
+ for (const name of registered) {
12976
+ const n = norm(name);
12977
+ if (n === a) return name;
12978
+ if (prefixHit === null && Math.min(n.length, a.length) >= 4 && (n.startsWith(a) || a.startsWith(n))) {
12979
+ prefixHit = name;
12980
+ }
12981
+ const d = boundedLevenshtein(a, n, 2);
12982
+ if (d !== null && d < levBest) {
12983
+ levBest = d;
12984
+ levHit = name;
12985
+ }
12986
+ }
12987
+ return prefixHit ?? levHit;
12988
+ }
12989
+ function boundedLevenshtein(a, b, cap) {
12990
+ if (Math.abs(a.length - b.length) > cap) return null;
12991
+ let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
12992
+ for (let i = 1; i <= a.length; i++) {
12993
+ const cur = [i, ...Array.from({ length: b.length }, () => 0)];
12994
+ let rowMin = i;
12995
+ for (let j = 1; j <= b.length; j++) {
12996
+ cur[j] = Math.min(
12997
+ prev[j] + 1,
12998
+ cur[j - 1] + 1,
12999
+ prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)
13000
+ );
13001
+ rowMin = Math.min(rowMin, cur[j]);
13002
+ }
13003
+ if (rowMin > cap) return null;
13004
+ prev = cur;
13005
+ }
13006
+ const d = prev[b.length];
13007
+ return d <= cap ? d : null;
13008
+ }
12967
13009
  var DEFAULT_MAX_CONCURRENCY = 8;
12968
13010
  var DEFAULT_TIMEOUT_MS = 12e4;
12969
13011
  var unsafeNoGateConstruction = false;
@@ -13163,7 +13205,8 @@ var DispatchingToolExecutor = class {
13163
13205
  const tool = this.#registry.get(call.name);
13164
13206
  if (tool === void 0) {
13165
13207
  const registered = this.#registry.names();
13166
- const message = `Unknown tool "${call.name}". ` + (registered.length > 0 ? `Available tools: ${registered.join(", ")}.` : "No tools are registered.");
13208
+ const suggested = suggestToolName(call.name, registered);
13209
+ const message = `Unknown tool "${call.name}". ` + (suggested !== null ? `Did you mean "${suggested}"? ` : "") + (registered.length > 0 ? `Available tools: ${registered.join(", ")}.` : "No tools are registered.");
13167
13210
  yield {
13168
13211
  t: "event",
13169
13212
  body: { type: "tool.failed", toolCallId: call.id, errorType: "unknown_tool", message }
@@ -30812,13 +30855,18 @@ var ImageGenArgsSchema = z42.object({
30812
30855
  // S-G1(媒体池化顺位取用):Optional——缺席即不发 model 位,网关按授权集顺位
30813
30856
  // 第一生效(与 bundle platformModels.imageGen 首行恒同);点名限集内(工具描述自列)。
30814
30857
  model: z42.string().min(1).optional().describe(
30815
- "Image model name from the authorized set listed in this tool description. Omit to use the default (the first authorized model)."
30858
+ "Image model name from the authorized set listed in this tool description. Omit to use the default (the first authorized model) when the user did not ask for a specific model. Never omit or swap this field as a workaround when the user named a model that is not in the set — tell the user and let them choose first."
30816
30859
  ),
30817
30860
  prompt: z42.string().refine((s) => s.trim().length > 0, { message: "prompt must be a non-empty string" }).describe("Positive prompt describing the desired image content, style and composition."),
30818
30861
  negativePrompt: z42.string().min(1).max(500).optional().describe("Negative prompt: content to keep out of the image."),
30819
30862
  size: z42.string().regex(/^\d{2,5}\*\d{2,5}$/, { message: "size must look like '1024*1024' (width*height)" }).optional().describe("Output resolution as 'width*height' (for example '1024*1024'; defaults to the model's default)."),
30820
30863
  n: z42.number().int().min(1).max(IMAGEGEN_TOOL_MAX_N).optional().describe(`Number of images to generate (default 1, max ${IMAGEGEN_TOOL_MAX_N}; each image is billed).`),
30821
- seed: z42.number().int().min(0).max(2147483647).optional().describe("Random seed for relatively stable output (defaults to a random seed upstream).")
30864
+ seed: z42.number().int().min(0).max(2147483647).optional().describe("Random seed for relatively stable output (defaults to a random seed upstream)."),
30865
+ // 媒体二批富输入位(2026-09-01;网关 TwpImagegenRequestSchema 同帽 1..14):
30866
+ // 受理域随模型(工具描述逐模型注明;不受理的模型在场即 bad_request)。
30867
+ imageUrls: z42.array(z42.string().min(1)).min(1).max(14).optional().describe(
30868
+ "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
+ )
30822
30870
  });
30823
30871
  function errorResult13(text, model, errorCode2) {
30824
30872
  const data = { model, images: [], imageCount: 0, ...errorCode2 !== void 0 ? { errorCode: errorCode2 } : {} };
@@ -30832,7 +30880,7 @@ function hintOf(code) {
30832
30880
  return " Image generation is not configured on this platform yet; tell the user instead of retrying.";
30833
30881
  }
30834
30882
  if (code === "model_not_authorized") {
30835
- return " Use an image model name that this app is authorized for.";
30883
+ return ` The requested model is not in the authorized image model set of this app. Do not silently retry with another model or without "model" — tell the user, show the authorized image models from this tool's description, and let the user choose.`;
30836
30884
  }
30837
30885
  if (code === "imagegen_quota_exceeded") {
30838
30886
  return " The daily image quota for this account is exhausted; retry after the daily reset (UTC+8).";
@@ -30842,6 +30890,25 @@ function hintOf(code) {
30842
30890
  }
30843
30891
  return "";
30844
30892
  }
30893
+ function imageModelNote(m) {
30894
+ const label = m.displayName !== m.model ? `${m.model} (${m.displayName})` : m.model;
30895
+ const c = m.constraints;
30896
+ if (c === void 0) return label;
30897
+ const notes = [];
30898
+ if (!c.promptRequired) {
30899
+ notes.push("task-action model, NOT usable via this tool — pick another model");
30900
+ }
30901
+ if (!c.size) notes.push("fixed output size — do not pass size");
30902
+ if (c.imageInput !== null) {
30903
+ const forms = c.imageInput.urlOk && c.imageInput.b64Ok ? "URL or base64 data URI" : c.imageInput.urlOk ? "URL only" : "base64 data URI only";
30904
+ const count = c.imageInput.min > 0 ? `requires ${c.imageInput.min === c.imageInput.max ? String(c.imageInput.min) : `${c.imageInput.min}-${c.imageInput.max}`} input image(s)` : `accepts up to ${c.imageInput.max} reference image(s)`;
30905
+ notes.push(`${count} via imageUrls (${forms})`);
30906
+ }
30907
+ if (!c.seed) notes.push("no seed");
30908
+ if (!c.negativePrompt) notes.push("no negativePrompt");
30909
+ if (c.maxImages === 1) notes.push("single image per call (n=1)");
30910
+ return notes.length > 0 ? `${label} [${notes.join("; ")}]` : label;
30911
+ }
30845
30912
  function authorizedModelsNote(models) {
30846
30913
  if (models === void 0) {
30847
30914
  return ' Omit "model" to use the app default, or ask the app developer for authorized model names.';
@@ -30849,8 +30916,8 @@ function authorizedModelsNote(models) {
30849
30916
  if (models.length === 0) {
30850
30917
  return " The platform has no image model configured for this app yet — tell the user instead of retrying or guessing model names.";
30851
30918
  }
30852
- const listed = models.map((m) => m.displayName !== m.model ? `${m.model} (${m.displayName})` : m.model).join(", ");
30853
- return ` Authorized image models (omit "model" to use the first as default): ${listed}.`;
30919
+ const listed = models.map((m) => `- ${imageModelNote(m)}`).join("\n");
30920
+ return ' Authorized image models — the first is the default when "model" is omitted; bracketed notes are hard per-model constraints enforced by the platform (violating them fails the call):\n' + listed + '\nIf the user names a model outside this list (including a video model asked to make images), do not silently omit "model" or substitute another model — tell the user, show this list, and let them choose.';
30854
30921
  }
30855
30922
  function createImageGenTool(options) {
30856
30923
  const base = options.baseUrl.replace(/\/+$/, "");
@@ -30859,7 +30926,7 @@ function createImageGenTool(options) {
30859
30926
  return {
30860
30927
  name: "ImageGen",
30861
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),
30862
- shortDescription: "Generate images from a prompt via the tansr platform (billed per image). Args: model?, prompt, negativePrompt?, size?, n?, seed?.",
30929
+ shortDescription: "Generate images from a prompt via the tansr platform (billed per image). Args: model?, prompt, negativePrompt?, size?, n?, seed?, imageUrls?.",
30863
30930
  inputSchema: ImageGenArgsSchema,
30864
30931
  isReadOnly: false,
30865
30932
  isConcurrencySafe: false,
@@ -30874,7 +30941,8 @@ function createImageGenTool(options) {
30874
30941
  ...args.negativePrompt !== void 0 ? { negativePrompt: args.negativePrompt } : {},
30875
30942
  ...args.size !== void 0 ? { size: args.size } : {},
30876
30943
  ...args.n !== void 0 ? { n: args.n } : {},
30877
- ...args.seed !== void 0 ? { seed: args.seed } : {}
30944
+ ...args.seed !== void 0 ? { seed: args.seed } : {},
30945
+ ...args.imageUrls !== void 0 ? { imageUrls: args.imageUrls } : {}
30878
30946
  };
30879
30947
  let response;
30880
30948
  try {
@@ -30930,15 +30998,21 @@ var VideoGenArgsSchema = z43.object({
30930
30998
  // S-G1(媒体池化顺位取用):Optional——缺席即不发 model 位,网关按授权集顺位
30931
30999
  // 第一生效(与 bundle platformModels.videoGen 首行恒同);点名限集内(工具描述自列)。
30932
31000
  model: z43.string().min(1).optional().describe(
30933
- "Video model name from the authorized set listed in this tool description. Omit to use the default (the first authorized model)."
31001
+ "Video model name from the authorized set listed in this tool description. Omit to use the default (the first authorized model) when the user did not ask for a specific model. Never omit or swap this field as a workaround when the user named a model that is not in the set — tell the user and let them choose first."
30934
31002
  ),
30935
31003
  prompt: z43.string().refine((s) => s.trim().length > 0, { message: "prompt must be a non-empty string" }).describe("Positive prompt describing the desired video content, motion, style and camera work."),
30936
31004
  negativePrompt: z43.string().min(1).max(500).optional().describe("Negative prompt: content to keep out of the video."),
30937
31005
  duration: z43.number().int().min(2).max(VIDEOGEN_TOOL_MAX_DURATION).optional().describe(
30938
- `Video duration in seconds (default 5, max ${VIDEOGEN_TOOL_MAX_DURATION}; billing is per second — longer costs more).`
31006
+ "Video duration in seconds (billing is per second — longer costs more). Models accept only the durations listed in their bracketed note; omit to use the model default."
30939
31007
  ),
30940
31008
  ratio: z43.string().regex(/^(adaptive|\d{1,2}:\d{1,2})$/, { message: "ratio must look like '16:9' (or 'adaptive' where supported)" }).optional().describe("Aspect ratio such as '16:9', '9:16' or '1:1' (defaults to the model's default)."),
30941
- seed: z43.number().int().min(0).max(2147483647).optional().describe("Random seed for relatively stable output (defaults to a random seed upstream).")
31009
+ seed: z43.number().int().min(0).max(2147483647).optional().describe("Random seed for relatively stable output (defaults to a random seed upstream)."),
31010
+ // 媒体二批富输入位(2026-09-01;网关 TwpVideogenRequestSchema 同帽 1..2):
31011
+ // i2v 首帧(seedance 支持首帧+尾帧两张);受理域随模型(描述逐模型注明,
31012
+ // i2v 专用行缺席即拒、纯文生行在场即拒)。
31013
+ imageUrls: z43.array(z43.string().min(1)).min(1).max(2).optional().describe(
31014
+ '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
+ )
30942
31016
  });
30943
31017
  function errorResult14(text, model, errorCode2) {
30944
31018
  const data = {
@@ -30958,7 +31032,7 @@ function hintOf2(code) {
30958
31032
  return " Video generation is not configured on this platform yet; tell the user instead of retrying.";
30959
31033
  }
30960
31034
  if (code === "model_not_authorized") {
30961
- return " Use a video model name that this app is authorized for.";
31035
+ return ` The requested model is not in the authorized video model set of this app. Do not silently retry with another model or without "model" — tell the user, show the authorized video models from this tool's description, and let the user choose.`;
30962
31036
  }
30963
31037
  if (code === "videogen_quota_exceeded") {
30964
31038
  return " The daily video-seconds quota for this account is exhausted; retry after the daily reset (UTC+8).";
@@ -30966,8 +31040,34 @@ function hintOf2(code) {
30966
31040
  if (code === "insufficient_balance") {
30967
31041
  return " The app account balance is insufficient; the app developer needs to top up.";
30968
31042
  }
31043
+ if (code === "upstream_error") {
31044
+ return " The video provider failed to execute the task. If imageUrls was passed, the provider may be unable to fetch that image host — retry with an image from a different image model or another public URL.";
31045
+ }
30969
31046
  return "";
30970
31047
  }
31048
+ function videoModelNote(m) {
31049
+ const label = m.displayName !== m.model ? `${m.model} (${m.displayName})` : m.model;
31050
+ const c = m.constraints;
31051
+ if (c === void 0) return label;
31052
+ const notes = [];
31053
+ const d = c.durations;
31054
+ notes.push(
31055
+ d.kind === "set" ? `duration ${d.values.join("|")}s ONLY (default ${d.defaultSec}s)` : `duration ${d.min}-${d.max}s (default ${d.defaultSec}s)`
31056
+ );
31057
+ if (c.imageInput === null) {
31058
+ notes.push("text-to-video only — rejects imageUrls");
31059
+ } else {
31060
+ const forms = c.imageInput.urlOk && c.imageInput.b64Ok ? "URL or base64 data URI" : c.imageInput.urlOk ? "URL only" : "base64 data URI only";
31061
+ notes.push(
31062
+ c.imageInput.required ? `image-to-video ONLY — first-frame image via imageUrls is REQUIRED (${forms})` : `optional first-frame image via imageUrls (${forms})`
31063
+ );
31064
+ }
31065
+ if (c.ratio === null) notes.push("no ratio");
31066
+ else if (c.ratio !== void 0) notes.push(`ratio ${c.ratio.join("|")}`);
31067
+ if (!c.seed) notes.push("no seed");
31068
+ if (!c.negativePrompt) notes.push("no negativePrompt");
31069
+ return `${label} [${notes.join("; ")}]`;
31070
+ }
30971
31071
  function authorizedModelsNote2(models) {
30972
31072
  if (models === void 0) {
30973
31073
  return ' Omit "model" to use the app default, or ask the app developer for authorized model names.';
@@ -30975,8 +31075,8 @@ function authorizedModelsNote2(models) {
30975
31075
  if (models.length === 0) {
30976
31076
  return " The platform has no video model configured for this app yet — tell the user instead of retrying or guessing model names.";
30977
31077
  }
30978
- const listed = models.map((m) => m.displayName !== m.model ? `${m.model} (${m.displayName})` : m.model).join(", ");
30979
- return ` Authorized video models (omit "model" to use the first as default): ${listed}.`;
31078
+ const listed = models.map((m) => `- ${videoModelNote(m)}`).join("\n");
31079
+ return ' Authorized video models — the first is the default when "model" is omitted; bracketed notes are hard per-model constraints enforced by the platform (violating them fails the call):\n' + listed + '\nIf the user names a model outside this list (including an image model asked to make videos), do not silently omit "model" or substitute another model — tell the user, show this list, and let them choose.';
30980
31080
  }
30981
31081
  function createVideoGenTool(options) {
30982
31082
  const base = options.baseUrl.replace(/\/+$/, "");
@@ -30985,7 +31085,7 @@ function createVideoGenTool(options) {
30985
31085
  return {
30986
31086
  name: "VideoGen",
30987
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),
30988
- shortDescription: "Generate a video from a prompt via the tansr platform (billed per second). Args: model?, prompt, negativePrompt?, duration?, ratio?, seed?.",
31088
+ shortDescription: "Generate a video from a prompt via the tansr platform (billed per second). Args: model?, prompt, negativePrompt?, duration?, ratio?, seed?, imageUrls?.",
30989
31089
  inputSchema: VideoGenArgsSchema,
30990
31090
  isReadOnly: false,
30991
31091
  isConcurrencySafe: false,
@@ -31000,7 +31100,8 @@ function createVideoGenTool(options) {
31000
31100
  ...args.negativePrompt !== void 0 ? { negativePrompt: args.negativePrompt } : {},
31001
31101
  ...args.duration !== void 0 ? { duration: args.duration } : {},
31002
31102
  ...args.ratio !== void 0 ? { ratio: args.ratio } : {},
31003
- ...args.seed !== void 0 ? { seed: args.seed } : {}
31103
+ ...args.seed !== void 0 ? { seed: args.seed } : {},
31104
+ ...args.imageUrls !== void 0 ? { imageUrls: args.imageUrls } : {}
31004
31105
  };
31005
31106
  let response;
31006
31107
  try {
@@ -31516,14 +31617,72 @@ function parseModel(raw) {
31516
31617
  contextWindow: typeof raw.contextWindow === "number" ? raw.contextWindow : null
31517
31618
  };
31518
31619
  }
31519
- function parseMediaModels(raw) {
31620
+ function parseMediaImageInput(raw, flagKey) {
31621
+ if (raw === null) return null;
31622
+ if (!isRecord8(raw)) return false;
31623
+ const flag = raw[flagKey];
31624
+ if (flagKey === "min" ? typeof flag !== "number" : typeof flag !== "boolean") return false;
31625
+ if (typeof raw.max !== "number" || typeof raw.urlOk !== "boolean" || typeof raw.b64Ok !== "boolean") return false;
31626
+ return { flag, max: raw.max, urlOk: raw.urlOk, b64Ok: raw.b64Ok };
31627
+ }
31628
+ function parseImageConstraints(raw) {
31629
+ if (!isRecord8(raw)) return void 0;
31630
+ if (typeof raw.size !== "boolean" || typeof raw.seed !== "boolean" || typeof raw.negativePrompt !== "boolean" || typeof raw.maxImages !== "number" || typeof raw.promptRequired !== "boolean") {
31631
+ return void 0;
31632
+ }
31633
+ const input = parseMediaImageInput(raw.imageInput, "min");
31634
+ if (input === false) return void 0;
31635
+ return {
31636
+ size: raw.size,
31637
+ seed: raw.seed,
31638
+ negativePrompt: raw.negativePrompt,
31639
+ maxImages: raw.maxImages,
31640
+ imageInput: input === null ? null : { min: input.flag, max: input.max, urlOk: input.urlOk, b64Ok: input.b64Ok },
31641
+ promptRequired: raw.promptRequired,
31642
+ ...raw.actionRequired === true ? { actionRequired: true } : {}
31643
+ };
31644
+ }
31645
+ function parseVideoConstraints(raw) {
31646
+ if (!isRecord8(raw)) return void 0;
31647
+ const d = raw.durations;
31648
+ let durations = null;
31649
+ if (isRecord8(d) && typeof d.defaultSec === "number") {
31650
+ if (d.kind === "set" && Array.isArray(d.values) && d.values.every((v) => typeof v === "number")) {
31651
+ durations = { kind: "set", values: [...d.values], defaultSec: d.defaultSec };
31652
+ } else if (d.kind === "range" && typeof d.min === "number" && typeof d.max === "number") {
31653
+ durations = { kind: "range", min: d.min, max: d.max, defaultSec: d.defaultSec };
31654
+ }
31655
+ }
31656
+ if (durations === null) return void 0;
31657
+ if (typeof raw.negativePrompt !== "boolean" || typeof raw.seed !== "boolean" || typeof raw.audioInput !== "boolean") {
31658
+ return void 0;
31659
+ }
31660
+ const input = parseMediaImageInput(raw.imageInput, "required");
31661
+ if (input === false) return void 0;
31662
+ let ratio;
31663
+ if (raw.ratio === void 0) ratio = void 0;
31664
+ else if (raw.ratio === null) ratio = null;
31665
+ else if (Array.isArray(raw.ratio) && raw.ratio.every((r) => typeof r === "string")) ratio = [...raw.ratio];
31666
+ else return void 0;
31667
+ return {
31668
+ durations,
31669
+ ...ratio !== void 0 ? { ratio } : {},
31670
+ negativePrompt: raw.negativePrompt,
31671
+ seed: raw.seed,
31672
+ imageInput: input === null ? null : { required: input.flag, max: input.max, urlOk: input.urlOk, b64Ok: input.b64Ok },
31673
+ audioInput: raw.audioInput
31674
+ };
31675
+ }
31676
+ function parseMediaModels(raw, parseConstraints) {
31520
31677
  if (!Array.isArray(raw)) return [];
31521
31678
  const out = [];
31522
31679
  for (const item of raw) {
31523
31680
  if (!isRecord8(item) || typeof item.model !== "string" || item.model === "") continue;
31681
+ const constraints = item.constraints === void 0 ? void 0 : parseConstraints(item.constraints);
31524
31682
  out.push({
31525
31683
  model: item.model,
31526
- displayName: typeof item.displayName === "string" && item.displayName !== "" ? item.displayName : item.model
31684
+ displayName: typeof item.displayName === "string" && item.displayName !== "" ? item.displayName : item.model,
31685
+ ...constraints !== void 0 ? { constraints } : {}
31527
31686
  });
31528
31687
  }
31529
31688
  return out;
@@ -31544,8 +31703,8 @@ function parseAppBundle(raw) {
31544
31703
  aliases,
31545
31704
  capabilities: parsedCaps.success ? parsedCaps.data : DEFAULT_APP_CAPABILITIES,
31546
31705
  platformModels: {
31547
- imageGen: parseMediaModels(mediaRaw.imageGen),
31548
- videoGen: parseMediaModels(mediaRaw.videoGen)
31706
+ imageGen: parseMediaModels(mediaRaw.imageGen, parseImageConstraints),
31707
+ videoGen: parseMediaModels(mediaRaw.videoGen, parseVideoConstraints)
31549
31708
  }
31550
31709
  };
31551
31710
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tansr/sdk",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Tansr public TypeScript SDK: headless agent API (query / createSession / runAgent) + pure protocol type re-exports (public, MIT).",
5
5
  "license": "MIT",
6
6
  "type": "module",