@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,22 @@
|
|
|
1
|
+
package "test"
|
|
2
|
+
|
|
3
|
+
role Worker { can execute }
|
|
4
|
+
|
|
5
|
+
Agent A : Worker {
|
|
6
|
+
on test(args: Json) {
|
|
7
|
+
const x = 5
|
|
8
|
+
return { x: x }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
Team T {
|
|
13
|
+
a = A
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
Agent B : Worker {
|
|
17
|
+
uses Team T
|
|
18
|
+
on start(args: Json) {
|
|
19
|
+
const result = await send peers.event("test").role(Worker).any()({}) timeout 2s
|
|
20
|
+
return result
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
package "test.crypto.sha256"
|
|
2
|
+
|
|
3
|
+
// Import crypto-js from npm for SHA256 hashing
|
|
4
|
+
import "crypto-js"
|
|
5
|
+
|
|
6
|
+
role SecurityAgent { can hash, can verify }
|
|
7
|
+
|
|
8
|
+
Agent HashAgent : SecurityAgent {
|
|
9
|
+
on hashPassword(args: Json) {
|
|
10
|
+
console.log("=".repeat(60))
|
|
11
|
+
console.log("Crypto SHA256 Test - Password Hashing")
|
|
12
|
+
console.log("=".repeat(60))
|
|
13
|
+
|
|
14
|
+
const password = args.password
|
|
15
|
+
console.log("\nOriginal password:", password)
|
|
16
|
+
|
|
17
|
+
// Hash with SHA256 (using chained method syntax)
|
|
18
|
+
const hash = crypto_js.SHA256(password).toString()
|
|
19
|
+
console.log("SHA256 hash:", hash)
|
|
20
|
+
|
|
21
|
+
// Hash with SHA512 for comparison
|
|
22
|
+
const hash512 = crypto_js.SHA512(password).toString()
|
|
23
|
+
console.log("SHA512 hash:", hash512)
|
|
24
|
+
|
|
25
|
+
// Hash with MD5 (less secure, for demonstration)
|
|
26
|
+
const hashMD5 = crypto_js.MD5(password).toString()
|
|
27
|
+
console.log("MD5 hash:", hashMD5)
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
password: password,
|
|
31
|
+
sha256: hash,
|
|
32
|
+
sha512: hash512,
|
|
33
|
+
md5: hashMD5
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
on verifyHash(args: Json) {
|
|
38
|
+
console.log("\n" + "=".repeat(60))
|
|
39
|
+
console.log("Hash Verification Test")
|
|
40
|
+
console.log("=".repeat(60))
|
|
41
|
+
|
|
42
|
+
const input = args.input
|
|
43
|
+
const expectedHash = args.expectedHash
|
|
44
|
+
|
|
45
|
+
console.log("\nInput:", input)
|
|
46
|
+
console.log("Expected hash:", expectedHash)
|
|
47
|
+
|
|
48
|
+
// Calculate hash (using chained method syntax)
|
|
49
|
+
const calculatedHash = crypto_js.SHA256(input).toString()
|
|
50
|
+
console.log("Calculated hash:", calculatedHash)
|
|
51
|
+
|
|
52
|
+
// Verify
|
|
53
|
+
const isValid = calculatedHash == expectedHash
|
|
54
|
+
console.log("Hash matches:", isValid)
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
input: input,
|
|
58
|
+
expectedHash: expectedHash,
|
|
59
|
+
calculatedHash: calculatedHash,
|
|
60
|
+
isValid: isValid
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
on hashData(args: Json) {
|
|
65
|
+
console.log("\n" + "=".repeat(60))
|
|
66
|
+
console.log("Data Integrity Test - JSON Hashing")
|
|
67
|
+
console.log("=".repeat(60))
|
|
68
|
+
|
|
69
|
+
const data = args.data
|
|
70
|
+
console.log("\nOriginal data:", JSON.stringify(data))
|
|
71
|
+
|
|
72
|
+
// Convert to JSON string and hash (using chained method syntax)
|
|
73
|
+
const dataString = JSON.stringify(data)
|
|
74
|
+
const hash = crypto_js.SHA256(dataString).toString()
|
|
75
|
+
console.log("SHA256 hash:", hash)
|
|
76
|
+
|
|
77
|
+
// Simulate data tampering
|
|
78
|
+
const tamperedData = { name: data.name, age: 99, email: data.email }
|
|
79
|
+
const tamperedString = JSON.stringify(tamperedData)
|
|
80
|
+
const tamperedHash = crypto_js.SHA256(tamperedString).toString()
|
|
81
|
+
console.log("\nTampered data:", JSON.stringify(tamperedData))
|
|
82
|
+
console.log("Tampered hash:", tamperedHash)
|
|
83
|
+
console.log("Hashes match:", hash == tamperedHash)
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
original: {
|
|
87
|
+
data: data,
|
|
88
|
+
hash: hash
|
|
89
|
+
},
|
|
90
|
+
tampered: {
|
|
91
|
+
data: tamperedData,
|
|
92
|
+
hash: tamperedHash
|
|
93
|
+
},
|
|
94
|
+
isCompromised: hash != tamperedHash
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
on compareAlgorithms(args: Json) {
|
|
99
|
+
console.log("\n" + "=".repeat(60))
|
|
100
|
+
console.log("Algorithm Comparison Test")
|
|
101
|
+
console.log("=".repeat(60))
|
|
102
|
+
|
|
103
|
+
const text = args.text
|
|
104
|
+
console.log("\nText to hash:", text)
|
|
105
|
+
|
|
106
|
+
// Hash with different algorithms (using chained method syntax)
|
|
107
|
+
const md5 = crypto_js.MD5(text).toString()
|
|
108
|
+
const sha1 = crypto_js.SHA1(text).toString()
|
|
109
|
+
const sha256 = crypto_js.SHA256(text).toString()
|
|
110
|
+
const sha512 = crypto_js.SHA512(text).toString()
|
|
111
|
+
const sha3 = crypto_js.SHA3(text).toString()
|
|
112
|
+
|
|
113
|
+
console.log("\nMD5 (32 chars):", md5)
|
|
114
|
+
console.log("SHA1 (40 chars):", sha1)
|
|
115
|
+
console.log("SHA256 (64 chars):", sha256)
|
|
116
|
+
console.log("SHA512 (128 chars):", sha512)
|
|
117
|
+
console.log("SHA3 (64 chars):", sha3)
|
|
118
|
+
|
|
119
|
+
console.log("\nHash lengths:")
|
|
120
|
+
console.log(" MD5:", md5.length, "characters")
|
|
121
|
+
console.log(" SHA1:", sha1.length, "characters")
|
|
122
|
+
console.log(" SHA256:", sha256.length, "characters")
|
|
123
|
+
console.log(" SHA512:", sha512.length, "characters")
|
|
124
|
+
console.log(" SHA3:", sha3.length, "characters")
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
text: text,
|
|
128
|
+
hashes: {
|
|
129
|
+
md5: md5,
|
|
130
|
+
sha1: sha1,
|
|
131
|
+
sha256: sha256,
|
|
132
|
+
sha512: sha512,
|
|
133
|
+
sha3: sha3
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
Team HashTeam {
|
|
140
|
+
hasher = HashAgent
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
Agent Coordinator : SecurityAgent {
|
|
144
|
+
uses Team HashTeam
|
|
145
|
+
|
|
146
|
+
on runTests(args: Json) {
|
|
147
|
+
console.log("\n" + "█".repeat(60))
|
|
148
|
+
console.log("█" + " ".repeat(58) + "█")
|
|
149
|
+
console.log("█" + " Crypto-JS SHA256 Integration Test Suite".padEnd(58) + "█")
|
|
150
|
+
console.log("█" + " ".repeat(58) + "█")
|
|
151
|
+
console.log("█".repeat(60))
|
|
152
|
+
|
|
153
|
+
// Test 1: Hash password
|
|
154
|
+
const result1 = await send peers.event("hashPassword").role(SecurityAgent).any()({
|
|
155
|
+
password: "MySecurePassword123!"
|
|
156
|
+
}) timeout 10s
|
|
157
|
+
|
|
158
|
+
// Test 2: Verify hash
|
|
159
|
+
const result2 = await send peers.event("verifyHash").role(SecurityAgent).any()({
|
|
160
|
+
input: "MySecurePassword123!",
|
|
161
|
+
expectedHash: result1.sha256
|
|
162
|
+
}) timeout 10s
|
|
163
|
+
|
|
164
|
+
// Test 3: Hash structured data
|
|
165
|
+
const result3 = await send peers.event("hashData").role(SecurityAgent).any()({
|
|
166
|
+
data: {
|
|
167
|
+
name: "Alice",
|
|
168
|
+
age: 30,
|
|
169
|
+
email: "alice@example.com"
|
|
170
|
+
}
|
|
171
|
+
}) timeout 10s
|
|
172
|
+
|
|
173
|
+
// Test 4: Compare algorithms
|
|
174
|
+
const result4 = await send peers.event("compareAlgorithms").role(SecurityAgent).any()({
|
|
175
|
+
text: "The quick brown fox jumps over the lazy dog"
|
|
176
|
+
}) timeout 10s
|
|
177
|
+
|
|
178
|
+
console.log("\n" + "█".repeat(60))
|
|
179
|
+
console.log("█" + " ".repeat(58) + "█")
|
|
180
|
+
console.log("█" + " All Crypto Tests Completed Successfully!".padEnd(58) + "█")
|
|
181
|
+
console.log("█" + " ".repeat(58) + "█")
|
|
182
|
+
console.log("█".repeat(60))
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
success: true,
|
|
186
|
+
tests: {
|
|
187
|
+
passwordHashing: result1,
|
|
188
|
+
hashVerification: result2,
|
|
189
|
+
dataIntegrity: result3,
|
|
190
|
+
algorithmComparison: result4
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
run Coordinator.runTests({})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Test delegation with explicit data passing
|
|
2
|
+
package "test.delegation"
|
|
3
|
+
|
|
4
|
+
role Worker { can execute }
|
|
5
|
+
|
|
6
|
+
// Specialist that saves users
|
|
7
|
+
Agent Saver : Worker {
|
|
8
|
+
llm default = { provider: "openai", model: "gpt-4o-mini" }
|
|
9
|
+
|
|
10
|
+
on saveUser(args: Json) {
|
|
11
|
+
playbook """
|
|
12
|
+
Save a user to registry with key "user:${args.id}".
|
|
13
|
+
User data: name="${args.name}", age=${args.age}
|
|
14
|
+
|
|
15
|
+
Return: { "saved": true, "id": "${args.id}", "name": "${args.name}" }
|
|
16
|
+
"""
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Team containing the saver
|
|
21
|
+
Team SaverTeam {
|
|
22
|
+
saver = Saver
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Orchestrator that delegates
|
|
26
|
+
Agent Orchestrator : Worker {
|
|
27
|
+
llm default = { provider: "openai", model: "gpt-4o-mini" }
|
|
28
|
+
uses Team SaverTeam
|
|
29
|
+
|
|
30
|
+
on start(args: Json) {
|
|
31
|
+
playbook """
|
|
32
|
+
Delegate the task of saving a user named "TestUser" with ID "123" and age 25.
|
|
33
|
+
|
|
34
|
+
CRITICAL: Pass data: { "id": "123", "name": "TestUser", "age": 25 }
|
|
35
|
+
|
|
36
|
+
Return the result from the delegation.
|
|
37
|
+
"""
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
run Orchestrator.start({})
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
package "test.multi.team.routing"
|
|
2
|
+
|
|
3
|
+
// Test: Multi-team routing with peers() and peers(TeamName)
|
|
4
|
+
// This test validates that:
|
|
5
|
+
// 1. peers.event() broadcasts to all teams
|
|
6
|
+
// 2. peers(TeamName).event() sends only to specific team
|
|
7
|
+
// 3. Multiple teams can coexist and be addressed independently
|
|
8
|
+
|
|
9
|
+
role Worker { can work, can process }
|
|
10
|
+
|
|
11
|
+
// Team A workers
|
|
12
|
+
Agent WorkerA1 : Worker {
|
|
13
|
+
on work(args: Json) {
|
|
14
|
+
return {
|
|
15
|
+
from: "WorkerA1",
|
|
16
|
+
team: "TeamA",
|
|
17
|
+
data: args
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
on process(args: Json) {
|
|
22
|
+
return {
|
|
23
|
+
from: "WorkerA1",
|
|
24
|
+
team: "TeamA",
|
|
25
|
+
operation: "process",
|
|
26
|
+
data: args
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Agent WorkerA2 : Worker {
|
|
32
|
+
on work(args: Json) {
|
|
33
|
+
return {
|
|
34
|
+
from: "WorkerA2",
|
|
35
|
+
team: "TeamA",
|
|
36
|
+
data: args
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
on process(args: Json) {
|
|
41
|
+
return {
|
|
42
|
+
from: "WorkerA2",
|
|
43
|
+
team: "TeamA",
|
|
44
|
+
operation: "process",
|
|
45
|
+
data: args
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Team B workers
|
|
51
|
+
Agent WorkerB1 : Worker {
|
|
52
|
+
on work(args: Json) {
|
|
53
|
+
return {
|
|
54
|
+
from: "WorkerB1",
|
|
55
|
+
team: "TeamB",
|
|
56
|
+
data: args
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
on process(args: Json) {
|
|
61
|
+
return {
|
|
62
|
+
from: "WorkerB1",
|
|
63
|
+
team: "TeamB",
|
|
64
|
+
operation: "process",
|
|
65
|
+
data: args
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
Agent WorkerB2 : Worker {
|
|
71
|
+
on work(args: Json) {
|
|
72
|
+
return {
|
|
73
|
+
from: "WorkerB2",
|
|
74
|
+
team: "TeamB",
|
|
75
|
+
data: args
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
on process(args: Json) {
|
|
80
|
+
return {
|
|
81
|
+
from: "WorkerB2",
|
|
82
|
+
team: "TeamB",
|
|
83
|
+
operation: "process",
|
|
84
|
+
data: args
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Team C workers
|
|
90
|
+
Agent WorkerC1 : Worker {
|
|
91
|
+
on work(args: Json) {
|
|
92
|
+
return {
|
|
93
|
+
from: "WorkerC1",
|
|
94
|
+
team: "TeamC",
|
|
95
|
+
data: args
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
on process(args: Json) {
|
|
100
|
+
return {
|
|
101
|
+
from: "WorkerC1",
|
|
102
|
+
team: "TeamC",
|
|
103
|
+
operation: "process",
|
|
104
|
+
data: args
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Define three teams
|
|
110
|
+
Team TeamA {
|
|
111
|
+
worker1 = WorkerA1
|
|
112
|
+
worker2 = WorkerA2
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
Team TeamB {
|
|
116
|
+
worker1 = WorkerB1
|
|
117
|
+
worker2 = WorkerB2
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
Team TeamC {
|
|
121
|
+
worker1 = WorkerC1
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Coordinator that uses all three teams
|
|
125
|
+
Agent TestCoordinator : Worker {
|
|
126
|
+
uses Team TeamA, TeamB, TeamC
|
|
127
|
+
|
|
128
|
+
on runTests(args: Json) {
|
|
129
|
+
console.log("=".repeat(60))
|
|
130
|
+
console.log("Multi-Team Routing Test Suite")
|
|
131
|
+
console.log("=".repeat(60))
|
|
132
|
+
|
|
133
|
+
// Test 1: Broadcast to all teams (peers.event)
|
|
134
|
+
console.log("\n[TEST 1] Broadcast to all teams with peers.event()")
|
|
135
|
+
console.log("-".repeat(60))
|
|
136
|
+
const result1 = await send peers.event("work").role(Worker).any()({
|
|
137
|
+
test: "broadcast",
|
|
138
|
+
message: "Should reach any team"
|
|
139
|
+
}) timeout 10s
|
|
140
|
+
|
|
141
|
+
console.log("Result:", JSON.stringify(result1, null, 2))
|
|
142
|
+
const test1Pass = result1 && result1.team
|
|
143
|
+
if (test1Pass) {
|
|
144
|
+
console.log("✓ TEST 1 PASSED: Received response from", result1.team)
|
|
145
|
+
} else {
|
|
146
|
+
console.log("✗ TEST 1 FAILED: No response received")
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Test 2: Send only to TeamA
|
|
150
|
+
console.log("\n[TEST 2] Send to TeamA only with peers(TeamA).event()")
|
|
151
|
+
console.log("-".repeat(60))
|
|
152
|
+
const result2 = await send peers(TeamA).event("work").role(Worker).any()({
|
|
153
|
+
test: "teamA",
|
|
154
|
+
message: "Should only reach TeamA"
|
|
155
|
+
}) timeout 10s
|
|
156
|
+
|
|
157
|
+
console.log("Result:", JSON.stringify(result2, null, 2))
|
|
158
|
+
const test2Pass = result2 && result2.team == "TeamA"
|
|
159
|
+
if (test2Pass) {
|
|
160
|
+
console.log("✓ TEST 2 PASSED: Correctly routed to TeamA")
|
|
161
|
+
} else {
|
|
162
|
+
console.log("✗ TEST 2 FAILED: Expected team=TeamA, got", result2.team)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Test 3: Send only to TeamB
|
|
166
|
+
console.log("\n[TEST 3] Send to TeamB only with peers(TeamB).event()")
|
|
167
|
+
console.log("-".repeat(60))
|
|
168
|
+
const result3 = await send peers(TeamB).event("work").role(Worker).any()({
|
|
169
|
+
test: "teamB",
|
|
170
|
+
message: "Should only reach TeamB"
|
|
171
|
+
}) timeout 10s
|
|
172
|
+
|
|
173
|
+
console.log("Result:", JSON.stringify(result3, null, 2))
|
|
174
|
+
const test3Pass = result3 && result3.team == "TeamB"
|
|
175
|
+
if (test3Pass) {
|
|
176
|
+
console.log("✓ TEST 3 PASSED: Correctly routed to TeamB")
|
|
177
|
+
} else {
|
|
178
|
+
console.log("✗ TEST 3 FAILED: Expected team=TeamB, got", result3.team)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Test 4: Send only to TeamC
|
|
182
|
+
console.log("\n[TEST 4] Send to TeamC only with peers(TeamC).event()")
|
|
183
|
+
console.log("-".repeat(60))
|
|
184
|
+
const result4 = await send peers(TeamC).event("work").role(Worker).any()({
|
|
185
|
+
test: "teamC",
|
|
186
|
+
message: "Should only reach TeamC"
|
|
187
|
+
}) timeout 10s
|
|
188
|
+
|
|
189
|
+
console.log("Result:", JSON.stringify(result4, null, 2))
|
|
190
|
+
const test4Pass = result4 && result4.team == "TeamC"
|
|
191
|
+
if (test4Pass) {
|
|
192
|
+
console.log("✓ TEST 4 PASSED: Correctly routed to TeamC")
|
|
193
|
+
} else {
|
|
194
|
+
console.log("✗ TEST 4 FAILED: Expected team=TeamC, got", result4.team)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Test 5: Different event to specific team
|
|
198
|
+
console.log("\n[TEST 5] Send 'process' event to TeamA only")
|
|
199
|
+
console.log("-".repeat(60))
|
|
200
|
+
const result5 = await send peers(TeamA).event("process").role(Worker).any()({
|
|
201
|
+
test: "process",
|
|
202
|
+
value: 42
|
|
203
|
+
}) timeout 10s
|
|
204
|
+
|
|
205
|
+
console.log("Result:", JSON.stringify(result5, null, 2))
|
|
206
|
+
const test5Pass = result5 && result5.team == "TeamA" && result5.operation == "process"
|
|
207
|
+
if (test5Pass) {
|
|
208
|
+
console.log("✓ TEST 5 PASSED: Process event routed to TeamA")
|
|
209
|
+
} else {
|
|
210
|
+
console.log("✗ TEST 5 FAILED: Expected TeamA process event")
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Test 6: Verify isolation - TeamB should not receive TeamA messages
|
|
214
|
+
console.log("\n[TEST 6] Verify team isolation")
|
|
215
|
+
console.log("-".repeat(60))
|
|
216
|
+
const resultA = await send peers(TeamA).event("work").role(Worker).any()({
|
|
217
|
+
target: "TeamA"
|
|
218
|
+
}) timeout 10s
|
|
219
|
+
const resultB = await send peers(TeamB).event("work").role(Worker).any()({
|
|
220
|
+
target: "TeamB"
|
|
221
|
+
}) timeout 10s
|
|
222
|
+
|
|
223
|
+
console.log("TeamA result:", JSON.stringify(resultA, null, 2))
|
|
224
|
+
console.log("TeamB result:", JSON.stringify(resultB, null, 2))
|
|
225
|
+
const test6Pass = resultA.team == "TeamA" && resultB.team == "TeamB"
|
|
226
|
+
if (test6Pass) {
|
|
227
|
+
console.log("✓ TEST 6 PASSED: Teams are properly isolated")
|
|
228
|
+
} else {
|
|
229
|
+
console.log("✗ TEST 6 FAILED: Team isolation failed")
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Summary
|
|
233
|
+
console.log("\n" + "=".repeat(60))
|
|
234
|
+
console.log("Test Summary")
|
|
235
|
+
console.log("=".repeat(60))
|
|
236
|
+
const allPassed = test1Pass && test2Pass && test3Pass && test4Pass && test5Pass && test6Pass
|
|
237
|
+
|
|
238
|
+
if (allPassed) {
|
|
239
|
+
console.log("\n✓ ALL 6 TESTS PASSED!")
|
|
240
|
+
} else {
|
|
241
|
+
console.log("\n✗ SOME TESTS FAILED - See results above")
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return {
|
|
245
|
+
success: allPassed,
|
|
246
|
+
results: {
|
|
247
|
+
test1: test1Pass,
|
|
248
|
+
test2: test2Pass,
|
|
249
|
+
test3: test3Pass,
|
|
250
|
+
test4: test4Pass,
|
|
251
|
+
test5: test5Pass,
|
|
252
|
+
test6: test6Pass
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
run TestCoordinator.runTests({})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Test: Error when no agent can handle an event
|
|
2
|
+
|
|
3
|
+
package "test.no.handler"
|
|
4
|
+
|
|
5
|
+
role Worker { can execute }
|
|
6
|
+
|
|
7
|
+
Agent SimpleWorker : Worker {
|
|
8
|
+
on doWork(args: Json) {
|
|
9
|
+
playbook """
|
|
10
|
+
Do some work
|
|
11
|
+
Return JSON: { "result": "done" }
|
|
12
|
+
"""
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
Team SimpleTeam {
|
|
17
|
+
worker = SimpleWorker
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
Agent Requester : Worker {
|
|
21
|
+
uses Team SimpleTeam
|
|
22
|
+
|
|
23
|
+
on testNoHandler(args: Json) {
|
|
24
|
+
console.log("Testing error when no agent can handle event...")
|
|
25
|
+
|
|
26
|
+
// Try to send an event that no agent in the team can handle
|
|
27
|
+
const result = await send peers.event("nonExistentEvent").any()({
|
|
28
|
+
data: "test"
|
|
29
|
+
}) timeout 5s
|
|
30
|
+
|
|
31
|
+
return result
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
run Requester.testNoHandler({})
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
package "test.npm.import"
|
|
2
|
+
|
|
3
|
+
// Import lodash from node_modules
|
|
4
|
+
import "lodash"
|
|
5
|
+
|
|
6
|
+
role Worker { can work }
|
|
7
|
+
|
|
8
|
+
Agent DataProcessor : Worker {
|
|
9
|
+
on process(args: Json) {
|
|
10
|
+
console.log("=".repeat(60))
|
|
11
|
+
console.log("Testing NPM Package Import (lodash)")
|
|
12
|
+
console.log("=".repeat(60))
|
|
13
|
+
|
|
14
|
+
// Test chunk
|
|
15
|
+
const chunked = lodash.chunk([1, 2, 3, 4, 5, 6, 7, 8], 3)
|
|
16
|
+
console.log("\nTest 1: chunk([1-8], 3) =", JSON.stringify(chunked))
|
|
17
|
+
|
|
18
|
+
// Test uniq
|
|
19
|
+
const unique = lodash.uniq([1, 2, 2, 3, 3, 3, 4, 5, 5])
|
|
20
|
+
console.log("Test 2: uniq([1,2,2,3,3,3,4,5,5]) =", JSON.stringify(unique))
|
|
21
|
+
|
|
22
|
+
// Test pick
|
|
23
|
+
const obj = { a: 1, b: 2, c: 3, d: 4 }
|
|
24
|
+
const picked = lodash.pick(obj, ["a", "c"])
|
|
25
|
+
console.log("Test 3: pick({a:1,b:2,c:3,d:4}, ['a','c']) =", JSON.stringify(picked))
|
|
26
|
+
|
|
27
|
+
// Test sum
|
|
28
|
+
const total = lodash.sum([1, 2, 3, 4, 5])
|
|
29
|
+
console.log("Test 4: sum([1,2,3,4,5]) =", total)
|
|
30
|
+
|
|
31
|
+
// Test mean
|
|
32
|
+
const avg = lodash.mean([10, 20, 30, 40, 50])
|
|
33
|
+
console.log("Test 5: mean([10,20,30,40,50]) =", avg)
|
|
34
|
+
|
|
35
|
+
// Test reverse
|
|
36
|
+
const reversed = lodash.reverse([1, 2, 3, 4, 5])
|
|
37
|
+
console.log("Test 6: reverse([1,2,3,4,5]) =", JSON.stringify(reversed))
|
|
38
|
+
|
|
39
|
+
// Test max
|
|
40
|
+
const maximum = lodash.max([10, 50, 30, 20, 40])
|
|
41
|
+
console.log("Test 7: max([10,50,30,20,40]) =", maximum)
|
|
42
|
+
|
|
43
|
+
// Test min
|
|
44
|
+
const minimum = lodash.min([10, 50, 30, 20, 40])
|
|
45
|
+
console.log("Test 8: min([10,50,30,20,40]) =", minimum)
|
|
46
|
+
|
|
47
|
+
console.log("\n" + "=".repeat(60))
|
|
48
|
+
console.log("All lodash tests completed!")
|
|
49
|
+
console.log("=".repeat(60))
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
success: true,
|
|
53
|
+
tests: {
|
|
54
|
+
chunked: chunked,
|
|
55
|
+
unique: unique,
|
|
56
|
+
picked: picked,
|
|
57
|
+
sum: total,
|
|
58
|
+
mean: avg,
|
|
59
|
+
reversed: reversed,
|
|
60
|
+
max: maximum,
|
|
61
|
+
min: minimum
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
run DataProcessor.process({})
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
package "test.peers.team"
|
|
2
|
+
|
|
3
|
+
role Worker { can work }
|
|
4
|
+
|
|
5
|
+
Agent WorkerA : Worker {
|
|
6
|
+
on work(args: Json) {
|
|
7
|
+
return { from: "WorkerA", data: args }
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
Agent WorkerB : Worker {
|
|
12
|
+
on work(args: Json) {
|
|
13
|
+
return { from: "WorkerB", data: args }
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
Team TeamA {
|
|
18
|
+
worker = WorkerA
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
Team TeamB {
|
|
22
|
+
worker = WorkerB
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
Agent Coordinator : Worker {
|
|
26
|
+
uses Team TeamA, TeamB
|
|
27
|
+
|
|
28
|
+
on coordinate(args: Json) {
|
|
29
|
+
// Test 1: Send to all teams via common router
|
|
30
|
+
console.log("Test 1: Send to all teams (peers.event)")
|
|
31
|
+
const resultAll = await send peers.event("work").role(Worker).any()({
|
|
32
|
+
message: "to all teams"
|
|
33
|
+
}) timeout 10s
|
|
34
|
+
console.log("Result from all:", JSON.stringify(resultAll))
|
|
35
|
+
|
|
36
|
+
// Test 2: Send only to TeamA
|
|
37
|
+
console.log("\nTest 2: Send to TeamA only (peers(TeamA).event)")
|
|
38
|
+
const resultTeamA = await send peers(TeamA).event("work").role(Worker).any()({
|
|
39
|
+
message: "to TeamA only"
|
|
40
|
+
}) timeout 10s
|
|
41
|
+
console.log("Result from TeamA:", JSON.stringify(resultTeamA))
|
|
42
|
+
|
|
43
|
+
// Test 3: Send only to TeamB
|
|
44
|
+
console.log("\nTest 3: Send to TeamB only (peers(TeamB).event)")
|
|
45
|
+
const resultTeamB = await send peers(TeamB).event("work").role(Worker).any()({
|
|
46
|
+
message: "to TeamB only"
|
|
47
|
+
}) timeout 10s
|
|
48
|
+
console.log("Result from TeamB:", JSON.stringify(resultTeamB))
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
success: true,
|
|
52
|
+
allTeams: resultAll,
|
|
53
|
+
teamA: resultTeamA,
|
|
54
|
+
teamB: resultTeamB
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
run Coordinator.coordinate({ test: true })
|