一个文件,无依赖。可在 Node 18+ 和现代浏览器中运行(内置 fetch、FormData、Web Crypto)。版本 1.7.2(文件中的 SDK_VERSION 常量)。客户端为每个 API 操作提供一个方法。
安装
下载 grem.ts 并放入您的项目。没有 npm 包。
快速开始
import { GremClient } from './grem';
const grem = new GremClient({ apiKey: process.env.GREM_API_KEY });
const { estimate } = await grem.valuation.express({
propertyCategory: 'apartment',
addressText: 'Torstraße 12, Berlin',
totalArea: 64,
});
console.log(estimate.pricePoint, estimate.currency);
默认基础地址为 https://developers.grem.capital/api/v1(选项 baseUrl)。在后台创建密钥:API → 密钥。
任务
每个任务响应都包含 jobId(API 1.6.0+)。jobs.wait 会轮询状态(免费),直到 state 为 completed、partial、failed 或 action_required。轮询失败(网络、5xx、429)不会使其停止:会继续轮询,最多允许连续 5 次失败:
const job = await grem.text.generate({ city: 'Berlin', totalArea: 64, language: 'zh' });
const done = await grem.jobs.wait('text/generate', job.jobId);
if (done.state === 'failed') throw new Error('generation failed');
报告审核需要等待确认:
const form = new FormData();
form.append('file', pdfBlob, 'report.pdf');
const review = await grem.valuation.review(form);
await grem.valuation.confirmReview(review.jobId);
const result = await grem.jobs.wait('valuation/review', review.jobId);
客户端包含的内容
| 分组 | 方法 |
|---|---|
| 密钥 | ping()、me() |
| 估价 | valuation.express、valuation.report、valuation.rent、valuation.review、valuation.confirmReview |
| 内容 | content.generate、text.generate、video.create、video.music、video.endings、avatar.video、avatar.list |
| 物料 | site.create、pdf.create、flyer.create、draft.extract、photo.enhance、floorplan.create |
| 参考数据 | voices()、toolsStatus()、works()、dictionaries() |
| 任务和文件 | jobs.get、jobs.wait、artifact(path, { range, signal })、uploads.images |
| 房源 | objects.list、get、create、update、delete、setAgency、setAssignee |
| 线索 | leads.list、get、create、update、delete、matches、claim、returnToPool |
| Swipe Match | match.list、get、events、sendEvent |
| Webhooks | webhooks.list、create、update、delete、test、deliveries、resend |
| 对话 | chat.createSession、listSessions、updateSession、deleteSession、sendMessage、history、stream |
带文件的工具接受 FormData:如何填写见各工具页面。
沙盒
使用测试密钥时,simulate 选项决定每次模拟调用的结果(沙盒):
const grem = new GremClient({ apiKey: process.env.GREM_TEST_KEY, simulate: 'failed' });
使用正式密钥时,simulate 选项会在创建客户端时抛出错误:否则调用会真实执行。
请求默认最多等待 5 分钟(timeoutMs):启动工具可能超过一分钟,提前放弃既不会停止工作,也不会停止计费。
客户端会在 Retry-After 之后重试被拒绝的调用,最多 maxRetries 次(默认 3,最大 10;0 关闭重试):429 总是重试,因为超出限制的调用未被处理;503 对读取重试,对写入仅在您传入 Idempotency-Key 时重试,因为 503 可能在副作用发生之后才返回。超过 30 秒的 Retry-After 不会等待:错误会立即抛出。您的 AbortSignal 也会取消等待。请把该 signal 传给 request()。没有 Retry-After 时,等待时间依次为 1、2、4 ... 秒。上传(uploads.images)在 503 后不重试(429 后会重试:上传未被处理)。传入的 signal 会取代请求超时(timeoutMs)。
错误
4xx 或 5xx 响应会抛出 GremError,包含 status、title、detail、code、errors、requestId 和 retryAfter(用于 429 和 503):
import { GremError } from './grem';
try {
await grem.text.generate({});
} catch (e) {
if (e instanceof GremError) console.error(e.status, e.title, e.code, e.detail);
}
安全重试
启动工具或创建记录的方法,最后一个参数是 Idempotency-Key:
await grem.pdf.create({ pdfName: '演示文稿', objectId, language: 'ZHO' }, crypto.randomUUID());
uploads.images 也接受键,但 API 会忽略它:重复上传会再次保存文件。
Webhooks
import { verifyWebhookSignature } from './grem';
app.post('/grem-hook', express.raw({ type: 'application/json' }), async (req, res) => {
const raw = req.body.toString('utf8');
const ok = await verifyWebhookSignature(process.env.GREM_WEBHOOK_SECRET, req.get('x-grem-signature'), raw);
if (!ok) return res.status(400).send('invalid signature');
const event = JSON.parse(raw);
res.sendStatus(200);
});
对话
const session = await grem.chat.createSession();
const stop = new AbortController();
const streaming = grem.chat
.stream(session.sessionId, (data) => console.log(data), stop.signal)
.catch((e) => { if (e.name !== 'AbortError') throw e; }); // stop.abort() rejects with AbortError
await grem.chat.sendMessage(session.sessionId, '你好!');
stop.abort(); // when you no longer need the stream
await streaming;
不传第三个参数时,sendMessage 会发送随机的 clientMessageId(Node 18 也可用)。要安全地重试消息,请传入并沿用您自己的 ID:同一个 ID 只回答一次、只扣费一次。