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/transports.ts CHANGED
@@ -29,23 +29,23 @@ import type {
29
29
  * Communication transport - maps contact channels to delivery mechanisms
30
30
  */
31
31
  export type Transport =
32
- | 'email' // Email transport (SendGrid, Resend, etc.)
33
- | 'sms' // SMS transport (Twilio, etc.)
34
- | 'voice' // Voice call transport (Vapi, Twilio, etc.)
35
- | 'slack' // Slack API
36
- | 'teams' // Microsoft Teams API
37
- | 'discord' // Discord API
38
- | 'whatsapp' // WhatsApp Business API
39
- | 'telegram' // Telegram Bot API
40
- | 'web' // Web push/in-app
41
- | 'webhook' // Generic webhook
32
+ | 'email' // Email transport (SendGrid, Resend, etc.)
33
+ | 'sms' // SMS transport (Twilio, etc.)
34
+ | 'voice' // Voice call transport (Vapi, Twilio, etc.)
35
+ | 'slack' // Slack API
36
+ | 'teams' // Microsoft Teams API
37
+ | 'discord' // Discord API
38
+ | 'whatsapp' // WhatsApp Business API
39
+ | 'telegram' // Telegram Bot API
40
+ | 'web' // Web push/in-app
41
+ | 'webhook' // Generic webhook
42
42
 
43
43
  /**
44
44
  * Transport configuration
45
45
  */
46
46
  export interface TransportConfig {
47
47
  transport: Transport
48
- provider?: string // Specific provider (e.g., 'sendgrid', 'resend')
48
+ provider?: string // Specific provider (e.g., 'sendgrid', 'resend')
49
49
  apiKey?: string
50
50
  apiUrl?: string
51
51
  options?: Record<string, unknown>
@@ -73,7 +73,7 @@ export interface MessagePayload {
73
73
 
74
74
  // Interactive (for questions/approvals)
75
75
  actions?: MessageAction[]
76
- schema?: unknown // SimpleSchema from ai-functions
76
+ schema?: unknown // SimpleSchema from ai-functions
77
77
  timeout?: number
78
78
  }
79
79
 
@@ -151,16 +151,16 @@ export function getTeamTransports(team: Team): Transport[] {
151
151
 
152
152
  // Add team-level contacts
153
153
  const contacts = team.contacts
154
- if (contacts.email) transports.add('email')
155
- if (contacts.slack) transports.add('slack')
156
- if (contacts.teams) transports.add('teams')
157
- if (contacts.discord) transports.add('discord')
158
- if (contacts.phone) transports.add('voice')
159
- if (contacts.sms) transports.add('sms')
160
- if (contacts.whatsapp) transports.add('whatsapp')
161
- if (contacts.telegram) transports.add('telegram')
162
- if (contacts.web) transports.add('web')
163
- if (contacts.webhook) transports.add('webhook')
154
+ if (contacts?.['email']) transports.add('email')
155
+ if (contacts?.['slack']) transports.add('slack')
156
+ if (contacts?.['teams']) transports.add('teams')
157
+ if (contacts?.['discord']) transports.add('discord')
158
+ if (contacts?.['phone']) transports.add('voice')
159
+ if (contacts?.['sms']) transports.add('sms')
160
+ if (contacts?.['whatsapp']) transports.add('whatsapp')
161
+ if (contacts?.['telegram']) transports.add('telegram')
162
+ if (contacts?.['web']) transports.add('web')
163
+ if (contacts?.['webhook']) transports.add('webhook')
164
164
 
165
165
  return Array.from(transports)
166
166
  }
@@ -196,7 +196,11 @@ export function resolveAddress(contacts: Contacts, channel: ContactChannel): Add
196
196
  switch (channel) {
197
197
  case 'email':
198
198
  const emailContact = contact as { address: string; name?: string }
199
- return { transport, value: emailContact.address, name: emailContact.name }
199
+ return {
200
+ transport,
201
+ value: emailContact.address,
202
+ ...(emailContact.name !== undefined && { name: emailContact.name }),
203
+ }
200
204
  case 'phone':
201
205
  case 'sms':
202
206
  case 'whatsapp':
@@ -246,8 +250,17 @@ export function resolveAddress(contacts: Contacts, channel: ContactChannel): Add
246
250
  export function resolveWorkerAddresses(worker: Worker): Address[] {
247
251
  const addresses: Address[] = []
248
252
  const channels: ContactChannel[] = [
249
- 'email', 'slack', 'teams', 'discord', 'phone', 'sms',
250
- 'whatsapp', 'telegram', 'web', 'api', 'webhook',
253
+ 'email',
254
+ 'slack',
255
+ 'teams',
256
+ 'discord',
257
+ 'phone',
258
+ 'sms',
259
+ 'whatsapp',
260
+ 'telegram',
261
+ 'web',
262
+ 'api',
263
+ 'webhook',
251
264
  ]
252
265
 
253
266
  for (const channel of channels) {
@@ -365,9 +378,7 @@ export async function sendToMultipleTransports(
365
378
  configs?: Record<Transport, TransportConfig>
366
379
  ): Promise<DeliveryResult[]> {
367
380
  const results = await Promise.all(
368
- transports.map(transport =>
369
- sendViaTransport(transport, payload, configs?.[transport])
370
- )
381
+ transports.map((transport) => sendViaTransport(transport, payload, configs?.[transport]))
371
382
  )
372
383
  return results
373
384
  }
@@ -385,7 +396,7 @@ export function buildNotifyPayload(action: NotifyActionData): MessagePayload {
385
396
  body: action.message,
386
397
  type: 'notification',
387
398
  priority: action.priority || 'normal',
388
- metadata: action.metadata,
399
+ ...(action.metadata !== undefined && { metadata: action.metadata }),
389
400
  }
390
401
  }
391
402
 
@@ -397,9 +408,9 @@ export function buildAskPayload(action: AskActionData): MessagePayload {
397
408
  to: resolveActionTarget(action.object),
398
409
  body: action.question,
399
410
  type: 'question',
400
- schema: action.schema,
401
- timeout: action.timeout,
402
- metadata: action.metadata,
411
+ ...(action.schema !== undefined && { schema: action.schema }),
412
+ ...(action.timeout !== undefined && { timeout: action.timeout }),
413
+ ...(action.metadata !== undefined && { metadata: action.metadata }),
403
414
  }
404
415
  }
405
416
 
@@ -411,7 +422,7 @@ export function buildApprovePayload(action: ApproveActionData): MessagePayload {
411
422
  to: resolveActionTarget(action.object),
412
423
  body: action.request,
413
424
  type: 'approval',
414
- timeout: action.timeout,
425
+ ...(action.timeout !== undefined && { timeout: action.timeout }),
415
426
  actions: [
416
427
  { id: 'approve', label: 'Approve', style: 'primary', value: true },
417
428
  { id: 'reject', label: 'Reject', style: 'danger', value: false },
@@ -450,7 +461,7 @@ export const MessageTypeMapping = {
450
461
  discord: 'chat',
451
462
  whatsapp: 'text',
452
463
  telegram: 'text',
453
- voice: 'voicemail', // For voicemail messages
464
+ voice: 'voicemail', // For voicemail messages
454
465
  } as const
455
466
 
456
467
  /**
@@ -490,15 +501,19 @@ export function toDigitalToolsMessage(
490
501
  /**
491
502
  * Convert digital-tools Message to worker notification format
492
503
  */
493
- export function fromDigitalToolsMessage(
494
- message: Record<string, unknown>
495
- ): Partial<MessagePayload> {
504
+ export function fromDigitalToolsMessage(message: Record<string, unknown>): Partial<MessagePayload> {
505
+ const to = message['to'] as string | string[]
506
+ const from = message['from'] as string | undefined
507
+ const subject = message['subject'] as string | undefined
508
+ const body = message['body'] as string
509
+ const html = message['html'] as string | undefined
510
+ const metadata = message['metadata'] as Record<string, unknown> | undefined
496
511
  return {
497
- to: message.to as string | string[],
498
- from: message.from as string | undefined,
499
- subject: message.subject as string | undefined,
500
- body: message.body as string,
501
- html: message.html as string | undefined,
502
- metadata: message.metadata as Record<string, unknown> | undefined,
512
+ to,
513
+ body,
514
+ ...(from !== undefined && { from }),
515
+ ...(subject !== undefined && { subject }),
516
+ ...(html !== undefined && { html }),
517
+ ...(metadata !== undefined && { metadata }),
503
518
  }
504
519
  }
package/src/types.ts CHANGED
@@ -11,11 +11,46 @@
11
11
  * - **Contacts**: How a worker can be reached (email, slack, phone, etc.)
12
12
  * - **Action**: Durable workflow action (notify, ask, approve, decide)
13
13
  * - **Team**: Group of workers with shared contacts
14
+ * - **CapabilityTier**: Agent capability level (code, generative, agentic, human)
14
15
  *
15
16
  * @packageDocumentation
16
17
  */
17
18
 
18
19
  import type { SimpleSchema } from 'ai-functions'
20
+ import type { Thing, ThingRef } from 'digital-objects'
21
+ import type { ThingRef as SchemaThingRef } from 'schema.org.ai'
22
+ import type { CapabilityTier, CapabilityProfile } from './capability-tiers.js'
23
+
24
+ // Import consolidated types from org.ai
25
+ import type { Role, Team, Goal, Goals, KPI, OKR, TeamMember, KeyResult } from 'org.ai'
26
+
27
+ // Re-export org.ai types for convenience
28
+ export type { Role, Team, Goal, Goals, KPI, OKR, TeamMember, KeyResult }
29
+
30
+ // Re-export digital-objects core types used by Worker/Role surfaces
31
+ export type { Thing, ThingRef }
32
+
33
+ // ============================================================================
34
+ // Identity (SVO co-design — aip-ttfk)
35
+ // ============================================================================
36
+
37
+ /**
38
+ * IdentityRef — reference to an `id.org.ai` Identity record.
39
+ *
40
+ * Widened from the `string`-only placeholder introduced in aip-ttfk to the
41
+ * `schema.org.ai` `ThingRef` shape now that the upstream package has shipped
42
+ * (`schema.org.ai@^0.1.0`). Two shapes are accepted:
43
+ * - bare string `$id` (back-compat with the original `IdentityRef = string`)
44
+ * - `{ $id, $type, name? }` typed reference, so callers can route by class
45
+ * without first resolving the Identity record.
46
+ *
47
+ * Per the SVO co-design plan (`docs/plans/2026-05-05-svo-co-design.md`,
48
+ * step 4), a `Worker` carries an `IdentityRef` so AuthBroker and
49
+ * PaymentBroker can gate Tool invocations on the worker's scopes and
50
+ * funding instruments. The typed form lets `Worker.resolve()` skip a
51
+ * fetch when `$type` is already known.
52
+ */
53
+ export type IdentityRef = SchemaThingRef
19
54
 
20
55
  // ============================================================================
21
56
  // Worker Types
@@ -30,10 +65,10 @@ export type WorkerType = 'agent' | 'human'
30
65
  * Worker status
31
66
  */
32
67
  export type WorkerStatus =
33
- | 'available' // Ready to accept work
34
- | 'busy' // Currently working
35
- | 'away' // Not available (break, offline)
36
- | 'offline' // Disconnected
68
+ | 'available' // Ready to accept work
69
+ | 'busy' // Currently working
70
+ | 'away' // Not available (break, offline)
71
+ | 'offline' // Disconnected
37
72
 
38
73
  // ============================================================================
39
74
  // Contact Channel Types
@@ -43,17 +78,17 @@ export type WorkerStatus =
43
78
  * Contact channel names - how workers can be reached
44
79
  */
45
80
  export type ContactChannel =
46
- | 'email' // Email communication
47
- | 'slack' // Slack workspace
48
- | 'teams' // Microsoft Teams
49
- | 'discord' // Discord server
50
- | 'phone' // Voice calls
51
- | 'sms' // SMS text messages
52
- | 'whatsapp' // WhatsApp messaging
53
- | 'telegram' // Telegram messaging
54
- | 'web' // Web UI/dashboard
55
- | 'api' // Programmatic API
56
- | 'webhook' // Webhook callbacks
81
+ | 'email' // Email communication
82
+ | 'slack' // Slack workspace
83
+ | 'teams' // Microsoft Teams
84
+ | 'discord' // Discord server
85
+ | 'phone' // Voice calls
86
+ | 'sms' // SMS text messages
87
+ | 'whatsapp' // WhatsApp messaging
88
+ | 'telegram' // Telegram messaging
89
+ | 'web' // Web UI/dashboard
90
+ | 'api' // Programmatic API
91
+ | 'webhook' // Webhook callbacks
57
92
 
58
93
  /**
59
94
  * Email contact - simple string or config object
@@ -233,6 +268,17 @@ export interface Worker {
233
268
  teams?: string[]
234
269
  skills?: string[]
235
270
  tools?: string[]
271
+ /** Capability tier (code, generative, agentic, human) */
272
+ capabilityTier?: CapabilityTier
273
+ /** Full capability profile for detailed configuration */
274
+ capabilityProfile?: CapabilityProfile
275
+ /**
276
+ * Reference to this Worker's `id.org.ai` Identity record (DID + scopes +
277
+ * payment instruments). Optional for backward compatibility — populated
278
+ * by deployments that have wired up an `id.org.ai` AuthBroker/
279
+ * PaymentBroker. SVO co-design step 4 (aip-ttfk).
280
+ */
281
+ identity?: IdentityRef
236
282
  metadata?: Record<string, unknown>
237
283
  }
238
284
 
@@ -244,6 +290,8 @@ export interface WorkerRef {
244
290
  type?: WorkerType
245
291
  name?: string
246
292
  role?: string
293
+ /** Capability tier for routing decisions */
294
+ capabilityTier?: CapabilityTier
247
295
  }
248
296
 
249
297
  // ============================================================================
@@ -251,11 +299,15 @@ export interface WorkerRef {
251
299
  // ============================================================================
252
300
 
253
301
  /**
254
- * Team - group of workers with shared contacts
302
+ * WorkerTeam - group of workers with shared contacts
303
+ *
304
+ * This is the digital-workers team interface that includes
305
+ * worker-specific contact channels. For the base Team type,
306
+ * use Team from org.ai.
255
307
  *
256
308
  * @example
257
309
  * ```ts
258
- * const engineering: Team = {
310
+ * const engineering: WorkerTeam = {
259
311
  * id: 'team_eng',
260
312
  * name: 'Engineering',
261
313
  * members: [alice, bob, deployBot],
@@ -266,14 +318,22 @@ export interface WorkerRef {
266
318
  * }
267
319
  * ```
268
320
  */
269
- export interface Team {
321
+ export interface WorkerTeam {
322
+ /** Team identifier */
270
323
  id: string
324
+ /** Team name */
271
325
  name: string
326
+ /** Team description */
272
327
  description?: string
328
+ /** Team members as WorkerRefs */
273
329
  members: WorkerRef[]
330
+ /** Worker-specific contact channels */
274
331
  contacts: Contacts
332
+ /** Team lead as WorkerRef */
275
333
  lead?: WorkerRef
334
+ /** Team goals */
276
335
  goals?: string[]
336
+ /** Additional metadata */
277
337
  metadata?: Record<string, unknown>
278
338
  }
279
339
 
@@ -615,9 +675,7 @@ export interface WorkerContext {
615
675
  /**
616
676
  * Make a decision (AI or human)
617
677
  */
618
- decide<T = string>(
619
- options: DecideOptions<T>
620
- ): Promise<DecideResult<T>>
678
+ decide<T = string>(options: DecideOptions<T>): Promise<DecideResult<T>>
621
679
  }
622
680
 
623
681
  // ============================================================================
@@ -671,53 +729,139 @@ export interface DecideOptions<T = string> {
671
729
  // ============================================================================
672
730
 
673
731
  /**
674
- * Worker role definition
732
+ * OrgRole a slot in an org structure (e.g., 'CEO', 'PDM') filled by a
733
+ * specific Person or Agent.
734
+ *
735
+ * SVO co-design step 4 (aip-ttfk). This is the Noun-extending Role from
736
+ * `docs/plans/2026-05-05-svo-co-design.md`: a `Thing` whose data records
737
+ * the slot's current `filler` and an optional `fallbackChain` for when
738
+ * the filler is unavailable. A `Worker` whose `id` references an
739
+ * `OrgRole` resolves to the current filler at invocation time.
740
+ *
741
+ * NAMING NOTE: the design doc calls this type `Role`, but `Role` is
742
+ * already imported from `org.ai` and re-exported above as a different
743
+ * concept (a job-description-shaped HR Role with skills, permissions,
744
+ * responsibilities). Renamed here to `OrgRole` to avoid the collision;
745
+ * see the aip-ttfk bead comment for the surfaced conflict.
746
+ *
747
+ * @example
748
+ * ```ts
749
+ * const ceo: OrgRole = {
750
+ * id: 'role_ceo',
751
+ * noun: 'OrgRole',
752
+ * data: {
753
+ * $type: 'Role',
754
+ * name: 'CEO',
755
+ * filler: 'person_priya',
756
+ * fallbackChain: ['person_alex'],
757
+ * },
758
+ * createdAt: new Date(),
759
+ * updatedAt: new Date(),
760
+ * }
761
+ * ```
762
+ */
763
+ export interface OrgRole
764
+ extends Thing<{
765
+ $type: 'Role'
766
+ /** Display name of the slot (e.g., 'CEO', 'PDM') */
767
+ name: string
768
+ /** Current filler — a Person or Agent ThingRef */
769
+ filler: ThingRef
770
+ /** Fallback fillers tried in order if `filler` is unavailable */
771
+ fallbackChain?: ThingRef[]
772
+ }> {}
773
+
774
+ /**
775
+ * WorkerRole - extends Role from org.ai with worker-specific requirements
776
+ *
777
+ * Inherits all fields from the base Role type (id, name, description, skills,
778
+ * permissions, tools, outputs, type, department, etc.) and makes responsibilities
779
+ * required for worker role definitions.
780
+ *
781
+ * @example
782
+ * ```ts
783
+ * const engineerRole: WorkerRole = {
784
+ * id: 'role_engineer',
785
+ * name: 'Software Engineer',
786
+ * description: 'Builds and maintains software',
787
+ * skills: ['typescript', 'react', 'node'],
788
+ * responsibilities: ['write code', 'review PRs', 'fix bugs'],
789
+ * }
790
+ * ```
675
791
  */
676
- export interface WorkerRole {
677
- name: string
678
- description: string
792
+ export interface WorkerRole extends Role {
793
+ /** List of responsibilities (required for worker roles) */
679
794
  responsibilities: string[]
680
- skills?: string[]
681
- permissions?: string[]
682
- type?: 'ai' | 'human' | 'hybrid'
683
795
  }
684
796
 
685
797
  /**
686
- * Worker goals
798
+ * WorkerGoals - categorized goals with metrics
799
+ *
800
+ * Organizes goals by timeframe (short-term, long-term, strategic)
801
+ * and includes associated KPI metrics for tracking.
802
+ *
803
+ * Note: org.ai's Goals is a simpler type (Goal[]). WorkerGoals
804
+ * provides additional structure for worker/team goal planning
805
+ * with string-based goals for simplicity.
687
806
  */
688
807
  export interface WorkerGoals {
808
+ /** Short-term goals (days to weeks) */
689
809
  shortTerm: string[]
810
+ /** Long-term goals (months to year) */
690
811
  longTerm: string[]
812
+ /** Strategic goals (multi-year vision) */
691
813
  strategic?: string[]
692
- metrics?: KPI[]
814
+ /** Associated KPI metrics */
815
+ metrics?: WorkerKPI[]
693
816
  }
694
817
 
695
818
  /**
696
- * KPI definition
819
+ * WorkerKPI - simplified KPI for worker goals
820
+ *
821
+ * A simpler KPI interface used in WorkerGoals.metrics.
822
+ * For the full KPI type with id, category, history, etc.,
823
+ * use KPI from org.ai.
697
824
  */
698
- export interface KPI {
825
+ export interface WorkerKPI {
826
+ /** KPI name */
699
827
  name: string
828
+ /** Description of what this measures */
700
829
  description: string
830
+ /** Current value */
701
831
  current: number
832
+ /** Target value */
702
833
  target: number
834
+ /** Unit of measurement */
703
835
  unit: string
836
+ /** Trend direction */
704
837
  trend?: 'up' | 'down' | 'stable'
838
+ /** Measurement period */
705
839
  period?: string
706
840
  }
707
841
 
708
842
  /**
709
- * OKR definition
843
+ * WorkerOKR - worker-specific OKR definition
844
+ *
845
+ * Uses WorkerRef for owner and simplified key results with
846
+ * required `current` and `target` fields for progress tracking.
847
+ * For the full org.ai OKR with `id`, `status`, `period`, etc.,
848
+ * import OKR from 'org.ai' directly.
710
849
  */
711
- export interface OKR {
850
+ export interface WorkerOKR {
851
+ /** The objective - what you want to achieve */
712
852
  objective: string
853
+ /** Measurable key results */
713
854
  keyResults: Array<{
714
855
  name: string
715
856
  current: number
716
857
  target: number
717
858
  unit: string
718
859
  }>
860
+ /** Owner as WorkerRef */
719
861
  owner?: WorkerRef
862
+ /** Due date */
720
863
  dueDate?: Date
864
+ /** Overall progress percentage */
721
865
  progress?: number
722
866
  }
723
867
 
@@ -776,13 +920,7 @@ export interface DoOptions {
776
920
  /**
777
921
  * Content type for generation
778
922
  */
779
- export type GenerationType =
780
- | 'text'
781
- | 'code'
782
- | 'structured'
783
- | 'image'
784
- | 'video'
785
- | 'audio'
923
+ export type GenerationType = 'text' | 'code' | 'structured' | 'image' | 'video' | 'audio'
786
924
 
787
925
  /**
788
926
  * Options for content generation
@@ -834,10 +972,8 @@ export interface TypeCheckResult<T = unknown> {
834
972
  }
835
973
 
836
974
  // ============================================================================
837
- // Team Alias
975
+ // Team Alias - Backwards Compatibility
838
976
  // ============================================================================
839
977
 
840
- /**
841
- * @deprecated Use Team instead
842
- */
843
- export type WorkerTeam = Team
978
+ // WorkerTeam is now the primary type that extends Team from org.ai
979
+ // The base Team type is re-exported from org.ai
@@ -0,0 +1,21 @@
1
+ /**
2
+ * ID generation utilities for request tracking across transports
3
+ */
4
+
5
+ /**
6
+ * Generate a unique request ID with the specified prefix.
7
+ *
8
+ * Format: `{prefix}_{timestamp}_{random}`
9
+ * - prefix: Customizable identifier (default: 'req')
10
+ * - timestamp: Unix timestamp in milliseconds
11
+ * - random: 9-character base36 random string
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * generateRequestId() // 'req_1706454932123_k7x3m9n2p'
16
+ * generateRequestId('apr') // 'apr_1706454932123_k7x3m9n2p'
17
+ * ```
18
+ */
19
+ export function generateRequestId(prefix: string = 'req'): string {
20
+ return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`
21
+ }