fieldkit-sdk
v2.0.1
Published
SDK for media analysis, content generation, document processing, and utility APIs
Maintainers
Readme
fieldkit-sdk
Node.js SDK for UnityClaw API - AI-powered image/video generation, media analysis, document processing, and more.
Installation
npm install fieldkit-sdkQuick Start
import { UnityClawClient } from 'fieldkit-sdk';
// Reads UNITYCLAW_KEY from environment variable
const client = new UnityClawClient();
// Or with explicit config
const client = new UnityClawClient({
apiKey: 'your-api-key',
baseUrl: 'https://unityclaw.com',
taskDir: './tasks',
timeout: 900000 // 15 minutes
});
// Write with Gemini, optionally grounded in local reference files
const writingResult = await client.writing.gemini({
prompt: '根据附件写一篇结构清晰的产品介绍',
attachment: [{ path: './files/product-brief.pdf' }]
});
// Generate image
const imageResult = await client.image.jimeng({
prompt: 'A beautiful sunset over mountains',
size: '2048x2048'
});
// Generate video (Kling)
const videoResult = await client.video.kling({
prompt: 'A cat playing piano',
model: 'kling-v2-6',
aspect_ratio: '16:9',
duration: '5'
});
// Translate document (local file will be auto-uploaded to get tmp_url)
const docResult = await client.document.translate({
attachment: [{ path: './files/doc.pdf' }],
source_language: { value: 'en', label: 'English' },
target_language: { value: 'zh', label: 'Chinese' }
});
// Analyze media
const mediaResult = await client.media.analyze({
url: [{ link: 'https://youtube.com/watch?v=...' }]
});Configuration
Browser authorization
The SDK does not start OAuth automatically. If creating a client throws
AuthenticationRequiredError (code: 'AUTH_REQUIRED'), the calling application
should ask the user for consent. Only after explicit consent, call:
import { AuthenticationRequiredError, UnityClawClient, loginWithOAuth } from 'fieldkit-sdk';
try {
const client = new UnityClawClient();
// Use the client for the original operation.
} catch (error) {
if (error instanceof AuthenticationRequiredError) {
// Ask the user for consent before calling loginWithOAuth().
await loginWithOAuth();
const client = new UnityClawClient();
// Retry the original operation once.
} else {
throw error;
}
}loginWithOAuth() performs Authorization Code + PKCE in the browser and saves
the resulting API Key to ~/.unityclaw/config.json. It does not return or log
the Key. For a non-production issuer, pass issuer explicitly. This SDK change
does not modify existing Skills or automatically retry operations.
Environment Variables
UNITYCLAW_KEY- Your UnityClaw API keyUNITYCLAW_API_KEY- Legacy API key fallbackUNITYCLAW_BASE_URL- API base URL (optional, defaults to https://unityclaw.com)UNITYCLAW_SOURCE- Value passed through in theX-Sourcerequest header (optional, defaults tounityclaw)
CLI Configuration
Use the CLI to persist configuration:
# Install globally
npm install -g fieldkit-sdk
# Set API key (stored in ~/.unityclaw/config.json)
fieldkit config set apiKey your-api-key
# Set custom base URL
fieldkit config set baseUrl https://custom.example.com
# Set the source identifier passed to the API
fieldkit config set source your-source
# View current configuration
fieldkit config
# Get a specific value
fieldkit config get apiKeyConfiguration Priority
- Constructor parameters (highest priority)
- Environment variables
- Config file (~/.unityclaw/config.json)
- Default values (lowest priority)
Task Folders
The synchronous SDK methods create a task folder with:
logs/request.json- Request detailslogs/response.json- API responselogs/execution.log- Execution logattachments/- Downloaded attachments (to avoid link expiration)
Async video submissions and video.queryTask() do not create a local task
folder or download results. Persist the returned task ID and save the final
video URL from a successful query according to your application's needs.
Default Task Directory
Tasks are stored in ~/Documents/tasks/ by default. You can override this:
const client = new UnityClawClient({
taskDir: '/path/to/custom/tasks',
source: 'your-source'
});API Reference
Image Generation
// JiMeng
await client.image.jimeng({
prompt: 'A sunset over mountains',
size: '2048x2048'
});
// JiMeng (Doubao)
await client.image.jimeng({
prompt: 'A futuristic city',
model: 'v6.0'
});
// GPT Image
await client.image.gptImage({
prompt: 'A clean product photo of a blue ceramic cup',
aspect_ratio: '1:1',
size: '1K',
output_format: 'png'
});
// GPT Image 2.5
await client.image.gptImage25({
prompt: 'A premium skincare product photo',
attachment: [{ tmp_url: 'https://example.com/reference.png' }],
aspect_ratio: '4:5',
size: '2K'
});
// Nano Banana 2
await client.image.aiImagePro({
prompt: '生成一张电商产品主图',
model: 'v2',
aspect_ratio: '1:1',
size: '2K'
});
// Nano Banana Pro
await client.image.aiImagePro({
prompt: '生成一张高质感品牌海报',
model: 'pro',
aspect_ratio: '4:5',
size: '2K'
});
// Gemini multi-prompt: generate up to five images in one request
await client.image.geminiMulti({
prompt: '第一张:商品正面图',
prompt_2: '第二张:商品使用场景图',
prompt_3: '第三张:商品细节特写图',
aspect_ratio: '4:5',
attachment: [{ path: './files/product.png' }]
});
// Gemini Image 2 multi-prompt (defaults to 2K)
await client.image.aiImage2Multi({
prompt: '第一张品牌海报',
prompt_2: '第二张品牌海报',
size: '2K'
});
// Gemini Image Lite multi-prompt (defaults to 1:1)
await client.image.aiImageLiteMulti({
prompt: '第一张方形商品图',
prompt_2: '第二张方形商品图'
});Video Generation
Wan 3.0, MiniMax H3, Seedance Mini, Seedance 2.5, and Seedance Real use the
async OpenAPI. Their methods return a task ID, not a finished video. Persist
that ID and call client.video.queryTask(taskId) later; do not submit again
when an Agent run ends. queryTask returns running, succeeded, or failed
and does not wait or generate. Other video methods retain synchronous results.
If OpenAPI is served from a different public origin, set openApiBaseUrl when
constructing the client. The target environment must route /openapi/v1 to
the OpenAPI service before using these methods.
// Kling
await client.video.kling({
prompt: 'A dancing robot',
model: 'kling-v1-5'
});
// These five methods submit async tasks. Save taskId, then query later.
// Seedance 2.5 (automatic duration or 4-30 seconds)
const submitted = await client.video.seedance25({
prompt: '镜头缓慢推近桌面上的产品',
resolution: '720p',
ratio: '16:9',
duration: '10'
});
// Seedance Mini (automatic duration or 4-15 seconds)
await client.video.seedance2Mini({
prompt: '让参考图中的人物转身看向镜头',
attachment: [{ path: './files/person.jpg' }],
ratio: '9:16',
duration: '8'
});
// Wan 3.0 reference-to-video (defaults: 1080P, adaptive ratio, 5 seconds)
await client.video.wan3({
prompt: '让产品缓慢旋转并展示材质细节',
action: 'reference',
attachment: [{ path: './files/product.jpg' }],
ratio: '16:9'
});
// Wan 3.0 first/last-frame video
await client.video.wan3({
action: 'first_last_frame',
attachment: [
{ path: './files/first-frame.jpg' },
{ path: './files/last-frame.jpg' }
],
resolution: '1080P',
duration: '10'
});
// MiniMax H3 and Seedance Real also submit async tasks:
// client.video.minimaxH3({ prompt: '...', ratio: '16:9' })
// client.video.seedanceReal({ prompt: '...' })
const task = await client.video.queryTask(submitted.taskId);
if (task.status === 'succeeded') console.log(task.result.videos);
else if (task.status === 'failed') console.error(task.error);
// If running, persist taskId and query it later. queryTask never resubmits.Document Processing
// Translate document
await client.document.translate({
attachment: [{ tmp_url: 'https://...', name: 'doc.pdf' }],
source_language: { value: 'en', label: 'English' },
target_language: { value: 'zh', label: 'Chinese' }
});
// Convert document
await client.document.convert({
attachment: [{ path: './files/doc.pdf' }],
input_format: 'pdf',
output_format: 'docx'
});Media Analysis
const result = await client.media.analyze({
url: [{ link: 'https://youtube.com/watch?v=...' }]
});
console.log(result.response.data?.summary);
console.log(result.response.data?.subtitle);License
MIT
