All skills
inference-shell avatar

/javascript-sdk

@fbe0aa4

JavaScript/TypeScript SDK for inference.sh - run AI apps, build agents, integrate with all models. Package: @inferencesh/sdk (npm install). Full TypeScript support, streaming, file uploads. Build agents with template or ad-hoc patterns, tool builder API, skills, human approval. Use for: JavaScript integration, TypeScript, Node.js, React, Next.js, frontend apps. Triggers: javascript sdk, typescript sdk, npm install, node.js api, js client, react ai, next.js ai, frontend sdk, @inferencesh/sdk, typescript agent, browser sdk, js integration

Use this Skill: https://skilld.dev/gh/inference-shell/skills/javascript-sdk

This session only. Nothing lands on disk.

referencesstreaming.md

≈2.4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Streaming Reference

Real-time progress updates and Server-Sent Events (SSE) handling.

Task Status Flow

RECEIVED (1) → QUEUED (2) → SCHEDULED (3) → PREPARING (4)
→ SERVING (5) → SETTING_UP (6) → RUNNING (7) → UPLOADING (8)
→ COMPLETED (10), FAILED (11), or CANCELLED (12)

Basic Streaming

import { inference } from '@inferencesh/sdk';

const client = inference({ apiKey: 'inf_...' });

const stream = await client.run({
  app: 'google/veo-3-1-fast',
  input: { prompt: 'A sunset timelapse' }
}, { stream: true });

for await (const update of stream) {
  console.log(`Status: ${update.status}`);
}

Handling Different Update Types

const stream = await client.run(config, { stream: true });

for await (const update of stream) {
  const { status } = update;

  // Task state changes
  if (status === 'queued') {
    console.log('Task queued, waiting for worker...');
  } else if (status === 'running') {
    console.log('Task is running...');
  } else if (status === 'completed') {
    console.log('Done!');
    console.log('Output:', update.output);
  } else if (status === 'failed') {
    console.log('Error:', update.error);
  }

  // Progress logs
  if (update.logs?.length) {
    for (const log of update.logs) {
      console.log(`  Log: ${log}`);
    }
  }

  // Partial outputs
  if (update.partial_output) {
    console.log(`  Partial: ${update.partial_output}`);
  }
}

Progress Tracking with UI

Node.js CLI Progress Bar

import { inference } from '@inferencesh/sdk';

function progressBar(current: number, total: number, width = 50) {
  const filled = Math.round(width * current / total);
  const bar = '█'.repeat(filled) + '░'.repeat(width - filled);
  const percent = (current / total * 100).toFixed(1);
  process.stdout.write(`\r[${bar}] ${percent}%`);
}

const stream = await client.run(config, { stream: true });

for await (const update of stream) {
  if (update.progress) {
    progressBar(update.progress.current, update.progress.total);
  }

  if (update.status === 'completed') {
    console.log('\n✓ Complete!');
  }
}

React Progress Component

import { useState, useEffect } from 'react';
import { inference } from '@inferencesh/sdk';

function ProgressDisplay({ config }: { config: any }) {
  const [status, setStatus] = useState('idle');
  const [progress, setProgress] = useState(0);
  const [logs, setLogs] = useState<string[]>([]);

  useEffect(() => {
    const client = inference({ proxyUrl: '/api/inference/proxy' });

    async function run() {
      const stream = await client.run(config, { stream: true });

      for await (const update of stream) {
        setStatus(update.status);

        if (update.progress) {
          setProgress(update.progress.current / update.progress.total * 100);
        }

        if (update.logs) {
          setLogs(prev => [...prev, ...update.logs]);
        }
      }
    }

    run();
  }, [config]);

  return (
    <div>
      <div>Status: {status}</div>
      <progress value={progress} max={100} />
      <ul>
        {logs.map((log, i) => <li key={i}>{log}</li>)}
      </ul>
    </div>
  );
}

Streaming with Timeout

async function streamWithTimeout(config: any, timeoutMs: number) {
  const client = inference({ apiKey: 'inf_...' });
  const start = Date.now();

  const stream = await client.run(config, { stream: true });

  for await (const update of stream) {
    if (Date.now() - start > timeoutMs) {
      console.log('Timeout reached');
      break;
    }

    console.log(`Status: ${update.status}`);

    if (['completed', 'failed'].includes(update.status)) {
      return update;
    }
  }
}

const result = await streamWithTimeout(config, 60000); // 1 minute

Agent Streaming

const agent = client.agent('my-org/assistant@latest');

const response = await agent.sendMessage('Explain quantum entanglement', {
  onMessage: (msg) => {
    if (msg.content) {
      // Stream text as it arrives
      process.stdout.write(msg.content);
    }

    if (msg.type === 'thinking') {
      console.log(`\n[Thinking: ${msg.content}]`);
    }
  },
  onToolCall: async (call) => {
    console.log(`\n[Calling tool: ${call.name}]`);
    const result = await executeTool(call.name, call.args);
    agent.submitToolResult(call.id, result);
  }
});

Multiple Streams in Parallel

async function parallelStreams() {
  const client = inference({ apiKey: 'inf_...' });

  const configs = [
    { app: 'infsh/flux-schnell', input: { prompt: 'A mountain' } },
    { app: 'infsh/flux-schnell', input: { prompt: 'An ocean' } },
    { app: 'infsh/flux-schnell', input: { prompt: 'A forest' } }
  ];

  async function streamOne(config: any, index: number) {
    const stream = await client.run(config, { stream: true });

    for await (const update of stream) {
      console.log(`[${index}] ${update.status}`);

      if (update.status === 'completed') {
        return update.output;
      }
    }
  }

  const results = await Promise.all(
    configs.map((c, i) => streamOne(c, i))
  );

  return results;
}

Cancelling a Stream

async function cancellableStream(config: any) {
  const client = inference({ apiKey: 'inf_...' });
  const controller = new AbortController();

  // Cancel after 10 seconds
  setTimeout(() => controller.abort(), 10000);

  try {
    const stream = await client.run(config, {
      stream: true,
      signal: controller.signal
    });

    for await (const update of stream) {
      console.log(update.status);
    }
  } catch (e) {
    if (e.name === 'AbortError') {
      console.log('Stream cancelled');
    } else {
      throw e;
    }
  }
}

Collecting All Logs

async function collectLogs(config: any) {
  const client = inference({ apiKey: 'inf_...' });
  const allLogs: string[] = [];

  const stream = await client.run(config, { stream: true });

  for await (const update of stream) {
    if (update.logs) {
      allLogs.push(...update.logs);
    }

    if (update.status === 'completed') {
      console.log('Final logs:');
      allLogs.forEach(log => console.log(`  ${log}`));
      return update.output;
    }
  }
}

Custom Stream Processor Class

class StreamProcessor {
  logs: string[] = [];
  startTime?: number;
  endTime?: number;

  process(update: any): boolean {
    if (!this.startTime) {
      this.startTime = Date.now();
    }

    if (update.logs) {
      this.logs.push(...update.logs);
    }

    if (['completed', 'failed'].includes(update.status)) {
      this.endTime = Date.now();
      return true; // Done
    }

    return false; // Continue
  }

  get duration(): number | null {
    if (this.startTime && this.endTime) {
      return this.endTime - this.startTime;
    }
    return null;
  }
}

// Usage
const processor = new StreamProcessor();
const stream = await client.run(config, { stream: true });

for await (const update of stream) {
  if (processor.process(update)) {
    break;
  }
}

console.log(`Duration: ${processor.duration}ms`);
console.log(`Logs: ${processor.logs.length}`);

Server-Sent Events in Browser

// For custom SSE handling in browser
async function browserSSE(taskId: string) {
  const eventSource = new EventSource(
    `/api/inference/stream?taskId=${taskId}`
  );

  eventSource.onmessage = (event) => {
    const update = JSON.parse(event.data);
    console.log('Update:', update);

    if (['completed', 'failed'].includes(update.status)) {
      eventSource.close();
    }
  };

  eventSource.onerror = (error) => {
    console.error('SSE error:', error);
    eventSource.close();
  };
}

React Hook for Streaming

import { useState, useCallback, useRef } from 'react';
import { inference } from '@inferencesh/sdk';

interface StreamState {
  status: string;
  output: any;
  logs: string[];
  error: string | null;
}

function useStream() {
  const [state, setState] = useState<StreamState>({
    status: 'idle',
    output: null,
    logs: [],
    error: null
  });
  const controllerRef = useRef<AbortController | null>(null);

  const run = useCallback(async (config: any) => {
    const client = inference({ proxyUrl: '/api/inference/proxy' });
    controllerRef.current = new AbortController();

    setState({ status: 'starting', output: null, logs: [], error: null });

    try {
      const stream = await client.run(config, {
        stream: true,
        signal: controllerRef.current.signal
      });

      for await (const update of stream) {
        setState(prev => ({
          ...prev,
          status: update.status,
          logs: update.logs ? [...prev.logs, ...update.logs] : prev.logs,
          output: update.output || prev.output
        }));
      }
    } catch (e: any) {
      if (e.name !== 'AbortError') {
        setState(prev => ({ ...prev, status: 'error', error: e.message }));
      }
    }
  }, []);

  const cancel = useCallback(() => {
    controllerRef.current?.abort();
  }, []);

  return { ...state, run, cancel };
}

// Usage in component
function Generator() {
  const { status, output, logs, run, cancel } = useStream();

  return (
    <div>
      <button onClick={() => run({ app: 'my-app', input: {...} })}>
        Start
      </button>
      <button onClick={cancel}>Cancel</button>
      <div>Status: {status}</div>
      {output && <img src={output.url} />}
    </div>
  );
}

Source: SKILL.md on GitHub

2 warnings16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The skill is a documentation package for the inference.sh JavaScript SDK. It provides comprehensive reference material and code examples for building AI agents and integrating with various AI models. Security analysis identified risks associated with pedagogical examples that use unsafe execution methods and the inherent vulnerability of the SDK's agent construction features to indirect prompt injection.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    6/9 files flagged

  • ZeroLeaks5mo

    3 findings · Score: 69/100

Signed by skilld at fbe0aa4. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last week.

Activeupdated 3 months ago
What it can do
Runs commands
All 5 allowed tools
Bash(npm *)Bash(npx *)Bash(node *)Bash(pnpm *)Bash(yarn *)

README badge

README badge for inference-shell/skills/javascript-sdk

Provides a JavaScript/TypeScript SDK for building AI applications on inference.sh, supporting 250+ models, streaming, file uploads, and multi-turn agents with tool integration. Use for Node.js backends, React/Next.js frontends, or ad-hoc agent creation with Claude, GPT-4o, or custom core models via the @inferencesh/sdk npm package.

Generated from the current SKILL.md.

Does this SDK support TypeScript?
Yes. The SDK includes full TypeScript type definitions and works with Node.js 18.0.0+. It also supports CommonJS and ESM.
Can I use this in a browser or frontend app?
Yes. For frontend apps, you proxy API calls through your backend (Next.js, Express, Hono, Remix, or SvelteKit) to keep your API key secure.
What models are available for agents?
The SDK supports Claude Sonnet 4, Claude 3.5 Haiku, GPT-4o, and GPT-4o Mini as core agent models, plus 250+ other AI apps accessible through the platform.
Does this support file uploads?
Yes. The SDK handles automatic file uploads for inputs and manual uploads via uploadFile(). It works with Node.js file paths and browser File objects.
Can I build multi-turn conversations?
Yes. The agent SDK supports multi-turn chat with sendMessage(), conversation reset, and chat history retrieval. You can also use sessions to keep workers warm across multiple calls.

Generated from the current SKILL.md. These answers refresh after source changes.