digital-workers 2.1.3 → 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 (183) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +2 -0
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +33 -21
  5. package/dist/actions.js.map +1 -1
  6. package/dist/agent-comms.d.ts.map +1 -1
  7. package/dist/agent-comms.js +36 -25
  8. package/dist/agent-comms.js.map +1 -1
  9. package/dist/approve.d.ts +40 -8
  10. package/dist/approve.d.ts.map +1 -1
  11. package/dist/approve.js +86 -20
  12. package/dist/approve.js.map +1 -1
  13. package/dist/ask.d.ts +38 -7
  14. package/dist/ask.d.ts.map +1 -1
  15. package/dist/ask.js +85 -25
  16. package/dist/ask.js.map +1 -1
  17. package/dist/browse.d.ts +223 -0
  18. package/dist/browse.d.ts.map +1 -0
  19. package/dist/browse.js +392 -0
  20. package/dist/browse.js.map +1 -0
  21. package/dist/capability-tiers.js +3 -3
  22. package/dist/capability-tiers.js.map +1 -1
  23. package/dist/cascade-context.d.ts +28 -28
  24. package/dist/client.d.ts +162 -0
  25. package/dist/client.d.ts.map +1 -0
  26. package/dist/client.js +64 -0
  27. package/dist/client.js.map +1 -0
  28. package/dist/decide.d.ts +42 -6
  29. package/dist/decide.d.ts.map +1 -1
  30. package/dist/decide.js +54 -11
  31. package/dist/decide.js.map +1 -1
  32. package/dist/do.d.ts +36 -7
  33. package/dist/do.d.ts.map +1 -1
  34. package/dist/do.js +82 -39
  35. package/dist/do.js.map +1 -1
  36. package/dist/error-escalation.d.ts.map +1 -1
  37. package/dist/error-escalation.js +38 -38
  38. package/dist/error-escalation.js.map +1 -1
  39. package/dist/generate.d.ts +48 -7
  40. package/dist/generate.d.ts.map +1 -1
  41. package/dist/generate.js +49 -8
  42. package/dist/generate.js.map +1 -1
  43. package/dist/goals.d.ts +10 -9
  44. package/dist/goals.d.ts.map +1 -1
  45. package/dist/goals.js +30 -24
  46. package/dist/goals.js.map +1 -1
  47. package/dist/image.d.ts +189 -0
  48. package/dist/image.d.ts.map +1 -0
  49. package/dist/image.js +528 -0
  50. package/dist/image.js.map +1 -0
  51. package/dist/index.d.ts +49 -2
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +58 -2
  54. package/dist/index.js.map +1 -1
  55. package/dist/is.d.ts +45 -10
  56. package/dist/is.d.ts.map +1 -1
  57. package/dist/is.js +56 -21
  58. package/dist/is.js.map +1 -1
  59. package/dist/kpis.d.ts +24 -15
  60. package/dist/kpis.d.ts.map +1 -1
  61. package/dist/kpis.js +16 -14
  62. package/dist/kpis.js.map +1 -1
  63. package/dist/load-balancing.d.ts.map +1 -1
  64. package/dist/load-balancing.js +124 -38
  65. package/dist/load-balancing.js.map +1 -1
  66. package/dist/logger.d.ts +76 -0
  67. package/dist/logger.d.ts.map +1 -0
  68. package/dist/logger.js +39 -0
  69. package/dist/logger.js.map +1 -0
  70. package/dist/notify.d.ts +38 -9
  71. package/dist/notify.d.ts.map +1 -1
  72. package/dist/notify.js +72 -17
  73. package/dist/notify.js.map +1 -1
  74. package/dist/role.d.ts +5 -4
  75. package/dist/role.d.ts.map +1 -1
  76. package/dist/role.js +13 -10
  77. package/dist/role.js.map +1 -1
  78. package/dist/runtime.d.ts +310 -0
  79. package/dist/runtime.d.ts.map +1 -0
  80. package/dist/runtime.js +510 -0
  81. package/dist/runtime.js.map +1 -0
  82. package/dist/team.d.ts +11 -6
  83. package/dist/team.d.ts.map +1 -1
  84. package/dist/team.js +22 -15
  85. package/dist/team.js.map +1 -1
  86. package/dist/transports/email.d.ts +318 -0
  87. package/dist/transports/email.d.ts.map +1 -0
  88. package/dist/transports/email.js +779 -0
  89. package/dist/transports/email.js.map +1 -0
  90. package/dist/transports/slack.d.ts +515 -0
  91. package/dist/transports/slack.d.ts.map +1 -0
  92. package/dist/transports/slack.js +844 -0
  93. package/dist/transports/slack.js.map +1 -0
  94. package/dist/transports.d.ts.map +1 -1
  95. package/dist/transports.js +44 -25
  96. package/dist/transports.js.map +1 -1
  97. package/dist/types.d.ts +141 -19
  98. package/dist/types.d.ts.map +1 -1
  99. package/dist/types.js +5 -0
  100. package/dist/types.js.map +1 -1
  101. package/dist/utils/id.d.ts +19 -0
  102. package/dist/utils/id.d.ts.map +1 -0
  103. package/dist/utils/id.js +21 -0
  104. package/dist/utils/id.js.map +1 -0
  105. package/dist/video.d.ts +203 -0
  106. package/dist/video.d.ts.map +1 -0
  107. package/dist/video.js +528 -0
  108. package/dist/video.js.map +1 -0
  109. package/dist/worker.d.ts +343 -0
  110. package/dist/worker.d.ts.map +1 -0
  111. package/dist/worker.js +698 -0
  112. package/dist/worker.js.map +1 -0
  113. package/package.json +32 -14
  114. package/src/actions.ts +39 -30
  115. package/src/agent-comms.ts +54 -92
  116. package/src/approve.ts +91 -20
  117. package/src/ask.ts +99 -25
  118. package/src/browse.ts +627 -0
  119. package/src/capability-tiers.ts +5 -5
  120. package/src/client.ts +221 -0
  121. package/src/decide.ts +81 -35
  122. package/src/do.ts +98 -52
  123. package/src/error-escalation.ts +55 -67
  124. package/src/generate.ts +52 -18
  125. package/src/goals.ts +36 -27
  126. package/src/image.ts +816 -0
  127. package/src/index.ts +187 -2
  128. package/src/is.ts +59 -25
  129. package/src/kpis.ts +41 -36
  130. package/src/load-balancing.ts +132 -46
  131. package/src/logger.ts +93 -0
  132. package/src/notify.ts +78 -17
  133. package/src/role.ts +30 -20
  134. package/src/runtime.ts +796 -0
  135. package/src/team.ts +24 -19
  136. package/src/transports/email.ts +1160 -0
  137. package/src/transports/slack.ts +1320 -0
  138. package/src/transports.ts +58 -43
  139. package/src/types.ts +174 -46
  140. package/src/utils/id.ts +21 -0
  141. package/src/video.ts +906 -0
  142. package/src/worker.ts +1007 -0
  143. package/test/approve.test.ts +305 -0
  144. package/test/ask.test.ts +274 -0
  145. package/test/browse.test.ts +361 -0
  146. package/test/decide.test.ts +252 -0
  147. package/test/do.test.ts +144 -0
  148. package/test/error-logging.test.ts +357 -0
  149. package/test/generate.test.ts +319 -0
  150. package/test/image.test.ts +398 -0
  151. package/test/is.test.ts +287 -0
  152. package/test/load-balancing-safety.test.ts +404 -0
  153. package/test/notify.test.ts +434 -0
  154. package/test/primitives.test.ts +320 -0
  155. package/test/runtime-integration.test.ts +892 -0
  156. package/test/transports/crypto.test.ts +230 -0
  157. package/test/transports/email.test.ts +866 -0
  158. package/test/transports/id-generation.test.ts +91 -0
  159. package/test/transports/slack.test.ts +760 -0
  160. package/test/type-safety.test.ts +834 -0
  161. package/test/types.test.ts +60 -2
  162. package/test/video.test.ts +530 -0
  163. package/test/worker.test.ts +1433 -0
  164. package/tsconfig.json +4 -1
  165. package/vitest.config.ts +42 -0
  166. package/wrangler.jsonc +36 -0
  167. package/.turbo/turbo-build.log +0 -4
  168. package/LICENSE +0 -21
  169. package/src/actions.js +0 -436
  170. package/src/approve.js +0 -234
  171. package/src/ask.js +0 -226
  172. package/src/decide.js +0 -244
  173. package/src/do.js +0 -227
  174. package/src/generate.js +0 -298
  175. package/src/goals.js +0 -205
  176. package/src/index.js +0 -68
  177. package/src/is.js +0 -317
  178. package/src/kpis.js +0 -270
  179. package/src/notify.js +0 -219
  180. package/src/role.js +0 -110
  181. package/src/team.js +0 -130
  182. package/src/transports.js +0 -357
  183. package/src/types.js +0 -71
@@ -424,25 +424,28 @@ export function createClassifiedError(
424
424
  original,
425
425
  severity: options.severity,
426
426
  category: options.category,
427
- tier: options.tier,
428
- agentId: options.agentId,
429
- taskId: options.taskId,
430
427
  timestamp: new Date(),
431
- stack: original.stack,
432
- previousError: options.previousError,
433
- context: options.context,
428
+ ...(original.stack !== undefined && { stack: original.stack }),
429
+ ...(options.tier !== undefined && { tier: options.tier }),
430
+ ...(options.agentId !== undefined && { agentId: options.agentId }),
431
+ ...(options.taskId !== undefined && { taskId: options.taskId }),
432
+ ...(options.previousError !== undefined && { previousError: options.previousError }),
433
+ ...(options.context !== undefined && { context: options.context }),
434
434
  }
435
435
  }
436
436
 
437
437
  /**
438
438
  * Classify an error automatically
439
439
  */
440
- export function classifyError(error: Error, options: Partial<{
441
- tier: CapabilityTier
442
- agentId: string
443
- taskId: string
444
- context: ErrorContext
445
- }> = {}): ClassifiedError {
440
+ export function classifyError(
441
+ error: Error,
442
+ options: Partial<{
443
+ tier: CapabilityTier
444
+ agentId: string
445
+ taskId: string
446
+ context: ErrorContext
447
+ }> = {}
448
+ ): ClassifiedError {
446
449
  const severity = getErrorSeverity(error)
447
450
  const category = getErrorCategory(error)
448
451
 
@@ -531,9 +534,11 @@ export function createEscalationPolicy(options: EscalationPolicyOptions): Escala
531
534
  return {
532
535
  maxEscalationDepth: options.maxEscalationDepth ?? 10,
533
536
  allowSkipTiers: options.allowSkipTiers ?? false,
534
- skipTierThreshold: options.skipTierThreshold,
537
+ ...(options.skipTierThreshold !== undefined && {
538
+ skipTierThreshold: options.skipTierThreshold,
539
+ }),
535
540
  rules: options.rules ?? [],
536
- tierPolicies: options.tierPolicies,
541
+ ...(options.tierPolicies !== undefined && { tierPolicies: options.tierPolicies }),
537
542
  }
538
543
  }
539
544
 
@@ -548,7 +553,7 @@ export function getNextEscalationTier(
548
553
 
549
554
  // Check custom rules first
550
555
  const applicableRules = policy.rules
551
- .filter(rule => rule.fromTier === currentTier && rule.condition(error))
556
+ .filter((rule) => rule.fromTier === currentTier && rule.condition(error))
552
557
  .sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0))
553
558
 
554
559
  if (applicableRules.length > 0) {
@@ -608,17 +613,13 @@ export function shouldEscalate(
608
613
  // Filter by time window if specified
609
614
  let relevantErrors = errorHistory
610
615
  if (timeWindow) {
611
- relevantErrors = errorHistory.filter(
612
- entry => now - entry.timestamp <= timeWindow
613
- )
616
+ relevantErrors = errorHistory.filter((entry) => now - entry.timestamp <= timeWindow)
614
617
  }
615
618
 
616
619
  // Calculate weighted count if severity multiplier is specified
617
620
  if (severityMultiplier) {
618
621
  const weightedCount = relevantErrors.reduce((sum, entry) => {
619
- const multiplier = entry.severity
620
- ? (severityMultiplier[entry.severity] ?? 1)
621
- : 1
622
+ const multiplier = entry.severity ? severityMultiplier[entry.severity] ?? 1 : 1
622
623
  return sum + multiplier
623
624
  }, 0)
624
625
  return weightedCount >= errorCount
@@ -630,10 +631,7 @@ export function shouldEscalate(
630
631
  /**
631
632
  * Detect circular escalation
632
633
  */
633
- export function detectCircularEscalation(
634
- path: EscalationPath,
635
- history: CapabilityTier[]
636
- ): boolean {
634
+ export function detectCircularEscalation(path: EscalationPath, history: CapabilityTier[]): boolean {
637
635
  // If we're going back to a tier we've already visited, it's circular
638
636
  if (history.includes(path.toTier)) {
639
637
  return true
@@ -642,7 +640,7 @@ export function detectCircularEscalation(
642
640
  // Check for de-escalation (going to a lower tier)
643
641
  if (TIER_ORDER[path.toTier] < TIER_ORDER[path.fromTier]) {
644
642
  // If we've already been at a tier higher than where we're going, it's circular
645
- const maxTierVisited = Math.max(...history.map(t => TIER_ORDER[t]))
643
+ const maxTierVisited = Math.max(...history.map((t) => TIER_ORDER[t]))
646
644
  if (TIER_ORDER[path.toTier] < maxTierVisited) {
647
645
  return true
648
646
  }
@@ -686,12 +684,7 @@ export function validateEscalationPath(
686
684
  * Calculate backoff delay with optional jitter
687
685
  */
688
686
  export function calculateBackoff(config: RetryConfig, attemptNumber: number): number {
689
- const {
690
- baseDelayMs,
691
- maxDelayMs = Infinity,
692
- backoffMultiplier = 2,
693
- jitterPercent = 0,
694
- } = config
687
+ const { baseDelayMs, maxDelayMs = Infinity, backoffMultiplier = 2, jitterPercent = 0 } = config
695
688
 
696
689
  // Calculate exponential delay
697
690
  let delay = baseDelayMs * Math.pow(backoffMultiplier, attemptNumber)
@@ -757,9 +750,7 @@ export function selectFallbackAgent(
757
750
  agents: AgentForFallback[]
758
751
  ): AgentForFallback | null {
759
752
  // Filter excluded agents
760
- let candidates = agents.filter(
761
- a => !config.excludeAgentIds?.includes(a.id)
762
- )
753
+ let candidates = agents.filter((a) => !config.excludeAgentIds?.includes(a.id))
763
754
 
764
755
  if (candidates.length === 0) {
765
756
  return null
@@ -768,9 +759,9 @@ export function selectFallbackAgent(
768
759
  switch (config.strategy) {
769
760
  case 'capability-match':
770
761
  if (config.requiredSkills && config.requiredSkills.length > 0) {
771
- candidates = candidates.filter(a => {
762
+ candidates = candidates.filter((a) => {
772
763
  const agentSkills = a.skills ?? []
773
- return config.requiredSkills!.every(skill => agentSkills.includes(skill))
764
+ return config.requiredSkills!.every((skill) => agentSkills.includes(skill))
774
765
  })
775
766
  }
776
767
  return candidates[0] ?? null
@@ -785,7 +776,7 @@ export function selectFallbackAgent(
785
776
 
786
777
  case 'same-tier':
787
778
  if (config.currentTier) {
788
- candidates = candidates.filter(a => a.tier === config.currentTier)
779
+ candidates = candidates.filter((a) => a.tier === config.currentTier)
789
780
  }
790
781
  return candidates[0] ?? null
791
782
 
@@ -849,7 +840,7 @@ export function createRecoveryState(options: RecoveryStateOptions): RecoveryStat
849
840
  return {
850
841
  errorId: options.errorId,
851
842
  tier: options.tier,
852
- agentId: options.agentId,
843
+ ...(options.agentId !== undefined && { agentId: options.agentId }),
853
844
  retryState: createRetryState(),
854
845
  escalated: false,
855
846
  resolved: false,
@@ -886,14 +877,14 @@ export function updateRecoveryState(
886
877
  escalated: true,
887
878
  escalationPath: [...state.escalationPath, newTier],
888
879
  lastAction: 'escalate',
889
- isTerminal: update.isTerminal,
880
+ ...(update.isTerminal !== undefined && { isTerminal: update.isTerminal }),
890
881
  }
891
882
 
892
883
  case 'fallback':
893
884
  const oldAgentId = state.agentId
894
885
  return {
895
886
  ...state,
896
- agentId: update.toAgentId,
887
+ ...(update.toAgentId !== undefined && { agentId: update.toAgentId }),
897
888
  fallbackHistory: oldAgentId
898
889
  ? [...state.fallbackHistory, oldAgentId]
899
890
  : state.fallbackHistory,
@@ -904,7 +895,7 @@ export function updateRecoveryState(
904
895
  return {
905
896
  ...state,
906
897
  resolved: true,
907
- resolution: update.resolution,
898
+ ...(update.resolution !== undefined && { resolution: update.resolution }),
908
899
  lastAction: 'resolve',
909
900
  }
910
901
 
@@ -967,10 +958,7 @@ export function createEscalationEngine(options: EscalationEngineOptions = {}): E
967
958
  retriesSuccessful: 0,
968
959
  }
969
960
 
970
- async function handleError(
971
- error: Error,
972
- opts: HandleErrorOptions
973
- ): Promise<EscalationResult> {
961
+ async function handleError(error: Error, opts: HandleErrorOptions): Promise<EscalationResult> {
974
962
  // Classify the error
975
963
  const severity = opts.severity ?? getErrorSeverity(error)
976
964
  const category = getErrorCategory(error)
@@ -978,11 +966,11 @@ export function createEscalationEngine(options: EscalationEngineOptions = {}): E
978
966
  const classifiedError = createClassifiedError(error, {
979
967
  severity,
980
968
  category,
981
- tier: opts.tier,
982
- agentId: opts.agentId,
983
- taskId: opts.taskId,
984
- previousError: opts.previousError,
985
- context: opts.context,
969
+ ...(opts.tier !== undefined && { tier: opts.tier }),
970
+ ...(opts.agentId !== undefined && { agentId: opts.agentId }),
971
+ ...(opts.taskId !== undefined && { taskId: opts.taskId }),
972
+ ...(opts.previousError !== undefined && { previousError: opts.previousError }),
973
+ ...(opts.context !== undefined && { context: opts.context }),
986
974
  })
987
975
 
988
976
  // Update metrics
@@ -1036,10 +1024,11 @@ export function createEscalationEngine(options: EscalationEngineOptions = {}): E
1036
1024
  } else if (opts.availableAgents && opts.availableAgents.length > 0) {
1037
1025
  // Try fallback
1038
1026
  action = 'fallback'
1039
- fallbackAgent = selectFallbackAgent(
1040
- { strategy: 'capability-match', excludeAgentIds: [opts.agentId ?? ''] },
1041
- opts.availableAgents
1042
- ) ?? undefined
1027
+ fallbackAgent =
1028
+ selectFallbackAgent(
1029
+ { strategy: 'capability-match', excludeAgentIds: [opts.agentId ?? ''] },
1030
+ opts.availableAgents
1031
+ ) ?? undefined
1043
1032
  } else {
1044
1033
  action = 'degrade'
1045
1034
  degradationLevel = getDegradationLevel(severity)
@@ -1049,10 +1038,11 @@ export function createEscalationEngine(options: EscalationEngineOptions = {}): E
1049
1038
  else {
1050
1039
  if (opts.availableAgents && opts.availableAgents.length > 0) {
1051
1040
  action = 'fallback'
1052
- fallbackAgent = selectFallbackAgent(
1053
- { strategy: 'same-tier', currentTier: 'human', excludeAgentIds: [opts.agentId ?? ''] },
1054
- opts.availableAgents
1055
- ) ?? undefined
1041
+ fallbackAgent =
1042
+ selectFallbackAgent(
1043
+ { strategy: 'same-tier', currentTier: 'human', excludeAgentIds: [opts.agentId ?? ''] },
1044
+ opts.availableAgents
1045
+ ) ?? undefined
1056
1046
  if (!fallbackAgent) {
1057
1047
  action = 'terminal'
1058
1048
  }
@@ -1065,14 +1055,12 @@ export function createEscalationEngine(options: EscalationEngineOptions = {}): E
1065
1055
  handled: true,
1066
1056
  action,
1067
1057
  classifiedError,
1068
- retryDelay,
1069
- escalationPath,
1070
- fallbackAgent,
1071
- degradationLevel,
1072
- preservedContext: opts.context,
1073
- errorChain: opts.previousError
1074
- ? buildErrorChain(classifiedError)
1075
- : undefined,
1058
+ ...(retryDelay !== undefined && { retryDelay }),
1059
+ ...(escalationPath !== undefined && { escalationPath }),
1060
+ ...(fallbackAgent !== undefined && { fallbackAgent }),
1061
+ ...(degradationLevel !== undefined && { degradationLevel }),
1062
+ ...(opts.context !== undefined && { preservedContext: opts.context }),
1063
+ ...(opts.previousError !== undefined && { errorChain: buildErrorChain(classifiedError) }),
1076
1064
  }
1077
1065
  }
1078
1066
 
package/src/generate.ts CHANGED
@@ -1,5 +1,34 @@
1
1
  /**
2
2
  * Content generation functionality for digital workers
3
+ *
4
+ * IMPORTANT: Worker-Context Generation vs Direct LLM Generation
5
+ * --------------------------------------------------------------
6
+ * This module provides content generation within a worker context,
7
+ * with rich metadata about the generation process.
8
+ *
9
+ * - `digital-workers.generate()` - Generates content with full metadata
10
+ * (tokens used, duration, model info) and supports multiple content types
11
+ * including text, code, structured, image, video, and audio.
12
+ *
13
+ * - `ai-functions.generate()` - Core generation primitive that powers all
14
+ * ai-functions; lower-level function with type-based dispatch.
15
+ *
16
+ * The key difference is context and metadata:
17
+ * - digital-workers returns `GenerateResult<T>` with content + metadata
18
+ * - ai-functions returns just the generated content
19
+ *
20
+ * Use digital-workers when you need:
21
+ * - Rich metadata about generation (tokens, duration, model)
22
+ * - Content type variants (text, code, structured, media)
23
+ * - Tone, audience, and length modifiers
24
+ * - Iterative refinement workflows
25
+ *
26
+ * Use ai-functions when you need:
27
+ * - Direct LLM generation without metadata
28
+ * - Template literal syntax (`ai\`prompt\``)
29
+ * - Promise pipelining and schema inference
30
+ *
31
+ * @module
3
32
  */
4
33
 
5
34
  import { generateObject, generateText } from 'ai-functions'
@@ -7,23 +36,31 @@ import type { SimpleSchema } from 'ai-functions'
7
36
  import type { GenerateResult, GenerateOptions } from './types.js'
8
37
 
9
38
  /**
10
- * Generate content
39
+ * Generate content with rich metadata and multiple content type support.
11
40
  *
12
- * Uses AI to generate various types of content including text,
13
- * code, structured data, images, video, and audio.
41
+ * **Key Difference from ai-functions.generate():**
42
+ * Unlike `ai-functions.generate()` which is a lower-level type-dispatch
43
+ * function, this function returns a `GenerateResult` wrapper with:
44
+ * - The generated content
45
+ * - Generation metadata (model, tokens, duration)
46
+ * - Content type information
47
+ *
48
+ * This provides better observability for worker-based content generation.
14
49
  *
15
50
  * @param prompt - What to generate
16
- * @param options - Generation options
17
- * @returns Promise resolving to generated content
51
+ * @param options - Generation options (type, schema, instructions, model)
52
+ * @returns Promise resolving to GenerateResult with content and metadata
18
53
  *
19
54
  * @example
20
55
  * ```ts
21
- * // Generate text content
56
+ * // Generate text content with metadata
22
57
  * const result = await generate('Write a product description for wireless earbuds', {
23
58
  * type: 'text',
24
59
  * instructions: 'Focus on sound quality and battery life. Keep it under 100 words.',
25
60
  * })
26
- * console.log(result.content)
61
+ * console.log(result.content) // The generated text
62
+ * console.log(result.metadata.tokens) // Tokens used
63
+ * console.log(result.metadata.duration) // Generation time in ms
27
64
  * ```
28
65
  *
29
66
  * @example
@@ -52,18 +89,17 @@ import type { GenerateResult, GenerateOptions } from './types.js'
52
89
  * instructions: 'Use TypeScript and hooks. Include prop types.',
53
90
  * })
54
91
  * console.log(result.content) // TypeScript React component code
92
+ * console.log(result.metadata.language) // 'typescript'
55
93
  * ```
94
+ *
95
+ * @see {@link ai-functions#generate} for lower-level type-dispatch generation
96
+ * @see {@link ai-functions#ai} for template literal generation syntax
56
97
  */
57
98
  export async function generate<T = string>(
58
99
  prompt: string,
59
100
  options: GenerateOptions = {}
60
101
  ): Promise<GenerateResult<T>> {
61
- const {
62
- type = 'text',
63
- schema,
64
- instructions,
65
- model = 'sonnet',
66
- } = options
102
+ const { type = 'text', schema, instructions, model = 'sonnet' } = options
67
103
 
68
104
  const startTime = Date.now()
69
105
 
@@ -111,7 +147,7 @@ export async function generate<T = string>(
111
147
  type: 'structured',
112
148
  metadata: {
113
149
  model,
114
- tokens: result.usage?.totalTokens,
150
+ tokens: (result.usage as { totalTokens?: number } | undefined)?.totalTokens,
115
151
  duration: Date.now() - startTime,
116
152
  },
117
153
  }
@@ -144,7 +180,7 @@ export async function generate<T = string>(
144
180
  type: 'code',
145
181
  metadata: {
146
182
  model,
147
- tokens: result.usage?.totalTokens,
183
+ tokens: (result.usage as { totalTokens?: number } | undefined)?.totalTokens,
148
184
  duration: Date.now() - startTime,
149
185
  language: codeResult.language,
150
186
  explanation: codeResult.explanation,
@@ -199,9 +235,7 @@ generate.variations = async <T = string>(
199
235
  count: number,
200
236
  options: GenerateOptions = {}
201
237
  ): Promise<Array<GenerateResult<T>>> => {
202
- return Promise.all(
203
- Array.from({ length: count }, () => generate<T>(prompt, options))
204
- )
238
+ return Promise.all(Array.from({ length: count }, () => generate<T>(prompt, options)))
205
239
  }
206
240
 
207
241
  /**
package/src/goals.ts CHANGED
@@ -2,7 +2,10 @@
2
2
  * Goals definition for digital workers
3
3
  */
4
4
 
5
- import type { WorkerGoals, KPI } from './types.js'
5
+ import { calculateProgress, isOnTrack } from 'org.ai'
6
+ import type { WorkerGoals, WorkerKPI } from './types.js'
7
+
8
+ // Note: Goal, Goals types are re-exported from types.ts which imports from org.ai
6
9
 
7
10
  /**
8
11
  * Define worker goals
@@ -15,7 +18,7 @@ import type { WorkerGoals, KPI } from './types.js'
15
18
  *
16
19
  * @example
17
20
  * ```ts
18
- * const engineeringGoals = Goals({
21
+ * const engineeringGoals = defineGoals({
19
22
  * shortTerm: [
20
23
  * 'Complete Q1 roadmap features',
21
24
  * 'Reduce bug backlog by 30%',
@@ -55,7 +58,7 @@ import type { WorkerGoals, KPI } from './types.js'
55
58
  *
56
59
  * @example
57
60
  * ```ts
58
- * const supportGoals = Goals({
61
+ * const supportGoals = defineGoals({
59
62
  * shortTerm: [
60
63
  * 'Achieve 95% customer satisfaction',
61
64
  * 'Reduce average response time to < 5 min',
@@ -78,7 +81,7 @@ import type { WorkerGoals, KPI } from './types.js'
78
81
  * })
79
82
  * ```
80
83
  */
81
- export function Goals(definition: WorkerGoals): WorkerGoals {
84
+ export function defineGoals(definition: WorkerGoals): WorkerGoals {
82
85
  return definition
83
86
  }
84
87
 
@@ -91,10 +94,10 @@ export function Goals(definition: WorkerGoals): WorkerGoals {
91
94
  *
92
95
  * @example
93
96
  * ```ts
94
- * const updated = Goals.addShortTerm(engineeringGoals, 'Complete security audit')
97
+ * const updated = defineGoals.addShortTerm(engineeringGoals, 'Complete security audit')
95
98
  * ```
96
99
  */
97
- Goals.addShortTerm = (goals: WorkerGoals, goal: string): WorkerGoals => ({
100
+ defineGoals.addShortTerm = (goals: WorkerGoals, goal: string): WorkerGoals => ({
98
101
  ...goals,
99
102
  shortTerm: [...goals.shortTerm, goal],
100
103
  })
@@ -108,10 +111,10 @@ Goals.addShortTerm = (goals: WorkerGoals, goal: string): WorkerGoals => ({
108
111
  *
109
112
  * @example
110
113
  * ```ts
111
- * const updated = Goals.addLongTerm(engineeringGoals, 'Build ML platform')
114
+ * const updated = defineGoals.addLongTerm(engineeringGoals, 'Build ML platform')
112
115
  * ```
113
116
  */
114
- Goals.addLongTerm = (goals: WorkerGoals, goal: string): WorkerGoals => ({
117
+ defineGoals.addLongTerm = (goals: WorkerGoals, goal: string): WorkerGoals => ({
115
118
  ...goals,
116
119
  longTerm: [...goals.longTerm, goal],
117
120
  })
@@ -125,10 +128,10 @@ Goals.addLongTerm = (goals: WorkerGoals, goal: string): WorkerGoals => ({
125
128
  *
126
129
  * @example
127
130
  * ```ts
128
- * const updated = Goals.addStrategic(engineeringGoals, 'Become carbon neutral')
131
+ * const updated = defineGoals.addStrategic(engineeringGoals, 'Become carbon neutral')
129
132
  * ```
130
133
  */
131
- Goals.addStrategic = (goals: WorkerGoals, goal: string): WorkerGoals => ({
134
+ defineGoals.addStrategic = (goals: WorkerGoals, goal: string): WorkerGoals => ({
132
135
  ...goals,
133
136
  strategic: [...(goals.strategic || []), goal],
134
137
  })
@@ -142,7 +145,7 @@ Goals.addStrategic = (goals: WorkerGoals, goal: string): WorkerGoals => ({
142
145
  *
143
146
  * @example
144
147
  * ```ts
145
- * const updated = Goals.addMetric(engineeringGoals, {
148
+ * const updated = defineGoals.addMetric(engineeringGoals, {
146
149
  * name: 'Code Quality',
147
150
  * description: 'Code quality score from SonarQube',
148
151
  * current: 85,
@@ -153,7 +156,7 @@ Goals.addStrategic = (goals: WorkerGoals, goal: string): WorkerGoals => ({
153
156
  * })
154
157
  * ```
155
158
  */
156
- Goals.addMetric = (goals: WorkerGoals, kpi: KPI): WorkerGoals => ({
159
+ defineGoals.addMetric = (goals: WorkerGoals, kpi: WorkerKPI): WorkerGoals => ({
157
160
  ...goals,
158
161
  metrics: [...(goals.metrics || []), kpi],
159
162
  })
@@ -168,22 +171,26 @@ Goals.addMetric = (goals: WorkerGoals, kpi: KPI): WorkerGoals => ({
168
171
  *
169
172
  * @example
170
173
  * ```ts
171
- * const updated = Goals.updateMetric(engineeringGoals, 'Deployment Frequency', {
174
+ * const updated = defineGoals.updateMetric(engineeringGoals, 'Deployment Frequency', {
172
175
  * current: 8,
173
176
  * trend: 'up',
174
177
  * })
175
178
  * ```
176
179
  */
177
- Goals.updateMetric = (
180
+ defineGoals.updateMetric = (
178
181
  goals: WorkerGoals,
179
182
  name: string,
180
- updates: Partial<Omit<KPI, 'name'>>
181
- ): WorkerGoals => ({
182
- ...goals,
183
- metrics: goals.metrics?.map((kpi) =>
183
+ updates: Partial<Omit<WorkerKPI, 'name'>>
184
+ ): WorkerGoals => {
185
+ const updatedMetrics = goals.metrics?.map((kpi) =>
184
186
  kpi.name === name ? { ...kpi, ...updates } : kpi
185
- ),
186
- })
187
+ )
188
+ const result: WorkerGoals = { ...goals }
189
+ if (updatedMetrics) {
190
+ result.metrics = updatedMetrics
191
+ }
192
+ return result
193
+ }
187
194
 
188
195
  /**
189
196
  * Get progress for a KPI (0-1)
@@ -194,12 +201,11 @@ Goals.updateMetric = (
194
201
  * @example
195
202
  * ```ts
196
203
  * const kpi = { current: 75, target: 100 }
197
- * const progress = Goals.progress(kpi) // 0.75
204
+ * const progress = defineGoals.progress(kpi) // 0.75
198
205
  * ```
199
206
  */
200
- Goals.progress = (kpi: Pick<KPI, 'current' | 'target'>): number => {
201
- if (kpi.target === 0) return 0
202
- return Math.min(1, Math.max(0, kpi.current / kpi.target))
207
+ defineGoals.progress = (kpi: Pick<WorkerKPI, 'current' | 'target'>): number => {
208
+ return calculateProgress(kpi)
203
209
  }
204
210
 
205
211
  /**
@@ -212,9 +218,12 @@ Goals.progress = (kpi: Pick<KPI, 'current' | 'target'>): number => {
212
218
  * @example
213
219
  * ```ts
214
220
  * const kpi = { current: 85, target: 100 }
215
- * const onTrack = Goals.onTrack(kpi) // true (85% >= 80% threshold)
221
+ * const onTrack = defineGoals.onTrack(kpi) // true (85% >= 80% threshold)
216
222
  * ```
217
223
  */
218
- Goals.onTrack = (kpi: Pick<KPI, 'current' | 'target'>, threshold = 0.8): boolean => {
219
- return Goals.progress(kpi) >= threshold
224
+ defineGoals.onTrack = (kpi: Pick<WorkerKPI, 'current' | 'target'>, threshold = 0.8): boolean => {
225
+ return isOnTrack(kpi, threshold)
220
226
  }
227
+
228
+ // Legacy alias for backward compatibility
229
+ export { defineGoals as Goals }