@macpaw/ai-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,128 @@
1
+ {
2
+ "name": "@macpaw/ai-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Vercel AI SDK extension layer for AI Gateway with MacPaw and Setapp auth flows",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ "./package.json": "./package.json",
11
+ ".": {
12
+ "import": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "require": {
17
+ "types": "./dist/index.d.cts",
18
+ "default": "./dist/index.cjs"
19
+ }
20
+ },
21
+ "./provider": {
22
+ "import": {
23
+ "types": "./dist/index.d.ts",
24
+ "default": "./dist/index.js"
25
+ },
26
+ "require": {
27
+ "types": "./dist/index.d.cts",
28
+ "default": "./dist/index.cjs"
29
+ }
30
+ },
31
+ "./nestjs": {
32
+ "import": {
33
+ "types": "./dist/nestjs/index.d.ts",
34
+ "default": "./dist/nestjs/index.js"
35
+ },
36
+ "require": {
37
+ "types": "./dist/nestjs/index.d.cts",
38
+ "default": "./dist/nestjs/index.cjs"
39
+ }
40
+ }
41
+ },
42
+ "bin": {
43
+ "macpaw-ai-setup": "./scripts/setup.mjs"
44
+ },
45
+ "files": [
46
+ "dist",
47
+ "README.md",
48
+ "MIGRATION.md",
49
+ "CHANGELOG.md",
50
+ "scripts",
51
+ "templates"
52
+ ],
53
+ "sideEffects": false,
54
+ "engines": {
55
+ "node": ">=18.0.0"
56
+ },
57
+ "publishConfig": {
58
+ "access": "restricted"
59
+ },
60
+ "keywords": [
61
+ "ai",
62
+ "ai-sdk-typescript",
63
+ "ai-sdk",
64
+ "gateway",
65
+ "macpaw",
66
+ "setapp",
67
+ "openai",
68
+ "streaming",
69
+ "sse",
70
+ "typescript",
71
+ "vercel-ai-sdk",
72
+ "nestjs"
73
+ ],
74
+ "license": "MIT",
75
+ "repository": {
76
+ "type": "git",
77
+ "url": "https://github.com/macpaw/ai-sdk-typescript.git"
78
+ },
79
+ "homepage": "https://github.com/macpaw/ai-sdk-typescript#readme",
80
+ "bugs": {
81
+ "url": "https://github.com/macpaw/ai-sdk-typescript/issues"
82
+ },
83
+ "devDependencies": {
84
+ "@ai-sdk/openai": "3.0.49",
85
+ "@ai-sdk/provider": "3.0.8",
86
+ "@eslint/js": "^10.0.1",
87
+ "@nestjs/common": "^11.1.17",
88
+ "@semantic-release/changelog": "^6.0.3",
89
+ "@semantic-release/git": "^10.0.1",
90
+ "@types/node": "^25.5.0",
91
+ "eslint": "^10.1.0",
92
+ "prettier": "^3.8.1",
93
+ "rxjs": "^7.8.2",
94
+ "semantic-release": "^25.0.3",
95
+ "tsup": "^8.5.1",
96
+ "typedoc": "^0.28.18",
97
+ "typescript": "^6.0.2",
98
+ "typescript-eslint": "^8.58.0",
99
+ "@vitest/coverage-v8": "^4.1.2",
100
+ "vitest": "^4.1.2"
101
+ },
102
+ "peerDependencies": {
103
+ "@ai-sdk/openai": "^3.0.0",
104
+ "@nestjs/common": ">=10.0.0"
105
+ },
106
+ "peerDependenciesMeta": {
107
+ "@nestjs/common": {
108
+ "optional": true
109
+ }
110
+ },
111
+ "scripts": {
112
+ "build": "tsup",
113
+ "dev": "tsup --watch",
114
+ "typecheck": "tsc --noEmit",
115
+ "lint": "eslint .",
116
+ "lint:fix": "eslint . --fix",
117
+ "format": "prettier --write .",
118
+ "format:check": "prettier --check .",
119
+ "test": "vitest run",
120
+ "test:watch": "vitest",
121
+ "test:coverage": "vitest run --coverage",
122
+ "docs": "typedoc",
123
+ "docs:watch": "typedoc --watch",
124
+ "size:pack": "npm pack --dry-run",
125
+ "verify:release": "pnpm typecheck && pnpm lint && pnpm test && pnpm build && pnpm size:pack",
126
+ "example:provider": "pnpm build && node examples/vercel-provider.mjs"
127
+ }
128
+ }
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Sets up AI coding assistant integration for the current project.
4
+ * Supports Cursor (skill), Claude Code (CLAUDE.md), and OpenAI Codex (AGENTS.md).
5
+ *
6
+ * Usage:
7
+ * pnpm exec macpaw-ai-setup # set up all three
8
+ * pnpm exec macpaw-ai-setup cursor # Cursor skill only
9
+ * pnpm exec macpaw-ai-setup claude # Claude Code only
10
+ * pnpm exec macpaw-ai-setup codex # OpenAI Codex only
11
+ */
12
+ import { fileURLToPath } from 'node:url';
13
+ import path from 'node:path';
14
+ import fs from 'node:fs';
15
+
16
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
+ const pkgRoot = path.resolve(__dirname, '..');
18
+ const projectRoot = process.cwd();
19
+
20
+ if (fs.realpathSync(pkgRoot) === fs.realpathSync(projectRoot)) {
21
+ console.log('ℹ Running inside the @macpaw/ai-sdk repo itself — nothing to copy.');
22
+ process.exit(0);
23
+ }
24
+
25
+ const tool = process.argv[2]?.toLowerCase();
26
+ const validTools = ['cursor', 'claude', 'codex'];
27
+
28
+ if (tool && !validTools.includes(tool)) {
29
+ console.error(`Unknown tool "${tool}". Valid options: ${validTools.join(', ')} (or omit to set up all).`);
30
+ process.exit(1);
31
+ }
32
+
33
+ const all = !tool;
34
+ const results = [];
35
+
36
+ // --- Cursor Skill ---
37
+ if (all || tool === 'cursor') {
38
+ const packagedCursorSkill = path.join(pkgRoot, 'templates', 'cursor', 'skills', 'integrate-ai-gateway');
39
+ const repoCursorSkill = path.join(pkgRoot, '.cursor', 'skills', 'integrate-ai-gateway');
40
+ const src = fs.existsSync(packagedCursorSkill) ? packagedCursorSkill : repoCursorSkill;
41
+ const destDir = path.join(projectRoot, '.cursor', 'skills');
42
+ const dest = path.join(destDir, 'integrate-ai-gateway');
43
+
44
+ if (!fs.existsSync(src)) {
45
+ results.push('✗ Cursor skill source not found (is @macpaw/ai-sdk installed?)');
46
+ } else {
47
+ fs.mkdirSync(destDir, { recursive: true });
48
+ fs.cpSync(src, dest, { recursive: true });
49
+ results.push('✓ Cursor skill → .cursor/skills/integrate-ai-gateway/');
50
+ }
51
+ }
52
+
53
+ // --- Claude Code (CLAUDE.md) ---
54
+ if (all || tool === 'claude') {
55
+ results.push(copyMarkdownTemplate('CLAUDE.md', 'Claude Code'));
56
+ }
57
+
58
+ // --- OpenAI Codex (AGENTS.md) ---
59
+ if (all || tool === 'codex') {
60
+ results.push(copyMarkdownTemplate('AGENTS.md', 'OpenAI Codex'));
61
+ }
62
+
63
+ console.log('\n @macpaw/ai-sdk — AI Assistant Setup\n');
64
+ results.forEach((r) => console.log(` ${r}`));
65
+ console.log('\n Now ask your AI assistant: "Integrate AI Gateway into this app"\n');
66
+
67
+ // ---------------------------------------------------------------------------
68
+
69
+ function copyMarkdownTemplate(filename, toolName) {
70
+ const src = path.join(pkgRoot, 'templates', filename);
71
+ const dest = path.join(projectRoot, filename);
72
+
73
+ if (!fs.existsSync(src)) {
74
+ return `✗ ${filename} template not found (is @macpaw/ai-sdk installed?)`;
75
+ }
76
+
77
+ const content = fs.readFileSync(src, 'utf8');
78
+
79
+ if (fs.existsSync(dest)) {
80
+ const existing = fs.readFileSync(dest, 'utf8');
81
+ if (existing.includes('@macpaw/ai-sdk')) {
82
+ return `· ${filename} already contains AI Gateway instructions — skipped`;
83
+ }
84
+ fs.appendFileSync(dest, '\n\n' + content);
85
+ return `✓ AI Gateway instructions appended to existing ${filename} (${toolName})`;
86
+ }
87
+
88
+ fs.writeFileSync(dest, content);
89
+ return `✓ ${filename} created (${toolName})`;
90
+ }
@@ -0,0 +1,51 @@
1
+ # @macpaw/ai-sdk — AI Gateway Instructions
2
+
3
+ Apply these rules when integrating MacPaw AI Gateway.
4
+
5
+ ## Use the correct package surface
6
+
7
+ - `@macpaw/ai-sdk`: `createAIGatewayProvider`, `createGatewayProvider`, `createGatewayFetch`, errors, `GatewayProviderSettings`.
8
+ - `@macpaw/ai-sdk/provider`: compatibility alias only.
9
+ - `@macpaw/ai-sdk/nestjs`: NestJS module and decorators.
10
+ - Install `@ai-sdk/openai` when using `createAIGatewayProvider` or `createGatewayProvider`.
11
+ - Never use `createAIGatewayClient`, `@macpaw/ai-sdk/client`, `runtime`, `types`, or `testing`.
12
+
13
+ ## Choose one integration path
14
+
15
+ - NestJS app: use `AIGatewayModule` and `@InjectAIGateway()`.
16
+ - Next.js / Vercel AI SDK app: keep generation on `ai`, replace only the model provider.
17
+ - Raw server or multipart HTTP flow: use `createGatewayFetch`.
18
+ - Existing `openai` / `@ai-sdk/openai` / `@anthropic-ai/sdk` usage: treat as migration.
19
+
20
+ ## Guardrails
21
+
22
+ - Do not invent a token source. Ask once if unclear.
23
+ - Do not place gateway tokens in browser-only code.
24
+ - `env` supports only `'production'`; use `baseURL` for staging/custom hosts.
25
+ - `createGatewayFetch` requires `baseURL`.
26
+ - Remove legacy imports and dependencies only after confirming all usages are migrated.
27
+
28
+ ## Canonical snippets
29
+
30
+ ```ts
31
+ const gateway = createAIGatewayProvider({
32
+ env: 'production',
33
+ getAuthToken: async () => process.env.AI_GATEWAY_TOKEN ?? null,
34
+ });
35
+ ```
36
+
37
+ ```ts
38
+ const gatewayFetch = createGatewayFetch({
39
+ baseURL: process.env.AI_GATEWAY_BASE_URL ?? 'https://api.macpaw.com/ai',
40
+ getAuthToken: async () => process.env.AI_GATEWAY_TOKEN ?? null,
41
+ });
42
+ ```
43
+
44
+ ## Error handling and verification
45
+
46
+ - Use `isAIGatewayError(error)` with `ErrorCode`.
47
+ - Prefer `AIGatewayExceptionFilter` in NestJS.
48
+ - Read available scripts from `package.json` before running checks.
49
+ - Run the relevant subset of `typecheck`, `lint`, `test`, and `build`.
50
+ - Report the chosen path, changed files, token source, checks run, and remaining manual steps.
51
+ - If env variables were added or required, name them explicitly, e.g. `AI_GATEWAY_TOKEN` and `AI_GATEWAY_BASE_URL`.
@@ -0,0 +1,55 @@
1
+ # @macpaw/ai-sdk — AI Gateway Integration
2
+
3
+ Use this guidance when integrating MacPaw AI Gateway into this project.
4
+
5
+ ## Rules
6
+
7
+ - Use `@macpaw/ai-sdk` for `createAIGatewayProvider`, `createGatewayProvider`, `createGatewayFetch`, errors, and `GatewayProviderSettings`.
8
+ - Use `@macpaw/ai-sdk/nestjs` for `AIGatewayModule`, `@InjectAIGateway()`, and `AIGatewayExceptionFilter`.
9
+ - Keep generation primitives on upstream `ai` / `@ai-sdk/*`.
10
+ - Install `@ai-sdk/openai` when using `createAIGatewayProvider` or `createGatewayProvider`; those paths depend on the OpenAI-compatible provider package.
11
+ - Do not use `createAIGatewayClient`, `@macpaw/ai-sdk/client`, `runtime`, `types`, or `testing`; those surfaces do not exist.
12
+
13
+ ## Guardrails
14
+
15
+ - Do not invent a token source. If server-side token retrieval is unclear, ask one concise question.
16
+ - Do not put real gateway tokens in browser-only code.
17
+ - Use `env: 'production'` only for the default MacPaw host. Use `baseURL` for staging or custom hosts.
18
+ - `createGatewayFetch` requires a resolved `baseURL`; do not pass only `env`.
19
+ - Remove old provider dependencies only after verifying there are no remaining usages.
20
+
21
+ ## Preferred paths
22
+
23
+ - NestJS: register `AIGatewayModule.forRoot()` / `forRootAsync()`, inject `GatewayProviderSettings` via `@InjectAIGateway()`, build the provider inside services.
24
+ - Next.js / Vercel AI SDK: keep `generateText`, `streamText`, hooks, and other Vercel APIs on `ai`; swap only the model provider to `createAIGatewayProvider`.
25
+ - Raw server HTTP or multipart: use `createGatewayFetch`.
26
+
27
+ ## Minimal examples
28
+
29
+ ```ts
30
+ const gateway = createAIGatewayProvider({
31
+ env: 'production',
32
+ getAuthToken: async () => process.env.AI_GATEWAY_TOKEN ?? null,
33
+ });
34
+ ```
35
+
36
+ ```ts
37
+ const gatewayFetch = createGatewayFetch({
38
+ baseURL: process.env.AI_GATEWAY_BASE_URL ?? 'https://api.macpaw.com/ai',
39
+ getAuthToken: async () => process.env.AI_GATEWAY_TOKEN ?? null,
40
+ });
41
+ ```
42
+
43
+ ## Error handling
44
+
45
+ - Prefer `isAIGatewayError(error)` and switch on `ErrorCode`.
46
+ - For NestJS, prefer `AIGatewayExceptionFilter`.
47
+ - Billing states are `InsufficientCredits` / `SubscriptionExpired`.
48
+
49
+ ## Verification
50
+
51
+ - Read `package.json` scripts first.
52
+ - Run the relevant subset of `typecheck`, `lint`, `test`, and `build`.
53
+ - Add one focused smoke path when integrating.
54
+ - Report: chosen integration path, files changed, token source, verification run, and any manual env steps left.
55
+ - If env variables were added or required, name them explicitly, e.g. `AI_GATEWAY_TOKEN` and `AI_GATEWAY_BASE_URL`.
@@ -0,0 +1,90 @@
1
+ ---
2
+ name: integrate-ai-gateway
3
+ description: Integrate applications with AI Gateway using @macpaw/ai-sdk. Use for NestJS, Next.js, Vercel AI SDK, raw fetch migrations, MacPaw AI, Setapp AI, createAIGatewayProvider, createGatewayFetch, and AI Gateway auth/error wiring.
4
+ ---
5
+
6
+ # AI Gateway Integration (@macpaw/ai-sdk)
7
+
8
+ ## Goal
9
+
10
+ Detect the app shape, choose one integration path, apply the smallest correct patch, add safe auth/error handling, run verification, and report exact changes.
11
+
12
+ ## Package surface
13
+
14
+ - Use `@macpaw/ai-sdk` for `createAIGatewayProvider`, `createGatewayProvider`, `createGatewayFetch`, `GATEWAY_PROVIDERS`, errors, and `GatewayProviderSettings`.
15
+ - Use `@macpaw/ai-sdk/provider` only as a compatibility alias.
16
+ - Use `@macpaw/ai-sdk/nestjs` for `AIGatewayModule`, `@InjectAIGateway()`, and `AIGatewayExceptionFilter`.
17
+ - Do not use `createAIGatewayClient`, `@macpaw/ai-sdk/client`, `runtime`, `types`, or `testing`; they do not exist.
18
+
19
+ ## Guardrails
20
+
21
+ - Do not invent a token source. If server-side token retrieval is unclear, ask one question.
22
+ - Do not place real tokens in browser-only code. Frontend-only apps need a backend/BFF token source.
23
+ - Do not remove direct OpenAI/Anthropic paths unless all usages are migrated or the user asked for it.
24
+ - Use `baseURL` for staging/custom hosts. `env` supports only `'production'`.
25
+ - `createGatewayFetch` requires a resolved `baseURL`; do not pass only `env`.
26
+
27
+ ## Choose one path
28
+
29
+ - NestJS markers: `@nestjs/common`, `*.module.ts`, decorators -> use `@macpaw/ai-sdk/nestjs` + `@macpaw/ai-sdk`.
30
+ - Next.js / Vercel markers: `next`, `ai`, `@ai-sdk/*` -> keep generation on `ai`, swap only the model provider.
31
+ - Express/Fastify/Hono/server scripts -> use `createGatewayFetch`, or `ai` + provider if already Vercel-shaped.
32
+ - Existing `openai`, `@ai-sdk/openai`, or `@anthropic-ai/sdk` usage -> treat as migration, not greenfield.
33
+
34
+ ## Canonical patterns
35
+
36
+ ```ts
37
+ // Vercel AI SDK
38
+ const gateway = createAIGatewayProvider({
39
+ env: 'production',
40
+ getAuthToken: async () => process.env.AI_GATEWAY_TOKEN ?? null,
41
+ });
42
+ const result = streamText({ model: gateway('openai/gpt-4o'), messages });
43
+ ```
44
+
45
+ ```ts
46
+ // NestJS
47
+ AIGatewayModule.forRootAsync({
48
+ useFactory: () => ({
49
+ env: 'production',
50
+ getAuthToken: async () => process.env.AI_GATEWAY_TOKEN ?? null,
51
+ }),
52
+ });
53
+ constructor(@InjectAIGateway() private readonly config: GatewayProviderSettings) {}
54
+ ```
55
+
56
+ ```ts
57
+ // Raw fetch / multipart
58
+ const baseURL = process.env.AI_GATEWAY_BASE_URL ?? 'https://api.macpaw.com/ai';
59
+ const gatewayFetch = createGatewayFetch({
60
+ baseURL,
61
+ getAuthToken: async () => process.env.AI_GATEWAY_TOKEN ?? null,
62
+ });
63
+ ```
64
+
65
+ ## Error handling
66
+
67
+ - Prefer `isAIGatewayError(error)` and switch on `ErrorCode`.
68
+ - Use `AIGatewayExceptionFilter` in NestJS.
69
+ - Treat `InsufficientCredits` / `SubscriptionExpired` as the billing states; there is no `PaymentRequired`.
70
+
71
+ ## Migration rules
72
+
73
+ - Keep `generateText`, `streamText`, `embed`, React hooks, and upstream primitives on `ai` / `@ai-sdk/*`.
74
+ - Replace direct gateway-bound provider construction with `createAIGatewayProvider` or `createGatewayProvider`.
75
+ - Replace raw HTTP gateway calls with `createGatewayFetch`.
76
+ - Remove old dependencies only after verifying there are no remaining imports/usages.
77
+
78
+ ## Verification
79
+
80
+ - Read `package.json` scripts before running commands.
81
+ - Prefer `typecheck`, `lint`, `test`, and `build` when available.
82
+ - Add one focused smoke path: provider call, route handler, or `fetch` stub.
83
+ - Do not claim success without reporting which verification commands actually ran.
84
+
85
+ ## Output contract
86
+
87
+ - State the chosen path: NestJS, Vercel, or raw fetch.
88
+ - List files changed.
89
+ - State where the token now comes from.
90
+ - State verification run and any manual env step left.