@flop-labs/客户端
一个用于FLOP的公用网关,浏览器和节点.js 22或以后的小型ESM获取客户端. 它唯一的运行时间依赖是 @flop-labs/contracts。 。 。 .
pnpm add @flop-labs/client
import { FlopClient, FlopHTTPError } from "@flop-labs/client";
const client = new FlopClient({ apiKey: "your-flop-api-key" });
const models = await client.listModels();
const model = await client.getModel(models.data[0].id);
try {
const completion = await client.createChatCompletion({
model: model.data.id,
messages: [{ role: "user", content: "Hello" }],
stream: false,
}, { signal: AbortSignal.timeout(30_000) });
console.log(completion.choices);
} catch (error) {
if (error instanceof FlopHTTPError) {
console.log(error.status, error.retryAfter);
// error.body retains the gateway's structured error, or non-JSON text.
}
throw error;
}
默认 baseURL 实值 https://api.flop.network/v1公众别名 services/rest-gateway/README.md。只获得来源的 URL /v1 附录。 明确的 API 路径必须结束于 /v1 (包括 /api/v1);后行鞭打被去除. HTTP(S) URL 包含证书,查询或片段被拒绝. 重新定向从未被跟踪;浏览器可能暴露为状态为0的不透明HTTP错误.
模型发现不需要 API 密钥, 也不发送无记名证书 。 聊天完成和收件检查要求 apiKey 并只将其发送到已配置的网关。 在服务器上保留特权证书 . fetch 可以注射用于测试或兼容的运输. 每个方法都接受一个可选的呼叫器 signal请求使用 credentials: "omit" 财务报告和审定财务报表 redirect: "manual"。 。 。 .
请求在网络接入前经过验证;利用共享合同在结构上检查JSON成功的答复。 供应商扩展和接收字段不变地返回。 这些是 网关所报告数据:客户不核实收据,证明书,付款,连锁包容,或最终性.
客户端支持 listModels(), (中文(简体) ), getModel(id), (中文(简体) ), createChatCompletion(request) (杰森语), streamChatCompletion(request) (SSE),和 getCredentialReceipt(requestId)钱包业务、x402资金和赠款薄荷在外。 已付款的请求一经发出:没有自动复试,包括429次,取消或运输故障。 暂停不能确定网关没有起作用;在人工重复付费电话之前解决这一结果.
listModels 还接受 offset (非负整数), limit (1-1000) (中文(简体) ), output_modalities 财务报告和审定财务报表 supported_parameters (名称阵列),与 signal。这些序列化为公共模型种子的查询参数;模型细节 ID 被编码为一个路径段.
FlopHTTPError 保留 status, (中文(简体) ), body,原始的则 retryAfter 头曰. 它的信息不包括请求的证书和网关机构内容. FlopValidationError 报告配置、输入或成功反应不当. FlopTransportError 将潜在的运输故障保留为: cause;呼叫取消会宣传信号的理由. 避免登录错误机构或原因,而不应用您的应用程序的数据政策.
正在流出聊天完成
streamChatCompletion 返回一个同步生成器。 它第一次发送一个POST
激起 力量 stream: true并拒绝明白的、 stream: false。其产量
结构验证 ChatCompletionChunk 对象返回 a
ChatCompletionStreamResult 成功终止。 使用 next() 保留
终端返回值( o)for await 消耗块但丢弃返回值 :
const stream = client.streamChatCompletion({
model: "flop/model",
messages: [{ role: "user", content: "Hello" }],
}, { signal: AbortSignal.timeout(30_000) });
while (true) {
const next = await stream.next();
if (next.done) {
console.log(next.value.finishReason, next.value.usage, next.value.receipt);
console.log(next.value.toolCalls); // Complete calls assembled by index.
break;
}
console.log(next.value.choices[0]?.delta.content ?? "");
}
执行人执行角色/内容/工具/完成/使用/[DONE] 生命周期.
只有一个有效的成功
完成、使用/接收框架, [DONE],而被关闭的机体则产生终端结果.
提前执行关闭时不返回结果;关闭则取消身体
读者。 客户端通过 EOF 读取拒绝数据框架 [DONE]。 。 。 .
在溪流打开前, 未成功 HTTP 状态丢弃 FlopHTTPError,保留
尸体和 Retry-AfterHTTP 200 要求 text/event-stream; JSON 重放
对流出请求的回复被拒绝。 投出带内故障 FlopStreamError
与 body, (中文(简体) ), usageSource (单位:千美元)"estimated" (一) 供应时, retryAfter (秒),和
outputStreamed8. 收款使用情况和估计出错使用情况仍然不同.
框架或命令抛出错误 FlopValidationError缺少 [DONE] 或一个
运输失败抛出 FlopStreamInterruptionError与已知的事业.
以信号的确切原因中止拒绝并取消阅读器. 取消 停止阅读;它不会取消接受的工作或付款。 无出错或中断 触发重试。 和解和任何重播都是打电话者的决定.
呼叫者拥有的重放身份
两种付费方法都接受 { idempotencyKey } 并行 signal键作为
Idempotency-Key,必须包含1-128可打印的 ASCII 字符,没有白空格,
发现后就会被拒绝 客户端从不为您创建密钥或重试.
持久恢复用途 createChatCompletion 与 stream: false: 网关
存储完成的 JSON 响应用于重放,而不是重放的 SSE 正文.
追回含糊不清的请求
坚持请求 ID, 原始相关性 ID, 确切的请求正文和网关 URL
在第一个支付POST之前. Idempotency-Key 是请求的ID,除非呼叫者
用品 X-Request-ID,优先进行。 失去反应后,使用
getCredentialReceipt 在考虑重放前使用同一ID:
import { FlopClient, FlopHTTPError } from "@flop-labs/client";
// Loaded from the application's durable job record; no new ID is generated here.
async function observeLostResponse(client: FlopClient, originalRequestId: string) {
try {
const receipt = await client.getCredentialReceipt(originalRequestId, {
signal: AbortSignal.timeout(10_000),
});
if (receipt.state === "reserved" || receipt.state === "estimated") {
return { action: "wait-or-reconcile" as const, receipt };
}
return { action: "review-terminal-observation" as const, receipt };
} catch (error) {
if (error instanceof FlopHTTPError && error.status === 404) {
return { action: "investigate-missing-record" as const };
}
// 401: obtain authorized parent access; timeout/transport failure: outcome unknown.
throw error;
}
}
此示例不提交推论,也不记录证书、提示或产出. 既无缺行也无超时证明没有发生有偿工作。 他们必须 不启动自动替换的带薪工作。 如果操作员随后选择 JSON重放,使用原始证书,ID,相关ID,身体和路由; 3; 积极的父母可以检查孩子的分类账,但不能作为孩子重放.
检索用途 GET /keys/me/receipts/{request_id} 并读到一个准确的,对案件敏感的
ID独立于最新20榜单. 身份证跟随客户端的1-128可打印的 ASCII
符号规则; . 财务报告和审定财务报表 .. 路径段无效。 客户端 URL 编码 ID 和
将回复描述为 CredentialReceipt。错误的ID 本地失败
FlopValidationError (HTTP呼叫者收到400 invalid_request_id; 401 否认
失踪/无效/失效/撤销权力; 404 receipt_not_found 包括两个缺席
和范围外的记录 而不透露另一个证书的要求.
积极的家长会看到自己和所有孩子的要求。 一个孩子只看到自己的 即使其用途已用尽或 演示文稿窗口关闭。 查找既未显示新会话, 也未扩展会话 . 儿童期满或被吊销,拒绝与该儿童一起获得康复;使用其授权, 替换为活动父 。 父母期满或撤销均否认。 过期子女补助金 在未解决的请求完成后, 元数据会被刷新, 而保留分类账行 仍然可以被活动父母读取.
reserved 持有未设完成检查站的配额; estimated 保留
完成后保留,实际开支尚未解决. settled 核对记录
支出和 released 记录还原了保留配额。 释放行不
发明零结算证据. response_status 描述缓存的 HTTP 检查点
与定居无关。 重新找找就可以在原作开始的时候解决
缓存的 JSON 完成情况仍有待报告; 重放未改变的检查点返回 .
检查时不返回快取、输出或缓存的完成正文.
reserved_spend 财务报告和审定财务报表 settled_spend fLOP 配额值.
settled_spend_raw当可用时,是作为小数整数的精确分配
原始 FLOP 基单元中的字符串 : 10^18 生 = 1 FLOP。未知数量、频道标识符
而终极事件仍然是无效的. terminal_event 识别可用的终端
频道证据; 集合请求共享频道事件和分配, 不分开
要求矿工付款或烧掉交易。 这些观测数据是网关数据,
或承诺立即解决.
回收只覆盖已配置的网关所保留的 SQLite 分类账 。 没有 今天的自动分类账 TTL,但没有存档或跨出道保证:数据库 丢失、 操作员删除或切换网关可以使记录无法使用。 保护 根据您申请的留用政策,您拥有自己的工作身份和证据.
任务关联
网关组代理任务转弯 X-Correlation-ID调用 client.task() 一次
每个任务并通过返回的手柄进行付费呼叫:
相同的随机 id, 和下一个 task() 呼叫开始一个新的.
const task = client.task(); // or client.task("job-42") to supply your own id
await task.createChatCompletion({ model: "qwen/qwen3-8b", messages });
await task.createChatCompletion({ model: "qwen/qwen3-8b", messages: [...messages, reply, toolResult] });
两种方法都接受 { correlationId } 直接说 值跟随
一分之能 - 键符号规则 并在发现时被拒绝。 不重复使用一个标识
任务,因为网关将将它们合并为一个会话。 在一个
一能键必须发送其原始相关性 id.