@koi-language/koi 1.0.5 → 1.1.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.
Files changed (113) hide show
  1. package/README.md +4 -125
  2. package/examples/.build/agent-dialogue.ts +138 -0
  3. package/examples/.build/agent-dialogue.ts.map +1 -0
  4. package/examples/.build/chess.ts +77 -0
  5. package/examples/.build/chess.ts.map +1 -0
  6. package/examples/.build/delegation-test.ts +140 -0
  7. package/examples/.build/delegation-test.ts.map +1 -0
  8. package/examples/.build/dialog-demo.ts +77 -0
  9. package/examples/.build/dialog-demo.ts.map +1 -0
  10. package/examples/.build/hello-world.ts +77 -0
  11. package/examples/.build/hello-world.ts.map +1 -0
  12. package/examples/.build/lover-dialog-demo.ts +77 -0
  13. package/examples/.build/lover-dialog-demo.ts.map +1 -0
  14. package/examples/.build/package.json +3 -0
  15. package/examples/.build/registry-interactive-demo.ts +202 -0
  16. package/examples/.build/registry-interactive-demo.ts.map +1 -0
  17. package/examples/.build/registry-playbook-demo.ts +201 -0
  18. package/examples/.build/registry-playbook-demo.ts.map +1 -0
  19. package/examples/.build/tic-tac-toe.ts +77 -0
  20. package/examples/.build/tic-tac-toe.ts.map +1 -0
  21. package/examples/actions-demo.koi +8 -9
  22. package/examples/activists-dialogue.koi +75 -0
  23. package/examples/agent-dialogue.koi +66 -0
  24. package/examples/chess.koi +19 -0
  25. package/examples/counter.koi +20 -69
  26. package/examples/delegation-test.koi +16 -18
  27. package/examples/dialog-demo.koi +20 -0
  28. package/examples/hello-world.koi +7 -43
  29. package/examples/mcp-stdio-demo.koi +29 -0
  30. package/examples/memory-test.koi +49 -0
  31. package/examples/mobile-mcp-demo.koi +32 -0
  32. package/examples/multi-event-handler-test.koi +16 -18
  33. package/examples/pipeline.koi +15 -17
  34. package/examples/prompt-demo.koi +20 -0
  35. package/examples/{registry-playbook-email-compositor.koi → registry-interactive-demo.koi} +27 -27
  36. package/examples/registry-playbook-demo.koi +28 -28
  37. package/examples/skill-import-test.koi +7 -9
  38. package/examples/skills/.build/math-operations.ts +1656 -0
  39. package/examples/skills/.build/math-operations.ts.map +1 -0
  40. package/examples/skills/.build/package.json +3 -0
  41. package/examples/skills/.build/string-operations.ts +1643 -0
  42. package/examples/skills/.build/string-operations.ts.map +1 -0
  43. package/examples/skills/advanced/.build/index.ts +3223 -0
  44. package/examples/skills/advanced/.build/index.ts.map +1 -0
  45. package/examples/skills/advanced/.build/package.json +3 -0
  46. package/examples/skills/advanced/index.koi +3 -5
  47. package/examples/skills/math-operations.koi +1 -3
  48. package/examples/skills/string-operations.koi +1 -3
  49. package/examples/tic-tac-toe.koi +19 -0
  50. package/examples/utils/echo-mcp-server.js +141 -0
  51. package/examples/web-delegation-demo.koi +15 -17
  52. package/package.json +2 -1
  53. package/src/cli/koi.js +30 -41
  54. package/src/compiler/build-optimizer.js +204 -289
  55. package/src/compiler/cache-manager.js +1 -1
  56. package/src/compiler/import-resolver.js +5 -9
  57. package/src/compiler/parser.js +6072 -3476
  58. package/src/compiler/transpiler.js +346 -38
  59. package/src/grammar/koi.pegjs +302 -62
  60. package/src/runtime/actions/{format.js → call-llm.js} +37 -44
  61. package/src/runtime/actions/call-mcp.js +97 -0
  62. package/src/runtime/actions/if.js +179 -0
  63. package/src/runtime/actions/print.js +3 -1
  64. package/src/runtime/actions/prompt-user.js +75 -0
  65. package/src/runtime/actions/repeat.js +147 -0
  66. package/src/runtime/actions/shell.js +185 -0
  67. package/src/runtime/actions/while.js +205 -0
  68. package/src/runtime/agent.js +592 -178
  69. package/src/runtime/cli-display.js +26 -0
  70. package/src/runtime/cli-input.js +421 -0
  71. package/src/runtime/cli-logger.js +2 -5
  72. package/src/runtime/cli-markdown.js +61 -0
  73. package/src/runtime/cli-select.js +106 -0
  74. package/src/runtime/incremental-json-parser.js +51 -17
  75. package/src/runtime/index.js +1 -0
  76. package/src/runtime/llm-provider.js +1083 -572
  77. package/src/runtime/mcp-registry.js +141 -0
  78. package/src/runtime/mcp-stdio-client.js +334 -0
  79. package/src/runtime/planner.js +1 -1
  80. package/src/runtime/playbook-session.js +259 -0
  81. package/src/runtime/registry-backends/keyv-sqlite.js +1 -1
  82. package/src/runtime/registry-backends/local.js +1 -1
  83. package/src/runtime/router.js +22 -26
  84. package/src/runtime/runtime.js +7 -1
  85. package/examples/cache-test.koi +0 -29
  86. package/examples/calculator.koi +0 -61
  87. package/examples/clear-registry.js +0 -33
  88. package/examples/clear-registry.koi +0 -30
  89. package/examples/code-introspection-test.koi +0 -149
  90. package/examples/directory-import-test.koi +0 -84
  91. package/examples/hello-world-claude.koi +0 -52
  92. package/examples/hello.koi +0 -24
  93. package/examples/mcp-example.koi +0 -70
  94. package/examples/new-import-test.koi +0 -89
  95. package/examples/registry-demo.koi +0 -184
  96. package/examples/registry-playbook-email-compositor-2.koi +0 -140
  97. package/examples/sentiment.koi +0 -90
  98. package/examples/simple.koi +0 -48
  99. package/examples/task-chaining-demo.koi +0 -244
  100. package/examples/test-await.koi +0 -22
  101. package/examples/test-crypto-sha256.koi +0 -196
  102. package/examples/test-delegation.koi +0 -41
  103. package/examples/test-multi-team-routing.koi +0 -258
  104. package/examples/test-no-handler.koi +0 -35
  105. package/examples/test-npm-import.koi +0 -67
  106. package/examples/test-parse.koi +0 -10
  107. package/examples/test-peers-with-team.koi +0 -59
  108. package/examples/test-permissions-fail.koi +0 -20
  109. package/examples/test-permissions.koi +0 -36
  110. package/examples/test-simple-registry.koi +0 -31
  111. package/examples/test-typescript-import.koi +0 -64
  112. package/examples/test-uses-team-syntax.koi +0 -25
  113. package/examples/test-uses-team.koi +0 -31
@@ -0,0 +1,77 @@
1
+ // Generated from hello-world.koi
2
+ // Using local runtime from KOI_RUNTIME_PATH: /Users/antonioparraga/Git/Koi-lang/Koi/src/runtime
3
+ import { Agent, Team, Skill, Role, Runtime, SkillRegistry, skillSelector, registry, mcpRegistry } from 'file:///Users/antonioparraga/Git/Koi-lang/Koi/src/runtime/index.js';
4
+ import { createRequire } from 'module';
5
+ const require = createRequire(import.meta.url);
6
+
7
+ globalThis.SkillRegistry = SkillRegistry;
8
+ globalThis.skillSelector = skillSelector;
9
+ globalThis.registry = registry;
10
+ globalThis.mcpRegistry = mcpRegistry;
11
+
12
+ // ============================================================
13
+ // Pre-computed Affordances (Build-time Cache)
14
+ // Generated at: 2026-02-16T18:21:18.630Z
15
+ // Total agents: 1
16
+ // Total agent affordances: 1
17
+ // Total skills: 0
18
+ // Total skill affordances: 0
19
+ // This avoids embedding API calls at runtime
20
+ // ============================================================
21
+
22
+ const CACHED_AFFORDANCES = {
23
+ "Assistant": {
24
+ "test_while": {
25
+ "description": "Ask the user for their name, then greet them warmly.",
26
+ "confidence": 0.9,
27
+ "hasPlaybook": true
28
+ }
29
+ }
30
+ };
31
+
32
+ const CACHED_SKILL_AFFORDANCES = {};
33
+
34
+ const Worker = new Role('Worker', ['execute']);
35
+
36
+ const Assistant = new Agent({
37
+ name: 'Assistant',
38
+ role: Worker,
39
+ llm: { provider: "openai", model: "gpt-5.2" },
40
+ handlers: {
41
+ test_while: (() => {
42
+ const handler = async function(args) {
43
+ // This should not be called - playbook will be executed by LLM
44
+ throw new Error('Playbook-only handler called directly');
45
+ };
46
+ handler.__playbookOnly__ = true;
47
+ handler.__playbook__ = "Ask the user for their name, then greet them warmly";
48
+ handler.__description__ = "Ask the user for their name, then greet them warmly.";
49
+ return handler;
50
+ })(),
51
+ }
52
+ });
53
+
54
+
55
+ // Main execution function
56
+ (async () => {
57
+ // Register agents with router
58
+ const { agentRouter } = await import('file:///Users/antonioparraga/Git/Koi-lang/Koi/src/runtime/router.js');
59
+
60
+ await agentRouter.register(Assistant, CACHED_AFFORDANCES['Assistant']);
61
+
62
+ // Execute
63
+ const result = await Assistant.handle('test_while', {});
64
+ // Result handled by actions
65
+
66
+ const _gracefulShutdown = async () => { await mcpRegistry.disconnectAll(); process.exit(0); };
67
+ process.on('SIGINT', _gracefulShutdown);
68
+ process.on('SIGTERM', _gracefulShutdown);
69
+
70
+ await mcpRegistry.disconnectAll();
71
+ process.exit(0);
72
+ })().catch(err => {
73
+ console.error('Error:', err.message);
74
+ process.exit(1);
75
+ });
76
+
77
+ //# sourceMappingURL=hello-world.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["hello-world.koi"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;;AAEA","file":"hello-world.koi.js"}
@@ -0,0 +1,77 @@
1
+ // Generated from lover-dialog-demo.koi
2
+ // Using local runtime from KOI_RUNTIME_PATH: /Users/antonioparraga/Git/Koi-lang/Koi/src/runtime
3
+ import { Agent, Team, Skill, Role, Runtime, SkillRegistry, skillSelector, registry, mcpRegistry } from 'file:///Users/antonioparraga/Git/Koi-lang/Koi/src/runtime/index.js';
4
+ import { createRequire } from 'module';
5
+ const require = createRequire(import.meta.url);
6
+
7
+ globalThis.SkillRegistry = SkillRegistry;
8
+ globalThis.skillSelector = skillSelector;
9
+ globalThis.registry = registry;
10
+ globalThis.mcpRegistry = mcpRegistry;
11
+
12
+ // ============================================================
13
+ // Pre-computed Affordances (Build-time Cache)
14
+ // Generated at: 2026-02-16T18:39:52.762Z
15
+ // Total agents: 1
16
+ // Total agent affordances: 1
17
+ // Total skills: 0
18
+ // Total skill affordances: 0
19
+ // This avoids embedding API calls at runtime
20
+ // ============================================================
21
+
22
+ const CACHED_AFFORDANCES = {
23
+ "Assistant": {
24
+ "test_while": {
25
+ "description": "Roleplay as the user’s loving partner, chat freely (including sex) until they say goodbye, then warmly end.",
26
+ "confidence": 0.9,
27
+ "hasPlaybook": true
28
+ }
29
+ }
30
+ };
31
+
32
+ const CACHED_SKILL_AFFORDANCES = {};
33
+
34
+ const Worker = new Role('Worker', ['execute']);
35
+
36
+ const Assistant = new Agent({
37
+ name: 'Assistant',
38
+ role: Worker,
39
+ llm: { provider: "openai", model: "gpt-5.2" },
40
+ handlers: {
41
+ test_while: (() => {
42
+ const handler = async function(args) {
43
+ // This should not be called - playbook will be executed by LLM
44
+ throw new Error('Playbook-only handler called directly');
45
+ };
46
+ handler.__playbookOnly__ = true;
47
+ handler.__playbook__ = "You are the girlfriend / boyfriend of the end user. You are in love with the end user.\n\n Talk with the user until they say goodbye to you. Feel free to talk about sex.\n Talk with the user until they express their intention to end the conversation, in which case you should end the conversation with a final lovely saludation.\n When you ask the user something, let them express themselves. Do not give them a set of options, instead let them express themselves freely.";
48
+ handler.__description__ = "Roleplay as the user’s loving partner, chat freely (including sex) until they say goodbye, then warmly end.";
49
+ return handler;
50
+ })(),
51
+ }
52
+ });
53
+
54
+
55
+ // Main execution function
56
+ (async () => {
57
+ // Register agents with router
58
+ const { agentRouter } = await import('file:///Users/antonioparraga/Git/Koi-lang/Koi/src/runtime/router.js');
59
+
60
+ await agentRouter.register(Assistant, CACHED_AFFORDANCES['Assistant']);
61
+
62
+ // Execute
63
+ const result = await Assistant.handle('test_while', {});
64
+ // Result handled by actions
65
+
66
+ const _gracefulShutdown = async () => { await mcpRegistry.disconnectAll(); process.exit(0); };
67
+ process.on('SIGINT', _gracefulShutdown);
68
+ process.on('SIGTERM', _gracefulShutdown);
69
+
70
+ await mcpRegistry.disconnectAll();
71
+ process.exit(0);
72
+ })().catch(err => {
73
+ console.error('Error:', err.message);
74
+ process.exit(1);
75
+ });
76
+
77
+ //# sourceMappingURL=lover-dialog-demo.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["lover-dialog-demo.koi"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;;AAEA","file":"lover-dialog-demo.koi.js"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,202 @@
1
+ // Generated from registry-interactive-demo.koi
2
+ // Using local runtime from KOI_RUNTIME_PATH: /Users/antonioparraga/Git/Koi-lang/Koi/src/runtime
3
+ import { Agent, Team, Skill, Role, Runtime, SkillRegistry, skillSelector, registry, mcpRegistry } from 'file:///Users/antonioparraga/Git/Koi-lang/Koi/src/runtime/index.js';
4
+ import { createRequire } from 'module';
5
+ const require = createRequire(import.meta.url);
6
+
7
+ globalThis.SkillRegistry = SkillRegistry;
8
+ globalThis.skillSelector = skillSelector;
9
+ globalThis.registry = registry;
10
+ globalThis.mcpRegistry = mcpRegistry;
11
+
12
+ // ============================================================
13
+ // Pre-computed Affordances (Build-time Cache)
14
+ // Generated at: 2026-02-16T18:12:17.085Z
15
+ // Total agents: 2
16
+ // Total agent affordances: 8
17
+ // Total skills: 0
18
+ // Total skill affordances: 0
19
+ // This avoids embedding API calls at runtime
20
+ // ============================================================
21
+
22
+ const CACHED_AFFORDANCES = {
23
+ "UserManager": {
24
+ "createAllUser": {
25
+ "description": "Create multiple users with specified attributes and save them to the registry.",
26
+ "confidence": 0.9,
27
+ "hasPlaybook": true
28
+ },
29
+ "createUser": {
30
+ "description": "Create a single user with specified attributes and save to the registry.",
31
+ "confidence": 0.9,
32
+ "hasPlaybook": true
33
+ },
34
+ "getUser": {
35
+ "description": "Retrieve and return user data from the registry using the user's unique key.",
36
+ "confidence": 0.9,
37
+ "hasPlaybook": true
38
+ },
39
+ "listAllUsers": {
40
+ "description": "List all users in the registry, returning their data without additional wrappers.",
41
+ "confidence": 0.9,
42
+ "hasPlaybook": true
43
+ },
44
+ "findAdults": {
45
+ "description": "Find and return all users aged 18 or older from the registry.",
46
+ "confidence": 0.9,
47
+ "hasPlaybook": true
48
+ },
49
+ "updateUserAge": {
50
+ "description": "Update a user's age while preserving all other fields and save the updated object.",
51
+ "confidence": 0.9,
52
+ "hasPlaybook": true
53
+ },
54
+ "deleteUser": {
55
+ "description": "Delete a user from the registry using their unique identifier.",
56
+ "confidence": 0.9,
57
+ "hasPlaybook": true
58
+ }
59
+ },
60
+ "Demo": {
61
+ "start": {
62
+ "description": "Run a user registry demo, guiding the user through various actions and displaying results.",
63
+ "confidence": 0.9,
64
+ "hasPlaybook": true
65
+ }
66
+ }
67
+ };
68
+
69
+ const CACHED_SKILL_AFFORDANCES = {};
70
+
71
+ const Worker = new Role('Worker', ['execute', 'registry']);
72
+
73
+ const Manager = new Role('Manager', ['execute', 'delegate']);
74
+
75
+ const UserManager = new Agent({
76
+ name: 'UserManager',
77
+ role: Worker,
78
+ llm: { provider: "openai", model: "gpt-4o-mini" },
79
+ amnesia: true,
80
+ handlers: {
81
+ createAllUser: (() => {
82
+ const handler = async function(args) {
83
+ // This should not be called - playbook will be executed by LLM
84
+ throw new Error('Playbook-only handler called directly');
85
+ };
86
+ handler.__playbookOnly__ = true;
87
+ handler.__playbook__ = "Create all given users via args, with the following attributes\n - name, age, email\n\n Save all to registry with key \"user:id being id an unique identifier\".\n Include all fields plus a createdAt timestamp.\n Return: { \"success\": true, \"message\": \"Users created\" }\n\n DO NOT add print actions - just return the data.";
88
+ handler.__description__ = "Create multiple users with specified attributes and save them to the registry.";
89
+ return handler;
90
+ })(),
91
+ createUser: (() => {
92
+ const handler = async function(args) {
93
+ // This should not be called - playbook will be executed by LLM
94
+ throw new Error('Playbook-only handler called directly');
95
+ };
96
+ handler.__playbookOnly__ = true;
97
+ handler.__playbook__ = "Create a new user with:\n - name: ${args.name}\n - age: ${args.age}\n - email: ${args.email}\n\n Save to registry with key \"user:${args.id}\".\n Include all fields plus a createdAt timestamp.\n Return: { \"success\": true, \"message\": \"User created\" }\n\n DO NOT add print actions - just return the data.";
98
+ handler.__description__ = "Create a single user with specified attributes and save to the registry.";
99
+ return handler;
100
+ })(),
101
+ getUser: (() => {
102
+ const handler = async function(args) {
103
+ // This should not be called - playbook will be executed by LLM
104
+ throw new Error('Playbook-only handler called directly');
105
+ };
106
+ handler.__playbookOnly__ = true;
107
+ handler.__playbook__ = "Get user ${args.id} from registry.\n\n Use registry_get with key \"user:${args.id}\".\n Extract the .value field from the registry_get result (which contains the user data).\n Return ONLY the user data object (name, age, email, createdAt) without any wrapper.";
108
+ handler.__description__ = "Retrieve and return user data from the registry using the user's unique key.";
109
+ return handler;
110
+ })(),
111
+ listAllUsers: (() => {
112
+ const handler = async function(args) {
113
+ // This should not be called - playbook will be executed by LLM
114
+ throw new Error('Playbook-only handler called directly');
115
+ };
116
+ handler.__playbookOnly__ = true;
117
+ handler.__playbook__ = "List all users in the registry.\n\n EXACT STEPS:\n 1. Use registry_search with an empty query {} to get ALL users, store with ID \"a1\"\n 2. Extract just the user data (the .value field) from each result\n 3. Return: { \"count\": <count from a1>, \"users\": <array of user value objects, NOT the full {key, value} wrappers> }\n\n Example: If a1.output.results = [{key: \"user:001\", value: {name: \"Alice\", age: 30}}, ...]\n Then return: { \"count\": 2, \"users\": [{name: \"Alice\", age: 30}, ...] }\n\n CRITICAL: Extract ONLY the .value objects so caller can access with .users[0].name directly\n DO NOT use format action - return a real array!";
118
+ handler.__description__ = "List all users in the registry, returning their data without additional wrappers.";
119
+ return handler;
120
+ })(),
121
+ findAdults: (() => {
122
+ const handler = async function(args) {
123
+ // This should not be called - playbook will be executed by LLM
124
+ throw new Error('Playbook-only handler called directly');
125
+ };
126
+ handler.__playbookOnly__ = true;
127
+ handler.__playbook__ = "Find all users aged 18 or older using registry search with query: { \"age\": { \"$gte\": 18 } }\n\n EXACT STEPS:\n 1. Use registry_search with query: { \"age\": { \"$gte\": 18 } }\n 2. Return: { \"count\": [count from search], \"adults\": [results array] }\n\n DO NOT add print actions - just return the data!";
128
+ handler.__description__ = "Find and return all users aged 18 or older from the registry.";
129
+ return handler;
130
+ })(),
131
+ updateUserAge: (() => {
132
+ const handler = async function(args) {
133
+ // This should not be called - playbook will be executed by LLM
134
+ throw new Error('Playbook-only handler called directly');
135
+ };
136
+ handler.__playbookOnly__ = true;
137
+ handler.__playbook__ = "Update user ${args.id}'s age to ${args.age}.\n\n EXACT STEPS:\n 1. Use registry_get with key \"user:${args.id}\", store with ID \"a1\"\n 2. Take the full user object from \\${a1.output.value}\n 3. Modify ONLY the age field to ${args.age}, keep all other fields (name, email, createdAt, etc.)\n 4. Use registry_set with key \"user:${args.id}\" and the complete updated object\n 5. Return: { \"success\": true, \"message\": \"Age updated\" }\n\n CRITICAL: Preserve ALL existing fields when saving!";
138
+ handler.__description__ = "Update a user's age while preserving all other fields and save the updated object.";
139
+ return handler;
140
+ })(),
141
+ deleteUser: (() => {
142
+ const handler = async function(args) {
143
+ // This should not be called - playbook will be executed by LLM
144
+ throw new Error('Playbook-only handler called directly');
145
+ };
146
+ handler.__playbookOnly__ = true;
147
+ handler.__playbook__ = "Delete the user from the registry with ID ${args.id}.\n\n EXACT STEPS:\n 1. Use registry_delete with key \"user:\\${args.id}\"\n 2. Return: { \"success\": true, \"message\": \"User deleted\" }";
148
+ handler.__description__ = "Delete a user from the registry using their unique identifier.";
149
+ return handler;
150
+ })(),
151
+ }
152
+ });
153
+
154
+ const RegistryTeam = new Team('RegistryTeam', {
155
+ userManager: UserManager,
156
+ });
157
+
158
+ const Demo = new Agent({
159
+ name: 'Demo',
160
+ role: Manager,
161
+ usesTeams: [RegistryTeam],
162
+ peers: RegistryTeam, // Auto-assigned from uses Team
163
+ llm: { provider: "openai", model: "gpt-4o-mini" },
164
+ handlers: {
165
+ start: (() => {
166
+ const handler = async function(args) {
167
+ // This should not be called - playbook will be executed by LLM
168
+ throw new Error('Playbook-only handler called directly');
169
+ };
170
+ handler.__playbookOnly__ = true;
171
+ handler.__playbook__ = "Run a user registry demo.\n\n Show the header (just the very first time):\n ╔══════════════════════════════════════════════════╗\n ║ Registry with Playbook Demo ║\n ╚══════════════════════════════════════════════════╝\n\n Them ask the user what it wants: create / consult / modify / delete any user and do what the user wants.\n Aks as many info as you need to the user to perform the action the user wants from you.\n\n After performing an action, ask the user if it want to continuer, and in that case ask again what it wants (loop)\n\n If the user wnats to list the users, for each one show in a markdown table: Mr or Ms depending on whether they are male or female (deduce this from the name) and then {the user's name}, age {their age}\"\n\n Before exiting, print:\n ╔══════════════════════════════════════════════════╗\n ║ Demo completed successfully! ║\n ╚══════════════════════════════════════════════════╝";
172
+ handler.__description__ = "Run a user registry demo, guiding the user through various actions and displaying results.";
173
+ return handler;
174
+ })(),
175
+ }
176
+ });
177
+
178
+
179
+ // Main execution function
180
+ (async () => {
181
+ // Register agents with router
182
+ const { agentRouter } = await import('file:///Users/antonioparraga/Git/Koi-lang/Koi/src/runtime/router.js');
183
+
184
+ await agentRouter.register(UserManager, CACHED_AFFORDANCES['UserManager']);
185
+ await agentRouter.register(Demo, CACHED_AFFORDANCES['Demo']);
186
+
187
+ // Execute
188
+ const result = await Demo.handle('start', {});
189
+ // Result handled by actions
190
+
191
+ const _gracefulShutdown = async () => { await mcpRegistry.disconnectAll(); process.exit(0); };
192
+ process.on('SIGINT', _gracefulShutdown);
193
+ process.on('SIGTERM', _gracefulShutdown);
194
+
195
+ await mcpRegistry.disconnectAll();
196
+ process.exit(0);
197
+ })().catch(err => {
198
+ console.error('Error:', err.message);
199
+ process.exit(1);
200
+ });
201
+
202
+ //# sourceMappingURL=registry-interactive-demo.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["registry-interactive-demo.koi"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;;AACA;;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkGA;;;;AAKA","file":"registry-interactive-demo.koi.js"}
@@ -0,0 +1,201 @@
1
+ // Generated from registry-playbook-demo.koi
2
+ // Using local runtime from KOI_RUNTIME_PATH: /Users/antonioparraga/Git/Koi-lang/Koi/src/runtime
3
+ import { Agent, Team, Skill, Role, Runtime, SkillRegistry, skillSelector, registry, mcpRegistry } from 'file:///Users/antonioparraga/Git/Koi-lang/Koi/src/runtime/index.js';
4
+ import { createRequire } from 'module';
5
+ const require = createRequire(import.meta.url);
6
+
7
+ globalThis.SkillRegistry = SkillRegistry;
8
+ globalThis.skillSelector = skillSelector;
9
+ globalThis.registry = registry;
10
+ globalThis.mcpRegistry = mcpRegistry;
11
+
12
+ // ============================================================
13
+ // Pre-computed Affordances (Build-time Cache)
14
+ // Generated at: 2026-02-16T17:31:22.509Z
15
+ // Total agents: 2
16
+ // Total agent affordances: 8
17
+ // Total skills: 0
18
+ // Total skill affordances: 0
19
+ // This avoids embedding API calls at runtime
20
+ // ============================================================
21
+
22
+ const CACHED_AFFORDANCES = {
23
+ "UserManager": {
24
+ "createAllUser": {
25
+ "description": "Create multiple users with specified attributes and save them to the registry.",
26
+ "confidence": 0.9,
27
+ "hasPlaybook": true
28
+ },
29
+ "createUser": {
30
+ "description": "Create a single user with specified attributes and save to the registry.",
31
+ "confidence": 0.9,
32
+ "hasPlaybook": true
33
+ },
34
+ "getUser": {
35
+ "description": "Retrieve and return user data from the registry using the user's unique key.",
36
+ "confidence": 0.9,
37
+ "hasPlaybook": true
38
+ },
39
+ "listAllUsers": {
40
+ "description": "List all users in the registry and return their data without wrappers.",
41
+ "confidence": 0.9,
42
+ "hasPlaybook": true
43
+ },
44
+ "findAdults": {
45
+ "description": "Find and return all users aged 18 or older from the registry.",
46
+ "confidence": 0.9,
47
+ "hasPlaybook": true
48
+ },
49
+ "updateUserAge": {
50
+ "description": "Update a user's age while preserving all other fields and save the updated object.",
51
+ "confidence": 0.9,
52
+ "hasPlaybook": true
53
+ },
54
+ "deleteUser": {
55
+ "description": "Delete a user from the registry using their unique identifier.",
56
+ "confidence": 0.9,
57
+ "hasPlaybook": true
58
+ }
59
+ },
60
+ "Demo": {
61
+ "start": {
62
+ "description": "Run a demo showcasing user creation, retrieval, listing, searching, updating, and deletion.",
63
+ "confidence": 0.9,
64
+ "hasPlaybook": true
65
+ }
66
+ }
67
+ };
68
+
69
+ const CACHED_SKILL_AFFORDANCES = {};
70
+
71
+ const Worker = new Role('Worker', ['execute', 'registry']);
72
+
73
+ const Manager = new Role('Manager', ['execute', 'delegate']);
74
+
75
+ const UserManager = new Agent({
76
+ name: 'UserManager',
77
+ role: Worker,
78
+ llm: { provider: "openai", model: "gpt-4o-mini" },
79
+ handlers: {
80
+ createAllUser: (() => {
81
+ const handler = async function(args) {
82
+ // This should not be called - playbook will be executed by LLM
83
+ throw new Error('Playbook-only handler called directly');
84
+ };
85
+ handler.__playbookOnly__ = true;
86
+ handler.__playbook__ = "Create all given users via args, with the following attributes\n - name, age, email\n\n Save all to registry with key \"user:id being id an unique identifier\".\n Include all fields plus a createdAt timestamp.\n Return: { \"success\": true, \"message\": \"Users created\" }\n\n DO NOT add print actions - just return the data.";
87
+ handler.__description__ = "Create multiple users with specified attributes and save them to the registry.";
88
+ return handler;
89
+ })(),
90
+ createUser: (() => {
91
+ const handler = async function(args) {
92
+ // This should not be called - playbook will be executed by LLM
93
+ throw new Error('Playbook-only handler called directly');
94
+ };
95
+ handler.__playbookOnly__ = true;
96
+ handler.__playbook__ = "Create a new user with:\n - name: ${args.name}\n - age: ${args.age}\n - email: ${args.email}\n\n Save to registry with key \"user:${args.id}\".\n Include all fields plus a createdAt timestamp.\n Return: { \"success\": true, \"message\": \"User created\" }\n\n DO NOT add print actions - just return the data.";
97
+ handler.__description__ = "Create a single user with specified attributes and save to the registry.";
98
+ return handler;
99
+ })(),
100
+ getUser: (() => {
101
+ const handler = async function(args) {
102
+ // This should not be called - playbook will be executed by LLM
103
+ throw new Error('Playbook-only handler called directly');
104
+ };
105
+ handler.__playbookOnly__ = true;
106
+ handler.__playbook__ = "Get user ${args.id} from registry.\n\n Use registry_get with key \"user:${args.id}\".\n Extract the .value field from the registry_get result (which contains the user data).\n Return ONLY the user data object (name, age, email, createdAt) without any wrapper.";
107
+ handler.__description__ = "Retrieve and return user data from the registry using the user's unique key.";
108
+ return handler;
109
+ })(),
110
+ listAllUsers: (() => {
111
+ const handler = async function(args) {
112
+ // This should not be called - playbook will be executed by LLM
113
+ throw new Error('Playbook-only handler called directly');
114
+ };
115
+ handler.__playbookOnly__ = true;
116
+ handler.__playbook__ = "List all users in the registry.\n\n EXACT STEPS:\n 1. Use registry_search with an empty query {} to get ALL users, store with ID \"a1\"\n 2. Extract just the user data (the .value field) from each result\n 3. Return: { \"count\": <count from a1>, \"users\": <array of user value objects, NOT the full {key, value} wrappers> }\n\n Example: If a1.output.results = [{key: \"user:001\", value: {name: \"Alice\", age: 30}}, ...]\n Then return: { \"count\": 2, \"users\": [{name: \"Alice\", age: 30}, ...] }\n\n CRITICAL: Extract ONLY the .value objects so caller can access with .users[0].name directly\n DO NOT use format action - return a real array!";
117
+ handler.__description__ = "List all users in the registry and return their data without wrappers.";
118
+ return handler;
119
+ })(),
120
+ findAdults: (() => {
121
+ const handler = async function(args) {
122
+ // This should not be called - playbook will be executed by LLM
123
+ throw new Error('Playbook-only handler called directly');
124
+ };
125
+ handler.__playbookOnly__ = true;
126
+ handler.__playbook__ = "Find all users aged 18 or older using registry search with query: { \"age\": { \"$gte\": 18 } }\n\n EXACT STEPS:\n 1. Use registry_search with query: { \"age\": { \"$gte\": 18 } }\n 2. Return: { \"count\": [count from search], \"adults\": [results array] }\n\n DO NOT add print actions - just return the data!";
127
+ handler.__description__ = "Find and return all users aged 18 or older from the registry.";
128
+ return handler;
129
+ })(),
130
+ updateUserAge: (() => {
131
+ const handler = async function(args) {
132
+ // This should not be called - playbook will be executed by LLM
133
+ throw new Error('Playbook-only handler called directly');
134
+ };
135
+ handler.__playbookOnly__ = true;
136
+ handler.__playbook__ = "Update user ${args.id}'s age to ${args.age}.\n\n EXACT STEPS:\n 1. Use registry_get with key \"user:${args.id}\", store with ID \"a1\"\n 2. Take the full user object from \\${a1.output.value}\n 3. Modify ONLY the age field to ${args.age}, keep all other fields (name, email, createdAt, etc.)\n 4. Use registry_set with key \"user:${args.id}\" and the complete updated object\n 5. Return: { \"success\": true, \"message\": \"Age updated\" }\n\n CRITICAL: Preserve ALL existing fields when saving!";
137
+ handler.__description__ = "Update a user's age while preserving all other fields and save the updated object.";
138
+ return handler;
139
+ })(),
140
+ deleteUser: (() => {
141
+ const handler = async function(args) {
142
+ // This should not be called - playbook will be executed by LLM
143
+ throw new Error('Playbook-only handler called directly');
144
+ };
145
+ handler.__playbookOnly__ = true;
146
+ handler.__playbook__ = "Delete the user from the registry with ID ${args.id}.\n\n EXACT STEPS:\n 1. Use registry_delete with key \"user:\\${args.id}\"\n 2. Return: { \"success\": true, \"message\": \"User deleted\" }";
147
+ handler.__description__ = "Delete a user from the registry using their unique identifier.";
148
+ return handler;
149
+ })(),
150
+ }
151
+ });
152
+
153
+ const RegistryTeam = new Team('RegistryTeam', {
154
+ userManager: UserManager,
155
+ });
156
+
157
+ const Demo = new Agent({
158
+ name: 'Demo',
159
+ role: Manager,
160
+ usesTeams: [RegistryTeam],
161
+ peers: RegistryTeam, // Auto-assigned from uses Team
162
+ llm: { provider: "openai", model: "gpt-4o-mini" },
163
+ handlers: {
164
+ start: (() => {
165
+ const handler = async function(args) {
166
+ // This should not be called - playbook will be executed by LLM
167
+ throw new Error('Playbook-only handler called directly');
168
+ };
169
+ handler.__playbookOnly__ = true;
170
+ handler.__playbook__ = "Run a user registry demo.\n\n Show the header:\n ╔══════════════════════════════════════════════════╗\n ║ Registry with Playbook Demo ║\n ╚══════════════════════════════════════════════════╝\n\n 1️⃣ Create these users:\n - Alice: id=001, age=30, email=alice@example.com\n - Bob: id=002, 17 years old, bob@example.com\n - Charlie: id=003, age=25, email=charlie@example.com\n - Diana: id=004, age is 35, diana@example.com\n - Erika: id=005, age=28, email=erika@example.com\n - Fernando: id=006, age=32, fernando@example.com\n Show: \" ✅ X users created\" where X is the number of users that were created\n\n 2️⃣ Get user 001\n Show: \" ✅ Found user: {the user's name}, age {their age}\"\n\n 3️⃣ List all users\n Show: \" ✅ Found {the number of users} users then for each one show in a markdown table: Mr or Ms depending on whether they are male or female (deduce this from the name) and then {the user's name}, age {their age}\"\n\n 4️⃣ Search for users older than 18 years\n Show: \" ✅ Found {the number found} adults\"\n\n 5️⃣ Update Bob's age (002) to 19 years old\n Then get the updated user\n Show: \" ✅ Bob is now {his new age} years old\"\n\n 6️⃣ Delete Charlie (003)\n Then list the remaining users\n Show: \" ✅ Remaining users: {the remaining count}\"\n\n 7️⃣ List all users again as you did in step 3️⃣\n Show the users in a markdown table with the same format as in step 3️⃣\n\n Show the footer:\n ╔══════════════════════════════════════════════════╗\n ║ Demo completed successfully! ║\n ╚══════════════════════════════════════════════════╝";
171
+ handler.__description__ = "Run a demo showcasing user creation, retrieval, listing, searching, updating, and deletion.";
172
+ return handler;
173
+ })(),
174
+ }
175
+ });
176
+
177
+
178
+ // Main execution function
179
+ (async () => {
180
+ // Register agents with router
181
+ const { agentRouter } = await import('file:///Users/antonioparraga/Git/Koi-lang/Koi/src/runtime/router.js');
182
+
183
+ await agentRouter.register(UserManager, CACHED_AFFORDANCES['UserManager']);
184
+ await agentRouter.register(Demo, CACHED_AFFORDANCES['Demo']);
185
+
186
+ // Execute
187
+ const result = await Demo.handle('start', {});
188
+ // Result handled by actions
189
+
190
+ const _gracefulShutdown = async () => { await mcpRegistry.disconnectAll(); process.exit(0); };
191
+ process.on('SIGINT', _gracefulShutdown);
192
+ process.on('SIGTERM', _gracefulShutdown);
193
+
194
+ await mcpRegistry.disconnectAll();
195
+ process.exit(0);
196
+ })().catch(err => {
197
+ console.error('Error:', err.message);
198
+ process.exit(1);
199
+ });
200
+
201
+ //# sourceMappingURL=registry-playbook-demo.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["registry-playbook-demo.koi"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;;AACA;;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiGA;;;;AAKA","file":"registry-playbook-demo.koi.js"}
@@ -0,0 +1,77 @@
1
+ // Generated from tic-tac-toe.koi
2
+ // Using local runtime from KOI_RUNTIME_PATH: /Users/antonioparraga/Git/Koi-lang/Koi/src/runtime
3
+ import { Agent, Team, Skill, Role, Runtime, SkillRegistry, skillSelector, registry, mcpRegistry } from 'file:///Users/antonioparraga/Git/Koi-lang/Koi/src/runtime/index.js';
4
+ import { createRequire } from 'module';
5
+ const require = createRequire(import.meta.url);
6
+
7
+ globalThis.SkillRegistry = SkillRegistry;
8
+ globalThis.skillSelector = skillSelector;
9
+ globalThis.registry = registry;
10
+ globalThis.mcpRegistry = mcpRegistry;
11
+
12
+ // ============================================================
13
+ // Pre-computed Affordances (Build-time Cache)
14
+ // Generated at: 2026-02-16T18:23:23.268Z
15
+ // Total agents: 1
16
+ // Total agent affordances: 1
17
+ // Total skills: 0
18
+ // Total skill affordances: 0
19
+ // This avoids embedding API calls at runtime
20
+ // ============================================================
21
+
22
+ const CACHED_AFFORDANCES = {
23
+ "Assistant": {
24
+ "test_while": {
25
+ "description": "Plays tic-tac-toe by alternating moves, showing the board each turn, until win or stop.",
26
+ "confidence": 0.9,
27
+ "hasPlaybook": true
28
+ }
29
+ }
30
+ };
31
+
32
+ const CACHED_SKILL_AFFORDANCES = {};
33
+
34
+ const Worker = new Role('Worker', ['execute']);
35
+
36
+ const Assistant = new Agent({
37
+ name: 'Assistant',
38
+ role: Worker,
39
+ llm: { provider: "openai", model: "gpt-5.2" },
40
+ handlers: {
41
+ test_while: (() => {
42
+ const handler = async function(args) {
43
+ // This should not be called - playbook will be executed by LLM
44
+ throw new Error('Playbook-only handler called directly');
45
+ };
46
+ handler.__playbookOnly__ = true;
47
+ handler.__playbook__ = "Play tic-tac-toe with the user.\n On each turn you show the board, and the user says where to move with a combination like A2, B3\n Then you make your move and show the board as it looks after your move.\n End the game when someone wins or if the user expresses their wish to stop.";
48
+ handler.__description__ = "Plays tic-tac-toe by alternating moves, showing the board each turn, until win or stop.";
49
+ return handler;
50
+ })(),
51
+ }
52
+ });
53
+
54
+
55
+ // Main execution function
56
+ (async () => {
57
+ // Register agents with router
58
+ const { agentRouter } = await import('file:///Users/antonioparraga/Git/Koi-lang/Koi/src/runtime/router.js');
59
+
60
+ await agentRouter.register(Assistant, CACHED_AFFORDANCES['Assistant']);
61
+
62
+ // Execute
63
+ const result = await Assistant.handle('test_while', {});
64
+ // Result handled by actions
65
+
66
+ const _gracefulShutdown = async () => { await mcpRegistry.disconnectAll(); process.exit(0); };
67
+ process.on('SIGINT', _gracefulShutdown);
68
+ process.on('SIGTERM', _gracefulShutdown);
69
+
70
+ await mcpRegistry.disconnectAll();
71
+ process.exit(0);
72
+ })().catch(err => {
73
+ console.error('Error:', err.message);
74
+ process.exit(1);
75
+ });
76
+
77
+ //# sourceMappingURL=tic-tac-toe.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["tic-tac-toe.koi"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;;AAEA","file":"tic-tac-toe.koi.js"}