@j-o-r/hello-dave 0.1.1 → 0.1.5
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/CHANGELOG.md +42 -25
- package/README.md +81 -221
- package/TODO.md +173 -35
- package/agents/agent_creator.js +105 -0
- package/agents/agent_creator.prompt.md +371 -0
- package/agents/ask_agent.js +64 -127
- package/agents/claude_agent.js +68 -0
- package/agents/code_agent.js +55 -135
- package/agents/code_agent.prompt.md +50 -0
- package/agents/echo_agent.js +76 -0
- package/agents/financial_expert.js +75 -0
- package/agents/gpt_agent.js +52 -103
- package/agents/gpt_code.js +81 -0
- package/agents/grok_agent.js +58 -114
- package/agents/minimax_agent.js +92 -0
- package/agents/mureka_agent.js +77 -0
- package/agents/planner_agent.js +172 -0
- package/agents/stability_agent.js +87 -0
- package/agents/test_agent.js +75 -157
- package/agents/weather_agent.js +73 -0
- package/agents/workflow_agent.js +189 -0
- package/bin/dave.js +436 -184
- package/docs/bin-dave.md +85 -35
- package/docs/cdn-ssh.md +100 -0
- package/docs/creating-agents.md +301 -0
- package/docs/creating-toolsets.md +336 -0
- package/docs/docs-organization.md +48 -0
- package/docs/project-overview.md +86 -51
- package/lib/API/elevenlabs.io/music.compose.md +441 -0
- package/lib/API/elevenlabs.io/music.create-composition-plan.md +370 -0
- package/lib/API/elevenlabs.io/music.stream.md +425 -0
- package/lib/API/lalal.ai/lalal.js +445 -0
- package/lib/API/lalal.ai/openapi.json +2614 -0
- package/lib/API/minimax/ImageToolset.js +82 -37
- package/lib/API/minimax/MusicToolset.js +125 -79
- package/lib/API/minimax/VideoToolset.js +170 -167
- package/lib/API/minimax/image.js +5 -1
- package/lib/API/minimax/music.js +210 -23
- package/lib/API/minimax/video.js +242 -53
- package/lib/API/mureka/MusicToolset.js +646 -0
- package/lib/API/mureka/README.md +41 -0
- package/lib/API/mureka/index.js +7 -0
- package/lib/API/mureka/music.js +658 -0
- package/lib/API/openai.com/index.js +7 -0
- package/lib/API/openai.com/{reponses/text.js → responses.js} +64 -18
- package/lib/API/openai.com/video.create.character.md +40 -0
- package/lib/API/openai.com/video.create.md +219 -0
- package/lib/API/openai.com/video.delete.md +44 -0
- package/lib/API/openai.com/video.download.md +31 -0
- package/lib/API/openai.com/video.edit.md +155 -0
- package/lib/API/openai.com/video.extend.md +166 -0
- package/lib/API/openai.com/video.fetch.character.md +43 -0
- package/lib/API/openai.com/video.js +784 -0
- package/lib/API/openai.com/video.list.md +201 -0
- package/lib/API/openai.com/video.remix.md +175 -0
- package/lib/API/openai.com/video.retrieve.md +139 -0
- package/lib/API/openai.com/videoToolset.js +616 -0
- package/lib/API/stability.ai/ImageToolset.js +131 -40
- package/lib/API/stability.ai/MusicToolset.js +79 -47
- package/lib/API/stability.ai/audio.js +63 -131
- package/lib/API/x.ai/chat.responses.md +1040 -0
- package/lib/API/x.ai/image.js +229 -59
- package/lib/API/x.ai/imageToolset.js +376 -0
- package/lib/API/x.ai/index.js +1 -1
- package/lib/API/x.ai/responses.js +9 -18
- package/lib/Agent.js +271 -0
- package/lib/Agent.js.old +284 -0
- package/lib/AgentLauncher.js +593 -0
- package/lib/Cli.js +87 -13
- package/lib/Prompt.js +23 -1
- package/lib/Session.js +5 -4
- package/lib/ToolSet.js +102 -6
- package/lib/agentLoader.js +369 -0
- package/lib/cdn.js +67 -231
- package/lib/{CdnToolset.js → cdnToolset.js} +47 -64
- package/lib/defaultToolsets.js +43 -0
- package/lib/fafs.js +1 -1
- package/lib/genericToolset.js +442 -119
- package/lib/handOffToolset.js +179 -0
- package/lib/index.js +34 -27
- package/lib/toolsetLoader.js +248 -0
- package/package.json +10 -4
- package/types/API/lalal.ai/lalal.d.ts +116 -0
- package/types/API/minimax/image.d.ts +2 -1
- package/types/API/minimax/music.d.ts +189 -26
- package/types/API/minimax/video.d.ts +100 -31
- package/types/API/mureka/index.d.ts +7 -0
- package/types/API/mureka/music.d.ts +472 -0
- package/types/API/openai.com/index.d.ts +7 -0
- package/types/API/openai.com/{reponses/text.d.ts → responses.d.ts} +11 -11
- package/types/API/openai.com/video.d.ts +409 -0
- package/types/API/openai.com/videoToolset.d.ts +24 -0
- package/types/API/stability.ai/audio.d.ts +14 -103
- package/types/API/stability.ai/image.d.ts +2 -2
- package/types/API/x.ai/image.d.ts +138 -26
- package/types/API/x.ai/imageToolset.d.ts +3 -0
- package/types/API/x.ai/index.d.ts +1 -1
- package/types/API/x.ai/responses.d.ts +4 -4
- package/types/Agent.d.ts +123 -0
- package/types/AgentLauncher.d.ts +250 -0
- package/types/Cli.d.ts +28 -8
- package/types/Prompt.d.ts +23 -5
- package/types/Session.d.ts +1 -1
- package/types/ToolSet.d.ts +10 -0
- package/types/agentLoader.d.ts +78 -0
- package/types/cdn.d.ts +15 -90
- package/types/defaultToolsets.d.ts +9 -0
- package/types/fafs.d.ts +1 -1
- package/types/genericToolset.d.ts +1 -1
- package/types/handOffToolset.d.ts +28 -0
- package/types/index.d.ts +19 -17
- package/types/toolsetLoader.d.ts +114 -0
- package/utils/format_log.js +101 -23
- package/utils/launch_agent.js +18 -0
- package/utils/list_sessions.sh +13 -5
- package/utils/search_sessions.sh +65 -29
- package/utils/toolsets.js +33 -0
- package/README.md.bak.1779452127 +0 -240
- package/agents/codeserver.sh +0 -47
- package/agents/daisy_agent.js +0 -173
- package/agents/docs_agent.js +0 -148
- package/agents/memory_agent.js +0 -263
- package/agents/minimax.js +0 -173
- package/agents/npm_agent.js +0 -202
- package/agents/prompt_agent.js +0 -133
- package/agents/readme_agent.js +0 -148
- package/agents/spawn_agent.js +0 -160
- package/agents/stability.js +0 -173
- package/agents/todo_agent.js +0 -175
- package/bin/codeDave +0 -58
- package/docs/agent-dave-websocket-protocol.md +0 -180
- package/docs/agent-manager.md +0 -244
- package/docs/codeserver-pattern.md +0 -191
- package/docs/generic-toolset.md +0 -326
- package/docs/howtos/agent-networking.md +0 -253
- package/docs/howtos/spawn-agents.md.bak +0 -200
- package/docs/howtos/spawn-agents.md.bak_new +0 -200
- package/docs/multi-agent-clusters.md +0 -265
- package/docs/music-toolsets.md +0 -137
- package/docs/path-resolution-best-practices.md +0 -104
- package/docs/plans/minimax-music-generation.md +0 -80
- package/docs/plans/unified-agent-architecture.md +0 -146
- package/docs/plans/websocket-streaming-plan.md.bak +0 -317
- package/docs/prompt/spawn_agent.md +0 -175
- package/docs/prompt/spawn_agent.md.bak +0 -201
- package/docs/prompt/task_clarification_and_documentation.md +0 -35
- package/docs/prompt-class.md +0 -141
- package/docs/todo-archive-infra-2026-04-21.md +0 -15
- package/docs/todo-archive-v0.0.8.md +0 -1
- package/docs/todo-archive-v0.1.0.md +0 -32
- package/docs/todo-archive.md +0 -44
- package/docs/tools-syntax-validation.md +0 -121
- package/docs/toolset.md +0 -164
- package/docs/xai-responses.md +0 -111
- package/docs/xai_collections.md +0 -106
- package/lib/API/x.ai/ImageToolset.js +0 -165
- package/lib/API/x.ai/text.js +0 -415
- package/lib/AgentClient.js +0 -248
- package/lib/AgentManager.js +0 -245
- package/lib/AgentServer.js +0 -404
- package/lib/wsCli.js +0 -287
- package/lib/wsIO.js +0 -90
- package/types/API/x.ai/text.d.ts +0 -286
- package/types/AgentClient.d.ts +0 -109
- package/types/AgentManager.d.ts +0 -100
- package/types/AgentServer.d.ts +0 -89
- package/types/wsCli.d.ts +0 -17
- package/types/wsIO.d.ts +0 -30
- package/utils/test.sh +0 -46
- /package/docs/{suggestions.md → _notes/token-counts.md} +0 -0
- /package/lib/API/openai.com/{reponses/MESSAGES.md → MESSAGES.md} +0 -0
- /package/types/API/{x.ai/ImageToolset.d.ts → mureka/MusicToolset.d.ts} +0 -0
- /package/types/{CdnToolset.d.ts → cdnToolset.d.ts} +0 -0
package/lib/API/x.ai/image.js
CHANGED
|
@@ -1,40 +1,68 @@
|
|
|
1
|
+
import { request as doRequest } from '@j-o-r/apiserver';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
6
|
* @file lib/API/x.ai/image.js
|
|
3
7
|
* @module x.ai/image
|
|
4
|
-
* @description Pure HTTP wrapper for the xAI Grok Imagine API.
|
|
8
|
+
* @description Pure HTTP wrapper for the xAI Grok Imagine API (v1).
|
|
9
|
+
*
|
|
10
|
+
* Provides a clean, minimal, and robust interface for:
|
|
11
|
+
* - Text-to-image generation via `generateImage()`
|
|
12
|
+
* - Natural language image editing (with up to 3 reference images) via `editImage()`
|
|
13
|
+
* - Image-to-video generation via `generateVideo()` — fully automatic with internal polling
|
|
14
|
+
*
|
|
15
|
+
* All public functions handle:
|
|
16
|
+
* - Authentication via the `XAIKEY` environment variable (Bearer token)
|
|
17
|
+
* - Request formatting and validation
|
|
18
|
+
* - Automatic local file saving to `.cache/xai/` (with timestamped filenames)
|
|
19
|
+
* - Robust error handling and propagation
|
|
20
|
+
*
|
|
21
|
+
* Video generation is asynchronous on the xAI server side. The `generateVideo()` function
|
|
22
|
+
* submits the request and internally polls `/videos/{request_id}` until the result is ready
|
|
23
|
+
* (or times out). The helper `pollVideoResult()` is exported for advanced control.
|
|
5
24
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
9
|
-
* - Image-to-video generation (fully automatic with internal polling)
|
|
25
|
+
* **Supported Models** (current as of June 2026):
|
|
26
|
+
* - Image generation & editing: `grok-imagine-image-quality`, `grok-imagine-image`
|
|
27
|
+
* - Video generation: `grok-imagine-video`
|
|
10
28
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
29
|
+
* **Source Documentation**: Derived from the official xAI Imagine API documentation in the
|
|
30
|
+
* accompanying Markdown files:
|
|
31
|
+
* - `image.md` (overview, pricing, capabilities, supported models)
|
|
32
|
+
* - `image.to.generation.md` (text-to-image details, aspect ratios, resolution, n, response_format)
|
|
33
|
+
* - `image.editing.md` (image editing, multi-image support, compositing)
|
|
34
|
+
* - `image.to.video.md` (image-to-video specifics, duration, motion prompts)
|
|
13
35
|
*
|
|
14
|
-
* @see ./image.md
|
|
36
|
+
* @see ./image.md
|
|
37
|
+
* @see ./image.to.generation.md
|
|
38
|
+
* @see ./image.editing.md
|
|
39
|
+
* @see ./image.to.video.md
|
|
15
40
|
*/
|
|
16
41
|
|
|
17
42
|
/**
|
|
18
43
|
* @constant {string} BASE_URL
|
|
19
|
-
* @description Base URL for the xAI API.
|
|
44
|
+
* @description Base URL for the xAI API (version 1). All endpoints are relative to this.
|
|
45
|
+
* @type {string}
|
|
20
46
|
*/
|
|
21
47
|
const BASE_URL = 'https://api.x.ai/v1';
|
|
22
48
|
|
|
23
49
|
/**
|
|
24
50
|
* @constant {string} TMP_DIR
|
|
25
|
-
* @description
|
|
51
|
+
* @description Absolute path to the local directory where generated images and videos are saved.
|
|
52
|
+
* The directory is created automatically (recursively) if it does not exist.
|
|
53
|
+
* Location: `<process.cwd()>/.cache/xai/`
|
|
54
|
+
* @type {string}
|
|
26
55
|
*/
|
|
27
56
|
const TMP_DIR = path.join(process.cwd(), '.cache', 'xai');
|
|
28
57
|
|
|
29
|
-
import { request as doRequest } from '@j-o-r/apiserver';
|
|
30
|
-
import fs from 'fs/promises';
|
|
31
|
-
import path from 'path';
|
|
32
|
-
|
|
33
58
|
/**
|
|
34
59
|
* Builds authenticated headers for xAI requests.
|
|
35
60
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
61
|
+
* Requires the `XAIKEY` environment variable to be set.
|
|
62
|
+
* Throws a descriptive error if the key is missing.
|
|
63
|
+
*
|
|
64
|
+
* @returns {Object} Headers object containing `Authorization: Bearer <key>` and `Content-Type: application/json`.
|
|
65
|
+
* @throws {Error} If `process.env.XAIKEY` is not set.
|
|
38
66
|
*/
|
|
39
67
|
const getHeaders = () => {
|
|
40
68
|
if (!process.env.XAIKEY) {
|
|
@@ -47,23 +75,35 @@ const getHeaders = () => {
|
|
|
47
75
|
};
|
|
48
76
|
|
|
49
77
|
/**
|
|
50
|
-
* Ensures the temporary directory for media files exists.
|
|
78
|
+
* Ensures the temporary directory (`TMP_DIR`) for media files exists.
|
|
79
|
+
*
|
|
80
|
+
* Creates the directory recursively if needed. Safe to call multiple times.
|
|
51
81
|
*
|
|
52
82
|
* @async
|
|
53
|
-
* @returns {Promise<void>}
|
|
83
|
+
* @returns {Promise<void>} Resolves when the directory is guaranteed to exist.
|
|
54
84
|
*/
|
|
55
85
|
async function ensureTmpDir() {
|
|
56
86
|
await fs.mkdir(TMP_DIR, { recursive: true });
|
|
57
87
|
}
|
|
58
88
|
|
|
59
89
|
/**
|
|
60
|
-
* Saves image or video data
|
|
90
|
+
* Saves image or video data to a local file in `TMP_DIR`.
|
|
91
|
+
*
|
|
92
|
+
* Supports multiple input formats:
|
|
93
|
+
* - Remote HTTP(S) URL (auto-downloads)
|
|
94
|
+
* - Base64 string (plain or data URI)
|
|
95
|
+
* - Node.js `Buffer`
|
|
96
|
+
* - `Blob` or `ArrayBuffer`
|
|
97
|
+
*
|
|
98
|
+
* Automatically creates the target directory if necessary.
|
|
99
|
+
* Filenames are timestamped to avoid collisions.
|
|
61
100
|
*
|
|
62
101
|
* @async
|
|
63
102
|
* @param {string|Buffer|Blob|ArrayBuffer} data - Media content to save.
|
|
64
|
-
* @param {string} [filenamePrefix='xai-media'] - Prefix for the
|
|
65
|
-
* @param {string} [ext='png'] - File extension.
|
|
103
|
+
* @param {string} [filenamePrefix='xai-media'] - Prefix for the generated filename.
|
|
104
|
+
* @param {string} [ext='png'] - File extension (e.g. 'png', 'jpg', 'mp4').
|
|
66
105
|
* @returns {Promise<string>} Absolute path to the saved file.
|
|
106
|
+
* @throws {Error} On unsupported data type, download failure, or write error.
|
|
67
107
|
*/
|
|
68
108
|
async function saveMediaToLocal(data, filenamePrefix = 'xai-media', ext = 'png') {
|
|
69
109
|
await ensureTmpDir();
|
|
@@ -95,12 +135,20 @@ async function saveMediaToLocal(data, filenamePrefix = 'xai-media', ext = 'png')
|
|
|
95
135
|
}
|
|
96
136
|
|
|
97
137
|
/**
|
|
98
|
-
* Prepares an image input into the format expected by xAI
|
|
99
|
-
*
|
|
138
|
+
* Prepares an image input into the format expected by the xAI API:
|
|
139
|
+
* `{ url: string, type: 'image_url' }`
|
|
140
|
+
*
|
|
141
|
+
* Accepts a wide variety of inputs and normalizes them:
|
|
142
|
+
* - Public HTTP(S) URL → passed through
|
|
143
|
+
* - Base64 data URI (`data:image/...`) → passed through
|
|
144
|
+
* - Local filesystem path → read and converted to base64 data URI
|
|
145
|
+
* - `Buffer` → converted to PNG base64 data URI
|
|
146
|
+
* - `Blob` → converted to PNG base64 data URI
|
|
100
147
|
*
|
|
101
148
|
* @async
|
|
102
|
-
* @param {string|Buffer|Blob} imageInput - Image source.
|
|
103
|
-
* @returns {Promise<Object>} Object with `url` and `type`.
|
|
149
|
+
* @param {string|Buffer|Blob} imageInput - Image source (URL, path, base64, Buffer, or Blob).
|
|
150
|
+
* @returns {Promise<Object>} Object with `url` (string) and `type: 'image_url'`.
|
|
151
|
+
* @throws {Error} If input is missing or of an unsupported type.
|
|
104
152
|
*/
|
|
105
153
|
async function prepareImageInput(imageInput) {
|
|
106
154
|
if (!imageInput) throw new Error('Image input is required');
|
|
@@ -145,21 +193,56 @@ async function prepareImageInput(imageInput) {
|
|
|
145
193
|
============================================================ */
|
|
146
194
|
|
|
147
195
|
/**
|
|
148
|
-
* Generates one or more images from a text prompt using Grok Imagine.
|
|
196
|
+
* Generates one or more images from a text prompt using Grok Imagine models.
|
|
197
|
+
*
|
|
198
|
+
* **Supported models** (current):
|
|
199
|
+
* - `grok-imagine-image-quality` — Recommended primary model.
|
|
200
|
+
* - `grok-imagine-image` — Alternative image model.
|
|
201
|
+
*
|
|
202
|
+
* Default: `grok-imagine-image-quality`.
|
|
203
|
+
*
|
|
204
|
+
* Supported features:
|
|
205
|
+
* - Up to 10 images per request (`n`)
|
|
206
|
+
* - Custom aspect ratios (see `image.to.generation.md` for the full table)
|
|
207
|
+
* - Resolutions: `1k` or `2k`
|
|
208
|
+
* - Response formats: `url` (temporary public URL) or `b64_json` (base64)
|
|
209
|
+
*
|
|
210
|
+
* All generated images are automatically saved to the local `.cache/xai/` directory.
|
|
211
|
+
* The function returns both the local path and the original API response data.
|
|
149
212
|
*
|
|
150
213
|
* @async
|
|
151
214
|
* @function generateImage
|
|
152
|
-
* @param {string} prompt - Detailed text prompt describing the desired image.
|
|
215
|
+
* @param {string} prompt - Detailed text prompt describing the desired image(s). Required.
|
|
153
216
|
* @param {Object} [options={}] - Optional generation parameters.
|
|
154
|
-
* @param {string} [options.model='grok-imagine-image-quality'] - Model
|
|
155
|
-
* @param {number} [options.n=1] - Number of images to generate
|
|
156
|
-
* @param {string} [options.response_format='url'] - `'url'` or `'b64_json'`.
|
|
157
|
-
* @
|
|
158
|
-
* @
|
|
217
|
+
* @param {string} [options.model='grok-imagine-image-quality'] - Model identifier. Supported values: `grok-imagine-image-quality` (recommended) or `grok-imagine-image`.
|
|
218
|
+
* @param {number} [options.n=1] - Number of images to generate. Range: 1–10. Default: 1.
|
|
219
|
+
* @param {string} [options.response_format='url'] - `'url'` (default) or `'b64_json'`.
|
|
220
|
+
* @param {string} [options.aspect_ratio] - Desired aspect ratio (e.g. `'16:9'`, `'1:1'`, `'auto'`).
|
|
221
|
+
* @param {string} [options.resolution] - Output resolution (`'1k'` or `'2k'`).
|
|
222
|
+
* @returns {Promise<Object>} Result object containing:
|
|
223
|
+
* - `local_path` (string) – absolute path to the saved file
|
|
224
|
+
* - `url` (string, if response_format=url) – temporary public URL
|
|
225
|
+
* - `base64` (string, if response_format=b64_json)
|
|
226
|
+
* - `revised_prompt` (string) – model-revised version of the prompt (if provided)
|
|
227
|
+
* - `raw` (Object) – full original API response
|
|
228
|
+
* @throws {Error} If `prompt` is missing/invalid, or on any API/network error.
|
|
159
229
|
*
|
|
160
230
|
* @example
|
|
231
|
+
* // Basic usage (uses recommended model)
|
|
161
232
|
* const result = await generateImage("A futuristic city at night");
|
|
162
233
|
* console.log(result.local_path);
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* // Multiple images with custom aspect ratio and resolution
|
|
237
|
+
* const results = await generateImage("Mountain landscape at sunrise", {
|
|
238
|
+
* n: 4,
|
|
239
|
+
* aspect_ratio: "16:9",
|
|
240
|
+
* resolution: "2k"
|
|
241
|
+
* });
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* // Using the alternative model
|
|
245
|
+
* const result = await generateImage("...", { model: "grok-imagine-image" });
|
|
163
246
|
*/
|
|
164
247
|
async function generateImage(prompt, options = {}) {
|
|
165
248
|
if (!prompt || typeof prompt !== 'string') {
|
|
@@ -174,6 +257,10 @@ async function generateImage(prompt, options = {}) {
|
|
|
174
257
|
// Note: "size" is not supported by the xAI Grok Imagine API
|
|
175
258
|
};
|
|
176
259
|
|
|
260
|
+
// Add optional params if provided
|
|
261
|
+
if (options.aspect_ratio) body.aspect_ratio = options.aspect_ratio;
|
|
262
|
+
if (options.resolution) body.resolution = options.resolution;
|
|
263
|
+
|
|
177
264
|
const headers = getHeaders();
|
|
178
265
|
const res = await doRequest(`${BASE_URL}/images/generations`, 'POST', headers, body);
|
|
179
266
|
|
|
@@ -213,27 +300,49 @@ async function generateImage(prompt, options = {}) {
|
|
|
213
300
|
|
|
214
301
|
/**
|
|
215
302
|
* Edits one or more images using a natural language prompt.
|
|
216
|
-
*
|
|
303
|
+
*
|
|
304
|
+
* Supports up to 3 reference images for advanced compositing, style transfer,
|
|
305
|
+
* multi-subject scenes, or object insertion/removal.
|
|
306
|
+
*
|
|
307
|
+
* The model analyzes the provided image(s) and applies the edits described in the prompt.
|
|
308
|
+
*
|
|
309
|
+
* **Official API payload (per current xAI Inference API spec)**:
|
|
310
|
+
* - Single image: `"image": { "url": "...", "type": "image_url" }`
|
|
311
|
+
* - Multiple images (up to 3): `"images": [ { "url": "...", "type": "image_url" }, ... ]`
|
|
312
|
+
* (array of objects — **not** `image_urls`)
|
|
313
|
+
*
|
|
314
|
+
* When using multiple images, refer to them in the prompt as <IMAGE_0>, <IMAGE_1>, <IMAGE_2>, etc.
|
|
315
|
+
*
|
|
316
|
+
* **Supported models** (same as generation):
|
|
317
|
+
* - `grok-imagine-image-quality` (recommended)
|
|
318
|
+
* - `grok-imagine-image`
|
|
319
|
+
*
|
|
320
|
+
* All output images are automatically saved locally.
|
|
217
321
|
*
|
|
218
322
|
* @async
|
|
219
323
|
* @function editImage
|
|
220
|
-
* @param {string} prompt -
|
|
221
|
-
* @param {string|Buffer|Blob|Array<string|Buffer|Blob>} imageInputs - One or more images
|
|
324
|
+
* @param {string} prompt - Natural language description of the desired edit(s). Required.
|
|
325
|
+
* @param {string|Buffer|Blob|Array<string|Buffer|Blob>} imageInputs - One or more reference images.
|
|
326
|
+
* Accepts URLs, local paths, base64, Buffers, or Blobs. **Maximum: 3 images**.
|
|
222
327
|
* @param {Object} [options={}] - Optional parameters.
|
|
223
|
-
* @param {string} [options.model='grok-imagine-image-quality']
|
|
224
|
-
* @param {number} [options.n=1]
|
|
225
|
-
* @param {string} [options.response_format='url']
|
|
226
|
-
* @
|
|
227
|
-
* @
|
|
328
|
+
* @param {string} [options.model='grok-imagine-image-quality'] - Model identifier. Supported values: `grok-imagine-image-quality` (recommended) or `grok-imagine-image`.
|
|
329
|
+
* @param {number} [options.n=1] - Number of output images. Range: 1–10. Default: 1.
|
|
330
|
+
* @param {string} [options.response_format='url'] - `'url'` or `'b64_json'`.
|
|
331
|
+
* @param {string} [options.aspect_ratio] - Desired aspect ratio for output.
|
|
332
|
+
* @param {string} [options.resolution] - Output resolution (`'1k'` or `'2k'`).
|
|
333
|
+
* @returns {Promise<Object>} Result object (same shape as `generateImage`):
|
|
334
|
+
* - `local_path`, `url`/`base64`, `revised_prompt`, `raw`
|
|
335
|
+
* @throws {Error} If prompt or imageInputs are missing, more than 3 images are supplied,
|
|
336
|
+
* or on API/network error.
|
|
228
337
|
*
|
|
229
338
|
* @example
|
|
230
|
-
* // Single
|
|
339
|
+
* // Single-image edit (recommended model)
|
|
231
340
|
* const result = await editImage("Make this a pencil sketch", "./photo.png");
|
|
232
341
|
*
|
|
233
342
|
* @example
|
|
234
343
|
* // Multi-image editing (up to 3)
|
|
235
344
|
* const result = await editImage(
|
|
236
|
-
* "Combine
|
|
345
|
+
* "Combine <IMAGE_0> and <IMAGE_1> into one scene with a city background",
|
|
237
346
|
* ["./person1.png", "./person2.png"]
|
|
238
347
|
* );
|
|
239
348
|
*/
|
|
@@ -252,11 +361,22 @@ async function editImage(prompt, imageInputs, options = {}) {
|
|
|
252
361
|
const body = {
|
|
253
362
|
model: options.model || 'grok-imagine-image-quality',
|
|
254
363
|
prompt,
|
|
255
|
-
image: preparedImages.length === 1 ? preparedImages[0] : preparedImages,
|
|
256
364
|
n: options.n || 1,
|
|
257
365
|
response_format: options.response_format || 'url'
|
|
258
366
|
};
|
|
259
367
|
|
|
368
|
+
if (preparedImages.length === 1) {
|
|
369
|
+
// Single image: object form (official docs example)
|
|
370
|
+
body.image = preparedImages[0];
|
|
371
|
+
} else {
|
|
372
|
+
// Multi-image (2–3): array of objects under the official `images` field
|
|
373
|
+
// (per current Inference API spec — not `image_urls`)
|
|
374
|
+
body.images = preparedImages;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if (options.aspect_ratio) body.aspect_ratio = options.aspect_ratio;
|
|
378
|
+
if (options.resolution) body.resolution = options.resolution;
|
|
379
|
+
|
|
260
380
|
const headers = getHeaders();
|
|
261
381
|
const res = await doRequest(`${BASE_URL}/images/edits`, 'POST', headers, body);
|
|
262
382
|
|
|
@@ -294,7 +414,32 @@ async function editImage(prompt, imageInputs, options = {}) {
|
|
|
294
414
|
INTERNAL: Poll video result
|
|
295
415
|
============================================================ */
|
|
296
416
|
|
|
297
|
-
|
|
417
|
+
/**
|
|
418
|
+
* Polls the xAI video status endpoint until generation completes or fails.
|
|
419
|
+
*
|
|
420
|
+
* This is an internal helper used by `generateVideo()`, but it is exported for
|
|
421
|
+
* advanced use cases where you want manual control over polling parameters.
|
|
422
|
+
*
|
|
423
|
+
* The xAI video endpoint returns `status: 'done'`, `'failed'`, or `'expired'`.
|
|
424
|
+
* On success it also provides `video.url`.
|
|
425
|
+
*
|
|
426
|
+
* **Timeout note**: Video generation can be slow. The default `intervalMs` was
|
|
427
|
+
* increased (and the function exported) to give callers more flexibility.
|
|
428
|
+
* Recommended values: `intervalMs` 15000–30000, `maxAttempts` 60+ for longer videos.
|
|
429
|
+
*
|
|
430
|
+
* @async
|
|
431
|
+
* @function pollVideoResult
|
|
432
|
+
* @param {string} requestId - The `request_id` returned from a `/videos/generations` call. Required.
|
|
433
|
+
* @param {number} [maxAttempts=60] - Maximum number of polling attempts. Default: 60.
|
|
434
|
+
* @param {number} [intervalMs=15000] - Milliseconds to wait between polls. Default: 15000.
|
|
435
|
+
* @returns {Promise<Object>} Result containing:
|
|
436
|
+
* - `local_path` (string) – path to the saved MP4
|
|
437
|
+
* - `url` (string) – public video URL
|
|
438
|
+
* - `status: 'done'`
|
|
439
|
+
* - `raw` (Object) – full response
|
|
440
|
+
* @throws {Error} On failure/expiration status, missing request_id, or polling timeout.
|
|
441
|
+
*/
|
|
442
|
+
async function pollVideoResult(requestId, maxAttempts = 60, intervalMs = 15000) {
|
|
298
443
|
if (!requestId) throw new Error('Video request_id is required');
|
|
299
444
|
|
|
300
445
|
const headers = getHeaders();
|
|
@@ -316,14 +461,14 @@ async function _pollVideoResult(requestId, maxAttempts = 60, intervalMs = 5000)
|
|
|
316
461
|
}
|
|
317
462
|
|
|
318
463
|
if (data.status === 'failed' || data.status === 'expired') {
|
|
319
|
-
throw new Error(`Video generation ${data.status}: ${JSON.stringify(data)}`);
|
|
464
|
+
throw new Error(`Video generation ${data.status}: ${JSON.stringify(data)} request: ${requestId}`);
|
|
320
465
|
}
|
|
321
466
|
}
|
|
322
467
|
|
|
323
468
|
await new Promise(resolve => setTimeout(resolve, intervalMs));
|
|
324
469
|
}
|
|
325
470
|
|
|
326
|
-
throw new Error(`Timeout polling video request ${requestId}`);
|
|
471
|
+
throw new Error(`Timeout polling video request: ${requestId}`);
|
|
327
472
|
}
|
|
328
473
|
|
|
329
474
|
/* ============================================================
|
|
@@ -331,28 +476,52 @@ async function _pollVideoResult(requestId, maxAttempts = 60, intervalMs = 5000)
|
|
|
331
476
|
============================================================ */
|
|
332
477
|
|
|
333
478
|
/**
|
|
334
|
-
* Generates a video from a still image
|
|
335
|
-
*
|
|
336
|
-
*
|
|
479
|
+
* Generates a video from a still image + text motion prompt.
|
|
480
|
+
*
|
|
481
|
+
* This function is **fully automatic**: it posts to `/videos/generations` and then
|
|
482
|
+
* internally calls `pollVideoResult()` until the video is ready.
|
|
483
|
+
*
|
|
484
|
+
* **Supported model**: Only `grok-imagine-video` (the sole model for image-to-video generation).
|
|
485
|
+
*
|
|
486
|
+
* The provided image becomes the first frame; the prompt describes the desired motion/animation.
|
|
487
|
+
* Supports public URLs or base64 data URIs for the source image.
|
|
488
|
+
*
|
|
489
|
+
* Video parameters (from official docs):
|
|
490
|
+
* - `duration`: 1–15 seconds (affects pricing)
|
|
491
|
+
* - `aspect_ratio`, `resolution`
|
|
492
|
+
*
|
|
493
|
+
* **Important**: Video generation can take a long time and is prone to polling timeouts.
|
|
494
|
+
* Use the exported `pollVideoResult()` directly with higher `intervalMs`/`maxAttempts`
|
|
495
|
+
* if you encounter frequent timeouts.
|
|
337
496
|
*
|
|
338
497
|
* @async
|
|
339
498
|
* @function generateVideo
|
|
340
|
-
* @param {string} prompt - Description of the desired motion or animation.
|
|
341
|
-
* @param {string|Buffer|Blob} imageInput - Source image (URL, path, base64, Buffer, or Blob).
|
|
499
|
+
* @param {string} prompt - Description of the desired motion or animation. Required.
|
|
500
|
+
* @param {string|Buffer|Blob} imageInput - Source image (URL, local path, base64, Buffer, or Blob). Required.
|
|
342
501
|
* @param {Object} [options={}] - Optional video parameters.
|
|
343
|
-
* @param {
|
|
344
|
-
* @param {
|
|
502
|
+
* @param {string} [options.model='grok-imagine-video'] - Model identifier (only `grok-imagine-video` is supported).
|
|
503
|
+
* @param {number} [options.duration=8] - Video length in seconds (1–15). Default: 8.
|
|
504
|
+
* @param {string} [options.aspect_ratio='16:9'] - Aspect ratio for the video.
|
|
345
505
|
* @param {string} [options.resolution='720p'] - Output resolution.
|
|
346
|
-
* @returns {Promise<Object>} Result containing `local_path
|
|
347
|
-
* @throws {Error}
|
|
506
|
+
* @returns {Promise<Object>} Result containing `local_path`, `url`, `status: 'done'`, and `raw`.
|
|
507
|
+
* @throws {Error} If prompt or imageInput is missing, or on generation failure/timeout.
|
|
348
508
|
*
|
|
349
509
|
* @example
|
|
510
|
+
* // Basic usage with public image URL
|
|
350
511
|
* const result = await generateVideo(
|
|
351
512
|
* "Make the water crash down and slowly pan out",
|
|
352
513
|
* "https://example.com/waterfall.png",
|
|
353
514
|
* { duration: 12 }
|
|
354
515
|
* );
|
|
355
516
|
* console.log(result.local_path);
|
|
517
|
+
*
|
|
518
|
+
* @example
|
|
519
|
+
* // Using a local file with custom aspect ratio
|
|
520
|
+
* const result = await generateVideo(
|
|
521
|
+
* "Animate the character walking forward",
|
|
522
|
+
* "./character.png",
|
|
523
|
+
* { duration: 10, aspect_ratio: "9:16" }
|
|
524
|
+
* );
|
|
356
525
|
*/
|
|
357
526
|
async function generateVideo(prompt, imageInput, options = {}) {
|
|
358
527
|
if (!prompt) throw new Error('generateVideo() requires a prompt');
|
|
@@ -382,12 +551,13 @@ async function generateVideo(prompt, imageInput, options = {}) {
|
|
|
382
551
|
throw new Error('No request_id returned from video generation');
|
|
383
552
|
}
|
|
384
553
|
|
|
385
|
-
// Automatically poll until ready
|
|
386
|
-
return await
|
|
554
|
+
// Automatically poll until ready (uses updated defaults in pollVideoResult)
|
|
555
|
+
return await pollVideoResult(request_id);
|
|
387
556
|
}
|
|
388
557
|
|
|
389
558
|
export {
|
|
390
559
|
generateImage,
|
|
391
560
|
editImage,
|
|
392
|
-
generateVideo
|
|
393
|
-
|
|
561
|
+
generateVideo,
|
|
562
|
+
pollVideoResult
|
|
563
|
+
};
|