digital-workers 2.1.1 → 2.3.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 (197) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +136 -180
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +34 -21
  5. package/dist/actions.js.map +1 -1
  6. package/dist/agent-comms.d.ts +438 -0
  7. package/dist/agent-comms.d.ts.map +1 -0
  8. package/dist/agent-comms.js +677 -0
  9. package/dist/agent-comms.js.map +1 -0
  10. package/dist/approve.d.ts +40 -8
  11. package/dist/approve.d.ts.map +1 -1
  12. package/dist/approve.js +86 -20
  13. package/dist/approve.js.map +1 -1
  14. package/dist/ask.d.ts +38 -7
  15. package/dist/ask.d.ts.map +1 -1
  16. package/dist/ask.js +85 -25
  17. package/dist/ask.js.map +1 -1
  18. package/dist/browse.d.ts +223 -0
  19. package/dist/browse.d.ts.map +1 -0
  20. package/dist/browse.js +392 -0
  21. package/dist/browse.js.map +1 -0
  22. package/dist/capability-tiers.d.ts +230 -0
  23. package/dist/capability-tiers.d.ts.map +1 -0
  24. package/dist/capability-tiers.js +388 -0
  25. package/dist/capability-tiers.js.map +1 -0
  26. package/dist/cascade-context.d.ts +523 -0
  27. package/dist/cascade-context.d.ts.map +1 -0
  28. package/dist/cascade-context.js +494 -0
  29. package/dist/cascade-context.js.map +1 -0
  30. package/dist/client.d.ts +162 -0
  31. package/dist/client.d.ts.map +1 -0
  32. package/dist/client.js +64 -0
  33. package/dist/client.js.map +1 -0
  34. package/dist/decide.d.ts +42 -6
  35. package/dist/decide.d.ts.map +1 -1
  36. package/dist/decide.js +54 -11
  37. package/dist/decide.js.map +1 -1
  38. package/dist/do.d.ts +36 -7
  39. package/dist/do.d.ts.map +1 -1
  40. package/dist/do.js +82 -39
  41. package/dist/do.js.map +1 -1
  42. package/dist/error-escalation.d.ts +416 -0
  43. package/dist/error-escalation.d.ts.map +1 -0
  44. package/dist/error-escalation.js +656 -0
  45. package/dist/error-escalation.js.map +1 -0
  46. package/dist/generate.d.ts +48 -7
  47. package/dist/generate.d.ts.map +1 -1
  48. package/dist/generate.js +49 -8
  49. package/dist/generate.js.map +1 -1
  50. package/dist/goals.d.ts +10 -9
  51. package/dist/goals.d.ts.map +1 -1
  52. package/dist/goals.js +30 -24
  53. package/dist/goals.js.map +1 -1
  54. package/dist/image.d.ts +189 -0
  55. package/dist/image.d.ts.map +1 -0
  56. package/dist/image.js +528 -0
  57. package/dist/image.js.map +1 -0
  58. package/dist/index.d.ts +59 -2
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +92 -2
  61. package/dist/index.js.map +1 -1
  62. package/dist/is.d.ts +45 -10
  63. package/dist/is.d.ts.map +1 -1
  64. package/dist/is.js +56 -21
  65. package/dist/is.js.map +1 -1
  66. package/dist/kpis.d.ts +24 -15
  67. package/dist/kpis.d.ts.map +1 -1
  68. package/dist/kpis.js +16 -14
  69. package/dist/kpis.js.map +1 -1
  70. package/dist/load-balancing.d.ts +395 -0
  71. package/dist/load-balancing.d.ts.map +1 -0
  72. package/dist/load-balancing.js +991 -0
  73. package/dist/load-balancing.js.map +1 -0
  74. package/dist/logger.d.ts +76 -0
  75. package/dist/logger.d.ts.map +1 -0
  76. package/dist/logger.js +39 -0
  77. package/dist/logger.js.map +1 -0
  78. package/dist/notify.d.ts +38 -9
  79. package/dist/notify.d.ts.map +1 -1
  80. package/dist/notify.js +72 -17
  81. package/dist/notify.js.map +1 -1
  82. package/dist/role.d.ts +5 -4
  83. package/dist/role.d.ts.map +1 -1
  84. package/dist/role.js +13 -10
  85. package/dist/role.js.map +1 -1
  86. package/dist/runtime.d.ts +310 -0
  87. package/dist/runtime.d.ts.map +1 -0
  88. package/dist/runtime.js +510 -0
  89. package/dist/runtime.js.map +1 -0
  90. package/dist/team.d.ts +11 -6
  91. package/dist/team.d.ts.map +1 -1
  92. package/dist/team.js +22 -15
  93. package/dist/team.js.map +1 -1
  94. package/dist/transports/email.d.ts +318 -0
  95. package/dist/transports/email.d.ts.map +1 -0
  96. package/dist/transports/email.js +779 -0
  97. package/dist/transports/email.js.map +1 -0
  98. package/dist/transports/slack.d.ts +515 -0
  99. package/dist/transports/slack.d.ts.map +1 -0
  100. package/dist/transports/slack.js +844 -0
  101. package/dist/transports/slack.js.map +1 -0
  102. package/dist/transports.d.ts.map +1 -1
  103. package/dist/transports.js +44 -25
  104. package/dist/transports.js.map +1 -1
  105. package/dist/types.d.ts +149 -19
  106. package/dist/types.d.ts.map +1 -1
  107. package/dist/types.js +6 -0
  108. package/dist/types.js.map +1 -1
  109. package/dist/utils/id.d.ts +19 -0
  110. package/dist/utils/id.d.ts.map +1 -0
  111. package/dist/utils/id.js +21 -0
  112. package/dist/utils/id.js.map +1 -0
  113. package/dist/video.d.ts +203 -0
  114. package/dist/video.d.ts.map +1 -0
  115. package/dist/video.js +528 -0
  116. package/dist/video.js.map +1 -0
  117. package/dist/worker.d.ts +343 -0
  118. package/dist/worker.d.ts.map +1 -0
  119. package/dist/worker.js +698 -0
  120. package/dist/worker.js.map +1 -0
  121. package/package.json +24 -5
  122. package/src/actions.ts +48 -38
  123. package/src/agent-comms.ts +1200 -0
  124. package/src/approve.ts +91 -20
  125. package/src/ask.ts +99 -25
  126. package/src/browse.ts +627 -0
  127. package/src/capability-tiers.ts +545 -0
  128. package/src/cascade-context.ts +648 -0
  129. package/src/client.ts +221 -0
  130. package/src/decide.ts +81 -35
  131. package/src/do.ts +98 -52
  132. package/src/error-escalation.ts +1123 -0
  133. package/src/generate.ts +52 -18
  134. package/src/goals.ts +36 -27
  135. package/src/image.ts +816 -0
  136. package/src/index.ts +410 -2
  137. package/src/is.ts +59 -25
  138. package/src/kpis.ts +41 -36
  139. package/src/load-balancing.ts +1467 -0
  140. package/src/logger.ts +93 -0
  141. package/src/notify.ts +78 -17
  142. package/src/role.ts +30 -20
  143. package/src/runtime.ts +796 -0
  144. package/src/team.ts +24 -19
  145. package/src/transports/email.ts +1160 -0
  146. package/src/transports/slack.ts +1320 -0
  147. package/src/transports.ts +58 -43
  148. package/src/types.ts +182 -46
  149. package/src/utils/id.ts +21 -0
  150. package/src/video.ts +906 -0
  151. package/src/worker.ts +1007 -0
  152. package/test/agent-comms.test.ts +1397 -0
  153. package/test/approve.test.ts +305 -0
  154. package/test/ask.test.ts +274 -0
  155. package/test/browse.test.ts +361 -0
  156. package/test/capability-tiers.test.ts +631 -0
  157. package/test/cascade-context.test.ts +692 -0
  158. package/test/decide.test.ts +252 -0
  159. package/test/do.test.ts +144 -0
  160. package/test/error-escalation.test.ts +1205 -0
  161. package/test/error-logging.test.ts +357 -0
  162. package/test/generate.test.ts +319 -0
  163. package/test/image.test.ts +398 -0
  164. package/test/is.test.ts +287 -0
  165. package/test/load-balancing-safety.test.ts +404 -0
  166. package/test/load-balancing-thread-safety.test.ts +464 -0
  167. package/test/load-balancing.test.ts +1145 -0
  168. package/test/notify.test.ts +434 -0
  169. package/test/primitives.test.ts +320 -0
  170. package/test/runtime-integration.test.ts +892 -0
  171. package/test/transports/crypto.test.ts +230 -0
  172. package/test/transports/email.test.ts +866 -0
  173. package/test/transports/id-generation.test.ts +91 -0
  174. package/test/transports/slack.test.ts +760 -0
  175. package/test/type-safety.test.ts +834 -0
  176. package/test/types.test.ts +95 -2
  177. package/test/video.test.ts +530 -0
  178. package/test/worker.test.ts +1433 -0
  179. package/tsconfig.json +4 -1
  180. package/vitest.config.ts +42 -0
  181. package/wrangler.jsonc +36 -0
  182. package/.turbo/turbo-build.log +0 -5
  183. package/src/actions.js +0 -436
  184. package/src/approve.js +0 -234
  185. package/src/ask.js +0 -226
  186. package/src/decide.js +0 -244
  187. package/src/do.js +0 -227
  188. package/src/generate.js +0 -298
  189. package/src/goals.js +0 -205
  190. package/src/index.js +0 -68
  191. package/src/is.js +0 -317
  192. package/src/kpis.js +0 -270
  193. package/src/notify.js +0 -219
  194. package/src/role.js +0 -110
  195. package/src/team.js +0 -130
  196. package/src/transports.js +0 -357
  197. package/src/types.js +0 -71
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # digital-workers
2
2
 
3
+ ## 2.3.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [9e2779a]
8
+ - ai-functions@2.3.0
9
+ - ai-workflows@2.3.0
10
+
11
+ ## 2.1.3
12
+
13
+ ### Patch Changes
14
+
15
+ - Documentation and testing improvements
16
+
17
+ - Add deterministic AI testing suite with self-validating patterns
18
+ - Apply StoryBrand narrative to all package READMEs
19
+ - Update TESTING.md with four principles of deterministic AI testing
20
+ - Fix duplicate examples package name conflict
21
+
22
+ - Updated dependencies
23
+ - ai-functions@2.1.3
24
+ - ai-workflows@2.1.3
25
+
3
26
  ## 2.1.1
4
27
 
5
28
  ### Patch Changes
package/README.md CHANGED
@@ -1,73 +1,50 @@
1
1
  # digital-workers
2
2
 
3
- Abstract interface for organizing digital work, independent of whether AI or humans perform individual tasks.
3
+ ![Stability: Beta](https://img.shields.io/badge/stability-beta-yellow)
4
4
 
5
- ## Overview
5
+ **You're building AI-powered workflows. But who should actually do the work?**
6
6
 
7
- **Digital workers** provides the foundational abstraction for structuring and organizing work in the digital enterprise. It defines a unified interface that both AI agents and humans implement, enabling you to design workflows without coupling them to specific execution strategies.
7
+ Sometimes it's an AI agent operating autonomously. Sometimes it requires human judgment. Often it's both working together. And as AI capabilities evolve, you need workflows that can adapt without rewriting everything.
8
8
 
9
- ### Why This Abstraction Matters
9
+ `digital-workers` gives you a single interface that works whether the worker is human or AI - so you can design once and swap implementations as your needs change.
10
10
 
11
- When building AI-powered systems, you face a fundamental question: *who should do this task?* Sometimes it's an AI agent operating autonomously. Sometimes it requires human judgment. Often it's a mix of both.
11
+ ## The Problem
12
12
 
13
- `digital-workers` lets you define work in terms of **what** needs to happen, not **who** does it:
13
+ ```typescript
14
+ // Without digital-workers: You're locked into implementation details
15
+ if (task.requiresHumanJudgment) {
16
+ await sendSlackToAlice(task.description)
17
+ const approval = await waitForSlackResponse()
18
+ // Different code path for humans...
19
+ } else {
20
+ await callAIAgent(task.description)
21
+ // Completely different code path for AI...
22
+ }
23
+ ```
24
+
25
+ Your workflow logic becomes tangled with *who* does the work instead of *what* needs to happen.
26
+
27
+ ## The Solution
14
28
 
15
29
  ```typescript
16
- // This workflow doesn't care if alice is an AI agent or a human
30
+ // With digital-workers: Define what, not who
17
31
  await worker$.approve('Deploy v2.0 to production', alice, { via: 'slack' })
18
32
  ```
19
33
 
20
- The same Worker interface works whether `alice` is:
34
+ The same code works whether `alice` is:
21
35
  - A human product manager who gets a Slack notification
22
36
  - An AI agent that evaluates deployment criteria autonomously
23
37
  - A supervised AI that escalates to humans for high-risk decisions
24
38
 
25
- ### Package Relationships
39
+ ## Quick Start
26
40
 
27
- ```
28
- ┌─────────────────────────────────────────────────────────┐
29
- │ ai-workflows │
30
- │ (orchestrates work execution) │
31
- └────────────────────────┬────────────────────────────────┘
32
-
33
-
34
- ┌─────────────────────────────────────────────────────────┐
35
- │ digital-workers │
36
- │ (abstract interface for work & workers) │
37
- └────────────────────────┬────────────────────────────────┘
38
-
39
- ┌─────────────┴─────────────┐
40
- ▼ ▼
41
- ┌─────────────────────┐ ┌─────────────────────────────┐
42
- │ autonomous-agents │ │ human-in-the-loop │
43
- │ (AI implementation)│ │ (human implementation) │
44
- └─────────────────────┘ └─────────────────────────────┘
45
- ```
46
-
47
- - **digital-workers**: Defines the abstract `Worker` interface, action types, and communication patterns
48
- - **autonomous-agents**: Implements `Worker` for AI agents with autonomous decision-making
49
- - **human-in-the-loop**: Implements `Worker` for humans with approval workflows and notifications
50
-
51
- ## Installation
41
+ ### 1. Install
52
42
 
53
43
  ```bash
54
44
  pnpm add digital-workers
55
45
  ```
56
46
 
57
- ## Core Concepts
58
-
59
- ### The Worker Abstraction
60
-
61
- A **Worker** is the unified interface for any entity that can perform work—whether AI or human. This abstraction enables you to:
62
-
63
- 1. **Design workflows once** - Define your business logic without hardcoding execution strategy
64
- 2. **Swap implementations** - Start with humans, transition to AI agents as they prove reliable
65
- 3. **Mix freely** - Teams can include both AI agents and humans working together
66
- 4. **Route dynamically** - Assign tasks based on availability, capability, or risk level
67
-
68
- ### Worker
69
-
70
- A **Worker** is the common interface for both AI agents and humans:
47
+ ### 2. Define Your Workers
71
48
 
72
49
  ```typescript
73
50
  import type { Worker } from 'digital-workers'
@@ -80,7 +57,6 @@ const alice: Worker = {
80
57
  contacts: {
81
58
  email: 'alice@company.com',
82
59
  slack: { workspace: 'acme', user: 'U123' },
83
- phone: '+1-555-1234',
84
60
  },
85
61
  }
86
62
 
@@ -90,57 +66,12 @@ const codeReviewer: Worker = {
90
66
  type: 'agent',
91
67
  status: 'available',
92
68
  contacts: {
93
- api: { endpoint: 'https://api.internal/reviewer', auth: 'bearer' },
94
- webhook: { url: 'https://hooks.internal/reviewer' },
69
+ api: { endpoint: 'https://api.internal/reviewer' },
95
70
  },
96
71
  }
97
72
  ```
98
73
 
99
- ### Contacts
100
-
101
- Workers have **contacts** that define how they can be reached:
102
-
103
- ```typescript
104
- import type { Contacts } from 'digital-workers'
105
-
106
- const contacts: Contacts = {
107
- email: 'team@company.com', // Simple string
108
- slack: { workspace: 'acme', channel: '#eng' }, // Config object
109
- phone: { number: '+1-555-0000', voice: 'en-US' },
110
- sms: '+1-555-0001',
111
- teams: { tenant: 'company', channel: 'Engineering' },
112
- discord: { server: 'dev-community', channel: 'support' },
113
- telegram: { chat: '@company_support' },
114
- web: { url: 'https://dashboard.company.com', pushEnabled: true },
115
- api: { endpoint: 'https://api.company.com', auth: 'bearer' },
116
- webhook: { url: 'https://hooks.company.com/events' },
117
- }
118
- ```
119
-
120
- ### Team
121
-
122
- **Teams** group workers with shared contacts:
123
-
124
- ```typescript
125
- import { Team } from 'digital-workers'
126
-
127
- const engineering = Team({
128
- id: 'team_eng',
129
- name: 'Engineering',
130
- members: [alice, bob, codeReviewer],
131
- contacts: {
132
- slack: '#engineering',
133
- email: 'eng@company.com',
134
- },
135
- lead: alice,
136
- })
137
- ```
138
-
139
- ## Worker Actions
140
-
141
- Worker actions are durable workflow actions with Actor/Object semantics that integrate with `ai-workflows`:
142
-
143
- ### Using with Workflows (Recommended)
74
+ ### 3. Build Your Workflow
144
75
 
145
76
  ```typescript
146
77
  import { Workflow } from 'ai-workflows'
@@ -151,7 +82,7 @@ const workflow = Workflow($ => {
151
82
  const worker$ = withWorkers($)
152
83
 
153
84
  $.on.Expense.submitted(async (expense) => {
154
- // Notify finance team
85
+ // Notify the finance team
155
86
  await worker$.notify(finance, `New expense: ${expense.amount}`)
156
87
 
157
88
  // Request approval from manager
@@ -168,58 +99,35 @@ const workflow = Workflow($ => {
168
99
  })
169
100
  ```
170
101
 
171
- ### Direct Workflow Integration
102
+ ## What You Can Do
172
103
 
173
- ```typescript
174
- // Using $.do for durable actions
175
- await $.do('Worker.notify', {
176
- actor: 'system',
177
- object: alice,
178
- action: 'notify',
179
- message: 'Deployment complete',
180
- via: 'slack',
181
- })
182
-
183
- // Using $.send for fire-and-forget
184
- await $.send('Worker.notified', { ... })
185
- ```
186
-
187
- ### Action Types
188
-
189
- #### notify - Send notifications
104
+ ### Notify - Send Messages
190
105
 
191
106
  ```typescript
192
- await worker$.notify(target, 'Message content', {
193
- via: 'slack', // Channel to use
194
- priority: 'urgent', // 'low' | 'normal' | 'high' | 'urgent'
107
+ await worker$.notify(target, 'Deployment complete', {
108
+ via: 'slack',
109
+ priority: 'urgent',
195
110
  })
196
111
  ```
197
112
 
198
- #### ask - Request information
113
+ ### Ask - Request Information
199
114
 
200
115
  ```typescript
201
- const result = await worker$.ask<Priority>(
116
+ const result = await worker$.ask<{ priority: string }>(
202
117
  target,
203
118
  'What priority should this be?',
204
- {
205
- via: 'slack',
206
- schema: { priority: 'low | normal | high' },
207
- }
119
+ { schema: { priority: 'low | normal | high' } }
208
120
  )
209
- console.log(result.answer) // { priority: 'high' }
121
+ console.log(result.answer.priority) // 'high'
210
122
  ```
211
123
 
212
- #### approve - Request approval
124
+ ### Approve - Get Sign-off
213
125
 
214
126
  ```typescript
215
127
  const result = await worker$.approve(
216
128
  'Deploy v2.0 to production',
217
129
  manager,
218
- {
219
- via: 'slack',
220
- context: { version: '2.0', environment: 'production' },
221
- timeout: 3600000, // 1 hour
222
- }
130
+ { via: 'slack', timeout: 3600000 }
223
131
  )
224
132
 
225
133
  if (result.approved) {
@@ -227,12 +135,12 @@ if (result.approved) {
227
135
  }
228
136
  ```
229
137
 
230
- #### decide - AI-powered decisions
138
+ ### Decide - Make Choices
231
139
 
232
140
  ```typescript
233
141
  const result = await worker$.decide({
234
142
  options: ['React', 'Vue', 'Svelte'],
235
- context: 'Choosing a frontend framework for our new project',
143
+ context: 'Choosing a frontend framework',
236
144
  criteria: ['DX', 'Performance', 'Ecosystem'],
237
145
  })
238
146
 
@@ -241,9 +149,31 @@ console.log(result.reasoning) // 'React offers the best ecosystem...'
241
149
  console.log(result.confidence) // 0.85
242
150
  ```
243
151
 
244
- ## Standalone Functions
152
+ ## Teams
245
153
 
246
- For use outside workflows:
154
+ Group workers with shared contacts:
155
+
156
+ ```typescript
157
+ import { Team } from 'digital-workers'
158
+
159
+ const engineering = Team({
160
+ id: 'team_eng',
161
+ name: 'Engineering',
162
+ members: [alice, bob, codeReviewer],
163
+ contacts: {
164
+ slack: '#engineering',
165
+ email: 'eng@company.com',
166
+ },
167
+ lead: alice,
168
+ })
169
+
170
+ // Notify the whole team
171
+ await worker$.notify(engineering, 'Sprint planning in 10 minutes')
172
+ ```
173
+
174
+ ## Standalone Usage
175
+
176
+ Use outside of workflows:
247
177
 
248
178
  ```typescript
249
179
  import { notify, ask, approve, decide } from 'digital-workers'
@@ -251,87 +181,113 @@ import { notify, ask, approve, decide } from 'digital-workers'
251
181
  // Simple notification
252
182
  await notify(alice, 'Task completed', { via: 'slack' })
253
183
 
254
- // Ask with variants
184
+ // Ask variants
255
185
  await ask(alice, 'What is the status?')
256
186
  await ask.ai('What is our refund policy?', { policies: [...] })
257
187
  await ask.yesNo(manager, 'Should we proceed?')
258
188
 
259
189
  // Approval variants
260
190
  await approve('Deploy to production', manager)
261
- await approve.all('Major change', [cto, vpe, securityLead])
262
- await approve.any('Urgent fix', oncallTeam)
191
+ await approve.all('Major change', [cto, vpe, securityLead]) // All must approve
192
+ await approve.any('Urgent fix', oncallTeam) // Any one can approve
263
193
 
264
- // Decision making
194
+ // Decision variants
265
195
  await decide({ options: ['A', 'B', 'C'], criteria: ['cost', 'time'] })
266
196
  await decide.yesNo('Should we proceed?', context)
267
197
  await decide.prioritize(['Task 1', 'Task 2', 'Task 3'])
268
198
  ```
269
199
 
270
- ## Additional Utilities
200
+ ## How It Fits Together
201
+
202
+ ```
203
+ ┌─────────────────────────────────────────────────────────┐
204
+ │ ai-workflows │
205
+ │ (orchestrates work execution) │
206
+ └────────────────────────┬────────────────────────────────┘
207
+
208
+
209
+ ┌─────────────────────────────────────────────────────────┐
210
+ │ digital-workers │
211
+ │ (abstract interface for work & workers) │
212
+ └────────────────────────┬────────────────────────────────┘
213
+
214
+ ┌─────────────┴─────────────┐
215
+ ▼ ▼
216
+ ┌─────────────────────┐ ┌─────────────────────────────┐
217
+ │ autonomous-agents │ │ human-in-the-loop │
218
+ │ (AI implementation)│ │ (human implementation) │
219
+ └─────────────────────┘ └─────────────────────────────┘
220
+ ```
221
+
222
+ - **digital-workers**: The abstract `Worker` interface, action types, and communication patterns
223
+ - **autonomous-agents**: Implements `Worker` for AI agents with autonomous decision-making
224
+ - **human-in-the-loop**: Implements `Worker` for humans with approval workflows and notifications
225
+ - **ai-workflows**: Orchestrates work execution with durable, event-driven workflows
226
+
227
+ ## Advanced Features
228
+
229
+ ### Capability Tiers
271
230
 
272
- ### Role Definition
231
+ Route work based on agent capabilities:
273
232
 
274
233
  ```typescript
275
- import { Role } from 'digital-workers'
234
+ import { matchTierToComplexity, canExecuteAtTier } from 'digital-workers'
276
235
 
277
- const engineer = Role({
278
- name: 'Software Engineer',
279
- description: 'Builds and maintains software',
280
- responsibilities: ['Write code', 'Review PRs', 'Fix bugs'],
281
- skills: ['TypeScript', 'React', 'Node.js'],
282
- })
236
+ const tier = matchTierToComplexity({ reasoning: 'high', toolUse: true })
237
+ // Returns: { tier: 'agentic', confidence: 0.9 }
283
238
  ```
284
239
 
285
- ### Goals & KPIs
240
+ ### Load Balancing
241
+
242
+ Distribute work across available workers:
286
243
 
287
244
  ```typescript
288
- import { Goals, kpis, okrs } from 'digital-workers'
289
-
290
- const teamGoals = Goals({
291
- shortTerm: ['Ship v2.0', 'Reduce tech debt'],
292
- longTerm: ['100% test coverage'],
293
- metrics: [
294
- { name: 'Velocity', current: 42, target: 50, unit: 'points' },
295
- ],
296
- })
245
+ import { createLeastBusyBalancer, createCapabilityRouter } from 'digital-workers'
246
+
247
+ const balancer = createLeastBusyBalancer(workers)
248
+ const router = createCapabilityRouter(agents)
297
249
  ```
298
250
 
299
- ### Content Generation
251
+ ### Error Escalation
252
+
253
+ Automatic escalation when things go wrong:
300
254
 
301
255
  ```typescript
302
- import { generate } from 'digital-workers'
256
+ import { createEscalationEngine, createEscalationPolicy } from 'digital-workers'
303
257
 
304
- const result = await generate('Write a product description', {
305
- type: 'text',
306
- instructions: 'Keep it under 100 words',
258
+ const policy = createEscalationPolicy({
259
+ maxRetries: 3,
260
+ escalationPath: ['junior-agent', 'senior-agent', 'human'],
307
261
  })
262
+
263
+ const engine = createEscalationEngine(policy)
308
264
  ```
309
265
 
310
- ### Type Validation
266
+ ### Agent Communication
267
+
268
+ Direct agent-to-agent messaging:
311
269
 
312
270
  ```typescript
313
- import { is } from 'digital-workers'
271
+ import { sendToAgent, requestFromAgent, initiateHandoff } from 'digital-workers'
314
272
 
315
- const result = await is('hello@example.com', 'email')
316
- console.log(result.valid) // true
273
+ await sendToAgent(targetAgent, { type: 'task', payload: data })
274
+ const response = await requestFromAgent(agent, query, { timeout: 5000 })
275
+ await initiateHandoff(fromAgent, toAgent, context)
317
276
  ```
318
277
 
319
278
  ## Type Reference
320
279
 
321
- Key types exported:
280
+ Key exports:
322
281
 
323
- - `Worker` - Worker interface
324
- - `Team` - Team interface
325
- - `WorkerRef` - Lightweight worker reference
326
- - `Contacts` - Contact configuration
327
- - `ContactChannel` - Channel names
328
- - `WorkerAction` - Action types
329
- - `NotifyResult`, `AskResult`, `ApprovalResult`, `DecideResult`, `DoResult`
330
- - `WorkerContext` - Context extension for workflows
282
+ - `Worker`, `Team`, `WorkerRef` - Core interfaces
283
+ - `Contacts`, `ContactChannel` - Communication configuration
284
+ - `NotifyResult`, `AskResult`, `ApprovalResult`, `DecideResult`, `DoResult` - Action results
285
+ - `CapabilityTier`, `CapabilityProfile` - Agent capability levels
286
+ - `LoadBalancer`, `EscalationEngine` - Advanced orchestration
331
287
 
332
288
  ## Related Packages
333
289
 
334
- - `autonomous-agents` - **Implements** `Worker` for AI agents with autonomous decision-making, goals, and metrics
335
- - `human-in-the-loop` - **Implements** `Worker` for humans with approval workflows, notifications, and escalation
336
- - `ai-workflows` - **Uses** `digital-workers` to orchestrate work execution with durable, event-driven workflows
337
- - `services-as-software` - External service integration (crosses company boundaries, unlike workers)
290
+ - **autonomous-agents** - Implements `Worker` for AI agents with goals, metrics, and autonomous decision-making
291
+ - **human-in-the-loop** - Implements `Worker` for humans with approval workflows, notifications, and escalation
292
+ - **ai-workflows** - Uses `digital-workers` to orchestrate work execution with durable, event-driven workflows
293
+ - **services-as-software** - External service integration (crosses company boundaries, unlike workers)
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,KAAK,EAIV,YAAY,EAGZ,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,UAAU,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACd,MAAM,YAAY,CAAA;AAMnB;;GAEG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,gBAAgB,EACtB,CAAC,EAAE,eAAe,GACjB,OAAO,CAAC,YAAY,CAAC,CAkDvB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,CAAC,GAAG,MAAM,EACxC,IAAI,EAAE,aAAa,EACnB,CAAC,EAAE,eAAe,GACjB,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CA4BvB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,iBAAiB,EACvB,CAAC,EAAE,eAAe,GACjB,OAAO,CAAC,cAAc,CAAC,CAiCzB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,CAAC,GAAG,MAAM,EAC3C,IAAI,EAAE,gBAAgB,EACtB,CAAC,EAAE,eAAe,GACjB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAU1B;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EACxC,IAAI,EAAE,YAAY,EAClB,CAAC,EAAE,eAAe,GACjB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAyDtB;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,eAAe,GAAG,IAAI,CAY9D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,eAAe,GAAG,eAAe,GAAG,aAAa,CAgE/E;AAMD;;GAEG;AACH,wBAAsB,MAAM,CAC1B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CA2BvB;AAED;;GAEG;AACH,wBAAsB,GAAG,CAAC,CAAC,GAAG,MAAM,EAClC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAgBvB;AAED;;GAEG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,cAAc,CAAC,CAiBzB;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,CAAC,GAAG,MAAM,EACrC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GACxB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAE1B"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAEnD,OAAO,KAAK,EAIV,YAAY,EAGZ,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,UAAU,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACd,MAAM,YAAY,CAAA;AAMnB;;GAEG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,gBAAgB,EACtB,CAAC,EAAE,eAAe,GACjB,OAAO,CAAC,YAAY,CAAC,CAkDvB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,CAAC,GAAG,MAAM,EACxC,IAAI,EAAE,aAAa,EACnB,CAAC,EAAE,eAAe,GACjB,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CA+BvB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,iBAAiB,EACvB,CAAC,EAAE,eAAe,GACjB,OAAO,CAAC,cAAc,CAAC,CAiCzB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,CAAC,GAAG,MAAM,EAC3C,IAAI,EAAE,gBAAgB,EACtB,CAAC,EAAE,eAAe,GACjB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAU1B;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EACxC,IAAI,EAAE,YAAY,EAClB,CAAC,EAAE,eAAe,GACjB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CA2DtB;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,eAAe,GAAG,IAAI,CAY9D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,eAAe,GAAG,eAAe,GAAG,aAAa,CAoE/E;AAMD;;GAEG;AACH,wBAAsB,MAAM,CAC1B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CA6BvB;AAED;;GAEG;AACH,wBAAsB,GAAG,CAAC,CAAC,GAAG,MAAM,EAClC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAgBvB;AAED;;GAEG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,cAAc,CAAC,CAiBzB;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAE5F"}
package/dist/actions.js CHANGED
@@ -10,6 +10,7 @@
10
10
  *
11
11
  * @packageDocumentation
12
12
  */
13
+ import { generateRequestId } from './utils/id.js';
13
14
  // ============================================================================
14
15
  // Action Handlers
15
16
  // ============================================================================
@@ -73,10 +74,13 @@ export async function handleAsk(data, $) {
73
74
  throw new Error('No valid channel available for ask action');
74
75
  }
75
76
  // Send question and wait for response
76
- const answer = await sendQuestion(channel, question, contacts, { schema, timeout });
77
+ const answer = await sendQuestion(channel, question, contacts, {
78
+ ...(schema !== undefined && { schema }),
79
+ ...(timeout !== undefined && { timeout }),
80
+ });
77
81
  const result = {
78
82
  answer,
79
- answeredBy: recipient,
83
+ ...(recipient !== undefined && { answeredBy: recipient }),
80
84
  answeredAt: new Date(),
81
85
  via: channel,
82
86
  };
@@ -99,15 +103,15 @@ export async function handleApprove(data, $) {
99
103
  }
100
104
  // Send approval request and wait for response
101
105
  const response = await sendApprovalRequest(channel, request, contacts, {
102
- context,
103
- timeout,
104
- escalate,
106
+ ...(context !== undefined && { context }),
107
+ ...(timeout !== undefined && { timeout }),
108
+ ...(escalate !== undefined && { escalate }),
105
109
  });
106
110
  const result = {
107
111
  approved: response.approved,
108
- approvedBy: approver,
112
+ ...(approver !== undefined && { approvedBy: approver }),
109
113
  approvedAt: new Date(),
110
- notes: response.notes,
114
+ ...(response.notes !== undefined && { notes: response.notes }),
111
115
  via: channel,
112
116
  };
113
117
  // Emit result event
@@ -143,7 +147,9 @@ export async function handleDo(data, $) {
143
147
  timestamp: new Date(),
144
148
  });
145
149
  // Execute the task (this would integrate with agent execution)
146
- result = await executeTask(target, instruction, { timeout });
150
+ result = await executeTask(target, instruction, {
151
+ ...(timeout !== undefined && { timeout }),
152
+ });
147
153
  steps.push({
148
154
  action: 'complete',
149
155
  result,
@@ -171,7 +177,7 @@ export async function handleDo(data, $) {
171
177
  const failResult = {
172
178
  result: undefined,
173
179
  success: false,
174
- error: lastError?.message,
180
+ ...(lastError !== undefined && { error: lastError.message }),
175
181
  duration: Date.now() - startTime,
176
182
  steps,
177
183
  };
@@ -207,12 +213,12 @@ export function registerWorkerActions($) {
207
213
  // Register action handlers using the proxy pattern
208
214
  // The $ context provides event registration via $.on[Namespace][event]
209
215
  const on = $.on;
210
- if (on.Worker) {
211
- on.Worker.notify?.(handleNotify);
212
- on.Worker.ask?.(handleAsk);
213
- on.Worker.approve?.(handleApprove);
214
- on.Worker.decide?.(handleDecide);
215
- on.Worker.do?.(handleDo);
216
+ if (on['Worker']) {
217
+ on['Worker']['notify']?.(handleNotify);
218
+ on['Worker']['ask']?.(handleAsk);
219
+ on['Worker']['approve']?.(handleApprove);
220
+ on['Worker']['decide']?.(handleDecide);
221
+ on['Worker']['do']?.(handleDo);
216
222
  }
217
223
  }
218
224
  /**
@@ -238,6 +244,7 @@ export function registerWorkerActions($) {
238
244
  export function withWorkers($) {
239
245
  const workerContext = {
240
246
  async notify(target, message, options = {}) {
247
+ // Workflow handler returns NotifyResult; $.do passes through the result
241
248
  return $.do('Worker.notify', {
242
249
  actor: 'system',
243
250
  object: target,
@@ -260,7 +267,11 @@ export function withWorkers($) {
260
267
  const actor = typeof target === 'string'
261
268
  ? target
262
269
  : 'id' in target
263
- ? { id: target.id, type: 'type' in target ? target.type : undefined, name: 'name' in target ? target.name : undefined }
270
+ ? {
271
+ id: target.id,
272
+ ...('type' in target && target.type !== undefined && { type: target.type }),
273
+ ...('name' in target && target.name !== undefined && { name: target.name }),
274
+ }
264
275
  : 'system';
265
276
  return $.do('Worker.approve', {
266
277
  actor,
@@ -295,7 +306,9 @@ export async function notify(target, message, options = {}) {
295
306
  }
296
307
  const delivery = await Promise.all(channels.map(async (channel) => {
297
308
  try {
298
- await sendToChannel(channel, message, contacts, { priority: options.priority });
309
+ await sendToChannel(channel, message, contacts, {
310
+ ...(options.priority !== undefined && { priority: options.priority }),
311
+ });
299
312
  return { channel, status: 'sent' };
300
313
  }
301
314
  catch (error) {
@@ -323,7 +336,7 @@ export async function ask(target, question, options = {}) {
323
336
  const answer = await sendQuestion(channel, question, contacts, options);
324
337
  return {
325
338
  answer,
326
- answeredBy: recipients[0],
339
+ ...(recipients[0] !== undefined && { answeredBy: recipients[0] }),
327
340
  answeredAt: new Date(),
328
341
  via: channel,
329
342
  };
@@ -340,9 +353,9 @@ export async function approve(request, target, options = {}) {
340
353
  const response = await sendApprovalRequest(channel, request, contacts, options);
341
354
  return {
342
355
  approved: response.approved,
343
- approvedBy: recipients[0],
356
+ ...(recipients[0] !== undefined && { approvedBy: recipients[0] }),
344
357
  approvedAt: new Date(),
345
- notes: response.notes,
358
+ ...(response.notes !== undefined && { notes: response.notes }),
346
359
  via: channel,
347
360
  };
348
361
  }
@@ -432,6 +445,6 @@ async function executeTask(target, instruction, options) {
432
445
  return { completed: true, instruction };
433
446
  }
434
447
  function generateId(prefix) {
435
- return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
448
+ return generateRequestId(prefix);
436
449
  }
437
450
  //# sourceMappingURL=actions.js.map