diff --git a/skills/xsai/SKILL.md b/skills/xsai/SKILL.md index f86a57f..06d31ed 100644 --- a/skills/xsai/SKILL.md +++ b/skills/xsai/SKILL.md @@ -1,14 +1,16 @@ --- name: xsai -description: Use this skill when the user is building with `xsai` or any `@xsai/*` package, or needs a small OpenAI-compatible runtime for text generation, streaming, tool calling, structured output, embeddings, image generation, speech synthesis, or transcription. +description: Use this skill when the user is building with `xsai` or any `@xsai/*` package, or is evaluating xsAI for a small OpenAI-compatible workflow with text generation, streaming, tool calling, structured output, embeddings, image generation, speech synthesis, or transcription. --- # xsAI -Use this skill for `xsai` code, package selection, API selection, and positioning. +Use this skill for `xsai` code, package selection, API selection, canonical examples, and positioning. ## Use xsAI when +- The user is already using `xsai` or any `@xsai/*` package. +- The user is evaluating xsAI for an OpenAI-compatible integration. - The target API is OpenAI-compatible. - The user wants a small runtime or package footprint. - The user needs text generation, streaming, structured output, or tool calling without a broad framework. @@ -20,15 +22,21 @@ Use this skill for `xsai` code, package selection, API selection, and positionin - The user wants a batteries-included AI application framework. - The task depends on provider-specific APIs that are not exposed through an OpenAI-compatible surface. -## Default guidance +## Default workflow -- Prefer the smallest package that solves the task. Use the umbrella `xsai` package only when the user needs several features at once. +- First inspect the existing dependency and import style in the repo. Preserve `xsai` versus granular `@xsai/*` imports unless the user asks to change them. +- If the user has not chosen xsAI yet, confirm the task fits an OpenAI-compatible surface before recommending it. +- Prefer the smallest package that solves the task. Use the umbrella `xsai` package only when the user needs several features at once or explicitly wants one dependency. +- When writing or editing code, read `references/recipes.md` first and start from the closest canonical example. +- Keep examples minimal and runnable. Include `baseURL` and `model` explicitly. Include `apiKey` for hosted providers; omit it only when the target endpoint truly does not need one. +- Preserve the project's existing schema library and provider wiring unless there is a clear reason to change them. - Keep recommendations aligned with xsAI's scope: OpenAI-compatible, Fetch-based, runtime-portable, and intentionally narrow. - If the user is optimizing for bundle or install size, explicitly prefer granular packages such as `@xsai/generate-text` over `xsai`. - If the user asks for broader provider abstraction, say xsAI intentionally does not optimize for that. -## Package selection +## References +- Read `references/recipes.md` when the user wants code, edits xsAI code, or needs a canonical minimal example. - Read `references/package-selection.md` when the user needs help choosing between `xsai` and granular packages. - Read `references/text-stream-tools.md` for `generateText`, `streamText`, tool calling, and common chat options. - Read `references/structured-output.md` for `generateObject`, `streamObject`, `tool()`, `rawTool()`, or schema guidance. @@ -38,19 +46,22 @@ Use this skill for `xsai` code, package selection, API selection, and positionin ## API selection rules - Use `generateText` for unary text generation. -- Use `streamText` for incremental text, reasoning deltas, or tool events. +- Use `streamText` for incremental text, reasoning deltas, tool events, or lightweight agent loops. - Use `generateObject` for validated structured output. - Use `streamObject` when the user needs incremental object parsing. - Use `tool()` when the user has a Standard Schema library such as Zod or Valibot. - Use `rawTool()` when the user already has raw JSON Schema. +- Use a plain `Tool` object only when the repo already uses that shape or when avoiding `tool()`'s async setup matters. ## Key constraints -- `baseURL` and `model` are required in practice for xsAI calls. +- `baseURL` and `model` are usually required in practice for xsAI calls. +- `apiKey` is provider-dependent. Most hosted providers need it; local or proxy endpoints may not. - xsAI is OpenAI-compatible-first. Do not imply support for non-compatible provider APIs. - `streamText()` returns immediately; callers consume `textStream`, `fullStream`, and result promises asynchronously. - `streamObject()` is async because schema conversion happens before streaming starts. - `maxSteps` controls repeated tool-use loops by issuing additional API calls with tool results appended. +- `generateObject()`, `streamObject()`, and `tool()` rely on `xsschema`; some schema vendors need extra JSON Schema converter packages. - xsAI is designed to stay small. Avoid recommending the umbrella package when a smaller package is enough. ## Positioning diff --git a/skills/xsai/agents/openai.yaml b/skills/xsai/agents/openai.yaml index 171cfc3..9ed67d6 100644 --- a/skills/xsai/agents/openai.yaml +++ b/skills/xsai/agents/openai.yaml @@ -1,7 +1,7 @@ interface: display_name: "xsAI" - short_description: "Use xsAI for lightweight OpenAI-compatible apps" - default_prompt: "Use $xsai to build or explain a small OpenAI-compatible workflow with xsAI." + short_description: "Use xsAI for minimal OpenAI-compatible code" + default_prompt: "Use $xsai to choose the smallest xsAI package and build a runnable OpenAI-compatible example." policy: allow_implicit_invocation: true diff --git a/skills/xsai/references/recipes.md b/skills/xsai/references/recipes.md new file mode 100644 index 0000000..1c7e382 --- /dev/null +++ b/skills/xsai/references/recipes.md @@ -0,0 +1,172 @@ +# Recipes + +Use this reference when the user wants code, when you are editing xsAI code, or when a prompt needs a canonical minimal example. + +## General rules + +- Prefer granular `@xsai/*` imports in new examples. +- Switch to the umbrella `xsai` package only when the repo already uses it or the user explicitly wants one dependency. +- Keep `baseURL` and `model` explicit. +- Include `apiKey` for hosted providers. For local or proxy endpoints, only include it if the target actually requires one. +- Preserve the repo's existing schema library instead of swapping between Zod, Valibot, ArkType, or Effect without a reason. + +## Minimal text generation + +```ts +import { generateText } from '@xsai/generate-text' +import { env } from 'node:process' + +const { text } = await generateText({ + apiKey: env.OPENAI_API_KEY!, + baseURL: 'https://api.openai.com/v1/', + messages: [ + { + content: 'You are a helpful assistant.', + role: 'system', + }, + { + content: 'Write one sentence about the moon.', + role: 'user', + }, + ], + model: 'gpt-4o', +}) +``` + +Use this as the default starting point for simple scripts, tests, and one-shot helpers. + +## Streaming text with tools + +```ts +import { streamText } from '@xsai/stream-text' +import { tool } from '@xsai/tool' +import { env } from 'node:process' +import * as v from 'valibot' + +const add = await tool({ + description: 'Adds two numbers', + execute: ({ a, b }) => (Number.parseInt(a) + Number.parseInt(b)).toString(), + name: 'add', + parameters: v.object({ + a: v.pipe(v.string(), v.description('First number')), + b: v.pipe(v.string(), v.description('Second number')), + }), +}) + +const { fullStream } = streamText({ + apiKey: env.OPENAI_API_KEY!, + baseURL: 'https://api.openai.com/v1/', + maxSteps: 2, + messages: [ + { + content: 'You are a helpful assistant.', + role: 'system', + }, + { + content: 'What is 12 plus 30? Use the add tool.', + role: 'user', + }, + ], + model: 'gpt-4o', + toolChoice: 'required', + tools: [add], +}) + +const text: string[] = [] + +for await (const event of fullStream) { + if (event.type === 'text-delta') { + text.push(event.text) + } + + if (event.type === 'tool-call' || event.type === 'tool-result') { + console.log(event) + } +} + +console.log(text.join('')) +``` + +Use `textStream` for plain live text. Use `fullStream` when the caller needs tool events, reasoning deltas, or finish metadata. + +## Validated structured output + +Valibot examples require `@valibot/to-json-schema` in the project. If the repo already uses a different supported schema library, keep that choice. + +```ts +import { generateObject } from '@xsai/generate-object' +import { env } from 'node:process' +import * as v from 'valibot' + +const { object } = await generateObject({ + apiKey: env.OPENAI_API_KEY!, + baseURL: 'https://api.openai.com/v1/', + messages: [ + { + content: 'Extract the event information.', + role: 'system', + }, + { + content: 'Alice and Bob are going to a science fair on Friday.', + role: 'user', + }, + ], + model: 'gpt-4o', + schema: v.object({ + date: v.string(), + name: v.string(), + participants: v.array(v.string()), + }), +}) +``` + +Prefer this over asking the model for free-form JSON. + +## Streaming structured output + +```ts +import { streamObject } from '@xsai/stream-object' +import { env } from 'node:process' +import * as v from 'valibot' + +const { partialObjectStream } = await streamObject({ + apiKey: env.OPENAI_API_KEY!, + baseURL: 'https://api.openai.com/v1/', + messages: [ + { + content: 'Extract the event information.', + role: 'system', + }, + { + content: 'Alice and Bob are going to a science fair on Friday.', + role: 'user', + }, + ], + model: 'gpt-4o', + schema: v.object({ + date: v.string(), + name: v.string(), + participants: v.array(v.string()), + }), +}) + +for await (const partialObject of partialObjectStream) { + console.log(partialObject) +} +``` + +Use object mode for partial updates and `output: 'array'` with `elementStream` when the caller needs item-by-item results. + +## Embeddings + +```ts +import { embed } from '@xsai/embed' + +const { embedding, usage } = await embed({ + baseURL: 'http://localhost:11434/v1/', + input: 'sunny day at the beach', + model: 'all-minilm', +}) +``` + +Use `embedMany` for batch inputs with the same provider and model. diff --git a/skills/xsai/references/structured-output.md b/skills/xsai/references/structured-output.md index 78dd3de..08c6dd2 100644 --- a/skills/xsai/references/structured-output.md +++ b/skills/xsai/references/structured-output.md @@ -19,6 +19,10 @@ xsAI supports Standard Schema style libraries through `xsschema`, including: - Effect Use these when the user wants typed structured output. +Some schema vendors need an extra JSON Schema converter package in the project: + +- Zod v3: `zod-to-json-schema` +- Valibot: `@valibot/to-json-schema` ## `generateObject`