@noodleseed/agent-kit 0.16.0 → 0.17.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/manifest.json +13 -13
- package/package.json +1 -1
- package/skills/claude-code/SKILL.md +1 -1
- package/skills/claude-code/examples/food-ordering/src/server.ts +19 -19
- package/skills/claude-code/examples/weather/src/server.ts +29 -41
- package/skills/claude-code/references/authoring-workflow.md +10 -10
- package/skills/claude-code/references/connect-an-api.md +2 -2
- package/skills/claude-code/references/sdk-surface.md +6 -6
- package/skills/codex/SKILL.md +1 -1
- package/skills/codex/examples/food-ordering/src/server.ts +19 -19
- package/skills/codex/examples/weather/src/server.ts +29 -41
- package/skills/codex/references/authoring-workflow.md +10 -10
- package/skills/codex/references/connect-an-api.md +2 -2
- package/skills/codex/references/sdk-surface.md +6 -6
package/manifest.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
"packageVersion": "0.
|
|
2
|
+
"packageVersion": "0.17.0",
|
|
3
3
|
"files": [
|
|
4
4
|
{
|
|
5
5
|
"path": "skills/codex/SKILL.md",
|
|
6
|
-
"sha256": "
|
|
6
|
+
"sha256": "5f24dd83ca00ad0b078de17f0a978b28ee17b17678ab103a0151f550444e1c47",
|
|
7
7
|
"agentTarget": "codex"
|
|
8
8
|
},
|
|
9
9
|
{
|
|
10
10
|
"path": "skills/codex/references/sdk-surface.md",
|
|
11
|
-
"sha256": "
|
|
11
|
+
"sha256": "7275aedfb2338040f1b9f989765179ce970d1b25c77066b3d3f4f4e2fe39f7cc",
|
|
12
12
|
"agentTarget": "codex"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"path": "skills/codex/references/authoring-workflow.md",
|
|
31
|
-
"sha256": "
|
|
31
|
+
"sha256": "bf59d1550ce72fa188e50e74b7d586be49a0e5473501ee3b83a5f41687ac5163",
|
|
32
32
|
"agentTarget": "codex"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"path": "skills/codex/references/connect-an-api.md",
|
|
36
|
-
"sha256": "
|
|
36
|
+
"sha256": "497221256ebb78300b5e4055daff3f222052a7b78fb829fd24171668dd7fc0fa",
|
|
37
37
|
"agentTarget": "codex"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
@@ -268,7 +268,7 @@
|
|
|
268
268
|
},
|
|
269
269
|
{
|
|
270
270
|
"path": "skills/codex/examples/food-ordering/src/server.ts",
|
|
271
|
-
"sha256": "
|
|
271
|
+
"sha256": "491e7e7e8289d4295d09ca2a5f7035f00a06e1d9f3349c406397f90a966269df",
|
|
272
272
|
"agentTarget": "codex"
|
|
273
273
|
},
|
|
274
274
|
{
|
|
@@ -338,7 +338,7 @@
|
|
|
338
338
|
},
|
|
339
339
|
{
|
|
340
340
|
"path": "skills/codex/examples/weather/src/server.ts",
|
|
341
|
-
"sha256": "
|
|
341
|
+
"sha256": "95cd3a2ef47be898469d40d109f3fb89ac6e59a34fd8ad600c80dfe2908d4598",
|
|
342
342
|
"agentTarget": "codex"
|
|
343
343
|
},
|
|
344
344
|
{
|
|
@@ -348,12 +348,12 @@
|
|
|
348
348
|
},
|
|
349
349
|
{
|
|
350
350
|
"path": "skills/claude-code/SKILL.md",
|
|
351
|
-
"sha256": "
|
|
351
|
+
"sha256": "24cdedbf4db8484b6e06823037b5b8fd0ef7ee39a57eb0fd135d167196fea3ff",
|
|
352
352
|
"agentTarget": "claude-code"
|
|
353
353
|
},
|
|
354
354
|
{
|
|
355
355
|
"path": "skills/claude-code/references/sdk-surface.md",
|
|
356
|
-
"sha256": "
|
|
356
|
+
"sha256": "7275aedfb2338040f1b9f989765179ce970d1b25c77066b3d3f4f4e2fe39f7cc",
|
|
357
357
|
"agentTarget": "claude-code"
|
|
358
358
|
},
|
|
359
359
|
{
|
|
@@ -373,12 +373,12 @@
|
|
|
373
373
|
},
|
|
374
374
|
{
|
|
375
375
|
"path": "skills/claude-code/references/authoring-workflow.md",
|
|
376
|
-
"sha256": "
|
|
376
|
+
"sha256": "bf59d1550ce72fa188e50e74b7d586be49a0e5473501ee3b83a5f41687ac5163",
|
|
377
377
|
"agentTarget": "claude-code"
|
|
378
378
|
},
|
|
379
379
|
{
|
|
380
380
|
"path": "skills/claude-code/references/connect-an-api.md",
|
|
381
|
-
"sha256": "
|
|
381
|
+
"sha256": "497221256ebb78300b5e4055daff3f222052a7b78fb829fd24171668dd7fc0fa",
|
|
382
382
|
"agentTarget": "claude-code"
|
|
383
383
|
},
|
|
384
384
|
{
|
|
@@ -613,7 +613,7 @@
|
|
|
613
613
|
},
|
|
614
614
|
{
|
|
615
615
|
"path": "skills/claude-code/examples/food-ordering/src/server.ts",
|
|
616
|
-
"sha256": "
|
|
616
|
+
"sha256": "491e7e7e8289d4295d09ca2a5f7035f00a06e1d9f3349c406397f90a966269df",
|
|
617
617
|
"agentTarget": "claude-code"
|
|
618
618
|
},
|
|
619
619
|
{
|
|
@@ -683,7 +683,7 @@
|
|
|
683
683
|
},
|
|
684
684
|
{
|
|
685
685
|
"path": "skills/claude-code/examples/weather/src/server.ts",
|
|
686
|
-
"sha256": "
|
|
686
|
+
"sha256": "95cd3a2ef47be898469d40d109f3fb89ac6e59a34fd8ad600c80dfe2908d4598",
|
|
687
687
|
"agentTarget": "claude-code"
|
|
688
688
|
},
|
|
689
689
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noodleseed/agent-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Self-checking, self-updating agent skills for the Noodle Seed CLI. Authored in this repo by @noodle-borg/agent-kit; this is the published, independently-versioned canonical skills artifact the CLI fetches and verifies.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -17,28 +17,28 @@ const state = connector('noodle_state')
|
|
|
17
17
|
.version('1.0.0')
|
|
18
18
|
.operation('read_state', {
|
|
19
19
|
type: 'read',
|
|
20
|
-
input: {
|
|
21
|
-
handle:
|
|
22
|
-
key:
|
|
23
|
-
},
|
|
24
|
-
output: {
|
|
25
|
-
value:
|
|
26
|
-
revision:
|
|
27
|
-
status:
|
|
28
|
-
},
|
|
20
|
+
input: z.object({
|
|
21
|
+
handle: z.string(),
|
|
22
|
+
key: z.string().optional(),
|
|
23
|
+
}),
|
|
24
|
+
output: z.object({
|
|
25
|
+
value: z.record(z.string(), z.unknown()),
|
|
26
|
+
revision: z.number().int(),
|
|
27
|
+
status: z.string(),
|
|
28
|
+
}),
|
|
29
29
|
})
|
|
30
30
|
.operation('patch_state', {
|
|
31
31
|
type: 'action',
|
|
32
|
-
input: {
|
|
33
|
-
handle:
|
|
34
|
-
expectedRevision:
|
|
35
|
-
value:
|
|
36
|
-
},
|
|
37
|
-
output: {
|
|
38
|
-
value:
|
|
39
|
-
revision:
|
|
40
|
-
status:
|
|
41
|
-
},
|
|
32
|
+
input: z.object({
|
|
33
|
+
handle: z.string(),
|
|
34
|
+
expectedRevision: z.number().int(),
|
|
35
|
+
value: z.record(z.string(), z.unknown()),
|
|
36
|
+
}),
|
|
37
|
+
output: z.object({
|
|
38
|
+
value: z.record(z.string(), z.unknown()),
|
|
39
|
+
revision: z.number().int(),
|
|
40
|
+
status: z.string(),
|
|
41
|
+
}),
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
const stores = [
|
|
@@ -19,13 +19,13 @@ const geocoding = connector('open_meteo_geocoding')
|
|
|
19
19
|
method: 'GET',
|
|
20
20
|
path: '/v1/search',
|
|
21
21
|
query: ['name'],
|
|
22
|
-
input: { name:
|
|
23
|
-
output: {
|
|
24
|
-
latitude:
|
|
25
|
-
longitude:
|
|
26
|
-
place:
|
|
27
|
-
country:
|
|
28
|
-
},
|
|
22
|
+
input: z.object({ name: z.string() }),
|
|
23
|
+
output: z.object({
|
|
24
|
+
latitude: z.number(),
|
|
25
|
+
longitude: z.number(),
|
|
26
|
+
place: z.string().optional(),
|
|
27
|
+
country: z.string().optional(),
|
|
28
|
+
}),
|
|
29
29
|
response: {
|
|
30
30
|
latitude: '${response.results[0].latitude}',
|
|
31
31
|
longitude: '${response.results[0].longitude}',
|
|
@@ -44,13 +44,8 @@ const geocoding = connector('open_meteo_geocoding')
|
|
|
44
44
|
method: 'GET',
|
|
45
45
|
path: '/v1/search',
|
|
46
46
|
query: ['name', 'count'],
|
|
47
|
-
input: {
|
|
48
|
-
|
|
49
|
-
count: { type: 'number' },
|
|
50
|
-
},
|
|
51
|
-
output: {
|
|
52
|
-
results: { type: 'array' },
|
|
53
|
-
},
|
|
47
|
+
input: z.object({ name: z.string(), count: z.number().optional() }),
|
|
48
|
+
output: z.object({ results: z.array(z.unknown()).optional() }),
|
|
54
49
|
response: {
|
|
55
50
|
results: '${response.results}',
|
|
56
51
|
},
|
|
@@ -69,15 +64,12 @@ const forecast = connector('open_meteo_forecast')
|
|
|
69
64
|
method: 'GET',
|
|
70
65
|
path: '/v1/forecast?current_weather=true',
|
|
71
66
|
query: ['latitude', 'longitude'],
|
|
72
|
-
input: {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
windspeed: { type: 'number' },
|
|
79
|
-
weathercode: { type: 'number' },
|
|
80
|
-
},
|
|
67
|
+
input: z.object({ latitude: z.number(), longitude: z.number() }),
|
|
68
|
+
output: z.object({
|
|
69
|
+
temperature: z.number().optional(),
|
|
70
|
+
windspeed: z.number().optional(),
|
|
71
|
+
weathercode: z.number().optional(),
|
|
72
|
+
}),
|
|
81
73
|
response: {
|
|
82
74
|
temperature: '${response.current_weather.temperature}',
|
|
83
75
|
windspeed: '${response.current_weather.windspeed}',
|
|
@@ -91,18 +83,18 @@ const brief = connector('weather_brief')
|
|
|
91
83
|
.version('1.0.0')
|
|
92
84
|
.compute('summarize', {
|
|
93
85
|
type: 'read',
|
|
94
|
-
input: {
|
|
95
|
-
place:
|
|
96
|
-
country:
|
|
97
|
-
temperature:
|
|
98
|
-
windspeed:
|
|
99
|
-
weathercode:
|
|
100
|
-
},
|
|
101
|
-
output: {
|
|
102
|
-
conditions:
|
|
103
|
-
headline:
|
|
104
|
-
advice:
|
|
105
|
-
},
|
|
86
|
+
input: z.object({
|
|
87
|
+
place: z.string(),
|
|
88
|
+
country: z.string().optional(),
|
|
89
|
+
temperature: z.number(),
|
|
90
|
+
windspeed: z.number(),
|
|
91
|
+
weathercode: z.number(),
|
|
92
|
+
}),
|
|
93
|
+
output: z.object({
|
|
94
|
+
conditions: z.string(),
|
|
95
|
+
headline: z.string(),
|
|
96
|
+
advice: z.string(),
|
|
97
|
+
}),
|
|
106
98
|
// A real function — type-checked here, serialized to source and run in the sandbox. It must be
|
|
107
99
|
// self-contained: no imports, no closure over outer variables, synchronous.
|
|
108
100
|
run: (input) => {
|
|
@@ -162,12 +154,8 @@ const placeNarrow = connector('geo_places')
|
|
|
162
154
|
.version('1.0.0')
|
|
163
155
|
.compute('narrow', {
|
|
164
156
|
type: 'read',
|
|
165
|
-
input: {
|
|
166
|
-
|
|
167
|
-
},
|
|
168
|
-
output: {
|
|
169
|
-
places: { type: 'array', required: true },
|
|
170
|
-
},
|
|
157
|
+
input: z.object({ results: z.unknown().optional() }),
|
|
158
|
+
output: z.object({ places: z.array(z.unknown()) }),
|
|
171
159
|
// Self-contained: no imports, no closure over outer variables, synchronous.
|
|
172
160
|
run: (input) => {
|
|
173
161
|
const raw = input.results;
|
|
@@ -55,16 +55,16 @@ const crm = connector('crm').version('1.0.0').http({
|
|
|
55
55
|
method: 'GET',
|
|
56
56
|
path: '/customers',
|
|
57
57
|
query: ['email'],
|
|
58
|
-
input: { email:
|
|
59
|
-
output: { id:
|
|
58
|
+
input: z.object({ email: z.string() }),
|
|
59
|
+
output: z.object({ id: z.string(), name: z.string().optional() }),
|
|
60
60
|
response: { id: '${response.data[0].id}', name: '${response.data[0].name}' },
|
|
61
61
|
},
|
|
62
62
|
create_ticket: {
|
|
63
63
|
type: 'action',
|
|
64
64
|
method: 'POST',
|
|
65
65
|
path: '/tickets',
|
|
66
|
-
input: { customer_id:
|
|
67
|
-
output: { ticket_id:
|
|
66
|
+
input: z.object({ customer_id: z.string(), body: z.string() }),
|
|
67
|
+
output: z.object({ ticket_id: z.string() }),
|
|
68
68
|
request: { customer_id: '${args.customer_id}', body: '${args.body}' },
|
|
69
69
|
response: { ticket_id: '${response.id}' },
|
|
70
70
|
},
|
|
@@ -120,16 +120,16 @@ const tasks = connector('tasks').version('1.0.0').http({
|
|
|
120
120
|
method: 'GET',
|
|
121
121
|
path: '/tasks',
|
|
122
122
|
query: ['query'],
|
|
123
|
-
input: { query:
|
|
124
|
-
output: { matches:
|
|
123
|
+
input: z.object({ query: z.string() }),
|
|
124
|
+
output: z.object({ matches: z.array(z.unknown()) }),
|
|
125
125
|
response: { matches: '${response.results}' },
|
|
126
126
|
},
|
|
127
127
|
close_task: {
|
|
128
128
|
type: 'action',
|
|
129
129
|
method: 'POST',
|
|
130
130
|
path: '/tasks/{id}/close',
|
|
131
|
-
input: { id:
|
|
132
|
-
output: { ok:
|
|
131
|
+
input: z.object({ id: z.string() }),
|
|
132
|
+
output: z.object({ ok: z.boolean() }),
|
|
133
133
|
response: { ok: '${response.ok}' },
|
|
134
134
|
},
|
|
135
135
|
},
|
|
@@ -163,8 +163,8 @@ The model never sees a task id from the user; `find_tasks` returns `{ id, title
|
|
|
163
163
|
|
|
164
164
|
```ts
|
|
165
165
|
const scoring = connector('scoring').version('1.0.0').compute('normalize', {
|
|
166
|
-
input: { email:
|
|
167
|
-
output: { score:
|
|
166
|
+
input: z.object({ email: z.string(), priority: z.string().optional() }),
|
|
167
|
+
output: z.object({ score: z.number() }),
|
|
168
168
|
calls: { find_customer: 'crm.find_customer' },
|
|
169
169
|
limits: { timeoutMs: 1000, maxHostCalls: 2 },
|
|
170
170
|
run(input, { callOperation }) {
|
|
@@ -62,7 +62,7 @@ Most real tools return a variable-length list (search results, a user’s tasks)
|
|
|
62
62
|
|
|
63
63
|
```ts
|
|
64
64
|
// The API returns { results: [ { id, name, country, … }, … ] }
|
|
65
|
-
output: { places:
|
|
65
|
+
output: z.object({ places: z.array(z.unknown()) }),
|
|
66
66
|
response: { places: '${response.results}' },
|
|
67
67
|
```
|
|
68
68
|
|
|
@@ -96,7 +96,7 @@ Pair the read/list with the mutations your intent tools need:
|
|
|
96
96
|
```ts
|
|
97
97
|
close_task: {
|
|
98
98
|
type: 'action', method: 'POST', path: '/tasks/{id}/close',
|
|
99
|
-
input: { id:
|
|
99
|
+
input: z.object({ id: z.string() }),
|
|
100
100
|
responseType: 'empty',
|
|
101
101
|
},
|
|
102
102
|
```
|
|
@@ -144,8 +144,8 @@ const crm = connector('crm')
|
|
|
144
144
|
method: 'GET',
|
|
145
145
|
path: '/tickets',
|
|
146
146
|
query: ['id'],
|
|
147
|
-
input: { id:
|
|
148
|
-
output: { subject:
|
|
147
|
+
input: z.object({ id: z.string() }),
|
|
148
|
+
output: z.object({ subject: z.string().optional(), status: z.string().optional() }),
|
|
149
149
|
response: { subject: '${response.subject}', status: '${response.status}' },
|
|
150
150
|
},
|
|
151
151
|
},
|
|
@@ -195,8 +195,8 @@ const orders = connector('orders')
|
|
|
195
195
|
method: 'GET',
|
|
196
196
|
path: '/orders',
|
|
197
197
|
query: ['id'],
|
|
198
|
-
input: { id:
|
|
199
|
-
output: { id:
|
|
198
|
+
input: z.object({ id: z.string() }),
|
|
199
|
+
output: z.object({ id: z.string().optional(), status: z.string().optional() }),
|
|
200
200
|
response: { id: '${response.id}', status: '${response.status}' },
|
|
201
201
|
},
|
|
202
202
|
get_tracking: {
|
|
@@ -204,8 +204,8 @@ const orders = connector('orders')
|
|
|
204
204
|
method: 'GET',
|
|
205
205
|
path: '/tracking',
|
|
206
206
|
query: ['order_id'],
|
|
207
|
-
input: { order_id:
|
|
208
|
-
output: { url:
|
|
207
|
+
input: z.object({ order_id: z.string() }),
|
|
208
|
+
output: z.object({ url: z.string().optional() }),
|
|
209
209
|
response: { url: '${response.url}' },
|
|
210
210
|
},
|
|
211
211
|
},
|
package/skills/codex/SKILL.md
CHANGED
|
@@ -17,28 +17,28 @@ const state = connector('noodle_state')
|
|
|
17
17
|
.version('1.0.0')
|
|
18
18
|
.operation('read_state', {
|
|
19
19
|
type: 'read',
|
|
20
|
-
input: {
|
|
21
|
-
handle:
|
|
22
|
-
key:
|
|
23
|
-
},
|
|
24
|
-
output: {
|
|
25
|
-
value:
|
|
26
|
-
revision:
|
|
27
|
-
status:
|
|
28
|
-
},
|
|
20
|
+
input: z.object({
|
|
21
|
+
handle: z.string(),
|
|
22
|
+
key: z.string().optional(),
|
|
23
|
+
}),
|
|
24
|
+
output: z.object({
|
|
25
|
+
value: z.record(z.string(), z.unknown()),
|
|
26
|
+
revision: z.number().int(),
|
|
27
|
+
status: z.string(),
|
|
28
|
+
}),
|
|
29
29
|
})
|
|
30
30
|
.operation('patch_state', {
|
|
31
31
|
type: 'action',
|
|
32
|
-
input: {
|
|
33
|
-
handle:
|
|
34
|
-
expectedRevision:
|
|
35
|
-
value:
|
|
36
|
-
},
|
|
37
|
-
output: {
|
|
38
|
-
value:
|
|
39
|
-
revision:
|
|
40
|
-
status:
|
|
41
|
-
},
|
|
32
|
+
input: z.object({
|
|
33
|
+
handle: z.string(),
|
|
34
|
+
expectedRevision: z.number().int(),
|
|
35
|
+
value: z.record(z.string(), z.unknown()),
|
|
36
|
+
}),
|
|
37
|
+
output: z.object({
|
|
38
|
+
value: z.record(z.string(), z.unknown()),
|
|
39
|
+
revision: z.number().int(),
|
|
40
|
+
status: z.string(),
|
|
41
|
+
}),
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
const stores = [
|
|
@@ -19,13 +19,13 @@ const geocoding = connector('open_meteo_geocoding')
|
|
|
19
19
|
method: 'GET',
|
|
20
20
|
path: '/v1/search',
|
|
21
21
|
query: ['name'],
|
|
22
|
-
input: { name:
|
|
23
|
-
output: {
|
|
24
|
-
latitude:
|
|
25
|
-
longitude:
|
|
26
|
-
place:
|
|
27
|
-
country:
|
|
28
|
-
},
|
|
22
|
+
input: z.object({ name: z.string() }),
|
|
23
|
+
output: z.object({
|
|
24
|
+
latitude: z.number(),
|
|
25
|
+
longitude: z.number(),
|
|
26
|
+
place: z.string().optional(),
|
|
27
|
+
country: z.string().optional(),
|
|
28
|
+
}),
|
|
29
29
|
response: {
|
|
30
30
|
latitude: '${response.results[0].latitude}',
|
|
31
31
|
longitude: '${response.results[0].longitude}',
|
|
@@ -44,13 +44,8 @@ const geocoding = connector('open_meteo_geocoding')
|
|
|
44
44
|
method: 'GET',
|
|
45
45
|
path: '/v1/search',
|
|
46
46
|
query: ['name', 'count'],
|
|
47
|
-
input: {
|
|
48
|
-
|
|
49
|
-
count: { type: 'number' },
|
|
50
|
-
},
|
|
51
|
-
output: {
|
|
52
|
-
results: { type: 'array' },
|
|
53
|
-
},
|
|
47
|
+
input: z.object({ name: z.string(), count: z.number().optional() }),
|
|
48
|
+
output: z.object({ results: z.array(z.unknown()).optional() }),
|
|
54
49
|
response: {
|
|
55
50
|
results: '${response.results}',
|
|
56
51
|
},
|
|
@@ -69,15 +64,12 @@ const forecast = connector('open_meteo_forecast')
|
|
|
69
64
|
method: 'GET',
|
|
70
65
|
path: '/v1/forecast?current_weather=true',
|
|
71
66
|
query: ['latitude', 'longitude'],
|
|
72
|
-
input: {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
windspeed: { type: 'number' },
|
|
79
|
-
weathercode: { type: 'number' },
|
|
80
|
-
},
|
|
67
|
+
input: z.object({ latitude: z.number(), longitude: z.number() }),
|
|
68
|
+
output: z.object({
|
|
69
|
+
temperature: z.number().optional(),
|
|
70
|
+
windspeed: z.number().optional(),
|
|
71
|
+
weathercode: z.number().optional(),
|
|
72
|
+
}),
|
|
81
73
|
response: {
|
|
82
74
|
temperature: '${response.current_weather.temperature}',
|
|
83
75
|
windspeed: '${response.current_weather.windspeed}',
|
|
@@ -91,18 +83,18 @@ const brief = connector('weather_brief')
|
|
|
91
83
|
.version('1.0.0')
|
|
92
84
|
.compute('summarize', {
|
|
93
85
|
type: 'read',
|
|
94
|
-
input: {
|
|
95
|
-
place:
|
|
96
|
-
country:
|
|
97
|
-
temperature:
|
|
98
|
-
windspeed:
|
|
99
|
-
weathercode:
|
|
100
|
-
},
|
|
101
|
-
output: {
|
|
102
|
-
conditions:
|
|
103
|
-
headline:
|
|
104
|
-
advice:
|
|
105
|
-
},
|
|
86
|
+
input: z.object({
|
|
87
|
+
place: z.string(),
|
|
88
|
+
country: z.string().optional(),
|
|
89
|
+
temperature: z.number(),
|
|
90
|
+
windspeed: z.number(),
|
|
91
|
+
weathercode: z.number(),
|
|
92
|
+
}),
|
|
93
|
+
output: z.object({
|
|
94
|
+
conditions: z.string(),
|
|
95
|
+
headline: z.string(),
|
|
96
|
+
advice: z.string(),
|
|
97
|
+
}),
|
|
106
98
|
// A real function — type-checked here, serialized to source and run in the sandbox. It must be
|
|
107
99
|
// self-contained: no imports, no closure over outer variables, synchronous.
|
|
108
100
|
run: (input) => {
|
|
@@ -162,12 +154,8 @@ const placeNarrow = connector('geo_places')
|
|
|
162
154
|
.version('1.0.0')
|
|
163
155
|
.compute('narrow', {
|
|
164
156
|
type: 'read',
|
|
165
|
-
input: {
|
|
166
|
-
|
|
167
|
-
},
|
|
168
|
-
output: {
|
|
169
|
-
places: { type: 'array', required: true },
|
|
170
|
-
},
|
|
157
|
+
input: z.object({ results: z.unknown().optional() }),
|
|
158
|
+
output: z.object({ places: z.array(z.unknown()) }),
|
|
171
159
|
// Self-contained: no imports, no closure over outer variables, synchronous.
|
|
172
160
|
run: (input) => {
|
|
173
161
|
const raw = input.results;
|
|
@@ -55,16 +55,16 @@ const crm = connector('crm').version('1.0.0').http({
|
|
|
55
55
|
method: 'GET',
|
|
56
56
|
path: '/customers',
|
|
57
57
|
query: ['email'],
|
|
58
|
-
input: { email:
|
|
59
|
-
output: { id:
|
|
58
|
+
input: z.object({ email: z.string() }),
|
|
59
|
+
output: z.object({ id: z.string(), name: z.string().optional() }),
|
|
60
60
|
response: { id: '${response.data[0].id}', name: '${response.data[0].name}' },
|
|
61
61
|
},
|
|
62
62
|
create_ticket: {
|
|
63
63
|
type: 'action',
|
|
64
64
|
method: 'POST',
|
|
65
65
|
path: '/tickets',
|
|
66
|
-
input: { customer_id:
|
|
67
|
-
output: { ticket_id:
|
|
66
|
+
input: z.object({ customer_id: z.string(), body: z.string() }),
|
|
67
|
+
output: z.object({ ticket_id: z.string() }),
|
|
68
68
|
request: { customer_id: '${args.customer_id}', body: '${args.body}' },
|
|
69
69
|
response: { ticket_id: '${response.id}' },
|
|
70
70
|
},
|
|
@@ -120,16 +120,16 @@ const tasks = connector('tasks').version('1.0.0').http({
|
|
|
120
120
|
method: 'GET',
|
|
121
121
|
path: '/tasks',
|
|
122
122
|
query: ['query'],
|
|
123
|
-
input: { query:
|
|
124
|
-
output: { matches:
|
|
123
|
+
input: z.object({ query: z.string() }),
|
|
124
|
+
output: z.object({ matches: z.array(z.unknown()) }),
|
|
125
125
|
response: { matches: '${response.results}' },
|
|
126
126
|
},
|
|
127
127
|
close_task: {
|
|
128
128
|
type: 'action',
|
|
129
129
|
method: 'POST',
|
|
130
130
|
path: '/tasks/{id}/close',
|
|
131
|
-
input: { id:
|
|
132
|
-
output: { ok:
|
|
131
|
+
input: z.object({ id: z.string() }),
|
|
132
|
+
output: z.object({ ok: z.boolean() }),
|
|
133
133
|
response: { ok: '${response.ok}' },
|
|
134
134
|
},
|
|
135
135
|
},
|
|
@@ -163,8 +163,8 @@ The model never sees a task id from the user; `find_tasks` returns `{ id, title
|
|
|
163
163
|
|
|
164
164
|
```ts
|
|
165
165
|
const scoring = connector('scoring').version('1.0.0').compute('normalize', {
|
|
166
|
-
input: { email:
|
|
167
|
-
output: { score:
|
|
166
|
+
input: z.object({ email: z.string(), priority: z.string().optional() }),
|
|
167
|
+
output: z.object({ score: z.number() }),
|
|
168
168
|
calls: { find_customer: 'crm.find_customer' },
|
|
169
169
|
limits: { timeoutMs: 1000, maxHostCalls: 2 },
|
|
170
170
|
run(input, { callOperation }) {
|
|
@@ -62,7 +62,7 @@ Most real tools return a variable-length list (search results, a user’s tasks)
|
|
|
62
62
|
|
|
63
63
|
```ts
|
|
64
64
|
// The API returns { results: [ { id, name, country, … }, … ] }
|
|
65
|
-
output: { places:
|
|
65
|
+
output: z.object({ places: z.array(z.unknown()) }),
|
|
66
66
|
response: { places: '${response.results}' },
|
|
67
67
|
```
|
|
68
68
|
|
|
@@ -96,7 +96,7 @@ Pair the read/list with the mutations your intent tools need:
|
|
|
96
96
|
```ts
|
|
97
97
|
close_task: {
|
|
98
98
|
type: 'action', method: 'POST', path: '/tasks/{id}/close',
|
|
99
|
-
input: { id:
|
|
99
|
+
input: z.object({ id: z.string() }),
|
|
100
100
|
responseType: 'empty',
|
|
101
101
|
},
|
|
102
102
|
```
|
|
@@ -144,8 +144,8 @@ const crm = connector('crm')
|
|
|
144
144
|
method: 'GET',
|
|
145
145
|
path: '/tickets',
|
|
146
146
|
query: ['id'],
|
|
147
|
-
input: { id:
|
|
148
|
-
output: { subject:
|
|
147
|
+
input: z.object({ id: z.string() }),
|
|
148
|
+
output: z.object({ subject: z.string().optional(), status: z.string().optional() }),
|
|
149
149
|
response: { subject: '${response.subject}', status: '${response.status}' },
|
|
150
150
|
},
|
|
151
151
|
},
|
|
@@ -195,8 +195,8 @@ const orders = connector('orders')
|
|
|
195
195
|
method: 'GET',
|
|
196
196
|
path: '/orders',
|
|
197
197
|
query: ['id'],
|
|
198
|
-
input: { id:
|
|
199
|
-
output: { id:
|
|
198
|
+
input: z.object({ id: z.string() }),
|
|
199
|
+
output: z.object({ id: z.string().optional(), status: z.string().optional() }),
|
|
200
200
|
response: { id: '${response.id}', status: '${response.status}' },
|
|
201
201
|
},
|
|
202
202
|
get_tracking: {
|
|
@@ -204,8 +204,8 @@ const orders = connector('orders')
|
|
|
204
204
|
method: 'GET',
|
|
205
205
|
path: '/tracking',
|
|
206
206
|
query: ['order_id'],
|
|
207
|
-
input: { order_id:
|
|
208
|
-
output: { url:
|
|
207
|
+
input: z.object({ order_id: z.string() }),
|
|
208
|
+
output: z.object({ url: z.string().optional() }),
|
|
209
209
|
response: { url: '${response.url}' },
|
|
210
210
|
},
|
|
211
211
|
},
|