@vibedev-si/dsh-vibedev 0.3.0 → 0.3.1

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 CHANGED
@@ -3,7 +3,7 @@
3
3
  在 DeepSeek Harness 里登录 VibeDev 账号,和 DeepSeek 账号并存:
4
4
 
5
5
  - **VibeDev 的模型**:登录后,模型选择器里会多出「VibeDev」一组(Claude、GPT 等网关提供的模型),和 DeepSeek 的模型并列,选中就能用;
6
- - **媒体生成**:Agent 可以生成图片、视频、音乐和播客,并把语音转成文字,结果保存在工作区的 `media/` 目录下;
6
+ - **媒体生成**:Agent 可以生成图片、视频、音乐、播客和语音,并把语音转成文字,结果保存在工作区的 `media/` 目录下;
7
7
  - **网页搜索**:提供走 VibeDev 网关的网页搜索,见下面的「网页搜索」。
8
8
 
9
9
  费用都从你的 VibeDev 余额里扣,DeepSeek 账号照常由 DeepSeek Harness 自己管理,两边互不影响。还没有 VibeDev 账号的话,可以在 [VibeDev](https://api.vibedev.studio) 注册。
@@ -65,8 +65,8 @@
65
65
  | --- | --- |
66
66
  | `image_generate` | 生成图片;带参考图时用来改图、换风格或把产品放进场景。生成的图片 Agent 自己能看到。 |
67
67
  | `video_generate` | 生成视频,在后台运行,一般 1 到 10 分钟。完成后会通知 Agent,文件保存在 `media/videos/`。 |
68
- | `audio_generate` | 生成音乐(可以自带歌词)或一期播客(围绕一个话题或一个网页)。 |
69
- | `audio_transcribe` | 把语音转成文字(目前只支持普通话)。 |
68
+ | `audio_generate` | 生成音乐(可以自带歌词)、一期播客(围绕一个话题或一个网页),或一段语音(朗读文字,可以用参考音频指定音色)。 |
69
+ | `audio_transcribe` | 把语音转成文字(以文件上传,语言和时长限制以模型声明为准,目前常见为普通话)。 |
70
70
  | `media_models` | 列出账号可用的媒体模型和价格;视频模型还会列出每种模式接受哪些输入。 |
71
71
  | `media_tasks` | 查看进行中和已完成的视频、音频任务。 |
72
72
  | `media_account` | 查看用的是哪个 VibeDev 账号;登录或退出(和侧边栏、设置里的登录是同一个)。 |
@@ -81,11 +81,22 @@
81
81
 
82
82
  每个视频模型支持的模式、参考素材数量、时长、画面比例和分辨率都不一样。插件会按网关下发的模型能力逐项检查:模型不支持的请求,会在上传和扣费之前就被拒绝,并说明这个模型支持什么。所有参考素材会先上传到 VibeDev 网关的素材库,网关会检查格式,并测量参考视频的时长。
83
83
 
84
+ ### 音频模型
85
+
86
+ 音频模型是音乐、播客、语音还是转写,只看网关模型目录里 `audio.generation_kind` 的声明,不按模型名称猜;没有声明类型的模型会列出来,但不能用来生成。每个模型只提交它在 `request_fields` 里声明的字段,正文写进 `prompt_field` 指定的字段:
87
+
88
+ - 音乐:`prompt`、`lyrics`、`genre`、`mood`、`gender`;
89
+ - 播客:`prompt`、`source_url`;
90
+ - 语音:按模型声明,例如 Seed 是 `text_prompt`、`references`(参考音频)、`audio_config`(输出格式和采样率)、`watermark`。
91
+
92
+ 参考音频的数量、大小、时长、不能同时使用的字段,以及 WAV、MP3 等格式各自支持的采样率,都以网关下发的能力为准。音乐和播客不接受参考音频、格式、采样率或时长参数。
93
+
84
94
  ## 费用
85
95
 
86
96
  - VibeDev 的聊天模型按用量计费,价格以 VibeDev 网关为准。
87
- - 图片按张计费,视频按秒计费(参考视频的时长也计入),音乐和播客按次计费。`media_models` 会列出当前价格。
88
- - 视频和音频只在成功时扣费,失败不扣。视频提交后无法取消。
97
+ - 图片按张计费,视频按秒计费(参考视频的时长也计入),音乐和播客按次计费,语音按原始秒计费(按服务商返回的原始时长,可能和播放时长不同),转写按分钟计费。`media_models` 会列出当前价格;目录没有给出价格的模型显示「未定价」,不代表免费。
98
+ - 视频和音频只在成功时扣费,失败和取消的任务不扣。视频提交后无法取消。
99
+ - 同一次操作只会生成一次:提交没有得到确认时,会用同一个请求键向网关确认结果;查询或下载失败只会重新查询、刷新链接,不会重新提交。结果已经生成、但费用还在结算(`settlement_pending`)时,结果照常保存,不会重新生成。
89
100
  - 插件设置里的「每次付费生成前先询问」默认关闭。打开后,每次付费的媒体请求之前都会先弹出确认,并显示预估金额。
90
101
 
91
102
  ## 设置
@@ -96,7 +107,7 @@
96
107
  | --- | --- | --- |
97
108
  | 每次付费生成前先询问 | 关 | 打开后,每次媒体生成前先确认费用。 |
98
109
  | 保存目录 | `media` | 相对于工作区。 |
99
- | 默认生图 / 视频 / 音乐 / 播客 / 转写模型 | 空 | 留空时由 Agent 按模型目录选择。 |
110
+ | 默认生图 / 视频 / 音乐 / 播客 / 语音合成 / 转写模型 | 空 | 留空时由 Agent 按模型目录选择;可以填模型 id 或别名。 |
100
111
 
101
112
  另有几项只能在配置文件(`cordis.patch.yml` 中 `dsh-vibedev` 一行)里改:`displayName`(模型选择器里显示的组名,默认 `VibeDev`)、`preferredModels`(排在最前的 VibeDev 模型)、`openBrowserOnSignIn`(登录时是否自动打开系统浏览器,默认开)、`catalogRefreshMinutes`(模型目录刷新间隔,默认 30 分钟)、`client`(登录时报给网关的客户端名称,默认 `vibedev-plugin`)、`primary`(作为应用的主账号显示,默认关,VibeDev 应用里开)。
102
113
 
@@ -137,7 +148,7 @@ npm run build
137
148
  Sign in to VibeDev in DeepSeek Harness, next to the DeepSeek account:
138
149
 
139
150
  - **VibeDev models**: once signed in, the model picker gains a "VibeDev" group (Claude, GPT and the other models of the VibeDev gateway) next to DeepSeek's;
140
- - **Media generation**: the agent generates images, videos, music and podcasts and transcribes speech; results are saved in the workspace under `media/`.
151
+ - **Media generation**: the agent generates images, videos, music, podcasts and speech, and transcribes speech; results are saved in the workspace under `media/`.
141
152
 
142
153
  Everything is paid from your VibeDev balance; the DeepSeek account stays DeepSeek Harness's own, and the two do not affect each other. To create an account, register at [VibeDev](https://api.vibedev.studio). This plugin was renamed from `dsh-media`.
143
154
 
@@ -149,13 +160,17 @@ Everything is paid from your VibeDev balance; the DeepSeek account stays DeepSee
149
160
 
150
161
  **Creator tools withdrawn (0.2.5)**: the Creator tools line 0.2.4 added at the end of Settings → VibeDev account is gone. It was a cross-plugin recommendation slot, and in the settings page it hurt the layout; a redesign can revisit it later. Only that interface change is reverted: the account, the balance, the model list, the sign-in and saved screenplays, boards and film files are untouched.
151
162
 
163
+ **Gateway audio (0.3.1)**: audio models are recognized from the catalog's structured `audio` block (music, podcast, speech, transcription), never from their names; speech generation (Seed) joins music and podcasts; prices show their unit (per generation, per second of original audio, per minute) and "not priced" when the catalog states none; the `vibedevMedia` service gains `startAudio` with an operation key and query-only result reading.
164
+
152
165
  **Models**: the list comes from the VibeDev gateway for your account, so nothing is listed before you sign in; models appear right after, without a restart. Using a VibeDev model while signed out, or after the sign-in has ended, asks you to sign in; a used-up balance says so with the top-up link. These messages are separate from the DeepSeek account's. An expired access token is renewed and the request sent again, without repeating any output.
153
166
 
154
167
  **Web search**: the plugin registers the web search provider `vibedev-gateway`, signed in with your VibeDev account. Registering does not select it: DeepSeek Harness keeps its own search unless the profile sets `searchProvider: vibedev-gateway` on the `web` row (the VibeDev app does). Searching is free, but the gateway refuses every request, searches included, while the balance is zero.
155
168
 
156
- **Media tools**: `image_generate`, `video_generate` (runs as a background job), `audio_generate` (music or a podcast), `audio_transcribe` (Mandarin only for now), `media_models`, `media_tasks` and `media_account`. Reference images, videos and audio, and first and last frames, can each be a workspace path, an http(s) link, or `chat:1` for the most recent matching file you attached. A request the model cannot serve is refused before anything is uploaded or charged.
169
+ **Media tools**: `image_generate`, `video_generate` (runs as a background job), `audio_generate` (music, a podcast or speech), `audio_transcribe` (a multipart file upload; languages and limits as each model declares), `media_models`, `media_tasks` and `media_account`. Reference images, videos and audio, and first and last frames, can each be a workspace path, an http(s) link, or `chat:1` for the most recent matching file you attached. A request the model cannot serve is refused before anything is uploaded or charged.
170
+
171
+ **Audio models**: whether an audio model makes music, a podcast, speech or a transcription comes from its catalog declaration (`audio.generation_kind`), never from its name; a model that declares no kind is listed but cannot generate. Each model is sent only the fields it declares in `request_fields`, with the text in its `prompt_field`: music takes `prompt`, `lyrics`, `genre`, `mood` and `gender`; a podcast `prompt` and `source_url`; speech what it declares (Seed: `text_prompt`, `references`, `audio_config`, `watermark`). Speech reference limits (count, size, length, exclusions) and the sample rates of each output format come from the gateway. Music and podcasts take no references, format, sample rate or duration.
157
172
 
158
- **Cost**: chat models are billed by usage at the gateway's prices; images per image, video per second (reference video length counts), music and podcasts per request. Failed video and audio tasks are not charged, and a submitted video cannot be cancelled. "Ask before each paid generation" is off by default.
173
+ **Cost**: chat models are billed by usage at the gateway's prices; images per image, video per second (reference video length counts), music and podcasts per request, speech per second of original audio (the length the provider reports, which can differ from playback), transcription per minute. A model without a catalog price is shown as "not priced" (未定价), never as free. Failed and cancelled video and audio tasks are not charged, and a submitted video cannot be cancelled. One operation generates once: an unconfirmed submission is settled under the same key, a failed query or download only queries again or renews the link, and a result whose charge is still settling (`settlement_pending`) is kept, never generated again. "Ask before each paid generation" is off by default.
159
174
 
160
175
  **Settings**: open "VibeDev Account & Models" on the Plugins page for the spending confirmation, the output folder and the default media models. `displayName`, `preferredModels`, `openBrowserOnSignIn`, `catalogRefreshMinutes`, `client` (the client name sent with the sign-in, default `vibedev-plugin`) and `primary` (show the account as the app's main account; off by default, on in the VibeDev app) are set in the profile's `cordis.patch.yml` row `dsh-vibedev`.
161
176
 
@@ -163,7 +178,7 @@ Everything is paid from your VibeDev balance; the DeepSeek account stays DeepSee
163
178
 
164
179
  **Privacy**: prompts and reference media are sent to the VibeDev gateway, which forwards them to the model provider. The plugin's own sign-in is kept in the DeepSeek Harness credential store, and task records under `dsh-media/` in the DeepSeek Harness data folder (the former name, kept so an upgrade loses nothing).
165
180
 
166
- **For other plugins**: the `vibedevMedia` service generates images and videos through the same model choice, reference checks, idempotent submission and background saving; the film workbench ([dsh-film](https://github.com/VibeDev-Si/dsh-film)) storyboard uses it.
181
+ **For other plugins**: the `vibedevMedia` service generates images, videos and audio (`startAudio`: music, podcasts and speech) through the same model choice, reference checks, idempotent submission and background saving; the film workbench ([dsh-film](https://github.com/VibeDev-Si/dsh-film)) storyboard uses it. `audioForms()` describes the form of each audio model (only its declared fields, choices and limits, and its price). Every task is read the same way: `task` (as recorded), `refreshTask` (ask the gateway again — fresh links, settlement; a query, never a submission), `onTask` (each change) and `result` (the files to play or download). Pass the same `operationId` when one click is retried: its task is returned and nothing is submitted twice.
167
182
 
168
183
  **Third-party code**: the model route in `src/llm/` is ported from the VibeDev app; `context.ts`, `replay.ts` and `stream.ts` are copied from DeepSeek Harness's `@deepseek-ai/dsh-llm-pi-ai` (MIT). The licences of the bundled pi-ai, Anthropic SDK, OpenAI SDK and their dependencies are in `THIRD-PARTY-NOTICES.txt`.
169
184
 
@@ -1,4 +1,4 @@
1
- THIRD-PARTY NOTICES · @vibedev-si/dsh-vibedev 0.3.0
1
+ THIRD-PARTY NOTICES · @vibedev-si/dsh-vibedev 0.3.1
2
2
 
3
3
  This package bundles code from the projects below. Each is used under the licence that
4
4
  follows its name; the licence texts are reproduced as the projects ship them.
package/client/client.js CHANGED
@@ -263,6 +263,7 @@ window.__ModuleLoader__.load({ id: "@vibedev-si/dsh-vibedev", factory: (require)
263
263
  videoModel: "视频",
264
264
  musicModel: "音乐",
265
265
  podcastModel: "播客",
266
+ speechModel: "语音合成",
266
267
  transcriptionModel: "语音转写",
267
268
  modelPlaceholder: "留空自动选择",
268
269
  account: "账号",
@@ -338,6 +339,7 @@ window.__ModuleLoader__.load({ id: "@vibedev-si/dsh-vibedev", factory: (require)
338
339
  videoModel: "Video",
339
340
  musicModel: "Music",
340
341
  podcastModel: "Podcasts",
342
+ speechModel: "Speech",
341
343
  transcriptionModel: "Speech to text",
342
344
  modelPlaceholder: "Empty: chosen automatically",
343
345
  account: "Account",
@@ -680,6 +682,7 @@ window.__ModuleLoader__.load({ id: "@vibedev-si/dsh-vibedev", factory: (require)
680
682
  "videoModel",
681
683
  "musicModel",
682
684
  "podcastModel",
685
+ "speechModel",
683
686
  "transcriptionModel"
684
687
  ];
685
688
  /** Every field the page edits. */
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Audio generation requests — music, podcasts and speech — checked against what
3
+ * the chosen model declares in the catalog's `audio` block, and turned into the
4
+ * body of `POST /v1/audio/generations`.
5
+ *
6
+ * Each kind sends only its own fields:
7
+ *
8
+ * | kind | wire fields |
9
+ * | ------- | --------------------------------------------------------------- |
10
+ * | music | model, prompt, lyrics, genre, mood, gender |
11
+ * | podcast | model, prompt, source_url |
12
+ * | speech | as declared; Seed: model, text_prompt, references, audio_config, watermark |
13
+ *
14
+ * The main text goes in the model's `prompt_field`. A field the model does not
15
+ * declare in `request_fields` is refused before anything is uploaded or charged;
16
+ * music and podcasts never take speech references, output formats, sample rates
17
+ * or a duration. Speech references, formats and sample rates come from the
18
+ * catalog only (count, size, length, mutual exclusions, the sample rates of
19
+ * each format), never from a fixed list.
20
+ * @module dsh-vibedev/audio/request
21
+ */
22
+ import type { AudioCapabilities, AudioGenerationKind, MediaModel } from '../gateway/catalog.js';
23
+ import type { AudioQuote } from '../pricing.js';
24
+ import type { MediaCall, MediaRuntime } from '../runtime.js';
25
+ import type { TaskRecord } from '../tasks/store.js';
26
+ /** The kinds of audio a generation request makes. */
27
+ export type AudioMakeKind = Exclude<AudioGenerationKind, 'transcription'>;
28
+ export declare const AUDIO_MAKE_KINDS: readonly AudioMakeKind[];
29
+ /** What to generate. Unset fields are not sent. */
30
+ export interface AudioRequest {
31
+ /** What to make; with a named model it must match the model's declared kind. */
32
+ readonly kind?: AudioMakeKind;
33
+ /** A model id or alias; otherwise the pinned or first model of the kind. */
34
+ readonly model?: string;
35
+ /** The main text: a song description, a podcast topic, or the words to speak. */
36
+ readonly prompt?: string;
37
+ /** Music. */
38
+ readonly lyrics?: string;
39
+ readonly genre?: string;
40
+ readonly mood?: string;
41
+ readonly gender?: string;
42
+ /** Podcast: an http(s) page for the hosts to discuss. */
43
+ readonly sourceUrl?: string;
44
+ /** Speech: reference audio (a voice to imitate) — workspace paths, links or `chat:` attachments. */
45
+ readonly references?: readonly string[];
46
+ /** Speech: an output format the model declares (`wav`, `mp3`, …). */
47
+ readonly format?: string;
48
+ /** Speech: a sample rate the model declares for that format. */
49
+ readonly sampleRate?: number;
50
+ /** Speech: whether the provider adds its watermark, when the model takes the field. */
51
+ readonly watermark?: boolean;
52
+ /** Not an audio-generation parameter; refused for music and podcasts, and for speech unless declared. */
53
+ readonly duration?: number;
54
+ /**
55
+ * One user operation's key: the same key always answers with the same task,
56
+ * so a repeated click or a retried call never creates a second one. Letters,
57
+ * digits, `-` and `_`, at most 80. Generated when absent.
58
+ */
59
+ readonly operationId?: string;
60
+ }
61
+ /**
62
+ * What an audio model makes, from its declaration only.
63
+ * @param model - the model.
64
+ * @returns the kind, or undefined when the catalog does not declare it.
65
+ */
66
+ export declare function audioKindOf(model: MediaModel): AudioMakeKind | undefined;
67
+ /** The wire fields a model takes. */
68
+ export declare function requestFieldsOf(model: MediaModel): readonly string[];
69
+ /** The field the main text goes in. */
70
+ export declare function promptFieldOf(model: MediaModel): string | undefined;
71
+ /** The output format and sample rate a speech request uses, from the declared formats only. */
72
+ export declare function audioConfigOf(model: MediaModel, format: string | undefined, sampleRate: number | undefined): {
73
+ format: string;
74
+ sample_rate?: number;
75
+ } | undefined;
76
+ /**
77
+ * Check a request against the model and build the body, without references
78
+ * (they are uploaded first; their URLs are added by {@link prepareAudioTask}).
79
+ * @param model - the chosen model.
80
+ * @param request - what to generate.
81
+ * @returns the body without references, and the wire fields the request uses.
82
+ * @throws {@link MediaError} for a field the model does not take, a missing text, or a value outside the declared choices.
83
+ */
84
+ export declare function audioRequestBody(model: MediaModel, request: AudioRequest): Record<string, unknown>;
85
+ /**
86
+ * Choose the model for a request: the one named (an id or an alias), else the
87
+ * pinned or first model of the kind. A named model must make the kind asked for.
88
+ */
89
+ export declare function chooseAudioModel(runtime: MediaRuntime, request: Pick<AudioRequest, 'kind' | 'model'>, signal?: AbortSignal): Promise<MediaModel>;
90
+ /** A checked, priced audio task ready to submit. */
91
+ export interface PreparedAudio {
92
+ readonly model: MediaModel;
93
+ readonly kind: AudioMakeKind;
94
+ readonly quote: AudioQuote;
95
+ readonly draft: TaskRecord;
96
+ }
97
+ /**
98
+ * Everything before an audio submission: choose the model, check every field
99
+ * against its declaration, upload and measure speech references, price it,
100
+ * confirm the spending, and build the task under the operation's key.
101
+ * @param runtime - the media runtime.
102
+ * @param call - the tool call or host call.
103
+ * @param request - what to generate.
104
+ * @param save - where the result goes.
105
+ * @returns the prepared task.
106
+ */
107
+ export declare function prepareAudioTask(runtime: MediaRuntime, call: MediaCall, request: AudioRequest, save: {
108
+ readonly folder: string;
109
+ readonly stem: string;
110
+ }): Promise<PreparedAudio>;
111
+ /** One field of an audio form, for interfaces that build their form from the catalog. */
112
+ export interface AudioFormField {
113
+ /** The {@link AudioRequest} key. */
114
+ readonly key: 'prompt' | 'lyrics' | 'genre' | 'mood' | 'gender' | 'sourceUrl' | 'references' | 'format' | 'sampleRate' | 'watermark';
115
+ /** The wire field it is sent as. */
116
+ readonly wire: string;
117
+ readonly required: boolean;
118
+ /** Declared choices. */
119
+ readonly choices?: readonly string[];
120
+ /** For `sampleRate`: the rates of each format. */
121
+ readonly sampleRates?: Readonly<Record<string, readonly number[]>>;
122
+ /** For `references`: the declared limits. */
123
+ readonly limits?: NonNullable<AudioCapabilities['references']>;
124
+ readonly maxChars?: number;
125
+ }
126
+ /** What a form for one audio model shows. */
127
+ export interface AudioForm {
128
+ readonly model: string;
129
+ readonly name: string;
130
+ readonly kind: AudioMakeKind;
131
+ readonly fields: readonly AudioFormField[];
132
+ readonly price: AudioQuote;
133
+ readonly defaultFormat?: string;
134
+ }
135
+ /**
136
+ * The form an interface shows for one model: only the fields the model
137
+ * declares, with their declared choices and limits.
138
+ * @param model - the model.
139
+ * @returns the form, or undefined for a model that cannot generate audio.
140
+ */
141
+ export declare function audioFormOf(model: MediaModel): AudioForm | undefined;
@@ -25,8 +25,8 @@ export interface UploadedAsset {
25
25
  readonly sha256: string;
26
26
  readonly bytes: number;
27
27
  }
28
- /** Purposes the plugin uploads under. */
29
- export type AssetPurpose = 'video_reference';
28
+ /** Purposes the plugin uploads under: references of a video request, and the reference audio of a speech request. */
29
+ export type AssetPurpose = 'video_reference' | 'audio_reference' | (string & {});
30
30
  /**
31
31
  * Read an asset answer from `uploads`, `complete` or `refresh`.
32
32
  * @param body - the parsed answer.
@@ -8,6 +8,12 @@
8
8
  * the versioned per-mode declarations (`modes_schema_version: 1`). A mode the
9
9
  * model does not list is unsupported; an unknown schema version makes the model
10
10
  * unusable rather than guessed at.
11
+ *
12
+ * Audio capabilities follow the `audio` block: `generation_kind` (music,
13
+ * podcast, speech or transcription), `prompt_field`, `request_fields`,
14
+ * `billing_unit` and the declared limits (references, output formats and their
15
+ * sample rates). An audio model that declares no kind is listed but cannot be
16
+ * chosen for generation: neither its name nor its id decides what it makes.
11
17
  * @module dsh-vibedev/gateway/catalog
12
18
  */
13
19
  /** What a media model produces. */
@@ -81,10 +87,16 @@ export interface VideoCapabilities {
81
87
  /** References must be relayed through the gateway media library. */
82
88
  readonly gatewayRelayRequired?: boolean;
83
89
  }
90
+ /**
91
+ * What a price is charged per: one generation, one second of output, one
92
+ * second of ORIGINAL audio (speech is billed on the provider's original length,
93
+ * not on what plays back after processing), or one minute of input audio.
94
+ */
95
+ export type PriceUnit = 'generation' | 'second' | 'original_second' | 'minute';
84
96
  /** One price tier: video tiers are resolutions (`720p`), image tiers size buckets (`1K`). */
85
97
  export interface MediaPriceTier {
86
98
  readonly tier: string;
87
- readonly unit: 'generation' | 'second';
99
+ readonly unit: PriceUnit;
88
100
  readonly amount: number;
89
101
  }
90
102
  /** A model's selling price, account multiplier included. */
@@ -92,23 +104,76 @@ export interface MediaPricing {
92
104
  readonly currency: string;
93
105
  readonly tiers: readonly MediaPriceTier[];
94
106
  readonly default?: {
95
- readonly unit: 'generation' | 'second';
107
+ readonly unit: PriceUnit;
96
108
  readonly amount: number;
97
109
  };
98
110
  }
111
+ /** What an audio model does, as the catalog declares it (`audio.generation_kind`). */
112
+ export declare const AUDIO_GENERATION_KINDS: readonly ["music", "podcast", "speech", "transcription"];
113
+ export type AudioGenerationKind = typeof AUDIO_GENERATION_KINDS[number];
114
+ /** How an audio model is billed (`audio.billing_unit`). */
115
+ export type AudioBillingUnit = 'generation' | 'original_second' | 'minute';
116
+ /** The reference audio a speech model takes (a voice to imitate), as the catalog declares it. */
117
+ export interface AudioReferenceLimits {
118
+ readonly min: number;
119
+ readonly max: number;
120
+ readonly maxBytes?: number;
121
+ readonly minSeconds?: number;
122
+ readonly maxSeconds?: number;
123
+ readonly maxTotalSeconds?: number;
124
+ /** Accepted MIME types; absent states no restriction. */
125
+ readonly mimes?: readonly string[];
126
+ /** Request fields that may not be sent together with references. */
127
+ readonly exclusiveWith?: readonly string[];
128
+ /** The media-library purpose references are uploaded under, when the catalog names one. */
129
+ readonly purpose?: string;
130
+ }
131
+ /** One output format a speech model can write, with the sample rates it takes in that format. */
132
+ export interface AudioOutputFormat {
133
+ readonly format: string;
134
+ readonly sampleRates: readonly number[];
135
+ readonly defaultSampleRate?: number;
136
+ }
137
+ /**
138
+ * An audio model's declared capabilities. Nothing here is assumed: a field the
139
+ * catalog does not declare is absent, and a model without `generationKind`
140
+ * cannot be chosen for any kind of generation.
141
+ */
142
+ export interface AudioCapabilities {
143
+ readonly generationKind?: AudioGenerationKind;
144
+ /** The request field the main text goes in (`prompt`, `text_prompt`, …). */
145
+ readonly promptField?: string;
146
+ /** The request fields the model accepts, under their wire names. */
147
+ readonly requestFields: readonly string[];
148
+ readonly billingUnit?: AudioBillingUnit;
149
+ readonly references?: AudioReferenceLimits;
150
+ readonly outputFormats?: readonly AudioOutputFormat[];
151
+ readonly defaultFormat?: string;
152
+ /** Declared choices for enumerated fields (`gender`, `genre`, …), under their wire names. */
153
+ readonly choices?: Readonly<Record<string, readonly string[]>>;
154
+ readonly maxPromptChars?: number;
155
+ /** Transcription input limits. */
156
+ readonly maxInputBytes?: number;
157
+ readonly maxInputSeconds?: number;
158
+ readonly inputMimes?: readonly string[];
159
+ readonly languages?: readonly string[];
160
+ }
99
161
  /** One media model of the catalog. */
100
162
  export interface MediaModel {
101
163
  readonly id: string;
102
164
  readonly name: string;
103
165
  readonly description?: string;
104
166
  readonly kind: MediaKind;
105
- /** For audio models: what they produce. */
106
- readonly audioKind?: 'music' | 'podcast';
167
+ /** Other ids the gateway answers to for this model. */
168
+ readonly aliases?: readonly string[];
169
+ /** For audio models: what they produce, from `audio.generation_kind` only; absent when undeclared. */
170
+ readonly audioKind?: Exclude<AudioGenerationKind, 'transcription'>;
107
171
  /** Endpoints the catalog lists for the model. */
108
172
  readonly endpoints: readonly string[];
109
173
  readonly inputModalities: readonly string[];
110
174
  readonly pricing?: MediaPricing;
111
175
  readonly video?: VideoCapabilities;
176
+ readonly audio?: AudioCapabilities;
112
177
  }
113
178
  type Json = Record<string, unknown>;
114
179
  /**
@@ -124,6 +189,12 @@ export declare function parseVideoCapabilities(raw: Json): VideoCapabilities;
124
189
  * @returns the usable modes and their constraints.
125
190
  */
126
191
  export declare function effectiveVideoModes(video: VideoCapabilities): Partial<Record<VideoMode, VideoModeConstraint>>;
192
+ /**
193
+ * Parse an audio capability block.
194
+ * @param raw - the block.
195
+ * @returns the declared capabilities; `generationKind` is absent unless declared.
196
+ */
197
+ export declare function parseAudioCapabilities(raw: Json): AudioCapabilities;
127
198
  /**
128
199
  * Parse a `/v1/models` body into its media models.
129
200
  * @param body - `{data:[...]}` or a bare array.
package/lib/index.d.ts CHANGED
@@ -24,11 +24,13 @@ import type { Context, Volatile } from '@deepseek-ai/cordis';
24
24
  import Schema from '@deepseek-ai/schemastery';
25
25
  export { MediaError } from './gateway/errors.js';
26
26
  export { MediaHostService } from './service.js';
27
- export type { HostTarget, MediaTaskView } from './service.js';
27
+ export type { HostTarget, MediaOutputView, MediaTaskView } from './service.js';
28
+ export type { AudioForm, AudioFormField, AudioMakeKind, AudioRequest } from './audio/request.js';
29
+ export type { AudioQuote } from './pricing.js';
28
30
  export type { ImageRequest } from './tools/image.js';
29
31
  export type { VideoRequest } from './tools/video.js';
30
32
  export { parseMediaCatalog } from './gateway/catalog.js';
31
- export type { MediaModel, VideoCapabilities, VideoMode } from './gateway/catalog.js';
33
+ export type { AudioCapabilities, AudioGenerationKind, MediaModel, PriceUnit, VideoCapabilities, VideoMode } from './gateway/catalog.js';
32
34
  export { ACCOUNT_ROUTE_PREFIX, AccountService } from './account/index.js';
33
35
  export type { AccountSource, AccountView } from './account/index.js';
34
36
  export { GATEWAY_SEARCH_PROVIDER_ID as SEARCH_PROVIDER_ID } from './search/provider.js';
@@ -55,6 +57,7 @@ export interface Config {
55
57
  videoModel: Volatile<string>;
56
58
  musicModel: Volatile<string>;
57
59
  podcastModel: Volatile<string>;
60
+ speechModel: Volatile<string>;
58
61
  transcriptionModel: Volatile<string>;
59
62
  /** Gateway origin. */
60
63
  gatewayOrigin: string;
@@ -78,6 +81,7 @@ export declare const Config: Schema<Schemastery.ObjectS<NoInfer<{
78
81
  videoModel: Schema<string, string, "volatile-defined">;
79
82
  musicModel: Schema<string, string, "volatile-defined">;
80
83
  podcastModel: Schema<string, string, "volatile-defined">;
84
+ speechModel: Schema<string, string, "volatile-defined">;
81
85
  transcriptionModel: Schema<string, string, "volatile-defined">;
82
86
  gatewayOrigin: Schema<string, string, "defined">;
83
87
  client: Schema<string, string, "defined">;
@@ -95,6 +99,7 @@ export declare const Config: Schema<Schemastery.ObjectS<NoInfer<{
95
99
  videoModel: Schema<string, string, "volatile-defined">;
96
100
  musicModel: Schema<string, string, "volatile-defined">;
97
101
  podcastModel: Schema<string, string, "volatile-defined">;
102
+ speechModel: Schema<string, string, "volatile-defined">;
98
103
  transcriptionModel: Schema<string, string, "volatile-defined">;
99
104
  gatewayOrigin: Schema<string, string, "defined">;
100
105
  client: Schema<string, string, "defined">;