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/src/logger.ts ADDED
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Logger Interface for Digital Workers
3
+ *
4
+ * Provides a simple, extensible logging interface that can be injected
5
+ * into components for error logging and debugging. Consumers can provide
6
+ * their own logger implementation (e.g., winston, pino, console).
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+
11
+ /**
12
+ * Logger interface for structured logging
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * // Using with console
17
+ * const consoleLogger: Logger = {
18
+ * debug: (msg, meta) => console.debug(msg, meta),
19
+ * info: (msg, meta) => console.info(msg, meta),
20
+ * warn: (msg, meta) => console.warn(msg, meta),
21
+ * error: (msg, error, meta) => console.error(msg, error, meta),
22
+ * }
23
+ *
24
+ * // Using with a custom logger
25
+ * const customLogger: Logger = {
26
+ * debug: (msg, meta) => myLogger.debug({ message: msg, ...meta }),
27
+ * info: (msg, meta) => myLogger.info({ message: msg, ...meta }),
28
+ * warn: (msg, meta) => myLogger.warn({ message: msg, ...meta }),
29
+ * error: (msg, error, meta) => myLogger.error({ message: msg, error, ...meta }),
30
+ * }
31
+ * ```
32
+ */
33
+ export interface Logger {
34
+ /**
35
+ * Log debug-level messages
36
+ * @param msg - The log message
37
+ * @param meta - Optional metadata object
38
+ */
39
+ debug(msg: string, meta?: object): void
40
+
41
+ /**
42
+ * Log info-level messages
43
+ * @param msg - The log message
44
+ * @param meta - Optional metadata object
45
+ */
46
+ info(msg: string, meta?: object): void
47
+
48
+ /**
49
+ * Log warning-level messages
50
+ * @param msg - The log message
51
+ * @param meta - Optional metadata object
52
+ */
53
+ warn(msg: string, meta?: object): void
54
+
55
+ /**
56
+ * Log error-level messages
57
+ * @param msg - The log message
58
+ * @param error - Optional error object with stack trace
59
+ * @param meta - Optional metadata object
60
+ */
61
+ error(msg: string, error?: Error, meta?: object): void
62
+ }
63
+
64
+ /**
65
+ * A no-op logger that discards all log messages.
66
+ * Used as a default when no logger is provided.
67
+ */
68
+ export const noopLogger: Logger = {
69
+ debug: () => {},
70
+ info: () => {},
71
+ warn: () => {},
72
+ error: () => {},
73
+ }
74
+
75
+ /**
76
+ * Creates a console-based logger for debugging purposes.
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * const transport = createSlackTransport({
81
+ * ...config,
82
+ * logger: createConsoleLogger(),
83
+ * })
84
+ * ```
85
+ */
86
+ export function createConsoleLogger(): Logger {
87
+ return {
88
+ debug: (msg, meta) => console.debug(`[DEBUG] ${msg}`, meta ?? ''),
89
+ info: (msg, meta) => console.info(`[INFO] ${msg}`, meta ?? ''),
90
+ warn: (msg, meta) => console.warn(`[WARN] ${msg}`, meta ?? ''),
91
+ error: (msg, error, meta) => console.error(`[ERROR] ${msg}`, error ?? '', meta ?? ''),
92
+ }
93
+ }
package/src/notify.ts CHANGED
@@ -1,7 +1,28 @@
1
1
  /**
2
2
  * Notification functionality for digital workers
3
+ *
4
+ * IMPORTANT: Real Channel Delivery vs LLM Generation
5
+ * ---------------------------------------------------
6
+ * This module sends real notifications via communication channels,
7
+ * NOT LLM-generated notification content.
8
+ *
9
+ * - `digital-workers.notify()` - Sends actual notifications to Workers
10
+ * via real channels (Slack, email, SMS, etc.) with delivery tracking.
11
+ *
12
+ * - ai-functions does not have an equivalent `notify` primitive since
13
+ * it focuses on LLM operations, not communication channel delivery.
14
+ *
15
+ * Use digital-workers.notify() when you need:
16
+ * - Real notification delivery to people/agents
17
+ * - Multi-channel delivery (Slack + SMS for urgent)
18
+ * - Delivery tracking and confirmation
19
+ * - Priority-based channel selection
20
+ * - Scheduled notifications
21
+ *
22
+ * @module
3
23
  */
4
24
 
25
+ import { generateRequestId } from './utils/id.js'
5
26
  import type {
6
27
  Worker,
7
28
  Team,
@@ -14,30 +35,39 @@ import type {
14
35
  } from './types.js'
15
36
 
16
37
  /**
17
- * Send a notification to a worker or team
38
+ * Send a notification to a Worker (Human or AI Agent) via communication channels.
39
+ *
40
+ * **Unique to digital-workers:**
41
+ * This function sends real notifications via actual communication channels
42
+ * (Slack, email, SMS, phone, etc.). There is no equivalent in ai-functions
43
+ * since ai-functions focuses on LLM operations rather than external delivery.
18
44
  *
19
- * Routes notifications through the specified channel(s), falling back
20
- * to the target's preferred channel if not specified.
45
+ * This is a **communication delivery primitive** for worker coordination.
21
46
  *
22
- * @param target - The worker or team to notify
47
+ * @param target - The worker or team to notify (routes to their configured channels)
23
48
  * @param message - The notification message
24
- * @param options - Notification options
25
- * @returns Promise resolving to notification result
49
+ * @param options - Notification options (channel, priority, metadata)
50
+ * @returns Promise resolving to NotifyResult with delivery status and metadata
26
51
  *
27
52
  * @example
28
53
  * ```ts
29
54
  * // Notify a worker via their preferred channel
30
- * await notify(alice, 'Deployment completed successfully')
55
+ * const result = await notify(alice, 'Deployment completed successfully')
56
+ * console.log(result.sent) // true
57
+ * console.log(result.via) // ['slack']
31
58
  *
32
59
  * // Notify via specific channel
33
60
  * await notify(alice, 'Urgent: Server down!', { via: 'slack' })
34
61
  *
35
- * // Notify via multiple channels
62
+ * // Notify via multiple channels (for urgent messages)
36
63
  * await notify(alice, 'Critical alert', { via: ['slack', 'sms'] })
37
64
  *
38
- * // Notify a team
65
+ * // Notify a team (reaches all members via their channels)
39
66
  * await notify(engineering, 'Sprint planning tomorrow', { via: 'slack' })
40
67
  * ```
68
+ *
69
+ * @see {@link notify.alert} for high-priority urgent notifications
70
+ * @see {@link notify.schedule} for delayed/scheduled notifications
41
71
  */
42
72
  export async function notify(
43
73
  target: ActionTarget,
@@ -66,7 +96,10 @@ export async function notify(
66
96
  const delivery = await Promise.all(
67
97
  channels.map(async (channel) => {
68
98
  try {
69
- await sendToChannel(channel, message, contacts, { priority, metadata })
99
+ await sendToChannel(channel, message, contacts, {
100
+ priority,
101
+ ...(metadata !== undefined && { metadata }),
102
+ })
70
103
  return { channel, status: 'sent' as const }
71
104
  } catch (error) {
72
105
  return {
@@ -286,18 +319,46 @@ async function sendToChannel(
286
319
  throw new Error(`No ${channel} contact configured`)
287
320
  }
288
321
 
289
- // In a real implementation, this would:
290
- // 1. Format the message for the channel
291
- // 2. Send via the appropriate API (Slack, SendGrid, Twilio, etc.)
292
- // 3. Handle delivery confirmation
322
+ // Import transport functions dynamically to avoid circular dependencies
323
+ const { channelToTransport, sendViaTransport, hasTransport, resolveAddress } = await import(
324
+ './transports.js'
325
+ )
326
+
327
+ const transport = channelToTransport(channel)
328
+ const address = resolveAddress(contacts, channel)
329
+
330
+ // If transport is registered, use it for real delivery
331
+ if (hasTransport(transport) && address) {
332
+ const payload = {
333
+ to: address.value,
334
+ body: message,
335
+ type: 'notification' as const,
336
+ priority: (options.priority || 'normal') as 'low' | 'normal' | 'high' | 'urgent',
337
+ ...(options.metadata !== undefined && { metadata: options.metadata }),
338
+ }
339
+
340
+ const result = await sendViaTransport(transport, payload)
341
+
342
+ if (!result.success) {
343
+ throw new Error(`Failed to send notification via ${transport}: ${result.error}`)
344
+ }
345
+ return
346
+ }
293
347
 
294
- // For now, simulate success
295
- await new Promise((resolve) => setTimeout(resolve, 10))
348
+ // No transport registered - log to console for development/testing
349
+ // This provides visibility into what would be sent
350
+ console.log(`[digital-workers] Notification (${channel}):`, {
351
+ to: typeof contact === 'string' ? contact : JSON.stringify(contact),
352
+ message,
353
+ priority: options.priority || 'normal',
354
+ metadata: options.metadata,
355
+ note: `No transport registered for '${transport}'. Register a transport handler to enable real delivery.`,
356
+ })
296
357
  }
297
358
 
298
359
  /**
299
360
  * Generate a unique message ID
300
361
  */
301
362
  function generateMessageId(prefix = 'msg'): string {
302
- return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
363
+ return generateRequestId(prefix)
303
364
  }
package/src/role.ts CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  import type { WorkerRole } from './types.js'
6
6
 
7
+ // Note: Role type is re-exported from types.ts which imports from org.ai
8
+
7
9
  /**
8
10
  * Define a worker role
9
11
  *
@@ -15,7 +17,7 @@ import type { WorkerRole } from './types.js'
15
17
  *
16
18
  * @example
17
19
  * ```ts
18
- * const engineer = Role({
20
+ * const engineer = defineRole({
19
21
  * name: 'Software Engineer',
20
22
  * description: 'Builds and maintains software systems',
21
23
  * responsibilities: [
@@ -31,7 +33,7 @@ import type { WorkerRole } from './types.js'
31
33
  *
32
34
  * @example
33
35
  * ```ts
34
- * const supportAgent = Role({
36
+ * const supportAgent = defineRole({
35
37
  * name: 'Customer Support Agent',
36
38
  * description: 'Assists customers with inquiries and issues',
37
39
  * responsibilities: [
@@ -44,11 +46,13 @@ import type { WorkerRole } from './types.js'
44
46
  * })
45
47
  * ```
46
48
  */
47
- export function Role(definition: Omit<WorkerRole, 'type'> & { type?: WorkerRole['type'] }): WorkerRole {
49
+ export function defineRole(
50
+ definition: Omit<WorkerRole, 'type'> & { type?: WorkerRole['type'] }
51
+ ): WorkerRole {
48
52
  return {
49
- type: 'hybrid', // Default to hybrid (can be AI or human)
50
53
  ...definition,
51
- }
54
+ type: definition.type ?? 'hybrid',
55
+ } as WorkerRole
52
56
  }
53
57
 
54
58
  /**
@@ -56,7 +60,7 @@ export function Role(definition: Omit<WorkerRole, 'type'> & { type?: WorkerRole[
56
60
  *
57
61
  * @example
58
62
  * ```ts
59
- * const dataAnalyst = Role.ai({
63
+ * const dataAnalyst = defineRole.ai({
60
64
  * name: 'Data Analyst',
61
65
  * description: 'Analyzes data and generates insights',
62
66
  * responsibilities: [
@@ -67,17 +71,18 @@ export function Role(definition: Omit<WorkerRole, 'type'> & { type?: WorkerRole[
67
71
  * })
68
72
  * ```
69
73
  */
70
- Role.ai = (definition: Omit<WorkerRole, 'type'>): WorkerRole => ({
71
- ...definition,
72
- type: 'ai',
73
- })
74
+ defineRole.ai = (definition: Omit<WorkerRole, 'type'>): WorkerRole =>
75
+ ({
76
+ ...definition,
77
+ type: 'ai',
78
+ } as WorkerRole)
74
79
 
75
80
  /**
76
81
  * Create a human-specific role
77
82
  *
78
83
  * @example
79
84
  * ```ts
80
- * const manager = Role.human({
85
+ * const manager = defineRole.human({
81
86
  * name: 'Engineering Manager',
82
87
  * description: 'Leads engineering team and makes strategic decisions',
83
88
  * responsibilities: [
@@ -89,17 +94,18 @@ Role.ai = (definition: Omit<WorkerRole, 'type'>): WorkerRole => ({
89
94
  * })
90
95
  * ```
91
96
  */
92
- Role.human = (definition: Omit<WorkerRole, 'type'>): WorkerRole => ({
93
- ...definition,
94
- type: 'human',
95
- })
97
+ defineRole.human = (definition: Omit<WorkerRole, 'type'>): WorkerRole =>
98
+ ({
99
+ ...definition,
100
+ type: 'human',
101
+ } as WorkerRole)
96
102
 
97
103
  /**
98
104
  * Create a hybrid role (can be AI or human)
99
105
  *
100
106
  * @example
101
107
  * ```ts
102
- * const contentWriter = Role.hybrid({
108
+ * const contentWriter = defineRole.hybrid({
103
109
  * name: 'Content Writer',
104
110
  * description: 'Creates written content for various channels',
105
111
  * responsibilities: [
@@ -110,7 +116,11 @@ Role.human = (definition: Omit<WorkerRole, 'type'>): WorkerRole => ({
110
116
  * })
111
117
  * ```
112
118
  */
113
- Role.hybrid = (definition: Omit<WorkerRole, 'type'>): WorkerRole => ({
114
- ...definition,
115
- type: 'hybrid',
116
- })
119
+ defineRole.hybrid = (definition: Omit<WorkerRole, 'type'>): WorkerRole =>
120
+ ({
121
+ ...definition,
122
+ type: 'hybrid',
123
+ } as WorkerRole)
124
+
125
+ // Legacy alias for backward compatibility
126
+ export { defineRole as Role }