@darklake.ai/fathom
v0.1.0
Published
TypeScript SDK for Fathom — typed client for the agent gateway over HTTP + SSE.
Downloads
94
Maintainers
Readme
@darklake.ai/fathom
TypeScript SDK for Fathom — a typed client for the agent gateway over HTTP + SSE. Works in Node 18+ and modern browsers.
Install
npm install @darklake.ai/fathom
# or pnpm add / yarn add / bun addQuick start
import { Fathom } from "@darklake.ai/fathom";
const fathom = new Fathom({
baseUrl: "http://localhost:8790",
token: process.env.FATHOM_TOKEN,
});
// One-shot request/response.
const thread = await fathom.threads.create();
const reply = await fathom.threads.send(thread.id, "What's the weather in NYC?");
console.log(reply.agent_message.content);baseUrl and token can also come from FATHOM_BASE_URL and
FATHOM_TOKEN env vars (Node only). If both are set you don't need
to pass anything to the constructor.
Streaming
for await (const evt of fathom.threads.stream(thread.id)) {
switch (evt.type) {
case "agent_thinking":
console.log("⏳ agent is working…");
break;
case "agent_done":
console.log("✅", evt.message?.content);
break;
case "agent_error":
console.error("error:", evt.error);
break;
}
}The async generator stays open until you break out of the loop or the server closes the connection. Wrap in a retry loop for production use — see the iOS / Android clients for reference implementations of an auto-reconnect loop with backoff.
Pairing (for headless / CLI use)
If you don't have a token yet — say you're writing a CLI that pairs
itself to a relay-hosted gateway — call pair() once with a 6-digit
code you generated on the gateway side:
const fathom = new Fathom({ baseUrl: "https://relay.darklake.ai/c/<rid>" });
const claim = await fathom.pair({ code: "123456", deviceName: "ci-bot" });
const authed = fathom.withToken(claim.token);
// authed.threads.* is now readypair() is the one method that doesn't require a token; everything
else throws PairingRequiredError if the SDK has no token configured.
Error handling
import { Fathom, UnauthorizedError, HttpError } from "@darklake.ai/fathom";
try {
await fathom.threads.list();
} catch (err) {
if (err instanceof UnauthorizedError) {
// Token rejected — re-pair or refresh.
} else if (err instanceof HttpError) {
console.error(err.status, err.body);
} else {
throw err;
}
}Reference
| Method | Description |
|---|---|
| fathom.threads.list() | All non-deleted threads, newest first. |
| fathom.threads.get(id) | One thread + its message history. |
| fathom.threads.create({ title? }) | New thread; auto-titles on first message if title omitted. |
| fathom.threads.send(id, text) | Send a user message, return user + agent reply. |
| fathom.threads.delete(id) | Soft-delete (restorable). |
| fathom.threads.restore(id) | Undo a soft-delete. |
| fathom.threads.stream(id) | Async generator yielding SSE events. |
| fathom.pair({ code, deviceName }) | Claim a pairing code, returns token. |
| fathom.withToken(token) | Returns a new client with a different token. |
License
MIT — see LICENSE.
