cracked-ai-sdk
v0.1.0
Published
Zero-dependency TypeScript client for Cracked, the agent tool router: discover, inspect, run and poll 50,000+ tools with one API key.
Maintainers
Readme
@cracked-ai/sdk (TypeScript)
Zero-dependency TypeScript/JavaScript client for Cracked, the tool router for agents: one API key, one balance, 50,000+ tools. ESM, typed, uses the global fetch (Node 18+, Bun, Deno, edge runtimes, browsers).
Publishing to npm soon. Until then install from the repo path:
npm install ./sdk/typescript # from the repo root (builds dist/ via prepublishOnly is NOT run for file installs; run `npm run build` in sdk/typescript first)
# or, once published:
npm install @cracked-ai/sdkBuild: cd sdk/typescript && npx tsc (emits dist/index.js + dist/index.d.ts).
Quick start
import { Cracked, CrackedError } from "@cracked-ai/sdk";
const c = new Cracked(); // reads CRACKED_API_KEY; base URL from CRACKED_BASE_URL (default https://cracked.ai/v1)
const { results } = await c.discover("weather forecast for a lat/long", { limit: 5 });
const schema = (await c.inspect(results[0].provider, results[0].endpoint)).input.body; // JSON Schema
const rec = await c.run("open-meteo", "/forecast", { latitude: 30.27, longitude: -97.74 });
console.log(rec.status, rec.billing.totalUsd, rec.output);No key yet? Register an agent workspace with no human in the loop (trial credit included):
const reg = await Cracked.registerAgent({ name: "my-agent" });
await reg.client.run(...); // ready to use
reg.apiKey; // shown once: store it as CRACKED_API_KEY
reg.claimUrl; // give this to your human: adds credit, unlocks top-upsMethods
| Method | Endpoint | Notes |
|---|---|---|
| discover(query, { limit, liveOnly, minScore, category, provider, includeApify, includeUnavailable }) | POST /discover | { query, count, results } |
| inspect(provider, endpoint) | POST /inspect | Schema in .input.body, price, health |
| run(provider, endpoint, input, { wait, poll, webhookUrl, timeoutMs, pollWait, signal }) | POST /run | RunRecord; polls on 202 when poll (defaults to wait) |
| runCapability(capability, input, opts) | POST /run { capability } | Smart run: Cracked picks the provider and falls back. Adds routedTo, attempts |
| capabilities(id?) | GET /capabilities?id= | List capabilities (input schema + ranked candidates), or one by id. No auth |
| getRun(runId, { wait }) | GET /runs/{id}?wait= | wait long-polls up to 100 s |
| waitFor(runId, { timeoutMs, pollWait }) | polls GET /runs/{id} | Throws CrackedTimeoutError (with .record) if still RUNNING |
| stop(runId) | POST /runs/{id}/stop | 409 if already finished |
| runs(limit) | GET /runs | Recent runs, no output bodies |
| feedback(runId, ok, note?) | POST /runs/{id}/feedback | Thumbs up/down |
| balance() | GET /wallet/balance | |
| whoami() | GET /auth/whoami | |
| referrals() / referralLink() | GET /referrals | Share the link: both sides get credit |
| bountyProgram() | GET /bounties/program | Public, no auth |
| bounties() | GET /bounties | Your bounty ledger |
| claimBounty(url) | POST /bounties | Backlink/listing bounty |
| Cracked.registerAgent({ name, ref, baseUrl }) | POST /agents/register | Static, no auth. Returns { client, apiKey, claimUrl, referralUrl, ... } |
| request(method, path, body?, opts?) | any | Escape hatch for endpoints not wrapped above |
Types exported: RunRecord, SmartRunRecord, RunStatus, DiscoverResult, DiscoverResponse, InspectResult, Balance, ReferralStats, AgentRegistration, BountyClaim, FeedbackResult, StopResult, Price, Billing, and more.
Async runs
// let the client poll (submit without holding the request open, then long-poll):
const rec = await c.run("apify", "/apify/instagram-profile-scraper", { usernames: ["nike"] }, { wait: false, poll: true, timeoutMs: 600_000 });
// or drive it yourself:
const started = await c.run("apify", "/apify/instagram-profile-scraper", { usernames: ["nike"] }, { wait: false }); // 202 RUNNING
const done = await c.waitFor(started.runId, { timeoutMs: 600_000 });
await c.stop(started.runId); // abort if neededTerminal statuses: COMPLETED, FAILED, BLOCKED, STOPPED, TIMED_OUT (isTerminal(status) helper exported). COMPLETED with providerResponse.httpStatus === 404 means the provider found nothing. BLOCKED (HTTP 503, not billed) means the provider needs your own key.
Errors
try { await c.run(...); }
catch (e) {
if (e instanceof CrackedError) {
e.status; e.code; e.message; e.runId;
if (e.insufficientFunds) /* 402 */ ;
if (e.unauthorized) /* 401 */ ;
if (e.rateLimited) /* 429 */ ;
}
}Transport failures throw CrackedError with status === 0 and code NETWORK_ERROR / NETWORK_TIMEOUT.
Publishing
cd sdk/typescript && npm run build && npm publish --access public