@cartanova/qgrid-ai-sdk 2.10.10 → 2.11.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.ko.md CHANGED
@@ -53,6 +53,7 @@ qgrid 서버(`http://localhost:44900`)가 실행 중이어야 합니다.
53
53
  OpenAI 서버 경로는 private ChatGPT Codex Responses backend를 HTTPS/SSE로 직접 호출합니다. 이 backend는 문서화되지 않아 예고 없이 변경될 수 있으며, qgrid의 mock protocol test는 live provider 검증이 아닙니다.
54
54
 
55
55
  ## 사용법
56
+ >
56
57
  > 들어가기전에: 모든 클라이언트 사용법은 [AI-SDK](https://ai-sdk.dev/docs/ai-sdk-core)와 동일합니다.
57
58
 
58
59
  ### 텍스트 생성
@@ -69,6 +70,7 @@ const { text } = await generateText({
69
70
  ```
70
71
 
71
72
  ### 구조화 응답 (Structured Output)
73
+ >
72
74
  > [AI-SDK structured output guide를 참조하세요](https://ai-sdk.dev/docs/ai-sdk-core/generating-structured-data)
73
75
 
74
76
  ```typescript
@@ -200,7 +202,7 @@ const { text } = await generateText({
200
202
  ```
201
203
 
202
204
  | 옵션 | 값 | 적용 범위 | 설명 |
203
- |---|---|---|---|
205
+ | --- | --- | --- | --- |
204
206
  | `tokenName` | provider prefix를 포함한 토큰 이름 | 공통 | `anthropic/yds`처럼 활성 토큰 하나를 엄격히 지정. prefix는 model provider와 같아야 하며 빈 값·누락·inactive·quota 초과 시 다른 토큰으로 fallback하지 않음 |
205
207
  | `logger` | `boolean` | 공통 | qgrid request log 저장 여부. 기본값은 `true`. `false`로 설정해도 client tool 실행과 multi-step 연결은 계속 동작 |
206
208
  | `sessionKey` | `string` | OpenAI 전용 | 전체 history 재전송 시 불투명 prompt-cache affinity를 파생하는 멀티턴 대화 식별자 ([아래](#멀티턴-prompt-cache-sessionkey) 참조) |
@@ -236,7 +238,7 @@ providerOptions: {
236
238
  Thinking 비활성화 정책 스냅샷(2026-10-10, Claude Code 조사 기준 2.1.295):
237
239
 
238
240
  | Provider | 현재 정책에서 off를 허용하는 모델 ID |
239
- |---|---|
241
+ | --- | --- |
240
242
  | OpenAI | `gpt-6-sol`, `gpt-6-luna`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.5` |
241
243
  | Anthropic | `claude-haiku-5-5`, `claude-sonnet-5-5`, `claude-haiku-4-5`, `claude-sonnet-4-5`, `claude-sonnet-4-6`, `claude-sonnet-5`, `claude-opus-4-5`, `claude-opus-4-6`, `claude-opus-4-7`, `claude-opus-4-8`, `claude-opus-5` |
242
244
 
@@ -333,6 +335,156 @@ Images를 직접 호출하고 요청 로그에는 채팅과 이미지 usage의
333
335
  텍스트만 응답할 수도 있습니다. 공개 SDK 도구 팩토리는 제공하지 않으며, 자동 채팅 이미지도
334
336
  `generateImage`와 같이 PNG만 지원합니다.
335
337
 
338
+ ## Grok 사용
339
+
340
+ qgrid는 `grok/*` 모델을 qgrid 대시보드에 등록한 xAI 구독 토큰(요금제: Plus, Premium, Super, Ultra)(Grok 로그인)으로 라우팅합니다.
341
+ 토큰 이름은 `grok/` prefix를 가집니다(예: `grok/main`). 모든 Grok 모델은 다른 모델과 같은 factory
342
+ 설정을 받습니다: `serverUrl`(기본값 `QGRID_URL`), `projectName`(기본값 `QGRID_PROJECT_NAME`).
343
+ 서버와 SDK를 함께 업데이트하세요.
344
+
345
+ | Factory | 모델 ID | AI SDK 함수 |
346
+ | --- | --- | --- |
347
+ | `qgrid(id)` | `grok/grok-4.7`(카탈로그 기본 모델), `grok/grok-4.7-build-fast`, `grok/grok-4.6`, `grok/grok-4.5`, 그 밖의 `grok/<id>` | `generateText`, `streamText` |
348
+ | `qgrid.image(id)` | `grok/grok-imagine-image`, `grok/grok-imagine-image-2.0`, `grok/grok-imagine-image-quality` | `generateImage` |
349
+ | `qgrid.video(id)` | `grok/grok-imagine-video`, `grok/grok-imagine-video-1.5`, `grok/grok-imagine-video-1.5-lite` | `experimental_generateVideo` |
350
+ | `qgrid.transcription(id)` | `grok/grok-voice-transcribe-2.0` | `experimental_transcribe` |
351
+ | `qgrid.speech(id)` | `grok/grok-tts`(ID는 request log 라벨로만 쓰임) | `experimental_generateSpeech` |
352
+
353
+ qgrid는 카탈로그에 없는 language model ID를 거부하지 않고 그대로 전달합니다(OpenAI와 같음). 판단은
354
+ subscription backend가 하며 다른 모델로 응답할 수 있으므로, 실제로 실행된 모델은 request log의 응답 모델(또는
355
+ 결과의 response metadata)에서 확인하세요.
356
+
357
+ 옵션은 `providerOptions.xai` 아래에 `@ai-sdk/xai`와 같은 이름을 쓰므로 `@ai-sdk/xai`용 코드가 그대로
358
+ 컴파일됩니다. qgrid 전용 설정(`grok/` prefix를 포함한 `tokenName`, `logger`)은 `providerOptions.qgrid`에
359
+ 둡니다. 형식이 잘못된 값은 요청 전에 예외를 던지고, 형식은 맞지만 qgrid가 지원하지 않는 옵션은 AI SDK
360
+ `unsupported` warning과 함께 무시됩니다.
361
+
362
+ ### Grok 텍스트
363
+
364
+ ```typescript
365
+ import { generateText } from "ai";
366
+ import { qgrid } from "@cartanova/qgrid-ai-sdk";
367
+
368
+ const { text, providerMetadata } = await generateText({
369
+ model: qgrid("grok/grok-4.7"),
370
+ prompt: "Summarize this release note",
371
+ providerOptions: { xai: { reasoningEffort: "high", promptCacheKey: "session-42" } },
372
+ });
373
+ providerMetadata?.xai?.costInUsdTicks; // 1 tick = 1e-10 USD
374
+ ```
375
+
376
+ Grok language model은 user 이미지 part(https URL 또는 inline bytes)를 버리지 않고 전달합니다.
377
+
378
+ | `providerOptions.xai` 키 | Language model 처리 |
379
+ | --- | --- |
380
+ | `promptCacheKey` | 그대로 전달: `providerOptions.qgrid.sessionKey`와 같은 cache affinity 핸들 |
381
+ | `serviceTier` | 미지원: Grok subscription proxy의 처리 방식이 검증되지 않음(raw API 요청에 넣으면 400) |
382
+ | `parallelToolCalls` | 미지원: Grok subscription proxy의 처리 방식이 검증되지 않음(raw API 요청에 넣으면 400) |
383
+ | `reasoningEffort` | qgrid `effort`로 변환, 모델의 `low`/`medium`/`high`/`xhigh` 집합으로 검증. 이 경로는 항상 reasoning하므로 `none`은 미지원 |
384
+ | `store` | 미지원: qgrid는 항상 `store: false`를 보냄 |
385
+ | `previousResponseId` | 미지원: qgrid가 대화 history를 직접 재생함 |
386
+ | `include` | 미지원: qgrid가 include 목록을 고정함 |
387
+ | `maxTurns` | 미지원: qgrid는 서버 측 agentic turn을 실행하지 않음 |
388
+ | `user`, `safetyIdentifier` | 미지원: qgrid는 최종 사용자 식별자를 전달하지 않음 |
389
+
390
+ ### Grok 미디어 옵션
391
+
392
+ | 모델 | 그대로 전달 | 변환 | 미지원(warning) |
393
+ | --- | --- | --- | --- |
394
+ | Image | `n`(호출당 최대 3), `aspectRatio`, `xai.resolution`(`1k`/`1.5k`/`2k`), `xai.quality`, `xai.aspect_ratio`(`aspectRatio`가 없을 때) | 참조 `images`는 `referenceImages`(edit endpoint), `xai.output_format`은 `outputFormat`이 되며 `png`, `jpeg`, `webp`만 허용 | `size`, `seed`, `mask`, `xai.sync_mode`, `xai.user` |
395
+ | Video | `duration`(정수 1-15), `aspectRatio`, `xai.resolution`(`480p`/`720p`/`1080p`), `xai.mode: "reference-to-video"`(지원하는 유일한 mode, `xai.referenceImageUrls` 필요), `xai.pollIntervalMs`, `xai.pollTimeoutMs` | `resolution` `WxH`는 `@ai-sdk/xai`와 같이 매핑(`1280x720` → `720p`), prompt `image`는 시작 프레임, `xai.referenceImageUrls`(7개가 아닌 최대 5개)는 `referenceImages`, `xai.lastFrame`(qgrid 확장, `grok-imagine-video-1.5` 전용) | `fps`, `seed`, `xai.keyframes`, `xai.storageOptions`, `xai.referenceVoiceIds`, `xai.user`. `xai.mode` `edit-video`/`extend-video`와 `xai.videoUrl`은 예외 |
396
+ | Transcription | `xai.language` | 오디오 bytes는 base64로, `mediaType`은 파라미터 제거(`audio/webm;codecs=opus` → `audio/webm`) | 나머지 모든 `xai` 키(`audioFormat`, `sampleRate`, `format`, `diarize`, `keyterm`, ...) |
397
+ | Speech | `voice`, `language` | `outputFormat`은 `format`(`mp3`, `wav`, `pcm`, `mulaw`, `alaw`, 그 외 값은 `@ai-sdk/xai`처럼 warning과 함께 `mp3`) | `instructions`, `speed`, 모든 `xai` 키(`sampleRate`, `bitRate`, `withTimestamps`, ...) |
398
+
399
+ **요청 크기.** qgrid 서버는 최대 10 MiB JSON body를 받습니다. inline 미디어는 base64로 전송되어 3분의 1만큼
400
+ 커지므로, 서버는 inline 오디오, 각 inline 이미지, 한 요청의 inline 이미지 합계(비디오: `image` + `lastFrame` +
401
+ 참조 이미지)를 디코딩 기준 7 MiB로 제한합니다. SDK는 더 큰 입력을 전송 전에 거부하고, 서버 413도 같은 크기
402
+ 오류로 보여줍니다. 입력을 압축하거나, 옵션이 허용하면 https 이미지 URL을 넘기세요.
403
+
404
+ ### Grok 이미지
405
+
406
+ ```typescript
407
+ import { generateImage } from "ai";
408
+ import { qgrid } from "@cartanova/qgrid-ai-sdk";
409
+
410
+ const { images, providerMetadata } = await generateImage({
411
+ model: qgrid.image("grok/grok-imagine-image"),
412
+ prompt: "A lighthouse at dusk, oil painting",
413
+ n: 2,
414
+ aspectRatio: "16:9",
415
+ providerOptions: { xai: { resolution: "2k", quality: "high", output_format: "jpeg" } },
416
+ });
417
+ images[0].mediaType; // "image/jpeg"
418
+ providerMetadata.xai?.images[0]; // revisedPrompt와 해당 호출의 costInUsdTicks
419
+ providerMetadata.qgrid?.images[0]; // mediaType, tokenName, requestLogId, costUsd
420
+ ```
421
+
422
+ `generateImage`는 배치 호출의 `images` 배열만 합치므로, 각 호출의 비용은 그 호출의 첫 이미지 항목에 담깁니다.
423
+
424
+ ### Grok 비디오
425
+
426
+ ```typescript
427
+ import { experimental_generateVideo as generateVideo } from "ai";
428
+ import { qgrid, QgridVideoTimeoutError, resumeQgridVideo } from "@cartanova/qgrid-ai-sdk";
429
+
430
+ try {
431
+ const { video, providerMetadata } = await generateVideo({
432
+ model: qgrid.video("grok/grok-imagine-video-1.5", { projectName: "studio" }),
433
+ prompt: "A paper boat drifting down a rain gutter",
434
+ duration: 6,
435
+ aspectRatio: "16:9",
436
+ providerOptions: { xai: { resolution: "720p" } },
437
+ });
438
+ providerMetadata.xai?.videoUrl; // api.x.ai URL
439
+ video.uint8Array; // qgrid가 아니라 이 프로세스에서 AI SDK가 다운로드
440
+ } catch (error) {
441
+ if (error instanceof QgridVideoTimeoutError) {
442
+ const { videos } = await resumeQgridVideo(error.jobHandle, { projectName: "studio" });
443
+ videos[0]; // { type: "url", url, mediaType: "video/mp4" }
444
+ } else {
445
+ throw error;
446
+ }
447
+ }
448
+ ```
449
+
450
+ - 모델은 `videoStart` 후 300초 예산 안에서 5초마다 `videoStatus`를 polling합니다(`xai.pollIntervalMs` / `xai.pollTimeoutMs`로 변경). 예산이 끝나면 진행 중인 status 요청도 끊으므로 호출은 제때 `QgridVideoTimeoutError`로 끝납니다. `abortSignal`은 polling만 멈추며 upstream job은 계속 실행됩니다.
451
+ - start와 status의 `projectName`은 반드시 같아야 합니다. 서버는 job을 시작한 project에만 job handle 결과를 돌려줍니다. factory나 `QGRID_PROJECT_NAME`으로 한 번 지정하고, `resumeQgridVideo`에도 같은 값을 넘기세요.
452
+ - 결과는 `@ai-sdk/xai`와 똑같이 `{ type: "url", url, mediaType: "video/mp4" }`입니다. URL은 `api.x.ai` 저장소를 가리키며 qgrid는 비디오를 가져오거나 프록시하거나 저장하지 않습니다. `experimental_generateVideo`는 호출한 프로세스에서 이 URL을 다운로드합니다. URL만 쓰려면 `download`를 직접 넘기세요.
453
+ - AI SDK v3 video model에는 `doGenerate`만 있습니다(`doStart`/`doStatus` 없음). 시간 초과된 job은 `resumeQgridVideo(jobHandle, options)`로 이어서 기다립니다. handle은 `providerMetadata.qgrid.jobHandle`과 `QgridVideoTimeoutError` / `QgridVideoGenerationError`에도 있습니다.
454
+ - 비디오 생성은 ZDR이 아닌 계정에서 live 검증되었습니다(기본 길이 8초; `experimental_generateVideo`의 최상위 `duration` 옵션으로 변경). Zero Data Retention 계정은 xAI가 거부하므로 비디오 라우팅에서 제외됩니다.
455
+ - 비디오는 Zero Data Retention 계정으로 라우팅되지 않습니다. xAI가 이런 계정에 `output.upload_url`을 요구하는데 qgrid는 이를 지원하지 않습니다. 모든 토큰이 ZDR이면 HTTP 503으로 실패하므로, xAI에서 data-retention opt-out을 끄거나 ZDR이 아닌 계정을 추가하세요.
456
+
457
+ ### Grok 음성 인식과 음성 합성
458
+
459
+ ```typescript
460
+ import { readFile } from "node:fs/promises";
461
+ import {
462
+ experimental_generateSpeech as generateSpeech,
463
+ experimental_transcribe as transcribe,
464
+ } from "ai";
465
+ import { qgrid } from "@cartanova/qgrid-ai-sdk";
466
+
467
+ const transcript = await transcribe({
468
+ model: qgrid.transcription("grok/grok-voice-transcribe-2.0"),
469
+ audio: await readFile("meeting.mp3"),
470
+ providerOptions: { xai: { language: "en" } },
471
+ });
472
+ transcript.text;
473
+ transcript.durationInSeconds;
474
+
475
+ const speech = await generateSpeech({
476
+ model: qgrid.speech("grok/grok-tts"),
477
+ text: "Your build is ready.",
478
+ voice: "ara",
479
+ language: "en",
480
+ outputFormat: "mp3",
481
+ });
482
+ speech.audio.uint8Array;
483
+ ```
484
+
485
+ - `experimental_transcribe`는 bytes로 오디오 형식을 감지하고 실패하면 `audio/wav`를 씁니다. 서버는 `audio/*`가 아닌 값을 거부합니다. transcript에는 segment가 없습니다(`segments: []`).
486
+ - 음성 합성 텍스트는 최대 15,000자입니다. `voice`, `language`, `outputFormat`을 지정하지 않으면 서버 기본값 `ara`, `en`, `mp3`가 쓰이며, live 검증된 조합은 이것뿐입니다. 다른 voice, language(`@ai-sdk/xai`의 `auto` 포함), codec은 그대로 전달되지만 미검증입니다. 서버가 돌려준 오디오 MIME 타입은 `providerMetadata.qgrid.mediaType`에 있고, AI SDK의 `speech.audio.mediaType`은 bytes에서 추정한 값입니다.
487
+
336
488
  ## Telemetry Logger
337
489
 
338
490
  서버와 AI SDK 2.10.0부터 qgrid provider의 `generateText` 결과에서는 `result.providerMetadata?.qgrid?.requestLogId`로 요청 로그 ID를 확인할 수 있습니다. `streamText`는 스트림 소비 후 `(await result.providerMetadata)?.qgrid?.requestLogId`로 확인합니다. 직접 API를 호출하면 `query` 응답과 스트림 `done` 이벤트의 최상위 `requestLogId`에 같은 값이 담깁니다. `logger: false` 또는 구버전 서버에서는 이 필드가 없으며, 툴 호출 후속 단계는 같은 요청 로그 ID를 공유합니다. 이 ID는 후속 요청 연결 상태가 아니며, 아래 telemetry logger를 쓰는 외부 provider에는 이 metadata가 추가되지 않습니다.
@@ -443,7 +595,7 @@ type QgridSupportedModel =
443
595
  ### GPT-6 사양
444
596
 
445
597
  | 모델 | Context (Codex 카탈로그) | 최대 출력 (공개 API) | 1M tokens당 input / cached input / cache write / output |
446
- |---|---:|---:|---:|
598
+ | --- | ---: | ---: | ---: |
447
599
  | `openai/gpt-6-astra` | 272K | 128K | $10 / $1 / $12.50 / $50 |
448
600
  | `openai/gpt-6.1-sol` | 272K | 128K | $2 / $0.10 / $2.50 / $10 |
449
601
  | `openai/gpt-6-sol` | 272K | 128K | $2 / $0.20 / $2.50 / $10 |
@@ -454,7 +606,7 @@ type QgridSupportedModel =
454
606
  ### GPT-5.6 사양
455
607
 
456
608
  | 모델 | Context (Codex 카탈로그) | 최대 출력 (공개 API) | 1M tokens당 input / cached input / cache write / output |
457
- |---|---:|---:|---:|
609
+ | --- | ---: | ---: | ---: |
458
610
  | `openai/gpt-5.6-sol` | 272K | 128K | $4 / $0.40 / $5 / $20 |
459
611
  | `openai/gpt-5.6-terra` | 272K | 128K | $2 / $0.20 / $2.50 / $12 |
460
612
  | `openai/gpt-5.6-luna` | 272K | 128K | $0.20 / $0.02 / $0.25 / $1.20 |
@@ -496,7 +648,7 @@ qgrid(modelId, {
496
648
  ## 환경변수
497
649
 
498
650
  | 변수 | 설명 | 기본값 |
499
- |---|---|---|
651
+ | --- | --- | --- |
500
652
  | `QGRID_URL` | qgrid 서버 주소 | `http://localhost:44900` |
501
653
  | `QGRID_PROJECT_NAME` | request log 프로젝트 이름 (provider/logger 공통) | (없음) |
502
654
 
package/README.md CHANGED
@@ -53,6 +53,7 @@ A qgrid server (`http://localhost:44900`) must be running.
53
53
  The OpenAI server route calls the private ChatGPT Codex Responses backend directly over HTTPS/SSE. That backend is undocumented and may change without notice; qgrid's mocked protocol tests are not live-provider verification.
54
54
 
55
55
  ## Usage
56
+ >
56
57
  > Before you start: all client-side usage is identical to the [AI SDK](https://ai-sdk.dev/docs/ai-sdk-core).
57
58
 
58
59
  ### Text generation
@@ -69,6 +70,7 @@ const { text } = await generateText({
69
70
  ```
70
71
 
71
72
  ### Structured Output
73
+ >
72
74
  > See the [AI SDK structured output guide](https://ai-sdk.dev/docs/ai-sdk-core/generating-structured-data)
73
75
 
74
76
  ```typescript
@@ -209,7 +211,7 @@ const { text } = await generateText({
209
211
  ```
210
212
 
211
213
  | Option | Values | Applies to | Description |
212
- |---|---|---|---|
214
+ | --- | --- | --- | --- |
213
215
  | `tokenName` | provider-prefixed token name | both providers | Strictly targets one active token, such as `anthropic/yds`. The prefix must match the model provider; empty, missing, inactive, or over-threshold targets fail without fallback |
214
216
  | `logger` | `boolean` | both providers | qgrid request logging. Defaults to `true`; `false` disables request-log persistence for this generation without disabling client tools or multi-step continuation |
215
217
  | `sessionKey` | `string` | OpenAI only | Multi-turn conversation identifier used to derive opaque prompt-cache affinity while replaying full history (see [below](#multi-turn-prompt-cache-sessionkey)) |
@@ -245,7 +247,7 @@ providerOptions: {
245
247
  Thinking-off policy snapshot (2026-10-10; Claude Code investigation baseline 2.1.295):
246
248
 
247
249
  | Provider | Off-capable model IDs in the current policy |
248
- |---|---|
250
+ | --- | --- |
249
251
  | OpenAI | `gpt-6-sol`, `gpt-6-luna`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.5` |
250
252
  | Anthropic | `claude-haiku-5-5`, `claude-sonnet-5-5`, `claude-haiku-4-5`, `claude-sonnet-4-5`, `claude-sonnet-4-6`, `claude-sonnet-5`, `claude-opus-4-5`, `claude-opus-4-6`, `claude-opus-4-7`, `claude-opus-4-8`, `claude-opus-5` |
251
253
 
@@ -343,6 +345,158 @@ output, then combines separate chat and image usage estimates in the request log
343
345
  still return text only. No public SDK image-tool factory is required; automatic chat images
344
346
  are PNG-only, like `generateImage`.
345
347
 
348
+ ## Using Grok
349
+
350
+ qgrid routes `grok/*` models through an xAI subscription token (plans: Plus, Premium, Super, Ultra) registered in the qgrid
351
+ dashboard (Grok sign-in). Token names carry the `grok/` prefix, for example `grok/main`. Every
352
+ Grok model accepts the same factory config as the other models: `serverUrl` (default
353
+ `QGRID_URL`) and `projectName` (default `QGRID_PROJECT_NAME`). Update the server and SDK together.
354
+
355
+ | Factory | Model ids | AI SDK function |
356
+ | --- | --- | --- |
357
+ | `qgrid(id)` | `grok/grok-4.7` (default catalog model), `grok/grok-4.7-build-fast`, `grok/grok-4.6`, `grok/grok-4.5`, any other `grok/<id>` | `generateText`, `streamText` |
358
+ | `qgrid.image(id)` | `grok/grok-imagine-image`, `grok/grok-imagine-image-2.0`, `grok/grok-imagine-image-quality` | `generateImage` |
359
+ | `qgrid.video(id)` | `grok/grok-imagine-video`, `grok/grok-imagine-video-1.5`, `grok/grok-imagine-video-1.5-lite` | `experimental_generateVideo` |
360
+ | `qgrid.transcription(id)` | `grok/grok-voice-transcribe-2.0` | `experimental_transcribe` |
361
+ | `qgrid.speech(id)` | `grok/grok-tts` (the id only labels the request log) | `experimental_generateSpeech` |
362
+
363
+ qgrid forwards a language-model id that is not in its catalog unchanged instead of rejecting it,
364
+ as it does for OpenAI; the subscription backend decides. It may serve a different model, so check
365
+ the response model in the request log (or the result's response metadata) to see which one ran.
366
+
367
+ Options use the `@ai-sdk/xai` names under `providerOptions.xai`, so code written for
368
+ `@ai-sdk/xai` keeps compiling. qgrid-only settings (`tokenName` with the `grok/` prefix, `logger`)
369
+ stay under `providerOptions.qgrid`. Malformed values throw before any request; well-formed
370
+ options qgrid cannot honor are dropped with an AI SDK `unsupported` warning.
371
+
372
+ ### Grok text
373
+
374
+ ```typescript
375
+ import { generateText } from "ai";
376
+ import { qgrid } from "@cartanova/qgrid-ai-sdk";
377
+
378
+ const { text, providerMetadata } = await generateText({
379
+ model: qgrid("grok/grok-4.7"),
380
+ prompt: "Summarize this release note",
381
+ providerOptions: { xai: { reasoningEffort: "high", promptCacheKey: "session-42" } },
382
+ });
383
+ providerMetadata?.xai?.costInUsdTicks; // 1 tick = 1e-10 USD
384
+ ```
385
+
386
+ Grok language models keep user image parts (https URLs or inline bytes) instead of dropping them.
387
+
388
+ | `providerOptions.xai` key | Language model handling |
389
+ | --- | --- |
390
+ | `promptCacheKey` | Faithful: the same cache-affinity handle as `providerOptions.qgrid.sessionKey` |
391
+ | `serviceTier` | Unsupported: the Grok subscription proxy's handling is unverified (a raw API request with it gets a 400) |
392
+ | `parallelToolCalls` | Unsupported: the Grok subscription proxy's handling is unverified (a raw API request with it gets a 400) |
393
+ | `reasoningEffort` | Transformed to qgrid `effort`, validated against the model's `low`/`medium`/`high`/`xhigh` set; `none` is unsupported because the route always reasons |
394
+ | `store` | Unsupported: qgrid always sends `store: false` |
395
+ | `previousResponseId` | Unsupported: qgrid replays conversation history itself |
396
+ | `include` | Unsupported: qgrid fixes the include list itself |
397
+ | `maxTurns` | Unsupported: qgrid does not run server-side agentic turns |
398
+ | `user`, `safetyIdentifier` | Unsupported: qgrid does not forward end-user identifiers |
399
+
400
+ ### Grok media options
401
+
402
+ | Model | Faithful | Transformed | Unsupported (warning) |
403
+ | --- | --- | --- | --- |
404
+ | Image | `n` (up to 3 per call), `aspectRatio`, `xai.resolution` (`1k`/`1.5k`/`2k`), `xai.quality`, `xai.aspect_ratio` (used when `aspectRatio` is unset) | reference `images` become `referenceImages` (edit endpoint); `xai.output_format` becomes `outputFormat` and must be `png`, `jpeg`, or `webp` | `size`, `seed`, `mask`, `xai.sync_mode`, `xai.user` |
405
+ | Video | `duration` (integer 1-15), `aspectRatio`, `xai.resolution` (`480p`/`720p`/`1080p`), `xai.mode: "reference-to-video"` (the only supported mode; needs `xai.referenceImageUrls`), `xai.pollIntervalMs`, `xai.pollTimeoutMs` | `resolution` `WxH` is mapped as in `@ai-sdk/xai` (`1280x720` to `720p`); prompt `image` becomes the start frame; `xai.referenceImageUrls` (up to 5, not 7) become `referenceImages`; `xai.lastFrame` (qgrid extension, `grok-imagine-video-1.5` only) | `fps`, `seed`, `xai.keyframes`, `xai.storageOptions`, `xai.referenceVoiceIds`, `xai.user`. `xai.mode` `edit-video`/`extend-video` and `xai.videoUrl` throw |
406
+ | Transcription | `xai.language` | audio bytes become base64 and `mediaType` loses its parameters (`audio/webm;codecs=opus` to `audio/webm`) | every other `xai` key (`audioFormat`, `sampleRate`, `format`, `diarize`, `keyterm`, ...) |
407
+ | Speech | `voice`, `language` | `outputFormat` becomes `format` (`mp3`, `wav`, `pcm`, `mulaw`, `alaw`; anything else falls back to `mp3` with a warning, as in `@ai-sdk/xai`) | `instructions`, `speed`, every `xai` key (`sampleRate`, `bitRate`, `withTimestamps`, ...) |
408
+
409
+ **Request size.** The qgrid server accepts JSON bodies up to 10 MiB. Inline media travels as
410
+ base64, which grows by a third, so the server caps inline audio, each inline image, and all
411
+ inline images of one request together (video: `image` + `lastFrame` + references) at 7 MiB
412
+ decoded. The SDK rejects larger input before transport; a server 413 surfaces as the same size
413
+ error. Compress the input, or pass an https image URL where the option accepts one.
414
+
415
+ ### Grok images
416
+
417
+ ```typescript
418
+ import { generateImage } from "ai";
419
+ import { qgrid } from "@cartanova/qgrid-ai-sdk";
420
+
421
+ const { images, providerMetadata } = await generateImage({
422
+ model: qgrid.image("grok/grok-imagine-image"),
423
+ prompt: "A lighthouse at dusk, oil painting",
424
+ n: 2,
425
+ aspectRatio: "16:9",
426
+ providerOptions: { xai: { resolution: "2k", quality: "high", output_format: "jpeg" } },
427
+ });
428
+ images[0].mediaType; // "image/jpeg"
429
+ providerMetadata.xai?.images[0]; // revisedPrompt and the call's costInUsdTicks
430
+ providerMetadata.qgrid?.images[0]; // mediaType, tokenName, requestLogId, costUsd
431
+ ```
432
+
433
+ `generateImage` merges only the `images` arrays of batched calls, so each call's cost rides on
434
+ its first image entry.
435
+
436
+ ### Grok video
437
+
438
+ ```typescript
439
+ import { experimental_generateVideo as generateVideo } from "ai";
440
+ import { qgrid, QgridVideoTimeoutError, resumeQgridVideo } from "@cartanova/qgrid-ai-sdk";
441
+
442
+ try {
443
+ const { video, providerMetadata } = await generateVideo({
444
+ model: qgrid.video("grok/grok-imagine-video-1.5", { projectName: "studio" }),
445
+ prompt: "A paper boat drifting down a rain gutter",
446
+ duration: 6,
447
+ aspectRatio: "16:9",
448
+ providerOptions: { xai: { resolution: "720p" } },
449
+ });
450
+ providerMetadata.xai?.videoUrl; // the api.x.ai URL
451
+ video.uint8Array; // downloaded by AI SDK in this process, not by qgrid
452
+ } catch (error) {
453
+ if (error instanceof QgridVideoTimeoutError) {
454
+ const { videos } = await resumeQgridVideo(error.jobHandle, { projectName: "studio" });
455
+ videos[0]; // { type: "url", url, mediaType: "video/mp4" }
456
+ } else {
457
+ throw error;
458
+ }
459
+ }
460
+ ```
461
+
462
+ - The model calls `videoStart`, then polls `videoStatus` every 5 s within a 300 s budget (override with `xai.pollIntervalMs` / `xai.pollTimeoutMs`). The budget also cuts off a status request still in flight, so the call ends with `QgridVideoTimeoutError` on time. `abortSignal` stops polling; the upstream job keeps running.
463
+ - `projectName` is required to be identical for start and status: the server only answers a job handle to the project that started it. Set it once on the factory or through `QGRID_PROJECT_NAME`; pass the same value to `resumeQgridVideo`.
464
+ - The result is `{ type: "url", url, mediaType: "video/mp4" }`, exactly as `@ai-sdk/xai` returns it. The URL points at `api.x.ai` storage; qgrid never fetches, proxies, or stores the video. `experimental_generateVideo` downloads it from the calling process; pass a custom `download` to keep only the URL.
465
+ - AI SDK v3 video models only have `doGenerate` (no `doStart`/`doStatus`). `resumeQgridVideo(jobHandle, options)` is the qgrid way to continue a timed-out job; the handle is also in `providerMetadata.qgrid.jobHandle` and on `QgridVideoTimeoutError` / `QgridVideoGenerationError`.
466
+ - Video generation was verified live on a non-ZDR account (default clip is 8 s; pass the top-level `duration` option of `experimental_generateVideo` to change it). Zero Data Retention accounts are refused by xAI and are skipped for video.
467
+ - Video is not routed to Zero Data Retention accounts: xAI requires an `output.upload_url` for them, which qgrid does not support. When every token is ZDR the call fails with HTTP 503; turn off the data-retention opt-out at xAI or add a non-ZDR account.
468
+
469
+ ### Grok transcription and speech
470
+
471
+ ```typescript
472
+ import { readFile } from "node:fs/promises";
473
+ import {
474
+ experimental_generateSpeech as generateSpeech,
475
+ experimental_transcribe as transcribe,
476
+ } from "ai";
477
+ import { qgrid } from "@cartanova/qgrid-ai-sdk";
478
+
479
+ const transcript = await transcribe({
480
+ model: qgrid.transcription("grok/grok-voice-transcribe-2.0"),
481
+ audio: await readFile("meeting.mp3"),
482
+ providerOptions: { xai: { language: "en" } },
483
+ });
484
+ transcript.text;
485
+ transcript.durationInSeconds;
486
+
487
+ const speech = await generateSpeech({
488
+ model: qgrid.speech("grok/grok-tts"),
489
+ text: "Your build is ready.",
490
+ voice: "ara",
491
+ language: "en",
492
+ outputFormat: "mp3",
493
+ });
494
+ speech.audio.uint8Array;
495
+ ```
496
+
497
+ - `experimental_transcribe` detects the audio type from its bytes and falls back to `audio/wav`; the server rejects anything that is not `audio/*`. Transcripts carry no segments (`segments: []`).
498
+ - Speech text is limited to 15,000 characters. Unset `voice`, `language` and `outputFormat` use the server defaults `ara`, `en` and `mp3`, the only combination verified live. Other voices, languages (including `@ai-sdk/xai`'s `auto`) and codecs are passed through but unverified. The server's audio MIME type is in `providerMetadata.qgrid.mediaType`; AI SDK's `speech.audio.mediaType` is sniffed from the bytes.
499
+
346
500
  ## Telemetry Logger
347
501
 
348
502
  With qgrid server and SDK 2.10.0+, read the parent request-log ID from `result.providerMetadata?.qgrid?.requestLogId` after `generateText`. For `streamText`, consume the stream first, then read `(await result.providerMetadata)?.qgrid?.requestLogId`. Raw API query responses and stream `done` events expose the same ID as top-level `requestLogId`. The field is omitted with `logger: false` or an older server. Tool-run steps share the parent ID; it is not continuation state. This metadata applies to the qgrid provider, not external providers using the telemetry logger below.
@@ -454,7 +608,7 @@ type QgridSupportedModel =
454
608
  ### GPT-6 specifications
455
609
 
456
610
  | Model | Context (Codex catalog) | Max output (public API) | Input / cached input / cache write / output per 1M tokens |
457
- |---|---:|---:|---:|
611
+ | --- | ---: | ---: | ---: |
458
612
  | `openai/gpt-6-astra` | 272K | 128K | $10 / $1 / $12.50 / $50 |
459
613
  | `openai/gpt-6.1-sol` | 272K | 128K | $2 / $0.10 / $2.50 / $10 |
460
614
  | `openai/gpt-6-sol` | 272K | 128K | $2 / $0.20 / $2.50 / $10 |
@@ -465,7 +619,7 @@ The Codex catalog fetched on 2026-09-23 advertises a 272K context window for Ast
465
619
  ### GPT-5.6 specifications
466
620
 
467
621
  | Model | Context (Codex catalog) | Max output (public API) | Input / cached input / cache write / output per 1M tokens |
468
- |---|---:|---:|---:|
622
+ | --- | ---: | ---: | ---: |
469
623
  | `openai/gpt-5.6-sol` | 272K | 128K | $4 / $0.40 / $5 / $20 |
470
624
  | `openai/gpt-5.6-terra` | 272K | 128K | $2 / $0.20 / $2.50 / $12 |
471
625
  | `openai/gpt-5.6-luna` | 272K | 128K | $0.20 / $0.02 / $0.25 / $1.20 |
@@ -507,7 +661,7 @@ If multiple projects/workflows share one qgrid server, set `QGRID_PROJECT_NAME`.
507
661
  ## Environment variables
508
662
 
509
663
  | Variable | Description | Default |
510
- |---|---|---|
664
+ | --- | --- | --- |
511
665
  | `QGRID_URL` | qgrid server address | `http://localhost:44900` |
512
666
  | `QGRID_PROJECT_NAME` | request log project name (provider and logger) | (empty) |
513
667
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,19 @@
1
- import { ImageModelV3, LanguageModelV3 } from "@ai-sdk/provider";
1
+ import { z } from "zod";
2
+ import { Experimental_VideoModelV3, Experimental_VideoModelV3VideoData, ImageModelV3, LanguageModelV3, SharedV3ProviderMetadata, SpeechModelV3, TranscriptionModelV3 } from "@ai-sdk/provider";
2
3
  import { TelemetrySettings } from "ai";
4
+ //#region src/grok-options.d.ts
5
+ /** Effort values qgrid forwards to the Grok subscription backend (`reasoning.effort`). */
6
+ type QgridGrokEffort = "low" | "medium" | "high" | "xhigh";
7
+ type XaiOptionsIssue = {
8
+ path: string;
9
+ message: string;
10
+ };
11
+ /** Thrown when `providerOptions.xai` has an invalid shape or value type. */
12
+ declare class QgridXaiOptionsError extends Error {
13
+ readonly issues: XaiOptionsIssue[];
14
+ constructor(issues: XaiOptionsIssue[]);
15
+ }
16
+ //#endregion
3
17
  //#region src/index.types.d.ts
4
18
  /**
5
19
  * OpenAI 경로(ChatGPT 구독 Codex 백엔드)의 reasoning effort. 백엔드 모델 카탈로그의
@@ -22,7 +36,16 @@ type QgridCommonProviderConfig = {
22
36
  projectName?: string;
23
37
  };
24
38
  /** Codex Images request ID, not a guaranteed serving version; does not select a chat model. */
25
- type QgridImageModel = "openai/gpt-image-2";
39
+ type QgridImageModel = "openai/gpt-image-2" | "grok/grok-imagine-image" | "grok/grok-imagine-image-2.0" | "grok/grok-imagine-image-quality";
40
+ /** Grok video generation model ids (xAI subscription; not yet wired to a provider factory). */
41
+ type QgridVideoModel = "grok/grok-imagine-video" | "grok/grok-imagine-video-1.5" | "grok/grok-imagine-video-1.5-lite";
42
+ /** Grok speech-to-text model ids. */
43
+ type QgridTranscriptionModel = "grok/grok-voice-transcribe-2.0";
44
+ /**
45
+ * Grok text-to-speech model id. Placeholder: the live probe verified the `/tts` endpoint with the
46
+ * subscription JWT, but no TTS model id was observed (`/speech-models` returned 404).
47
+ */
48
+ type QgridSpeechModel = "grok/grok-tts";
26
49
  type QgridImageProviderConfig = QgridCommonProviderConfig;
27
50
  /** `providerOptions.qgrid` for `generateImage({ model: qgrid.image(...) })`. */
28
51
  type QgridImageProviderOptions = {
@@ -102,7 +125,46 @@ type QgridAnthropicProviderOptions = QgridCommonProviderOptions & {
102
125
  * `QgridOpenAIProviderOptions` / `QgridAnthropicProviderOptions` 를 직접 쓰는 편이 정확하다.
103
126
  */
104
127
  type QgridProviderOptions = QgridOpenAIProviderOptions | QgridAnthropicProviderOptions;
105
- type QgridSupportedModel = "openai/gpt-6-astra" | "openai/gpt-6.1-sol" | "openai/gpt-6-sol" | "openai/gpt-6-luna" | "openai/gpt-5.6-sol" | "openai/gpt-5.6-terra" | "openai/gpt-5.6-luna" | "openai/gpt-5.5" | "openai/gpt-5.4" | "openai/gpt-5.2" | "openai/gpt-5.4-mini" | "openai/gpt-5.3-codex" | "openai/gpt-5.3-codex-spark" | "anthropic/claude-fable-5-1" | "anthropic/claude-fable-5" | "anthropic/claude-haiku-4-5" | "anthropic/claude-sonnet-4" | "anthropic/claude-sonnet-4-5" | "anthropic/claude-sonnet-4-6" | "anthropic/claude-sonnet-4-7" | "anthropic/claude-sonnet-5" | "anthropic/claude-opus-4" | "anthropic/claude-opus-4-1" | "anthropic/claude-opus-4-5" | "anthropic/claude-opus-4-6" | "anthropic/claude-opus-4-7" | "anthropic/claude-opus-4-8" | "anthropic/claude-opus-5" | "anthropic/claude-opus-5-5" | "anthropic/claude-sonnet-5-5" | "anthropic/claude-haiku-5-5";
128
+ /**
129
+ * Grok(xAI subscription) language model ids. The literals are the four ids the subscription
130
+ * `/models` catalog returned at GROK_BUILD_VERSION 1.0.60 (`grok-4.7` is the default); any other
131
+ * `grok/<id>` is accepted so newly cataloged models need no SDK release.
132
+ */
133
+ type QgridGrokModel = "grok/grok-4.7" | "grok/grok-4.7-build-fast" | "grok/grok-4.6" | "grok/grok-4.5" | (`grok/${string}` & {});
134
+ /**
135
+ * `providerOptions.xai` for Grok models, cloned field-for-field from `@ai-sdk/xai`
136
+ * (`xai-responses-language-model-options.ts`) so code written for `@ai-sdk/xai` keeps parsing.
137
+ * Parsing only proves the shape; `mapXaiProviderOptions` decides which keys qgrid honors.
138
+ */
139
+ declare const qgridXaiProviderOptionsSchema: z.ZodObject<{
140
+ reasoningEffort: z.ZodOptional<z.ZodEnum<{
141
+ none: "none";
142
+ low: "low";
143
+ medium: "medium";
144
+ high: "high";
145
+ xhigh: "xhigh";
146
+ }>>;
147
+ maxTurns: z.ZodOptional<z.ZodNumber>;
148
+ parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
149
+ promptCacheKey: z.ZodOptional<z.ZodString>;
150
+ safetyIdentifier: z.ZodOptional<z.ZodString>;
151
+ serviceTier: z.ZodOptional<z.ZodEnum<{
152
+ default: "default";
153
+ priority: "priority";
154
+ }>>;
155
+ store: z.ZodOptional<z.ZodBoolean>;
156
+ previousResponseId: z.ZodOptional<z.ZodString>;
157
+ user: z.ZodOptional<z.ZodString>;
158
+ include: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodEnum<{
159
+ "file_search_call.results": "file_search_call.results";
160
+ "web_search_call.action.sources": "web_search_call.action.sources";
161
+ "code_interpreter_call.outputs": "code_interpreter_call.outputs";
162
+ "reasoning.encrypted_content": "reasoning.encrypted_content";
163
+ no_inline_citations: "no_inline_citations";
164
+ }>>>>;
165
+ }, z.core.$strip>;
166
+ type QgridXaiProviderOptions = z.infer<typeof qgridXaiProviderOptionsSchema>;
167
+ type QgridSupportedModel = "openai/gpt-6-astra" | "openai/gpt-6.1-sol" | "openai/gpt-6-sol" | "openai/gpt-6-luna" | "openai/gpt-5.6-sol" | "openai/gpt-5.6-terra" | "openai/gpt-5.6-luna" | "openai/gpt-5.5" | "openai/gpt-5.4" | "openai/gpt-5.2" | "openai/gpt-5.4-mini" | "openai/gpt-5.3-codex" | "openai/gpt-5.3-codex-spark" | "anthropic/claude-fable-5-1" | "anthropic/claude-fable-5" | "anthropic/claude-haiku-4-5" | "anthropic/claude-sonnet-4" | "anthropic/claude-sonnet-4-5" | "anthropic/claude-sonnet-4-6" | "anthropic/claude-sonnet-4-7" | "anthropic/claude-sonnet-5" | "anthropic/claude-opus-4" | "anthropic/claude-opus-4-1" | "anthropic/claude-opus-4-5" | "anthropic/claude-opus-4-6" | "anthropic/claude-opus-4-7" | "anthropic/claude-opus-4-8" | "anthropic/claude-opus-5" | "anthropic/claude-opus-5-5" | "anthropic/claude-sonnet-5-5" | "anthropic/claude-haiku-5-5" | QgridGrokModel;
106
168
  /** Observed image response values. Usage is response-level and appears on the first image only. */
107
169
  type QgridImageGenerationMetadata = {
108
170
  route: "codex-images" | "codex-responses";
@@ -155,16 +217,126 @@ type QgridLoggerConfig = {
155
217
  };
156
218
  //#endregion
157
219
  //#region src/image-model.d.ts
220
+ /** Server-side Fastify body limit (`sonamu.config.ts` `bodyLimit`). Larger bodies get a 413. */
221
+ declare const QGRID_MAX_REQUEST_BODY_BYTES: number;
222
+ /** `config` for `qgrid.image/video/transcription/speech`; same fields as the language model. */
223
+ type QgridMediaProviderConfig = QgridImageProviderConfig;
224
+ /** Non-2xx response from a qgrid media endpoint. */
225
+ declare class QgridMediaHttpError extends Error {
226
+ readonly status: number;
227
+ constructor(message: string, status: number);
228
+ }
229
+ declare const grokQgridOptionsSchema: z.ZodObject<{
230
+ tokenName: z.ZodOptional<z.ZodString>;
231
+ logger: z.ZodOptional<z.ZodBoolean>;
232
+ }, z.core.$strip>;
233
+ /** `providerOptions.qgrid` accepted by every Grok media model. */
234
+ type QgridGrokMediaProviderOptions = z.infer<typeof grokQgridOptionsSchema>;
158
235
  declare function createQgridImage(modelId: QgridImageModel, config?: QgridImageProviderConfig): ImageModelV3;
236
+ /** `providerOptions.xai` for Grok images, field-for-field from `@ai-sdk/xai` `xaiImageModelOptions`. */
237
+ declare const xaiImageOptionsSchema: z.ZodObject<{
238
+ aspect_ratio: z.ZodOptional<z.ZodString>;
239
+ output_format: z.ZodOptional<z.ZodString>;
240
+ sync_mode: z.ZodOptional<z.ZodBoolean>;
241
+ resolution: z.ZodOptional<z.ZodEnum<{
242
+ "1k": "1k";
243
+ "1.5k": "1.5k";
244
+ "2k": "2k";
245
+ }>>;
246
+ quality: z.ZodOptional<z.ZodEnum<{
247
+ low: "low";
248
+ medium: "medium";
249
+ high: "high";
250
+ auto: "auto";
251
+ }>>;
252
+ user: z.ZodOptional<z.ZodString>;
253
+ }, z.core.$strip>;
254
+ /** `providerOptions.xai` accepted by `qgrid.image("grok/...")` (the `@ai-sdk/xai` image option shape). */
255
+ type QgridXaiImageProviderOptions = z.infer<typeof xaiImageOptionsSchema>;
256
+ //#endregion
257
+ //#region src/speech-model.d.ts
258
+ /**
259
+ * Grok text-to-speech through `POST /api/qgrid/speak`. `voice`, `language` and `outputFormat`
260
+ * map to the server's `voice`, `language` and `format`; when omitted the server applies
261
+ * `ara` / `en` / `mp3` (the only combination verified live). The model id only labels the log.
262
+ */
263
+ declare function createQgridSpeech(modelId: QgridSpeechModel, config?: QgridMediaProviderConfig): SpeechModelV3;
264
+ //#endregion
265
+ //#region src/transcription-model.d.ts
266
+ /** `providerOptions.xai` honored by `qgrid.transcription(...)`. */
267
+ type QgridXaiTranscriptionProviderOptions = {
268
+ language?: string;
269
+ };
270
+ declare function createQgridTranscription(modelId: QgridTranscriptionModel, config?: QgridMediaProviderConfig): TranscriptionModelV3;
271
+ //#endregion
272
+ //#region src/video-model.d.ts
273
+ /** `providerOptions.xai` accepted by `qgrid.video(...)`. */
274
+ type QgridXaiVideoProviderOptions = {
275
+ mode?: "reference-to-video";
276
+ /** 1 to 5 https or PNG/JPEG/WebP data URLs (the qgrid server caps @ai-sdk/xai's 7 at 5). */
277
+ referenceImageUrls?: string[];
278
+ resolution?: "480p" | "720p" | "1080p";
279
+ /** qgrid extension: pinned last frame (https or data URL); grok-imagine-video-1.5 only. */
280
+ lastFrame?: string;
281
+ pollIntervalMs?: number;
282
+ pollTimeoutMs?: number;
283
+ };
284
+ /**
285
+ * Raised when the poll budget runs out. The job keeps running on xAI; pass `jobHandle` to
286
+ * `resumeQgridVideo` (with the same `projectName`) to keep waiting.
287
+ */
288
+ declare class QgridVideoTimeoutError extends Error {
289
+ readonly jobHandle: string;
290
+ constructor(jobHandle: string, timeoutMs: number);
291
+ }
292
+ /** The upstream job finished as failed (including content-policy blocks). */
293
+ declare class QgridVideoGenerationError extends Error {
294
+ readonly jobHandle: string;
295
+ constructor(jobHandle: string, detail: string | undefined);
296
+ }
297
+ type QgridVideoPollOptions = {
298
+ pollIntervalMs?: number;
299
+ pollTimeoutMs?: number;
300
+ abortSignal?: AbortSignal;
301
+ headers?: Record<string, string | undefined>;
302
+ };
303
+ type QgridVideoResult = {
304
+ videos: Experimental_VideoModelV3VideoData[];
305
+ providerMetadata: SharedV3ProviderMetadata;
306
+ response: {
307
+ timestamp: Date;
308
+ modelId: string;
309
+ headers: Record<string, string> | undefined;
310
+ };
311
+ };
312
+ /**
313
+ * Keeps polling a video job started by `qgrid.video(...)`, for example after a
314
+ * `QgridVideoTimeoutError`. `config.projectName` must equal the one used to start the job.
315
+ * AI SDK v3 video models expose only `doGenerate` (no `doStart` / `doStatus`), so resuming is
316
+ * a qgrid helper rather than an `experimental_generateVideo` option.
317
+ */
318
+ declare function resumeQgridVideo(jobHandle: string, options?: QgridVideoPollOptions & QgridMediaProviderConfig & {
319
+ modelId?: QgridVideoModel;
320
+ }): Promise<QgridVideoResult>;
321
+ declare function createQgridVideo(modelId: QgridVideoModel, config?: QgridMediaProviderConfig): Experimental_VideoModelV3;
159
322
  //#endregion
160
323
  //#region src/logger.d.ts
161
324
  declare function createQgridLogger(config?: QgridLoggerConfig): TelemetrySettings;
162
325
  //#endregion
163
326
  //#region src/index.d.ts
327
+ /** `qgrid()` config for Grok models; `defaultEffort` uses the Grok catalog effort vocabulary. */
328
+ type QgridGrokProviderConfig = Omit<QgridOpenAIProviderConfig, "defaultEffort"> & {
329
+ /** Omitted: the server applies the model's catalog default effort. */
330
+ defaultEffort?: QgridGrokEffort;
331
+ };
164
332
  declare function qgrid(modelId: QgridOpenAIModel, config?: QgridOpenAIProviderConfig): LanguageModelV3;
165
333
  declare function qgrid(modelId: QgridAnthropicModel, config?: QgridAnthropicProviderConfig): LanguageModelV3;
334
+ declare function qgrid(modelId: QgridGrokModel, config?: QgridGrokProviderConfig): LanguageModelV3;
166
335
  declare namespace qgrid {
167
336
  var image: typeof createQgridImage;
337
+ var video: typeof createQgridVideo;
338
+ var transcription: typeof createQgridTranscription;
339
+ var speech: typeof createQgridSpeech;
168
340
  }
169
341
  //#endregion
170
- export { type QgridAnthropicEffort, type QgridAnthropicModel, type QgridAnthropicProviderConfig, type QgridAnthropicProviderOptions, type QgridImageGenerationMetadata, type QgridImageModel, type QgridImageProviderConfig, type QgridImageProviderOptions, type QgridLoggerConfig, type QgridOpenAIEffort, type QgridOpenAIModel, type QgridOpenAIProviderConfig, type QgridOpenAIProviderOptions, type QgridProviderConfig, type QgridProviderOptions, type QgridSupportedModel, createQgridLogger, qgrid as default, qgrid };
342
+ export { QGRID_MAX_REQUEST_BODY_BYTES, type QgridAnthropicEffort, type QgridAnthropicModel, type QgridAnthropicProviderConfig, type QgridAnthropicProviderOptions, type QgridGrokEffort, type QgridGrokMediaProviderOptions, type QgridGrokModel, QgridGrokProviderConfig, type QgridImageGenerationMetadata, type QgridImageModel, type QgridImageProviderConfig, type QgridImageProviderOptions, type QgridLoggerConfig, QgridMediaHttpError, type QgridMediaProviderConfig, type QgridOpenAIEffort, type QgridOpenAIModel, type QgridOpenAIProviderConfig, type QgridOpenAIProviderOptions, type QgridProviderConfig, type QgridProviderOptions, type QgridSpeechModel, type QgridSupportedModel, type QgridTranscriptionModel, QgridVideoGenerationError, type QgridVideoModel, type QgridVideoPollOptions, type QgridVideoResult, QgridVideoTimeoutError, type QgridXaiImageProviderOptions, QgridXaiOptionsError, type QgridXaiProviderOptions, type QgridXaiTranscriptionProviderOptions, type QgridXaiVideoProviderOptions, createQgridLogger, qgrid as default, qgrid, resumeQgridVideo };