diff --git a/.netconfig b/.netconfig
index 9b8300f..16c4609 100644
--- a/.netconfig
+++ b/.netconfig
@@ -105,13 +105,13 @@
weak
[file "src/Directory.Build.props"]
url = https://github.com/devlooped/oss/blob/main/src/Directory.Build.props
- sha = 6e2438919e108aeb75106dc0737c45f5e55d5f42
- etag = f1d6384abf18d8d891ce5e835a10c73fe029c42151374be96d7e4af43d189c65
+ sha = 59861ddd1e330f3da410652b4c7fc6585726c0cf
+ etag = 1561f1be53cc25ac0cd85a06b3f65d69764b174d0f60bf72ca2f8fc70573b75e
weak
[file "src/Directory.Build.targets"]
url = https://github.com/devlooped/oss/blob/main/src/Directory.Build.targets
- sha = 3a758f47e8955c15a016b3db08f383781cbdee26
- etag = 22005ab28676aa6d790171003057c81fe4ceec01251626385a3dcef3417ae3cd
+ sha = 59861ddd1e330f3da410652b4c7fc6585726c0cf
+ etag = cb1f7a3e5bf85e7307407b7b6d8b9869330e2191a2317ccf6218a552e5890b08
weak
[file "src/nuget.config"]
url = https://github.com/devlooped/oss/blob/main/src/nuget.config
@@ -152,8 +152,8 @@
weak
[file "src/xAI.Protocol/chat.proto"]
url = https://github.com/xai-org/xai-proto/blob/main/proto/xai/api/v1/chat.proto
- sha = 17a2da08cbbf89aa1f33ffe58b687fe0b2d50468
- etag = e7da2c915664caf64c0da7d886826de37fcf98753cf613a6ad8aad96f6ddcda5
+ sha = 2c2df4f5d9429f5f21e58bb9e63285c69bcc144f
+ etag = 061acaded15e83e3056dfcb1a738cd6aa0cad27f7f6ec38b6bf84e3077d448ac
weak
[file "src/xAI.Protocol/deferred.proto"]
url = https://github.com/xai-org/xai-proto/blob/main/proto/xai/api/v1/deferred.proto
@@ -172,8 +172,8 @@
weak
[file "src/xAI.Protocol/image.proto"]
url = https://github.com/xai-org/xai-proto/blob/main/proto/xai/api/v1/image.proto
- sha = d67bcf3e661aa9641af9750632fa1c38ea974da1
- etag = 3ea27e240320c26d14b8c64d00f236c078127ebdb6fa957efc49232dfd75a20c
+ sha = 2c2df4f5d9429f5f21e58bb9e63285c69bcc144f
+ etag = 3d66f35d2e1555c6eae2218705b6f8ee5fa6537939b6ae0a18e0a2fd13a81bff
weak
[file "src/xAI.Protocol/models.proto"]
url = https://github.com/xai-org/xai-proto/blob/main/proto/xai/api/v1/models.proto
@@ -192,13 +192,13 @@
weak
[file "src/xAI.Protocol/usage.proto"]
url = https://github.com/xai-org/xai-proto/blob/main/proto/xai/api/v1/usage.proto
- sha = d8def643bea79ad10f5a678d70ae37edca26490f
- etag = 74c44beb7bfd2e75ea0524ff9be820cc067e009b071dee59869a16d372280a0a
+ sha = 2c2df4f5d9429f5f21e58bb9e63285c69bcc144f
+ etag = 0bf9577be87d3cfc79895971071ef1eaa78645cb784462e7e90bff03440dfff4
weak
[file "src/xAI.Protocol/video.proto"]
url = https://github.com/xai-org/xai-proto/blob/main/proto/xai/api/v1/video.proto
- sha = 43a1b6b731943b8f031c2f2d946f7183f0933ffd
- etag = 37562e78a6d64800b09c643632a33b6bc902955b491114bd5b6ec957d23d6e64
+ sha = 723dd2aa22d17be35617463837dc47cda008d90e
+ etag = 24af69223d5fafc1ae8554f1ee43fdb0ff8c1eeacfa2e8ce9719fd58179d2fb8
weak
[file "src/xAI.Protocol/google/protobuf/timestamp.proto"]
url = https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/timestamp.proto
@@ -233,6 +233,6 @@
weak
[file "src/xAI.Protocol/files.proto"]
url = https://github.com/xai-org/xai-proto/blob/main/proto/xai/api/v1/files.proto
- etag = 4c91f851b288a225acfc1173f2f8853a1b550da1e97d2fdcec99debb5f8fac43
+ etag = b5e8ed748220b2fa727e8845f09f612cb77813d02c4260b77e6464aa0c98d57f
weak
- sha = 0c0f5353aa7ab2a4ffea310f9d9364ed5c424af2
+ sha = c666ac39e9a8f562e94b2b57872a75bc1438ec2b
diff --git a/readme.md b/readme.md
index aa1edae..f5d522d 100644
--- a/readme.md
+++ b/readme.md
@@ -618,7 +618,6 @@ Uses your own API Key.
[](https://github.com/drivenet)
[](https://github.com/Keflon)
[](https://github.com/tbolon)
-[](https://github.com/kfrancis)
[](https://github.com/rbnswartz)
[](https://github.com/jfoshee)
[](https://github.com/Mrxx99)
@@ -639,6 +638,7 @@ Uses your own API Key.
[](https://github.com/wizardness)
[](https://github.com/eska-gmbh)
[](https://github.com/geodata-no)
+[](https://github.com/jslachta)
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 93a0b1e..5c43a5d 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -25,10 +25,12 @@
false
MIT
-
+
+ logo.png
icon.png
readme.md
+ logo.png
icon.png
readme.md
diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets
index 4a6ef38..c9a50b6 100644
--- a/src/Directory.Build.targets
+++ b/src/Directory.Build.targets
@@ -63,7 +63,12 @@
+ Condition="'$(PackageIcon)' == 'icon.png'" />
+
+
-
+ Condition="'$(PackageIcon)' != '' and Exists('$(MSBuildThisFileDirectory)$(PackageIcon)') and !Exists('$(MSBuildProjectDirectory)\$(PackageIcon)')" />
, >=, <, <=, AND, OR, NOT.
+ // Examples:
+ // - 'name:"report"'
+ // - 'content_type = "application/pdf"'
+ // - 'size_bytes > 1000000 AND created_at > "2024-01-01T00:00:00Z"'
+ optional string filter = 5;
}
// Response message for `Files.ListFiles`.
@@ -179,3 +235,48 @@ message FileContentChunk {
// Up to 5 MB of file bytes. Final/intermediate chunks may be smaller.
bytes data = 1;
}
+
+// Request message for `Files.CreatePublicUrl`.
+message CreatePublicUrlRequest {
+ // The ID of the file to create a public URL for.
+ string file_id = 1;
+
+ // Seconds from now until the public URL expires. Must be between 3600
+ // (1 hour) and 2592000 (30 days).
+ //
+ // If omitted and the file has a TTL, the public URL inherits the file's
+ // expiry. If omitted and the file has no TTL, the public URL remains
+ // valid indefinitely until the file is deleted or the URL is explicitly
+ // revoked via `RevokePublicUrl`.
+ optional int64 expires_after = 2;
+}
+
+// Response message for `Files.CreatePublicUrl`.
+message CreatePublicUrlResponse {
+ // The full public URL that can be shared and accessed without an API key.
+ string public_url = 1;
+
+ // When the public URL expires. Present when the public URL has an expiry,
+ // either from an explicit `expires_after` in the request or inherited from
+ // the file's TTL. Absent when the public URL is valid indefinitely.
+ optional google.protobuf.Timestamp expires_at = 2;
+}
+
+// Request message for `Files.RevokePublicUrl`.
+message RevokePublicUrlRequest {
+ // The ID of the file whose public URL should be revoked.
+ string file_id = 1;
+}
+
+// Response message for `Files.RevokePublicUrl`.
+message RevokePublicUrlResponse {
+ // The file ID whose public URL was revoked.
+ string file_id = 1;
+
+ // True if a public URL was actually revoked. False if the file had
+ // no active public URL (no-op).
+ bool revoked = 2;
+
+ // The full public URL that was revoked. Only present when revoked is true.
+ optional string public_url = 3;
+}
diff --git a/src/xAI.Protocol/image.proto b/src/xAI.Protocol/image.proto
index 325339f..09a72b9 100644
--- a/src/xAI.Protocol/image.proto
+++ b/src/xAI.Protocol/image.proto
@@ -1,9 +1,9 @@
syntax = "proto3";
-option csharp_namespace = "xAI.Protocol";
package xai_api;
-import "usage.proto";
+import "google/protobuf/timestamp.proto";
+import "xai/api/v1/usage.proto";
// An API service for interaction with image generation models.
service Image {
@@ -36,6 +36,12 @@ message GenerateImageRequest {
// in. See ImageFormat enum for options.
ImageFormat format = 11;
+ // Optional quality setting for image generation.
+ // Only supported by grok-imagine models.
+ // Defaults to medium. Some models restrict the accepted values (a request
+ // outside the model's supported set is rejected).
+ optional ImageQuality quality = 12;
+
// Optional aspect ratio for image generation/editing.
// Only supported by grok-imagine models.
// Defaults to 1:1 if not specified. Auto is only supported for image generation
@@ -54,6 +60,62 @@ message GenerateImageRequest {
// Each image is either an image URL or a base64-encoded version of the image.
// This field cannot be set together with the `image` field.
repeated ImageUrlContent images = 17;
+
+ // Optional output storage configuration. When present, the generated
+ // image(s) are stored in the Files API and a file_id is returned in
+ // the response alongside the ephemeral URL.
+ optional StorageOptions storage_options = 19;
+}
+
+// Configuration for storing generation output in the Files API.
+message StorageOptions {
+ // Filename for the stored file.
+ string filename = 1;
+ // Seconds from now until the file auto-expires. If omitted, the file
+ // does not expire.
+ optional int64 expires_after = 2;
+ // When present, a public URL is created for the stored file after upload.
+ // The public URL is accessible without authentication.
+ // Omit entirely to store the file privately (no public URL).
+ optional PublicUrlOptions public_url = 3;
+}
+
+// Configuration for creating a public URL alongside file storage.
+message PublicUrlOptions {
+ // Seconds from now until the public URL expires.
+ //
+ // If omitted and the file has a TTL (`StorageOptions.expires_after`),
+ // the public URL inherits the file's expiry. If omitted and the file
+ // has no TTL, the public URL remains valid indefinitely until the file
+ // is deleted or the URL is explicitly revoked via `RevokePublicUrl`.
+ // The file itself always remains accessible via authenticated endpoints
+ // after the public URL expires.
+ optional int64 expires_after = 1;
+}
+
+// Information about a generated file stored in the Files API.
+message FileOutput {
+ // Files API file_id of the stored file.
+ string file_id = 1;
+ // Filename of the stored file.
+ string filename = 2;
+ reserved 3;
+ // Public URL for the stored file. Only present when the request included
+ // storage_options.public_url and creation succeeded.
+ optional string public_url = 4;
+ // When the public URL expires. Only present when public_url is set and
+ // has an independent expiry (i.e. the request specified
+ // public_url.expires_after, or the file has a TTL). Absent when the
+ // public URL is valid indefinitely.
+ optional google.protobuf.Timestamp public_url_expires_at = 5;
+ // When the stored file expires and will be automatically deleted. Only
+ // present when the file has an expiration (storage_options.expires_after
+ // was set).
+ optional google.protobuf.Timestamp expires_at = 6;
+ // Human-readable error when storage_options.public_url was set but
+ // public URL creation failed. The file itself was stored successfully —
+ // the public URL can be retried via `CreatePublicUrl`.
+ optional string public_url_error = 7;
}
// The response from the image generation models containing the generated image(s).
@@ -87,18 +149,35 @@ message GeneratedImage {
// The field will be true if the image respect moderation rules. Otherwise
// the field will be false and the image field is replaced by a placeholder.
bool respect_moderation = 4;
+
+ // Storage info for the generated image. Only present when the request
+ // included `storage_options` and the upload succeeded.
+ optional FileOutput file_output = 8;
+
+ // Human-readable error when `storage_options` was set but the upload
+ // failed. Only present on storage failure; absent on success or when
+ // storage was not requested.
+ optional string storage_error = 9;
}
// Contains data relating to an image that is provided to the model.
message ImageUrlContent {
- // This is either an image URL or a base64-encoded version of the image.
- // The following image formats are supported: PNG, JPG, and WebP.
- // If an image URL is provided, the image will be downloaded for every API
- // request without being cached. Images are fetched using
- // "XaiImageApiFetch/1.0" user agent, and will timeout after 5 seconds.
- // The image size is limited to 10 MiB. If the image download fails, the API
- // request will fail as well.
- string image_url = 1;
+ // The source of the image — either a direct URL/base64 string or a
+ // file_id from the xAI Files API. Exactly one must be set.
+ oneof source {
+ // This is either an image URL or a base64-encoded version of the image.
+ // The following image formats are supported: PNG, JPG, and WebP.
+ // If an image URL is provided, the image will be downloaded for every API
+ // request without being cached. Images are fetched using
+ // "XaiImageApiFetch/1.0" user agent, and will timeout after 5 seconds.
+ // The image size is limited to 10 MiB. If the image download fails, the API
+ // request will fail as well.
+ string image_url = 1;
+
+ // A file ID from the xAI Files API. The file must be an image
+ // (JPEG, PNG, or WebP).
+ string file_id = 3;
+ }
// The level of pre-processing resolution that will be applied to the image.
ImageDetail detail = 2;
diff --git a/src/xAI.Protocol/usage.proto b/src/xAI.Protocol/usage.proto
index e0171ac..0599ed1 100644
--- a/src/xAI.Protocol/usage.proto
+++ b/src/xAI.Protocol/usage.proto
@@ -1,5 +1,4 @@
syntax = "proto3";
-option csharp_namespace = "xAI.Protocol";
package xai_api;
@@ -78,4 +77,5 @@ enum ServerSideTool {
SERVER_SIDE_TOOL_MCP = 7;
SERVER_SIDE_TOOL_ATTACHMENT_SEARCH = 8;
SERVER_SIDE_TOOL_IMAGE_SEARCH = 10;
+ SERVER_SIDE_TOOL_IMAGE_GENERATION = 11;
}
diff --git a/src/xAI.Protocol/video.proto b/src/xAI.Protocol/video.proto
index b12e5be..08df675 100644
--- a/src/xAI.Protocol/video.proto
+++ b/src/xAI.Protocol/video.proto
@@ -1,11 +1,10 @@
syntax = "proto3";
-option csharp_namespace = "xAI.Protocol";
package xai_api;
-import "deferred.proto";
-import "image.proto";
-import "usage.proto";
+import "xai/api/v1/deferred.proto";
+import "xai/api/v1/image.proto";
+import "xai/api/v1/usage.proto";
// Aspect ratio for video generation.
enum VideoAspectRatio {
@@ -46,13 +45,41 @@ enum VideoResolution {
// 720p resolution.
// Dimensions vary by aspect ratio
VIDEO_RESOLUTION_720P = 2;
+
+ // 1080p resolution.
+ // Dimensions vary by aspect ratio.
+ // Supported on models that advertise 1080p (e.g. grok-imagine-video-1.5 for
+ // image-to-video); not available on all video models.
+ VIDEO_RESOLUTION_1080P = 3;
}
-// Specifies a video by URL for video editing.
+// Specifies a video by URL or file reference for video editing.
message VideoUrlContent {
- // Either a URL of the video (e.g., a public URL) or a base64-encoded video
- // as a data URL (e.g., "data:video/mp4;base64,...").
- string url = 1;
+ // The source of the video — either a direct URL/base64 string or a
+ // file_id from the xAI Files API. Exactly one must be set.
+ oneof source {
+ // Either a URL of the video (e.g., a public URL) or a base64-encoded video
+ // as a data URL (e.g., "data:video/mp4;base64,...").
+ string url = 1;
+
+ // A file ID from the xAI Files API. The file must be a video
+ // (e.g., MP4).
+ string file_id = 2;
+ }
+}
+
+// Reference audio input for video generation.
+message AudioUrlContent {
+ reserved 1;
+
+ // The source of the audio. Must be set.
+ oneof source {
+ // Identifier of a first-party preset voice (e.g. "ara"), using the same
+ // voice identifiers as the TTS API. Resolved server-side to a curated
+ // reference clip from the model's voice-preset catalog. Only supported
+ // by models that accept reference audio.
+ string voice_id = 2;
+ }
}
// An API service for interaction with video generation models.
@@ -111,6 +138,26 @@ message GenerateVideoRequest {
// When provided (and `image` is not set), generates video using these images
// as style/content references.
repeated ImageUrlContent reference_images = 13;
+
+ // Optional output storage configuration. When present, the generated
+ // video is stored in the Files API and a file_id is returned in
+ // the response alongside the ephemeral URL.
+ optional StorageOptions storage_options = 14;
+
+ reserved 15;
+
+ // Optional reference audio (voice identity) for reference-to-video
+ // generation. Each entry selects a first-party preset voice via
+ // `voice_id` (same identifiers as the TTS API). Only supported by select
+ // video models; at most three entries. May be provided without
+ // reference_images (audio-only reference-to-video) — at least one
+ // reference of either kind selects the reference-to-video mode.
+ repeated AudioUrlContent reference_audios = 16;
+
+ // Whether the generated video includes an audio track. Defaults to true.
+ // Set to false for a silent video (the audio track is stripped
+ // server-side after generation).
+ optional bool generate_audio = 17;
}
// Request for retrieving deferred video generation results.
@@ -155,6 +202,15 @@ message GeneratedVideo {
// The field will be true if the video respects moderation rules. Otherwise
// the field will be false and the video url field will be empty.
bool respect_moderation = 5;
+
+ // Storage info for the generated video. Only present when the request
+ // included `storage_options` and the upload succeeded.
+ optional FileOutput file_output = 6;
+
+ // Human-readable error when `storage_options` was set but the upload
+ // failed. Only present on storage failure; absent on success or when
+ // storage was not requested.
+ optional string storage_error = 7;
}
// Response from GetDeferredVideo, including the response if the video
@@ -192,4 +248,11 @@ message ExtendVideoRequest {
// Duration of the extension segment to generate in seconds (1-10).
// Defaults to 6 seconds if not specified.
optional int32 duration = 4;
+
+ // Optional output storage configuration. When present, the generated
+ // video is stored in the Files API and a file_id is returned in
+ // the response alongside the ephemeral URL.
+ optional StorageOptions storage_options = 6;
+
+ reserved 7;
}