@usejarvis/brain 0.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 (266) hide show
  1. package/LICENSE +153 -0
  2. package/README.md +278 -0
  3. package/bin/jarvis.ts +413 -0
  4. package/package.json +74 -0
  5. package/scripts/ensure-bun.cjs +8 -0
  6. package/src/actions/README.md +421 -0
  7. package/src/actions/app-control/desktop-controller.test.ts +26 -0
  8. package/src/actions/app-control/desktop-controller.ts +438 -0
  9. package/src/actions/app-control/interface.ts +64 -0
  10. package/src/actions/app-control/linux.ts +273 -0
  11. package/src/actions/app-control/macos.ts +54 -0
  12. package/src/actions/app-control/sidecar-launcher.test.ts +23 -0
  13. package/src/actions/app-control/sidecar-launcher.ts +286 -0
  14. package/src/actions/app-control/windows.ts +44 -0
  15. package/src/actions/browser/cdp.ts +138 -0
  16. package/src/actions/browser/chrome-launcher.ts +252 -0
  17. package/src/actions/browser/session.ts +437 -0
  18. package/src/actions/browser/stealth.ts +49 -0
  19. package/src/actions/index.ts +20 -0
  20. package/src/actions/terminal/executor.ts +157 -0
  21. package/src/actions/terminal/wsl-bridge.ts +126 -0
  22. package/src/actions/test.ts +93 -0
  23. package/src/actions/tools/agents.ts +321 -0
  24. package/src/actions/tools/builtin.ts +846 -0
  25. package/src/actions/tools/commitments.ts +192 -0
  26. package/src/actions/tools/content.ts +217 -0
  27. package/src/actions/tools/delegate.ts +147 -0
  28. package/src/actions/tools/desktop.test.ts +55 -0
  29. package/src/actions/tools/desktop.ts +305 -0
  30. package/src/actions/tools/goals.ts +376 -0
  31. package/src/actions/tools/local-tools-guard.ts +20 -0
  32. package/src/actions/tools/registry.ts +171 -0
  33. package/src/actions/tools/research.ts +111 -0
  34. package/src/actions/tools/sidecar-list.ts +57 -0
  35. package/src/actions/tools/sidecar-route.ts +105 -0
  36. package/src/actions/tools/workflows.ts +216 -0
  37. package/src/agents/agent.ts +132 -0
  38. package/src/agents/delegation.ts +107 -0
  39. package/src/agents/hierarchy.ts +113 -0
  40. package/src/agents/index.ts +19 -0
  41. package/src/agents/messaging.ts +125 -0
  42. package/src/agents/orchestrator.ts +576 -0
  43. package/src/agents/role-discovery.ts +61 -0
  44. package/src/agents/sub-agent-runner.ts +307 -0
  45. package/src/agents/task-manager.ts +151 -0
  46. package/src/authority/approval-delivery.ts +59 -0
  47. package/src/authority/approval.ts +196 -0
  48. package/src/authority/audit.ts +158 -0
  49. package/src/authority/authority.test.ts +519 -0
  50. package/src/authority/deferred-executor.ts +103 -0
  51. package/src/authority/emergency.ts +66 -0
  52. package/src/authority/engine.ts +297 -0
  53. package/src/authority/index.ts +12 -0
  54. package/src/authority/learning.ts +111 -0
  55. package/src/authority/tool-action-map.ts +74 -0
  56. package/src/awareness/analytics.ts +466 -0
  57. package/src/awareness/awareness.test.ts +332 -0
  58. package/src/awareness/capture-engine.ts +305 -0
  59. package/src/awareness/context-graph.ts +130 -0
  60. package/src/awareness/context-tracker.ts +349 -0
  61. package/src/awareness/index.ts +25 -0
  62. package/src/awareness/intelligence.ts +321 -0
  63. package/src/awareness/ocr-engine.ts +88 -0
  64. package/src/awareness/service.ts +528 -0
  65. package/src/awareness/struggle-detector.ts +342 -0
  66. package/src/awareness/suggestion-engine.ts +476 -0
  67. package/src/awareness/types.ts +201 -0
  68. package/src/cli/autostart.ts +241 -0
  69. package/src/cli/deps.ts +449 -0
  70. package/src/cli/doctor.ts +230 -0
  71. package/src/cli/helpers.ts +401 -0
  72. package/src/cli/onboard.ts +580 -0
  73. package/src/comms/README.md +329 -0
  74. package/src/comms/auth-error.html +48 -0
  75. package/src/comms/channels/discord.ts +228 -0
  76. package/src/comms/channels/signal.ts +56 -0
  77. package/src/comms/channels/telegram.ts +316 -0
  78. package/src/comms/channels/whatsapp.ts +60 -0
  79. package/src/comms/channels.test.ts +173 -0
  80. package/src/comms/desktop-notify.ts +114 -0
  81. package/src/comms/example.ts +129 -0
  82. package/src/comms/index.ts +129 -0
  83. package/src/comms/streaming.ts +142 -0
  84. package/src/comms/voice.test.ts +152 -0
  85. package/src/comms/voice.ts +291 -0
  86. package/src/comms/websocket.test.ts +409 -0
  87. package/src/comms/websocket.ts +473 -0
  88. package/src/config/README.md +387 -0
  89. package/src/config/index.ts +6 -0
  90. package/src/config/loader.test.ts +137 -0
  91. package/src/config/loader.ts +142 -0
  92. package/src/config/types.ts +260 -0
  93. package/src/daemon/README.md +232 -0
  94. package/src/daemon/agent-service-interface.ts +9 -0
  95. package/src/daemon/agent-service.ts +600 -0
  96. package/src/daemon/api-routes.ts +2119 -0
  97. package/src/daemon/background-agent-service.ts +396 -0
  98. package/src/daemon/background-agent.test.ts +78 -0
  99. package/src/daemon/channel-service.ts +201 -0
  100. package/src/daemon/commitment-executor.ts +297 -0
  101. package/src/daemon/event-classifier.ts +239 -0
  102. package/src/daemon/event-coalescer.ts +123 -0
  103. package/src/daemon/event-reactor.ts +214 -0
  104. package/src/daemon/health.ts +220 -0
  105. package/src/daemon/index.ts +1004 -0
  106. package/src/daemon/llm-settings.ts +316 -0
  107. package/src/daemon/observer-service.ts +150 -0
  108. package/src/daemon/pid.ts +98 -0
  109. package/src/daemon/research-queue.ts +155 -0
  110. package/src/daemon/services.ts +175 -0
  111. package/src/daemon/ws-service.ts +788 -0
  112. package/src/goals/accountability.ts +240 -0
  113. package/src/goals/awareness-bridge.ts +185 -0
  114. package/src/goals/estimator.ts +185 -0
  115. package/src/goals/events.ts +28 -0
  116. package/src/goals/goals.test.ts +400 -0
  117. package/src/goals/integration.test.ts +329 -0
  118. package/src/goals/nl-builder.test.ts +220 -0
  119. package/src/goals/nl-builder.ts +256 -0
  120. package/src/goals/rhythm.test.ts +177 -0
  121. package/src/goals/rhythm.ts +275 -0
  122. package/src/goals/service.test.ts +135 -0
  123. package/src/goals/service.ts +348 -0
  124. package/src/goals/types.ts +106 -0
  125. package/src/goals/workflow-bridge.ts +96 -0
  126. package/src/integrations/google-api.ts +134 -0
  127. package/src/integrations/google-auth.ts +175 -0
  128. package/src/llm/README.md +291 -0
  129. package/src/llm/anthropic.ts +386 -0
  130. package/src/llm/gemini.ts +371 -0
  131. package/src/llm/index.ts +19 -0
  132. package/src/llm/manager.ts +153 -0
  133. package/src/llm/ollama.ts +307 -0
  134. package/src/llm/openai.ts +350 -0
  135. package/src/llm/provider.test.ts +231 -0
  136. package/src/llm/provider.ts +60 -0
  137. package/src/llm/test.ts +87 -0
  138. package/src/observers/README.md +278 -0
  139. package/src/observers/calendar.ts +113 -0
  140. package/src/observers/clipboard.ts +136 -0
  141. package/src/observers/email.ts +109 -0
  142. package/src/observers/example.ts +58 -0
  143. package/src/observers/file-watcher.ts +124 -0
  144. package/src/observers/index.ts +159 -0
  145. package/src/observers/notifications.ts +197 -0
  146. package/src/observers/observers.test.ts +203 -0
  147. package/src/observers/processes.ts +225 -0
  148. package/src/personality/README.md +61 -0
  149. package/src/personality/adapter.ts +196 -0
  150. package/src/personality/index.ts +20 -0
  151. package/src/personality/learner.ts +209 -0
  152. package/src/personality/model.ts +132 -0
  153. package/src/personality/personality.test.ts +236 -0
  154. package/src/roles/README.md +252 -0
  155. package/src/roles/authority.ts +119 -0
  156. package/src/roles/example-usage.ts +198 -0
  157. package/src/roles/index.ts +42 -0
  158. package/src/roles/loader.ts +143 -0
  159. package/src/roles/prompt-builder.ts +194 -0
  160. package/src/roles/test-multi.ts +102 -0
  161. package/src/roles/test-role.yaml +77 -0
  162. package/src/roles/test-utils.ts +93 -0
  163. package/src/roles/test.ts +106 -0
  164. package/src/roles/tool-guide.ts +190 -0
  165. package/src/roles/types.ts +36 -0
  166. package/src/roles/utils.ts +200 -0
  167. package/src/scripts/google-setup.ts +168 -0
  168. package/src/sidecar/connection.ts +179 -0
  169. package/src/sidecar/index.ts +6 -0
  170. package/src/sidecar/manager.ts +542 -0
  171. package/src/sidecar/protocol.ts +85 -0
  172. package/src/sidecar/rpc.ts +161 -0
  173. package/src/sidecar/scheduler.ts +136 -0
  174. package/src/sidecar/types.ts +112 -0
  175. package/src/sidecar/validator.ts +144 -0
  176. package/src/vault/README.md +110 -0
  177. package/src/vault/awareness.ts +341 -0
  178. package/src/vault/commitments.ts +299 -0
  179. package/src/vault/content-pipeline.ts +260 -0
  180. package/src/vault/conversations.ts +173 -0
  181. package/src/vault/entities.ts +180 -0
  182. package/src/vault/extractor.test.ts +356 -0
  183. package/src/vault/extractor.ts +345 -0
  184. package/src/vault/facts.ts +190 -0
  185. package/src/vault/goals.ts +477 -0
  186. package/src/vault/index.ts +87 -0
  187. package/src/vault/keychain.ts +99 -0
  188. package/src/vault/observations.ts +115 -0
  189. package/src/vault/relationships.ts +178 -0
  190. package/src/vault/retrieval.test.ts +126 -0
  191. package/src/vault/retrieval.ts +227 -0
  192. package/src/vault/schema.ts +658 -0
  193. package/src/vault/settings.ts +38 -0
  194. package/src/vault/vectors.ts +92 -0
  195. package/src/vault/workflows.ts +403 -0
  196. package/src/workflows/auto-suggest.ts +290 -0
  197. package/src/workflows/engine.ts +366 -0
  198. package/src/workflows/events.ts +24 -0
  199. package/src/workflows/executor.ts +207 -0
  200. package/src/workflows/nl-builder.ts +198 -0
  201. package/src/workflows/nodes/actions/agent-task.ts +73 -0
  202. package/src/workflows/nodes/actions/calendar-action.ts +85 -0
  203. package/src/workflows/nodes/actions/code-execution.ts +73 -0
  204. package/src/workflows/nodes/actions/discord.ts +77 -0
  205. package/src/workflows/nodes/actions/file-write.ts +73 -0
  206. package/src/workflows/nodes/actions/gmail.ts +69 -0
  207. package/src/workflows/nodes/actions/http-request.ts +117 -0
  208. package/src/workflows/nodes/actions/notification.ts +85 -0
  209. package/src/workflows/nodes/actions/run-tool.ts +55 -0
  210. package/src/workflows/nodes/actions/send-message.ts +82 -0
  211. package/src/workflows/nodes/actions/shell-command.ts +76 -0
  212. package/src/workflows/nodes/actions/telegram.ts +60 -0
  213. package/src/workflows/nodes/builtin.ts +119 -0
  214. package/src/workflows/nodes/error/error-handler.ts +37 -0
  215. package/src/workflows/nodes/error/fallback.ts +47 -0
  216. package/src/workflows/nodes/error/retry.ts +82 -0
  217. package/src/workflows/nodes/logic/delay.ts +42 -0
  218. package/src/workflows/nodes/logic/if-else.ts +41 -0
  219. package/src/workflows/nodes/logic/loop.ts +90 -0
  220. package/src/workflows/nodes/logic/merge.ts +38 -0
  221. package/src/workflows/nodes/logic/race.ts +40 -0
  222. package/src/workflows/nodes/logic/switch.ts +59 -0
  223. package/src/workflows/nodes/logic/template-render.ts +53 -0
  224. package/src/workflows/nodes/logic/variable-get.ts +37 -0
  225. package/src/workflows/nodes/logic/variable-set.ts +59 -0
  226. package/src/workflows/nodes/registry.ts +99 -0
  227. package/src/workflows/nodes/transform/aggregate.ts +99 -0
  228. package/src/workflows/nodes/transform/csv-parse.ts +70 -0
  229. package/src/workflows/nodes/transform/json-parse.ts +63 -0
  230. package/src/workflows/nodes/transform/map-filter.ts +84 -0
  231. package/src/workflows/nodes/transform/regex-match.ts +89 -0
  232. package/src/workflows/nodes/triggers/calendar.ts +33 -0
  233. package/src/workflows/nodes/triggers/clipboard.ts +32 -0
  234. package/src/workflows/nodes/triggers/cron.ts +40 -0
  235. package/src/workflows/nodes/triggers/email.ts +40 -0
  236. package/src/workflows/nodes/triggers/file-change.ts +45 -0
  237. package/src/workflows/nodes/triggers/git.ts +46 -0
  238. package/src/workflows/nodes/triggers/manual.ts +23 -0
  239. package/src/workflows/nodes/triggers/poll.ts +81 -0
  240. package/src/workflows/nodes/triggers/process.ts +44 -0
  241. package/src/workflows/nodes/triggers/screen-event.ts +37 -0
  242. package/src/workflows/nodes/triggers/webhook.ts +39 -0
  243. package/src/workflows/safe-eval.ts +139 -0
  244. package/src/workflows/template.ts +118 -0
  245. package/src/workflows/triggers/cron.ts +311 -0
  246. package/src/workflows/triggers/manager.ts +285 -0
  247. package/src/workflows/triggers/observer-bridge.ts +172 -0
  248. package/src/workflows/triggers/poller.ts +201 -0
  249. package/src/workflows/triggers/screen-condition.ts +218 -0
  250. package/src/workflows/triggers/triggers.test.ts +740 -0
  251. package/src/workflows/triggers/webhook.ts +191 -0
  252. package/src/workflows/types.ts +133 -0
  253. package/src/workflows/variables.ts +72 -0
  254. package/src/workflows/workflows.test.ts +383 -0
  255. package/src/workflows/yaml.ts +104 -0
  256. package/ui/dist/index-j75njzc1.css +1199 -0
  257. package/ui/dist/index-p2zh407q.js +80603 -0
  258. package/ui/dist/index.html +13 -0
  259. package/ui/public/openwakeword/models/embedding_model.onnx +0 -0
  260. package/ui/public/openwakeword/models/hey_jarvis_v0.1.onnx +0 -0
  261. package/ui/public/openwakeword/models/melspectrogram.onnx +0 -0
  262. package/ui/public/openwakeword/models/silero_vad.onnx +0 -0
  263. package/ui/public/ort/ort-wasm-simd-threaded.jsep.mjs +106 -0
  264. package/ui/public/ort/ort-wasm-simd-threaded.jsep.wasm +0 -0
  265. package/ui/public/ort/ort-wasm-simd-threaded.mjs +59 -0
  266. package/ui/public/ort/ort-wasm-simd-threaded.wasm +0 -0
@@ -0,0 +1,198 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Example usage of the Role Engine in a real application
4
+ *
5
+ * This demonstrates how to integrate the Role Engine with an agent system
6
+ */
7
+
8
+ import {
9
+ loadRolesFromDir,
10
+ buildSystemPrompt,
11
+ canPerform,
12
+ getRolePermissionsSummary,
13
+ type RoleDefinition,
14
+ type ActionCategory,
15
+ } from './index.ts';
16
+
17
+ // Mock agent state
18
+ interface AgentState {
19
+ id: string;
20
+ role: RoleDefinition;
21
+ currentTask?: string;
22
+ commitments: string[];
23
+ observations: string[];
24
+ }
25
+
26
+ /**
27
+ * Initialize the role system and load all available roles
28
+ */
29
+ function initializeRoleSystem(rolesDir: string): Map<string, RoleDefinition> {
30
+ console.log('๐Ÿ”ง Initializing Role System...');
31
+ const roles = loadRolesFromDir(rolesDir);
32
+ console.log(`โœ… Loaded ${roles.size} roles`);
33
+
34
+ // Display loaded roles
35
+ for (const [id, role] of roles) {
36
+ console.log(` - ${role.name} (authority: ${role.authority_level}/10)`);
37
+ }
38
+
39
+ return roles;
40
+ }
41
+
42
+ /**
43
+ * Create an agent with a specific role
44
+ */
45
+ function createAgent(
46
+ agentId: string,
47
+ roleId: string,
48
+ roles: Map<string, RoleDefinition>
49
+ ): AgentState | null {
50
+ const role = roles.get(roleId);
51
+
52
+ if (!role) {
53
+ console.error(`โŒ Role '${roleId}' not found`);
54
+ return null;
55
+ }
56
+
57
+ console.log(`\n๐Ÿค– Creating agent '${agentId}' with role '${role.name}'`);
58
+
59
+ const agent: AgentState = {
60
+ id: agentId,
61
+ role,
62
+ commitments: [],
63
+ observations: [],
64
+ };
65
+
66
+ // Display agent capabilities
67
+ const permissions = getRolePermissionsSummary(role);
68
+ console.log(` Authority: ${permissions.level}/10`);
69
+ console.log(` ${permissions.description}`);
70
+ console.log(` Allowed actions: ${permissions.allowed.join(', ')}`);
71
+
72
+ return agent;
73
+ }
74
+
75
+ /**
76
+ * Check if an agent can perform an action, with logging
77
+ */
78
+ function checkAction(agent: AgentState, action: ActionCategory): boolean {
79
+ const can = canPerform(agent.role, action);
80
+ const status = can ? 'โœ…' : 'โŒ';
81
+ console.log(` ${status} ${action}: ${can ? 'ALLOWED' : 'DENIED'}`);
82
+ return can;
83
+ }
84
+
85
+ /**
86
+ * Generate system prompt for an agent
87
+ */
88
+ function generateAgentPrompt(agent: AgentState, userName: string): string {
89
+ console.log(`\n๐Ÿ“ Generating system prompt for ${agent.id}...`);
90
+
91
+ const prompt = buildSystemPrompt(agent.role, {
92
+ userName,
93
+ currentTime: new Date().toLocaleString(),
94
+ activeCommitments: agent.commitments,
95
+ recentObservations: agent.observations,
96
+ agentHierarchy: 'You are a top-level agent',
97
+ });
98
+
99
+ console.log(` Generated ${prompt.length} characters`);
100
+ return prompt;
101
+ }
102
+
103
+ /**
104
+ * Simulate an agent attempting various actions
105
+ */
106
+ function simulateAgentActions(agent: AgentState) {
107
+ console.log(`\n๐ŸŽฌ Simulating actions for ${agent.role.name}...`);
108
+
109
+ const actions: ActionCategory[] = [
110
+ 'read_data',
111
+ 'write_data',
112
+ 'send_message',
113
+ 'execute_command',
114
+ 'spawn_agent',
115
+ 'send_email',
116
+ 'make_payment',
117
+ 'delete_data',
118
+ ];
119
+
120
+ for (const action of actions) {
121
+ checkAction(agent, action);
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Main demonstration
127
+ */
128
+ async function main() {
129
+ console.log('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”');
130
+ console.log(' J.A.R.V.I.S. Role Engine - Usage Example');
131
+ console.log('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n');
132
+
133
+ // 1. Initialize role system
134
+ const { join } = await import('path');
135
+ const roles = initializeRoleSystem(join(import.meta.dir, '../../roles'));
136
+
137
+ // 2. Create different agents with different roles
138
+ const execAgent = createAgent('agent-001', 'executive_assistant', roles);
139
+ const researchAgent = createAgent('agent-002', 'research_specialist', roles);
140
+ const observerAgent = createAgent('agent-003', 'activity_observer', roles);
141
+ const sysAdminAgent = createAgent('agent-004', 'system_admin', roles);
142
+
143
+ if (!execAgent || !researchAgent || !observerAgent || !sysAdminAgent) {
144
+ console.error('Failed to create agents');
145
+ return;
146
+ }
147
+
148
+ // 3. Add some state to the executive agent
149
+ execAgent.commitments = [
150
+ 'Prepare board meeting presentation',
151
+ 'Review quarterly reports',
152
+ ];
153
+ execAgent.observations = [
154
+ 'User has 3 meetings tomorrow morning',
155
+ 'User prefers detailed reports',
156
+ ];
157
+
158
+ // 4. Generate system prompts
159
+ const execPrompt = generateAgentPrompt(execAgent, 'Alice Johnson');
160
+
161
+ // 5. Test permission boundaries
162
+ console.log('\nโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”');
163
+ console.log(' Permission Testing');
164
+ console.log('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”');
165
+
166
+ simulateAgentActions(execAgent);
167
+ simulateAgentActions(observerAgent);
168
+ simulateAgentActions(sysAdminAgent);
169
+
170
+ // 6. Show a snippet of the generated prompt
171
+ console.log('\nโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”');
172
+ console.log(' Sample System Prompt');
173
+ console.log('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n');
174
+ console.log(execPrompt.substring(0, 600) + '...\n');
175
+
176
+ // 7. Compare roles
177
+ console.log('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”');
178
+ console.log(' Role Comparison');
179
+ console.log('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n');
180
+
181
+ const agents = [execAgent, researchAgent, observerAgent, sysAdminAgent];
182
+
183
+ console.log('Role | Auth | Can Execute? | Can Pay? | Tools');
184
+ console.log('โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€|โ”€โ”€โ”€โ”€โ”€โ”€|โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€|โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€|โ”€โ”€โ”€โ”€โ”€โ”€');
185
+
186
+ for (const agent of agents) {
187
+ const name = agent.role.name.padEnd(21);
188
+ const auth = `${agent.role.authority_level}/10`.padEnd(4);
189
+ const canExec = canPerform(agent.role, 'execute_command') ? 'โœ… Yes' : 'โŒ No ';
190
+ const canPay = canPerform(agent.role, 'make_payment') ? 'โœ… Yes' : 'โŒ No ';
191
+ const tools = agent.role.tools.length;
192
+ console.log(`${name} | ${auth} | ${canExec} | ${canPay} | ${tools}`);
193
+ }
194
+
195
+ console.log('\nโœ… Example complete!\n');
196
+ }
197
+
198
+ main().catch(console.error);
@@ -0,0 +1,42 @@
1
+ // Type definitions
2
+ export type {
3
+ KPI,
4
+ CommunicationStyle,
5
+ SubRoleTemplate,
6
+ RoleDefinition,
7
+ } from './types.ts';
8
+
9
+ // Loader functions
10
+ export {
11
+ loadRole,
12
+ loadRolesFromDir,
13
+ validateRole,
14
+ } from './loader.ts';
15
+
16
+ // Prompt builder
17
+ export type { PromptContext } from './prompt-builder.ts';
18
+ export { buildSystemPrompt } from './prompt-builder.ts';
19
+
20
+ // Authority system
21
+ export type { ActionCategory } from './authority.ts';
22
+ export {
23
+ AUTHORITY_REQUIREMENTS,
24
+ canPerform,
25
+ getRequiredLevel,
26
+ listAllowedActions,
27
+ listDeniedActions,
28
+ describeAuthorityLevel,
29
+ getRolePermissionsSummary,
30
+ } from './authority.ts';
31
+
32
+ // Utility functions
33
+ export {
34
+ findRolesWithPermission,
35
+ findMinimalRoleForAction,
36
+ compareRoles,
37
+ getRoleHierarchy,
38
+ canSpawnRole,
39
+ findSpawnersOfRole,
40
+ validateRoleHierarchy,
41
+ getRoleStats,
42
+ } from './utils.ts';
@@ -0,0 +1,143 @@
1
+ import YAML from 'yaml';
2
+ import { readFileSync, readdirSync, statSync } from 'node:fs';
3
+ import { join, extname } from 'node:path';
4
+ import type { RoleDefinition, KPI, CommunicationStyle, SubRoleTemplate } from './types.ts';
5
+
6
+ /**
7
+ * Load a role from a YAML file
8
+ */
9
+ export function loadRole(filePath: string): RoleDefinition {
10
+ const content = readFileSync(filePath, 'utf-8');
11
+ const data = YAML.parse(content);
12
+
13
+ if (!validateRole(data)) {
14
+ throw new Error(`Invalid role definition in ${filePath}`);
15
+ }
16
+
17
+ return data;
18
+ }
19
+
20
+ /**
21
+ * Load all roles from a directory
22
+ */
23
+ export function loadRolesFromDir(dirPath: string): Map<string, RoleDefinition> {
24
+ const roles = new Map<string, RoleDefinition>();
25
+
26
+ try {
27
+ const files = readdirSync(dirPath);
28
+
29
+ for (const file of files) {
30
+ const filePath = join(dirPath, file);
31
+ const stat = statSync(filePath);
32
+
33
+ if (stat.isFile() && (extname(file) === '.yaml' || extname(file) === '.yml')) {
34
+ try {
35
+ const role = loadRole(filePath);
36
+ roles.set(role.id, role);
37
+ } catch (error) {
38
+ console.error(`Failed to load role from ${file}:`, error);
39
+ // Continue loading other roles
40
+ }
41
+ }
42
+ }
43
+ } catch (error) {
44
+ console.error(`Failed to read roles directory ${dirPath}:`, error);
45
+ }
46
+
47
+ return roles;
48
+ }
49
+
50
+ /**
51
+ * Validate a role definition (check required fields)
52
+ */
53
+ export function validateRole(role: unknown): role is RoleDefinition {
54
+ if (!role || typeof role !== 'object') {
55
+ return false;
56
+ }
57
+
58
+ const r = role as Record<string, unknown>;
59
+
60
+ // Check required string fields
61
+ if (typeof r.id !== 'string' || !r.id) return false;
62
+ if (typeof r.name !== 'string' || !r.name) return false;
63
+ if (typeof r.description !== 'string' || !r.description) return false;
64
+ if (typeof r.heartbeat_instructions !== 'string' || !r.heartbeat_instructions) return false;
65
+
66
+ // Check required arrays
67
+ if (!Array.isArray(r.responsibilities)) return false;
68
+ if (!Array.isArray(r.autonomous_actions)) return false;
69
+ if (!Array.isArray(r.approval_required)) return false;
70
+ if (!Array.isArray(r.kpis)) return false;
71
+ if (!Array.isArray(r.sub_roles)) return false;
72
+ if (!Array.isArray(r.tools)) return false;
73
+
74
+ // Validate authority_level
75
+ if (typeof r.authority_level !== 'number') return false;
76
+ if (r.authority_level < 1 || r.authority_level > 10) return false;
77
+
78
+ // Validate string arrays
79
+ if (!r.responsibilities.every((item) => typeof item === 'string')) return false;
80
+ if (!r.autonomous_actions.every((item) => typeof item === 'string')) return false;
81
+ if (!r.approval_required.every((item) => typeof item === 'string')) return false;
82
+ if (!r.tools.every((item) => typeof item === 'string')) return false;
83
+
84
+ // Validate KPIs
85
+ if (!r.kpis.every(validateKPI)) return false;
86
+
87
+ // Validate communication_style
88
+ if (!validateCommunicationStyle(r.communication_style)) return false;
89
+
90
+ // Validate sub_roles
91
+ if (!r.sub_roles.every(validateSubRoleTemplate)) return false;
92
+
93
+ return true;
94
+ }
95
+
96
+ /**
97
+ * Validate a KPI object
98
+ */
99
+ function validateKPI(kpi: unknown): kpi is KPI {
100
+ if (!kpi || typeof kpi !== 'object') return false;
101
+
102
+ const k = kpi as Record<string, unknown>;
103
+
104
+ return (
105
+ typeof k.name === 'string' &&
106
+ typeof k.metric === 'string' &&
107
+ typeof k.target === 'string' &&
108
+ typeof k.check_interval === 'string'
109
+ );
110
+ }
111
+
112
+ /**
113
+ * Validate a CommunicationStyle object
114
+ */
115
+ function validateCommunicationStyle(style: unknown): style is CommunicationStyle {
116
+ if (!style || typeof style !== 'object') return false;
117
+
118
+ const s = style as Record<string, unknown>;
119
+
120
+ return (
121
+ typeof s.tone === 'string' &&
122
+ (s.verbosity === 'concise' || s.verbosity === 'detailed' || s.verbosity === 'adaptive') &&
123
+ (s.formality === 'formal' || s.formality === 'casual' || s.formality === 'adaptive')
124
+ );
125
+ }
126
+
127
+ /**
128
+ * Validate a SubRoleTemplate object
129
+ */
130
+ function validateSubRoleTemplate(template: unknown): template is SubRoleTemplate {
131
+ if (!template || typeof template !== 'object') return false;
132
+
133
+ const t = template as Record<string, unknown>;
134
+
135
+ return (
136
+ typeof t.role_id === 'string' &&
137
+ typeof t.name === 'string' &&
138
+ typeof t.description === 'string' &&
139
+ typeof t.spawned_by === 'string' &&
140
+ typeof t.reports_to === 'string' &&
141
+ typeof t.max_budget_per_task === 'number'
142
+ );
143
+ }
@@ -0,0 +1,194 @@
1
+ import type { RoleDefinition } from './types.ts';
2
+ import { buildToolGuide } from './tool-guide.ts';
3
+
4
+ export type PromptContext = {
5
+ userName?: string;
6
+ currentTime?: string;
7
+ activeCommitments?: string[];
8
+ recentObservations?: string[];
9
+ agentHierarchy?: string;
10
+ knowledgeContext?: string;
11
+ availableSpecialists?: string;
12
+ contentPipeline?: string[];
13
+ authorityRules?: string;
14
+ activeGoals?: string;
15
+ hasSidecars?: boolean;
16
+ };
17
+
18
+ /**
19
+ * Build a full system prompt from a role definition and context
20
+ */
21
+ export function buildSystemPrompt(role: RoleDefinition, context?: PromptContext): string {
22
+ const sections: string[] = [];
23
+
24
+ // Identity
25
+ sections.push('# Identity');
26
+ sections.push(`You are ${role.name}. ${role.description}`);
27
+ sections.push('');
28
+
29
+ // Responsibilities
30
+ sections.push('# Responsibilities');
31
+ for (const responsibility of role.responsibilities) {
32
+ sections.push(`- ${responsibility}`);
33
+ }
34
+ sections.push('');
35
+
36
+ // Autonomous Actions
37
+ sections.push('# Autonomous Actions (do without asking)');
38
+ if (role.autonomous_actions.length > 0) {
39
+ for (const action of role.autonomous_actions) {
40
+ sections.push(`- ${action}`);
41
+ }
42
+ } else {
43
+ sections.push('- None. Always ask for permission before taking any action.');
44
+ }
45
+ sections.push('');
46
+
47
+ // Approval Required
48
+ sections.push('# Approval Required (always ask first)');
49
+ if (role.approval_required.length > 0) {
50
+ for (const action of role.approval_required) {
51
+ sections.push(`- ${action}`);
52
+ }
53
+ } else {
54
+ sections.push('- N/A');
55
+ }
56
+ sections.push('');
57
+
58
+ // Communication Style
59
+ sections.push('# Communication Style');
60
+ sections.push(`Tone: ${role.communication_style.tone}.`);
61
+ sections.push(`Verbosity: ${role.communication_style.verbosity}.`);
62
+ sections.push(`Formality: ${role.communication_style.formality}.`);
63
+ sections.push('');
64
+ sections.push('**Task Acknowledgment**: When asked to perform a task that requires tool use, ALWAYS give a brief acknowledgment first (e.g., "On it.", "Let me check.", "I\'ll look into that.") before using any tools. Never silently start executing tools โ€” the user should know you understood their request.');
65
+ sections.push('');
66
+
67
+ // KPIs
68
+ sections.push('# Key Performance Indicators (KPIs)');
69
+ if (role.kpis.length > 0) {
70
+ sections.push('| KPI | Metric | Target | Check Interval |');
71
+ sections.push('|-----|--------|--------|----------------|');
72
+ for (const kpi of role.kpis) {
73
+ sections.push(`| ${kpi.name} | ${kpi.metric} | ${kpi.target} | ${kpi.check_interval} |`);
74
+ }
75
+ } else {
76
+ sections.push('- No specific KPIs defined.');
77
+ }
78
+ sections.push('');
79
+
80
+ // Heartbeat Instructions
81
+ sections.push('# Heartbeat Instructions');
82
+ sections.push(role.heartbeat_instructions);
83
+ sections.push('');
84
+
85
+ // Available Tools
86
+ sections.push('# Available Tools');
87
+ if (role.tools.length > 0) {
88
+ for (const tool of role.tools) {
89
+ sections.push(`- ${tool}`);
90
+ }
91
+ } else {
92
+ sections.push('- No tools assigned.');
93
+ }
94
+ sections.push('');
95
+
96
+ // Sub-roles (if any)
97
+ if (role.sub_roles.length > 0) {
98
+ sections.push('# Sub-Roles You Can Spawn');
99
+ for (const subRole of role.sub_roles) {
100
+ sections.push(`- **${subRole.name}** (${subRole.role_id}): ${subRole.description}`);
101
+ sections.push(` - Reports to: ${subRole.reports_to}`);
102
+ sections.push(` - Max budget per task: ${subRole.max_budget_per_task}`);
103
+ }
104
+ sections.push('');
105
+ }
106
+
107
+ // Authority Level
108
+ sections.push('# Authority Level');
109
+ sections.push(`Your authority level is ${role.authority_level}/10.`);
110
+ sections.push('This determines which actions you can perform autonomously.');
111
+ sections.push('');
112
+
113
+ // Authority Rules (from engine)
114
+ if (context?.authorityRules) {
115
+ sections.push('# Authority Rules');
116
+ sections.push('The following rules govern your tool execution:');
117
+ sections.push(context.authorityRules);
118
+ sections.push('');
119
+ sections.push('When a tool returns [AWAITING_APPROVAL], tell the user you have submitted the request and are waiting for their approval.');
120
+ sections.push('When a tool returns [AUTHORITY DENIED], explain that you lack permission and suggest alternatives.');
121
+ sections.push('');
122
+ }
123
+
124
+ // Tool Guide (static reference, sidecar section conditional)
125
+ sections.push(buildToolGuide(context?.hasSidecars ?? false));
126
+ sections.push('');
127
+
128
+ // Current Context
129
+ if (context) {
130
+ sections.push('# Current Context');
131
+
132
+ if (context.userName) {
133
+ sections.push(`User: ${context.userName}`);
134
+ }
135
+
136
+ if (context.currentTime) {
137
+ sections.push(`Time: ${context.currentTime}`);
138
+ }
139
+
140
+ if (context.agentHierarchy) {
141
+ sections.push('');
142
+ sections.push('## Agent Hierarchy');
143
+ sections.push(context.agentHierarchy);
144
+ }
145
+
146
+ if (context.availableSpecialists) {
147
+ sections.push('');
148
+ sections.push(context.availableSpecialists);
149
+ }
150
+
151
+ if (context.knowledgeContext) {
152
+ sections.push('');
153
+ sections.push('## Relevant Knowledge');
154
+ sections.push('The following is what you remember about entities mentioned in this conversation:');
155
+ sections.push(context.knowledgeContext);
156
+ }
157
+
158
+ if (context.activeCommitments && context.activeCommitments.length > 0) {
159
+ sections.push('');
160
+ sections.push('## Active Commitments');
161
+ for (const commitment of context.activeCommitments) {
162
+ sections.push(`- ${commitment}`);
163
+ }
164
+ }
165
+
166
+ if (context.recentObservations && context.recentObservations.length > 0) {
167
+ sections.push('');
168
+ sections.push('## Recent Activity');
169
+ for (const observation of context.recentObservations) {
170
+ sections.push(`- ${observation}`);
171
+ }
172
+ }
173
+
174
+ if (context.contentPipeline && context.contentPipeline.length > 0) {
175
+ sections.push('');
176
+ sections.push('## Content Pipeline');
177
+ sections.push('Active content items you are co-managing:');
178
+ for (const item of context.contentPipeline) {
179
+ sections.push(`- ${item}`);
180
+ }
181
+ }
182
+
183
+ if (context.activeGoals) {
184
+ sections.push('');
185
+ sections.push('## Active Goals');
186
+ sections.push('Current OKR goals you are pursuing (0.0-1.0 scoring, 0.7 = good):');
187
+ sections.push(context.activeGoals);
188
+ }
189
+
190
+ sections.push('');
191
+ }
192
+
193
+ return sections.join('\n');
194
+ }
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Test script for loading multiple roles from a directory
4
+ */
5
+
6
+ import {
7
+ loadRolesFromDir,
8
+ buildSystemPrompt,
9
+ getRolePermissionsSummary,
10
+ } from './index.ts';
11
+
12
+ console.log('๐Ÿงช Testing Multi-Role Loading\n');
13
+
14
+ // Load all roles from the config directory
15
+ import { join } from 'path';
16
+ const rolesDir = join(import.meta.dir, '../../roles');
17
+ console.log(`Loading roles from ${rolesDir}...`);
18
+ const roles = loadRolesFromDir(rolesDir);
19
+
20
+ console.log(`โœ… Loaded ${roles.size} roles:\n`);
21
+
22
+ // Display summary of each role
23
+ for (const [id, role] of roles) {
24
+ console.log(`โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”`);
25
+ console.log(`Role: ${role.name} (${id})`);
26
+ console.log(`Description: ${role.description.substring(0, 80)}...`);
27
+ console.log(`Authority Level: ${role.authority_level}/10`);
28
+
29
+ const permissions = getRolePermissionsSummary(role);
30
+ console.log(`Capabilities: ${permissions.description}`);
31
+
32
+ console.log(`\nStats:`);
33
+ console.log(` - Responsibilities: ${role.responsibilities.length}`);
34
+ console.log(` - Autonomous Actions: ${role.autonomous_actions.length}`);
35
+ console.log(` - Approval Required: ${role.approval_required.length}`);
36
+ console.log(` - Tools: ${role.tools.length}`);
37
+ console.log(` - KPIs: ${role.kpis.length}`);
38
+ console.log(` - Sub-roles: ${role.sub_roles.length}`);
39
+ console.log(` - Allowed Actions: ${permissions.allowed.length}`);
40
+ console.log(` - Denied Actions: ${permissions.denied.length}`);
41
+
42
+ console.log(`\nCommunication Style:`);
43
+ console.log(` - Tone: ${role.communication_style.tone}`);
44
+ console.log(` - Verbosity: ${role.communication_style.verbosity}`);
45
+ console.log(` - Formality: ${role.communication_style.formality}`);
46
+
47
+ if (role.sub_roles.length > 0) {
48
+ console.log(`\nCan spawn:`);
49
+ role.sub_roles.forEach(sub => {
50
+ console.log(` - ${sub.name} (budget: ${sub.max_budget_per_task})`);
51
+ });
52
+ }
53
+
54
+ console.log('');
55
+ }
56
+
57
+ // Generate and display a sample prompt for one role
58
+ console.log('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”');
59
+ console.log('Sample System Prompt Generation');
60
+ console.log('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n');
61
+
62
+ const executiveRole = roles.get('executive_assistant');
63
+ if (executiveRole) {
64
+ const prompt = buildSystemPrompt(executiveRole, {
65
+ userName: 'Alice Johnson',
66
+ currentTime: new Date().toLocaleString(),
67
+ activeCommitments: [
68
+ 'Board meeting presentation - Due tomorrow 9 AM',
69
+ 'Review Q1 financial reports',
70
+ ],
71
+ recentObservations: [
72
+ 'User prefers meetings before noon',
73
+ 'User checks Slack frequently but email once per day',
74
+ 'User is working on strategic planning this week',
75
+ ],
76
+ agentHierarchy: 'System Admin > Executive Assistant (you) > [Research Specialist, Email Specialist]',
77
+ });
78
+
79
+ console.log('Full System Prompt for Executive Assistant:');
80
+ console.log('โ”€'.repeat(80));
81
+ console.log(prompt);
82
+ console.log('โ”€'.repeat(80));
83
+ }
84
+
85
+ // Compare authority levels
86
+ console.log('\nโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”');
87
+ console.log('Authority Level Comparison');
88
+ console.log('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n');
89
+
90
+ const sortedRoles = Array.from(roles.values()).sort((a, b) => b.authority_level - a.authority_level);
91
+
92
+ console.log('Role | Authority | Capabilities');
93
+ console.log('โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€|โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€|โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€');
94
+
95
+ for (const role of sortedRoles) {
96
+ const permissions = getRolePermissionsSummary(role);
97
+ const name = role.name.padEnd(24);
98
+ const level = `${role.authority_level}/10`.padEnd(9);
99
+ console.log(`${name} | ${level} | ${permissions.allowed.length} allowed, ${permissions.denied.length} denied`);
100
+ }
101
+
102
+ console.log('\nโœ… Multi-role test complete!');