@vertesia/common 0.81.1 → 1.0.0-dev.20260203.130115Z

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 (301) hide show
  1. package/package.json +5 -5
  2. package/src/analytics.ts +5 -2
  3. package/src/apikey.ts +20 -1
  4. package/src/apps.ts +269 -4
  5. package/src/ask-user.ts +35 -0
  6. package/src/channels.ts +70 -0
  7. package/src/data-platform.ts +976 -0
  8. package/src/email.ts +80 -0
  9. package/src/index.ts +7 -1
  10. package/src/integrations.ts +34 -0
  11. package/src/interaction.ts +280 -1
  12. package/src/pending-asks.ts +106 -0
  13. package/src/project.ts +90 -1
  14. package/src/prompt.ts +2 -1
  15. package/src/skill.ts +1 -0
  16. package/src/store/conversation-state.ts +152 -0
  17. package/src/store/dsl-workflow.ts +12 -0
  18. package/src/store/hive-memory.ts +167 -0
  19. package/src/store/index.ts +3 -0
  20. package/src/store/schedule.ts +238 -0
  21. package/src/store/signals.ts +20 -0
  22. package/src/store/store.ts +124 -0
  23. package/src/store/workflow.test.ts +578 -0
  24. package/src/store/workflow.ts +612 -53
  25. package/src/tool-execution.ts +47 -0
  26. package/src/user.ts +14 -1
  27. package/src/workflow-analytics.ts +925 -0
  28. package/lib/cjs/Progress.js +0 -61
  29. package/lib/cjs/Progress.js.map +0 -1
  30. package/lib/cjs/access-control.js +0 -56
  31. package/lib/cjs/access-control.js.map +0 -1
  32. package/lib/cjs/analytics.js +0 -3
  33. package/lib/cjs/analytics.js.map +0 -1
  34. package/lib/cjs/apikey.js +0 -16
  35. package/lib/cjs/apikey.js.map +0 -1
  36. package/lib/cjs/apps.js +0 -3
  37. package/lib/cjs/apps.js.map +0 -1
  38. package/lib/cjs/common.js +0 -3
  39. package/lib/cjs/common.js.map +0 -1
  40. package/lib/cjs/environment.js +0 -44
  41. package/lib/cjs/environment.js.map +0 -1
  42. package/lib/cjs/facets.js +0 -3
  43. package/lib/cjs/facets.js.map +0 -1
  44. package/lib/cjs/group.js +0 -5
  45. package/lib/cjs/group.js.map +0 -1
  46. package/lib/cjs/index.js +0 -49
  47. package/lib/cjs/index.js.map +0 -1
  48. package/lib/cjs/integrations.js +0 -12
  49. package/lib/cjs/integrations.js.map +0 -1
  50. package/lib/cjs/interaction.js +0 -74
  51. package/lib/cjs/interaction.js.map +0 -1
  52. package/lib/cjs/json-schema.js +0 -3
  53. package/lib/cjs/json-schema.js.map +0 -1
  54. package/lib/cjs/json.js +0 -3
  55. package/lib/cjs/json.js.map +0 -1
  56. package/lib/cjs/meters.js +0 -13
  57. package/lib/cjs/meters.js.map +0 -1
  58. package/lib/cjs/model_utility.js +0 -6
  59. package/lib/cjs/model_utility.js.map +0 -1
  60. package/lib/cjs/package.json +0 -3
  61. package/lib/cjs/payload.js +0 -3
  62. package/lib/cjs/payload.js.map +0 -1
  63. package/lib/cjs/project.js +0 -107
  64. package/lib/cjs/project.js.map +0 -1
  65. package/lib/cjs/prompt.js +0 -20
  66. package/lib/cjs/prompt.js.map +0 -1
  67. package/lib/cjs/query.js +0 -3
  68. package/lib/cjs/query.js.map +0 -1
  69. package/lib/cjs/rate-limiter.js +0 -6
  70. package/lib/cjs/rate-limiter.js.map +0 -1
  71. package/lib/cjs/refs.js +0 -14
  72. package/lib/cjs/refs.js.map +0 -1
  73. package/lib/cjs/runs.js +0 -3
  74. package/lib/cjs/runs.js.map +0 -1
  75. package/lib/cjs/skill.js +0 -14
  76. package/lib/cjs/skill.js.map +0 -1
  77. package/lib/cjs/store/activity-catalog.js +0 -3
  78. package/lib/cjs/store/activity-catalog.js.map +0 -1
  79. package/lib/cjs/store/collections.js +0 -9
  80. package/lib/cjs/store/collections.js.map +0 -1
  81. package/lib/cjs/store/common.js +0 -3
  82. package/lib/cjs/store/common.js.map +0 -1
  83. package/lib/cjs/store/doc-analyzer.js +0 -3
  84. package/lib/cjs/store/doc-analyzer.js.map +0 -1
  85. package/lib/cjs/store/dsl-workflow.js +0 -5
  86. package/lib/cjs/store/dsl-workflow.js.map +0 -1
  87. package/lib/cjs/store/index.js +0 -28
  88. package/lib/cjs/store/index.js.map +0 -1
  89. package/lib/cjs/store/object-types.js +0 -98
  90. package/lib/cjs/store/object-types.js.map +0 -1
  91. package/lib/cjs/store/signals.js +0 -3
  92. package/lib/cjs/store/signals.js.map +0 -1
  93. package/lib/cjs/store/store.js +0 -55
  94. package/lib/cjs/store/store.js.map +0 -1
  95. package/lib/cjs/store/temporalio.js +0 -44
  96. package/lib/cjs/store/temporalio.js.map +0 -1
  97. package/lib/cjs/store/worker.js +0 -3
  98. package/lib/cjs/store/worker.js.map +0 -1
  99. package/lib/cjs/store/workflow.js +0 -49
  100. package/lib/cjs/store/workflow.js.map +0 -1
  101. package/lib/cjs/sts-token-types.js +0 -32
  102. package/lib/cjs/sts-token-types.js.map +0 -1
  103. package/lib/cjs/tenant.js +0 -3
  104. package/lib/cjs/tenant.js.map +0 -1
  105. package/lib/cjs/training.js +0 -14
  106. package/lib/cjs/training.js.map +0 -1
  107. package/lib/cjs/transient-tokens.js +0 -9
  108. package/lib/cjs/transient-tokens.js.map +0 -1
  109. package/lib/cjs/user.js +0 -25
  110. package/lib/cjs/user.js.map +0 -1
  111. package/lib/cjs/utils/auth.js +0 -15
  112. package/lib/cjs/utils/auth.js.map +0 -1
  113. package/lib/cjs/utils/schemas.js +0 -114
  114. package/lib/cjs/utils/schemas.js.map +0 -1
  115. package/lib/cjs/utils/type-helpers.js +0 -3
  116. package/lib/cjs/utils/type-helpers.js.map +0 -1
  117. package/lib/cjs/versions.js +0 -8
  118. package/lib/cjs/versions.js.map +0 -1
  119. package/lib/esm/Progress.js +0 -57
  120. package/lib/esm/Progress.js.map +0 -1
  121. package/lib/esm/access-control.js +0 -53
  122. package/lib/esm/access-control.js.map +0 -1
  123. package/lib/esm/analytics.js +0 -2
  124. package/lib/esm/analytics.js.map +0 -1
  125. package/lib/esm/apikey.js +0 -13
  126. package/lib/esm/apikey.js.map +0 -1
  127. package/lib/esm/apps.js +0 -2
  128. package/lib/esm/apps.js.map +0 -1
  129. package/lib/esm/common.js +0 -2
  130. package/lib/esm/common.js.map +0 -1
  131. package/lib/esm/environment.js +0 -41
  132. package/lib/esm/environment.js.map +0 -1
  133. package/lib/esm/facets.js +0 -2
  134. package/lib/esm/facets.js.map +0 -1
  135. package/lib/esm/group.js +0 -2
  136. package/lib/esm/group.js.map +0 -1
  137. package/lib/esm/index.js +0 -33
  138. package/lib/esm/index.js.map +0 -1
  139. package/lib/esm/integrations.js +0 -9
  140. package/lib/esm/integrations.js.map +0 -1
  141. package/lib/esm/interaction.js +0 -71
  142. package/lib/esm/interaction.js.map +0 -1
  143. package/lib/esm/json-schema.js +0 -2
  144. package/lib/esm/json-schema.js.map +0 -1
  145. package/lib/esm/json.js +0 -2
  146. package/lib/esm/json.js.map +0 -1
  147. package/lib/esm/meters.js +0 -10
  148. package/lib/esm/meters.js.map +0 -1
  149. package/lib/esm/model_utility.js +0 -2
  150. package/lib/esm/model_utility.js.map +0 -1
  151. package/lib/esm/payload.js +0 -2
  152. package/lib/esm/payload.js.map +0 -1
  153. package/lib/esm/project.js +0 -102
  154. package/lib/esm/project.js.map +0 -1
  155. package/lib/esm/prompt.js +0 -17
  156. package/lib/esm/prompt.js.map +0 -1
  157. package/lib/esm/query.js +0 -2
  158. package/lib/esm/query.js.map +0 -1
  159. package/lib/esm/rate-limiter.js +0 -5
  160. package/lib/esm/rate-limiter.js.map +0 -1
  161. package/lib/esm/refs.js +0 -11
  162. package/lib/esm/refs.js.map +0 -1
  163. package/lib/esm/runs.js +0 -2
  164. package/lib/esm/runs.js.map +0 -1
  165. package/lib/esm/skill.js +0 -13
  166. package/lib/esm/skill.js.map +0 -1
  167. package/lib/esm/store/activity-catalog.js +0 -2
  168. package/lib/esm/store/activity-catalog.js.map +0 -1
  169. package/lib/esm/store/collections.js +0 -6
  170. package/lib/esm/store/collections.js.map +0 -1
  171. package/lib/esm/store/common.js +0 -2
  172. package/lib/esm/store/common.js.map +0 -1
  173. package/lib/esm/store/doc-analyzer.js +0 -2
  174. package/lib/esm/store/doc-analyzer.js.map +0 -1
  175. package/lib/esm/store/dsl-workflow.js +0 -2
  176. package/lib/esm/store/dsl-workflow.js.map +0 -1
  177. package/lib/esm/store/index.js +0 -12
  178. package/lib/esm/store/index.js.map +0 -1
  179. package/lib/esm/store/object-types.js +0 -95
  180. package/lib/esm/store/object-types.js.map +0 -1
  181. package/lib/esm/store/signals.js +0 -2
  182. package/lib/esm/store/signals.js.map +0 -1
  183. package/lib/esm/store/store.js +0 -52
  184. package/lib/esm/store/store.js.map +0 -1
  185. package/lib/esm/store/temporalio.js +0 -41
  186. package/lib/esm/store/temporalio.js.map +0 -1
  187. package/lib/esm/store/worker.js +0 -2
  188. package/lib/esm/store/worker.js.map +0 -1
  189. package/lib/esm/store/workflow.js +0 -45
  190. package/lib/esm/store/workflow.js.map +0 -1
  191. package/lib/esm/sts-token-types.js +0 -24
  192. package/lib/esm/sts-token-types.js.map +0 -1
  193. package/lib/esm/tenant.js +0 -2
  194. package/lib/esm/tenant.js.map +0 -1
  195. package/lib/esm/training.js +0 -11
  196. package/lib/esm/training.js.map +0 -1
  197. package/lib/esm/transient-tokens.js +0 -6
  198. package/lib/esm/transient-tokens.js.map +0 -1
  199. package/lib/esm/user.js +0 -22
  200. package/lib/esm/user.js.map +0 -1
  201. package/lib/esm/utils/auth.js +0 -11
  202. package/lib/esm/utils/auth.js.map +0 -1
  203. package/lib/esm/utils/schemas.js +0 -107
  204. package/lib/esm/utils/schemas.js.map +0 -1
  205. package/lib/esm/utils/type-helpers.js +0 -2
  206. package/lib/esm/utils/type-helpers.js.map +0 -1
  207. package/lib/esm/versions.js +0 -5
  208. package/lib/esm/versions.js.map +0 -1
  209. package/lib/tsconfig.tsbuildinfo +0 -1
  210. package/lib/types/Progress.d.ts +0 -21
  211. package/lib/types/Progress.d.ts.map +0 -1
  212. package/lib/types/access-control.d.ts +0 -73
  213. package/lib/types/access-control.d.ts.map +0 -1
  214. package/lib/types/analytics.d.ts +0 -85
  215. package/lib/types/analytics.d.ts.map +0 -1
  216. package/lib/types/apikey.d.ts +0 -80
  217. package/lib/types/apikey.d.ts.map +0 -1
  218. package/lib/types/apps.d.ts +0 -102
  219. package/lib/types/apps.d.ts.map +0 -1
  220. package/lib/types/common.d.ts +0 -31
  221. package/lib/types/common.d.ts.map +0 -1
  222. package/lib/types/environment.d.ts +0 -106
  223. package/lib/types/environment.d.ts.map +0 -1
  224. package/lib/types/facets.d.ts +0 -34
  225. package/lib/types/facets.d.ts.map +0 -1
  226. package/lib/types/group.d.ts +0 -21
  227. package/lib/types/group.d.ts.map +0 -1
  228. package/lib/types/index.d.ts +0 -33
  229. package/lib/types/index.d.ts.map +0 -1
  230. package/lib/types/integrations.d.ts +0 -28
  231. package/lib/types/integrations.d.ts.map +0 -1
  232. package/lib/types/interaction.d.ts +0 -727
  233. package/lib/types/interaction.d.ts.map +0 -1
  234. package/lib/types/json-schema.d.ts +0 -1
  235. package/lib/types/json-schema.d.ts.map +0 -1
  236. package/lib/types/json.d.ts +0 -1
  237. package/lib/types/json.d.ts.map +0 -1
  238. package/lib/types/meters.d.ts +0 -23
  239. package/lib/types/meters.d.ts.map +0 -1
  240. package/lib/types/model_utility.d.ts +0 -1
  241. package/lib/types/model_utility.d.ts.map +0 -1
  242. package/lib/types/payload.d.ts +0 -60
  243. package/lib/types/payload.d.ts.map +0 -1
  244. package/lib/types/project.d.ts +0 -173
  245. package/lib/types/project.d.ts.map +0 -1
  246. package/lib/types/prompt.d.ts +0 -77
  247. package/lib/types/prompt.d.ts.map +0 -1
  248. package/lib/types/query.d.ts +0 -118
  249. package/lib/types/query.d.ts.map +0 -1
  250. package/lib/types/rate-limiter.d.ts +0 -28
  251. package/lib/types/rate-limiter.d.ts.map +0 -1
  252. package/lib/types/refs.d.ts +0 -22
  253. package/lib/types/refs.d.ts.map +0 -1
  254. package/lib/types/runs.d.ts +0 -32
  255. package/lib/types/runs.d.ts.map +0 -1
  256. package/lib/types/skill.d.ts +0 -78
  257. package/lib/types/skill.d.ts.map +0 -1
  258. package/lib/types/store/activity-catalog.d.ts +0 -26
  259. package/lib/types/store/activity-catalog.d.ts.map +0 -1
  260. package/lib/types/store/collections.d.ts +0 -78
  261. package/lib/types/store/collections.d.ts.map +0 -1
  262. package/lib/types/store/common.d.ts +0 -22
  263. package/lib/types/store/common.d.ts.map +0 -1
  264. package/lib/types/store/doc-analyzer.d.ts +0 -140
  265. package/lib/types/store/doc-analyzer.d.ts.map +0 -1
  266. package/lib/types/store/dsl-workflow.d.ts +0 -238
  267. package/lib/types/store/dsl-workflow.d.ts.map +0 -1
  268. package/lib/types/store/index.d.ts +0 -11
  269. package/lib/types/store/index.d.ts.map +0 -1
  270. package/lib/types/store/object-types.d.ts +0 -23
  271. package/lib/types/store/object-types.d.ts.map +0 -1
  272. package/lib/types/store/signals.d.ts +0 -5
  273. package/lib/types/store/signals.d.ts.map +0 -1
  274. package/lib/types/store/store.d.ts +0 -358
  275. package/lib/types/store/store.d.ts.map +0 -1
  276. package/lib/types/store/temporalio.d.ts +0 -16
  277. package/lib/types/store/temporalio.d.ts.map +0 -1
  278. package/lib/types/store/worker.d.ts +0 -18
  279. package/lib/types/store/worker.d.ts.map +0 -1
  280. package/lib/types/store/workflow.d.ts +0 -439
  281. package/lib/types/store/workflow.d.ts.map +0 -1
  282. package/lib/types/sts-token-types.d.ts +0 -72
  283. package/lib/types/sts-token-types.d.ts.map +0 -1
  284. package/lib/types/tenant.d.ts +0 -10
  285. package/lib/types/tenant.d.ts.map +0 -1
  286. package/lib/types/training.d.ts +0 -38
  287. package/lib/types/training.d.ts.map +0 -1
  288. package/lib/types/transient-tokens.d.ts +0 -24
  289. package/lib/types/transient-tokens.d.ts.map +0 -1
  290. package/lib/types/user.d.ts +0 -116
  291. package/lib/types/user.d.ts.map +0 -1
  292. package/lib/types/utils/auth.d.ts +0 -3
  293. package/lib/types/utils/auth.d.ts.map +0 -1
  294. package/lib/types/utils/schemas.d.ts +0 -9
  295. package/lib/types/utils/schemas.d.ts.map +0 -1
  296. package/lib/types/utils/type-helpers.d.ts +0 -3
  297. package/lib/types/utils/type-helpers.d.ts.map +0 -1
  298. package/lib/types/versions.d.ts +0 -3
  299. package/lib/types/versions.d.ts.map +0 -1
  300. package/lib/vertesia-common.js +0 -2
  301. package/lib/vertesia-common.js.map +0 -1
@@ -0,0 +1,578 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import {
3
+ AgentMessageType,
4
+ AgentMessage,
5
+ CompactMessage,
6
+ normalizeMessageType,
7
+ toCompactMessage,
8
+ toAgentMessage,
9
+ parseMessage,
10
+ isCompactMessage,
11
+ isLegacyMessage,
12
+ createCompactMessage,
13
+ } from './workflow.js';
14
+
15
+ describe('CompactMessage converters', () => {
16
+ describe('normalizeMessageType', () => {
17
+ it('handles integer values (current format)', () => {
18
+ expect(normalizeMessageType(0)).toBe(AgentMessageType.SYSTEM);
19
+ expect(normalizeMessageType(1)).toBe(AgentMessageType.THOUGHT);
20
+ expect(normalizeMessageType(2)).toBe(AgentMessageType.PLAN);
21
+ expect(normalizeMessageType(3)).toBe(AgentMessageType.UPDATE);
22
+ expect(normalizeMessageType(4)).toBe(AgentMessageType.COMPLETE);
23
+ expect(normalizeMessageType(5)).toBe(AgentMessageType.WARNING);
24
+ expect(normalizeMessageType(6)).toBe(AgentMessageType.ERROR);
25
+ expect(normalizeMessageType(7)).toBe(AgentMessageType.ANSWER);
26
+ expect(normalizeMessageType(8)).toBe(AgentMessageType.QUESTION);
27
+ expect(normalizeMessageType(9)).toBe(AgentMessageType.REQUEST_INPUT);
28
+ expect(normalizeMessageType(10)).toBe(AgentMessageType.IDLE);
29
+ expect(normalizeMessageType(11)).toBe(AgentMessageType.TERMINATED);
30
+ expect(normalizeMessageType(12)).toBe(AgentMessageType.STREAMING_CHUNK);
31
+ expect(normalizeMessageType(13)).toBe(AgentMessageType.BATCH_PROGRESS);
32
+ });
33
+
34
+ it('handles string values (legacy format)', () => {
35
+ expect(normalizeMessageType('system')).toBe(AgentMessageType.SYSTEM);
36
+ expect(normalizeMessageType('thought')).toBe(AgentMessageType.THOUGHT);
37
+ expect(normalizeMessageType('plan')).toBe(AgentMessageType.PLAN);
38
+ expect(normalizeMessageType('update')).toBe(AgentMessageType.UPDATE);
39
+ expect(normalizeMessageType('complete')).toBe(AgentMessageType.COMPLETE);
40
+ expect(normalizeMessageType('warning')).toBe(AgentMessageType.WARNING);
41
+ expect(normalizeMessageType('error')).toBe(AgentMessageType.ERROR);
42
+ expect(normalizeMessageType('answer')).toBe(AgentMessageType.ANSWER);
43
+ expect(normalizeMessageType('question')).toBe(AgentMessageType.QUESTION);
44
+ expect(normalizeMessageType('request_input')).toBe(AgentMessageType.REQUEST_INPUT);
45
+ expect(normalizeMessageType('idle')).toBe(AgentMessageType.IDLE);
46
+ expect(normalizeMessageType('terminated')).toBe(AgentMessageType.TERMINATED);
47
+ expect(normalizeMessageType('streaming_chunk')).toBe(AgentMessageType.STREAMING_CHUNK);
48
+ expect(normalizeMessageType('batch_progress')).toBe(AgentMessageType.BATCH_PROGRESS);
49
+ });
50
+
51
+ it('handles AgentMessageType enum values', () => {
52
+ expect(normalizeMessageType(AgentMessageType.SYSTEM)).toBe(AgentMessageType.SYSTEM);
53
+ expect(normalizeMessageType(AgentMessageType.ERROR)).toBe(AgentMessageType.ERROR);
54
+ expect(normalizeMessageType(AgentMessageType.ANSWER)).toBe(AgentMessageType.ANSWER);
55
+ });
56
+
57
+ it('returns UPDATE for unknown values', () => {
58
+ expect(normalizeMessageType(999)).toBe(AgentMessageType.UPDATE);
59
+ expect(normalizeMessageType('unknown')).toBe(AgentMessageType.UPDATE);
60
+ });
61
+ });
62
+
63
+ describe('isCompactMessage', () => {
64
+ it('returns true for compact messages', () => {
65
+ expect(isCompactMessage({ t: AgentMessageType.UPDATE })).toBe(true);
66
+ expect(isCompactMessage({ t: 0, m: 'test' })).toBe(true);
67
+ });
68
+
69
+ it('returns false for non-compact messages', () => {
70
+ expect(isCompactMessage({ type: AgentMessageType.UPDATE })).toBe(false);
71
+ expect(isCompactMessage(null)).toBe(false);
72
+ expect(isCompactMessage(undefined)).toBe(false);
73
+ expect(isCompactMessage('string')).toBe(false);
74
+ expect(isCompactMessage(123)).toBe(false);
75
+ });
76
+ });
77
+
78
+ describe('isLegacyMessage', () => {
79
+ it('returns true for legacy messages', () => {
80
+ expect(isLegacyMessage({ type: AgentMessageType.UPDATE })).toBe(true);
81
+ expect(isLegacyMessage({
82
+ type: AgentMessageType.ANSWER,
83
+ timestamp: 12345,
84
+ workflow_run_id: 'run-1',
85
+ message: 'test'
86
+ })).toBe(true);
87
+ });
88
+
89
+ it('returns false for compact messages', () => {
90
+ expect(isLegacyMessage({ t: AgentMessageType.UPDATE })).toBe(false);
91
+ // Has both type and t - compact takes precedence
92
+ expect(isLegacyMessage({ type: AgentMessageType.UPDATE, t: AgentMessageType.UPDATE })).toBe(false);
93
+ });
94
+
95
+ it('returns false for non-messages', () => {
96
+ expect(isLegacyMessage(null)).toBe(false);
97
+ expect(isLegacyMessage(undefined)).toBe(false);
98
+ expect(isLegacyMessage({})).toBe(false);
99
+ });
100
+ });
101
+
102
+ describe('toCompactMessage', () => {
103
+ it('converts basic legacy message', () => {
104
+ const legacy: AgentMessage = {
105
+ type: AgentMessageType.UPDATE,
106
+ timestamp: 1234567890,
107
+ workflow_run_id: 'run-123',
108
+ message: 'Test message',
109
+ };
110
+
111
+ const compact = toCompactMessage(legacy);
112
+
113
+ expect(compact.t).toBe(AgentMessageType.UPDATE);
114
+ expect(compact.m).toBe('Test message');
115
+ expect(compact.ts).toBe(1234567890);
116
+ expect(compact.w).toBeUndefined(); // main is default, not included
117
+ });
118
+
119
+ it('includes workstream_id when not main', () => {
120
+ const legacy: AgentMessage = {
121
+ type: AgentMessageType.THOUGHT,
122
+ timestamp: 1234567890,
123
+ workflow_run_id: 'run-123',
124
+ message: 'Thinking...',
125
+ workstream_id: 'research',
126
+ };
127
+
128
+ const compact = toCompactMessage(legacy);
129
+
130
+ expect(compact.w).toBe('research');
131
+ });
132
+
133
+ it('excludes workstream_id when main', () => {
134
+ const legacy: AgentMessage = {
135
+ type: AgentMessageType.UPDATE,
136
+ timestamp: 1234567890,
137
+ workflow_run_id: 'run-123',
138
+ message: 'Update',
139
+ workstream_id: 'main',
140
+ };
141
+
142
+ const compact = toCompactMessage(legacy);
143
+
144
+ expect(compact.w).toBeUndefined();
145
+ });
146
+
147
+ it('includes details for non-streaming messages', () => {
148
+ const legacy: AgentMessage = {
149
+ type: AgentMessageType.PLAN,
150
+ timestamp: 1234567890,
151
+ workflow_run_id: 'run-123',
152
+ message: 'Plan created',
153
+ details: { plan: [{ id: 1, goal: 'Step 1' }] },
154
+ };
155
+
156
+ const compact = toCompactMessage(legacy);
157
+
158
+ expect(compact.d).toEqual({ plan: [{ id: 1, goal: 'Step 1' }] });
159
+ });
160
+
161
+ it('handles streaming chunk with is_final flag', () => {
162
+ const legacy: AgentMessage = {
163
+ type: AgentMessageType.STREAMING_CHUNK,
164
+ timestamp: 1234567890,
165
+ workflow_run_id: 'run-123',
166
+ message: 'chunk content',
167
+ details: {
168
+ streaming_id: 'stream-1',
169
+ chunk_index: 5,
170
+ is_final: true,
171
+ },
172
+ };
173
+
174
+ const compact = toCompactMessage(legacy);
175
+
176
+ expect(compact.t).toBe(AgentMessageType.STREAMING_CHUNK);
177
+ expect(compact.m).toBe('chunk content');
178
+ expect(compact.f).toBe(1);
179
+ expect(compact.d).toBeUndefined(); // streaming_id and chunk_index removed
180
+ });
181
+
182
+ it('handles streaming chunk without is_final', () => {
183
+ const legacy: AgentMessage = {
184
+ type: AgentMessageType.STREAMING_CHUNK,
185
+ timestamp: 1234567890,
186
+ workflow_run_id: 'run-123',
187
+ message: 'chunk content',
188
+ details: {
189
+ streaming_id: 'stream-1',
190
+ chunk_index: 2,
191
+ is_final: false,
192
+ },
193
+ };
194
+
195
+ const compact = toCompactMessage(legacy);
196
+
197
+ expect(compact.f).toBeUndefined();
198
+ });
199
+
200
+ it('normalizes legacy string type values', () => {
201
+ // Simulate a message from Redis with old string type
202
+ const legacy = {
203
+ type: 'answer' as unknown as AgentMessageType,
204
+ timestamp: 1234567890,
205
+ workflow_run_id: 'run-123',
206
+ message: 'Response',
207
+ };
208
+
209
+ const compact = toCompactMessage(legacy);
210
+
211
+ expect(compact.t).toBe(AgentMessageType.ANSWER);
212
+ });
213
+
214
+ it('omits empty/undefined fields', () => {
215
+ const legacy: AgentMessage = {
216
+ type: AgentMessageType.IDLE,
217
+ timestamp: 0,
218
+ workflow_run_id: 'run-123',
219
+ message: '',
220
+ };
221
+
222
+ const compact = toCompactMessage(legacy);
223
+
224
+ expect(compact).toEqual({ t: AgentMessageType.IDLE });
225
+ expect(Object.keys(compact)).toEqual(['t']);
226
+ });
227
+ });
228
+
229
+ describe('toAgentMessage', () => {
230
+ it('converts compact message to legacy format', () => {
231
+ const compact: CompactMessage = {
232
+ t: AgentMessageType.ANSWER,
233
+ m: 'Hello world',
234
+ ts: 1234567890,
235
+ };
236
+
237
+ const legacy = toAgentMessage(compact, 'run-456');
238
+
239
+ expect(legacy.type).toBe(AgentMessageType.ANSWER);
240
+ expect(legacy.message).toBe('Hello world');
241
+ expect(legacy.timestamp).toBe(1234567890);
242
+ expect(legacy.workflow_run_id).toBe('run-456');
243
+ expect(legacy.workstream_id).toBe('main');
244
+ });
245
+
246
+ it('restores workstream_id', () => {
247
+ const compact: CompactMessage = {
248
+ t: AgentMessageType.UPDATE,
249
+ m: 'Working...',
250
+ w: 'analysis',
251
+ };
252
+
253
+ const legacy = toAgentMessage(compact, 'run-789');
254
+
255
+ expect(legacy.workstream_id).toBe('analysis');
256
+ });
257
+
258
+ it('provides defaults for missing fields', () => {
259
+ const compact: CompactMessage = {
260
+ t: AgentMessageType.SYSTEM,
261
+ };
262
+
263
+ const legacy = toAgentMessage(compact);
264
+
265
+ expect(legacy.message).toBe('');
266
+ expect(legacy.workflow_run_id).toBe('');
267
+ expect(legacy.workstream_id).toBe('main');
268
+ expect(legacy.timestamp).toBeGreaterThan(0); // Uses Date.now()
269
+ });
270
+
271
+ it('restores details', () => {
272
+ const compact: CompactMessage = {
273
+ t: AgentMessageType.BATCH_PROGRESS,
274
+ m: 'Processing batch',
275
+ d: { batch_id: 'batch-1', completed: 5, total: 10 },
276
+ };
277
+
278
+ const legacy = toAgentMessage(compact, 'run-1');
279
+
280
+ expect(legacy.details).toEqual({ batch_id: 'batch-1', completed: 5, total: 10 });
281
+ });
282
+
283
+ it('restores streaming chunk details with is_final', () => {
284
+ const compact: CompactMessage = {
285
+ t: AgentMessageType.STREAMING_CHUNK,
286
+ m: 'chunk text',
287
+ w: 'stream-workstream',
288
+ f: 1,
289
+ };
290
+
291
+ const legacy = toAgentMessage(compact, 'run-1');
292
+
293
+ expect(legacy.details).toEqual({
294
+ streaming_id: 'stream-workstream',
295
+ is_final: true,
296
+ });
297
+ });
298
+
299
+ it('restores streaming chunk details without is_final', () => {
300
+ const compact: CompactMessage = {
301
+ t: AgentMessageType.STREAMING_CHUNK,
302
+ m: 'chunk text',
303
+ };
304
+
305
+ const legacy = toAgentMessage(compact, 'run-1');
306
+
307
+ expect(legacy.details).toEqual({
308
+ streaming_id: 'main',
309
+ is_final: false,
310
+ });
311
+ });
312
+ });
313
+
314
+ describe('parseMessage', () => {
315
+ it('parses compact message from object', () => {
316
+ const input: CompactMessage = { t: AgentMessageType.UPDATE, m: 'Test' };
317
+
318
+ const result = parseMessage(input);
319
+
320
+ expect(result).toEqual(input);
321
+ });
322
+
323
+ it('parses compact message from JSON string', () => {
324
+ const input = JSON.stringify({ t: AgentMessageType.ERROR, m: 'Error occurred' });
325
+
326
+ const result = parseMessage(input);
327
+
328
+ expect(result.t).toBe(AgentMessageType.ERROR);
329
+ expect(result.m).toBe('Error occurred');
330
+ });
331
+
332
+ it('converts legacy message object to compact', () => {
333
+ const legacy: AgentMessage = {
334
+ type: AgentMessageType.COMPLETE,
335
+ timestamp: 1234567890,
336
+ workflow_run_id: 'run-1',
337
+ message: 'Done!',
338
+ };
339
+
340
+ const result = parseMessage(legacy);
341
+
342
+ expect(isCompactMessage(result)).toBe(true);
343
+ expect(result.t).toBe(AgentMessageType.COMPLETE);
344
+ expect(result.m).toBe('Done!');
345
+ });
346
+
347
+ it('converts legacy message JSON string to compact', () => {
348
+ const legacy = JSON.stringify({
349
+ type: AgentMessageType.WARNING,
350
+ timestamp: 1234567890,
351
+ workflow_run_id: 'run-1',
352
+ message: 'Warning message',
353
+ });
354
+
355
+ const result = parseMessage(legacy);
356
+
357
+ expect(isCompactMessage(result)).toBe(true);
358
+ expect(result.t).toBe(AgentMessageType.WARNING);
359
+ });
360
+
361
+ it('throws error for unknown format', () => {
362
+ expect(() => parseMessage({})).toThrow('Unknown message format');
363
+ expect(() => parseMessage({ foo: 'bar' })).toThrow('Unknown message format');
364
+ });
365
+
366
+ it('throws error for invalid JSON', () => {
367
+ expect(() => parseMessage('not json')).toThrow();
368
+ });
369
+ });
370
+
371
+ describe('createCompactMessage', () => {
372
+ it('creates minimal compact message', () => {
373
+ const msg = createCompactMessage(AgentMessageType.IDLE);
374
+
375
+ expect(msg).toEqual({ t: AgentMessageType.IDLE });
376
+ });
377
+
378
+ it('creates compact message with all options', () => {
379
+ const msg = createCompactMessage(AgentMessageType.PLAN, {
380
+ message: 'Plan created',
381
+ workstreamId: 'planning',
382
+ details: { steps: 5 },
383
+ timestamp: 1234567890,
384
+ });
385
+
386
+ expect(msg).toEqual({
387
+ t: AgentMessageType.PLAN,
388
+ m: 'Plan created',
389
+ w: 'planning',
390
+ d: { steps: 5 },
391
+ ts: 1234567890,
392
+ });
393
+ });
394
+
395
+ it('excludes workstreamId when main', () => {
396
+ const msg = createCompactMessage(AgentMessageType.UPDATE, {
397
+ message: 'Update',
398
+ workstreamId: 'main',
399
+ });
400
+
401
+ expect(msg.w).toBeUndefined();
402
+ });
403
+
404
+ it('sets is_final flag for streaming chunks', () => {
405
+ const msg = createCompactMessage(AgentMessageType.STREAMING_CHUNK, {
406
+ message: 'final chunk',
407
+ isFinal: true,
408
+ });
409
+
410
+ expect(msg.f).toBe(1);
411
+ });
412
+ });
413
+
414
+ describe('round-trip conversion', () => {
415
+ it('legacy -> compact -> legacy preserves essential data', () => {
416
+ const original: AgentMessage = {
417
+ type: AgentMessageType.ANSWER,
418
+ timestamp: 1234567890,
419
+ workflow_run_id: 'run-abc',
420
+ message: 'This is a long response from the AI assistant.',
421
+ workstream_id: 'conversation',
422
+ details: { sources: ['doc1', 'doc2'] },
423
+ };
424
+
425
+ const compact = toCompactMessage(original);
426
+ const restored = toAgentMessage(compact, original.workflow_run_id);
427
+
428
+ expect(restored.type).toBe(original.type);
429
+ expect(restored.timestamp).toBe(original.timestamp);
430
+ expect(restored.workflow_run_id).toBe(original.workflow_run_id);
431
+ expect(restored.message).toBe(original.message);
432
+ expect(restored.workstream_id).toBe(original.workstream_id);
433
+ expect(restored.details).toEqual(original.details);
434
+ });
435
+
436
+ it('compact -> legacy -> compact preserves essential data', () => {
437
+ const original: CompactMessage = {
438
+ t: AgentMessageType.THOUGHT,
439
+ m: 'Analyzing the problem...',
440
+ w: 'reasoning',
441
+ d: { confidence: 0.85 },
442
+ ts: 1234567890,
443
+ };
444
+
445
+ const legacy = toAgentMessage(original, 'run-xyz');
446
+ const restored = toCompactMessage(legacy);
447
+
448
+ expect(restored.t).toBe(original.t);
449
+ expect(restored.m).toBe(original.m);
450
+ expect(restored.w).toBe(original.w);
451
+ expect(restored.d).toEqual(original.d);
452
+ expect(restored.ts).toBe(original.ts);
453
+ });
454
+
455
+ it('handles all message types in round-trip', () => {
456
+ const messageTypes = [
457
+ AgentMessageType.SYSTEM,
458
+ AgentMessageType.THOUGHT,
459
+ AgentMessageType.PLAN,
460
+ AgentMessageType.UPDATE,
461
+ AgentMessageType.COMPLETE,
462
+ AgentMessageType.WARNING,
463
+ AgentMessageType.ERROR,
464
+ AgentMessageType.ANSWER,
465
+ AgentMessageType.QUESTION,
466
+ AgentMessageType.REQUEST_INPUT,
467
+ AgentMessageType.IDLE,
468
+ AgentMessageType.TERMINATED,
469
+ AgentMessageType.BATCH_PROGRESS,
470
+ ];
471
+
472
+ for (const type of messageTypes) {
473
+ const original: AgentMessage = {
474
+ type,
475
+ timestamp: 1234567890,
476
+ workflow_run_id: 'run-test',
477
+ message: `Test message for type ${type}`,
478
+ };
479
+
480
+ const compact = toCompactMessage(original);
481
+ const restored = toAgentMessage(compact, original.workflow_run_id);
482
+
483
+ expect(restored.type).toBe(type);
484
+ expect(restored.message).toBe(original.message);
485
+ }
486
+ });
487
+
488
+ it('streaming chunk round-trip preserves is_final', () => {
489
+ const original: AgentMessage = {
490
+ type: AgentMessageType.STREAMING_CHUNK,
491
+ timestamp: 1234567890,
492
+ workflow_run_id: 'run-stream',
493
+ message: 'Final chunk content',
494
+ workstream_id: 'stream-1',
495
+ details: {
496
+ streaming_id: 'stream-1',
497
+ chunk_index: 10,
498
+ is_final: true,
499
+ },
500
+ };
501
+
502
+ const compact = toCompactMessage(original);
503
+ const restored = toAgentMessage(compact, original.workflow_run_id);
504
+
505
+ expect(restored.type).toBe(AgentMessageType.STREAMING_CHUNK);
506
+ expect(restored.details?.is_final).toBe(true);
507
+ expect(restored.details?.streaming_id).toBe(original.workstream_id);
508
+ });
509
+ });
510
+
511
+ describe('edge cases', () => {
512
+ it('handles unicode and special characters', () => {
513
+ const original: AgentMessage = {
514
+ type: AgentMessageType.ANSWER,
515
+ timestamp: 1234567890,
516
+ workflow_run_id: 'run-1',
517
+ message: 'Unicode: 你好世界 🎉 émojis & spëcial chars <script>alert(1)</script>',
518
+ };
519
+
520
+ const compact = toCompactMessage(original);
521
+ const restored = toAgentMessage(compact, original.workflow_run_id);
522
+
523
+ expect(restored.message).toBe(original.message);
524
+ });
525
+
526
+ it('handles very long messages', () => {
527
+ const longMessage = 'A'.repeat(100000);
528
+ const original: AgentMessage = {
529
+ type: AgentMessageType.ANSWER,
530
+ timestamp: 1234567890,
531
+ workflow_run_id: 'run-1',
532
+ message: longMessage,
533
+ };
534
+
535
+ const compact = toCompactMessage(original);
536
+ const restored = toAgentMessage(compact, original.workflow_run_id);
537
+
538
+ expect(restored.message).toBe(longMessage);
539
+ expect(restored.message.length).toBe(100000);
540
+ });
541
+
542
+ it('handles null-like values in details', () => {
543
+ const original: AgentMessage = {
544
+ type: AgentMessageType.UPDATE,
545
+ timestamp: 1234567890,
546
+ workflow_run_id: 'run-1',
547
+ message: 'Update',
548
+ details: { value: null, empty: '', zero: 0, bool: false },
549
+ };
550
+
551
+ const compact = toCompactMessage(original);
552
+ const restored = toAgentMessage(compact, original.workflow_run_id);
553
+
554
+ expect(restored.details).toEqual(original.details);
555
+ });
556
+
557
+ it('handles nested object details', () => {
558
+ const original: AgentMessage = {
559
+ type: AgentMessageType.PLAN,
560
+ timestamp: 1234567890,
561
+ workflow_run_id: 'run-1',
562
+ message: 'Plan',
563
+ details: {
564
+ plan: [
565
+ { id: 1, goal: 'Step 1', instructions: ['Do this', 'Then that'] },
566
+ { id: 2, goal: 'Step 2', instructions: ['Final step'] },
567
+ ],
568
+ metadata: { version: 1, author: 'agent' },
569
+ },
570
+ };
571
+
572
+ const compact = toCompactMessage(original);
573
+ const restored = toAgentMessage(compact, original.workflow_run_id);
574
+
575
+ expect(restored.details).toEqual(original.details);
576
+ });
577
+ });
578
+ });