@acosmi/sdk-ts 2.13.0 → 2.15.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.
@@ -179,15 +179,34 @@ interface RerankResponse {
179
179
  model?: string;
180
180
  }
181
181
  /**
182
- * 模型可接收的用户输入模态 (v1.2+).
182
+ * 模型可接收的用户输入模态 —— **本 SDK 已知的那些** (v1.2+).
183
183
  *
184
184
  * - 'text': 文本输入
185
185
  * - 'image': 截图 / 图片输入 (多模态)
186
+ * - 'video': 视频输入 (多模态向量 / 重排序类模型, 网关 2026-06-20 起下发)
186
187
  *
187
188
  * ManagedModel.inputModalities 包含 'image' 才允许向该模型直接发图;
188
189
  * 缺失字段时调用方应保守按 text-only / unknown 处理.
190
+ *
191
+ * 这个联合体是**查询用**的 (helper 的 modality 参数), 不是数据域的全集 —— 见
192
+ * {@link InputModalityTag}.
189
193
  */
190
- type InputModality = 'text' | 'image';
194
+ type InputModality = 'text' | 'image' | 'video';
195
+ /**
196
+ * 目录里实际可能出现的模态标签 —— **开放值域**, 已知取值见 {@link InputModality}.
197
+ *
198
+ * 值域由网关托管模型目录持有, 靠运营动作扩张 (不是靠发 SDK 新版)。把数据字段
199
+ * 声明成封闭联合体, 等于让类型对在网真实数据撒谎; 2026-08-02 CrabCode 客户端
200
+ * 因同一形态的封闭枚举 (Rust 侧) 把整个网关模型列表打空过数周。
201
+ *
202
+ * 因此: **查询**用 {@link InputModality} (已知标签, 有自动补全),
203
+ * **数据**用本类型 (照收未知标签, 不丢信息、不谎报)。
204
+ *
205
+ * 刻意就是朴素 `string`, 不用 `InputModality | (string & {})` 那个"保留补全"的
206
+ * 技巧: 补全只在**书写**字面量时有价值, 而本类型描述的是**读到**的目录数据;
207
+ * 那个技巧还要靠 `{}` —— 本仓 eslint `ban-types` 明令禁止。
208
+ */
209
+ type InputModalityTag = string;
191
210
  /** BucketClass 字面量常量 — V30 二轮审计 D-P1-3 修复 */
192
211
  declare const BucketClassCommercial = "COMMERCIAL";
193
212
  declare const BucketClassGeneric = "GENERIC";
@@ -261,14 +280,16 @@ interface ManagedModel {
261
280
  /**
262
281
  * 模型可接收的用户输入模态 (v1.2+, CrabCode desktop automation / computer-use 选模型用).
263
282
  *
264
- * 取值: 'text' | 'image' 的子集. 'image' 表示模型可直接接收 screenshot/image 输入.
283
+ * 已知取值见 {@link InputModality} ('text' | 'image' | 'video'); 'image' 表示模型可
284
+ * 直接接收 screenshot/image 输入。类型是**开放**的 ({@link InputModalityTag}) ——
285
+ * 目录新增模态时旧版 SDK 照样原样透出, 不静默丢值。
265
286
  *
266
287
  * 兼容上游字段名 input_modalities (snake_case) — listModels 在写缓存前会做归一化.
267
288
  *
268
289
  * **缺失语义**: 上游未下发时该字段为 undefined, 调用方必须保守按 text-only / unknown
269
290
  * 处理, 严禁默认假设支持 image. 同样严禁用模型名 substring 反推 modality.
270
291
  */
271
- inputModalities?: InputModality[];
292
+ inputModalities?: InputModalityTag[];
272
293
  }
273
294
  /** 单桶视图 — QuotaSummary.freeBuckets/paidBuckets 元素 */
274
295
  interface BucketRow {
@@ -501,9 +522,36 @@ interface SourcesEvent {
501
522
  sources: WebSearchSource[];
502
523
  session_id?: string;
503
524
  }
525
+ /** sources 事件结构错误的稳定机器码。 */
526
+ type SourcesEventIssueCode = 'invalid_json' | 'missing_sources' | 'sources_not_array' | 'source_not_object' | 'source_title_invalid' | 'source_url_invalid' | 'source_snippet_invalid' | 'session_id_invalid';
527
+ /**
528
+ * sources SSE 的无歧义分类结果。
529
+ *
530
+ * `empty_sources` 是合法零结果;`malformed_sources` 才表示结构损坏。
531
+ */
532
+ type SourcesEventParseResult = {
533
+ kind: 'not_sources';
534
+ } | {
535
+ kind: 'empty_sources';
536
+ session_id?: string;
537
+ } | {
538
+ kind: 'sources';
539
+ value: SourcesEvent;
540
+ } | {
541
+ kind: 'malformed_sources';
542
+ code: SourcesEventIssueCode;
543
+ };
544
+ /**
545
+ * 同时识别 SSE event name 与 JSON payload discriminator,并把合法空结果
546
+ * 与非 sources、结构损坏明确分开。未知额外字段不影响分类。
547
+ */
548
+ declare function classifySourcesEvent(ev: StreamEvent): SourcesEventParseResult;
504
549
  /**
505
550
  * 从 StreamEvent 中解析搜索来源
506
- * 返回 null 表示该事件不是 sources 类型
551
+ *
552
+ * @deprecated 需要区分合法空结果与结构损坏时使用 classifySourcesEvent。
553
+ * 此 legacy API 保留原有宽松解析和返回对象形状;新代码不得据此区分
554
+ * 合法空结果与结构损坏。
507
555
  */
508
556
  declare function parseSourcesEvent(ev: StreamEvent): SourcesEvent | null;
509
557
  /**
@@ -619,4 +667,4 @@ declare function getAdapter(provider: string): ProviderAdapter;
619
667
  */
620
668
  declare function getAdapterForModel(m: ManagedModel): ProviderAdapter;
621
669
 
622
- export { parseSourcesEvent as $, ThinkingMaxFallbackMaxTokens as A, BucketClassCommercial as B, type ChatContentBlock as C, ThinkingOff as D, type EffortConfig as E, type VideoTaskResponse as F, type GeoLoc as G, type WebSearchSource as H, type ImageGenerationRequest as I, type WindowLimitStatus as J, type WindowResetSummary as K, bucketInfoIsCommercial as L, type ManagedModel as M, bucketRowIsCommercial as N, type OutputConfig as O, type ProviderAdapter as P, type QuotaSummary as Q, type RerankDocument as R, type ServerTool as S, type ThinkingConfig as T, getAdapter as U, type VideoGenerationRequest as V, type WebSearchConfig as W, getAdapterForModel as X, newThinkingConfig as Y, newWebSearchTool as Z, parseSettlement as _, BucketClassGeneric as a, type BucketInfo as b, type BucketRow as c, type ChatMessage as d, type ChatRequest as e, type ChatResponse as f, type ChatUsage as g, type EmbeddingData as h, type EmbeddingRequest as i, type EmbeddingResponse as j, type ImageGenerationResponse as k, type InputModality as l, type ModelCapabilities as m, type MultimodalContent as n, ProviderFormat as o, type RerankQuery as p, type RerankRequest as q, type RerankResponse as r, type RerankResult as s, ServerToolTypeWebSearch as t, type SourcesEvent as u, type StreamEvent as v, type StreamSettlement as w, ThinkingHigh as x, ThinkingHighMinMaxTokens as y, ThinkingMax as z };
670
+ export { getAdapterForModel as $, ThinkingHigh as A, BucketClassCommercial as B, type ChatContentBlock as C, ThinkingHighMinMaxTokens as D, type EffortConfig as E, ThinkingMax as F, type GeoLoc as G, ThinkingMaxFallbackMaxTokens as H, type ImageGenerationRequest as I, ThinkingOff as J, type VideoTaskResponse as K, type WebSearchSource as L, type ManagedModel as M, type WindowLimitStatus as N, type OutputConfig as O, type ProviderAdapter as P, type QuotaSummary as Q, type RerankDocument as R, type ServerTool as S, type ThinkingConfig as T, type WindowResetSummary as U, type VideoGenerationRequest as V, type WebSearchConfig as W, bucketInfoIsCommercial as X, bucketRowIsCommercial as Y, classifySourcesEvent as Z, getAdapter as _, BucketClassGeneric as a, newThinkingConfig as a0, newWebSearchTool as a1, parseSettlement as a2, parseSourcesEvent as a3, type BucketInfo as b, type BucketRow as c, type ChatMessage as d, type ChatRequest as e, type ChatResponse as f, type ChatUsage as g, type EmbeddingData as h, type EmbeddingRequest as i, type EmbeddingResponse as j, type ImageGenerationResponse as k, type InputModality as l, type InputModalityTag as m, type ModelCapabilities as n, type MultimodalContent as o, ProviderFormat as p, type RerankQuery as q, type RerankRequest as r, type RerankResponse as s, type RerankResult as t, ServerToolTypeWebSearch as u, type SourcesEvent as v, type SourcesEventIssueCode as w, type SourcesEventParseResult as x, type StreamEvent as y, type StreamSettlement as z };
@@ -43,6 +43,57 @@ function newWebSearchTool(cfg) {
43
43
  }
44
44
  return st;
45
45
  }
46
+ function classifySourcesEvent(ev) {
47
+ let parsed;
48
+ try {
49
+ parsed = JSON.parse(ev.data);
50
+ } catch {
51
+ return ev.event === "sources" ? { kind: "malformed_sources", code: "invalid_json" } : { kind: "not_sources" };
52
+ }
53
+ const wrapper = typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : null;
54
+ if (wrapper?.type !== "sources" && ev.event !== "sources") {
55
+ return { kind: "not_sources" };
56
+ }
57
+ if (!wrapper || !Object.prototype.hasOwnProperty.call(wrapper, "sources")) {
58
+ return { kind: "malformed_sources", code: "missing_sources" };
59
+ }
60
+ if (Object.prototype.hasOwnProperty.call(wrapper, "session_id") && wrapper.session_id !== void 0 && typeof wrapper.session_id !== "string") {
61
+ return { kind: "malformed_sources", code: "session_id_invalid" };
62
+ }
63
+ if (!Array.isArray(wrapper.sources)) {
64
+ return { kind: "malformed_sources", code: "sources_not_array" };
65
+ }
66
+ const sessionID = typeof wrapper.session_id === "string" ? wrapper.session_id : void 0;
67
+ if (wrapper.sources.length === 0) {
68
+ return {
69
+ kind: "empty_sources",
70
+ ...sessionID === void 0 ? {} : { session_id: sessionID }
71
+ };
72
+ }
73
+ for (const source of wrapper.sources) {
74
+ if (typeof source !== "object" || source === null || Array.isArray(source)) {
75
+ return { kind: "malformed_sources", code: "source_not_object" };
76
+ }
77
+ const item = source;
78
+ if (typeof item.title !== "string") {
79
+ return { kind: "malformed_sources", code: "source_title_invalid" };
80
+ }
81
+ if (typeof item.url !== "string") {
82
+ return { kind: "malformed_sources", code: "source_url_invalid" };
83
+ }
84
+ if (Object.prototype.hasOwnProperty.call(item, "snippet") && item.snippet !== void 0 && typeof item.snippet !== "string") {
85
+ return { kind: "malformed_sources", code: "source_snippet_invalid" };
86
+ }
87
+ }
88
+ return {
89
+ kind: "sources",
90
+ value: {
91
+ ...wrapper,
92
+ sources: wrapper.sources,
93
+ ...sessionID === void 0 ? {} : { session_id: sessionID }
94
+ }
95
+ };
96
+ }
46
97
  function parseSourcesEvent(ev) {
47
98
  let wrapper;
48
99
  try {
@@ -3610,9 +3661,7 @@ function normalizeInputModalities(models) {
3610
3661
  if (Array.isArray(m.inputModalities)) continue;
3611
3662
  const snake = m.input_modalities;
3612
3663
  if (Array.isArray(snake)) {
3613
- m.inputModalities = snake.filter(
3614
- (v) => v === "text" || v === "image"
3615
- );
3664
+ m.inputModalities = snake.filter((v) => typeof v === "string");
3616
3665
  }
3617
3666
  }
3618
3667
  return models;
@@ -7793,6 +7842,7 @@ exports.bucketRowIsCommercial = bucketRowIsCommercial;
7793
7842
  exports.buildBetas = buildBetas;
7794
7843
  exports.chatBridgeScopes = chatBridgeScopes;
7795
7844
  exports.classifyComplianceError = classifyComplianceError;
7845
+ exports.classifySourcesEvent = classifySourcesEvent;
7796
7846
  exports.commerceScopes = commerceScopes;
7797
7847
  exports.completeWebAuthorizationRequest = completeWebAuthorizationRequest;
7798
7848
  exports.complianceErrorToRetryAdvice = complianceErrorToRetryAdvice;