@juspay/neurolink 9.86.5 → 9.87.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -51,27 +51,37 @@ export class ReplicateVideoHandler {
51
51
  const startTime = Date.now();
52
52
  const model = options.model ?? DEFAULT_MODEL;
53
53
  const dataUri = `data:image/${this.detectImageType(image)};base64,${image.toString("base64")}`;
54
- // Wan-Alpha + most image-to-video models accept this shape; specific
55
- // models may require provider-specific extras passed through
56
- // VideoOutputOptions.[unknown key].
54
+ // Replicate image-to-video models do not share an input schema. The
55
+ // legacy shape below (`image` + `num_frames`/`fps`/`aspect_ratio`) fits
56
+ // Wan-Alpha-era models; current models (minimax/hailuo-2.3-*,
57
+ // wan-video/wan-2.7-i2v) key the image as `first_frame_image` /
58
+ // `first_frame` and take `duration` instead of frame counts — a missing
59
+ // required image key fails the prediction on submit. `imageInputKey`
60
+ // selects the image key AND the modern `duration`/`resolution` shape;
61
+ // omitting it preserves the legacy payload exactly.
57
62
  //
58
- // `resolution` is forwarded as the `resolution` input parameter.
59
- // Wan-Alpha and several other Replicate image-to-video models accept it
60
- // (e.g. "720p", "1080p"). Models that do not recognise it will silently
61
- // ignore the field — the Replicate API does not reject unknown input keys.
62
63
  // `calculateDimensions` still populates the metadata `dimensions` field
63
64
  // so downstream consumers always receive correct width/height regardless
64
65
  // of whether the model honoured the resolution hint.
65
- const inputPayload = {
66
- image: dataUri,
67
- prompt,
68
- num_frames: (options.length ?? 4) * 24, // Assume 24 fps
69
- fps: 24,
70
- aspect_ratio: options.aspectRatio,
71
- ...(options.resolution !== undefined
72
- ? { resolution: options.resolution }
73
- : {}),
74
- };
66
+ const inputPayload = options.imageInputKey !== undefined
67
+ ? {
68
+ [options.imageInputKey]: dataUri,
69
+ prompt,
70
+ duration: options.length ?? 4,
71
+ ...(options.resolution !== undefined
72
+ ? { resolution: options.resolution }
73
+ : {}),
74
+ }
75
+ : {
76
+ image: dataUri,
77
+ prompt,
78
+ num_frames: (options.length ?? 4) * 24, // Assume 24 fps
79
+ fps: 24,
80
+ aspect_ratio: options.aspectRatio,
81
+ ...(options.resolution !== undefined
82
+ ? { resolution: options.resolution }
83
+ : {}),
84
+ };
75
85
  let prediction;
76
86
  try {
77
87
  prediction = await predict(auth, { model, input: inputPayload }, { abortSignal: options.abortSignal });
@@ -190,6 +190,18 @@ export type VideoOutputOptions = {
190
190
  * `image` Buffer argument passed to `generate()`.
191
191
  */
192
192
  imageUrl?: string;
193
+ /**
194
+ * Replicate only: the input-schema key the model expects the image under.
195
+ * Replicate image-to-video models disagree on this — e.g.
196
+ * `minimax/hailuo-2.3-fast` requires `first_frame_image`,
197
+ * `wan-video/wan-2.7-i2v` requires `first_frame` — and a model whose
198
+ * required image key is missing fails the prediction on submit. Setting
199
+ * this also switches the payload to the modern `duration`/`resolution`
200
+ * field shape those models expect (instead of the legacy
201
+ * `num_frames`/`fps`/`aspect_ratio` shape). Omit for models that accept
202
+ * the default `image` key.
203
+ */
204
+ imageInputKey?: string;
193
205
  /**
194
206
  * Per-call provider credentials. Takes precedence over instance-level
195
207
  * credentials set at construction time, which in turn override env vars.
@@ -28,13 +28,23 @@ const DEFAULT_TIMEOUT_MS = 60_000;
28
28
  function buildPinnedAgent(hostname, ip, family) {
29
29
  return new Agent({
30
30
  connect: {
31
- lookup: (host, _options, callback) => {
31
+ lookup: (host, options, callback) => {
32
32
  if (host.toLowerCase() !== hostname.toLowerCase()) {
33
33
  // The host the connect layer asks for differs from the URL host —
34
34
  // this happens for absolute Host headers etc. Reject defensively.
35
35
  callback(new Error(`safeFetch: refusing to resolve "${host}" — expected "${hostname}"`), "", 0);
36
36
  return;
37
37
  }
38
+ // Node ≥20 enables autoSelectFamily (Happy Eyeballs) by default, and
39
+ // its lookup contract passes `all: true` expecting an address ARRAY.
40
+ // Answering with the string form there fails the connection with
41
+ // "Invalid IP address: undefined" — which broke every safeDownload
42
+ // (Replicate / Runway / Kling asset fetches) on modern Node while
43
+ // plain curl of the same URL succeeded.
44
+ if (options?.all) {
45
+ callback(null, [{ address: ip, family }]);
46
+ return;
47
+ }
38
48
  callback(null, ip, family);
39
49
  },
40
50
  },
@@ -190,6 +190,18 @@ export type VideoOutputOptions = {
190
190
  * `image` Buffer argument passed to `generate()`.
191
191
  */
192
192
  imageUrl?: string;
193
+ /**
194
+ * Replicate only: the input-schema key the model expects the image under.
195
+ * Replicate image-to-video models disagree on this — e.g.
196
+ * `minimax/hailuo-2.3-fast` requires `first_frame_image`,
197
+ * `wan-video/wan-2.7-i2v` requires `first_frame` — and a model whose
198
+ * required image key is missing fails the prediction on submit. Setting
199
+ * this also switches the payload to the modern `duration`/`resolution`
200
+ * field shape those models expect (instead of the legacy
201
+ * `num_frames`/`fps`/`aspect_ratio` shape). Omit for models that accept
202
+ * the default `image` key.
203
+ */
204
+ imageInputKey?: string;
193
205
  /**
194
206
  * Per-call provider credentials. Takes precedence over instance-level
195
207
  * credentials set at construction time, which in turn override env vars.
@@ -28,13 +28,23 @@ const DEFAULT_TIMEOUT_MS = 60_000;
28
28
  function buildPinnedAgent(hostname, ip, family) {
29
29
  return new Agent({
30
30
  connect: {
31
- lookup: (host, _options, callback) => {
31
+ lookup: (host, options, callback) => {
32
32
  if (host.toLowerCase() !== hostname.toLowerCase()) {
33
33
  // The host the connect layer asks for differs from the URL host —
34
34
  // this happens for absolute Host headers etc. Reject defensively.
35
35
  callback(new Error(`safeFetch: refusing to resolve "${host}" — expected "${hostname}"`), "", 0);
36
36
  return;
37
37
  }
38
+ // Node ≥20 enables autoSelectFamily (Happy Eyeballs) by default, and
39
+ // its lookup contract passes `all: true` expecting an address ARRAY.
40
+ // Answering with the string form there fails the connection with
41
+ // "Invalid IP address: undefined" — which broke every safeDownload
42
+ // (Replicate / Runway / Kling asset fetches) on modern Node while
43
+ // plain curl of the same URL succeeded.
44
+ if (options?.all) {
45
+ callback(null, [{ address: ip, family }]);
46
+ return;
47
+ }
38
48
  callback(null, ip, family);
39
49
  },
40
50
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "9.86.5",
3
+ "version": "9.87.1",
4
4
  "packageManager": "pnpm@10.15.1",
5
5
  "description": "TypeScript AI SDK with 24+ LLM providers behind one consistent API. MCP-native (58+ servers), voice TTS/STT/realtime, RAG, agents, memory, context compaction. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · DeepSeek · NVIDIA NIM and more.",
6
6
  "author": {