Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -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 }}
65 changes: 51 additions & 14 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "veryfront",
"version": "0.0.66",
"version": "0.0.67",
Comment on lines 2 to +3

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep npm and deno package versions in sync

Bumping the deno manifest to 0.0.67 while npm/package.json still declares 0.0.66 leaves the npm build advertising the old version; when running the release tasks (deno task build:npm/npm publish) the new AI exports cannot be published because npm will reject re-publishing 0.0.66, so npm consumers will miss the added exports until the npm version is bumped.

Useful? React with 👍 / 👎.

"nodeModulesDir": "auto",
"exclude": [
"npm/",
Expand Down
88 changes: 88 additions & 0 deletions src/ai/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
27 changes: 25 additions & 2 deletions src/ai/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down