@hasna/connectors 0.4.2 → 0.5.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/bin/index.js +113 -1
- package/bin/mcp.js +113 -1
- package/bin/serve.js +112 -0
- package/connectors/connect-assemblyai/.env.example +11 -0
- package/connectors/connect-assemblyai/CLAUDE.md +128 -0
- package/connectors/connect-assemblyai/README.md +193 -0
- package/connectors/connect-assemblyai/package.json +50 -0
- package/connectors/connect-assemblyai/src/api/client.ts +192 -0
- package/connectors/connect-assemblyai/src/api/index.ts +71 -0
- package/connectors/connect-assemblyai/src/cli/index.ts +384 -0
- package/connectors/connect-assemblyai/src/index.ts +19 -0
- package/connectors/connect-assemblyai/src/types/index.ts +277 -0
- package/connectors/connect-assemblyai/src/utils/config.ts +103 -0
- package/connectors/connect-assemblyai/src/utils/output.ts +119 -0
- package/connectors/connect-assemblyai/tsconfig.json +16 -0
- package/connectors/connect-baseten/.env.example +11 -0
- package/connectors/connect-baseten/CLAUDE.md +128 -0
- package/connectors/connect-baseten/README.md +193 -0
- package/connectors/connect-baseten/package.json +51 -0
- package/connectors/connect-baseten/src/api/client.ts +71 -0
- package/connectors/connect-baseten/src/api/index.ts +40 -0
- package/connectors/connect-baseten/src/cli/index.ts +244 -0
- package/connectors/connect-baseten/src/index.ts +19 -0
- package/connectors/connect-baseten/src/types/index.ts +55 -0
- package/connectors/connect-baseten/src/utils/config.ts +103 -0
- package/connectors/connect-baseten/src/utils/output.ts +119 -0
- package/connectors/connect-baseten/tsconfig.json +16 -0
- package/connectors/connect-cerebras/.env.example +11 -0
- package/connectors/connect-cerebras/CLAUDE.md +128 -0
- package/connectors/connect-cerebras/README.md +193 -0
- package/connectors/connect-cerebras/package.json +51 -0
- package/connectors/connect-cerebras/src/api/client.ts +64 -0
- package/connectors/connect-cerebras/src/api/index.ts +32 -0
- package/connectors/connect-cerebras/src/cli/index.ts +244 -0
- package/connectors/connect-cerebras/src/index.ts +19 -0
- package/connectors/connect-cerebras/src/types/index.ts +65 -0
- package/connectors/connect-cerebras/src/utils/config.ts +103 -0
- package/connectors/connect-cerebras/src/utils/output.ts +119 -0
- package/connectors/connect-cerebras/tsconfig.json +16 -0
- package/connectors/connect-cohere/.env.example +11 -0
- package/connectors/connect-cohere/CLAUDE.md +128 -0
- package/connectors/connect-cohere/README.md +193 -0
- package/connectors/connect-cohere/package.json +53 -0
- package/connectors/connect-cohere/src/api/client.ts +109 -0
- package/connectors/connect-cohere/src/api/index.ts +59 -0
- package/connectors/connect-cohere/src/cli/index.ts +255 -0
- package/connectors/connect-cohere/src/index.ts +19 -0
- package/connectors/connect-cohere/src/types/index.ts +132 -0
- package/connectors/connect-cohere/src/utils/config.ts +197 -0
- package/connectors/connect-cohere/src/utils/output.ts +119 -0
- package/connectors/connect-cohere/tsconfig.json +16 -0
- package/connectors/connect-deepgram/.env.example +11 -0
- package/connectors/connect-deepgram/CLAUDE.md +128 -0
- package/connectors/connect-deepgram/README.md +193 -0
- package/connectors/connect-deepgram/package.json +51 -0
- package/connectors/connect-deepgram/src/api/client.ts +235 -0
- package/connectors/connect-deepgram/src/api/index.ts +57 -0
- package/connectors/connect-deepgram/src/cli/index.ts +339 -0
- package/connectors/connect-deepgram/src/index.ts +19 -0
- package/connectors/connect-deepgram/src/types/index.ts +232 -0
- package/connectors/connect-deepgram/src/utils/config.ts +103 -0
- package/connectors/connect-deepgram/src/utils/output.ts +119 -0
- package/connectors/connect-deepgram/tsconfig.json +16 -0
- package/connectors/connect-deepseek/.env.example +11 -0
- package/connectors/connect-deepseek/CLAUDE.md +128 -0
- package/connectors/connect-deepseek/README.md +193 -0
- package/connectors/connect-deepseek/package.json +51 -0
- package/connectors/connect-deepseek/src/api/client.ts +108 -0
- package/connectors/connect-deepseek/src/api/index.ts +36 -0
- package/connectors/connect-deepseek/src/cli/index.ts +167 -0
- package/connectors/connect-deepseek/src/index.ts +19 -0
- package/connectors/connect-deepseek/src/types/index.ts +72 -0
- package/connectors/connect-deepseek/src/utils/config.ts +103 -0
- package/connectors/connect-deepseek/src/utils/output.ts +119 -0
- package/connectors/connect-deepseek/tsconfig.json +16 -0
- package/connectors/connect-fal/.env.example +11 -0
- package/connectors/connect-fal/CLAUDE.md +128 -0
- package/connectors/connect-fal/README.md +193 -0
- package/connectors/connect-fal/package.json +51 -0
- package/connectors/connect-fal/src/api/client.ts +172 -0
- package/connectors/connect-fal/src/api/index.ts +55 -0
- package/connectors/connect-fal/src/cli/index.ts +341 -0
- package/connectors/connect-fal/src/index.ts +19 -0
- package/connectors/connect-fal/src/types/index.ts +135 -0
- package/connectors/connect-fal/src/utils/config.ts +103 -0
- package/connectors/connect-fal/src/utils/output.ts +119 -0
- package/connectors/connect-fal/tsconfig.json +16 -0
- package/connectors/connect-fireworks/.env.example +11 -0
- package/connectors/connect-fireworks/CLAUDE.md +128 -0
- package/connectors/connect-fireworks/README.md +193 -0
- package/connectors/connect-fireworks/package.json +51 -0
- package/connectors/connect-fireworks/src/api/client.ts +63 -0
- package/connectors/connect-fireworks/src/api/index.ts +36 -0
- package/connectors/connect-fireworks/src/cli/index.ts +244 -0
- package/connectors/connect-fireworks/src/index.ts +19 -0
- package/connectors/connect-fireworks/src/types/index.ts +70 -0
- package/connectors/connect-fireworks/src/utils/config.ts +103 -0
- package/connectors/connect-fireworks/src/utils/output.ts +119 -0
- package/connectors/connect-fireworks/tsconfig.json +16 -0
- package/connectors/connect-groq/.env.example +11 -0
- package/connectors/connect-groq/CLAUDE.md +128 -0
- package/connectors/connect-groq/README.md +193 -0
- package/connectors/connect-groq/package.json +52 -0
- package/connectors/connect-groq/src/api/client.ts +108 -0
- package/connectors/connect-groq/src/api/index.ts +36 -0
- package/connectors/connect-groq/src/cli/index.ts +171 -0
- package/connectors/connect-groq/src/index.ts +19 -0
- package/connectors/connect-groq/src/types/index.ts +69 -0
- package/connectors/connect-groq/src/utils/config.ts +103 -0
- package/connectors/connect-groq/src/utils/output.ts +119 -0
- package/connectors/connect-groq/tsconfig.json +16 -0
- package/connectors/connect-luma/.env.example +11 -0
- package/connectors/connect-luma/CLAUDE.md +128 -0
- package/connectors/connect-luma/README.md +193 -0
- package/connectors/connect-luma/package.json +53 -0
- package/connectors/connect-luma/src/api/client.ts +85 -0
- package/connectors/connect-luma/src/api/index.ts +44 -0
- package/connectors/connect-luma/src/cli/index.ts +300 -0
- package/connectors/connect-luma/src/index.ts +19 -0
- package/connectors/connect-luma/src/types/index.ts +60 -0
- package/connectors/connect-luma/src/utils/config.ts +103 -0
- package/connectors/connect-luma/src/utils/output.ts +119 -0
- package/connectors/connect-luma/tsconfig.json +16 -0
- package/connectors/connect-modal/.env.example +11 -0
- package/connectors/connect-modal/CLAUDE.md +128 -0
- package/connectors/connect-modal/README.md +193 -0
- package/connectors/connect-modal/package.json +51 -0
- package/connectors/connect-modal/src/api/client.ts +119 -0
- package/connectors/connect-modal/src/api/index.ts +69 -0
- package/connectors/connect-modal/src/cli/index.ts +224 -0
- package/connectors/connect-modal/src/index.ts +21 -0
- package/connectors/connect-modal/src/types/index.ts +60 -0
- package/connectors/connect-modal/src/utils/config.ts +114 -0
- package/connectors/connect-modal/src/utils/output.ts +119 -0
- package/connectors/connect-modal/tsconfig.json +16 -0
- package/connectors/connect-perplexity/.env.example +4 -0
- package/connectors/connect-perplexity/CLAUDE.md +156 -0
- package/connectors/connect-perplexity/README.md +184 -0
- package/connectors/connect-perplexity/package.json +58 -0
- package/connectors/connect-perplexity/scripts/publish.ts +210 -0
- package/connectors/connect-perplexity/src/api/client.ts +119 -0
- package/connectors/connect-perplexity/src/api/example.ts +118 -0
- package/connectors/connect-perplexity/src/api/index.ts +48 -0
- package/connectors/connect-perplexity/src/cli/index.ts +421 -0
- package/connectors/connect-perplexity/src/index.ts +24 -0
- package/connectors/connect-perplexity/src/types/index.ts +140 -0
- package/connectors/connect-perplexity/src/utils/config.ts +208 -0
- package/connectors/connect-perplexity/src/utils/output.ts +119 -0
- package/connectors/connect-perplexity/tsconfig.json +16 -0
- package/connectors/connect-replicate/.env.example +11 -0
- package/connectors/connect-replicate/CLAUDE.md +128 -0
- package/connectors/connect-replicate/README.md +193 -0
- package/connectors/connect-replicate/package.json +51 -0
- package/connectors/connect-replicate/src/api/client.ts +109 -0
- package/connectors/connect-replicate/src/api/index.ts +71 -0
- package/connectors/connect-replicate/src/cli/index.ts +250 -0
- package/connectors/connect-replicate/src/index.ts +19 -0
- package/connectors/connect-replicate/src/types/index.ts +85 -0
- package/connectors/connect-replicate/src/utils/config.ts +103 -0
- package/connectors/connect-replicate/src/utils/output.ts +119 -0
- package/connectors/connect-replicate/tsconfig.json +16 -0
- package/connectors/connect-roboflow/.env.example +11 -0
- package/connectors/connect-roboflow/CLAUDE.md +272 -0
- package/connectors/connect-roboflow/README.md +193 -0
- package/connectors/connect-roboflow/package.json +51 -0
- package/connectors/connect-roboflow/scripts/release.ts +179 -0
- package/connectors/connect-roboflow/src/api/client.ts +213 -0
- package/connectors/connect-roboflow/src/api/example.ts +48 -0
- package/connectors/connect-roboflow/src/api/index.ts +51 -0
- package/connectors/connect-roboflow/src/cli/index.ts +254 -0
- package/connectors/connect-roboflow/src/index.ts +103 -0
- package/connectors/connect-roboflow/src/types/index.ts +237 -0
- package/connectors/connect-roboflow/src/utils/auth.ts +274 -0
- package/connectors/connect-roboflow/src/utils/bulk.ts +212 -0
- package/connectors/connect-roboflow/src/utils/config.ts +326 -0
- package/connectors/connect-roboflow/src/utils/output.ts +175 -0
- package/connectors/connect-roboflow/src/utils/settings.ts +114 -0
- package/connectors/connect-roboflow/src/utils/storage.ts +198 -0
- package/connectors/connect-roboflow/tsconfig.json +16 -0
- package/connectors/connect-runway/.env.example +11 -0
- package/connectors/connect-runway/CLAUDE.md +128 -0
- package/connectors/connect-runway/README.md +193 -0
- package/connectors/connect-runway/package.json +52 -0
- package/connectors/connect-runway/src/api/client.ts +78 -0
- package/connectors/connect-runway/src/api/index.ts +40 -0
- package/connectors/connect-runway/src/cli/index.ts +283 -0
- package/connectors/connect-runway/src/index.ts +19 -0
- package/connectors/connect-runway/src/types/index.ts +52 -0
- package/connectors/connect-runway/src/utils/config.ts +103 -0
- package/connectors/connect-runway/src/utils/output.ts +119 -0
- package/connectors/connect-runway/tsconfig.json +16 -0
- package/connectors/connect-together/.env.example +11 -0
- package/connectors/connect-together/CLAUDE.md +128 -0
- package/connectors/connect-together/README.md +193 -0
- package/connectors/connect-together/package.json +52 -0
- package/connectors/connect-together/src/api/client.ts +106 -0
- package/connectors/connect-together/src/api/index.ts +47 -0
- package/connectors/connect-together/src/cli/index.ts +228 -0
- package/connectors/connect-together/src/index.ts +19 -0
- package/connectors/connect-together/src/types/index.ts +91 -0
- package/connectors/connect-together/src/utils/config.ts +142 -0
- package/connectors/connect-together/src/utils/output.ts +119 -0
- package/connectors/connect-together/tsconfig.json +16 -0
- package/dist/index.js +112 -0
- package/package.json +1 -1
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# scaffold-connector
|
|
2
|
+
|
|
3
|
+
A TypeScript scaffold for building API connector CLIs with multi-profile support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Multi-profile configuration (switch between different API keys/accounts)
|
|
8
|
+
- Bearer token authentication (easily customizable)
|
|
9
|
+
- Clean CLI structure with Commander.js
|
|
10
|
+
- Pretty and JSON output formats
|
|
11
|
+
- TypeScript with strict mode
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### 1. Clone and Rename
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Clone for your connector
|
|
19
|
+
git clone https://github.com/hasna/scaffold-connector.git connect-yourapi
|
|
20
|
+
cd connect-yourapi
|
|
21
|
+
|
|
22
|
+
# Update package.json name
|
|
23
|
+
# Change "@hasna/scaffold-connector" to "@hasna/connect-yourapi"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Update Configuration
|
|
27
|
+
|
|
28
|
+
Search for `TODO` comments throughout the codebase and update:
|
|
29
|
+
|
|
30
|
+
- `src/cli/index.ts` - Update `CONNECTOR_NAME` and description
|
|
31
|
+
- `src/utils/config.ts` - Update `CONNECTOR_NAME` and env var names
|
|
32
|
+
- `src/api/client.ts` - Update `DEFAULT_BASE_URL` and authentication method
|
|
33
|
+
- `src/api/index.ts` - Rename `Connector` class to your API name
|
|
34
|
+
- `src/types/index.ts` - Add your API's type definitions
|
|
35
|
+
- `package.json` - Update name, description, bin command
|
|
36
|
+
- `.env.example` - Update environment variable names
|
|
37
|
+
|
|
38
|
+
### 3. Install and Test
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Install dependencies
|
|
42
|
+
bun install
|
|
43
|
+
|
|
44
|
+
# Run CLI
|
|
45
|
+
bun run dev
|
|
46
|
+
|
|
47
|
+
# Or run specific commands
|
|
48
|
+
bun run dev profile list
|
|
49
|
+
bun run dev config show
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## CLI Structure
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
connector [options] [command]
|
|
56
|
+
|
|
57
|
+
Options:
|
|
58
|
+
-k, --api-key <key> API key (overrides config)
|
|
59
|
+
-f, --format <format> Output format (json, pretty)
|
|
60
|
+
-p, --profile <profile> Use a specific profile
|
|
61
|
+
|
|
62
|
+
Commands:
|
|
63
|
+
profile list List all profiles
|
|
64
|
+
profile use <name> Switch to a profile
|
|
65
|
+
profile create <name> Create a new profile
|
|
66
|
+
profile delete <name> Delete a profile
|
|
67
|
+
profile show [name] Show profile configuration
|
|
68
|
+
|
|
69
|
+
config set-key <key> Set API key for active profile
|
|
70
|
+
config show Show current configuration
|
|
71
|
+
config clear Clear configuration
|
|
72
|
+
|
|
73
|
+
example list Example API command (replace)
|
|
74
|
+
example get <id> Example API command (replace)
|
|
75
|
+
example create Example API command (replace)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Project Structure
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
src/
|
|
82
|
+
├── api/
|
|
83
|
+
│ ├── client.ts # HTTP client with authentication
|
|
84
|
+
│ ├── example.ts # Example API module (replace with your API)
|
|
85
|
+
│ └── index.ts # Main connector class
|
|
86
|
+
├── cli/
|
|
87
|
+
│ └── index.ts # CLI commands
|
|
88
|
+
├── types/
|
|
89
|
+
│ └── index.ts # Type definitions
|
|
90
|
+
├── utils/
|
|
91
|
+
│ ├── config.ts # Multi-profile configuration
|
|
92
|
+
│ └── output.ts # CLI output formatting
|
|
93
|
+
└── index.ts # Library exports
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Multi-Profile Configuration
|
|
97
|
+
|
|
98
|
+
Profiles are stored in `~/.connect/{connector-name}/profiles/`:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
~/.connect/connector/
|
|
102
|
+
├── current_profile # Name of active profile
|
|
103
|
+
└── profiles/
|
|
104
|
+
├── default.json # Default profile
|
|
105
|
+
├── work.json # Named profile
|
|
106
|
+
└── personal.json # Named profile
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Profile Commands
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Create profiles
|
|
113
|
+
connector profile create work --api-key sk-xxx --use
|
|
114
|
+
connector profile create personal --api-key sk-yyy
|
|
115
|
+
|
|
116
|
+
# Switch profiles
|
|
117
|
+
connector profile use work
|
|
118
|
+
|
|
119
|
+
# Use profile for single command
|
|
120
|
+
connector -p personal example list
|
|
121
|
+
|
|
122
|
+
# List profiles
|
|
123
|
+
connector profile list
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Customizing Authentication
|
|
127
|
+
|
|
128
|
+
Edit `src/api/client.ts` to change authentication:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// Bearer token (default)
|
|
132
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
133
|
+
|
|
134
|
+
// API Key header
|
|
135
|
+
'X-API-Key': this.apiKey,
|
|
136
|
+
|
|
137
|
+
// Basic auth
|
|
138
|
+
'Authorization': `Basic ${Buffer.from(`${this.apiKey}:${this.apiSecret}`).toString('base64')}`,
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Adding API Endpoints
|
|
142
|
+
|
|
143
|
+
1. Create a new file in `src/api/` (e.g., `users.ts`)
|
|
144
|
+
2. Export it from `src/api/index.ts`
|
|
145
|
+
3. Add types in `src/types/index.ts`
|
|
146
|
+
4. Add CLI commands in `src/cli/index.ts`
|
|
147
|
+
|
|
148
|
+
Example API module:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// src/api/users.ts
|
|
152
|
+
import type { ConnectorClient } from './client';
|
|
153
|
+
|
|
154
|
+
export class UsersApi {
|
|
155
|
+
constructor(private readonly client: ConnectorClient) {}
|
|
156
|
+
|
|
157
|
+
async list(options?: { limit?: number }) {
|
|
158
|
+
return this.client.get('/users', { limit: options?.limit });
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async get(id: string) {
|
|
162
|
+
return this.client.get(`/users/${id}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Environment Variables
|
|
168
|
+
|
|
169
|
+
| Variable | Description |
|
|
170
|
+
|----------|-------------|
|
|
171
|
+
| `CONNECTOR_API_KEY` | API key (overrides profile config) |
|
|
172
|
+
| `CONNECTOR_API_SECRET` | API secret (optional) |
|
|
173
|
+
| `CONNECTOR_BASE_URL` | Override base URL (optional) |
|
|
174
|
+
|
|
175
|
+
## Development
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Install dependencies
|
|
179
|
+
bun install
|
|
180
|
+
|
|
181
|
+
# Run CLI in development
|
|
182
|
+
bun run dev
|
|
183
|
+
|
|
184
|
+
# Build for distribution
|
|
185
|
+
bun run build
|
|
186
|
+
|
|
187
|
+
# Type check
|
|
188
|
+
bun run typecheck
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## License
|
|
192
|
+
|
|
193
|
+
MIT
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hasna/connect-luma",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Luma AI connector CLI - Dream Machine video generation with multi-profile support",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"connect-luma": "./bin/index.js"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "bun build ./src/index.ts --outdir ./dist --target bun && bun build ./src/cli/index.ts --outdir ./bin --target bun",
|
|
19
|
+
"dev": "bun run ./src/cli/index.ts",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"prepublishOnly": "bun run build"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"luma",
|
|
25
|
+
"lumaai",
|
|
26
|
+
"dream-machine",
|
|
27
|
+
"ai",
|
|
28
|
+
"api",
|
|
29
|
+
"connector",
|
|
30
|
+
"cli",
|
|
31
|
+
"typescript",
|
|
32
|
+
"bun",
|
|
33
|
+
"video",
|
|
34
|
+
"generation"
|
|
35
|
+
],
|
|
36
|
+
"author": "Hasna",
|
|
37
|
+
"license": "Apache-2.0",
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/bun": "latest",
|
|
40
|
+
"typescript": "^5"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"commander": "^12.1.0",
|
|
44
|
+
"chalk": "^5.3.0"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"bun": ">=1.0.0"
|
|
48
|
+
},
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "git+https://github.com/hasna/open-connectors.git"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { LumaApiError, type LumaConfig, type GenerationRequest, type ImageToVideoRequest, type Generation, type GenerationsListResponse } from '../types';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_BASE_URL = 'https://api.lumalabs.ai/dream-machine/v1';
|
|
4
|
+
|
|
5
|
+
export class LumaClient {
|
|
6
|
+
private readonly apiKey: string;
|
|
7
|
+
private readonly baseUrl: string;
|
|
8
|
+
|
|
9
|
+
constructor(config: LumaConfig) {
|
|
10
|
+
if (!config.apiKey) {
|
|
11
|
+
throw new Error('API key is required');
|
|
12
|
+
}
|
|
13
|
+
this.apiKey = config.apiKey;
|
|
14
|
+
this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
private async request<T>(path: string, options: RequestInit = {}): Promise<T> {
|
|
18
|
+
const url = `${this.baseUrl}${path}`;
|
|
19
|
+
|
|
20
|
+
const headers: Record<string, string> = {
|
|
21
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
'Accept': 'application/json',
|
|
24
|
+
...(options.headers as Record<string, string> || {}),
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const response = await fetch(url, {
|
|
28
|
+
...options,
|
|
29
|
+
headers,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (!response.ok) {
|
|
33
|
+
const errorText = await response.text();
|
|
34
|
+
let message = errorText;
|
|
35
|
+
try {
|
|
36
|
+
const errorJson = JSON.parse(errorText);
|
|
37
|
+
message = errorJson.detail || errorJson.error || errorJson.message || errorText;
|
|
38
|
+
} catch {
|
|
39
|
+
// Use raw text
|
|
40
|
+
}
|
|
41
|
+
throw new LumaApiError(message, response.status);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return response.json() as Promise<T>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async createGeneration(params: GenerationRequest): Promise<Generation> {
|
|
48
|
+
return this.request<Generation>('/generations', {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
body: JSON.stringify(params),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async imageToVideo(params: ImageToVideoRequest): Promise<Generation> {
|
|
55
|
+
return this.request<Generation>('/generations', {
|
|
56
|
+
method: 'POST',
|
|
57
|
+
body: JSON.stringify(params),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async getGeneration(generationId: string): Promise<Generation> {
|
|
62
|
+
return this.request<Generation>(`/generations/${generationId}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async listGenerations(limit?: number, offset?: number): Promise<GenerationsListResponse> {
|
|
66
|
+
const params = new URLSearchParams();
|
|
67
|
+
if (limit) params.append('limit', String(limit));
|
|
68
|
+
if (offset) params.append('offset', String(offset));
|
|
69
|
+
const query = params.toString();
|
|
70
|
+
return this.request<GenerationsListResponse>(`/generations${query ? '?' + query : ''}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async deleteGeneration(generationId: string): Promise<void> {
|
|
74
|
+
await this.request<void>(`/generations/${generationId}`, {
|
|
75
|
+
method: 'DELETE',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
getApiKeyPreview(): string {
|
|
80
|
+
if (this.apiKey.length > 10) {
|
|
81
|
+
return `${this.apiKey.substring(0, 6)}...${this.apiKey.substring(this.apiKey.length - 4)}`;
|
|
82
|
+
}
|
|
83
|
+
return '***';
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { LumaConfig, GenerationRequest, ImageToVideoRequest, Generation, GenerationsListResponse } from '../types';
|
|
2
|
+
import { LumaClient } from './client';
|
|
3
|
+
|
|
4
|
+
export class Luma {
|
|
5
|
+
private readonly client: LumaClient;
|
|
6
|
+
|
|
7
|
+
constructor(config: LumaConfig) {
|
|
8
|
+
this.client = new LumaClient(config);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async createGeneration(params: GenerationRequest): Promise<Generation> {
|
|
12
|
+
return this.client.createGeneration(params);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async imageToVideo(params: ImageToVideoRequest): Promise<Generation> {
|
|
16
|
+
return this.client.imageToVideo(params);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async getGeneration(generationId: string): Promise<Generation> {
|
|
20
|
+
return this.client.getGeneration(generationId);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async listGenerations(limit?: number, offset?: number): Promise<GenerationsListResponse> {
|
|
24
|
+
return this.client.listGenerations(limit, offset);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async deleteGeneration(generationId: string): Promise<void> {
|
|
28
|
+
return this.client.deleteGeneration(generationId);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static fromEnv(): Luma {
|
|
32
|
+
const apiKey = process.env.LUMA_API_KEY || process.env.LUMAAI_API_KEY;
|
|
33
|
+
if (!apiKey) {
|
|
34
|
+
throw new Error('LUMA_API_KEY environment variable is required');
|
|
35
|
+
}
|
|
36
|
+
return new Luma({ apiKey });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getApiKeyPreview(): string {
|
|
40
|
+
return this.client.getApiKeyPreview();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { LumaClient } from './client';
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { Luma } from '../api';
|
|
5
|
+
import {
|
|
6
|
+
getApiKey,
|
|
7
|
+
setApiKey,
|
|
8
|
+
clearConfig,
|
|
9
|
+
getConfigDir,
|
|
10
|
+
setProfileOverride,
|
|
11
|
+
getCurrentProfile,
|
|
12
|
+
setCurrentProfile,
|
|
13
|
+
listProfiles,
|
|
14
|
+
createProfile,
|
|
15
|
+
deleteProfile,
|
|
16
|
+
profileExists,
|
|
17
|
+
loadProfile,
|
|
18
|
+
} from '../utils/config';
|
|
19
|
+
import type { OutputFormat } from '../utils/output';
|
|
20
|
+
import { success, error, info, print } from '../utils/output';
|
|
21
|
+
|
|
22
|
+
const CONNECTOR_NAME = 'connect-luma';
|
|
23
|
+
const VERSION = '0.0.1';
|
|
24
|
+
|
|
25
|
+
const program = new Command();
|
|
26
|
+
|
|
27
|
+
program
|
|
28
|
+
.name(CONNECTOR_NAME)
|
|
29
|
+
.description('Luma AI connector CLI - Dream Machine video generation with multi-profile support')
|
|
30
|
+
.version(VERSION)
|
|
31
|
+
.option('-k, --api-key <key>', 'API key (overrides config)')
|
|
32
|
+
.option('-f, --format <format>', 'Output format (json, pretty)', 'pretty')
|
|
33
|
+
.option('-p, --profile <profile>', 'Use a specific profile')
|
|
34
|
+
.hook('preAction', (thisCommand) => {
|
|
35
|
+
const opts = thisCommand.opts();
|
|
36
|
+
if (opts.profile) {
|
|
37
|
+
if (!profileExists(opts.profile)) {
|
|
38
|
+
error(`Profile "${opts.profile}" does not exist. Create it with "${CONNECTOR_NAME} profile create ${opts.profile}"`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
setProfileOverride(opts.profile);
|
|
42
|
+
}
|
|
43
|
+
if (opts.apiKey) {
|
|
44
|
+
process.env.LUMA_API_KEY = opts.apiKey;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
function getFormat(cmd: Command): OutputFormat {
|
|
49
|
+
const parent = cmd.parent;
|
|
50
|
+
return (parent?.opts().format || 'pretty') as OutputFormat;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function getClient(): Luma {
|
|
54
|
+
const apiKey = getApiKey();
|
|
55
|
+
if (!apiKey) {
|
|
56
|
+
error(`No API key configured. Run "${CONNECTOR_NAME} config set-key <key>" or set LUMA_API_KEY environment variable.`);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
return new Luma({ apiKey });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ============================================
|
|
63
|
+
// Profile Commands
|
|
64
|
+
// ============================================
|
|
65
|
+
const profileCmd = program
|
|
66
|
+
.command('profile')
|
|
67
|
+
.description('Manage configuration profiles');
|
|
68
|
+
|
|
69
|
+
profileCmd
|
|
70
|
+
.command('list')
|
|
71
|
+
.description('List all profiles')
|
|
72
|
+
.action(() => {
|
|
73
|
+
const profiles = listProfiles();
|
|
74
|
+
const current = getCurrentProfile();
|
|
75
|
+
if (profiles.length === 0) {
|
|
76
|
+
info('No profiles found. Use "profile create <name>" to create one.');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
success(`Profiles:`);
|
|
80
|
+
profiles.forEach(p => {
|
|
81
|
+
const isActive = p === current ? chalk.green(' (active)') : '';
|
|
82
|
+
console.log(` ${p}${isActive}`);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
profileCmd
|
|
87
|
+
.command('use <name>')
|
|
88
|
+
.description('Switch to a profile')
|
|
89
|
+
.action((name: string) => {
|
|
90
|
+
if (!profileExists(name)) {
|
|
91
|
+
error(`Profile "${name}" does not exist. Create it with "profile create ${name}"`);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
setCurrentProfile(name);
|
|
95
|
+
success(`Switched to profile: ${name}`);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
profileCmd
|
|
99
|
+
.command('create <name>')
|
|
100
|
+
.description('Create a new profile')
|
|
101
|
+
.option('--api-key <key>', 'API key')
|
|
102
|
+
.option('--use', 'Switch to this profile after creation')
|
|
103
|
+
.action((name: string, opts) => {
|
|
104
|
+
if (profileExists(name)) {
|
|
105
|
+
error(`Profile "${name}" already exists`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
createProfile(name, { apiKey: opts.apiKey });
|
|
109
|
+
success(`Profile "${name}" created`);
|
|
110
|
+
if (opts.use) {
|
|
111
|
+
setCurrentProfile(name);
|
|
112
|
+
info(`Switched to profile: ${name}`);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
profileCmd
|
|
117
|
+
.command('delete <name>')
|
|
118
|
+
.description('Delete a profile')
|
|
119
|
+
.action((name: string) => {
|
|
120
|
+
if (name === 'default') {
|
|
121
|
+
error('Cannot delete the default profile');
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
if (deleteProfile(name)) {
|
|
125
|
+
success(`Profile "${name}" deleted`);
|
|
126
|
+
} else {
|
|
127
|
+
error(`Profile "${name}" not found`);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
profileCmd
|
|
133
|
+
.command('show [name]')
|
|
134
|
+
.description('Show profile configuration')
|
|
135
|
+
.action((name?: string) => {
|
|
136
|
+
const profileName = name || getCurrentProfile();
|
|
137
|
+
const config = loadProfile(profileName);
|
|
138
|
+
const active = getCurrentProfile();
|
|
139
|
+
console.log(chalk.bold(`Profile: ${profileName}${profileName === active ? chalk.green(' (active)') : ''}`));
|
|
140
|
+
info(`API Key: ${config.apiKey ? `${config.apiKey.substring(0, 8)}...` : chalk.gray('not set')}`);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// ============================================
|
|
144
|
+
// Config Commands
|
|
145
|
+
// ============================================
|
|
146
|
+
const configCmd = program
|
|
147
|
+
.command('config')
|
|
148
|
+
.description('Manage CLI configuration (for active profile)');
|
|
149
|
+
|
|
150
|
+
configCmd
|
|
151
|
+
.command('set-key <apiKey>')
|
|
152
|
+
.description('Set API key')
|
|
153
|
+
.action((apiKey: string) => {
|
|
154
|
+
setApiKey(apiKey);
|
|
155
|
+
success(`API key saved to profile: ${getCurrentProfile()}`);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
configCmd
|
|
159
|
+
.command('show')
|
|
160
|
+
.description('Show current configuration')
|
|
161
|
+
.action(() => {
|
|
162
|
+
const profileName = getCurrentProfile();
|
|
163
|
+
const apiKey = getApiKey();
|
|
164
|
+
console.log(chalk.bold(`Active Profile: ${profileName}`));
|
|
165
|
+
info(`Config directory: ${getConfigDir()}`);
|
|
166
|
+
info(`API Key: ${apiKey ? `${apiKey.substring(0, 8)}...` : chalk.gray('not set')}`);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
configCmd
|
|
170
|
+
.command('clear')
|
|
171
|
+
.description('Clear configuration for active profile')
|
|
172
|
+
.action(() => {
|
|
173
|
+
clearConfig();
|
|
174
|
+
success(`Configuration cleared for profile: ${getCurrentProfile()}`);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// ============================================
|
|
178
|
+
// Generation Commands
|
|
179
|
+
// ============================================
|
|
180
|
+
const genCmd = program
|
|
181
|
+
.command('generate')
|
|
182
|
+
.description('Video generation commands');
|
|
183
|
+
|
|
184
|
+
genCmd
|
|
185
|
+
.command('create <prompt>')
|
|
186
|
+
.description('Create a new video generation from text')
|
|
187
|
+
.option('-r, --ratio <ratio>', 'Aspect ratio (16:9, 9:16, 1:1, 4:3, 3:4)', '16:9')
|
|
188
|
+
.option('-l, --loop', 'Create a looping video')
|
|
189
|
+
.action(async (prompt: string, opts) => {
|
|
190
|
+
try {
|
|
191
|
+
const client = getClient();
|
|
192
|
+
const result = await client.createGeneration({
|
|
193
|
+
prompt,
|
|
194
|
+
aspect_ratio: opts.ratio as '16:9' | '9:16' | '1:1' | '4:3' | '3:4',
|
|
195
|
+
loop: opts.loop,
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const format = getFormat(genCmd);
|
|
199
|
+
if (format === 'json') {
|
|
200
|
+
print(result, format);
|
|
201
|
+
} else {
|
|
202
|
+
success(`Generation started: ${result.id}`);
|
|
203
|
+
info(`Status: ${result.state}`);
|
|
204
|
+
info(`Check status with: ${CONNECTOR_NAME} generation get ${result.id}`);
|
|
205
|
+
}
|
|
206
|
+
} catch (err) {
|
|
207
|
+
error(String(err));
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
genCmd
|
|
213
|
+
.command('animate <imageUrl>')
|
|
214
|
+
.description('Create video from image')
|
|
215
|
+
.option('-t, --text <prompt>', 'Text prompt')
|
|
216
|
+
.option('-r, --ratio <ratio>', 'Aspect ratio', '16:9')
|
|
217
|
+
.option('-l, --loop', 'Create a looping video')
|
|
218
|
+
.action(async (imageUrl: string, opts) => {
|
|
219
|
+
try {
|
|
220
|
+
const client = getClient();
|
|
221
|
+
const result = await client.imageToVideo({
|
|
222
|
+
prompt: opts.text,
|
|
223
|
+
keyframes: {
|
|
224
|
+
frame0: { type: 'image', url: imageUrl },
|
|
225
|
+
},
|
|
226
|
+
aspect_ratio: opts.ratio as '16:9' | '9:16' | '1:1' | '4:3' | '3:4',
|
|
227
|
+
loop: opts.loop,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const format = getFormat(genCmd);
|
|
231
|
+
if (format === 'json') {
|
|
232
|
+
print(result, format);
|
|
233
|
+
} else {
|
|
234
|
+
success(`Generation started: ${result.id}`);
|
|
235
|
+
info(`Status: ${result.state}`);
|
|
236
|
+
info(`Check status with: ${CONNECTOR_NAME} generation get ${result.id}`);
|
|
237
|
+
}
|
|
238
|
+
} catch (err) {
|
|
239
|
+
error(String(err));
|
|
240
|
+
process.exit(1);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
genCmd
|
|
245
|
+
.command('get <id>')
|
|
246
|
+
.description('Get generation status')
|
|
247
|
+
.action(async (id: string) => {
|
|
248
|
+
try {
|
|
249
|
+
const client = getClient();
|
|
250
|
+
const result = await client.getGeneration(id);
|
|
251
|
+
const format = getFormat(genCmd);
|
|
252
|
+
if (format === 'json') {
|
|
253
|
+
print(result, format);
|
|
254
|
+
} else {
|
|
255
|
+
console.log(chalk.bold(`Generation: ${result.id}`));
|
|
256
|
+
info(`Status: ${result.state}`);
|
|
257
|
+
if (result.assets?.video) {
|
|
258
|
+
success(`Video URL: ${result.assets.video}`);
|
|
259
|
+
}
|
|
260
|
+
if (result.failure_reason) {
|
|
261
|
+
error(`Failure: ${result.failure_reason}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
} catch (err) {
|
|
265
|
+
error(String(err));
|
|
266
|
+
process.exit(1);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
genCmd
|
|
271
|
+
.command('list')
|
|
272
|
+
.description('List generations')
|
|
273
|
+
.option('-l, --limit <number>', 'Maximum results', '10')
|
|
274
|
+
.option('-o, --offset <number>', 'Offset', '0')
|
|
275
|
+
.action(async (opts) => {
|
|
276
|
+
try {
|
|
277
|
+
const client = getClient();
|
|
278
|
+
const result = await client.listGenerations(parseInt(opts.limit), parseInt(opts.offset));
|
|
279
|
+
print(result, getFormat(genCmd));
|
|
280
|
+
} catch (err) {
|
|
281
|
+
error(String(err));
|
|
282
|
+
process.exit(1);
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
genCmd
|
|
287
|
+
.command('delete <id>')
|
|
288
|
+
.description('Delete a generation')
|
|
289
|
+
.action(async (id: string) => {
|
|
290
|
+
try {
|
|
291
|
+
const client = getClient();
|
|
292
|
+
await client.deleteGeneration(id);
|
|
293
|
+
success(`Generation ${id} deleted`);
|
|
294
|
+
} catch (err) {
|
|
295
|
+
error(String(err));
|
|
296
|
+
process.exit(1);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
program.parse();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Luma AI Connector
|
|
2
|
+
// TypeScript wrapper for Luma AI Dream Machine API
|
|
3
|
+
|
|
4
|
+
export { Luma } from './api';
|
|
5
|
+
export * from './types';
|
|
6
|
+
export { LumaClient } from './api';
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
getApiKey,
|
|
10
|
+
setApiKey,
|
|
11
|
+
getCurrentProfile,
|
|
12
|
+
setCurrentProfile,
|
|
13
|
+
listProfiles,
|
|
14
|
+
createProfile,
|
|
15
|
+
deleteProfile,
|
|
16
|
+
loadProfile,
|
|
17
|
+
saveProfile,
|
|
18
|
+
clearConfig,
|
|
19
|
+
} from './utils/config';
|