@xano/developer-mcp 1.0.5 → 1.0.7
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 +5 -0
- package/dist/templates/xanoscript-index.js +1 -0
- package/package.json +1 -1
- package/xanoscript_docs/README.md +53 -37
- package/xanoscript_docs/agents.md +13 -15
- package/xanoscript_docs/apis.md +25 -85
- package/xanoscript_docs/database.md +28 -31
- package/xanoscript_docs/ephemeral.md +5 -8
- package/xanoscript_docs/frontend.md +4 -7
- package/xanoscript_docs/functions.md +12 -63
- package/xanoscript_docs/integrations.md +5 -5
- package/xanoscript_docs/mcp-servers.md +10 -13
- package/xanoscript_docs/syntax.md +118 -48
- package/xanoscript_docs/tables.md +8 -11
- package/xanoscript_docs/tasks.md +6 -9
- package/xanoscript_docs/testing.md +5 -8
- package/xanoscript_docs/tools.md +3 -11
- package/xanoscript_docs/triggers.md +532 -0
- package/xanoscript_docs/types.md +21 -31
- package/xanoscript_docs/plan.md +0 -192
|
@@ -15,7 +15,7 @@ function "<name>" {
|
|
|
15
15
|
<type> <name> [filters=...] { description = "..." }
|
|
16
16
|
}
|
|
17
17
|
stack {
|
|
18
|
-
|
|
18
|
+
// Logic here
|
|
19
19
|
}
|
|
20
20
|
response = $result
|
|
21
21
|
}
|
|
@@ -63,20 +63,13 @@ Reference with path: `function.run "math/add" { ... }`
|
|
|
63
63
|
|
|
64
64
|
## Input Block
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
For complete type and filter reference, use `xanoscript_docs({ keyword: "input" })`.
|
|
67
67
|
|
|
68
68
|
```xs
|
|
69
69
|
input {
|
|
70
70
|
text name filters=trim
|
|
71
71
|
int age? filters=min:0
|
|
72
72
|
email contact filters=lower { sensitive = true }
|
|
73
|
-
object address? {
|
|
74
|
-
schema {
|
|
75
|
-
text street
|
|
76
|
-
text city
|
|
77
|
-
text zip
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
73
|
}
|
|
81
74
|
```
|
|
82
75
|
|
|
@@ -117,21 +110,21 @@ stack {
|
|
|
117
110
|
### Loops
|
|
118
111
|
```xs
|
|
119
112
|
stack {
|
|
120
|
-
|
|
113
|
+
// For loop (count-based)
|
|
121
114
|
for (10) {
|
|
122
115
|
each as $i {
|
|
123
116
|
debug.log { value = $i }
|
|
124
117
|
}
|
|
125
118
|
}
|
|
126
119
|
|
|
127
|
-
|
|
120
|
+
// Foreach (array iteration)
|
|
128
121
|
foreach ($input.items) {
|
|
129
122
|
each as $item {
|
|
130
123
|
debug.log { value = $item.name }
|
|
131
124
|
}
|
|
132
125
|
}
|
|
133
126
|
|
|
134
|
-
|
|
127
|
+
// While loop
|
|
135
128
|
while ($counter < 5) {
|
|
136
129
|
each {
|
|
137
130
|
math.add $counter { value = 1 }
|
|
@@ -158,49 +151,8 @@ stack {
|
|
|
158
151
|
```
|
|
159
152
|
|
|
160
153
|
### Error Handling
|
|
161
|
-
```xs
|
|
162
|
-
stack {
|
|
163
|
-
try_catch {
|
|
164
|
-
try {
|
|
165
|
-
function.run "risky_operation" { input = {} } as $result
|
|
166
|
-
}
|
|
167
|
-
catch {
|
|
168
|
-
debug.log { value = "Operation failed" }
|
|
169
|
-
var $result { value = null }
|
|
170
|
-
}
|
|
171
|
-
finally {
|
|
172
|
-
debug.log { value = "Cleanup complete" }
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
```
|
|
177
154
|
|
|
178
|
-
|
|
179
|
-
```xs
|
|
180
|
-
stack {
|
|
181
|
-
precondition ($input.amount > 0) {
|
|
182
|
-
error_type = "inputerror"
|
|
183
|
-
error = "Amount must be positive"
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
throw {
|
|
187
|
-
name = "ValidationError"
|
|
188
|
-
value = "Custom error message"
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
### Early Return
|
|
194
|
-
```xs
|
|
195
|
-
stack {
|
|
196
|
-
conditional {
|
|
197
|
-
if ($input.skip) {
|
|
198
|
-
return { value = null }
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
# Continue processing...
|
|
202
|
-
}
|
|
203
|
-
```
|
|
155
|
+
For complete error handling reference (preconditions, try-catch, throw, early return), use `xanoscript_docs({ keyword: "syntax" })`.
|
|
204
156
|
|
|
205
157
|
---
|
|
206
158
|
|
|
@@ -209,10 +161,10 @@ stack {
|
|
|
209
161
|
Specify what the function returns:
|
|
210
162
|
|
|
211
163
|
```xs
|
|
212
|
-
response = $total
|
|
213
|
-
response = { success: true, data: $result }
|
|
214
|
-
response = $items|first
|
|
215
|
-
response = null
|
|
164
|
+
response = $total // Single variable
|
|
165
|
+
response = { success: true, data: $result } // Object literal
|
|
166
|
+
response = $items|first // With filter
|
|
167
|
+
response = null // No return value
|
|
216
168
|
```
|
|
217
169
|
|
|
218
170
|
---
|
|
@@ -345,8 +297,5 @@ function "validate_email_unique" {
|
|
|
345
297
|
1. **Single responsibility** - Each function does one thing well
|
|
346
298
|
2. **Descriptive names** - Use verb_noun format: `calculate_total`, `validate_user`
|
|
347
299
|
3. **Organize in folders** - Group related functions: `utils/`, `auth/`, `orders/`
|
|
348
|
-
4. **
|
|
349
|
-
5. **
|
|
350
|
-
6. **Document purpose** - Add description field
|
|
351
|
-
7. **Return early** - Use return for guard clauses
|
|
352
|
-
8. **Keep stacks shallow** - Avoid deeply nested conditionals
|
|
300
|
+
4. **Return early** - Use return for guard clauses
|
|
301
|
+
5. **Keep stacks shallow** - Avoid deeply nested conditionals
|
|
@@ -182,20 +182,20 @@ cloud.elasticsearch.document {
|
|
|
182
182
|
|
|
183
183
|
### Key-Value Operations
|
|
184
184
|
```xs
|
|
185
|
-
|
|
185
|
+
// Set value
|
|
186
186
|
redis.set {
|
|
187
187
|
key = "user:123:session"
|
|
188
188
|
data = $session_data
|
|
189
|
-
ttl = 3600
|
|
189
|
+
ttl = 3600 // Expires in 1 hour
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
|
|
192
|
+
// Get value
|
|
193
193
|
redis.get { key = "user:123:session" } as $session
|
|
194
194
|
|
|
195
|
-
|
|
195
|
+
// Check exists
|
|
196
196
|
redis.has { key = "user:123:session" } as $exists
|
|
197
197
|
|
|
198
|
-
|
|
198
|
+
// Delete
|
|
199
199
|
redis.del { key = "user:123:session" }
|
|
200
200
|
```
|
|
201
201
|
|
|
@@ -147,18 +147,18 @@ mcp_server "CRM" {
|
|
|
147
147
|
### By Domain
|
|
148
148
|
```
|
|
149
149
|
mcp_servers/
|
|
150
|
-
├── support.xs
|
|
151
|
-
├── ecommerce.xs
|
|
152
|
-
├── analytics.xs
|
|
153
|
-
└── admin.xs
|
|
150
|
+
├── support.xs // Customer support tools
|
|
151
|
+
├── ecommerce.xs // Store management
|
|
152
|
+
├── analytics.xs // Reporting and metrics
|
|
153
|
+
└── admin.xs // Administrative functions
|
|
154
154
|
```
|
|
155
155
|
|
|
156
156
|
### By Access Level
|
|
157
157
|
```
|
|
158
158
|
mcp_servers/
|
|
159
|
-
├── public.xs
|
|
160
|
-
├── authenticated.xs
|
|
161
|
-
└── admin.xs
|
|
159
|
+
├── public.xs // Public-facing tools
|
|
160
|
+
├── authenticated.xs // Requires auth
|
|
161
|
+
└── admin.xs // Admin-only tools
|
|
162
162
|
```
|
|
163
163
|
|
|
164
164
|
---
|
|
@@ -182,9 +182,6 @@ The MCP protocol handles:
|
|
|
182
182
|
## Best Practices
|
|
183
183
|
|
|
184
184
|
1. **Clear naming** - Server name should indicate its purpose
|
|
185
|
-
2. **
|
|
186
|
-
3. **
|
|
187
|
-
4. **
|
|
188
|
-
5. **Use tags** - Organize servers by category
|
|
189
|
-
6. **Keep focused** - One domain per server (support, analytics, etc.)
|
|
190
|
-
7. **Document internally** - Use description for team documentation
|
|
185
|
+
2. **Comprehensive instructions** - Guide AI on server's overall purpose
|
|
186
|
+
3. **Logical tool grouping** - Group related tools in one server
|
|
187
|
+
4. **Keep focused** - One domain per server (support, analytics, etc.)
|
|
@@ -44,24 +44,24 @@ var $total { value = `$input.qty * $input.price` }
|
|
|
44
44
|
|
|
45
45
|
### Comparison
|
|
46
46
|
```xs
|
|
47
|
-
$a == $b
|
|
48
|
-
$a != $b
|
|
49
|
-
$a > $b
|
|
50
|
-
$a >= $b
|
|
51
|
-
$a < $b
|
|
52
|
-
$a <= $b
|
|
47
|
+
$a == $b // Equal
|
|
48
|
+
$a != $b // Not equal
|
|
49
|
+
$a > $b // Greater than
|
|
50
|
+
$a >= $b // Greater or equal
|
|
51
|
+
$a < $b // Less than
|
|
52
|
+
$a <= $b // Less or equal
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
### Logical
|
|
56
56
|
```xs
|
|
57
|
-
$a && $b
|
|
58
|
-
$a || $b
|
|
59
|
-
!$a
|
|
57
|
+
$a && $b // AND
|
|
58
|
+
$a || $b // OR
|
|
59
|
+
!$a // NOT
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
### Null-Safe Comparisons (DB Queries)
|
|
63
63
|
```xs
|
|
64
|
-
|
|
64
|
+
// In db.query where clauses - ignore condition if value is null
|
|
65
65
|
$db.post.category ==? $input.category
|
|
66
66
|
$db.post.date >=? $input.start_date
|
|
67
67
|
```
|
|
@@ -88,11 +88,11 @@ $db.post.date >=? $input.start_date
|
|
|
88
88
|
|
|
89
89
|
### Array Math
|
|
90
90
|
```xs
|
|
91
|
-
[1,2,3,4]|sum
|
|
92
|
-
[1,2,3,4]|avg
|
|
93
|
-
[1,2,3,4]|product
|
|
94
|
-
[5,2,8,1]|array_min
|
|
95
|
-
[5,2,8,1]|array_max
|
|
91
|
+
[1,2,3,4]|sum // 10
|
|
92
|
+
[1,2,3,4]|avg // 2.5
|
|
93
|
+
[1,2,3,4]|product // 24
|
|
94
|
+
[5,2,8,1]|array_min // 1
|
|
95
|
+
[5,2,8,1]|array_max // 8
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
### Trigonometry
|
|
@@ -123,10 +123,10 @@ $db.post.date >=? $input.start_date
|
|
|
123
123
|
|
|
124
124
|
### Regex
|
|
125
125
|
```xs
|
|
126
|
-
"/pattern/"|regex_matches:"subject"
|
|
127
|
-
"/(\w+)/"|regex_get_first_match:"test"
|
|
128
|
-
"/\w+/"|regex_get_all_matches:"a b c"
|
|
129
|
-
"/\s+/"|regex_replace:"-":"a b"
|
|
126
|
+
"/pattern/"|regex_matches:"subject" // Boolean match
|
|
127
|
+
"/(\w+)/"|regex_get_first_match:"test" // First match
|
|
128
|
+
"/\w+/"|regex_get_all_matches:"a b c" // All matches
|
|
129
|
+
"/\s+/"|regex_replace:"-":"a b" // Replace: "a-b"
|
|
130
130
|
```
|
|
131
131
|
|
|
132
132
|
---
|
|
@@ -155,36 +155,36 @@ $db.post.date >=? $input.start_date
|
|
|
155
155
|
|
|
156
156
|
### Functional Operations
|
|
157
157
|
```xs
|
|
158
|
-
|
|
159
|
-
[{v:1},{v:2}]|map:$$.v*2
|
|
158
|
+
// Map - transform each element
|
|
159
|
+
[{v:1},{v:2}]|map:$$.v*2 // [2,4]
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
[1,2,3,4]|filter:$$%2==0
|
|
161
|
+
// Filter - keep matching elements
|
|
162
|
+
[1,2,3,4]|filter:$$%2==0 // [2,4]
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
[{id:1},{id:2}]|find:$$.id==2
|
|
164
|
+
// Find - first matching element
|
|
165
|
+
[{id:1},{id:2}]|find:$$.id==2 // {id:2}
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
[{id:1},{id:2}]|findIndex:$$.id==2
|
|
167
|
+
// FindIndex - index of first match
|
|
168
|
+
[{id:1},{id:2}]|findIndex:$$.id==2 // 1
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
[1,2,3]|some:$$>2
|
|
170
|
+
// Some - any element matches?
|
|
171
|
+
[1,2,3]|some:$$>2 // true
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
[2,4,6]|every:$$%2==0
|
|
173
|
+
// Every - all elements match?
|
|
174
|
+
[2,4,6]|every:$$%2==0 // true
|
|
175
175
|
|
|
176
|
-
|
|
177
|
-
[1,2,3,4]|reduce:$$+$result:0
|
|
176
|
+
// Reduce - accumulate to single value
|
|
177
|
+
[1,2,3,4]|reduce:$$+$result:0 // 10
|
|
178
178
|
```
|
|
179
179
|
|
|
180
180
|
### Grouping & Indexing
|
|
181
181
|
```xs
|
|
182
|
-
|
|
182
|
+
// Group by property
|
|
183
183
|
[{g:"a",v:1},{g:"b",v:2},{g:"a",v:3}]|index_by:g
|
|
184
|
-
|
|
184
|
+
// {"a":[{g:"a",v:1},{g:"a",v:3}],"b":[{g:"b",v:2}]}
|
|
185
185
|
|
|
186
|
-
|
|
187
|
-
[{n:"z"},{n:"a"}]|sort:n:text:false
|
|
186
|
+
// Sort
|
|
187
|
+
[{n:"z"},{n:"a"}]|sort:n:text:false // Ascending by n
|
|
188
188
|
```
|
|
189
189
|
|
|
190
190
|
---
|
|
@@ -205,9 +205,9 @@ $db.post.date >=? $input.start_date
|
|
|
205
205
|
|
|
206
206
|
### Conditional Set
|
|
207
207
|
```xs
|
|
208
|
-
{a:1}|set_conditional:"b":2:true
|
|
209
|
-
{a:1}|set_ifnotempty:"b":"val"
|
|
210
|
-
{a:1}|set_ifnotnull:"b":$var
|
|
208
|
+
{a:1}|set_conditional:"b":2:true // {a:1,b:2} if condition true
|
|
209
|
+
{a:1}|set_ifnotempty:"b":"val" // Set only if val not empty
|
|
210
|
+
{a:1}|set_ifnotnull:"b":$var // Set only if $var not null
|
|
211
211
|
```
|
|
212
212
|
|
|
213
213
|
---
|
|
@@ -229,8 +229,8 @@ $db.post.date >=? $input.start_date
|
|
|
229
229
|
|
|
230
230
|
### Null Handling
|
|
231
231
|
```xs
|
|
232
|
-
null|first_notnull:0
|
|
233
|
-
""|first_notempty:"default"
|
|
232
|
+
null|first_notnull:0 // 0
|
|
233
|
+
""|first_notempty:"default" // "default"
|
|
234
234
|
```
|
|
235
235
|
|
|
236
236
|
---
|
|
@@ -249,12 +249,12 @@ null|first_notnull:0 # 0
|
|
|
249
249
|
|
|
250
250
|
### Timestamp Parts
|
|
251
251
|
```xs
|
|
252
|
-
$ts|timestamp_year
|
|
253
|
-
$ts|timestamp_month
|
|
254
|
-
$ts|timestamp_day_of_month
|
|
255
|
-
$ts|timestamp_hour
|
|
256
|
-
$ts|timestamp_minute
|
|
257
|
-
$ts|timestamp_day_of_week
|
|
252
|
+
$ts|timestamp_year // Year
|
|
253
|
+
$ts|timestamp_month // Month (1-12)
|
|
254
|
+
$ts|timestamp_day_of_month // Day (1-31)
|
|
255
|
+
$ts|timestamp_hour // Hour (0-23)
|
|
256
|
+
$ts|timestamp_minute // Minute (0-59)
|
|
257
|
+
$ts|timestamp_day_of_week // Day (0=Sunday)
|
|
258
258
|
```
|
|
259
259
|
|
|
260
260
|
---
|
|
@@ -312,3 +312,73 @@ Used in `db.query` where clauses:
|
|
|
312
312
|
$db.created_at|timestamp_add_days:7
|
|
313
313
|
$db.created_at|timestamp_subtract_hours:24
|
|
314
314
|
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Error Handling
|
|
319
|
+
|
|
320
|
+
### Preconditions
|
|
321
|
+
|
|
322
|
+
Validate conditions and throw typed errors:
|
|
323
|
+
|
|
324
|
+
```xs
|
|
325
|
+
precondition ($input.amount > 0) {
|
|
326
|
+
error_type = "inputerror"
|
|
327
|
+
error = "Amount must be positive"
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
precondition ($user != null) {
|
|
331
|
+
error_type = "notfound"
|
|
332
|
+
error = "User not found"
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
precondition ($user.id == $auth.id) {
|
|
336
|
+
error_type = "accessdenied"
|
|
337
|
+
error = "Not authorized"
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Error Types
|
|
342
|
+
|
|
343
|
+
| Type | HTTP Status | Use Case |
|
|
344
|
+
|------|-------------|----------|
|
|
345
|
+
| `inputerror` | 400 Bad Request | Invalid input data |
|
|
346
|
+
| `accessdenied` | 403 Forbidden | Authorization failure |
|
|
347
|
+
| `notfound` | 404 Not Found | Resource doesn't exist |
|
|
348
|
+
| `standard` | 500 Internal Server Error | General errors |
|
|
349
|
+
|
|
350
|
+
### Throwing Errors
|
|
351
|
+
|
|
352
|
+
```xs
|
|
353
|
+
throw {
|
|
354
|
+
name = "ValidationError"
|
|
355
|
+
value = "Custom error message"
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Try-Catch
|
|
360
|
+
|
|
361
|
+
```xs
|
|
362
|
+
try_catch {
|
|
363
|
+
try {
|
|
364
|
+
function.run "risky_operation" { input = {} } as $result
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
debug.log { value = "Operation failed" }
|
|
368
|
+
var $result { value = null }
|
|
369
|
+
}
|
|
370
|
+
finally {
|
|
371
|
+
debug.log { value = "Cleanup complete" }
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Early Return
|
|
377
|
+
|
|
378
|
+
```xs
|
|
379
|
+
conditional {
|
|
380
|
+
if ($input.skip) {
|
|
381
|
+
return { value = null }
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
```
|
|
@@ -10,9 +10,9 @@ Database table definitions in XanoScript.
|
|
|
10
10
|
|
|
11
11
|
```xs
|
|
12
12
|
table "<name>" {
|
|
13
|
-
auth = false
|
|
13
|
+
auth = false // true if used for authentication
|
|
14
14
|
schema {
|
|
15
|
-
int id
|
|
15
|
+
int id // Primary key (required)
|
|
16
16
|
text name filters=trim
|
|
17
17
|
timestamp created_at?=now
|
|
18
18
|
}
|
|
@@ -72,10 +72,10 @@ schema {
|
|
|
72
72
|
### Optional & Defaults
|
|
73
73
|
```xs
|
|
74
74
|
schema {
|
|
75
|
-
text nickname?
|
|
76
|
-
timestamp created_at?=now
|
|
77
|
-
bool is_active?=true
|
|
78
|
-
int status?=0
|
|
75
|
+
text nickname? // Optional, no default
|
|
76
|
+
timestamp created_at?=now // Optional, defaults to current time
|
|
77
|
+
bool is_active?=true // Optional, defaults to true
|
|
78
|
+
int status?=0 // Optional, defaults to 0
|
|
79
79
|
}
|
|
80
80
|
```
|
|
81
81
|
|
|
@@ -139,7 +139,7 @@ schema {
|
|
|
139
139
|
### Vector Fields
|
|
140
140
|
```xs
|
|
141
141
|
schema {
|
|
142
|
-
vector embedding
|
|
142
|
+
vector embedding // For AI/ML embeddings
|
|
143
143
|
}
|
|
144
144
|
```
|
|
145
145
|
|
|
@@ -264,7 +264,4 @@ table "order" {
|
|
|
264
264
|
2. **Use `auth = true`** only for authentication tables (typically just `user`)
|
|
265
265
|
3. **Add indexes** for fields used in WHERE clauses and JOINs
|
|
266
266
|
4. **Use appropriate types** - `email` for emails, `password` for credentials
|
|
267
|
-
5. **
|
|
268
|
-
6. **Use filters** - Apply `trim`, `lower` for consistency
|
|
269
|
-
7. **Default timestamps** - Use `?=now` for created_at fields
|
|
270
|
-
8. **Document with descriptions** - Add descriptions for non-obvious fields
|
|
267
|
+
5. **Default timestamps** - Use `?=now` for created_at fields
|
package/xanoscript_docs/tasks.md
CHANGED
|
@@ -222,7 +222,7 @@ task "risky_sync" {
|
|
|
222
222
|
url = "https://external-api.com/data"
|
|
223
223
|
method = "GET"
|
|
224
224
|
} as $data
|
|
225
|
-
|
|
225
|
+
// Process data...
|
|
226
226
|
}
|
|
227
227
|
catch {
|
|
228
228
|
util.send_email {
|
|
@@ -244,11 +244,8 @@ task "risky_sync" {
|
|
|
244
244
|
|
|
245
245
|
## Best Practices
|
|
246
246
|
|
|
247
|
-
1. **
|
|
248
|
-
2. **
|
|
249
|
-
3. **
|
|
250
|
-
4. **
|
|
251
|
-
5. **
|
|
252
|
-
6. **Consider timezone** - Schedule uses UTC (+0000)
|
|
253
|
-
7. **Batch operations** - Process in chunks for large datasets
|
|
254
|
-
8. **Set end dates** - Use ends_on for temporary schedules
|
|
247
|
+
1. **Descriptive names** - Indicate what and when: `daily_cleanup`, `hourly_sync`
|
|
248
|
+
2. **Handle errors** - Use try_catch for external dependencies
|
|
249
|
+
3. **Consider timezone** - Schedule uses UTC (+0000)
|
|
250
|
+
4. **Batch operations** - Process in chunks for large datasets
|
|
251
|
+
5. **Set end dates** - Use ends_on for temporary schedules
|
|
@@ -325,11 +325,8 @@ function "calculate_discount" {
|
|
|
325
325
|
|
|
326
326
|
## Best Practices
|
|
327
327
|
|
|
328
|
-
1. **Test happy paths** -
|
|
329
|
-
2. **
|
|
330
|
-
3. **
|
|
331
|
-
4. **
|
|
332
|
-
5. **
|
|
333
|
-
6. **One assertion focus** - Each test verifies one behavior
|
|
334
|
-
7. **Keep tests independent** - No shared state between tests
|
|
335
|
-
8. **Test at boundaries** - Min/max values, length limits
|
|
328
|
+
1. **Test happy paths, edge cases, and errors** - Cover expected, boundary, and failure scenarios
|
|
329
|
+
2. **Use mocks** - Isolate from external dependencies
|
|
330
|
+
3. **Descriptive test names** - Explain what's being tested
|
|
331
|
+
4. **One assertion focus** - Each test verifies one behavior
|
|
332
|
+
5. **Keep tests independent** - No shared state between tests
|
package/xanoscript_docs/tools.md
CHANGED
|
@@ -62,20 +62,15 @@ tool "get_user_by_email" {
|
|
|
62
62
|
|
|
63
63
|
## Input Block
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
For complete type reference, use `xanoscript_docs({ keyword: "input" })`. For tools, input `description` fields are sent to the AI, so write them clearly:
|
|
66
66
|
|
|
67
67
|
```xs
|
|
68
68
|
input {
|
|
69
|
-
int order_id {
|
|
70
|
-
description = "The unique order ID to look up"
|
|
71
|
-
}
|
|
69
|
+
int order_id { description = "The unique order ID to look up" }
|
|
72
70
|
enum status {
|
|
73
71
|
description = "New status to set"
|
|
74
72
|
values = ["pending", "processing", "shipped", "delivered"]
|
|
75
73
|
}
|
|
76
|
-
text reason? {
|
|
77
|
-
description = "Optional reason for the status change"
|
|
78
|
-
}
|
|
79
74
|
}
|
|
80
75
|
```
|
|
81
76
|
|
|
@@ -299,7 +294,4 @@ tool "cancel_order" {
|
|
|
299
294
|
2. **Describe all inputs** - Help AI construct valid requests
|
|
300
295
|
3. **Use enums for fixed options** - Reduces AI errors
|
|
301
296
|
4. **Keep tools focused** - One task per tool
|
|
302
|
-
5. **
|
|
303
|
-
6. **Validate inputs** - Use filters and preconditions
|
|
304
|
-
7. **Limit response size** - Don't return huge datasets
|
|
305
|
-
8. **Use composition** - Call other tools for complex operations
|
|
297
|
+
5. **Limit response size** - Don't return huge datasets
|