@flovialabs/sdk

中文文档
0.1.23发布于 2026/11/11MITTypeScriptES Module零依赖近 30 天下载 3191

TypeScript client and CLI for Flovia: MCP tools over HTTP and OpenAI-compatible generation. Zero dependencies.

原始使用文档
文档目录24 节
  1. Install
  2. 0.1.23 release notes
  3. 0.1.22 release notes
  4. 0.1.21 release notes
  5. 0.1.20 release notes
  6. 0.1.19 release notes
  7. 0.1.18 release notes
  8. 0.1.17 release notes
  9. Your key
  10. Quick start
  11. First data lookup
  12. Runway images and videos
  13. Run one result, display it, then reopen it
  14. Code runs and Team tasks
  15. Thinking effort
  16. Operation ids and replay
  17. Errors
  18. Notices and consent
  19. Retries
  20. Timeouts
  21. Contract version
  22. CLI
  23. Safety
  24. License

@flovialabs/sdk

TypeScript client and command-line tool for Flovia. It calls Flovia's tools over MCP (HTTP) and its OpenAI-compatible text generation.

Flovia is in alpha; APIs may change. Pin the version you use.

  • ESM with type declarations, no runtime dependencies (it uses fetch only).
  • Node.js 20 or later, or Bun.

Install

npm install --save-exact @flovialabs/[email protected]

0.1.23 release notes

flovia resets reads saved resets and free-window status concurrently and shows one waiting indicator. Both reads start even if one fails; if both fail, the first rejection determines the error. TTY waiting feedback updates one stderr line and clears it when the request finishes. Successful output and JSON keep their existing shape; piped stderr and --json have no waiting feedback. This release expects the same contract 2026-10-07.208 and changes no public client methods, types or runtime dependencies.

0.1.22 release notes

This release expects contract 2026-10-07.208 and includes team_feature_off in the typed public refusal codes. It adds no client methods or runtime dependencies. Per-Team sandbox opt-in remains deployment-gated. Installing the SDK does not enable that gate or change a Team owner’s setting.

0.1.21 release notes

This release expects contract 2026-10-07.207. It adds typed methods and CLI commands for code runs, saved results, schedules and Team workspace reads. Code runs and Team tasks remain subject to the relay's availability and consent checks; installing the SDK does not enable them. Save the original operation ID and request before sending. A lost reply or executed: "unknown" is not proof that nothing ran, so never create a replacement operation to recover it.

0.1.20 release notes

This release expects contract 2026-10-07.198. It adds client.spendMode() / flovia spend-mode for free-only mode and client.keyCaps() / client.setKeyCaps() / flovia key-caps for per-key daily and monthly spending caps. Relay replies since .182 add the flovia_quote tool, Gemini status / incomplete_details, whole-entry QuickNode log results, generation rows in usage breakdowns, Firecrawl and context.dev reads without an operation_id, and the elevenlabs_terms_required refusal. The CLI now refuses malformed operation ids, a missing option value, and a base URL with a query or fragment before sending anything. Provider availability follows the Relay's current configuration.

0.1.19 release notes

This release expects contract 2026-10-07.182, whose Relay replies include context.dev input-refusal details, MiniMax lookup IDs and conflict-recovery guidance, Nansen chain-retirement notices, and fal job counts with settled purchased-balance spend. The SDK also refuses timeout values that would overflow Node's timer before sending a request. Provider availability follows the Relay's current configuration.

0.1.18 release notes

This release expects contract 2026-10-07.178. It adds flovia install --client and the read-only flovia doctor command, lists up to 30 days of your usage history, and exports optional ForUser / ReplyCharge types for replies that include charge information. A missing charge is not zero. Replay and job snapshots must not be added as new calls. Earlier releases remain unchanged.

0.1.17 release notes

This release introduces client.consent(), client.acceptConsent(version) and the flovia consent commands, which are not in the published 0.1.16 package. It expects contract 2026-10-07.172. When the current notice is relay-consent-19, the CLI shows its December 3/new-record rule. Your earlier yes keeps working, and the CLI never answers for you.

Eligible Nansen answers and generated text/audio can be reopened only by their owner for up to 30 days under notice 18, from the original record's creation. Retrieval availability follows the Relay rollout and the notice on each original record. Earlier records keep their original periods. Other lookup replies and fal.ai URL copies get this period only for new notice 19 records, from 2026-12-03 or after your fresh explicit yes to notice 19. Old notice 18 and earlier lookup copies keep about 15 minutes; later agreement never extends them. Reopening does not renew the deadline, fetch fresh data or restore a missing copy. A fal.ai image URL still expires after about an hour; a saved URL does not extend the image's lifetime.

Your key

  1. Register at https://console.flovia.dev/auth/register with email verification and a Passkey.
  2. In Flovia Console, press Create API key. Give it an app name such as CLI or Cursor. Console shows it once; save it somewhere private.
  3. Set the key (flv_...) in the environment, then check it:
export FLOVIA_KEY=flv_...
npx flovia status

Without FLOVIA_KEY or --key-file, the CLI reads ~/.config/flovia/key, the file Console's Claude Code setup saves.

Claude Code pluginの既定の保存先は別ファイル ~/.config/flovia/relay-key です。CLIとpluginには別々のキーを使えます。キーを交換したときは、そのキーを使っていた保存先だけを更新してください。pluginのキーを交換した場合は、Claude Codeで /flovia:setup を再実行してください(保存先の基点 28e5cbeee1d7bca5c68c18d765e576445e452997、2026-10-25確認)。

status shows how much of your free allowance you have used, and your purchased balance. A $0 purchased balance is fine while free allowance remains.

Keys from the test period no longer work. The Quickstart has the full steps, and Free and paid use explains the limits. You can keep up to five active API keys on one account; all share its allowance, balance and limits. If a key is lost or exposed, select Revoke for that key on the API Key tab in Flovia Console, then Create API key and update the apps that used it. Other keys and OAuth connections keep working. See Manage API keys. Installing this package does not create an account or start a free allowance.

In code, the client reads FLOVIA_KEY, or you can pass it as new FloviaClient({ apiKey }). The client keeps the key private: it does not appear in logs, error messages or console.log(client). The SDK sends no telemetry.

baseUrl requires HTTPS. Plain HTTP is allowed only for loopback development (localhost, 127.0.0.1, [::1]). Raw transport diagnostics are not attached to errors because they may contain request headers.

Quick start

import { FloviaClient, newOperationId } from "@flovialabs/sdk";

const flovia = new FloviaClient(); // reads FLOVIA_KEY; base URL https://api.flovia.dev

// Your free allowance windows, services and the contract version
const status = await flovia.status();
console.log(status.five_hour.used_pct, status.week.used_pct);

// Your lookups today (or the last N days, up to 30)
const usage = await flovia.usageToday(); // today, UTC

// Any tool: list them, then call one
const tools = await flovia.listTools();
const reply = await flovia.call("flovia_status");

// A text generation (uses your free allowance first, then your purchased balance). Save the operation id before sending.
const op = newOperationId();
const request = { model: "gpt-6-luna" as const, input: "Explain a DEX aggregator in one sentence.", reasoning: { effort: "low" as const } };
// Persist { op, request } in your application's private storage before the next line.
const g = await flovia.generate(request, { operationId: op });
console.log(g.response.status, g.response.incomplete_details, g.outputText);

First data lookup

listTools() returns the tools offered to your account and their inputSchema. A catalog call sends nothing to the data provider. For example, list CoinGecko paths, then make one price lookup:

await flovia.call("flovia_coingecko", {
  path: "list", request_text: "Which prices can I read?", purpose: "choose a supported path",
});
const priceRequest = {
  path: "/simple/price", query: { ids: "bitcoin", vs_currencies: "usd", include_last_updated_at: true },
  request_text: "What is Bitcoin's USD price?", purpose: "check a price with its update time",
  conversation_id: "sdk-price-example", operation_id: newOperationId(),
};
// Save priceRequest before sending; this lookup uses your free allowance or purchased balance.
const price = await flovia.call("flovia_coingecko", priceRequest);

If either call asks for a notice or consent, stop and follow the human-answer flow below. Read the returned source time, coverage and missing-value notes; a successful lookup is not a guarantee that it answers your question. Flovia exposes selected read-only paths, methods and public HTML hosts, not every feature of the upstream plans. Use the live catalog for the supported subset. OpenAI supports text generation with gpt-6-luna; it does not fetch other providers or offer image/audio generation.

Runway images and videos

When listTools() offers flovia_runway, use the same call() method and your Flovia key. Runway needs the person's separate consent: show the returned notice and ask only when next_step requests it. Never supply a yes for the person. Runway may train on inputs and outputs; do not send private information or credentials.

const catalog = await flovia.call("flovia_runway", { action: "list" });
// After the person's actual consent has been recorded, save this request before sending.
const imageRequest = {
  action: "image", prompt: "A blue paper circle on a white background",
  operation_id: newOperationId(),
};
const accepted = await flovia.call("flovia_runway", imageRequest);
// Accepted is not completed. Later, explicitly read the same job's status:
const result = await flovia.call("flovia_runway", {
  action: "status", operation_id: imageRequest.operation_id,
});
// Only when output.state is ready, using the generation_id returned by Flovia:
const output = await flovia.downloadRunwayOutput(String(result["generation_id"]));
// output.data is Uint8Array; output.contentType is the checked media type.

Images are one 720p gen4_image result. Videos use action: "video" with duration: 2 through 5, and return MP4. Runway jobs never resend automatically, even with retryRateLimited: true. Keep the original operation ID after a disconnect or unknown result; never generate a replacement to recover it. A failed/moderated generation may still be charged. Status distinguishes the billing state from output delivery.

Flovia keeps output privately for up to 30 days from generation creation under notice 18 (earlier records keep 24 hours), with authenticated downloads; Runway's own retention is separate. The SDK download is a bounded (32 MiB), one-request GET to Flovia, never a provider URL. A download does not generate or charge again. OAuth-only MCP users can use the returned console_download_url while signed in to their own Console.

flovia call flovia_runway '{"action":"list"}'
# Create through call only after actual consent; save your JSON request first.
flovia call flovia_runway - < image-request.json
flovia call flovia_runway '{"action":"status","operation_id":"<saved-operation-id>"}'
flovia runway-output <generation_id> --out image.png

runway-output creates a new file with mode 0600; it never overwrites. A failed write may leave a private partial file, so inspect it before choosing another output path. Show Powered by Runway with a link to Runway when displaying generated media; SDK consumers must carry that attribution into their own interface.

Run one result, display it, then reopen it

Save this complete example as first-price.mjs beside your node_modules. Keep it server-side or on your own machine.

// Run on your own machine. Never bundle this file, FLOVIA_KEY or private usage into a browser app.
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { pathToFileURL } from "node:url";
import { FloviaClient, FloviaError, newOperationId } from "@flovialabs/sdk";

const mode = process.argv[2];
if (!["--new", "--replay", "--saved"].includes(mode)) {
  console.error("Use --new once, --replay with the saved request, or --saved (no network).");
  process.exit(1);
}
const directory = new URL("./.flovia-price/", pathToFileURL(process.cwd() + "/"));
const requestFile = new URL("request.json", directory);
const answerFile = new URL("answer.json", directory);

try {
  let reply;
  if (mode === "--saved") {
    reply = JSON.parse(await readFile(answerFile, "utf8"));
  } else {
    const client = new FloviaClient();
    if (mode === "--new") {
      await mkdir(directory, { mode: 0o700 });
      const request = {
        path: "/simple/price",
        query: { ids: "bitcoin", vs_currencies: "usd", include_last_updated_at: true },
        request_text: "What is Bitcoin's USD price?",
        purpose: "display one price with its source update time",
        conversation_id: "sdk-first-price",
        operation_id: newOperationId(),
      };
      // Exclusive creation: rerunning --new cannot silently replace the operation that might have run.
      await writeFile(requestFile, JSON.stringify(request), { mode: 0o600, flag: "wx" });
      await client.status(); // Account/allowance read only; stop on authentication errors.
    }
    const request = JSON.parse(await readFile(requestFile, "utf8"));
    reply = await client.call("flovia_coingecko", request);
    await writeFile(answerFile, JSON.stringify(reply), { mode: 0o600 });
  }
  const price = JSON.parse(reply.response).bitcoin;
  const updated = price?.last_updated_at;
  console.log(JSON.stringify({
    display: mode === "--saved" ? "Saved locally; not a live update" : reply.stored_answer ? "Earlier answer; not a live update" : "Fetched once; not auto-updating",
    btc_usd: price?.usd ?? null,
    provider_updated_at: Number.isFinite(updated) ? new Date(updated * 1000).toISOString() : null,
    flovia_received_at: reply.created_at ?? null,
    lookup_id: reply.lookup_id ?? null,
    charge_guidance: mode === "--saved" ? "Nothing: this display is offline; see the original lookup in private usage"
      : reply.for_user?.charged_to_you ?? "Unavailable; do not assume zero",
    attribution: "Data provided by CoinGecko",
  }, null, 2));
} catch (error) {
  if (error instanceof FloviaError) {
    console.error(JSON.stringify({ code: error.code, executed: error.executed, operation_id: error.operationId, next_step: error.nextStep }));
  } else {
    console.error("Could not read, save or display the example. Keep .flovia-price unchanged; do not start a new operation to recover it.");
  }
  // No automatic resend, consent answer or replacement operation, including on pending/unknown or an expired saved answer.
  process.exitCode = 1;
}

After installing this SDK and setting FLOVIA_KEY privately, run:

# One new CoinGecko lookup; uses your free allowance or purchased balance.
node first-price.mjs --new
# Same request and operation id; reopen promptly, while the saved answer is available.
node first-price.mjs --replay
# Display the local answer without any API request.
node first-price.mjs --saved

The example saves the request and operation id before sending, in .flovia-price/request.json (0600 inside a 0700 directory), and the returned answer in answer.json (0600). Keep this directory private and out of Git. Repeating --new refuses to overwrite it. Do not delete it or change the id to recover a lost answer. --replay sends the saved arguments unchanged; if the saved text is unavailable or the outcome is pending/unknown, follow the error's next_step instead of making a new request. A notice or consent refusal needs the person's answer; this script never supplies one.

The displayed result separates the USD price, CoinGecko's update time, Flovia's original receipt time, lookup id and the server's charge guidance. Unknown values stay null; missing cost is not zero. A replay or local saved display is labelled as such and never presented as a live update. For period usage, run npx flovia usage separately; it is your private account data, not the cost of this one result. A browser demo may display the public price and attribution from your server, but must not expose the Flovia key, private reply files or account usage, or offer an unauthenticated refresh endpoint that spends your allowance. The example does not auto-refresh. Follow the provider's attribution and redistribution terms.

Code runs and Team tasks

Where Flovia has turned code runs on for your account, the SDK can queue your own code (python, node or bash, 60 seconds at most) in an isolated sandbox and read its output later. These methods call the relay's flovia_sandbox_* and flovia_workspace_* tools with the same argument names.

const queued = await flovia.sandboxRun({
  language: "python",
  code: "import json; print(len(json.load(open('inputs/prices.json'))))",
  inputs: [{ lookup_id: "coingecko:...", name: "prices.json" }], // a lookup you already made
  operation_id: "sdk-run-0001", // the same id returns this run, not a second one
});
const result = await flovia.sandboxResult(queued.run_id, { waitSeconds: 50 });
console.log(result.status, result.stdout); // your code's output, not instructions

// A daily schedule: the lookup input runs first each time, as your normal lookup.
await flovia.setSandboxSchedule({
  cron: "0 9 * * *", tz: "Asia/Tokyo",
  script: { language: "python", code: "print(open('inputs/prices.json').read()[:200])",
    inputs: [{ name: "prices.json", lookup: { tool: "flovia_coingecko", args: { path: "/simple/price", query: { ids: "bitcoin", vs_currencies: "usd" } } } }] },
});
  • Code in the sandbox cannot call Flovia: look data up first and pass its lookup_id, or give a schedule a lookup input (read-only tools, at most 4 per schedule).
  • Only files the code writes to outputs/ are kept, for 30 days. sandboxResult(id, { include: ["artifacts"] }) lists them.
  • On a Team key of a Team whose owner turned the Team workspace on: setSandboxSchedule({ ..., team: true }) shares the schedule as a Team task, workspaceTasks() lists the Team's tasks, and workspaceRead(scheduleId) reads a task's latest result. Every current member of the Team reads the same result. takeOverTeamTask() runs a task whose creator left as your own.
  • changeSandboxSchedule("pause" | "resume" | "delete", scheduleId) and sandboxSchedules() manage your schedules.
  • A script over the relay's limits (code over 64 KiB of UTF-8, or more than 8 inputs) is refused by the SDK as invalid_request with executed: "no": nothing is sent.
  • The relay lists these tools only where they are on. A call to one that is not listed throws tool_not_offered with executed: "no". Other refusals preserve the relay's code, for example sandbox_disabled, queue_full or consent_missing, and its executed value. Treat a request as unexecuted only when executed is "no". On "unknown", keep the original operation ID and request and follow nextStep; do not create a replacement operation.

Thinking effort

For Luna, set reasoning.effort to none, low, medium, high, xhigh or max; omitting it keeps Flovia's none default. Higher effort can take longer and use more reasoning tokens. Those tokens share max_output_tokens with the visible answer, so an answer may be shorter or incomplete. The default output limit remains 1,000, with an explicit maximum of 4,000. Effort does not raise Flovia's per-request spending cap or guarantee a better answer. Save the effort with the rest of the request; changing it under the same operation id is a different request and is refused.

Operation ids and replay

generate() requires an operation id (8-128 characters of A-Z a-z 0-9 _ . : -). Create one with newOperationId() and store it with the request before sending.

If the reply is lost (timeout, network error, executed: "unknown"), keep the request and same id. A completed or incomplete saved answer can be reopened with the unchanged request, replayed: true and no additional charge. For generations made under data-use notice 18 (including matching registration Terms), the period is up to 30 days from creation. This covers accepted use from 2026-12-01T00:00Z, or work after your earlier explicit agreement to notice 18. Earlier generations keep about 15 minutes; later agreement does not extend them. A failed save or missing copy can prevent reopening even before expiry. Follow nextStep for generation_pending or generation_unknown; the answer may not be available yet. After answer_expired or operation_retired, Flovia cannot return the saved text. Expired or deleted copies are not restored. Never start a new id to recover a lost answer: that may run and charge twice. A new generation requires the person's decision to spend again. Data use explains the retrieval periods and their limits.

Errors

A refusal (ok: false) or a failed request throws FloviaError:

fieldmeaning
codea public code such as rate_limited or window_5h (PUBLIC_CODES lists them), or http_<status>
messagewhat happened
nextStepwhat to do next
executed"yes", "no" or "unknown": whether the request ran. On "unknown", keep the same operation id
retryAfterSecondshow long to wait, when given
statusthe HTTP status, when there is one
operationIdthe operation id of the request
replythe full reply body

HTTP 401 with code: "formal_registration_required" means test access ended: register at https://console.flovia.dev/auth/register with email verification and a Passkey (or use the link in your invitation email if you have one); if you have already registered, sign in to Console, press Create API key, then reconnect with the new key. A generic unauthorized means the key was not accepted; check your account and current key in Console. Both are unsent (executed: "no") and are never retried automatically. The SDK does not expose arbitrary authentication response bodies.

These two codes stop the call on purpose. Show the notice in full and follow nextStep; a separate explicit opt-in may be required. The SDK never consents for the person.

  1. Show the full error.reply.user_notice unchanged (error.reply.notice for case reports), and error.reply.consent.question when present. For data_consent_needed, use consent.line when there is no question; the short question does not replace the notice.
  2. For data_consent_needed, get the person's own answer through your normal flow. Follow nextStep for the consent tool: lookup consent uses flovia_data_consent; Runway uses flovia_runway with action: "consent". Pass answer ("y" or "n" from that answer), consent_version from error.reply.consent.version, and user_words containing their actual words. Do not substitute the current SDK version or a generated answer. Case-report notice_first uses its own explicit opt-in and returned consent_version, not flovia_data_consent.
  3. For data_consent_needed, repeat the unchanged call only after their y is accepted; with n, stop. For notice_first, show the notice and follow nextStep; add notice_shown: true only when requested. Never opt in to a report automatically.

Do not answer these automatically from code or from an agent.

Retries

  • client.generate() (the HTTP generation route) is never resent automatically.
  • With new FloviaClient({ retryRateLimited: true }), a tool call refused with rate_limited, too_many_in_parallel or reservation_changed and executed: "no" is resent once, unchanged (same operation_id), after retry_after_seconds (at least 1 s, at most 60 s). Off by default. This covers generation tools called through client.call() (flovia_openai, flovia_minimax, flovia_fal) too: such a refusal means nothing ran and nothing was charged. flovia_runway is never resent.
  • Anything with executed: "unknown" is not resent.

Timeouts

Each request times out after 300 seconds by default (a long generation can take minutes). Change it with timeoutMs (more than 0, at most 2147483647 ms; --timeout at most 2147483 seconds). A timeout throws FloviaError with code timeout and executed: "unknown".

A lost or unreadable reply is also executed: "unknown", even after HTTP 200. Keep the saved operation ID and request; do not start another operation to recover the answer. A retired operation is never treated as proof that nothing ran.

Contract version

status() compares the server's contract_version with the one this SDK was written for (EXPECTED_CONTRACT_VERSION) and warns once with console.warn when they differ. Replace the warning with onContractMismatch.

CLI

The package installs a flovia command.

export FLOVIA_KEY=flv_...              # or: --key-file ~/.config/flovia/key
npx flovia status
npx flovia usage --days 30
npx flovia tools
npx flovia tools --json              # includes each tool's inputSchema
npx flovia tools flovia_coingecko --json # only this tool's description and inputSchema
npx flovia call flovia_usage_today '{}'
npx flovia generate --op sdk-example-0001 --max-output 1000 --reasoning-effort low "Explain a DEX aggregator."
# Only to reopen that exact request while its saved answer is available:
npx flovia generate --op sdk-example-0001 --max-output 1000 --reasoning-effort low --yes "Explain a DEX aggregator."
npx flovia resets                    # saved resets and both free windows (read-only)
npx flovia resets use 42 --yes       # use saved reset 42 (cannot be undone)
npx flovia consent                   # current notice version, your yes and the notice text (read-only)
npx flovia consent accept relay-consent-19 --yes   # your own yes to the version just shown (same as Console)
npx flovia key-caps                  # each key's daily and monthly spending cap and use (read-only)
npx flovia key-caps set <key-id> --day 5 --month none   # cap one key; a call over it is refused, nothing charged
npx flovia spend-mode                # free-only or allow-paid (read-only)
npx flovia spend-mode free-only      # never use the purchased balance or plan credit
npx flovia sandbox run python job.py   # queue your own code; prints an operation_id first, then the run_id
npx flovia sandbox run python job.py --op sdk-run-0001   # the same request again (a lost reply): returns that run, queues nothing new
npx flovia sandbox result <run-id> --wait   # the run's status and output (your code's output)
npx flovia sandbox schedules         # your schedules (read-only)
npx flovia workspace                 # a Team key's shared tasks (read-only)
npx flovia workspace read <schedule-id>   # a Team task's latest result (read-only)
npx flovia agents-md                 # a short note for CLAUDE.md or AGENTS.md
npx flovia help
npx flovia --version

These commands run after installing @flovialabs/sdk in the current project. Without a local installation, specify the package: npx --package=@flovialabs/[email protected] flovia --help. Use a unique operation id for each new request; sdk-example-0001 is only an example. Save the id, prompt and options before sending, and keep them unchanged for replay.

Get or manage your key in Console, save it privately, then run flovia status --key-file <saved-key-file>. A connected key can still have sharing declined, withdrawn or stopped; status shows those separately from provider availability. It never answers consent for you.

For a data lookup, save its JSON object (including your chosen operation_id) in a private request.json before sending. Keep it out of Git and read it from stdin rather than quoting it in a shell argument:

flovia call flovia_coingecko - < request.json

This sends the saved request once. Reopening it uses the same file and operation ID; never create a new ID to recover a lost answer. The CLI does not invent or save an ID for call. Inspect the live inputSchema first, and follow any returned consent or recovery instructions. tools <tool> --json returns one tool object; tools --json keeps returning the full array. Neither executes a data lookup. Without --json, tools <tool> ends with an example call line built from the schema's required arguments (placeholders to replace). Exa and Firecrawl examples also include their default action's inputs and an operation_id placeholder when those fields are offered. An unknown tool name gets the closest offered name.

With --json, an error is also one JSON object on stdout: ok: false, code, meaning, and when present next_step, executed, retry_after_seconds and operation_id, next to the reply's own fields. Exit codes stay 0, 1 and 2.

To connect one AI client to Flovia's MCP server in one command (since 0.1.18; not included in 0.1.17):

npx flovia install --client claude-code           # or codex, cursor, claude-desktop, hermes
npx flovia install --client cursor --auth key --dry-run

The default --auth oauth adds the server and lets the client sign in; no key is used. --auth key points Claude Code at the key file (--key-file, default ~/.config/flovia/key) and Codex and Cursor at FLOVIA_KEY and FLOVIA_API_KEY; the key is never written into the client's settings, a command argument or the output. Claude Code and Codex are changed through their own claude mcp add and codex mcp add. Cursor's ~/.cursor/mcp.json keeps its other entries. Hermes Agent gets a new ~/.hermes/config.yaml only when it is missing or empty; an identical generated entry is left unchanged. Other existing Hermes settings are left untouched: merge Flovia by hand using Console's Quick Install. Claude desktop gets the custom-connector link. --dry-run shows the commands and files without changing anything.

Hermes Agent uses its Client ID Metadata Document by default. If sign-in reports invalid_client or times out, follow the manual DCR fallback in the Hermes guide. The installer keeps existing Hermes settings unchanged.

To check what install set up (since 0.1.18; not included in 0.1.17):

npx flovia doctor                                  # every client
npx flovia doctor --client codex --network

doctor only reads each client's personal settings (~/.claude.json, ~/.codex/config.toml, ~/.cursor/mcp.json, ~/.hermes/config.yaml). It reports whether the flovia entry points at https://api.flovia.dev/mcp, whether it signs in or uses a key, and whether that key file is readable or that environment variable is set. It never writes, never runs the client or a helper, and never prints a key, a header value or a URL's query. A sign-in entry gets the client's command to sign in again: after a revoked or expired sign-in, clients keep retrying until a person signs in anew. Claude desktop is checked in Claude's Settings > Connectors. --network also asks Flovia: /mcp must answer with its sign-in challenge, and a Flovia-format key the recognised entry uses must be accepted by flovia_status. Fetching and reading the reply share the --timeout deadline, which defaults to 300 seconds. Without --client, clients that are not set up are listed but do not fail; the exit code is 1 when a check fails.

For Claude Code, doctor checks the key file only when headersHelper exactly matches the helper install generates for the default path or the supplied --key-file path. Other helpers and unsafe or credential-like environment-variable names produce an authentication warning and require manual inspection; doctor neither reads another key nor sends a request for that entry. URL warnings show the expected endpoint without echoing the configured URL's host or path. It does not parse full TOML or YAML: inline tables and flow mappings may be reported as an absent entry and need manual inspection.

For an AI agent, flovia agents-md prints a short note to paste into CLAUDE.md or AGENTS.md. It contains no key and makes no request.

For multiline generation text, keep the original input in a private file:

flovia generate --new-op --max-output 1000 --reasoning-effort high --yes - < prompt.txt
# To recover this request, use its printed id, the SAME file and options:
flovia generate --op <saved-id> --max-output 1000 --reasoning-effort high --yes - < prompt.txt

Keep the same --key-file and --base-url too. For a prompt starting with a hyphen, use -- before the prompt. Long answers can take minutes; an interactive terminal shows elapsed time on stderr. Piped and JSON output stays unchanged. A timeout does not prove that nothing ran: never recover by repeating --new-op. Partial answers are delivered and settled, but the CLI never generates a continuation automatically. The HTTP reply does not include exact Flovia cost; use flovia usage for period totals, which are not the price of this one answer. A replay adds no charge.

status shows your purchased balance. usage shows lookup counts, free allowance percentages and the purchased-balance totals from the server; its generation subtotal is already included in the period total. Missing amounts show -, not zero. It does not add rounded endpoint percentages. To continue a listing, copy the printed command with its exact --since and --cursor; do not combine --days with --cursor.

  • Every command takes --json (the raw reply), --base-url URL, --timeout SECONDS and --key-file PATH.
  • generate uses your free allowance first, then your purchased balance. It needs --op ID or --new-op, and asks for confirmation on a terminal; add --yes in scripts.
  • generate prints the response status and incomplete reason. incomplete / max_output_tokens means the delivered text stopped at the output limit, not that a continuation ran. Exit 0 means the response was delivered, not that the text is complete or correct. --json retains the full public response.
  • resets only reads: the number of saved resets, the next to expire, and the 5-hour and weekly windows. resets use <id> --yes uses one; both free windows (5-hour and week) start again from 0%. Without --yes nothing is sent, even on a terminal. It is never resent automatically: after a lost reply, run flovia resets before trying again. Not used; nothing changed. exits 1. In code: client.bankedResets() and client.useBankedReset(id).
  • consent only reads: the current notice version, the version you last said yes to, whether that yes is to an earlier version (it keeps working; continued use accepts the current one), and the full notice. consent accept <version> --yes records your own yes to exactly that version, the same as answering in Console; an older version is refused and nothing is recorded, and a repeat changes nothing. Without --yes it shows the text and sends nothing (exit 2). Only the account owner should run it, never an agent on their behalf. In code: client.consent() and client.acceptConsent(version).
  • Exit codes: 0 ok, 1 an error from Flovia, 2 a usage error.

Safety

  • The key is read only from FLOVIA_KEY or a key file, never from a command-line argument (other users can see arguments in ps). It is never printed.
  • A key file readable by other users gets a warning; use chmod 600.
  • --base-url must be https, so the key is never sent unencrypted. Plain http is allowed only for localhost, 127.0.0.1 and [::1].
  • The CLI shows the full notice, next_step and any returned consent.question, then stops. On data_consent_needed, consent.line (as Runway returns) supplies the question when consent.question is absent. Questions appear under Your choice:. Notice text, links and questions stay unchanged; only headings and help text are shortened. The person answers themselves; --yes confirms spending, not data consent or report opt-in.

License

MIT

版本与发布记录

@flovialabs/sdk 共发布 25 个版本,首次发布于 2026/10/13;过去 12 个月发布了 25 个版本。

版本发布日期距今
0.1.23latest2026/11/114 天前
0.1.222026/11/114 天前
0.1.212026/11/114 天前
0.1.202026/11/069 天前
0.1.192026/11/0312 天前
0.1.182026/11/0313 天前

关于 @flovialabs/sdk 的常见问题

@flovialabs/sdk 是什么?

TypeScript client and CLI for Flovia: MCP tools over HTTP and OpenAI-compatible generation. Zero dependencies.

如何安装 @flovialabs/sdk?

在项目目录运行 npm install @flovialabs/sdk,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 flovia,可以用 npx flovia 直接运行。

@flovialabs/sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@flovialabs/sdk 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@flovialabs/sdk 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@flovialabs/sdk 可以商用吗?

@flovialabs/sdk 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@flovialabs/sdk 的下载量有多少?

根据 npm 官方下载统计,@flovialabs/sdk 在 2026/10/15 – 2026/11/13 这 30 天内被下载 3,191 次,日均约 106 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@flovialabs/sdk 还在维护吗?

最新版本 0.1.23 发布于 2026/11/11(4 天前);至今共发布 25 个版本,其中过去 12 个月发布了 25 个;首次发布于 2026/10/13。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。