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.
- package/CHANGELOG.md +23 -0
- package/README.md +136 -180
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +34 -21
- package/dist/actions.js.map +1 -1
- package/dist/agent-comms.d.ts +438 -0
- package/dist/agent-comms.d.ts.map +1 -0
- package/dist/agent-comms.js +677 -0
- package/dist/agent-comms.js.map +1 -0
- package/dist/approve.d.ts +40 -8
- package/dist/approve.d.ts.map +1 -1
- package/dist/approve.js +86 -20
- package/dist/approve.js.map +1 -1
- package/dist/ask.d.ts +38 -7
- package/dist/ask.d.ts.map +1 -1
- package/dist/ask.js +85 -25
- package/dist/ask.js.map +1 -1
- package/dist/browse.d.ts +223 -0
- package/dist/browse.d.ts.map +1 -0
- package/dist/browse.js +392 -0
- package/dist/browse.js.map +1 -0
- package/dist/capability-tiers.d.ts +230 -0
- package/dist/capability-tiers.d.ts.map +1 -0
- package/dist/capability-tiers.js +388 -0
- package/dist/capability-tiers.js.map +1 -0
- package/dist/cascade-context.d.ts +523 -0
- package/dist/cascade-context.d.ts.map +1 -0
- package/dist/cascade-context.js +494 -0
- package/dist/cascade-context.js.map +1 -0
- package/dist/client.d.ts +162 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +64 -0
- package/dist/client.js.map +1 -0
- package/dist/decide.d.ts +42 -6
- package/dist/decide.d.ts.map +1 -1
- package/dist/decide.js +54 -11
- package/dist/decide.js.map +1 -1
- package/dist/do.d.ts +36 -7
- package/dist/do.d.ts.map +1 -1
- package/dist/do.js +82 -39
- package/dist/do.js.map +1 -1
- package/dist/error-escalation.d.ts +416 -0
- package/dist/error-escalation.d.ts.map +1 -0
- package/dist/error-escalation.js +656 -0
- package/dist/error-escalation.js.map +1 -0
- package/dist/generate.d.ts +48 -7
- package/dist/generate.d.ts.map +1 -1
- package/dist/generate.js +49 -8
- package/dist/generate.js.map +1 -1
- package/dist/goals.d.ts +10 -9
- package/dist/goals.d.ts.map +1 -1
- package/dist/goals.js +30 -24
- package/dist/goals.js.map +1 -1
- package/dist/image.d.ts +189 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +528 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +59 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +92 -2
- package/dist/index.js.map +1 -1
- package/dist/is.d.ts +45 -10
- package/dist/is.d.ts.map +1 -1
- package/dist/is.js +56 -21
- package/dist/is.js.map +1 -1
- package/dist/kpis.d.ts +24 -15
- package/dist/kpis.d.ts.map +1 -1
- package/dist/kpis.js +16 -14
- package/dist/kpis.js.map +1 -1
- package/dist/load-balancing.d.ts +395 -0
- package/dist/load-balancing.d.ts.map +1 -0
- package/dist/load-balancing.js +991 -0
- package/dist/load-balancing.js.map +1 -0
- package/dist/logger.d.ts +76 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +39 -0
- package/dist/logger.js.map +1 -0
- package/dist/notify.d.ts +38 -9
- package/dist/notify.d.ts.map +1 -1
- package/dist/notify.js +72 -17
- package/dist/notify.js.map +1 -1
- package/dist/role.d.ts +5 -4
- package/dist/role.d.ts.map +1 -1
- package/dist/role.js +13 -10
- package/dist/role.js.map +1 -1
- package/dist/runtime.d.ts +310 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +510 -0
- package/dist/runtime.js.map +1 -0
- package/dist/team.d.ts +11 -6
- package/dist/team.d.ts.map +1 -1
- package/dist/team.js +22 -15
- package/dist/team.js.map +1 -1
- package/dist/transports/email.d.ts +318 -0
- package/dist/transports/email.d.ts.map +1 -0
- package/dist/transports/email.js +779 -0
- package/dist/transports/email.js.map +1 -0
- package/dist/transports/slack.d.ts +515 -0
- package/dist/transports/slack.d.ts.map +1 -0
- package/dist/transports/slack.js +844 -0
- package/dist/transports/slack.js.map +1 -0
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +44 -25
- package/dist/transports.js.map +1 -1
- package/dist/types.d.ts +149 -19
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/id.d.ts +19 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +21 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/video.d.ts +203 -0
- package/dist/video.d.ts.map +1 -0
- package/dist/video.js +528 -0
- package/dist/video.js.map +1 -0
- package/dist/worker.d.ts +343 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +698 -0
- package/dist/worker.js.map +1 -0
- package/package.json +24 -5
- package/src/actions.ts +48 -38
- package/src/agent-comms.ts +1200 -0
- package/src/approve.ts +91 -20
- package/src/ask.ts +99 -25
- package/src/browse.ts +627 -0
- package/src/capability-tiers.ts +545 -0
- package/src/cascade-context.ts +648 -0
- package/src/client.ts +221 -0
- package/src/decide.ts +81 -35
- package/src/do.ts +98 -52
- package/src/error-escalation.ts +1123 -0
- package/src/generate.ts +52 -18
- package/src/goals.ts +36 -27
- package/src/image.ts +816 -0
- package/src/index.ts +410 -2
- package/src/is.ts +59 -25
- package/src/kpis.ts +41 -36
- package/src/load-balancing.ts +1467 -0
- package/src/logger.ts +93 -0
- package/src/notify.ts +78 -17
- package/src/role.ts +30 -20
- package/src/runtime.ts +796 -0
- package/src/team.ts +24 -19
- package/src/transports/email.ts +1160 -0
- package/src/transports/slack.ts +1320 -0
- package/src/transports.ts +58 -43
- package/src/types.ts +182 -46
- package/src/utils/id.ts +21 -0
- package/src/video.ts +906 -0
- package/src/worker.ts +1007 -0
- package/test/agent-comms.test.ts +1397 -0
- package/test/approve.test.ts +305 -0
- package/test/ask.test.ts +274 -0
- package/test/browse.test.ts +361 -0
- package/test/capability-tiers.test.ts +631 -0
- package/test/cascade-context.test.ts +692 -0
- package/test/decide.test.ts +252 -0
- package/test/do.test.ts +144 -0
- package/test/error-escalation.test.ts +1205 -0
- package/test/error-logging.test.ts +357 -0
- package/test/generate.test.ts +319 -0
- package/test/image.test.ts +398 -0
- package/test/is.test.ts +287 -0
- package/test/load-balancing-safety.test.ts +404 -0
- package/test/load-balancing-thread-safety.test.ts +464 -0
- package/test/load-balancing.test.ts +1145 -0
- package/test/notify.test.ts +434 -0
- package/test/primitives.test.ts +320 -0
- package/test/runtime-integration.test.ts +892 -0
- package/test/transports/crypto.test.ts +230 -0
- package/test/transports/email.test.ts +866 -0
- package/test/transports/id-generation.test.ts +91 -0
- package/test/transports/slack.test.ts +760 -0
- package/test/type-safety.test.ts +834 -0
- package/test/types.test.ts +95 -2
- package/test/video.test.ts +530 -0
- package/test/worker.test.ts +1433 -0
- package/tsconfig.json +4 -1
- package/vitest.config.ts +42 -0
- package/wrangler.jsonc +36 -0
- package/.turbo/turbo-build.log +0 -5
- package/src/actions.js +0 -436
- package/src/approve.js +0 -234
- package/src/ask.js +0 -226
- package/src/decide.js +0 -244
- package/src/do.js +0 -227
- package/src/generate.js +0 -298
- package/src/goals.js +0 -205
- package/src/index.js +0 -68
- package/src/is.js +0 -317
- package/src/kpis.js +0 -270
- package/src/notify.js +0 -219
- package/src/role.js +0 -110
- package/src/team.js +0 -130
- package/src/transports.js +0 -357
- 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
|
-
|
|
3
|
+

|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**You're building AI-powered workflows. But who should actually do the work?**
|
|
6
6
|
|
|
7
|
-
|
|
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
|
-
|
|
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
|
-
|
|
11
|
+
## The Problem
|
|
12
12
|
|
|
13
|
-
|
|
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
|
-
//
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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'
|
|
94
|
-
webhook: { url: 'https://hooks.internal/reviewer' },
|
|
69
|
+
api: { endpoint: 'https://api.internal/reviewer' },
|
|
95
70
|
},
|
|
96
71
|
}
|
|
97
72
|
```
|
|
98
73
|
|
|
99
|
-
###
|
|
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
|
-
|
|
102
|
+
## What You Can Do
|
|
172
103
|
|
|
173
|
-
|
|
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, '
|
|
193
|
-
via: 'slack',
|
|
194
|
-
priority: 'urgent',
|
|
107
|
+
await worker$.notify(target, 'Deployment complete', {
|
|
108
|
+
via: 'slack',
|
|
109
|
+
priority: 'urgent',
|
|
195
110
|
})
|
|
196
111
|
```
|
|
197
112
|
|
|
198
|
-
|
|
113
|
+
### Ask - Request Information
|
|
199
114
|
|
|
200
115
|
```typescript
|
|
201
|
-
const result = await worker$.ask<
|
|
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) //
|
|
121
|
+
console.log(result.answer.priority) // 'high'
|
|
210
122
|
```
|
|
211
123
|
|
|
212
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
##
|
|
152
|
+
## Teams
|
|
245
153
|
|
|
246
|
-
|
|
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
|
|
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
|
|
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
|
-
##
|
|
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
|
-
|
|
231
|
+
Route work based on agent capabilities:
|
|
273
232
|
|
|
274
233
|
```typescript
|
|
275
|
-
import {
|
|
234
|
+
import { matchTierToComplexity, canExecuteAtTier } from 'digital-workers'
|
|
276
235
|
|
|
277
|
-
const
|
|
278
|
-
|
|
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
|
-
###
|
|
240
|
+
### Load Balancing
|
|
241
|
+
|
|
242
|
+
Distribute work across available workers:
|
|
286
243
|
|
|
287
244
|
```typescript
|
|
288
|
-
import {
|
|
289
|
-
|
|
290
|
-
const
|
|
291
|
-
|
|
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
|
-
###
|
|
251
|
+
### Error Escalation
|
|
252
|
+
|
|
253
|
+
Automatic escalation when things go wrong:
|
|
300
254
|
|
|
301
255
|
```typescript
|
|
302
|
-
import {
|
|
256
|
+
import { createEscalationEngine, createEscalationPolicy } from 'digital-workers'
|
|
303
257
|
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
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
|
-
###
|
|
266
|
+
### Agent Communication
|
|
267
|
+
|
|
268
|
+
Direct agent-to-agent messaging:
|
|
311
269
|
|
|
312
270
|
```typescript
|
|
313
|
-
import {
|
|
271
|
+
import { sendToAgent, requestFromAgent, initiateHandoff } from 'digital-workers'
|
|
314
272
|
|
|
315
|
-
|
|
316
|
-
|
|
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
|
|
280
|
+
Key exports:
|
|
322
281
|
|
|
323
|
-
- `Worker` -
|
|
324
|
-
- `
|
|
325
|
-
- `
|
|
326
|
-
- `
|
|
327
|
-
- `
|
|
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
|
-
-
|
|
335
|
-
-
|
|
336
|
-
-
|
|
337
|
-
-
|
|
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)
|
package/dist/actions.d.ts.map
CHANGED
|
@@ -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;
|
|
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, {
|
|
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, {
|
|
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
|
|
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
|
|
211
|
-
on
|
|
212
|
-
on
|
|
213
|
-
on
|
|
214
|
-
on
|
|
215
|
-
on
|
|
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
|
-
? {
|
|
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, {
|
|
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
|
|
448
|
+
return generateRequestId(prefix);
|
|
436
449
|
}
|
|
437
450
|
//# sourceMappingURL=actions.js.map
|