npm package: @kynver-app/sdk
Description: Kynver developer SDK — REST API client, execution tracking (KynverTracker), and React receipt components.
Author: Kynver
Latest version: 1.0.0

# @kynver-app/sdk

Kynver developer SDK: REST API client, execution tracking (KynverTracker), and React receipt components.

**Version:** 1.0.0 · **Strict semver.** Pin as `"@kynver-app/sdk": "^1.0.0"` to allow non-breaking updates.

---

## ⚠️ API key: server-side only

**Never use the SDK with an `apiKey` in the browser or in client-side code.** The key would be exposed in the bundle and in network requests. Use the authenticated client and tracker only in:

- Server Components (Next.js)
- Route Handlers / API routes
- Server-side utilities (Node.js scripts, workers)

The React receipt components (`@kynver-app/sdk/react`) are safe to use client-side — they only receive `receiptId` and `agentDid`.

### Next.js example (correct pattern)

```ts
// app/actions/agent.ts — Server Action or server-only module
"use server";
import { KynverClient, KynverTracker } from "@kynver-app/sdk";

const client = new KynverClient({ apiKey: process.env.KYNVER_API_KEY });
const tracker = new KynverTracker({
  agentDid: process.env.KYNVER_AGENT_DID!,
  apiKey: process.env.KYNVER_API_KEY,
});

export async function getAgent(slug: string) {
  return client.getAgent(slug);
}

export async function reportExecution(payload: { instruction: string; output: string }) {
  return tracker.reportExecution(payload);
}
```

```tsx
// app/page.tsx — Client component only receives data, no apiKey
import { getAgent } from "./actions/agent";
import { KynverChatReceipt } from "@kynver-app/sdk/react";

export default async function Page() {
  const agent = await getAgent("my-agent");
  return (
    <div>
      <p>{agent.name}</p>
      <KynverChatReceipt receiptId="..." agentDid={agent.did} />
    </div>
  );
}
```

---

## Install

```bash
npm install @kynver-app/sdk
```

Recommendation: `"@kynver-app/sdk": "^1.0.0"` so you get patch and minor updates without breaking changes.

---

## Quickstart

### REST client

```ts
import { KynverClient } from "@kynver-app/sdk";

const client = new KynverClient({
  baseUrl: "https://kynver.com", // optional; default from KYNVER_API_BASE_URL or https://kynver.com
  apiKey: process.env.KYNVER_API_KEY, // server-side only
});

const agent = await client.getAgent("my-agent-slug");
const reputation = await client.getReputation("my-agent-slug");
await client.submitReview("my-agent-slug", { rating: 5, reviewText: "Great!" });
```

### Execution tracker

```ts
import { KynverTracker } from "@kynver-app/sdk";

const tracker = new KynverTracker({
  agentDid: "did:kynver:...",
  apiKey: process.env.KYNVER_API_KEY,
});

const result = await tracker.reportExecution({
  instruction: "Summarize this document",
  output: "The document says...",
  taskCategory: "summarization",
  status: "success",
});
// When Phase 7 receipt endpoint is live: result.receiptId
// Until then: result.queued === true
```

### captureAuthorization (pre-action gate)

`captureAuthorization` **throws** when the audit endpoint is unavailable so you can block the action:

```ts
try {
  const token = await tracker.captureAuthorization({
    actionType: "send_email",
    scope: "user:123",
    consentMethod: "in_app",
  });
  await tracker.reportExecution({
    instruction,
    output,
    authorizationTokenIds: [token.id],
  });
} catch (e) {
  if (e.code === "KYNVER_AUDIT_UNAVAILABLE") {
    // Block the action or show a message
    return;
  }
  throw e;
}
```

### Auto-instrumentation

Set env: `KYNVER_AGENT_DID`, `KYNVER_API_KEY`, and optionally `KYNVER_SIGNING_KEY`. Then:

```ts
import "@kynver-app/sdk/auto"; // first line of your agent entry file
import { reportExecutionFromAuto } from "@kynver-app/sdk/auto";

// After each LLM/chain invocation, call:
await reportExecutionFromAuto({
  instruction: userInput,
  output: modelOutput,
  taskCategory: "chat",
  status: "success",
});
```

---

## React receipt components

Place receipts **at the moment of task completion** (e.g. below the last agent message), not in settings or account pages.

```tsx
import { KynverChatReceipt, KynverTaskReceipt } from "@kynver-app/sdk/react";
// Optional default styles:
// import "@kynver-app/sdk/react/styles.css";

<KynverChatReceipt receiptId={receiptId} agentDid={agentDid} timestamp={iso} />
<KynverTaskReceipt receiptId={receiptId} agentDid={agentDid} taskCategory="summarization" status="success" />
```

For JSON API responses:

```ts
import { buildApiReceipt } from "@kynver-app/sdk/react";
const body = { result: "...", ...buildApiReceipt(receiptId, agentDid) };
return Response.json(body);
```

---

## Environment variables

| Variable | Description |
|----------|-------------|
| `KYNVER_API_BASE_URL` | Base URL (default: https://kynver.com) |
| `KYNVER_API_KEY` | Bearer token for authenticated calls (server-side only) |
| `KYNVER_AGENT_DID` | Agent DID for tracker / auto |
| `KYNVER_SIGNING_KEY` | Optional Tier 2 ed25519 private key |
| `KYNVER_JWKS_URL` | Override JWKS URL for encryption (default: baseUrl + /.well-known/jwks.json) |

---

## Entry points

- `@kynver-app/sdk` — client, tracker, types (no React)
- `@kynver-app/sdk/auto` — auto-instrumentation and `reportExecutionFromAuto`
- `@kynver-app/sdk/react` — React receipt components and `buildApiReceipt`
- `@kynver-app/sdk/react/styles.css` — optional default styles