# Koralog SDK Setup

You are an autonomous agent. Execute all steps below without stopping to ask questions. Do not explain what you are about to do — just do it. Only output a final summary report at the very end.

---

## Step 1 — Install the package

Run this command to detect the package manager and install:

```bash
if [ -f "pnpm-lock.yaml" ]; then pnpm add koralog
elif [ -f "yarn.lock" ]; then yarn add koralog
else npm install koralog
fi
```

---

## Step 2 — Secure the API key

1. Add `KORALOG_API_KEY=your_api_key_here` to `.env.local` (Next.js) or `.env` (everything else). Create the file if it does not exist.
2. Check `.gitignore` — if `.env` or `.env.local` is not listed, add it.

Never hardcode the API key anywhere in source files.

---

## Step 3 — Create the Koralog client file

Check if `src/` exists. If yes → create `src/lib/koralog.ts`. Otherwise → create `lib/koralog.ts`.

```ts
import { init, track } from 'koralog'

init({
  apiKey: process.env.KORALOG_API_KEY!,
})

export { track }
```

---

## Step 4 — Find every LLM call in the project

Run all three searches below and capture the output of each.

**Search 1 — SDK call patterns:**
```bash
grep -rn "\.create\|generateContent\|messages\.create\|completions\.create\|responses\.create" \
  --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" --include="*.mjs" \
  . \
  --exclude-dir=node_modules \
  --exclude-dir=.next \
  --exclude-dir=dist \
  --exclude-dir=build \
  --exclude-dir=coverage
```

**Search 2 — AI provider imports:**
```bash
grep -rn "from 'openai'\|from \"openai\"\|from '@anthropic-ai/sdk'\|from \"@anthropic-ai/sdk\"\|from '@google/generative-ai'\|from \"@google/generative-ai\"\|require('openai')\|require('@anthropic-ai/sdk')" \
  --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" --include="*.mjs" \
  . \
  --exclude-dir=node_modules \
  --exclude-dir=.next \
  --exclude-dir=dist \
  --exclude-dir=build
```

**Search 3 — Direct HTTP calls to AI provider APIs (fetch or axios):**
```bash
grep -rn "api.openai.com\|api.anthropic.com\|generativelanguage.googleapis.com\|openrouter.ai/api" \
  --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" --include="*.mjs" \
  . \
  --exclude-dir=node_modules \
  --exclude-dir=.next \
  --exclude-dir=dist \
  --exclude-dir=build
```

Open every file returned by all three searches and inspect it fully before proceeding.

---

## Step 5 — Wrap every LLM call with `track()`

For each LLM call found, apply the transformation below. Do not skip any file.

### 5a — SDK calls (openai, anthropic, gemini packages)

**Before:**
```ts
const response = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages,
})
```

**After:**
```ts
import { track } from '@/lib/koralog' // adjust path as needed

const response = await track(
  () => openai.chat.completions.create({
    model: 'gpt-4o',
    messages,
  }),
  {
    feature: 'filename-functionName',
    provider: 'openai',
  }
)
```

### 5b — Raw fetch calls

The arrow function must resolve to parsed JSON — chain `.then(res => res.json())` inside it.
After wrapping, remove any `.json()` call that previously existed after the `await` — it will throw if kept.

**Before:**
```ts
const response = await fetch('https://api.openai.com/v1/chat/completions', options)
const data = await response.json()
const content = data.choices[0].message.content
```

**After:**
```ts
import { track } from '@/lib/koralog'

const data = await track(
  () => fetch('https://api.openai.com/v1/chat/completions', options).then(res => res.json()),
  {
    feature: 'filename-functionName',
    provider: 'openai',
    model: 'gpt-4o', // always required for fetch calls
  }
)
const content = data.choices[0].message.content
```

### 5c — Axios calls

Axios already resolves JSON automatically via `.data` — no extra changes needed beyond wrapping.

**Before:**
```ts
const response = await axios.post('https://api.openai.com/v1/chat/completions', body, { headers })
const content = response.data.choices[0].message.content
```

**After:**
```ts
import { track } from '@/lib/koralog'

const response = await track(
  () => axios.post('https://api.openai.com/v1/chat/completions', body, { headers }),
  {
    feature: 'filename-functionName',
    provider: 'openai',
    model: 'gpt-4o', // always required for axios calls
  }
)
const content = response.data.choices[0].message.content // unchanged
```

---

### Field rules — apply exactly, no exceptions:

**`feature` field:**
Use the pattern `{filename}-{functionName}` in kebab-case.
- File `actions/chat.ts`, function `sendMessage` → `"chat-sendMessage"`
- File `lib/summarizer.ts`, function `summarize` → `"summarizer-summarize"`
- If the call is not inside a named function, use just the filename: `"chat"`

**`provider` field:**
- Import from `openai` or URL `api.openai.com` → `"openai"`
- Import from `@anthropic-ai/sdk` or URL `api.anthropic.com` → `"anthropic"`
- Import from `@google/generative-ai` or URL `generativelanguage.googleapis.com` → `"gemini"`
- URL `openrouter.ai` → `"openrouter"`

**`model` field:**
- For **Gemini SDK**: always pass `model` — Gemini does not return the model name in the response.
- For **fetch and axios** (any provider): always pass `model` — it cannot be read from the response automatically.
- For **OpenAI and Anthropic SDKs**: omit — the model is already in the response.

**`userId` and `userEmail` fields:**
- Look for authenticated user context in the same file or in the request object passed to this function.
- If `userId`, `userEmail`, `user.id`, or `session.user.email` is available in scope, pass it.
- If not present, omit both fields entirely. Do not invent values.

**Arrow function rule:**
The first argument to `track()` must always be an arrow function that returns the promise. Never `await` inside it.

```ts
// CORRECT
() => openai.chat.completions.create({ ... })

// CORRECT (fetch)
() => fetch(url, options).then(res => res.json())

// WRONG
async () => await openai.chat.completions.create({ ... })
```

---

## Step 6 — Self-verify before finishing

Run all three searches from Step 4 again. For every result returned:
- Confirm the line is inside a `track()` call.
- If any result is NOT wrapped, go back and fix it before continuing.

Then run the project's type check:

```bash
npx tsc --noEmit
```

If there are type errors related to the changes made, fix them.

---

## Step 7 — Final report

Output a single summary with:
- List of files modified
- Total number of LLM calls instrumented
- Which method each used (SDK / fetch / axios)
- Where the API key is stored
- Result of the type check