diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000000..decb9b3b95 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,67 @@ +name: Publish to npm + +on: + push: + tags: + - 'v*' # Trigger on version tags like v0.0.67, v1.0.0 + +jobs: + publish: + runs-on: ubuntu-latest + + steps: + - name: Clone repository + uses: actions/checkout@v4 + + - name: Validate tag matches deno.json version + run: | + TAG_VERSION="${GITHUB_REF#refs/tags/v}" + DENO_VERSION=$(jq -r '.version' deno.json) + + if [ "$TAG_VERSION" != "$DENO_VERSION" ]; then + echo "Error: Tag version ($TAG_VERSION) doesn't match deno.json version ($DENO_VERSION)" + echo "Please ensure deno.json version is updated before tagging." + exit 1 + fi + + echo "Version validated: $TAG_VERSION" + + - name: Setup Deno + uses: denoland/setup-deno@v2 + with: + deno-version: lts + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + registry-url: 'https://registry.npmjs.org' + + - name: Build npm package + run: deno task build:npm + + - name: Verify package version + working-directory: npm + run: | + PKG_VERSION=$(jq -r '.version' package.json) + TAG_VERSION="${GITHUB_REF#refs/tags/v}" + + if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then + echo "Error: Built package version ($PKG_VERSION) doesn't match tag ($TAG_VERSION)" + exit 1 + fi + + echo "Package version verified: $PKG_VERSION" + + - name: Publish to npm + working-directory: npm + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + with: + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ec153e48d..2383262a34 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -336,17 +336,28 @@ Brief description of changes ## Release Process -We use an automated script to handle versioning, testing, building, and publishing. +Releases are automated via GitHub Actions. When you push a version tag, CI automatically builds and publishes to npm. -### Prerequisites +### Quick Release + +```bash +# 1. Update version in deno.json (e.g., "version": "0.0.68") +# 2. Commit and merge to main +# 3. Create and push tag: +git checkout main && git pull +git tag v0.0.68 +git push origin v0.0.68 +``` -- Ensure you are on the `main` branch. -- Ensure your working directory is clean. -- Ensure you have `npm` authenticated (if publishing). +CI will automatically: +- Validate tag matches `deno.json` version +- Build the npm package (`deno task build:npm`) +- Publish to npm +- Create a GitHub Release with auto-generated notes -### Creating a Release +### Using the Release Script (Alternative) -Use the `release` task to create a new version: +For a guided release process, use the release task: ```bash # Patch release (0.0.1 -> 0.0.2) @@ -362,21 +373,47 @@ deno task release major deno task release 1.2.3 ``` -### What the script does - -1. **Runs Tests**: Executes `deno task test` to ensure stability. -2. **Updates Version**: Bumps the version in `deno.json`. -3. **Builds Package**: Runs `deno task build:npm` to generate the npm package. -4. **Publishes**: Prompts to publish to npm (optional). +The script will: +1. Run tests to ensure stability +2. Update the version in `deno.json` +3. Build the npm package +4. Prompt to publish (or you can push the tag for CI to publish) ### Dry Run -You can preview the release process without making changes: +Preview the release process without making changes: ```bash deno task release patch --dry-run ``` +### Version Numbering + +We follow [Semantic Versioning](https://semver.org/): +- **Patch** (0.0.x): Bug fixes, documentation updates +- **Minor** (0.x.0): New features, backward-compatible changes +- **Major** (x.0.0): Breaking changes + +### CI/CD Pipeline + +| Trigger | Workflow | Action | +|---------|----------|--------| +| PR to main | `ci.yml` | Runs tests, lint, typecheck | +| Push to main | `ci.yml` | Runs tests | +| Push tag `v*` | `publish.yml` | Builds and publishes to npm | + +### Troubleshooting + +**Tag doesn't match deno.json version:** +``` +Error: Tag version (0.0.68) doesn't match deno.json version (0.0.67) +``` +Fix: Update `deno.json` version before creating the tag. + +**npm publish fails:** +- Check that `NPM_TOKEN` secret is set in GitHub repository settings +- Verify the token has publish permissions + ## Module Guidelines ### Adding a New Module diff --git a/deno.json b/deno.json index 51264af515..3f5667b55e 100644 --- a/deno.json +++ b/deno.json @@ -1,6 +1,6 @@ { "name": "veryfront", - "version": "0.0.66", + "version": "0.0.67", "nodeModulesDir": "auto", "exclude": [ "npm/", diff --git a/src/ai/README.md b/src/ai/README.md index 14f82550bc..03e99efe39 100644 --- a/src/ai/README.md +++ b/src/ai/README.md @@ -104,6 +104,42 @@ ai/ ### AI SDK Integration +#### Re-exported Core Functions + +These functions are re-exported from the `ai` package for convenience: + +| Export | Description | +|--------|-------------| +| `generateText` | Generate text from a model | +| `streamText` | Stream text generation | +| `generateObject` | Generate structured objects | +| `streamObject` | Stream structured object generation | +| `convertToModelMessages` | Convert UI messages to model-compatible format | +| `embed` | Generate single embeddings | +| `embedMany` | Batch embedding generation | +| `aiTool` | AI SDK's type-safe tool helper (renamed from `tool` to avoid conflict with veryfront's `tool`) | +| `createIdGenerator` | Generate consistent message IDs | +| `smoothStream` | Smooth streaming output | +| `cosineSimilarity` | Vector similarity calculations | + +#### Experimental Functions + +| Export | Description | +|--------|-------------| +| `experimental_generateImage` | Image generation | +| `experimental_transcribe` | Audio to text transcription | +| `experimental_generateSpeech` | Text to speech generation | +| `experimental_createMCPClient` | MCP server connection client | + +#### Provider Re-exports + +| Export | Description | +|--------|-------------| +| `openai` | OpenAI provider from `@ai-sdk/openai` | +| `anthropic` | Anthropic provider from `@ai-sdk/anthropic` | + +#### Adapter Utilities + - `useAISDK()` - Use AI SDK with Veryfront - `aiSDKModel(provider, model)` - Create AI SDK model - `toAISDKTools(tools)` - Convert Veryfront tools to AI SDK @@ -253,6 +289,58 @@ const server = createMCPServer({ await server.listen({ port: 3100 }); ``` +### Using AI SDK Re-exports + +```typescript +import { + streamText, + convertToModelMessages, + openai, + aiTool, + cosineSimilarity, +} from "veryfront/ai"; +import { z } from "zod"; + +// Use AI SDK's streamText directly +export async function POST(req: Request) { + const { messages } = await req.json(); + + const result = streamText({ + model: openai("gpt-4o"), + messages: convertToModelMessages(messages), + tools: { + weather: aiTool({ + description: "Get the weather for a location", + parameters: z.object({ + location: z.string().describe("The location to get weather for"), + }), + execute: async ({ location }) => { + return { temperature: 72, condition: "sunny", location }; + }, + }), + }, + }); + + return result.toDataStreamResponse(); +} + +// Use embeddings and similarity +import { embed, embedMany } from "veryfront/ai"; + +const { embedding } = await embed({ + model: openai.embedding("text-embedding-3-small"), + value: "What is the meaning of life?", +}); + +const { embeddings } = await embedMany({ + model: openai.embedding("text-embedding-3-small"), + values: ["Hello world", "Goodbye world"], +}); + +// Calculate similarity between embeddings +const similarity = cosineSimilarity(embedding, embeddings[0]); +``` + ### React Integration ```typescript diff --git a/src/ai/index.ts b/src/ai/index.ts index 200adf3609..f0fde5583e 100644 --- a/src/ai/index.ts +++ b/src/ai/index.ts @@ -146,8 +146,31 @@ export { createMCPServer, MCPServer } from "./mcp/server.ts"; // import { useChat, useCompletion } from "veryfront/ai/client"; // This prevents server-side bundling issues -// Re-export AI SDK core -export { generateObject, generateText, streamText } from "ai"; +// Re-export AI SDK core functions +// - Text generation: generateText, streamText +// - Structured data: generateObject, streamObject +// - Message conversion: convertToModelMessages +// - Embeddings: embed, embedMany +// - Utilities: createIdGenerator, smoothStream, cosineSimilarity +// - Tool helper: aiTool (renamed from 'tool' to avoid conflict with veryfront's tool) +// - Experimental: experimental_generateImage, experimental_generateSpeech, experimental_transcribe, experimental_createMCPClient +export { + convertToModelMessages, + cosineSimilarity, + createIdGenerator, + embed, + embedMany, + experimental_createMCPClient, + experimental_generateImage, + experimental_generateSpeech, + experimental_transcribe, + generateObject, + generateText, + smoothStream, + streamObject, + streamText, + tool as aiTool, +} from "ai"; // Re-export AI SDK providers (30+ providers available) export { openai } from "@ai-sdk/openai";