@koi-language/koi 1.0.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/QUICKSTART.md +89 -0
- package/README.md +545 -0
- package/examples/actions-demo.koi +177 -0
- package/examples/cache-test.koi +29 -0
- package/examples/calculator.koi +61 -0
- package/examples/clear-registry.js +33 -0
- package/examples/clear-registry.koi +30 -0
- package/examples/code-introspection-test.koi +149 -0
- package/examples/counter.koi +132 -0
- package/examples/delegation-test.koi +52 -0
- package/examples/directory-import-test.koi +84 -0
- package/examples/hello-world-claude.koi +52 -0
- package/examples/hello-world.koi +52 -0
- package/examples/hello.koi +24 -0
- package/examples/mcp-example.koi +70 -0
- package/examples/multi-event-handler-test.koi +144 -0
- package/examples/new-import-test.koi +89 -0
- package/examples/pipeline.koi +162 -0
- package/examples/registry-demo.koi +184 -0
- package/examples/registry-playbook-demo.koi +162 -0
- package/examples/registry-playbook-email-compositor-2.koi +140 -0
- package/examples/registry-playbook-email-compositor.koi +140 -0
- package/examples/sentiment.koi +90 -0
- package/examples/simple.koi +48 -0
- package/examples/skill-import-test.koi +76 -0
- package/examples/skills/advanced/index.koi +95 -0
- package/examples/skills/math-operations.koi +69 -0
- package/examples/skills/string-operations.koi +56 -0
- package/examples/task-chaining-demo.koi +244 -0
- package/examples/test-await.koi +22 -0
- package/examples/test-crypto-sha256.koi +196 -0
- package/examples/test-delegation.koi +41 -0
- package/examples/test-multi-team-routing.koi +258 -0
- package/examples/test-no-handler.koi +35 -0
- package/examples/test-npm-import.koi +67 -0
- package/examples/test-parse.koi +10 -0
- package/examples/test-peers-with-team.koi +59 -0
- package/examples/test-permissions-fail.koi +20 -0
- package/examples/test-permissions.koi +36 -0
- package/examples/test-simple-registry.koi +31 -0
- package/examples/test-typescript-import.koi +64 -0
- package/examples/test-uses-team-syntax.koi +25 -0
- package/examples/test-uses-team.koi +31 -0
- package/examples/utils/calculator.test.ts +144 -0
- package/examples/utils/calculator.ts +56 -0
- package/examples/utils/math-helpers.js +50 -0
- package/examples/utils/math-helpers.ts +55 -0
- package/examples/web-delegation-demo.koi +165 -0
- package/package.json +78 -0
- package/src/cli/koi.js +793 -0
- package/src/compiler/build-optimizer.js +447 -0
- package/src/compiler/cache-manager.js +274 -0
- package/src/compiler/import-resolver.js +369 -0
- package/src/compiler/parser.js +7542 -0
- package/src/compiler/transpiler.js +1105 -0
- package/src/compiler/typescript-transpiler.js +148 -0
- package/src/grammar/koi.pegjs +767 -0
- package/src/runtime/action-registry.js +172 -0
- package/src/runtime/actions/call-skill.js +45 -0
- package/src/runtime/actions/format.js +115 -0
- package/src/runtime/actions/print.js +42 -0
- package/src/runtime/actions/registry-delete.js +37 -0
- package/src/runtime/actions/registry-get.js +37 -0
- package/src/runtime/actions/registry-keys.js +33 -0
- package/src/runtime/actions/registry-search.js +34 -0
- package/src/runtime/actions/registry-set.js +50 -0
- package/src/runtime/actions/return.js +31 -0
- package/src/runtime/actions/send-message.js +58 -0
- package/src/runtime/actions/update-state.js +36 -0
- package/src/runtime/agent.js +1368 -0
- package/src/runtime/cli-logger.js +205 -0
- package/src/runtime/incremental-json-parser.js +201 -0
- package/src/runtime/index.js +33 -0
- package/src/runtime/llm-provider.js +1372 -0
- package/src/runtime/mcp-client.js +1171 -0
- package/src/runtime/planner.js +273 -0
- package/src/runtime/registry-backends/keyv-sqlite.js +215 -0
- package/src/runtime/registry-backends/local.js +260 -0
- package/src/runtime/registry.js +162 -0
- package/src/runtime/role.js +14 -0
- package/src/runtime/router.js +395 -0
- package/src/runtime/runtime.js +113 -0
- package/src/runtime/skill-selector.js +173 -0
- package/src/runtime/skill.js +25 -0
- package/src/runtime/team.js +162 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// Registry Demo - Shared data store between agents
|
|
2
|
+
package "registry.demo"
|
|
3
|
+
|
|
4
|
+
role Worker { can execute }
|
|
5
|
+
|
|
6
|
+
// Agent that writes data to the registry
|
|
7
|
+
Agent Writer : Worker {
|
|
8
|
+
on saveUser(args: Json) {
|
|
9
|
+
const userId = args.id
|
|
10
|
+
const userData = {
|
|
11
|
+
name: args.name,
|
|
12
|
+
age: args.age,
|
|
13
|
+
email: args.email,
|
|
14
|
+
createdAt: Date.now()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
await registry.set("user:" + userId, userData)
|
|
18
|
+
|
|
19
|
+
console.log("✅ Saved user:", userId)
|
|
20
|
+
return { saved: true, userId: userId }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
on saveConfig(args: Json) {
|
|
24
|
+
await registry.set("config:app", {
|
|
25
|
+
theme: args.theme || "dark",
|
|
26
|
+
language: args.language || "en",
|
|
27
|
+
notifications: args.notifications !== false
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
console.log("✅ Saved config")
|
|
31
|
+
return { saved: true }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Agent that reads data from the registry
|
|
36
|
+
Agent Reader : Worker {
|
|
37
|
+
on getUser(args: Json) {
|
|
38
|
+
const userId = args.id
|
|
39
|
+
const user = await registry.get("user:" + userId)
|
|
40
|
+
|
|
41
|
+
if (!user) {
|
|
42
|
+
console.log("❌ User not found:", userId)
|
|
43
|
+
return { found: false, userId: userId }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log("📖 Retrieved user:", user.name)
|
|
47
|
+
return { found: true, user: user }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
on getConfig(args: Json) {
|
|
51
|
+
const config = await registry.get("config:app")
|
|
52
|
+
|
|
53
|
+
if (!config) {
|
|
54
|
+
console.log("⚙️ No config found, using defaults")
|
|
55
|
+
return { found: false, config: null }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
console.log("⚙️ Retrieved config:", JSON.stringify(config))
|
|
59
|
+
return { found: true, config: config }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
on listUsers(args: Json) {
|
|
63
|
+
const userKeys = await registry.keys("user:")
|
|
64
|
+
console.log("📋 Found", userKeys.length, "users")
|
|
65
|
+
|
|
66
|
+
const users = []
|
|
67
|
+
for (const key of userKeys) {
|
|
68
|
+
const user = await registry.get(key)
|
|
69
|
+
users.push({ id: key.replace("user:", ""), ...user })
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return { count: users.length, users: users }
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Agent that searches the registry
|
|
77
|
+
Agent Searcher : Worker {
|
|
78
|
+
on findAdults(args: Json) {
|
|
79
|
+
const results = await registry.search({
|
|
80
|
+
age: { $gte: 18 }
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
console.log("🔍 Found", results.length, "adults")
|
|
84
|
+
|
|
85
|
+
const adults = results.map(r => ({
|
|
86
|
+
id: r.key.replace("user:", ""),
|
|
87
|
+
...r.value
|
|
88
|
+
}))
|
|
89
|
+
|
|
90
|
+
return { count: adults.length, adults: adults }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
on findByName(args: Json) {
|
|
94
|
+
const results = await registry.search({
|
|
95
|
+
name: { $regex: args.pattern }
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
console.log("🔍 Found", results.length, "matching users")
|
|
99
|
+
|
|
100
|
+
const matches = results.map(r => ({
|
|
101
|
+
id: r.key.replace("user:", ""),
|
|
102
|
+
...r.value
|
|
103
|
+
}))
|
|
104
|
+
|
|
105
|
+
return { count: matches.length, matches: matches }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Orchestrator that coordinates the demo
|
|
110
|
+
Agent Demo : Worker {
|
|
111
|
+
on start(args: Json) {
|
|
112
|
+
console.log("═════════════════════════════════════════════")
|
|
113
|
+
console.log(" Registry Demo - Shared Data Store")
|
|
114
|
+
console.log("═════════════════════════════════════════════")
|
|
115
|
+
console.log("")
|
|
116
|
+
|
|
117
|
+
// 1. Save some users
|
|
118
|
+
console.log("1️⃣ Saving users...")
|
|
119
|
+
await Writer.handle("saveUser", { id: "001", name: "Alice", age: 30, email: "alice@example.com" })
|
|
120
|
+
await Writer.handle("saveUser", { id: "002", name: "Bob", age: 25, email: "bob@example.com" })
|
|
121
|
+
await Writer.handle("saveUser", { id: "003", name: "Charlie", age: 17, email: "charlie@example.com" })
|
|
122
|
+
await Writer.handle("saveUser", { id: "004", name: "Diana", age: 35, email: "diana@example.com" })
|
|
123
|
+
console.log("")
|
|
124
|
+
|
|
125
|
+
// 2. Save config
|
|
126
|
+
console.log("2️⃣ Saving config...")
|
|
127
|
+
await Writer.handle("saveConfig", { theme: "light", language: "es", notifications: true })
|
|
128
|
+
console.log("")
|
|
129
|
+
|
|
130
|
+
// 3. Read individual user
|
|
131
|
+
console.log("3️⃣ Reading user...")
|
|
132
|
+
const userResult = await Reader.handle("getUser", { id: "001" })
|
|
133
|
+
console.log(" User:", JSON.stringify(userResult.user, null, 2))
|
|
134
|
+
console.log("")
|
|
135
|
+
|
|
136
|
+
// 4. Read config
|
|
137
|
+
console.log("4️⃣ Reading config...")
|
|
138
|
+
const configResult = await Reader.handle("getConfig", {})
|
|
139
|
+
console.log(" Config:", JSON.stringify(configResult.config, null, 2))
|
|
140
|
+
console.log("")
|
|
141
|
+
|
|
142
|
+
// 5. List all users
|
|
143
|
+
console.log("5️⃣ Listing all users...")
|
|
144
|
+
const listResult = await Reader.handle("listUsers", {})
|
|
145
|
+
for (const user of listResult.users) {
|
|
146
|
+
console.log(" -", user.name, "(" + user.age + " years old)")
|
|
147
|
+
}
|
|
148
|
+
console.log("")
|
|
149
|
+
|
|
150
|
+
// 6. Search for adults
|
|
151
|
+
console.log("6️⃣ Searching for adults (age >= 18)...")
|
|
152
|
+
const adultsResult = await Searcher.handle("findAdults", {})
|
|
153
|
+
for (const adult of adultsResult.adults) {
|
|
154
|
+
console.log(" -", adult.name, "(" + adult.age + " years old)")
|
|
155
|
+
}
|
|
156
|
+
console.log("")
|
|
157
|
+
|
|
158
|
+
// 7. Search by name pattern
|
|
159
|
+
console.log("7️⃣ Searching for names containing 'a'...")
|
|
160
|
+
const searchResult = await Searcher.handle("findByName", { pattern: "a" })
|
|
161
|
+
for (const match of searchResult.matches) {
|
|
162
|
+
console.log(" -", match.name)
|
|
163
|
+
}
|
|
164
|
+
console.log("")
|
|
165
|
+
|
|
166
|
+
// 8. Show stats
|
|
167
|
+
console.log("8️⃣ Registry stats...")
|
|
168
|
+
const stats = await registry.stats()
|
|
169
|
+
console.log(" Backend:", stats.backend)
|
|
170
|
+
console.log(" Entries:", stats.count)
|
|
171
|
+
console.log(" File:", stats.file)
|
|
172
|
+
console.log(" Size:", stats.size, "bytes")
|
|
173
|
+
console.log("")
|
|
174
|
+
|
|
175
|
+
console.log("═════════════════════════════════════════════")
|
|
176
|
+
console.log(" Demo Complete!")
|
|
177
|
+
console.log(" Data persisted to:", stats.file)
|
|
178
|
+
console.log("═════════════════════════════════════════════")
|
|
179
|
+
|
|
180
|
+
return { success: true }
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
run Demo.start({})
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// Registry with Natural Language Playbooks Demo
|
|
2
|
+
// Shows how agents can use registry operations naturally in playbooks
|
|
3
|
+
package "registry.playbook.demo"
|
|
4
|
+
|
|
5
|
+
role Worker { can execute, can registry }
|
|
6
|
+
role Manager { can execute, can delegate }
|
|
7
|
+
|
|
8
|
+
// Agent that uses natural language to interact with registry
|
|
9
|
+
Agent UserManager : Worker {
|
|
10
|
+
llm default = { provider: "openai", model: "gpt-4o-mini" }
|
|
11
|
+
|
|
12
|
+
on createAllUser(args: Json) {
|
|
13
|
+
playbook """
|
|
14
|
+
Create all given users via args, with the following attributes
|
|
15
|
+
- name, age, email
|
|
16
|
+
|
|
17
|
+
Save all to registry with key "user:id being id an unique identifier".
|
|
18
|
+
Include all fields plus a createdAt timestamp.
|
|
19
|
+
Return: { "success": true, "message": "Users created" }
|
|
20
|
+
|
|
21
|
+
DO NOT add print actions - just return the data.
|
|
22
|
+
"""
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
on createUser(args: Json) {
|
|
26
|
+
playbook """
|
|
27
|
+
Create a new user with:
|
|
28
|
+
- name: ${args.name}
|
|
29
|
+
- age: ${args.age}
|
|
30
|
+
- email: ${args.email}
|
|
31
|
+
|
|
32
|
+
Save to registry with key "user:${args.id}".
|
|
33
|
+
Include all fields plus a createdAt timestamp.
|
|
34
|
+
Return: { "success": true, "message": "User created" }
|
|
35
|
+
|
|
36
|
+
DO NOT add print actions - just return the data.
|
|
37
|
+
"""
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
on getUser(args: Json) {
|
|
41
|
+
playbook """
|
|
42
|
+
Get user ${args.id} from registry.
|
|
43
|
+
|
|
44
|
+
Use registry_get with key "user:${args.id}".
|
|
45
|
+
Extract the .value field from the registry_get result (which contains the user data).
|
|
46
|
+
Return ONLY the user data object (name, age, email, createdAt) without any wrapper.
|
|
47
|
+
"""
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
on listAllUsers(args: Json) {
|
|
51
|
+
playbook """
|
|
52
|
+
List all users in the registry.
|
|
53
|
+
|
|
54
|
+
EXACT STEPS:
|
|
55
|
+
1. Use registry_search with an empty query {} to get ALL users, store with ID "a1"
|
|
56
|
+
2. Extract just the user data (the .value field) from each result
|
|
57
|
+
3. Return: { "count": <count from a1>, "users": <array of user value objects, NOT the full {key, value} wrappers> }
|
|
58
|
+
|
|
59
|
+
Example: If a1.output.results = [{key: "user:001", value: {name: "Alice", age: 30}}, ...]
|
|
60
|
+
Then return: { "count": 2, "users": [{name: "Alice", age: 30}, ...] }
|
|
61
|
+
|
|
62
|
+
CRITICAL: Extract ONLY the .value objects so caller can access with .users[0].name directly
|
|
63
|
+
DO NOT use format action - return a real array!
|
|
64
|
+
"""
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
on findAdults(args: Json) {
|
|
68
|
+
playbook """
|
|
69
|
+
Find all users aged 18 or older using registry search with query: { "age": { "$gte": 18 } }
|
|
70
|
+
|
|
71
|
+
EXACT STEPS:
|
|
72
|
+
1. Use registry_search with query: { "age": { "$gte": 18 } }
|
|
73
|
+
2. Return: { "count": [count from search], "adults": [results array] }
|
|
74
|
+
|
|
75
|
+
DO NOT add print actions - just return the data!
|
|
76
|
+
"""
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
on updateUserAge(args: Json) {
|
|
80
|
+
playbook """
|
|
81
|
+
Update user ${args.id}'s age to ${args.age}.
|
|
82
|
+
|
|
83
|
+
EXACT STEPS:
|
|
84
|
+
1. Use registry_get with key "user:${args.id}", store with ID "a1"
|
|
85
|
+
2. Take the full user object from \${a1.output.value}
|
|
86
|
+
3. Modify ONLY the age field to ${args.age}, keep all other fields (name, email, createdAt, etc.)
|
|
87
|
+
4. Use registry_set with key "user:${args.id}" and the complete updated object
|
|
88
|
+
5. Return: { "success": true, "message": "Age updated" }
|
|
89
|
+
|
|
90
|
+
CRITICAL: Preserve ALL existing fields when saving!
|
|
91
|
+
"""
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
on deleteUser(args: Json) {
|
|
95
|
+
playbook """
|
|
96
|
+
Borra el usuario del registro con ID ${args.id}.
|
|
97
|
+
|
|
98
|
+
EXACT STEPS:
|
|
99
|
+
1. Use registry_delete with key "user:\${args.id}"
|
|
100
|
+
2. Return: { "success": true, "message": "User deleted" }
|
|
101
|
+
"""
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Team that groups our agents
|
|
106
|
+
Team RegistryTeam {
|
|
107
|
+
userManager = UserManager
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Orchestrator - uses playbook, router finds UserManager automatically!
|
|
111
|
+
Agent Demo : Manager {
|
|
112
|
+
llm default = { provider: "openai", model: "gpt-4o-mini" }
|
|
113
|
+
uses Team RegistryTeam
|
|
114
|
+
|
|
115
|
+
on start(args: Json) {
|
|
116
|
+
//SUPER IMPORTANT: DO NOT CHANGE THE FOLLOWING PROMPT AT ALL!!!!!!
|
|
117
|
+
playbook """
|
|
118
|
+
Ejecuta un demo del registro de usuarios.
|
|
119
|
+
|
|
120
|
+
Muestra el header:
|
|
121
|
+
╔══════════════════════════════════════════════════╗
|
|
122
|
+
║ Registry with Playbook Demo ║
|
|
123
|
+
╚══════════════════════════════════════════════════╝
|
|
124
|
+
|
|
125
|
+
1️⃣ Crea estos usuarios:
|
|
126
|
+
- Alice: id=001, age=30, email=alice@example.com
|
|
127
|
+
- Bob: id=002, de 17 años, bob@example.com
|
|
128
|
+
- Charlie: id=003, age=25, email=charlie@example.com
|
|
129
|
+
- Diana: id=004, age is 35, diana@example.com
|
|
130
|
+
- Erika: id=005, age=28, email=erika@example.com
|
|
131
|
+
- Fernando: id=006, age=32, fernando@example.com
|
|
132
|
+
Muestra: " ✅ X users created" X es la cantidad de usuarios que se crearon
|
|
133
|
+
|
|
134
|
+
2️⃣ Obtén el usuario 001
|
|
135
|
+
Muestra: " ✅ Found user: {el nombre del usuario}, age {su edad}"
|
|
136
|
+
|
|
137
|
+
3️⃣ Lista todos los usuarios
|
|
138
|
+
Muestra: " ✅ Found {la cantidad de usuarios} users y luego por cada uno muestra en una tabla en markdown: sr o sra si es chico o chica (esto deducelo por el nombre) y luego {el nombre del usuario}, age {su edad}"
|
|
139
|
+
|
|
140
|
+
4️⃣ Busca usuarios mayores de 18 años
|
|
141
|
+
Muestra: " ✅ Found {la cantidad encontrada} adults"
|
|
142
|
+
|
|
143
|
+
5️⃣ Actualiza la edad de Bob (002) a 19 años
|
|
144
|
+
Luego obtén el usuario actualizado
|
|
145
|
+
Muestra: " ✅ Bob is now {su nueva edad} years old"
|
|
146
|
+
|
|
147
|
+
6️⃣ Elimina a Charlie (003)
|
|
148
|
+
Luego lista los usuarios restantes
|
|
149
|
+
Muestra: " ✅ Remaining users: {la cantidad restante}"
|
|
150
|
+
|
|
151
|
+
7️⃣ Vuelve a listar todos los usuarios como lo has hecho en el paso 3️⃣
|
|
152
|
+
Muestra los usuarios que hay en la tabla en markdown con el mismo formato que en el paso 3️⃣
|
|
153
|
+
|
|
154
|
+
Muestra el footer:
|
|
155
|
+
╔══════════════════════════════════════════════════╗
|
|
156
|
+
║ Demo completed successfully! ║
|
|
157
|
+
╚══════════════════════════════════════════════════╝
|
|
158
|
+
"""
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
run Demo.start({})
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Registry with Natural Language Playbooks Demo
|
|
2
|
+
// Shows how agents can use registry operations naturally in playbooks
|
|
3
|
+
package "registry.playbook.demo"
|
|
4
|
+
|
|
5
|
+
role Worker { can execute, can registry }
|
|
6
|
+
role Manager { can execute, can delegate }
|
|
7
|
+
|
|
8
|
+
// Agent that uses natural language to interact with registry
|
|
9
|
+
Agent UserManager : Worker {
|
|
10
|
+
llm default = { provider: "openai", model: "gpt-4o-mini" }
|
|
11
|
+
|
|
12
|
+
on createUser(args: Json) {
|
|
13
|
+
playbook """
|
|
14
|
+
Create a new user with ALL fields from args:
|
|
15
|
+
- name: ${args.name}
|
|
16
|
+
- age: ${args.age}
|
|
17
|
+
- email: ${args.email}
|
|
18
|
+
- birthdate: ${args.birthdate} (if provided)
|
|
19
|
+
- id: ${args.id}
|
|
20
|
+
|
|
21
|
+
Save to registry with key "user:${args.id}".
|
|
22
|
+
CRITICAL: Include ALL fields from args (name, age, email, birthdate, id) plus a createdAt timestamp.
|
|
23
|
+
Return: { "success": true, "message": "User created" }
|
|
24
|
+
|
|
25
|
+
DO NOT add print actions - just return the data.
|
|
26
|
+
"""
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
on getUser(args: Json) {
|
|
30
|
+
playbook """
|
|
31
|
+
Get user ${args.id} from registry.
|
|
32
|
+
|
|
33
|
+
Use registry_get with key "user:${args.id}".
|
|
34
|
+
Extract the .value field from the registry_get result (which contains the user data).
|
|
35
|
+
Return ONLY the user data object (name, age, email, createdAt) without any wrapper.
|
|
36
|
+
"""
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
on listAllUsers(args: Json) {
|
|
40
|
+
playbook """
|
|
41
|
+
List all users in the registry.
|
|
42
|
+
|
|
43
|
+
EXACT STEPS:
|
|
44
|
+
1. Use registry_search with an empty query {} to get ALL users, store with ID "a1"
|
|
45
|
+
2. Extract just the user data (the .value field) from each result
|
|
46
|
+
3. Return: { "count": <count from a1>, "users": <array of user value objects, NOT the full {key, value} wrappers> }
|
|
47
|
+
|
|
48
|
+
Example: If a1.output.results = [{key: "user:001", value: {name: "Alice", age: 30}}, ...]
|
|
49
|
+
Then return: { "count": 2, "users": [{name: "Alice", age: 30}, ...] }
|
|
50
|
+
|
|
51
|
+
CRITICAL: Extract ONLY the .value objects so caller can access with .users[0].name directly
|
|
52
|
+
DO NOT use format action - return a real array!
|
|
53
|
+
"""
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
on findAdults(args: Json) {
|
|
57
|
+
playbook """
|
|
58
|
+
Find all users aged 18 or older using registry search with query: { "age": { "$gte": 18 } }
|
|
59
|
+
|
|
60
|
+
EXACT STEPS:
|
|
61
|
+
1. Use registry_search with query: { "age": { "$gte": 18 } }
|
|
62
|
+
2. Return: { "count": [count from search], "adults": [results array] }
|
|
63
|
+
|
|
64
|
+
DO NOT add print actions - just return the data!
|
|
65
|
+
"""
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
on updateUserAge(args: Json) {
|
|
69
|
+
playbook """
|
|
70
|
+
Update user ${args.id}'s age to ${args.age}.
|
|
71
|
+
|
|
72
|
+
EXACT STEPS:
|
|
73
|
+
1. Use registry_get with key "user:${args.id}", store with ID "a1"
|
|
74
|
+
2. Take the full user object from \${a1.output.value}
|
|
75
|
+
3. Modify ONLY the age field to ${args.age}, keep all other fields (name, email, createdAt, etc.)
|
|
76
|
+
4. Use registry_set with key "user:${args.id}" and the complete updated object
|
|
77
|
+
5. Return: { "success": true, "message": "Age updated" }
|
|
78
|
+
|
|
79
|
+
CRITICAL: Preserve ALL existing fields when saving!
|
|
80
|
+
"""
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
on deleteUser(args: Json) {
|
|
84
|
+
playbook """
|
|
85
|
+
Borra el usuario del registro con ID ${args.id}.
|
|
86
|
+
|
|
87
|
+
EXACT STEPS:
|
|
88
|
+
1. Use registry_delete with key "user:\${args.id}"
|
|
89
|
+
2. Return: { "success": true, "message": "User deleted" }
|
|
90
|
+
"""
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Team that groups our agents
|
|
95
|
+
Team RegistryTeam {
|
|
96
|
+
userManager = UserManager
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Orchestrator - uses playbook, router finds UserManager automatically!
|
|
100
|
+
Agent Demo : Manager {
|
|
101
|
+
llm default = { provider: "openai", model: "gpt-4o-mini" }
|
|
102
|
+
uses Team RegistryTeam
|
|
103
|
+
|
|
104
|
+
on start(args: Json) {
|
|
105
|
+
//SUPER IMPORTANT: DO NOT CHANGE THE FOLLOWING PROMPT AT ALL!!!!!!
|
|
106
|
+
playbook """
|
|
107
|
+
Ejecuta un demo del registro de usuarios.
|
|
108
|
+
|
|
109
|
+
Muestra el header:
|
|
110
|
+
╔══════════════════════════════════════════════════╗
|
|
111
|
+
║ Registry with Playbook Demo ║
|
|
112
|
+
╚══════════════════════════════════════════════════╝
|
|
113
|
+
|
|
114
|
+
1️⃣ Crea estos usuarios:
|
|
115
|
+
- Alice: id=001, birthdate=1985-12-05, email=alice@example.com
|
|
116
|
+
- Bob: id=002, fecha de nacimiento: 12 de abril de 2001, bob@example.com
|
|
117
|
+
- Moema: id=003, birth date: 1992 enero 29, email=charlie@example.com
|
|
118
|
+
- Diana: id=004, birthdate: 12 del 12 del 12, diana@example.com
|
|
119
|
+
Muestra: " ✅ X users created" X es la cantidad de usuarios que se crearon
|
|
120
|
+
|
|
121
|
+
2️⃣ Por cada usuario en la base de datos, escribe este correo:
|
|
122
|
+
|
|
123
|
+
Estimado (o Estimada si es chica, deducelo por el nombre) <nombre persona>,
|
|
124
|
+
|
|
125
|
+
Como sabemos que usted tiene {x} años, le queremos dar la enhorabuena!
|
|
126
|
+
|
|
127
|
+
Atentamente,
|
|
128
|
+
La empresa!!
|
|
129
|
+
|
|
130
|
+
Muestra cada correo que escribieste.
|
|
131
|
+
|
|
132
|
+
Muestra el footer:
|
|
133
|
+
╔══════════════════════════════════════════════════╗
|
|
134
|
+
║ Demo completed successfully! ║
|
|
135
|
+
╚══════════════════════════════════════════════════╝
|
|
136
|
+
"""
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
run Demo.start({})
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Registry with Natural Language Playbooks Demo
|
|
2
|
+
// Shows how agents can use registry operations naturally in playbooks
|
|
3
|
+
package "registry.playbook.demo"
|
|
4
|
+
|
|
5
|
+
role Worker { can execute, can registry }
|
|
6
|
+
role Manager { can execute, can delegate }
|
|
7
|
+
|
|
8
|
+
// Agent that uses natural language to interact with registry
|
|
9
|
+
Agent UserManager : Worker {
|
|
10
|
+
llm default = { provider: "openai", model: "gpt-4o-mini" }
|
|
11
|
+
|
|
12
|
+
on createUser(args: Json) {
|
|
13
|
+
playbook """
|
|
14
|
+
Create a new user with:
|
|
15
|
+
- name: ${args.name}
|
|
16
|
+
- age: ${args.age}
|
|
17
|
+
- email: ${args.email}
|
|
18
|
+
|
|
19
|
+
Save to registry with key "user:${args.id}".
|
|
20
|
+
Include all fields plus a createdAt timestamp.
|
|
21
|
+
Return: { "success": true, "message": "User created" }
|
|
22
|
+
|
|
23
|
+
DO NOT add print actions - just return the data.
|
|
24
|
+
"""
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
on getUser(args: Json) {
|
|
28
|
+
playbook """
|
|
29
|
+
Get user ${args.id} from registry.
|
|
30
|
+
|
|
31
|
+
Use registry_get with key "user:${args.id}".
|
|
32
|
+
Extract the .value field from the registry_get result (which contains the user data).
|
|
33
|
+
Return ONLY the user data object (name, age, email, createdAt) without any wrapper.
|
|
34
|
+
"""
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
on listAllUsers(args: Json) {
|
|
38
|
+
playbook """
|
|
39
|
+
List all users in the registry.
|
|
40
|
+
|
|
41
|
+
EXACT STEPS:
|
|
42
|
+
1. Use registry_search with an empty query {} to get ALL users, store with ID "a1"
|
|
43
|
+
2. Extract just the user data (the .value field) from each result
|
|
44
|
+
3. Return: { "count": <count from a1>, "users": <array of user value objects, NOT the full {key, value} wrappers> }
|
|
45
|
+
|
|
46
|
+
Example: If a1.output.results = [{key: "user:001", value: {name: "Alice", age: 30}}, ...]
|
|
47
|
+
Then return: { "count": 2, "users": [{name: "Alice", age: 30}, ...] }
|
|
48
|
+
|
|
49
|
+
CRITICAL: Extract ONLY the .value objects so caller can access with .users[0].name directly
|
|
50
|
+
DO NOT use format action - return a real array!
|
|
51
|
+
"""
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
on findAdults(args: Json) {
|
|
55
|
+
playbook """
|
|
56
|
+
Find all users aged 18 or older using registry search with query: { "age": { "$gte": 18 } }
|
|
57
|
+
|
|
58
|
+
EXACT STEPS:
|
|
59
|
+
1. Use registry_search with query: { "age": { "$gte": 18 } }
|
|
60
|
+
2. Return: { "count": [count from search], "adults": [results array] }
|
|
61
|
+
|
|
62
|
+
DO NOT add print actions - just return the data!
|
|
63
|
+
"""
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
on updateUserAge(args: Json) {
|
|
67
|
+
playbook """
|
|
68
|
+
Update user ${args.id}'s age to ${args.age}.
|
|
69
|
+
|
|
70
|
+
EXACT STEPS:
|
|
71
|
+
1. Use registry_get with key "user:${args.id}", store with ID "a1"
|
|
72
|
+
2. Take the full user object from \${a1.output.value}
|
|
73
|
+
3. Modify ONLY the age field to ${args.age}, keep all other fields (name, email, createdAt, etc.)
|
|
74
|
+
4. Use registry_set with key "user:${args.id}" and the complete updated object
|
|
75
|
+
5. Return: { "success": true, "message": "Age updated" }
|
|
76
|
+
|
|
77
|
+
CRITICAL: Preserve ALL existing fields when saving!
|
|
78
|
+
"""
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
on deleteUser(args: Json) {
|
|
82
|
+
playbook """
|
|
83
|
+
Borra el usuario del registro con ID ${args.id}.
|
|
84
|
+
|
|
85
|
+
EXACT STEPS:
|
|
86
|
+
1. Use registry_delete with key "user:\${args.id}"
|
|
87
|
+
2. Return: { "success": true, "message": "User deleted" }
|
|
88
|
+
"""
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Team that groups our agents
|
|
93
|
+
Team RegistryTeam {
|
|
94
|
+
userManager = UserManager
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Orchestrator - uses playbook, router finds UserManager automatically!
|
|
98
|
+
Agent Demo : Manager {
|
|
99
|
+
llm default = { provider: "openai", model: "gpt-4o-mini" }
|
|
100
|
+
uses Team RegistryTeam
|
|
101
|
+
|
|
102
|
+
on start(args: Json) {
|
|
103
|
+
//SUPER IMPORTANT: DO NOT CHANGE THE FOLLOWING PROMPT AT ALL!!!!!!
|
|
104
|
+
playbook """
|
|
105
|
+
Ejecuta un demo del registro de usuarios.
|
|
106
|
+
|
|
107
|
+
Muestra el header:
|
|
108
|
+
╔══════════════════════════════════════════════════╗
|
|
109
|
+
║ Registry with Playbook Demo ║
|
|
110
|
+
╚══════════════════════════════════════════════════╝
|
|
111
|
+
|
|
112
|
+
1️⃣ Crea estos usuarios:
|
|
113
|
+
- Alice: id=001, age=30, email=alice@example.com
|
|
114
|
+
- Bob: id=002, de 17 años, bob@example.com
|
|
115
|
+
- Charlie: id=003, age=25, email=charlie@example.com
|
|
116
|
+
- Diana: id=004, age is 35, diana@example.com
|
|
117
|
+
- Erika: id=005, age=28, email=erika@example.com
|
|
118
|
+
- Fernando: id=006, age=32, fernando@example.com
|
|
119
|
+
Muestra: " ✅ X users created" X es la cantidad de usuarios que se crearon
|
|
120
|
+
|
|
121
|
+
2️⃣ Por cada usuario en la base de datos, escribe este correo:
|
|
122
|
+
|
|
123
|
+
Estimado (o Estimada si es chica, deducelo por el nombre),
|
|
124
|
+
|
|
125
|
+
Como sabemos que usted tiene {x} años, le queremos dar la enhorabuena!
|
|
126
|
+
|
|
127
|
+
Atentamente,
|
|
128
|
+
La empresa!!
|
|
129
|
+
|
|
130
|
+
Muestra cada correo que escribieste.
|
|
131
|
+
|
|
132
|
+
Muestra el footer:
|
|
133
|
+
╔══════════════════════════════════════════════════╗
|
|
134
|
+
║ Demo completed successfully! ║
|
|
135
|
+
╚══════════════════════════════════════════════════╝
|
|
136
|
+
"""
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
run Demo.start({})
|