Chat de IA con streaming, prompts versionados, tool calling y registro de uso y coste; modelo por env
Código11 archivosContexto~668 tokensescaneo superado
Instalar
$
genpm add @core/aiQué obtienes
- Código en src/lib/ai/, 11 archivos. (12,9 kB)
- Reglas de IA en src/lib/ai/AGENTS.md, más archivos de reglas para tu IDE.
- Variables añadidas a .env.example: AI_MODEL, AI_PROVIDER_API_KEY.
- Resuelve @core/db por ti.
README
Este paquete no tiene README.
~668 tokens→ src/lib/ai/AGENTS.md→ .cursor/rules/genpm-core-ai.mdc
Esto es exactamente lo que lee tu IA cuando trabaja en src/lib/ai. No se añade nada más a su contexto.
@core/ai — rules for AI agents
Purpose
Streaming chat endpoint on the Vercel AI SDK, with versioned system prompts, a tool-calling scaffold and per-response
usage logging (tokens and cost) in the database. Provider and model come from env: nothing is hardcoded. No RAG,
embeddings or chat history storage (store UIMessage[] yourself if you need it).
Map
index.ts— public API:streamChat,getModel,setModel,recordUsage,prompts,tools,PRICES.prompts.ts— your config: system prompts withversion. Bumpversionwhenever you change a prompt.tools.ts— your config: tools the model can call (zodinputSchema+ server-sideexecute).prices.ts— your config: USD per million tokens perAI_MODEL, for cost logging.schema.ts—ai_usagetable. Depends on../db(@core/db).adapters/hono.ts,adapters/next.ts—POST /ai/chatreturning a UI message stream foruseChat.
Integration
- Requires Node 22+ (AI SDK 7). Env:
AI_MODELas<provider>:<model-id>plusAI_PROVIDER_API_KEY, and install that provider package:anthropic→@ai-sdk/anthropic,openai→@ai-sdk/openai, alsogoogle,mistral,groq,xai. OrAI_MODEL=<provider>/<model-id>withAI_GATEWAY_API_KEY(Vercel AI Gateway, no extra package). Ask the user which provider and model to use; do not pick one for them. - Generate and apply migrations (see
src/lib/db/AGENTS.md). - Hono:
app.route('/ai', aiRoutes({ getUserId: (c) => c.get('user')?.id, requireUser: true }))after@core/auth'ssessionMiddleware(omit both options without auth). Next.js:app/api/ai/chat/route.ts→export const POST = chatRoute({ getUserId, requireUser: true }). Delete the adapter of the framework you don't use. - Frontend:
useChat({ transport: new DefaultChatTransport({ api: '/ai/chat' }) })from@ai-sdk/react. - Verify:
curl -N -X POST localhost:3000/ai/chat -H 'content-type: application/json' -d '{"messages":[{"id":"1","role":"user","parts":[{"type":"text","text":"hi"}]}]}'.
Conventions
- One prompt per use case in
prompts.ts; pass it withstreamChat({ prompt: 'assistant', … }). - Tools authorize inside
executeusing the user id; never trust ids sent by the model. - Query
ai_usagefor quotas (e.g. tokens per user per day) before callingstreamChat. - Tests:
setModel(new MockLanguageModelV4(...))fromai/test.
Don't
- Don't hardcode a model or API key, and don't call the provider from the browser.
- Don't log prompts or completions with user data in production.
- Don't let tools run destructive actions without an explicit user confirmation step.
# @core/ai — rules for AI agents
## Purpose
Streaming chat endpoint on the Vercel AI SDK, with versioned system prompts, a tool-calling scaffold and per-response
usage logging (tokens and cost) in the database. Provider and model come from env: nothing is hardcoded. No RAG,
embeddings or chat history storage (store `UIMessage[]` yourself if you need it).
## Map
- `index.ts` — public API: `streamChat`, `getModel`, `setModel`, `recordUsage`, `prompts`, `tools`, `PRICES`.
- `prompts.ts` — **your config**: system prompts with `version`. Bump `version` whenever you change a prompt.
- `tools.ts` — **your config**: tools the model can call (zod `inputSchema` + server-side `execute`).
- `prices.ts` — **your config**: USD per million tokens per `AI_MODEL`, for cost logging.
- `schema.ts` — `ai_usage` table. Depends on `../db` (@core/db).
- `adapters/hono.ts`, `adapters/next.ts` — `POST /ai/chat` returning a UI message stream for `useChat`.
## Integration
1. Requires Node 22+ (AI SDK 7). Env: `AI_MODEL` as `<provider>:<model-id>` plus `AI_PROVIDER_API_KEY`, and install
that provider package: `anthropic` → `@ai-sdk/anthropic`, `openai` → `@ai-sdk/openai`, also `google`, `mistral`,
`groq`, `xai`. Or `AI_MODEL=<provider>/<model-id>` with `AI_GATEWAY_API_KEY` (Vercel AI Gateway, no extra package).
Ask the user which provider and model to use; do not pick one for them.
2. Generate and apply migrations (see `src/lib/db/AGENTS.md`).
3. Hono: `app.route('/ai', aiRoutes({ getUserId: (c) => c.get('user')?.id, requireUser: true }))` after
`@core/auth`'s `sessionMiddleware` (omit both options without auth).
Next.js: `app/api/ai/chat/route.ts` → `export const POST = chatRoute({ getUserId, requireUser: true })`.
Delete the adapter of the framework you don't use.
4. Frontend: `useChat({ transport: new DefaultChatTransport({ api: '/ai/chat' }) })` from `@ai-sdk/react`.
5. Verify: `curl -N -X POST localhost:3000/ai/chat -H 'content-type: application/json' -d '{"messages":[{"id":"1","role":"user","parts":[{"type":"text","text":"hi"}]}]}'`.
## Conventions
- One prompt per use case in `prompts.ts`; pass it with `streamChat({ prompt: 'assistant', … })`.
- Tools authorize inside `execute` using the user id; never trust ids sent by the model.
- Query `ai_usage` for quotas (e.g. tokens per user per day) before calling `streamChat`.
- Tests: `setModel(new MockLanguageModelV4(...))` from `ai/test`.
## Don't
- Don't hardcode a model or API key, and don't call the provider from the browser.
- Don't log prompts or completions with user data in production.
- Don't let tools run destructive actions without an explicit user confirmation step.
El árbol exacto que se inyectará, tras aplicar .genpmignore. Anclado a
// Modelo por entorno, nunca fijo en el código:
// AI_MODEL="anthropic:<model-id>" (o "openai:…", "google:…", "mistral:…", "groq:…", "xai:…") + AI_PROVIDER_API_KEY
// e instala el paquete del proveedor (`@ai-sdk/anthropic`, `@ai-sdk/openai`…).
// AI_MODEL="<provider>/<model>" usa el AI Gateway de Vercel (AI_GATEWAY_API_KEY), sin paquete extra.
import type { LanguageModel } from 'ai';
const FACTORIES: Record<string, { pkg: string; fn: string }> = {
anthropic: { pkg: '@ai-sdk/anthropic', fn: 'createAnthropic' },
openai: { pkg: '@ai-sdk/openai', fn: 'createOpenAI' },
google: { pkg: '@ai-sdk/google', fn: 'createGoogleGenerativeAI' },
mistral: { pkg: '@ai-sdk/mistral', fn: 'createMistral' },
groq: { pkg: '@ai-sdk/groq', fn: 'createGroq' },
xai: { pkg: '@ai-sdk/xai', fn: 'createXai' },
};
let override: LanguageModel | null = null;
/** Fija el modelo a mano (tests, o un proveedor que no está en la lista). */
export function setModel(model: LanguageModel | null): void {
override = model;
}
export function modelId(env: NodeJS.ProcessEnv = process.env): string {
if (override) return typeof override === 'string' ? override : `${override.provider}:${override.modelId}`;
const id = env.AI_MODEL;
if (!id) throw new Error('AI_MODEL is not set, e.g. "anthropic:<model-id>" (see src/lib/ai/AGENTS.md)');
return id;
}
export async function getModel(env: NodeJS.ProcessEnv = process.env): Promise<LanguageModel> {
if (override) return override;
const id = modelId(env);
const sep = id.indexOf(':');
if (sep < 0) return id; // "<provider>/<model>" → AI Gateway
const provider = id.slice(0, sep);
const name = id.slice(sep + 1);
const f = FACTORIES[provider];
if (!f) throw new Error(`Unknown AI provider "${provider}". Use one of ${Object.keys(FACTORIES).join(', ')} or setModel().`);
let mod: Record<string, unknown>;
try {
mod = (await import(f.pkg)) as Record<string, unknown>;
} catch {
throw new Error(`Install ${f.pkg} to use AI_MODEL=${id}`);
}
const create = mod[f.fn] as (opts: { apiKey?: string }) => (model: string) => LanguageModel;
return create({ apiKey: env.AI_PROVIDER_API_KEY })(name);
}
Este paquete no declara servidores MCP.
| Versión | Commit | Publicado | Escaneo |
|---|---|---|---|
| 1.0.0 | 5b1e62b | hace 4 horas | ✔ escaneo superado |
- genpm
- @core/db ^1.0.0
- propuesta
- GenPM propone el comando npm y solo lo ejecuta si dices que sí.
- escaneo
- escaneo superado · 0 hallazgos
- commit
- v1.0.0 → 5b1e62b6abcfd9ec65065b64fb87aad6d3a6b23f · verificado tras la descarga
- scripts
- Ninguno. GenPM nunca ejecuta código del paquete.
- licencia
- MIT
- reporte
- ¿Ves algo raro?