@squidcloud/cli 1.0.446 → 1.0.447
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/dist/index.js +1 -5
- package/dist/resources/claude/skills/squid-development/SKILL.md +66 -2473
- package/dist/resources/claude/skills/squid-development/reference/admin.md +242 -0
- package/dist/resources/claude/skills/squid-development/reference/ai.md +773 -0
- package/dist/resources/claude/skills/squid-development/reference/api.md +87 -0
- package/dist/resources/claude/skills/squid-development/reference/backend.md +462 -0
- package/dist/resources/claude/skills/squid-development/reference/client.md +442 -0
- package/dist/resources/claude/skills/squid-development/reference/connectors.md +33 -0
- package/dist/resources/claude/skills/squid-development/reference/console.md +189 -0
- package/dist/resources/claude/skills/squid-development/reference/databases.md +472 -0
- package/dist/resources/claude/skills/squid-development/reference/openai.md +98 -0
- package/dist/resources/claude/skills/squid-development/reference/security.md +356 -0
- package/package.json +2 -2
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
# Database & Data Management
|
|
2
|
+
|
|
3
|
+
Squid provides database functionality similar to Firestore but more powerful, with collections, document references, and real-time capabilities. Squid supports multiple database types including NoSQL databases (like MongoDB) and relational databases (like PostgreSQL, MySQL).
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
- Collection Access
|
|
7
|
+
- Document References
|
|
8
|
+
- CRUD Operations
|
|
9
|
+
- Real-time Subscriptions
|
|
10
|
+
- Query Operators
|
|
11
|
+
- OR Queries
|
|
12
|
+
- Join Queries
|
|
13
|
+
- Dereference
|
|
14
|
+
- Pagination
|
|
15
|
+
- Watch Changes
|
|
16
|
+
- Transactions
|
|
17
|
+
- Numeric Operations
|
|
18
|
+
- Native Queries
|
|
19
|
+
- Backend Decorator: @trigger
|
|
20
|
+
- Schema Discovery
|
|
21
|
+
|
|
22
|
+
## Collection Access
|
|
23
|
+
|
|
24
|
+
A collection represents a set of documents (similar to a table in relational databases or a collection in NoSQL databases).
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
// Get collection reference in the built-in database
|
|
28
|
+
const users = squid.collection<User>('users');
|
|
29
|
+
|
|
30
|
+
// Get collection reference in a specific integration
|
|
31
|
+
const orders = squid.collection<Order>('orders', 'postgres-db');
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Type parameter**: The generic type `<T>` defines the structure of documents in the collection.
|
|
35
|
+
|
|
36
|
+
## Document References
|
|
37
|
+
|
|
38
|
+
The `doc()` method has different behaviors:
|
|
39
|
+
|
|
40
|
+
### No parameters - `doc()`
|
|
41
|
+
Generates a new document ID (useful for creating new documents):
|
|
42
|
+
```typescript
|
|
43
|
+
// For built_in_db without schema - generates a random ID
|
|
44
|
+
const newDocRef = collection.doc();
|
|
45
|
+
await newDocRef.insert({ name: 'John', age: 30 });
|
|
46
|
+
|
|
47
|
+
// For other integrations - creates a placeholder that gets resolved on insert
|
|
48
|
+
const newDocRef = collection.doc();
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### String parameter - `doc(stringId)`
|
|
52
|
+
**Only supported for `built_in_db` integration without a defined schema:**
|
|
53
|
+
```typescript
|
|
54
|
+
// Valid only for built_in_db collections without schema
|
|
55
|
+
const docRef = collection.doc('my-doc-id');
|
|
56
|
+
const docRef = collection.doc('user-12345');
|
|
57
|
+
```
|
|
58
|
+
**Important**: For collections with defined schemas or non-built_in_db integrations, you must use object format.
|
|
59
|
+
|
|
60
|
+
### Object parameter - `doc({id: value})`
|
|
61
|
+
Used for collections with defined primary keys. The object maps primary key field names to their values:
|
|
62
|
+
```typescript
|
|
63
|
+
// Single primary key field "id"
|
|
64
|
+
const docRef = collection.doc({ id: 'user-123' });
|
|
65
|
+
|
|
66
|
+
// Single primary key field "userId"
|
|
67
|
+
const docRef = collection.doc({ userId: 42 });
|
|
68
|
+
|
|
69
|
+
// Composite primary key (id1, id2)
|
|
70
|
+
const docRef = collection.doc({ id1: 'part1', id2: 'part2' });
|
|
71
|
+
|
|
72
|
+
// Partial primary key - missing fields generated on server if supported
|
|
73
|
+
const docRef = collection.doc({ id1: 'part1' }); // id2 generated on insert
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Key points about document IDs:**
|
|
77
|
+
- For `built_in_db` without schema: can use string IDs or object format
|
|
78
|
+
- For `built_in_db` with schema: must use object format matching primary key fields
|
|
79
|
+
- For other integrations: must use object format matching primary key fields
|
|
80
|
+
- Partial primary keys: missing fields may be auto-generated on insert (if integration supports it)
|
|
81
|
+
- Empty `doc()`: generates a placeholder ID that gets resolved when document is created
|
|
82
|
+
|
|
83
|
+
## CRUD Operations
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// Insert
|
|
87
|
+
await userDoc.insert({ name: 'John', email: 'john@example.com' });
|
|
88
|
+
|
|
89
|
+
// Update (partial)
|
|
90
|
+
await userDoc.update({ name: 'Jane' });
|
|
91
|
+
|
|
92
|
+
// Update specific path
|
|
93
|
+
await userDoc.setInPath('address.street', 'Main St');
|
|
94
|
+
|
|
95
|
+
// Delete specific path
|
|
96
|
+
await userDoc.deleteInPath('tempData');
|
|
97
|
+
|
|
98
|
+
// Delete document
|
|
99
|
+
await userDoc.delete();
|
|
100
|
+
|
|
101
|
+
// Get data (promise)
|
|
102
|
+
const userData = await userDoc.snapshot();
|
|
103
|
+
console.log(userData);
|
|
104
|
+
|
|
105
|
+
// Get data (observable - realtime)
|
|
106
|
+
userDoc.snapshots().subscribe(data => {
|
|
107
|
+
console.log(data);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Get cached data (no server fetch)
|
|
111
|
+
const cached = userDoc.peek();
|
|
112
|
+
|
|
113
|
+
// Check if document has data populated
|
|
114
|
+
if (userDoc.hasData) {
|
|
115
|
+
console.log('Document is loaded');
|
|
116
|
+
// Access data directly (with defensive copy)
|
|
117
|
+
console.log(userDoc.data);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Bulk operations
|
|
121
|
+
await users.insertMany([
|
|
122
|
+
{ id: 'user-1', data: { name: 'Alice' } },
|
|
123
|
+
{ id: 'user-2', data: { name: 'Bob' } }
|
|
124
|
+
]);
|
|
125
|
+
|
|
126
|
+
await users.deleteMany(['user-1', 'user-2']);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Real-time Subscriptions
|
|
130
|
+
|
|
131
|
+
Squid provides real-time data synchronization. Subscribe to document or query changes and receive updates automatically.
|
|
132
|
+
|
|
133
|
+
### Document Subscriptions
|
|
134
|
+
```typescript
|
|
135
|
+
// Subscribe to document changes
|
|
136
|
+
const subscription = docRef.snapshots().subscribe((userData) => {
|
|
137
|
+
if (userData) {
|
|
138
|
+
console.log('Document updated:', userData);
|
|
139
|
+
} else {
|
|
140
|
+
console.log('Document deleted or does not exist');
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Unsubscribe when done
|
|
145
|
+
subscription.unsubscribe();
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Query Subscriptions
|
|
149
|
+
```typescript
|
|
150
|
+
// Subscribe to query results - ALWAYS use dereference()
|
|
151
|
+
const subscription = collection
|
|
152
|
+
.query()
|
|
153
|
+
.eq('status', 'active')
|
|
154
|
+
.gte('age', 18)
|
|
155
|
+
.dereference() // Important: Converts DocumentReferences to actual data
|
|
156
|
+
.snapshots()
|
|
157
|
+
.subscribe((users) => {
|
|
158
|
+
console.log('Active users updated:', users);
|
|
159
|
+
// users is Array<User> with actual data
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Unsubscribe when done
|
|
163
|
+
subscription.unsubscribe();
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Real-time Updates
|
|
167
|
+
When data changes on the server (from any client or backend operation):
|
|
168
|
+
- Document subscriptions receive the updated document data
|
|
169
|
+
- Query subscriptions receive the updated query results
|
|
170
|
+
- Updates are pushed to clients via WebSocket connections
|
|
171
|
+
- Changes are automatically reflected in the local data
|
|
172
|
+
|
|
173
|
+
**Important**: Always unsubscribe from subscriptions when they're no longer needed to prevent memory leaks.
|
|
174
|
+
|
|
175
|
+
## Query Operators
|
|
176
|
+
|
|
177
|
+
**ALL Available Operators:**
|
|
178
|
+
- Comparison: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`
|
|
179
|
+
- Arrays: `in`, `nin`, `arrayIncludesSome`, `arrayIncludesAll`, `arrayNotIncludes`
|
|
180
|
+
- Patterns: `like`, `notLike` (% = any chars, _ = one char)
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// Basic query
|
|
184
|
+
const activeUsers = await users.query()
|
|
185
|
+
.eq('status', 'active')
|
|
186
|
+
.gt('age', 18)
|
|
187
|
+
.sortBy('name', true) // true = ascending
|
|
188
|
+
.limit(100) // max 20000, default 1000
|
|
189
|
+
.snapshot();
|
|
190
|
+
|
|
191
|
+
activeUsers.data.forEach(doc => {
|
|
192
|
+
console.log(doc.data); // Document data
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// Realtime query
|
|
196
|
+
users.query()
|
|
197
|
+
.eq('status', 'active')
|
|
198
|
+
.snapshots().subscribe(snapshot => {
|
|
199
|
+
snapshot.data.forEach(doc => console.log(doc.data));
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Pattern matching (CASE-INSENSITIVE by default)
|
|
203
|
+
const results = await users.query()
|
|
204
|
+
.like('email', '%.com') // case-insensitive by default
|
|
205
|
+
.snapshot();
|
|
206
|
+
|
|
207
|
+
// Case-sensitive pattern matching
|
|
208
|
+
const caseSensitive = await users.query()
|
|
209
|
+
.like('name', 'John%', true) // third parameter: caseSensitive = true
|
|
210
|
+
.snapshot();
|
|
211
|
+
|
|
212
|
+
// Array operators
|
|
213
|
+
const tagged = await posts.query()
|
|
214
|
+
.in('category', ['tech', 'news'])
|
|
215
|
+
.arrayIncludesSome('tags', ['urgent', 'important'])
|
|
216
|
+
.snapshot();
|
|
217
|
+
|
|
218
|
+
// Using where() method (all operators above are shortcuts for where)
|
|
219
|
+
const results1 = await users.query().eq('status', 'active').snapshot();
|
|
220
|
+
const results2 = await users.query().where('status', '==', 'active').snapshot();
|
|
221
|
+
// These are equivalent
|
|
222
|
+
|
|
223
|
+
// Multiple sort
|
|
224
|
+
const sorted = await users.query()
|
|
225
|
+
.sortBy('lastName', true)
|
|
226
|
+
.sortBy('firstName', true)
|
|
227
|
+
.limit(50)
|
|
228
|
+
.snapshot();
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Note:** `offset()` does NOT exist - use `paginate()` for pagination.
|
|
232
|
+
|
|
233
|
+
## OR Queries
|
|
234
|
+
|
|
235
|
+
Combine multiple queries with OR logic:
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
const query1 = users.query().eq('status', 'active');
|
|
239
|
+
const query2 = users.query().eq('status', 'pending');
|
|
240
|
+
const orResults = await users.or(query1, query2)
|
|
241
|
+
.dereference()
|
|
242
|
+
.snapshot();
|
|
243
|
+
// Returns documents matching either query
|
|
244
|
+
// Note: Results are merged and deduplicated
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Join Queries
|
|
248
|
+
|
|
249
|
+
Combine data from multiple collections:
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
// Start with joinQuery() and alias
|
|
253
|
+
const results = await teachers
|
|
254
|
+
.joinQuery('teacher') // Alias for teachers collection
|
|
255
|
+
.join(
|
|
256
|
+
students.query(),
|
|
257
|
+
'students', // Alias for students collection
|
|
258
|
+
{ left: 'id', right: 'teacherId' } // Join condition
|
|
259
|
+
)
|
|
260
|
+
.dereference() // Important: converts refs to actual data
|
|
261
|
+
.snapshot();
|
|
262
|
+
// Results: Array<{ teacher: Teacher, students?: Student }>
|
|
263
|
+
|
|
264
|
+
// Inner join (only matching records)
|
|
265
|
+
const innerResults = await teachers
|
|
266
|
+
.joinQuery('teacher')
|
|
267
|
+
.join(
|
|
268
|
+
students.query(),
|
|
269
|
+
'students',
|
|
270
|
+
{ left: 'id', right: 'teacherId' },
|
|
271
|
+
{ isInner: true } // Inner join option
|
|
272
|
+
)
|
|
273
|
+
.dereference()
|
|
274
|
+
.snapshot();
|
|
275
|
+
|
|
276
|
+
// Multi-level joins
|
|
277
|
+
const threeWay = await collection1
|
|
278
|
+
.joinQuery('a')
|
|
279
|
+
.join(collection2.query(), 'b', { left: 'id', right: 'parentId' })
|
|
280
|
+
.join(collection3.query(), 'c', { left: 'id', right: 'grandParentId' })
|
|
281
|
+
.dereference()
|
|
282
|
+
.snapshot();
|
|
283
|
+
|
|
284
|
+
// Grouped joins (nests one-to-many as arrays)
|
|
285
|
+
const grouped = await teachers
|
|
286
|
+
.joinQuery('teacher')
|
|
287
|
+
.join(students.query(), 'students', { left: 'id', right: 'teacherId' })
|
|
288
|
+
.grouped()
|
|
289
|
+
.dereference()
|
|
290
|
+
.snapshot();
|
|
291
|
+
// Results: Array<{ teacher: Teacher, students: Student[] }>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Dereference
|
|
295
|
+
|
|
296
|
+
Converts DocumentReferences to actual data:
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
// WITHOUT dereference: returns Array<DocumentReference<User>>
|
|
300
|
+
const refs = await users.query().eq('active', true).snapshot();
|
|
301
|
+
// refs.data[0].data to access actual data
|
|
302
|
+
|
|
303
|
+
// WITH dereference: returns Array<User> directly
|
|
304
|
+
const userData = await users.query()
|
|
305
|
+
.eq('active', true)
|
|
306
|
+
.dereference()
|
|
307
|
+
.snapshot();
|
|
308
|
+
// userData[0] is the actual user object
|
|
309
|
+
|
|
310
|
+
// ALWAYS use dereference() for:
|
|
311
|
+
// - Real-time subscriptions (makes working with data easier)
|
|
312
|
+
// - When you need document data directly
|
|
313
|
+
// DON'T use dereference() if:
|
|
314
|
+
// - You need DocumentReference methods like .update() or .delete()
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Pagination
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
const pagination = users.query()
|
|
321
|
+
.sortBy('createdAt', false)
|
|
322
|
+
.dereference()
|
|
323
|
+
.paginate({
|
|
324
|
+
pageSize: 50, // Number of items per page (default: 100)
|
|
325
|
+
subscribe: true // Subscribe to real-time updates (default: true)
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
const firstPage = await pagination.first(); // Jump to first page
|
|
329
|
+
const nextPage = await pagination.next(); // Go to next page
|
|
330
|
+
const prevPage = await pagination.prev(); // Go to previous page
|
|
331
|
+
|
|
332
|
+
// Check pagination state
|
|
333
|
+
console.log(firstPage.hasNext); // boolean
|
|
334
|
+
console.log(firstPage.hasPrev); // boolean
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Watch Changes
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
users.query()
|
|
341
|
+
.eq('status', 'active')
|
|
342
|
+
.changes()
|
|
343
|
+
.subscribe(changes => {
|
|
344
|
+
console.log('Inserts:', changes.inserts);
|
|
345
|
+
console.log('Updates:', changes.updates);
|
|
346
|
+
console.log('Deletes:', changes.deletes);
|
|
347
|
+
});
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
## Transactions
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
await squid.runInTransaction(async (txId) => {
|
|
354
|
+
const userRef = squid.collection('users').doc('user-1');
|
|
355
|
+
const accountRef = squid.collection('accounts').doc('acc-1');
|
|
356
|
+
|
|
357
|
+
// Pass txId as last parameter to each operation
|
|
358
|
+
// Use incrementInPath/decrementInPath for numeric operations
|
|
359
|
+
await userRef.decrementInPath('balance', 100, txId);
|
|
360
|
+
await accountRef.incrementInPath('balance', 100, txId);
|
|
361
|
+
|
|
362
|
+
// Both commit together or rollback together
|
|
363
|
+
});
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Numeric Operations
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
// Increment/decrement
|
|
370
|
+
await userDoc.incrementInPath('loginCount', 1);
|
|
371
|
+
await userDoc.decrementInPath('credits', 50);
|
|
372
|
+
|
|
373
|
+
// For arrays/objects, use update() with full new value
|
|
374
|
+
const currentData = await userDoc.snapshot();
|
|
375
|
+
await userDoc.update({
|
|
376
|
+
tags: [...currentData.tags, 'newTag'],
|
|
377
|
+
notifications: [...currentData.notifications, { msg: 'Hi' }]
|
|
378
|
+
});
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
## Native Queries
|
|
382
|
+
|
|
383
|
+
For advanced queries that require database-specific syntax:
|
|
384
|
+
|
|
385
|
+
### SQL (PostgreSQL, MySQL, etc.)
|
|
386
|
+
Uses `${param}` syntax for parameters:
|
|
387
|
+
```typescript
|
|
388
|
+
const users = await squid.executeNativeRelationalQuery<User[]>(
|
|
389
|
+
'postgres-db',
|
|
390
|
+
'SELECT * FROM users WHERE age > ${minAge}',
|
|
391
|
+
{ minAge: 18 }
|
|
392
|
+
);
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### MongoDB Aggregation
|
|
396
|
+
```typescript
|
|
397
|
+
const orders = await squid.executeNativeMongoQuery<Order[]>(
|
|
398
|
+
'mongo-db',
|
|
399
|
+
'orders',
|
|
400
|
+
[
|
|
401
|
+
{ $match: { status: 'completed' } },
|
|
402
|
+
{ $group: { _id: '$userId', total: { $sum: '$amount' } } }
|
|
403
|
+
]
|
|
404
|
+
);
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Elasticsearch
|
|
408
|
+
```typescript
|
|
409
|
+
const products = await squid.executeNativeElasticQuery(
|
|
410
|
+
'elastic-db',
|
|
411
|
+
'products',
|
|
412
|
+
{ query: { match: { name: 'laptop' } } },
|
|
413
|
+
'_search', // endpoint (optional)
|
|
414
|
+
'GET' // method (optional)
|
|
415
|
+
);
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Pure (Finos Legend Pure Language)
|
|
419
|
+
Uses `${param}` syntax:
|
|
420
|
+
```typescript
|
|
421
|
+
const items = await squid.executeNativePureQuery(
|
|
422
|
+
'my-db',
|
|
423
|
+
'from products->filter(p | $p.price < ${maxPrice})',
|
|
424
|
+
{ maxPrice: 1000 }
|
|
425
|
+
);
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
## Backend Decorator: @trigger
|
|
429
|
+
|
|
430
|
+
Responds to database collection changes:
|
|
431
|
+
|
|
432
|
+
```typescript
|
|
433
|
+
import { SquidService, trigger, TriggerRequest } from '@squidcloud/backend';
|
|
434
|
+
|
|
435
|
+
export class MyService extends SquidService {
|
|
436
|
+
@trigger({ id: 'user-created', collection: 'users', mutationTypes: ['insert'] })
|
|
437
|
+
async onUserCreated(request: TriggerRequest<User>): Promise<void> {
|
|
438
|
+
console.log(request.mutationType); // 'insert' | 'update' | 'delete'
|
|
439
|
+
console.log(request.docBefore);
|
|
440
|
+
console.log(request.docAfter);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## Schema Discovery
|
|
446
|
+
|
|
447
|
+
AI-powered schema analysis for database integrations:
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
const integrations = squid.admin().integrations();
|
|
451
|
+
|
|
452
|
+
// Discover schema from a database connection
|
|
453
|
+
const discovered = await integrations.discoverDataConnectionSchema('postgres-db');
|
|
454
|
+
console.log(discovered.schema); // Discovered tables, columns, relationships
|
|
455
|
+
console.log(discovered.collectionReadiness); // Permission and replication status
|
|
456
|
+
|
|
457
|
+
// Generate AI descriptions for data schema
|
|
458
|
+
const schemaResult = await integrations.generateAiDescriptionsForDataSchema('postgres-db', {
|
|
459
|
+
schema: currentSchema,
|
|
460
|
+
collections: ['users', 'orders'],
|
|
461
|
+
instructions: 'Use business terminology'
|
|
462
|
+
});
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
For security rules on databases, see [security.md](security.md).
|
|
466
|
+
|
|
467
|
+
## Best Practices
|
|
468
|
+
|
|
469
|
+
1. **Use transactions for multi-doc updates** - Atomic operations prevent partial updates
|
|
470
|
+
2. **Limit query results** - Default 1000, max 20000
|
|
471
|
+
3. **Use snapshots for one-time data** - Use subscriptions only for real-time needs
|
|
472
|
+
4. **Batch operations when possible** - Use insertMany, deleteMany for efficiency
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# OpenAI Provider Features
|
|
2
|
+
|
|
3
|
+
OpenAI-specific features in Squid. For general AI usage, see [ai.md](ai.md).
|
|
4
|
+
|
|
5
|
+
## Model Constants
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import {
|
|
9
|
+
OPENAI_CHAT_MODEL_NAMES, // Chat models
|
|
10
|
+
OPENAI_IMAGE_MODEL_NAMES, // DALL-E
|
|
11
|
+
OPENAI_AUDIO_TRANSCRIPTION_MODEL_NAMES, // Whisper
|
|
12
|
+
OPENAI_AUDIO_CREATE_SPEECH_MODEL_NAMES, // TTS
|
|
13
|
+
OPENAI_EMBEDDINGS_MODEL_NAMES, // Embeddings
|
|
14
|
+
} from '@squidcloud/client';
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Source of truth:** `node_modules/@squidcloud/client/dist/internal-common/src/public-types/ai-common.public-types.d.ts`
|
|
18
|
+
|
|
19
|
+
## OpenAI-Specific Parameters
|
|
20
|
+
|
|
21
|
+
### Verbosity Control
|
|
22
|
+
|
|
23
|
+
Controls response length. OpenAI plain text responses only (ignored for other providers).
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
const response = await agent.ask('Explain quantum computing', {
|
|
27
|
+
verbosity: 'low' // 'low' | 'medium' | 'high'
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Reasoning Models
|
|
32
|
+
|
|
33
|
+
o-series and gpt-5 series models support `reasoningEffort` (no temperature support):
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
const response = await agent.ask('Complex problem...', {
|
|
37
|
+
reasoningEffort: 'high' // 'minimal' | 'low' | 'medium' | 'high'
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Code Interpreter
|
|
42
|
+
|
|
43
|
+
Execute Python code with file access. Supported by **OpenAI, Gemini, and Claude** models.
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
const response = await agent.ask('Analyze this data', {
|
|
47
|
+
useCodeInterpreter: 'llm',
|
|
48
|
+
fileIds: [fileId] // from squid.ai().files('openai').uploadFile()
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Squid's Built-in Code Interpreter
|
|
53
|
+
|
|
54
|
+
Squid also provides its own code interpreter via the `executePythonCode` AI function, which executes prepared Python code independently of the LLM provider.
|
|
55
|
+
|
|
56
|
+
## File Upload
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
const aiFiles = squid.ai().files('openai');
|
|
60
|
+
const fileId = await aiFiles.uploadFile({ file: myFile, purpose: 'assistants' });
|
|
61
|
+
await aiFiles.deleteFile(fileId);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Voice (TTS)
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const voiceResult = await agent.askWithVoiceResponse('Hello', {
|
|
68
|
+
voiceOptions: {
|
|
69
|
+
modelName: 'tts-1', // see OPENAI_AUDIO_CREATE_SPEECH_MODEL_NAMES
|
|
70
|
+
voice: 'alloy', // alloy, ash, ballad, coral, echo, fable, onyx, nova, sage, shimmer, verse
|
|
71
|
+
speed: 1.0 // 0.25 to 4.0
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Image Generation (DALL-E)
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const imageUrl = await squid.ai().image().generate('A futuristic city', {
|
|
80
|
+
modelName: 'dall-e-3',
|
|
81
|
+
quality: 'hd', // 'hd' | 'standard'
|
|
82
|
+
size: '1024x1024' // '1024x1024' | '1792x1024' | '1024x1792'
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Audio Transcription (Whisper)
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const text = await squid.ai().audio().transcribe(audioFile, {
|
|
90
|
+
modelName: 'whisper-1',
|
|
91
|
+
language: 'en',
|
|
92
|
+
responseFormat: 'text' // 'json' | 'text' | 'srt' | 'verbose_json' | 'vtt'
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## OpenAI-Compatible Providers
|
|
97
|
+
|
|
98
|
+
Squid supports any OpenAI-compatible API via `openai_compatible` integration type. Configure with custom `baseUrl`, API key, and model list. Supports chat and function calling (not code interpreter).
|