@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/CHANGELOG.md +39 -0
- package/LICENSE +21 -0
- package/MIGRATION.md +52 -0
- package/README.md +272 -0
- package/dist/chunk-KGOVQRMH.js +287 -0
- package/dist/chunk-KGOVQRMH.js.map +1 -0
- package/dist/chunk-N26BDEG5.cjs +302 -0
- package/dist/chunk-N26BDEG5.cjs.map +1 -0
- package/dist/gateway-errors-DdgDIyQw.d.cts +181 -0
- package/dist/gateway-errors-DdgDIyQw.d.ts +181 -0
- package/dist/index.cjs +483 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +109 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.js +438 -0
- package/dist/index.js.map +1 -0
- package/dist/nestjs/index.cjs +149 -0
- package/dist/nestjs/index.cjs.map +1 -0
- package/dist/nestjs/index.d.cts +117 -0
- package/dist/nestjs/index.d.ts +117 -0
- package/dist/nestjs/index.js +145 -0
- package/dist/nestjs/index.js.map +1 -0
- package/package.json +128 -0
- package/scripts/setup.mjs +90 -0
- package/templates/AGENTS.md +51 -0
- package/templates/CLAUDE.md +55 -0
- package/templates/cursor/skills/integrate-ai-gateway/SKILL.md +90 -0
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.
|