{
  "markdown": "# kern-link\n\n[![Test](https://github.com/julienlegoux/kern-link/actions/workflows/test.yml/badge.svg)](https://github.com/julienlegoux/kern-link/actions/workflows/test.yml)\n[![Go Reference](https://pkg.go.dev/badge/github.com/julienlegoux/kern-link/ai.svg)](https://pkg.go.dev/github.com/julienlegoux/kern-link/ai)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\nA unified LLM API for Go: one streaming interface across 35 providers —\nAnthropic, OpenAI, Google (Gemini & Vertex), Mistral, AWS Bedrock, Azure,\nGitHub Copilot, OpenAI Codex, OpenRouter, Groq, xAI, and more — with automatic\ncredential resolution (env keys and OAuth), token & cost tracking, and\nconversations you can persist and hand off to a different model mid-session.\n\nkern-link is a full-parity Go port of\n[`@earendil-works/pi-ai`](https://github.com/earendil-works/pi/tree/main/packages/ai)\nthat tracks upstream over time.\n\n## Features\n\n- **One message model, every provider** — write against `ai.Context` /\n  `ai.Message` once; adapters translate to each vendor's wire protocol\n  (Anthropic Messages, OpenAI Completions & Responses, Gemini, Mistral,\n  Bedrock Converse, …).\n- **Unified streaming events** — text, thinking, and tool-call deltas arrive\n  as one typed event protocol, ending in exactly one done/error event.\n  Provider failures are in-band, never lost.\n- **Auth that just works** — per-provider env keys, a cross-process-safe\n  credential store, and real OAuth flows (Claude Pro/Max, GitHub Copilot,\n  ChatGPT Plus/Pro) via the bundled `pi-ai login` CLI.\n- **Cost & token accounting** — an embedded model catalog with per-model\n  pricing, `ai.CalculateCost`, token estimation, and cache-read/write\n  breakdowns.\n- **Session persistence & model hand-off** — conversations are plain\n  JSON-serializable `[]ai.Message`; resume any conversation on any provider\n  ([how](docs/usage.md#session-persistence-and-model-hand-off)).\n- **Tool calling, thinking levels, retry/overflow classifiers** — portable\n  across providers, clamped to what each model supports.\n- **Offline-testable** — the in-process `faux` provider exercises the full\n  streaming contract without a network.\n\n## Install\n\n```sh\ngo get github.com/julienlegoux/kern-link\n```\n\n## Quick start\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"time\"\n\n\t\"github.com/julienlegoux/kern-link/ai\"\n\t\"github.com/julienlegoux/kern-link/ai/providers\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\t// Reads ANTHROPIC_API_KEY (or stored OAuth credentials) automatically.\n\tmodels := providers.Models(nil)\n\n\tmodel := models.GetModel(\"anthropic\", \"claude-sonnet-4-5\")\n\tif model == nil {\n\t\tlog.Fatal(\"unknown model\")\n\t}\n\n\tchat := ai.Context{\n\t\tSystemPrompt: \"You are a helpful assistant.\",\n\t\tMessages: []ai.Message{\n\t\t\t&ai.UserMessage{\n\t\t\t\tContent:   ai.UserText(\"Hello, who are you?\"),\n\t\t\t\tTimestamp: time.Now().UnixMilli(),\n\t\t\t},\n\t\t},\n\t}\n\n\tstream := models.StreamSimple(ctx, model, chat, &ai.SimpleStreamOptions{})\n\tfor ev := range stream.Events(ctx) {\n\t\tif e, ok := ev.(ai.TextDeltaEvent); ok {\n\t\t\tfmt.Print(e.Delta)\n\t\t}\n\t}\n\n\tmsg, err := stream.Result(ctx)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tcost := ai.CalculateCost(model, &msg.Usage)\n\tfmt.Printf(\"\\ntokens in=%d out=%d  $%.6f\\n\",\n\t\tmsg.Usage.Input, msg.Usage.Output, cost.Total)\n}\n```\n\nA conversation is just `[]ai.Message` and round-trips through `encoding/json`,\nso saving a session and resuming it — on the same model or a different\nprovider — needs no extra machinery. See\n[Session persistence and model hand-off](docs/usage.md#session-persistence-and-model-hand-off).\n\n## Authentication\n\nSet the provider's env var (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`,\n`GEMINI_API_KEY`, …) or log in once over OAuth:\n\n```sh\ngo run github.com/julienlegoux/kern-link/cmd/pi-ai login\n```\n\nCredentials land in `~/.pi/agent/auth.json` and are picked up (and refreshed)\nautomatically. Full details — resolution order, every env var, Bedrock/Vertex\nspecifics — in [docs/auth.md](docs/auth.md).\n\n### Credential modes\n\nThe two paths carry different terms-of-service risk:\n\n- **API keys** (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, AWS creds, Google ADC, …)\n  — billed per token under a developer agreement written for programmatic\n  access. No ToS risk. Use these in anything you ship.\n- **Subscription OAuth** (Claude Pro/Max, ChatGPT Plus/Pro, GitHub Copilot) —\n  `pi-ai login` yields a first-party client's credential, and kern-link then\n  presents itself as that client (`user-agent: claude-cli/…`,\n  `Editor-Version: vscode/…`). This is inherited upstream behavior and it is\n  fine for personal use. Shipping it in a product means directing users to\n  impersonate a first-party client against a subscription not licensed for\n  programmatic access — providers can revoke the account.\n\nSee [docs/auth.md](docs/auth.md#credential-modes-and-terms-of-service-risk) for\nthe details.\n\n## Documentation\n\n| Doc | What's in it |\n|---|---|\n| [pkg.go.dev](https://pkg.go.dev/github.com/julienlegoux/kern-link/ai) | API reference with runnable examples |\n| [docs/usage.md](docs/usage.md) | Streaming, tool calls, thinking levels, cost tracking, persistence & model hand-off, offline testing |\n| [docs/architecture.md](docs/architecture.md) | Package layering, the unified message/event model, request flow, provider list |\n| [docs/auth.md](docs/auth.md) | Env keys per provider, credential store, OAuth flows, the `pi-ai` CLI |\n| [docs/PORTING.md](docs/PORTING.md) | Upstream→Go file mapping, intentional deviations, sync procedure |\n\n## Development\n\n```sh\ngo test ./... -race\n```\n\nEverything runs offline; live provider tests are gated behind environment API\nkeys, mirroring upstream.\n\n## Upstream & parity\n\nThe port targets full functional parity with the upstream TypeScript package.\nThe pinned revision lives in `upstream/UPSTREAM.lock`; `upstream/sync.sh`\ndiffs upstream since the pin (also run weekly in CI, which opens an issue when\nupstream moved). Every ported file carries a `// Ports:` header naming its\nupstream source — see [docs/PORTING.md](docs/PORTING.md).\n\n## License\n\n[MIT](LICENSE). Ported from [`@earendil-works/pi-ai`](https://github.com/earendil-works/pi)\n(MIT, © Mario Zechner) — see [NOTICE](NOTICE).\n",
  "bytes": 6219,
  "sha": "fa16910cb284681c513e779017bc9792f398c15705909179170d101b6db290aa",
  "repo_slug": "kern-ia/kern-link",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/okf_kern_ia_kern_link_docs_index_md_f7d63715/readme"
}