Files

1 line
35 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "alexanys/ai-sub-auth", "files": {"AGENT.md": {"56279a3374d540301c3da75f9429cf46fcb553e6": {"t": 1785747165.708805, "n": 12860, "h": "050247f9533210d8", "c": "# Agent Integration Guide\n\n> **For AI Agents**: Read this file to understand how to integrate `ai-sub-auth` into any application.\n> This file is designed to be consumed by Claude Code, OpenClaw, Cursor, Copilot, or any agentic coding tool.\n\n## What is ai-sub-auth?\n\nA lightweight Python module (~500 LOC, only depends on `httpx`) that authenticates against AI providers using existing user subscriptions. It handles OAuth PKCE (OpenAI Codex), API keys (Claude, Gemini, DeepSeek), and device code (GitHub Copilot) — all through a unified `LLMClient` interface.\n\n**3-line integration:**\n```python\n# Recommended — auto-detects your subscription\nfrom ai_sub_auth import AI\nai = AI()\nresult = await ai.chat(\"your prompt here\", system=\"your system prompt\")\n\n# Or explicit provider selection\nfrom ai_sub_auth import LLMClient, PROVIDERS\nclient = LLMClient(PROVIDERS[\"openai_codex\"], model=\"openai-codex/gpt-4o\")\nresp = await client.chat(\"your prompt here\", system=\"your system prompt\")\n```\n\n## Subscription Reality (2026)\n\nWhich AI subscriptions can be bridged into third-party apps:\n\n| Provider | Method | Status | Notes |\n|----------|--------|--------|-------|\n| **OpenAI ChatGPT Plus/Pro** | OAuth PKCE | ✅ Safe & encouraged | OpenAI actively supports via Codex SDK, MCP, Apps SDK |\n| **Claude** | API Key | ✅ Works (pay-per-token) | Anthropic banned subscription OAuth (Feb 2026). Use API key only |\n| **GitHub Copilot** | Device Code | ⚠️ Works but violates ToS | Not recommended for production |\n| **Google Gemini** | API Key | ✅ Works (pay-per-token) | Google banned subscription OAuth. Accounts permanently banned |\n| **DeepSeek, OpenRouter** | API Key | ✅ Works | Standard API key auth |\n\n**Key insight:** OpenAI Codex OAuth is the only path where users can reuse their existing subscription ($20/mo ChatGPT Plus) in third-party apps at zero additional cost. All other providers require pay-per-token API keys.\n\n### Provider Selection Guide\n\nWhen integrating AI into an app, help the user choose:\n\n1. **User has ChatGPT Plus/Pro** → Use OpenAI Codex OAuth (zero extra cost, best value)\n2. **User has Claude API key** → Use Anthropic API Key (high quality, pay-per-token)\n3. **User has both** → Default to OpenAI Codex (free with subscription), fall back to Claude\n4. **User has neither** → Guide them to get ChatGPT Plus ($20/mo) or a free-tier API key\n\n⚠️ **Anti-Patterns — Do NOT:**\n- Attempt to bridge Claude Pro/Max subscription via OAuth (Anthropic will block it)\n- Attempt to bridge Google Gemini subscription via OAuth (Google will permanently ban the account)\n- Hardcode provider-specific API calls in the target app (use ai-sub-auth's unified interface)\n- Store tokens outside the module's TokenStore (security risk)\n\n---\n\n## Quick Reference\n\n| File | Purpose |\n|------|---------|\n| `ai_sub_auth/facade.py` | **AI Facade** — auto-detects subscription, recommended entry point |\n| `ai_sub_auth/providers.py` | Provider registry — add new providers here |\n| `ai_sub_auth/oauth_flow.py` | OAuth PKCE login + auto token refresh |\n| `ai_sub_auth/token_store.py` | Secure token storage (~/.ai-sub-auth/tokens/) |\n| `ai_sub_auth/api_client.py` | Unified LLMClient — routes to correct API |\n| `ai_sub_auth/models.py` | Data models: OAuthToken, ProviderConfig, LLMResponse |\n| `ai_sub_auth/exceptions.py` | AuthError, TokenExpiredError, LoginRequiredError |\n\n---\n\n## Meta Skill Framework\n\nWhen integrating AI into any application, every useful AI feature is a composition of exactly **8 meta skills**:\n\n```\nSkill Direction What it does\n───────── ───────────── ─────────────────────────────────────────\nSUMMARIZE many → few Reduce volume while preserving meaning\nGENERATE few → many Produce new content from intent or spec\nANALYZE raw → insight Find patterns, anomalies, trends in data\nTRANSFORM form A → form B Convert between formats, styles, languages\nCLASSIFY items → buckets Assign categories, priorities, or labels\nEVALUATE content → score Judge quality against criteria\nCONVERSE user ↔ AI Multi-turn contextual dialogue\nEXTRACT noise → signal Pull structured data from unstructured input\n```\n\n### When to apply each skill\n\n| Skill | Trigger signals in the target app |\n|-------|----------------------------------|\n| SUMMARIZE | Has collections of text (notes, emails, logs, threads, history) |\n| GENERATE | Has \"create/new\" buttons, blank editors, templates, boilerplate |\n| ANALYZE | Has charts, tables, dashboards, numerical/time-series data |\n| TRANSFORM | Has import/export, format conversion, audience adaptation |\n| CLASSIFY | Has inbox/queue/feed, manual tagging, predefined categories |\n| EVALUATE | Has submissions, reviews, quality checks, rubrics, checklists |\n| CONVERSE | Has help section, complex workflows, onboarding, Q&A needs |\n| EXTRACT | Has manual data entry, forms, paste-from-external, uploads |\n\n---\n\n## 3-Suggestion Protocol\n\nWhen you encounter a new application, follow this protocol to suggest AI integrations:\n\n### Step 1: SCAN — Build an App Profile\n\nExamine in order: README → directory structure → routes/endpoints → data models → UI entry points.\n\nProduce:\n```\ndomain: [e.g., \"education\", \"finance\", \"devtools\", \"personal\"]\nverbs: [what the app DOES — \"create tasks\", \"send emails\", \"track expenses\"]\nnouns: [what the app KNOWS — \"notes\", \"transactions\", \"users\", \"documents\"]\nroles: [who uses it — \"admin\", \"user\", \"viewer\"]\nexisting_ai: [what's already AI-powered, if anything]\n```\n\n### Step 2: MATCH — Score skills against the profile\n\nFor each of the 8 meta skills, check if its trigger signals are present in the app profile. Prioritize skills that are NOT yet implemented (greenfield bonus).\n\n### Step 3: RANK — Select exactly 3\n\nRank by: **Impact (3x)** × **Feasibility (2x)** × **Differentiation (1x)**\n\nHard rules:\n- 3 suggestions, never more, never fewer\n- No two suggestions use the same meta skill\n- At least one must be a **quick win** (< 50 lines to integrate)\n- At least one must be **high ceiling** (transformative if done fully)\n\n### Step 4: PRESENT — Use this template for each suggestion\n\n```\n## Suggestion [1/3]: [SKILL] — [One-line description]\n\n**What it does:** [2-3 sentences, user perspective]\n**Why this app needs it:** [Connect to a specific pain point from SCAN]\n**Integration point:** [Exact file(s) and function(s)]\n**Effort:** [Quick win | Moderate | Deep integration]\n\n**Implementation sketch:**\n1. [Hook: where in the app to add this]\n2. [Service: the ai-sub-auth call pattern]\n3. [UI: how the user triggers and sees it]\n```\n\n### Step 5: IMPLEMENT — Upon user approval\n\n```\n1. AUTH → from ai_sub_auth import LLMClient, PROVIDERS\n2. SERVICE → Create function: input → LLMClient.chat(prompt, system) → parsed output\n3. ROUTE → Wire into app's existing API/endpoint pattern\n4. UI → Add trigger (button/auto/hook) following app's component style\n5. VERIFY → Test auth, test output, test error handling\n```\n\n---\n\n## Integration Patterns by App Category\n\n| Category | Best 3 skills | Example integration |\n|----------|--------------|-------------------|\n| **Notes/PKM** (Obsidian, Logseq) | Summarize, Analyze, Generate | \"Summarize this week's notes\" button |\n| **Dev tools** (terminals, IDEs) | Evaluate, Analyze, Generate | Inline code review on git diff |\n| **Email/Chat** (Thunderbird, Element) | Generate, Summarize, Classify | Draft reply + inbox triage |\n| **CMS/Blog** (Hugo, WordPress) | Generate, Transform, Evaluate | AI first draft + SEO metadata |\n| **Data/Analytics** (Grafana, Metabase) | Analyze, Transform, Generate | Natural language → SQL query |\n| **Personal** (finance, health, calendar) | Analyze, Extract, Generate | Voice → structured expense entry |\n| **System/Infra** (monitoring, CI/CD) | Analyze, Generate, Transform | Log correlation → incident summary |\n\n---\n\n## Implementation Example\n\nHere's a complete example of adding SUMMARIZE to a note-taking app:\n\n```python\n# 1. AUTH — one-time setup\nfrom ai_sub_auth import LLMClient, PROVIDERS, oauth_login\n\n# If using ChatGPT subscription (OAuth):\n# oauth_login(PROVIDERS[\"openai_codex\"]) # first time only\nclient = LLMClient(PROVIDERS[\"openai_codex\"], model=\"openai-codex/gpt-4o\")\n\n# Or if using API key:\n# client = LLMClient(PROVIDERS[\"anthropic\"], api_key=\"sk-...\", model=\"claude-sonnet-4-5-20250514\")\n\n# 2. SERVICE — the AI function\nasync def summarize_notes(notes: list[str], max_points: int = 5) -> dict:\n combined = \"\\n---\\n\".join(notes)\n resp = await client.chat(\n message=combined,\n system=f\"Summarize these {len(notes)} notes into {max_points} key points. \"\n f\"Output JSON: {{\\\"points\\\": [\\\"...\\\"], \\\"action_items\\\": [\\\"...\\\"]}}\",\n )\n import json\n return json.loads(resp.content)\n\n# 3. ROUTE — hook into your app's API\n# @app.post(\"/api/ai/summarize\")\n# async def api_summarize(request): ...\n\n# 4. UI — add a button\n# <button onClick={summarize}>✨ Summarize</button>\n```\n\n### TRANSFORM Example: Adding translation to a messaging app\n\n```python\n# 1. AUTH — one-time setup\nfrom ai_sub_auth import LLMClient, PROVIDERS, oauth_login\n\n# Using ChatGPT subscription (zero cost for the user):\n# oauth_login(PROVIDERS[\"openai_codex\"]) # first time only\nclient = LLMClient(PROVIDERS[\"openai_codex\"], model=\"openai-codex/gpt-4o\")\n\n# 2. SERVICE — the AI function\nasync def translate_message(text: str, source_lang: str, target_lang: str) -> dict:\n resp = await client.chat(\n message=text,\n system=(\n f\"Translate the following from {source_lang} to {target_lang}. \"\n f\"Preserve tone, formatting, and any embedded links. \"\n f'Output JSON: {{\"translation\": \"...\", \"detected_lang\": \"...\", \"confidence\": 0.0-1.0}}'\n ),\n )\n import json\n return json.loads(resp.content)\n\n# 3. ROUTE — hook into your messaging app's API\nfrom fastapi import APIRouter\nrouter = APIRouter()\n\n@router.post(\"/api/ai/translate\")\nasync def api_translate(request: dict):\n result = await translate_message(\n text=request[\"text\"],\n source_lang=request.get(\"source_lang\", \"auto\"),\n target_lang=request[\"target_lang\"],\n )\n return result\n\n# 4. UI — add inline translate button on each message\n# <button onClick={() => translate(msg.id, userLang)}>🌐 Translate</button>\n# Shows translated text below original, with \"Translated from {detected_lang}\" label\n```\n\n### EXTRACT Example: Structured data extraction from documents\n\n```python\n# 1. AUTH — one-time setup\nfrom ai_sub_auth import LLMClient, PROVIDERS, oauth_login\n\n# Using ChatGPT subscription:\n# oauth_login(PROVIDERS[\"openai_codex\"]) # first time only\nclient = LLMClient(PROVIDERS[\"openai_codex\"], model=\"openai-codex/gpt-4o\")\n\n# Or using Claude API key for higher extraction accuracy:\n# client = LLMClient(PROVIDERS[\"anthropic\"], api_key=\"sk-...\", model=\"claude-sonnet-4-5-20250514\")\n\n# 2. SERVICE — the AI function\nasync def extract_invoice_data(raw_text: str) -> dict:\n resp = await client.chat(\n message=raw_text,\n system=(\n \"Extract structured data from this invoice/receipt. \"\n \"Output JSON: {\"\n '\"vendor\": \"...\", \"date\": \"YYYY-MM-DD\", \"currency\": \"...\", '\n '\"total\": 0.00, \"tax\": 0.00, \"subtotal\": 0.00, '\n '\"line_items\": [{\"description\": \"...\", \"qty\": 1, \"unit_price\": 0.00, \"amount\": 0.00}]'\n \"}\"\n \" If a field is not found, use null.\"\n ),\n )\n import json\n return json.loads(resp.content)\n\n# 3. ROUTE — hook into your document management app's API\nfrom fastapi import APIRouter, UploadFile\nrouter = APIRouter()\n\n@router.post(\"/api/ai/extract-invoice\")\nasync def api_extract_invoice(file: UploadFile):\n raw_text = (await file.read()).decode(\"utf-8\") # or use OCR for images\n result = await extract_invoice_data(raw_text)\n return result\n\n# 4. UI — add extract button on document upload\n# <button onClick={() => extractData(doc.id)}>📋 Extract Data</button>\n# Pre-fills form fields with extracted values; user reviews and confirms\n```\n\n---\n\n## Principles\n\n1. **Eight is enough.** Every AI feature maps to one of the 8 skills. Don't invent a ninth — it's a composition.\n2. **Skills are verbs, not features.** \"Summarize\" is a skill. \"Email summary\" is a feature = skill + context.\n3. **Three suggestions, never more.** Fewer forces prioritization. More creates paralysis.\n4. **Quick-win plus high-ceiling.** Build trust with a fast win, then go deep.\n5. **Follow the host.** Mirror the target app's conventions for auth, routing, and UI. Be a guest, not an invader.\n6. **Auth is first, not last.** Every AI feature goes through ai-sub-auth from step 1.\n7. **Subscription-first.** Prefer OAuth subscription bridge (ChatGPT Plus) over API keys when available. It's zero extra cost for the user.\n"}, "cf86f9f422516ecf0d15f7cffe77d1a613c0461b": {"t": 1785770834.5574625, "n": 12860, "h": "050247f9533210d8", "c": "# Agent Integration Guide\n\n> **For AI Agents**: Read this file to understand how to integrate `ai-sub-auth` into any application.\n> This file is designed to be consumed by Claude Code, OpenClaw, Cursor, Copilot, or any agentic coding tool.\n\n## What is ai-sub-auth?\n\nA lightweight Python module (~500 LOC, only depends on `httpx`) that authenticates against AI providers using existing user subscriptions. It handles OAuth PKCE (OpenAI Codex), API keys (Claude, Gemini, DeepSeek), and device code (GitHub Copilot) — all through a unified `LLMClient` interface.\n\n**3-line integration:**\n```python\n# Recommended — auto-detects your subscription\nfrom ai_sub_auth import AI\nai = AI()\nresult = await ai.chat(\"your prompt here\", system=\"your system prompt\")\n\n# Or explicit provider selection\nfrom ai_sub_auth import LLMClient, PROVIDERS\nclient = LLMClient(PROVIDERS[\"openai_codex\"], model=\"openai-codex/gpt-4o\")\nresp = await client.chat(\"your prompt here\", system=\"your system prompt\")\n```\n\n## Subscription Reality (2026)\n\nWhich AI subscriptions can be bridged into third-party apps:\n\n| Provider | Method | Status | Notes |\n|----------|--------|--------|-------|\n| **OpenAI ChatGPT Plus/Pro** | OAuth PKCE | ✅ Safe & encouraged | OpenAI actively supports via Codex SDK, MCP, Apps SDK |\n| **Claude** | API Key | ✅ Works (pay-per-token) | Anthropic banned subscription OAuth (Feb 2026). Use API key only |\n| **GitHub Copilot** | Device Code | ⚠️ Works but violates ToS | Not recommended for production |\n| **Google Gemini** | API Key | ✅ Works (pay-per-token) | Google banned subscription OAuth. Accounts permanently banned |\n| **DeepSeek, OpenRouter** | API Key | ✅ Works | Standard API key auth |\n\n**Key insight:** OpenAI Codex OAuth is the only path where users can reuse their existing subscription ($20/mo ChatGPT Plus) in third-party apps at zero additional cost. All other providers require pay-per-token API keys.\n\n### Provider Selection Guide\n\nWhen integrating AI into an app, help the user choose:\n\n1. **User has ChatGPT Plus/Pro** → Use OpenAI Codex OAuth (zero extra cost, best value)\n2. **User has Claude API key** → Use Anthropic API Key (high quality, pay-per-token)\n3. **User has both** → Default to OpenAI Codex (free with subscription), fall back to Claude\n4. **User has neither** → Guide them to get ChatGPT Plus ($20/mo) or a free-tier API key\n\n⚠️ **Anti-Patterns — Do NOT:**\n- Attempt to bridge Claude Pro/Max subscription via OAuth (Anthropic will block it)\n- Attempt to bridge Google Gemini subscription via OAuth (Google will permanently ban the account)\n- Hardcode provider-specific API calls in the target app (use ai-sub-auth's unified interface)\n- Store tokens outside the module's TokenStore (security risk)\n\n---\n\n## Quick Reference\n\n| File | Purpose |\n|------|---------|\n| `ai_sub_auth/facade.py` | **AI Facade** — auto-detects subscription, recommended entry point |\n| `ai_sub_auth/providers.py` | Provider registry — add new providers here |\n| `ai_sub_auth/oauth_flow.py` | OAuth PKCE login + auto token refresh |\n| `ai_sub_auth/token_store.py` | Secure token storage (~/.ai-sub-auth/tokens/) |\n| `ai_sub_auth/api_client.py` | Unified LLMClient — routes to correct API |\n| `ai_sub_auth/models.py` | Data models: OAuthToken, ProviderConfig, LLMResponse |\n| `ai_sub_auth/exceptions.py` | AuthError, TokenExpiredError, LoginRequiredError |\n\n---\n\n## Meta Skill Framework\n\nWhen integrating AI into any application, every useful AI feature is a composition of exactly **8 meta skills**:\n\n```\nSkill Direction What it does\n───────── ───────────── ─────────────────────────────────────────\nSUMMARIZE many → few Reduce volume while preserving meaning\nGENERATE few → many Produce new content from intent or spec\nANALYZE raw → insight Find patterns, anomalies, trends in data\nTRANSFORM form A → form B Convert between formats, styles, languages\nCLASSIFY items → buckets Assign categories, priorities, or labels\nEVALUATE content → score Judge quality against criteria\nCONVERSE user ↔ AI Multi-turn contextual dialogue\nEXTRACT noise → signal Pull structured data from unstructured input\n```\n\n### When to apply each skill\n\n| Skill | Trigger signals in the target app |\n|-------|----------------------------------|\n| SUMMARIZE | Has collections of text (notes, emails, logs, threads, history) |\n| GENERATE | Has \"create/new\" buttons, blank editors, templates, boilerplate |\n| ANALYZE | Has charts, tables, dashboards, numerical/time-series data |\n| TRANSFORM | Has import/export, format conversion, audience adaptation |\n| CLASSIFY | Has inbox/queue/feed, manual tagging, predefined categories |\n| EVALUATE | Has submissions, reviews, quality checks, rubrics, checklists |\n| CONVERSE | Has help section, complex workflows, onboarding, Q&A needs |\n| EXTRACT | Has manual data entry, forms, paste-from-external, uploads |\n\n---\n\n## 3-Suggestion Protocol\n\nWhen you encounter a new application, follow this protocol to suggest AI integrations:\n\n### Step 1: SCAN — Build an App Profile\n\nExamine in order: README → directory structure → routes/endpoints → data models → UI entry points.\n\nProduce:\n```\ndomain: [e.g., \"education\", \"finance\", \"devtools\", \"personal\"]\nverbs: [what the app DOES — \"create tasks\", \"send emails\", \"track expenses\"]\nnouns: [what the app KNOWS — \"notes\", \"transactions\", \"users\", \"documents\"]\nroles: [who uses it — \"admin\", \"user\", \"viewer\"]\nexisting_ai: [what's already AI-powered, if anything]\n```\n\n### Step 2: MATCH — Score skills against the profile\n\nFor each of the 8 meta skills, check if its trigger signals are present in the app profile. Prioritize skills that are NOT yet implemented (greenfield bonus).\n\n### Step 3: RANK — Select exactly 3\n\nRank by: **Impact (3x)** × **Feasibility (2x)** × **Differentiation (1x)**\n\nHard rules:\n- 3 suggestions, never more, never fewer\n- No two suggestions use the same meta skill\n- At least one must be a **quick win** (< 50 lines to integrate)\n- At least one must be **high ceiling** (transformative if done fully)\n\n### Step 4: PRESENT — Use this template for each suggestion\n\n```\n## Suggestion [1/3]: [SKILL] — [One-line description]\n\n**What it does:** [2-3 sentences, user perspective]\n**Why this app needs it:** [Connect to a specific pain point from SCAN]\n**Integration point:** [Exact file(s) and function(s)]\n**Effort:** [Quick win | Moderate | Deep integration]\n\n**Implementation sketch:**\n1. [Hook: where in the app to add this]\n2. [Service: the ai-sub-auth call pattern]\n3. [UI: how the user triggers and sees it]\n```\n\n### Step 5: IMPLEMENT — Upon user approval\n\n```\n1. AUTH → from ai_sub_auth import LLMClient, PROVIDERS\n2. SERVICE → Create function: input → LLMClient.chat(prompt, system) → parsed output\n3. ROUTE → Wire into app's existing API/endpoint pattern\n4. UI → Add trigger (button/auto/hook) following app's component style\n5. VERIFY → Test auth, test output, test error handling\n```\n\n---\n\n## Integration Patterns by App Category\n\n| Category | Best 3 skills | Example integration |\n|----------|--------------|-------------------|\n| **Notes/PKM** (Obsidian, Logseq) | Summarize, Analyze, Generate | \"Summarize this week's notes\" button |\n| **Dev tools** (terminals, IDEs) | Evaluate, Analyze, Generate | Inline code review on git diff |\n| **Email/Chat** (Thunderbird, Element) | Generate, Summarize, Classify | Draft reply + inbox triage |\n| **CMS/Blog** (Hugo, WordPress) | Generate, Transform, Evaluate | AI first draft + SEO metadata |\n| **Data/Analytics** (Grafana, Metabase) | Analyze, Transform, Generate | Natural language → SQL query |\n| **Personal** (finance, health, calendar) | Analyze, Extract, Generate | Voice → structured expense entry |\n| **System/Infra** (monitoring, CI/CD) | Analyze, Generate, Transform | Log correlation → incident summary |\n\n---\n\n## Implementation Example\n\nHere's a complete example of adding SUMMARIZE to a note-taking app:\n\n```python\n# 1. AUTH — one-time setup\nfrom ai_sub_auth import LLMClient, PROVIDERS, oauth_login\n\n# If using ChatGPT subscription (OAuth):\n# oauth_login(PROVIDERS[\"openai_codex\"]) # first time only\nclient = LLMClient(PROVIDERS[\"openai_codex\"], model=\"openai-codex/gpt-4o\")\n\n# Or if using API key:\n# client = LLMClient(PROVIDERS[\"anthropic\"], api_key=\"sk-...\", model=\"claude-sonnet-4-5-20250514\")\n\n# 2. SERVICE — the AI function\nasync def summarize_notes(notes: list[str], max_points: int = 5) -> dict:\n combined = \"\\n---\\n\".join(notes)\n resp = await client.chat(\n message=combined,\n system=f\"Summarize these {len(notes)} notes into {max_points} key points. \"\n f\"Output JSON: {{\\\"points\\\": [\\\"...\\\"], \\\"action_items\\\": [\\\"...\\\"]}}\",\n )\n import json\n return json.loads(resp.content)\n\n# 3. ROUTE — hook into your app's API\n# @app.post(\"/api/ai/summarize\")\n# async def api_summarize(request): ...\n\n# 4. UI — add a button\n# <button onClick={summarize}>✨ Summarize</button>\n```\n\n### TRANSFORM Example: Adding translation to a messaging app\n\n```python\n# 1. AUTH — one-time setup\nfrom ai_sub_auth import LLMClient, PROVIDERS, oauth_login\n\n# Using ChatGPT subscription (zero cost for the user):\n# oauth_login(PROVIDERS[\"openai_codex\"]) # first time only\nclient = LLMClient(PROVIDERS[\"openai_codex\"], model=\"openai-codex/gpt-4o\")\n\n# 2. SERVICE — the AI function\nasync def translate_message(text: str, source_lang: str, target_lang: str) -> dict:\n resp = await client.chat(\n message=text,\n system=(\n f\"Translate the following from {source_lang} to {target_lang}. \"\n f\"Preserve tone, formatting, and any embedded links. \"\n f'Output JSON: {{\"translation\": \"...\", \"detected_lang\": \"...\", \"confidence\": 0.0-1.0}}'\n ),\n )\n import json\n return json.loads(resp.content)\n\n# 3. ROUTE — hook into your messaging app's API\nfrom fastapi import APIRouter\nrouter = APIRouter()\n\n@router.post(\"/api/ai/translate\")\nasync def api_translate(request: dict):\n result = await translate_message(\n text=request[\"text\"],\n source_lang=request.get(\"source_lang\", \"auto\"),\n target_lang=request[\"target_lang\"],\n )\n return result\n\n# 4. UI — add inline translate button on each message\n# <button onClick={() => translate(msg.id, userLang)}>🌐 Translate</button>\n# Shows translated text below original, with \"Translated from {detected_lang}\" label\n```\n\n### EXTRACT Example: Structured data extraction from documents\n\n```python\n# 1. AUTH — one-time setup\nfrom ai_sub_auth import LLMClient, PROVIDERS, oauth_login\n\n# Using ChatGPT subscription:\n# oauth_login(PROVIDERS[\"openai_codex\"]) # first time only\nclient = LLMClient(PROVIDERS[\"openai_codex\"], model=\"openai-codex/gpt-4o\")\n\n# Or using Claude API key for higher extraction accuracy:\n# client = LLMClient(PROVIDERS[\"anthropic\"], api_key=\"sk-...\", model=\"claude-sonnet-4-5-20250514\")\n\n# 2. SERVICE — the AI function\nasync def extract_invoice_data(raw_text: str) -> dict:\n resp = await client.chat(\n message=raw_text,\n system=(\n \"Extract structured data from this invoice/receipt. \"\n \"Output JSON: {\"\n '\"vendor\": \"...\", \"date\": \"YYYY-MM-DD\", \"currency\": \"...\", '\n '\"total\": 0.00, \"tax\": 0.00, \"subtotal\": 0.00, '\n '\"line_items\": [{\"description\": \"...\", \"qty\": 1, \"unit_price\": 0.00, \"amount\": 0.00}]'\n \"}\"\n \" If a field is not found, use null.\"\n ),\n )\n import json\n return json.loads(resp.content)\n\n# 3. ROUTE — hook into your document management app's API\nfrom fastapi import APIRouter, UploadFile\nrouter = APIRouter()\n\n@router.post(\"/api/ai/extract-invoice\")\nasync def api_extract_invoice(file: UploadFile):\n raw_text = (await file.read()).decode(\"utf-8\") # or use OCR for images\n result = await extract_invoice_data(raw_text)\n return result\n\n# 4. UI — add extract button on document upload\n# <button onClick={() => extractData(doc.id)}>📋 Extract Data</button>\n# Pre-fills form fields with extracted values; user reviews and confirms\n```\n\n---\n\n## Principles\n\n1. **Eight is enough.** Every AI feature maps to one of the 8 skills. Don't invent a ninth — it's a composition.\n2. **Skills are verbs, not features.** \"Summarize\" is a skill. \"Email summary\" is a feature = skill + context.\n3. **Three suggestions, never more.** Fewer forces prioritization. More creates paralysis.\n4. **Quick-win plus high-ceiling.** Build trust with a fast win, then go deep.\n5. **Follow the host.** Mirror the target app's conventions for auth, routing, and UI. Be a guest, not an invader.\n6. **Auth is first, not last.** Every AI feature goes through ai-sub-auth from step 1.\n7. **Subscription-first.** Prefer OAuth subscription bridge (ChatGPT Plus) over API keys when available. It's zero extra cost for the user.\n"}, "5095f6781d517b62fba873e30397a70e44c9b373": {"t": 1785770836.3327777, "n": 7591, "h": "5189260059628372", "c": "# Agent Integration Guide\n\n> **For AI Agents**: Read this file to understand how to integrate `ai-sub-auth` into any application.\n> This file is designed to be consumed by Claude Code, OpenClaw, Cursor, Copilot, or any agentic coding tool.\n\n## What is ai-sub-auth?\n\nA lightweight Python module (~500 LOC, only depends on `httpx`) that authenticates against AI providers using existing user subscriptions. It handles OAuth PKCE (OpenAI Codex), API keys (Claude, Gemini, DeepSeek), and device code (GitHub Copilot) — all through a unified `LLMClient` interface.\n\n**3-line integration:**\n```python\nfrom ai_sub_auth import LLMClient, PROVIDERS\nclient = LLMClient(PROVIDERS[\"openai_codex\"], model=\"openai-codex/gpt-4o\")\nresp = await client.chat(\"your prompt here\", system=\"your system prompt\")\n```\n\n## Quick Reference\n\n| File | Purpose |\n|------|---------|\n| `ai_sub_auth/providers.py` | Provider registry — add new providers here |\n| `ai_sub_auth/oauth_flow.py` | OAuth PKCE login + auto token refresh |\n| `ai_sub_auth/token_store.py` | Secure token storage (~/.ai-sub-auth/tokens/) |\n| `ai_sub_auth/api_client.py` | Unified LLMClient — routes to correct API |\n| `ai_sub_auth/models.py` | Data models: OAuthToken, ProviderConfig, LLMResponse |\n| `ai_sub_auth/exceptions.py` | AuthError, TokenExpiredError, LoginRequiredError |\n\n---\n\n## Meta Skill Framework\n\nWhen integrating AI into any application, every useful AI feature is a composition of exactly **8 meta skills**:\n\n```\nSkill Direction What it does\n───────── ───────────── ─────────────────────────────────────────\nSUMMARIZE many → few Reduce volume while preserving meaning\nGENERATE few → many Produce new content from intent or spec\nANALYZE raw → insight Find patterns, anomalies, trends in data\nTRANSFORM form A → form B Convert between formats, styles, languages\nCLASSIFY items → buckets Assign categories, priorities, or labels\nEVALUATE content → score Judge quality against criteria\nCONVERSE user ↔ AI Multi-turn contextual dialogue\nEXTRACT noise → signal Pull structured data from unstructured input\n```\n\n### When to apply each skill\n\n| Skill | Trigger signals in the target app |\n|-------|----------------------------------|\n| SUMMARIZE | Has collections of text (notes, emails, logs, threads, history) |\n| GENERATE | Has \"create/new\" buttons, blank editors, templates, boilerplate |\n| ANALYZE | Has charts, tables, dashboards, numerical/time-series data |\n| TRANSFORM | Has import/export, format conversion, audience adaptation |\n| CLASSIFY | Has inbox/queue/feed, manual tagging, predefined categories |\n| EVALUATE | Has submissions, reviews, quality checks, rubrics, checklists |\n| CONVERSE | Has help section, complex workflows, onboarding, Q&A needs |\n| EXTRACT | Has manual data entry, forms, paste-from-external, uploads |\n\n---\n\n## 3-Suggestion Protocol\n\nWhen you encounter a new application, follow this protocol to suggest AI integrations:\n\n### Step 1: SCAN — Build an App Profile\n\nExamine in order: README → directory structure → routes/endpoints → data models → UI entry points.\n\nProduce:\n```\ndomain: [e.g., \"education\", \"finance\", \"devtools\", \"personal\"]\nverbs: [what the app DOES — \"create tasks\", \"send emails\", \"track expenses\"]\nnouns: [what the app KNOWS — \"notes\", \"transactions\", \"users\", \"documents\"]\nroles: [who uses it — \"admin\", \"user\", \"viewer\"]\nexisting_ai: [what's already AI-powered, if anything]\n```\n\n### Step 2: MATCH — Score skills against the profile\n\nFor each of the 8 meta skills, check if its trigger signals are present in the app profile. Prioritize skills that are NOT yet implemented (greenfield bonus).\n\n### Step 3: RANK — Select exactly 3\n\nRank by: **Impact (3x)** × **Feasibility (2x)** × **Differentiation (1x)**\n\nHard rules:\n- 3 suggestions, never more, never fewer\n- No two suggestions use the same meta skill\n- At least one must be a **quick win** (< 50 lines to integrate)\n- At least one must be **high ceiling** (transformative if done fully)\n\n### Step 4: PRESENT — Use this template for each suggestion\n\n```\n## Suggestion [1/3]: [SKILL] — [One-line description]\n\n**What it does:** [2-3 sentences, user perspective]\n**Why this app needs it:** [Connect to a specific pain point from SCAN]\n**Integration point:** [Exact file(s) and function(s)]\n**Effort:** [Quick win | Moderate | Deep integration]\n\n**Implementation sketch:**\n1. [Hook: where in the app to add this]\n2. [Service: the ai-sub-auth call pattern]\n3. [UI: how the user triggers and sees it]\n```\n\n### Step 5: IMPLEMENT — Upon user approval\n\n```\n1. AUTH → from ai_sub_auth import LLMClient, PROVIDERS\n2. SERVICE → Create function: input → LLMClient.chat(prompt, system) → parsed output\n3. ROUTE → Wire into app's existing API/endpoint pattern\n4. UI → Add trigger (button/auto/hook) following app's component style\n5. VERIFY → Test auth, test output, test error handling\n```\n\n---\n\n## Integration Patterns by App Category\n\n| Category | Best 3 skills | Example integration |\n|----------|--------------|-------------------|\n| **Notes/PKM** (Obsidian, Logseq) | Summarize, Analyze, Generate | \"Summarize this week's notes\" button |\n| **Dev tools** (terminals, IDEs) | Evaluate, Analyze, Generate | Inline code review on git diff |\n| **Email/Chat** (Thunderbird, Element) | Generate, Summarize, Classify | Draft reply + inbox triage |\n| **CMS/Blog** (Hugo, WordPress) | Generate, Transform, Evaluate | AI first draft + SEO metadata |\n| **Data/Analytics** (Grafana, Metabase) | Analyze, Transform, Generate | Natural language → SQL query |\n| **Personal** (finance, health, calendar) | Analyze, Extract, Generate | Voice → structured expense entry |\n| **System/Infra** (monitoring, CI/CD) | Analyze, Generate, Transform | Log correlation → incident summary |\n\n---\n\n## Implementation Example\n\nHere's a complete example of adding SUMMARIZE to a note-taking app:\n\n```python\n# 1. AUTH — one-time setup\nfrom ai_sub_auth import LLMClient, PROVIDERS, oauth_login\n\n# If using ChatGPT subscription (OAuth):\n# oauth_login(PROVIDERS[\"openai_codex\"]) # first time only\nclient = LLMClient(PROVIDERS[\"openai_codex\"], model=\"openai-codex/gpt-4o\")\n\n# Or if using API key:\n# client = LLMClient(PROVIDERS[\"anthropic\"], api_key=\"sk-...\", model=\"claude-sonnet-4-5-20250514\")\n\n# 2. SERVICE — the AI function\nasync def summarize_notes(notes: list[str], max_points: int = 5) -> dict:\n combined = \"\\n---\\n\".join(notes)\n resp = await client.chat(\n message=combined,\n system=f\"Summarize these {len(notes)} notes into {max_points} key points. \"\n f\"Output JSON: {{\\\"points\\\": [\\\"...\\\"], \\\"action_items\\\": [\\\"...\\\"]}}\",\n )\n import json\n return json.loads(resp.content)\n\n# 3. ROUTE — hook into your app's API\n# @app.post(\"/api/ai/summarize\")\n# async def api_summarize(request): ...\n\n# 4. UI — add a button\n# <button onClick={summarize}>✨ Summarize</button>\n```\n\n---\n\n## Principles\n\n1. **Eight is enough.** Every AI feature maps to one of the 8 skills. Don't invent a ninth — it's a composition.\n2. **Skills are verbs, not features.** \"Summarize\" is a skill. \"Email summary\" is a feature = skill + context.\n3. **Three suggestions, never more.** Fewer forces prioritization. More creates paralysis.\n4. **Quick-win plus high-ceiling.** Build trust with a fast win, then go deep.\n5. **Follow the host.** Mirror the target app's conventions for auth, routing, and UI. Be a guest, not an invader.\n6. **Auth is first, not last.** Every AI feature goes through ai-sub-auth from step 1.\n"}}}}