Skip to content

Vifu SDK

@vifu/sdk is the browser API that lets a game use Vifu platform capabilities without handling backend URLs, provider keys, or host messaging directly.

Use The SDK For

  • AI text generation and tool-style game actions
  • player-owned save and restore
  • declared data, media, and bundled files
  • external links opened through the host
  • game-owned tools that model calls or runtime agents may request
  • Runtime Agents for NPCs, tutors, companions, and other independent entities
  • dictionary, speech, review, camera, and other declared platform capabilities

Do not call OpenAI, Anthropic, OpenRouter, Vifu platform API, LM Studio, Ollama, or other backend endpoints directly from deployed game JavaScript.

Install

npm

Use npm when your game has a bundler or build step:

bash
npm install @vifu/sdk@alpha
ts
import { createVifuSDK } from "@vifu/sdk";

const vifu = createVifuSDK();
await vifu.ready();

CDN

Load the browser build from jsDelivr. Deployed games should use an exact SDK version:

html
<script src="https://cdn.jsdelivr.net/npm/@vifu/[email protected]/dist/browser/vifu-sdk.js"></script>
<script>
  const vifu = window.vifu;
</script>

AI

Use vifu.ai.generateText(...) for the common case: one game asks Vifu AI for text, classification, or a tool-backed action. The game does not choose the backend provider; the active Vifu session owns provider routing, credentials, quota, and the player's selected Mind.

ts
const result = await vifu.ai.generateText({
  model: "basic",
  messages: [
    { role: "user", content: "Give the player a short hint." }
  ]
});

showHint(result.content);

Model names are product-level aliases:

ModelUse it for
basicLow-cost NPC text, hints, summaries, and simple classification.
qualityHigher-quality story turns, planning, and reasoning.

Backend provider names are intentionally not part of the game contract.

Tool Calls

Pass tools directly to generateText when the visible game actions only matter for this turn:

ts
const result = await vifu.ai.generateText({
  model: "basic",
  messages: [{ role: "user", content: "The player says: open blue door." }],
  tools: {
    openDoor: {
      description: "Open a visible door by color.",
      parameters: {
        type: "object",
        properties: {
          color: { type: "string", enum: ["blue", "red", "green"] }
        },
        required: ["color"],
        additionalProperties: false
      },
      execute: ({ color }) => openDoor(String(color))
    }
  },
  maxSteps: 3
});

This is the best default for existing games such as AIventure. You do not need to create a Runtime Agent just to expose one turn's tools.

Runtime Agents

Use a Runtime Agent only when a specific entity needs isolated tools, instructions, and run history. Examples: two NPCs speaking at the same time, a tutor and a director sharing a scene, or a companion that must not see an NPC's private tools.

ts
const openDoorTool = vifu.tool({
  name: "open_door",
  description: "Open a visible door by color.",
  parameters: {
    type: "object",
    properties: {
      color: { type: "string", enum: ["blue", "red", "green"] }
    },
    required: ["color"],
    additionalProperties: false
  },
  execute: ({ color }) => openDoor(String(color))
});

const guard = vifu.agent({
  name: "Blue Door Guard",
  kind: "npc",
  instructions: "You guard the current puzzle room.",
  tools: [openDoorTool]
});

const result = await vifu.run(guard, "The player says: open blue door", {
  state: currentRoomSummary(),
  maxSteps: 3
});

name is only a readable label. Vifu assigns the internal runtime id automatically. Omit mind when the user or host should choose the active Mind; set mind only when the game intentionally binds this entity to a specific Vifu Mind.

NeedUse
Existing game with one active AI turnvifu.ai.generateText(...)
One turn with temporary game actionsvifu.ai.generateText({ tools })
Multiple independent NPCs, tutors, companions, or directorsvifu.agent(...) and vifu.run(...)

Game State

ts
vifu.gameState.configure({
  slotId: "autosave",
  source: "door-quest",
  serialize: ({ reason }) => ({
    schema: "door-quest.save.v1",
    reason,
    roomId: currentRoom.id,
    inventory: player.inventory
  }),
  restore: (stateBlob) => {
    restoreGame(stateBlob);
  }
});

await vifu.gameState.restore();
await vifu.gameState.save({ reason: "checkpoint" });

Resources

Declare resources in manifest.json:

json
{
  "name": "resource-demo",
  "data": {
    "world": { "src": "assets/world.json", "type": "json" }
  },
  "media": {
    "intro": { "src": "assets/intro.mp3", "type": "audio" }
  },
  "bundle": {
    "include": ["assets/**"]
  }
}

Read them through the SDK:

ts
const world = await vifu.resources.readJson("world");
const introUrl = vifu.resources.mediaUrl("intro");
const spriteUrl = vifu.resources.fileUrl("assets/player.png");

Game code should not construct /v1/assets/runtime-* URLs manually.

Status

ts
console.log(vifu.status());

Outside Vifu, managed platform capabilities may be unavailable. Your game should still boot and remain playable with local fallback behavior.