@foresthubai/workflow-core 0.4.3 → 0.4.5

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 (298) hide show
  1. package/LICENSE +202 -202
  2. package/NOTICE +14 -14
  3. package/README.md +63 -63
  4. package/dist/api/deployment.d.ts +74 -0
  5. package/dist/api/deployment.d.ts.map +1 -0
  6. package/dist/api/deployment.js +6 -0
  7. package/dist/api/deployment.js.map +1 -0
  8. package/dist/api/engine.d.ts +744 -0
  9. package/dist/api/engine.d.ts.map +1 -0
  10. package/dist/api/engine.js +6 -0
  11. package/dist/api/engine.js.map +1 -0
  12. package/dist/api/index.d.ts +4 -0
  13. package/dist/api/index.d.ts.map +1 -1
  14. package/dist/api/index.js +2 -0
  15. package/dist/api/index.js.map +1 -1
  16. package/dist/api/workflow.d.ts +25 -9
  17. package/dist/api/workflow.d.ts.map +1 -1
  18. package/dist/channel/Channel.d.ts +1 -1
  19. package/dist/channel/Channel.d.ts.map +1 -1
  20. package/dist/channel/Channel.js +3 -1
  21. package/dist/channel/Channel.js.map +1 -1
  22. package/dist/channel/ChannelDefinition.d.ts.map +1 -1
  23. package/dist/channel/ChannelDefinition.js +24 -0
  24. package/dist/channel/ChannelDefinition.js.map +1 -1
  25. package/dist/channel/index.d.ts.map +1 -1
  26. package/dist/channel/index.js +2 -0
  27. package/dist/channel/index.js.map +1 -1
  28. package/dist/channel/serialization.d.ts.map +1 -1
  29. package/dist/channel/serialization.js +8 -0
  30. package/dist/channel/serialization.js.map +1 -1
  31. package/dist/deploy/index.d.ts +5 -1
  32. package/dist/deploy/index.d.ts.map +1 -1
  33. package/dist/deploy/index.js +4 -1
  34. package/dist/deploy/index.js.map +1 -1
  35. package/dist/deploy/inputs.d.ts +26 -0
  36. package/dist/deploy/inputs.d.ts.map +1 -0
  37. package/dist/deploy/inputs.js +4 -0
  38. package/dist/deploy/inputs.js.map +1 -0
  39. package/dist/deploy/requirements.d.ts +24 -0
  40. package/dist/deploy/requirements.d.ts.map +1 -1
  41. package/dist/deploy/requirements.js +63 -0
  42. package/dist/deploy/requirements.js.map +1 -1
  43. package/dist/deploy/spec.d.ts +27 -0
  44. package/dist/deploy/spec.d.ts.map +1 -0
  45. package/dist/deploy/spec.js +352 -0
  46. package/dist/deploy/spec.js.map +1 -0
  47. package/dist/diagnostics/__fixtures__/diagnosticFixtures.d.ts.map +1 -1
  48. package/dist/diagnostics/__fixtures__/diagnosticFixtures.js +2 -0
  49. package/dist/diagnostics/__fixtures__/diagnosticFixtures.js.map +1 -1
  50. package/dist/diagnostics/diagnostics.d.ts.map +1 -1
  51. package/dist/diagnostics/diagnostics.js +2 -0
  52. package/dist/diagnostics/diagnostics.js.map +1 -1
  53. package/dist/diagnostics/index.d.ts.map +1 -1
  54. package/dist/diagnostics/index.js +2 -0
  55. package/dist/diagnostics/index.js.map +1 -1
  56. package/dist/edge/Edge.d.ts.map +1 -1
  57. package/dist/edge/Edge.js +2 -0
  58. package/dist/edge/Edge.js.map +1 -1
  59. package/dist/edge/EdgeDefinition.d.ts.map +1 -1
  60. package/dist/edge/EdgeDefinition.js +2 -0
  61. package/dist/edge/EdgeDefinition.js.map +1 -1
  62. package/dist/edge/EdgeType.d.ts.map +1 -1
  63. package/dist/edge/EdgeType.js +2 -0
  64. package/dist/edge/EdgeType.js.map +1 -1
  65. package/dist/edge/index.d.ts.map +1 -1
  66. package/dist/edge/index.js +2 -2
  67. package/dist/edge/index.js.map +1 -1
  68. package/dist/edge/serialization.d.ts.map +1 -1
  69. package/dist/edge/serialization.js +2 -0
  70. package/dist/edge/serialization.js.map +1 -1
  71. package/dist/expression/index.d.ts.map +1 -1
  72. package/dist/expression/index.js +2 -0
  73. package/dist/expression/index.js.map +1 -1
  74. package/dist/expression/parser.d.ts.map +1 -1
  75. package/dist/expression/parser.js +2 -0
  76. package/dist/expression/parser.js.map +1 -1
  77. package/dist/expression/types.d.ts.map +1 -1
  78. package/dist/expression/types.js +2 -0
  79. package/dist/expression/types.js.map +1 -1
  80. package/dist/function/FunctionDeclaration.d.ts.map +1 -1
  81. package/dist/function/FunctionDeclaration.js +2 -0
  82. package/dist/function/FunctionDeclaration.js.map +1 -1
  83. package/dist/function/index.d.ts.map +1 -1
  84. package/dist/function/index.js +2 -0
  85. package/dist/function/index.js.map +1 -1
  86. package/dist/function/serialization.d.ts.map +1 -1
  87. package/dist/function/serialization.js +2 -0
  88. package/dist/function/serialization.js.map +1 -1
  89. package/dist/id/index.d.ts.map +1 -1
  90. package/dist/id/index.js +2 -0
  91. package/dist/id/index.js.map +1 -1
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +2 -0
  94. package/dist/index.js.map +1 -1
  95. package/dist/memory/Memory.d.ts.map +1 -1
  96. package/dist/memory/Memory.js +2 -0
  97. package/dist/memory/Memory.js.map +1 -1
  98. package/dist/memory/MemoryDefinition.d.ts.map +1 -1
  99. package/dist/memory/MemoryDefinition.js +2 -0
  100. package/dist/memory/MemoryDefinition.js.map +1 -1
  101. package/dist/memory/MemoryFileDefinition.d.ts.map +1 -1
  102. package/dist/memory/MemoryFileDefinition.js +2 -0
  103. package/dist/memory/MemoryFileDefinition.js.map +1 -1
  104. package/dist/memory/MemoryRegistry.d.ts.map +1 -1
  105. package/dist/memory/MemoryRegistry.js +2 -0
  106. package/dist/memory/MemoryRegistry.js.map +1 -1
  107. package/dist/memory/VectorDatabaseDefinition.d.ts.map +1 -1
  108. package/dist/memory/VectorDatabaseDefinition.js +2 -0
  109. package/dist/memory/VectorDatabaseDefinition.js.map +1 -1
  110. package/dist/memory/index.d.ts.map +1 -1
  111. package/dist/memory/index.js +2 -0
  112. package/dist/memory/index.js.map +1 -1
  113. package/dist/memory/serialization.d.ts.map +1 -1
  114. package/dist/memory/serialization.js +2 -0
  115. package/dist/memory/serialization.js.map +1 -1
  116. package/dist/migration/index.d.ts.map +1 -1
  117. package/dist/migration/index.js +2 -0
  118. package/dist/migration/index.js.map +1 -1
  119. package/dist/migration/migrate.d.ts.map +1 -1
  120. package/dist/migration/migrate.js +2 -0
  121. package/dist/migration/migrate.js.map +1 -1
  122. package/dist/migration/migrations.d.ts.map +1 -1
  123. package/dist/migration/migrations.js +2 -0
  124. package/dist/migration/migrations.js.map +1 -1
  125. package/dist/migration/version.d.ts.map +1 -1
  126. package/dist/migration/version.js +2 -0
  127. package/dist/migration/version.js.map +1 -1
  128. package/dist/model/LLMModelDefinition.d.ts.map +1 -1
  129. package/dist/model/LLMModelDefinition.js +2 -0
  130. package/dist/model/LLMModelDefinition.js.map +1 -1
  131. package/dist/model/Model.d.ts.map +1 -1
  132. package/dist/model/Model.js +2 -13
  133. package/dist/model/Model.js.map +1 -1
  134. package/dist/model/ModelDefinition.d.ts.map +1 -1
  135. package/dist/model/ModelDefinition.js +2 -0
  136. package/dist/model/ModelDefinition.js.map +1 -1
  137. package/dist/model/ModelRegistry.d.ts.map +1 -1
  138. package/dist/model/ModelRegistry.js +2 -0
  139. package/dist/model/ModelRegistry.js.map +1 -1
  140. package/dist/model/index.d.ts.map +1 -1
  141. package/dist/model/index.js +2 -0
  142. package/dist/model/index.js.map +1 -1
  143. package/dist/model/serialization.d.ts.map +1 -1
  144. package/dist/model/serialization.js +2 -0
  145. package/dist/model/serialization.js.map +1 -1
  146. package/dist/node/AgentNode.d.ts.map +1 -1
  147. package/dist/node/AgentNode.js +2 -0
  148. package/dist/node/AgentNode.js.map +1 -1
  149. package/dist/node/DataNode.d.ts.map +1 -1
  150. package/dist/node/DataNode.js +2 -0
  151. package/dist/node/DataNode.js.map +1 -1
  152. package/dist/node/FunctionNode.d.ts.map +1 -1
  153. package/dist/node/FunctionNode.js +2 -0
  154. package/dist/node/FunctionNode.js.map +1 -1
  155. package/dist/node/InputNode.d.ts.map +1 -1
  156. package/dist/node/InputNode.js +2 -0
  157. package/dist/node/InputNode.js.map +1 -1
  158. package/dist/node/LogicNode.d.ts.map +1 -1
  159. package/dist/node/LogicNode.js +2 -0
  160. package/dist/node/LogicNode.js.map +1 -1
  161. package/dist/node/MqttNode.d.ts.map +1 -1
  162. package/dist/node/MqttNode.js +2 -0
  163. package/dist/node/MqttNode.js.map +1 -1
  164. package/dist/node/Node.d.ts.map +1 -1
  165. package/dist/node/Node.js +2 -7
  166. package/dist/node/Node.js.map +1 -1
  167. package/dist/node/NodeDefinition.d.ts.map +1 -1
  168. package/dist/node/NodeDefinition.js +2 -0
  169. package/dist/node/NodeDefinition.js.map +1 -1
  170. package/dist/node/NodeRegistry.d.ts.map +1 -1
  171. package/dist/node/NodeRegistry.js +2 -0
  172. package/dist/node/NodeRegistry.js.map +1 -1
  173. package/dist/node/OutputNode.d.ts.map +1 -1
  174. package/dist/node/OutputNode.js +4 -2
  175. package/dist/node/OutputNode.js.map +1 -1
  176. package/dist/node/ToolNode.d.ts.map +1 -1
  177. package/dist/node/ToolNode.js +2 -0
  178. package/dist/node/ToolNode.js.map +1 -1
  179. package/dist/node/TriggerNode.d.ts.map +1 -1
  180. package/dist/node/TriggerNode.js +2 -0
  181. package/dist/node/TriggerNode.js.map +1 -1
  182. package/dist/node/constants.d.ts.map +1 -1
  183. package/dist/node/constants.js +2 -0
  184. package/dist/node/constants.js.map +1 -1
  185. package/dist/node/index.d.ts.map +1 -1
  186. package/dist/node/index.js +2 -0
  187. package/dist/node/index.js.map +1 -1
  188. package/dist/node/methods.d.ts.map +1 -1
  189. package/dist/node/methods.js +2 -0
  190. package/dist/node/methods.js.map +1 -1
  191. package/dist/node/serialization.d.ts.map +1 -1
  192. package/dist/node/serialization.js +33 -13
  193. package/dist/node/serialization.js.map +1 -1
  194. package/dist/parameter/OutputParameter.d.ts.map +1 -1
  195. package/dist/parameter/OutputParameter.js +2 -0
  196. package/dist/parameter/OutputParameter.js.map +1 -1
  197. package/dist/parameter/Parameter.d.ts.map +1 -1
  198. package/dist/parameter/Parameter.js +2 -0
  199. package/dist/parameter/Parameter.js.map +1 -1
  200. package/dist/parameter/index.d.ts.map +1 -1
  201. package/dist/parameter/index.js +2 -0
  202. package/dist/parameter/index.js.map +1 -1
  203. package/dist/variable/Variable.d.ts.map +1 -1
  204. package/dist/variable/Variable.js +2 -0
  205. package/dist/variable/Variable.js.map +1 -1
  206. package/dist/variable/index.d.ts.map +1 -1
  207. package/dist/variable/index.js +2 -3
  208. package/dist/variable/index.js.map +1 -1
  209. package/dist/variable/operations.d.ts.map +1 -1
  210. package/dist/variable/operations.js +2 -0
  211. package/dist/variable/operations.js.map +1 -1
  212. package/dist/workflow/Workflow.d.ts.map +1 -1
  213. package/dist/workflow/Workflow.js +2 -0
  214. package/dist/workflow/Workflow.js.map +1 -1
  215. package/dist/workflow/index.d.ts.map +1 -1
  216. package/dist/workflow/index.js +2 -0
  217. package/dist/workflow/index.js.map +1 -1
  218. package/dist/workflow/serialization.d.ts.map +1 -1
  219. package/dist/workflow/serialization.js +2 -4
  220. package/dist/workflow/serialization.js.map +1 -1
  221. package/package.json +2 -2
  222. package/src/api/deployment.ts +74 -0
  223. package/src/api/engine.ts +744 -0
  224. package/src/api/index.ts +29 -11
  225. package/src/api/workflow.ts +25 -9
  226. package/src/channel/Channel.ts +14 -11
  227. package/src/channel/ChannelDefinition.ts +101 -76
  228. package/src/channel/index.ts +9 -6
  229. package/src/channel/serialization.ts +77 -68
  230. package/src/deploy/index.ts +17 -1
  231. package/src/deploy/inputs.ts +44 -0
  232. package/src/deploy/requirements.test.ts +64 -61
  233. package/src/deploy/requirements.ts +159 -41
  234. package/src/deploy/spec.test.ts +227 -0
  235. package/src/deploy/spec.ts +397 -0
  236. package/src/diagnostics/__fixtures__/diagnosticFixtures.ts +161 -158
  237. package/src/diagnostics/diagnostics.test.ts +881 -878
  238. package/src/diagnostics/diagnostics.ts +939 -936
  239. package/src/diagnostics/index.ts +14 -11
  240. package/src/edge/Edge.ts +26 -23
  241. package/src/edge/EdgeDefinition.ts +48 -45
  242. package/src/edge/EdgeType.ts +22 -19
  243. package/src/edge/index.ts +11 -8
  244. package/src/edge/serialization.ts +86 -83
  245. package/src/expression/index.ts +7 -4
  246. package/src/expression/parser.ts +365 -362
  247. package/src/expression/types.ts +33 -30
  248. package/src/function/FunctionDeclaration.ts +57 -54
  249. package/src/function/index.ts +6 -3
  250. package/src/function/serialization.ts +43 -40
  251. package/src/globals.d.ts +12 -9
  252. package/src/id/index.ts +11 -8
  253. package/src/index.ts +25 -22
  254. package/src/memory/Memory.ts +18 -15
  255. package/src/memory/MemoryDefinition.ts +19 -16
  256. package/src/memory/MemoryFileDefinition.ts +40 -37
  257. package/src/memory/MemoryRegistry.ts +38 -35
  258. package/src/memory/VectorDatabaseDefinition.ts +24 -21
  259. package/src/memory/index.ts +11 -8
  260. package/src/memory/serialization.ts +50 -47
  261. package/src/migration/index.ts +7 -4
  262. package/src/migration/migrate.test.ts +47 -44
  263. package/src/migration/migrate.ts +61 -58
  264. package/src/migration/migrations.ts +27 -24
  265. package/src/migration/version.ts +12 -9
  266. package/src/model/LLMModelDefinition.ts +15 -12
  267. package/src/model/Model.ts +42 -39
  268. package/src/model/ModelDefinition.ts +18 -15
  269. package/src/model/ModelRegistry.ts +36 -33
  270. package/src/model/index.ts +10 -7
  271. package/src/model/serialization.ts +33 -30
  272. package/src/node/AgentNode.ts +85 -82
  273. package/src/node/DataNode.ts +44 -41
  274. package/src/node/FunctionNode.ts +79 -76
  275. package/src/node/InputNode.ts +188 -185
  276. package/src/node/LogicNode.ts +36 -33
  277. package/src/node/MqttNode.ts +130 -127
  278. package/src/node/Node.ts +64 -61
  279. package/src/node/NodeDefinition.ts +40 -37
  280. package/src/node/NodeRegistry.ts +88 -85
  281. package/src/node/OutputNode.ts +90 -87
  282. package/src/node/ToolNode.ts +35 -32
  283. package/src/node/TriggerNode.ts +275 -272
  284. package/src/node/constants.ts +19 -16
  285. package/src/node/index.ts +29 -26
  286. package/src/node/methods.ts +281 -278
  287. package/src/node/serialization.test.ts +51 -0
  288. package/src/node/serialization.ts +565 -544
  289. package/src/parameter/OutputParameter.ts +71 -68
  290. package/src/parameter/Parameter.ts +246 -243
  291. package/src/parameter/index.ts +36 -33
  292. package/src/variable/Variable.ts +13 -10
  293. package/src/variable/index.ts +19 -16
  294. package/src/variable/operations.ts +109 -106
  295. package/src/workflow/Workflow.ts +44 -41
  296. package/src/workflow/index.ts +6 -3
  297. package/src/workflow/serialization.test.ts +243 -240
  298. package/src/workflow/serialization.ts +245 -242
@@ -1,21 +1,24 @@
1
- import type { MemoryDefinition } from "./MemoryDefinition";
2
-
3
- /**
4
- * RAG knowledge base referenced from Retriever nodes. Only descriptive config
5
- * lives here; the backend collection it binds to is supplied at deploy time.
6
- */
7
- export const VectorDatabaseDefinition: MemoryDefinition = {
8
- type: "VectorDatabase",
9
- label: "Vector Database",
10
- description: "RAG knowledge base that Retriever nodes can query",
11
- parameters: [
12
- {
13
- id: "description",
14
- label: "Description",
15
- description: "What this knowledge base contains",
16
- type: "string",
17
- multiline: true,
18
- optional: true,
19
- },
20
- ],
21
- };
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 ForestHub.
3
+
4
+ import type { MemoryDefinition } from "./MemoryDefinition";
5
+
6
+ /**
7
+ * RAG knowledge base referenced from Retriever nodes. Only descriptive config
8
+ * lives here; the backend collection it binds to is supplied at deploy time.
9
+ */
10
+ export const VectorDatabaseDefinition: MemoryDefinition = {
11
+ type: "VectorDatabase",
12
+ label: "Vector Database",
13
+ description: "RAG knowledge base that Retriever nodes can query",
14
+ parameters: [
15
+ {
16
+ id: "description",
17
+ label: "Description",
18
+ description: "What this knowledge base contains",
19
+ type: "string",
20
+ multiline: true,
21
+ optional: true,
22
+ },
23
+ ],
24
+ };
@@ -1,8 +1,11 @@
1
- export type { MemoryType, Memory, MemoryRef } from "./Memory";
2
- export { ALL_MEMORY_TYPES } from "./Memory";
3
- export type { MemoryDefinition } from "./MemoryDefinition";
4
- export { MemoryFileDefinition } from "./MemoryFileDefinition";
5
- export { VectorDatabaseDefinition } from "./VectorDatabaseDefinition";
6
- export { MemoryRegistry } from "./MemoryRegistry";
7
- export { serialize, deserialize } from "./serialization";
8
- export type { ApiMemory } from "./serialization";
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 ForestHub.
3
+
4
+ export type { MemoryType, Memory, MemoryRef } from "./Memory";
5
+ export { ALL_MEMORY_TYPES } from "./Memory";
6
+ export type { MemoryDefinition } from "./MemoryDefinition";
7
+ export { MemoryFileDefinition } from "./MemoryFileDefinition";
8
+ export { VectorDatabaseDefinition } from "./VectorDatabaseDefinition";
9
+ export { MemoryRegistry } from "./MemoryRegistry";
10
+ export { serialize, deserialize } from "./serialization";
11
+ export type { ApiMemory } from "./serialization";
@@ -1,47 +1,50 @@
1
- import type { Schemas } from "../api";
2
- import type { Memory } from "./Memory";
3
-
4
- export type ApiMemory = Schemas["Memory"];
5
-
6
- /**
7
- * Serialize a domain Memory to the API discriminated-union shape.
8
- * MemoryFile drops `maxSizeBytes` when unset (absent and null both mean "unlimited").
9
- */
10
- export function serialize(mem: Memory): ApiMemory {
11
- const { id, label, type, arguments: args } = mem;
12
- switch (type) {
13
- case "MemoryFile":
14
- return {
15
- type,
16
- id,
17
- label,
18
- description: (args.description as string) ?? "",
19
- content: (args.content as string) ?? "",
20
- ...(args.maxSizeBytes != null ? { maxSizeBytes: args.maxSizeBytes as number } : {}),
21
- };
22
- case "VectorDatabase":
23
- return {
24
- type,
25
- id,
26
- label,
27
- ...(args.description != null ? { description: args.description as string } : {}),
28
- };
29
- }
30
- }
31
-
32
- /** Convert an API Memory into a domain Memory. */
33
- export function deserialize(api: ApiMemory): Memory {
34
- const { id, label, type } = api;
35
- const args: Record<string, unknown> = {};
36
- switch (type) {
37
- case "MemoryFile":
38
- args.description = api.description ?? "";
39
- args.content = api.content ?? "";
40
- if (api.maxSizeBytes != null) args.maxSizeBytes = api.maxSizeBytes;
41
- break;
42
- case "VectorDatabase":
43
- if (api.description != null) args.description = api.description;
44
- break;
45
- }
46
- return { id, label, type, arguments: args };
47
- }
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 ForestHub.
3
+
4
+ import type { Schemas } from "../api";
5
+ import type { Memory } from "./Memory";
6
+
7
+ export type ApiMemory = Schemas["Memory"];
8
+
9
+ /**
10
+ * Serialize a domain Memory to the API discriminated-union shape.
11
+ * MemoryFile drops `maxSizeBytes` when unset (absent and null both mean "unlimited").
12
+ */
13
+ export function serialize(mem: Memory): ApiMemory {
14
+ const { id, label, type, arguments: args } = mem;
15
+ switch (type) {
16
+ case "MemoryFile":
17
+ return {
18
+ type,
19
+ id,
20
+ label,
21
+ description: (args.description as string) ?? "",
22
+ content: (args.content as string) ?? "",
23
+ ...(args.maxSizeBytes != null ? { maxSizeBytes: args.maxSizeBytes as number } : {}),
24
+ };
25
+ case "VectorDatabase":
26
+ return {
27
+ type,
28
+ id,
29
+ label,
30
+ ...(args.description != null ? { description: args.description as string } : {}),
31
+ };
32
+ }
33
+ }
34
+
35
+ /** Convert an API Memory into a domain Memory. */
36
+ export function deserialize(api: ApiMemory): Memory {
37
+ const { id, label, type } = api;
38
+ const args: Record<string, unknown> = {};
39
+ switch (type) {
40
+ case "MemoryFile":
41
+ args.description = api.description ?? "";
42
+ args.content = api.content ?? "";
43
+ if (api.maxSizeBytes != null) args.maxSizeBytes = api.maxSizeBytes;
44
+ break;
45
+ case "VectorDatabase":
46
+ if (api.description != null) args.description = api.description;
47
+ break;
48
+ }
49
+ return { id, label, type, arguments: args };
50
+ }
@@ -1,4 +1,7 @@
1
- export { CURRENT_SCHEMA_VERSION, BASELINE_SCHEMA_VERSION } from "./version";
2
- export { migrate, readSchemaVersion } from "./migrate";
3
- export { MIGRATIONS } from "./migrations";
4
- export type { Migration } from "./migrations";
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 ForestHub.
3
+
4
+ export { CURRENT_SCHEMA_VERSION, BASELINE_SCHEMA_VERSION } from "./version";
5
+ export { migrate, readSchemaVersion } from "./migrate";
6
+ export { MIGRATIONS } from "./migrations";
7
+ export type { Migration } from "./migrations";
@@ -1,44 +1,47 @@
1
- import { describe, it, expect } from "vitest";
2
- import { migrate, readSchemaVersion } from "./migrate";
3
- import { CURRENT_SCHEMA_VERSION } from "./version";
4
-
5
- describe("readSchemaVersion", () => {
6
- it("reads an explicit integer version", () => {
7
- expect(readSchemaVersion({ schemaVersion: 3 })).toBe(3);
8
- });
9
-
10
- it("defaults missing, non-integer, or out-of-range to the baseline", () => {
11
- expect(readSchemaVersion({})).toBe(1);
12
- expect(readSchemaVersion({ schemaVersion: 1.5 })).toBe(1);
13
- expect(readSchemaVersion({ schemaVersion: 0 })).toBe(1);
14
- expect(readSchemaVersion({ schemaVersion: "2" })).toBe(1);
15
- });
16
- });
17
-
18
- describe("migrate", () => {
19
- it("stamps the current version on a baseline document", () => {
20
- const out = migrate({ nodes: [], edges: [] });
21
- expect(out.schemaVersion).toBe(CURRENT_SCHEMA_VERSION);
22
- });
23
-
24
- it("passes through a document already at the current version", () => {
25
- const doc = { schemaVersion: CURRENT_SCHEMA_VERSION, nodes: [] };
26
- expect(migrate(doc).schemaVersion).toBe(CURRENT_SCHEMA_VERSION);
27
- });
28
-
29
- it("does not mutate its input", () => {
30
- const doc: Record<string, unknown> = { nodes: [] };
31
- migrate(doc);
32
- expect("schemaVersion" in doc).toBe(false);
33
- });
34
-
35
- it("rejects a document newer than this build supports", () => {
36
- expect(() => migrate({ schemaVersion: CURRENT_SCHEMA_VERSION + 1 })).toThrow(/newer than this build/);
37
- });
38
-
39
- it("rejects a non-object document", () => {
40
- expect(() => migrate(null)).toThrow(/must be a JSON object/);
41
- expect(() => migrate([])).toThrow(/must be a JSON object/);
42
- expect(() => migrate(42)).toThrow(/must be a JSON object/);
43
- });
44
- });
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 ForestHub.
3
+
4
+ import { describe, it, expect } from "vitest";
5
+ import { migrate, readSchemaVersion } from "./migrate";
6
+ import { CURRENT_SCHEMA_VERSION } from "./version";
7
+
8
+ describe("readSchemaVersion", () => {
9
+ it("reads an explicit integer version", () => {
10
+ expect(readSchemaVersion({ schemaVersion: 3 })).toBe(3);
11
+ });
12
+
13
+ it("defaults missing, non-integer, or out-of-range to the baseline", () => {
14
+ expect(readSchemaVersion({})).toBe(1);
15
+ expect(readSchemaVersion({ schemaVersion: 1.5 })).toBe(1);
16
+ expect(readSchemaVersion({ schemaVersion: 0 })).toBe(1);
17
+ expect(readSchemaVersion({ schemaVersion: "2" })).toBe(1);
18
+ });
19
+ });
20
+
21
+ describe("migrate", () => {
22
+ it("stamps the current version on a baseline document", () => {
23
+ const out = migrate({ nodes: [], edges: [] });
24
+ expect(out.schemaVersion).toBe(CURRENT_SCHEMA_VERSION);
25
+ });
26
+
27
+ it("passes through a document already at the current version", () => {
28
+ const doc = { schemaVersion: CURRENT_SCHEMA_VERSION, nodes: [] };
29
+ expect(migrate(doc).schemaVersion).toBe(CURRENT_SCHEMA_VERSION);
30
+ });
31
+
32
+ it("does not mutate its input", () => {
33
+ const doc: Record<string, unknown> = { nodes: [] };
34
+ migrate(doc);
35
+ expect("schemaVersion" in doc).toBe(false);
36
+ });
37
+
38
+ it("rejects a document newer than this build supports", () => {
39
+ expect(() => migrate({ schemaVersion: CURRENT_SCHEMA_VERSION + 1 })).toThrow(/newer than this build/);
40
+ });
41
+
42
+ it("rejects a non-object document", () => {
43
+ expect(() => migrate(null)).toThrow(/must be a JSON object/);
44
+ expect(() => migrate([])).toThrow(/must be a JSON object/);
45
+ expect(() => migrate(42)).toThrow(/must be a JSON object/);
46
+ });
47
+ });
@@ -1,58 +1,61 @@
1
- import type { ApiWorkflow } from "../workflow/Workflow";
2
- import { MIGRATIONS, type Migration } from "./migrations";
3
- import { BASELINE_SCHEMA_VERSION, CURRENT_SCHEMA_VERSION } from "./version";
4
-
5
- /**
6
- * Index the registry by `from` and assert it forms a contiguous chain over
7
- * [BASELINE_SCHEMA_VERSION, CURRENT_SCHEMA_VERSION). A gap or duplicate is a
8
- * programming error, so it throws at module load rather than on first use.
9
- */
10
- function buildChain(migrations: readonly Migration[]): ReadonlyMap<number, Migration> {
11
- const byFrom = new Map<number, Migration>();
12
- for (const m of migrations) {
13
- if (!Number.isInteger(m.from) || m.from < BASELINE_SCHEMA_VERSION || m.from >= CURRENT_SCHEMA_VERSION) {
14
- throw new Error(`[migration] from must be an integer in [${BASELINE_SCHEMA_VERSION}, ${CURRENT_SCHEMA_VERSION}), got ${m.from}`);
15
- }
16
- if (byFrom.has(m.from)) {
17
- throw new Error(`[migration] duplicate migration from ${m.from}`);
18
- }
19
- byFrom.set(m.from, m);
20
- }
21
- for (let v = BASELINE_SCHEMA_VERSION; v < CURRENT_SCHEMA_VERSION; v++) {
22
- if (!byFrom.has(v)) throw new Error(`[migration] missing migration from ${v} -> ${v + 1}`);
23
- }
24
- return byFrom;
25
- }
26
-
27
- const CHAIN = buildChain(MIGRATIONS);
28
-
29
- /** Read the schema version, defaulting absent/invalid to the baseline. */
30
- export function readSchemaVersion(doc: Record<string, unknown>): number {
31
- const v = doc.schemaVersion;
32
- return typeof v === "number" && Number.isInteger(v) && v >= BASELINE_SCHEMA_VERSION ? v : BASELINE_SCHEMA_VERSION;
33
- }
34
-
35
- /**
36
- * Upgrade a raw, parsed workflow document to CURRENT_SCHEMA_VERSION and return
37
- * it as the current {@link ApiWorkflow}, ready for `deserialize`. Runs on
38
- * untyped JSON so each migration stays pinned to the shape it was written for.
39
- * Throws on a non-object, or a version newer than this build supports.
40
- */
41
- export function migrate(raw: unknown): ApiWorkflow {
42
- if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
43
- throw new Error("[migration] workflow document must be a JSON object");
44
- }
45
- let doc: Record<string, unknown> = { ...(raw as Record<string, unknown>) };
46
-
47
- const version = readSchemaVersion(doc);
48
- if (version > CURRENT_SCHEMA_VERSION) {
49
- throw new Error(`[migration] schemaVersion ${version} is newer than this build supports (${CURRENT_SCHEMA_VERSION})`);
50
- }
51
-
52
- for (let v = version; v < CURRENT_SCHEMA_VERSION; v++) {
53
- doc = CHAIN.get(v)!.migrate(doc); // non-null: buildChain covers every v in range
54
- }
55
-
56
- doc.schemaVersion = CURRENT_SCHEMA_VERSION;
57
- return doc as ApiWorkflow;
58
- }
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 ForestHub.
3
+
4
+ import type { ApiWorkflow } from "../workflow/Workflow";
5
+ import { MIGRATIONS, type Migration } from "./migrations";
6
+ import { BASELINE_SCHEMA_VERSION, CURRENT_SCHEMA_VERSION } from "./version";
7
+
8
+ /**
9
+ * Index the registry by `from` and assert it forms a contiguous chain over
10
+ * [BASELINE_SCHEMA_VERSION, CURRENT_SCHEMA_VERSION). A gap or duplicate is a
11
+ * programming error, so it throws at module load rather than on first use.
12
+ */
13
+ function buildChain(migrations: readonly Migration[]): ReadonlyMap<number, Migration> {
14
+ const byFrom = new Map<number, Migration>();
15
+ for (const m of migrations) {
16
+ if (!Number.isInteger(m.from) || m.from < BASELINE_SCHEMA_VERSION || m.from >= CURRENT_SCHEMA_VERSION) {
17
+ throw new Error(`[migration] from must be an integer in [${BASELINE_SCHEMA_VERSION}, ${CURRENT_SCHEMA_VERSION}), got ${m.from}`);
18
+ }
19
+ if (byFrom.has(m.from)) {
20
+ throw new Error(`[migration] duplicate migration from ${m.from}`);
21
+ }
22
+ byFrom.set(m.from, m);
23
+ }
24
+ for (let v = BASELINE_SCHEMA_VERSION; v < CURRENT_SCHEMA_VERSION; v++) {
25
+ if (!byFrom.has(v)) throw new Error(`[migration] missing migration from ${v} -> ${v + 1}`);
26
+ }
27
+ return byFrom;
28
+ }
29
+
30
+ const CHAIN = buildChain(MIGRATIONS);
31
+
32
+ /** Read the schema version, defaulting absent/invalid to the baseline. */
33
+ export function readSchemaVersion(doc: Record<string, unknown>): number {
34
+ const v = doc.schemaVersion;
35
+ return typeof v === "number" && Number.isInteger(v) && v >= BASELINE_SCHEMA_VERSION ? v : BASELINE_SCHEMA_VERSION;
36
+ }
37
+
38
+ /**
39
+ * Upgrade a raw, parsed workflow document to CURRENT_SCHEMA_VERSION and return
40
+ * it as the current {@link ApiWorkflow}, ready for `deserialize`. Runs on
41
+ * untyped JSON so each migration stays pinned to the shape it was written for.
42
+ * Throws on a non-object, or a version newer than this build supports.
43
+ */
44
+ export function migrate(raw: unknown): ApiWorkflow {
45
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
46
+ throw new Error("[migration] workflow document must be a JSON object");
47
+ }
48
+ let doc: Record<string, unknown> = { ...(raw as Record<string, unknown>) };
49
+
50
+ const version = readSchemaVersion(doc);
51
+ if (version > CURRENT_SCHEMA_VERSION) {
52
+ throw new Error(`[migration] schemaVersion ${version} is newer than this build supports (${CURRENT_SCHEMA_VERSION})`);
53
+ }
54
+
55
+ for (let v = version; v < CURRENT_SCHEMA_VERSION; v++) {
56
+ doc = CHAIN.get(v)!.migrate(doc); // non-null: buildChain covers every v in range
57
+ }
58
+
59
+ doc.schemaVersion = CURRENT_SCHEMA_VERSION;
60
+ return doc as ApiWorkflow;
61
+ }
@@ -1,24 +1,27 @@
1
- /**
2
- * A single-step upgrade of the persisted workflow format, from `from` to
3
- * `from + 1`. Operates on the raw parsed document, never the domain types.
4
- * Forward-only: there is no down-path.
5
- *
6
- * A shipped migration is immutable saved files depend on its exact behaviour.
7
- * Express the next change as a new migration, never an edit to an old one.
8
- */
9
- export interface Migration {
10
- /** Schema version this migration expects as input. Produces `from + 1`. */
11
- readonly from: number;
12
- /** Pure transform on the raw document; must not mutate its input. */
13
- migrate(doc: Record<string, unknown>): Record<string, unknown>;
14
- }
15
-
16
- /**
17
- * Ordered registry of single-step format migrations. To change the format:
18
- * bump CURRENT_SCHEMA_VERSION, append one migration with `from` set to the
19
- * previous value, and reconcile serialize/deserialize. {@link migrate} asserts
20
- * at load that the chain is contiguous over [BASELINE, CURRENT).
21
- */
22
- export const MIGRATIONS: readonly Migration[] = [
23
- // First entry will be `{ from: 1, migrate: (doc) => ... }`.
24
- ];
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 ForestHub.
3
+
4
+ /**
5
+ * A single-step upgrade of the persisted workflow format, from `from` to
6
+ * `from + 1`. Operates on the raw parsed document, never the domain types.
7
+ * Forward-only: there is no down-path.
8
+ *
9
+ * A shipped migration is immutable — saved files depend on its exact behaviour.
10
+ * Express the next change as a new migration, never an edit to an old one.
11
+ */
12
+ export interface Migration {
13
+ /** Schema version this migration expects as input. Produces `from + 1`. */
14
+ readonly from: number;
15
+ /** Pure transform on the raw document; must not mutate its input. */
16
+ migrate(doc: Record<string, unknown>): Record<string, unknown>;
17
+ }
18
+
19
+ /**
20
+ * Ordered registry of single-step format migrations. To change the format:
21
+ * bump CURRENT_SCHEMA_VERSION, append one migration with `from` set to the
22
+ * previous value, and reconcile serialize/deserialize. {@link migrate} asserts
23
+ * at load that the chain is contiguous over [BASELINE, CURRENT).
24
+ */
25
+ export const MIGRATIONS: readonly Migration[] = [
26
+ // First entry will be `{ from: 1, migrate: (doc) => ... }`.
27
+ ];
@@ -1,9 +1,12 @@
1
- /**
2
- * Persisted-format version this build reads and writes. A plain monotonic
3
- * integer, decoupled from the contract/package semver. Bump only when the
4
- * serialized {@link ApiWorkflow} shape changes, adding a matching migration.
5
- */
6
- export const CURRENT_SCHEMA_VERSION = 1;
7
-
8
- /** Version assumed for documents that carry no `schemaVersion`. */
9
- export const BASELINE_SCHEMA_VERSION = 1;
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 ForestHub.
3
+
4
+ /**
5
+ * Persisted-format version this build reads and writes. A plain monotonic
6
+ * integer, decoupled from the contract/package semver. Bump only when the
7
+ * serialized {@link ApiWorkflow} shape changes, adding a matching migration.
8
+ */
9
+ export const CURRENT_SCHEMA_VERSION = 1;
10
+
11
+ /** Version assumed for documents that carry no `schemaVersion`. */
12
+ export const BASELINE_SCHEMA_VERSION = 1;
@@ -1,12 +1,15 @@
1
- import type { ModelDefinition } from "./ModelDefinition";
2
-
3
- /**
4
- * A declared custom/self-hosted LLM model.
5
- * Capabilities default to ["chat"] on serialize; a capability editor can be added later.
6
- */
7
- export const LLMModelDefinition: ModelDefinition = {
8
- type: "LLMModel",
9
- label: "Custom LLM Model",
10
- description: "A self-hosted or custom LLM the llmproxy doesn't ship by default",
11
- parameters: [],
12
- };
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 ForestHub.
3
+
4
+ import type { ModelDefinition } from "./ModelDefinition";
5
+
6
+ /**
7
+ * A declared custom/self-hosted LLM model.
8
+ * Capabilities default to ["chat"] on serialize; a capability editor can be added later.
9
+ */
10
+ export const LLMModelDefinition: ModelDefinition = {
11
+ type: "LLMModel",
12
+ label: "Custom LLM Model",
13
+ description: "A self-hosted or custom LLM the llmproxy doesn't ship by default",
14
+ parameters: [],
15
+ };
@@ -1,39 +1,42 @@
1
- // Domain Model — covers two distinct things that share a picker:
2
- // 1. The STATIC catalog (ModelInfo[]): the set of models the llmproxy already
3
- // supports. Supplied to the editor as data (props), not declared per-workflow.
4
- // A node simply stores the chosen catalog ModelID directly.
5
- // 2. DECLARED custom models (Model): self-hosted / custom models the
6
- // llmproxy doesn't ship. These are channel-like declared in the workflow,
7
- // referenced by id from nodes, and mapped to an llmproxy provider at deploy.
8
- //
9
- // A node's `model` field is always just a ModelID string either way; static ids
10
- // resolve via the catalog (no mapping), custom ids via a declared Model.
11
- //
12
- // `type` is the api discriminator; new model families (e.g. future YOLO/ONNX
13
- // variants) register their own definition in ModelRegistry, mirroring nodes.
14
-
15
- import type { Schemas } from "../api";
16
-
17
- /** A capability a model supports (chat, embedding, vision, ...). From the api. */
18
- export type ModelCapability = Schemas["ModelCapability"];
19
-
20
- export type ModelType = "LLMModel";
21
-
22
- export const ALL_MODEL_TYPES: ModelType[] = ["LLMModel"];
23
-
24
- export interface Model {
25
- id: string;
26
- label: string;
27
- type: ModelType;
28
- arguments: Record<string, unknown>;
29
- }
30
-
31
- /**
32
- * One entry in the static model catalog handed to the builder via props. The
33
- * embedder maps the llmproxy's richer ModelInfo down to this minimal shape.
34
- */
35
- export interface ModelInfo {
36
- id: string;
37
- label: string;
38
- capabilities: ModelCapability[];
39
- }
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 ForestHub.
3
+
4
+ // Domain Model covers two distinct things that share a picker:
5
+ // 1. The STATIC catalog (ModelInfo[]): the set of models the llmproxy already
6
+ // supports. Supplied to the editor as data (props), not declared per-workflow.
7
+ // A node simply stores the chosen catalog ModelID directly.
8
+ // 2. DECLARED custom models (Model): self-hosted / custom models the
9
+ // llmproxy doesn't ship. These are channel-like declared in the workflow,
10
+ // referenced by id from nodes, and mapped to an llmproxy provider at deploy.
11
+ //
12
+ // A node's `model` field is always just a ModelID string either way; static ids
13
+ // resolve via the catalog (no mapping), custom ids via a declared Model.
14
+ //
15
+ // `type` is the api discriminator; new model families (e.g. future YOLO/ONNX
16
+ // variants) register their own definition in ModelRegistry, mirroring nodes.
17
+
18
+ import type { Schemas } from "../api";
19
+
20
+ /** A capability a model supports (chat, embedding, vision, ...). From the api. */
21
+ export type ModelCapability = Schemas["ModelCapability"];
22
+
23
+ export type ModelType = "LLMModel";
24
+
25
+ export const ALL_MODEL_TYPES: ModelType[] = ["LLMModel"];
26
+
27
+ export interface Model {
28
+ id: string;
29
+ label: string;
30
+ type: ModelType;
31
+ arguments: Record<string, unknown>;
32
+ }
33
+
34
+ /**
35
+ * One entry in the static model catalog handed to the builder via props. The
36
+ * embedder maps the llmproxy's richer ModelInfo down to this minimal shape.
37
+ */
38
+ export interface ModelInfo {
39
+ id: string;
40
+ label: string;
41
+ capabilities: ModelCapability[];
42
+ }
@@ -1,15 +1,18 @@
1
- import type { Parameter } from "../parameter";
2
- import type { ModelType } from "./Model";
3
-
4
- /**
5
- * Static, per-type metadata for a declared (custom) model variant. Mirrors
6
- * MemoryDefinition / NodeDefinition: one definition object per ModelType,
7
- * registered in ModelRegistry. `label` is a top-level instance field (edited
8
- * like a channel label), so it is never a parameter here.
9
- */
10
- export interface ModelDefinition {
11
- type: ModelType;
12
- label: string;
13
- description: string;
14
- parameters: Parameter[];
15
- }
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 ForestHub.
3
+
4
+ import type { Parameter } from "../parameter";
5
+ import type { ModelType } from "./Model";
6
+
7
+ /**
8
+ * Static, per-type metadata for a declared (custom) model variant. Mirrors
9
+ * MemoryDefinition / NodeDefinition: one definition object per ModelType,
10
+ * registered in ModelRegistry. `label` is a top-level instance field (edited
11
+ * like a channel label), so it is never a parameter here.
12
+ */
13
+ export interface ModelDefinition {
14
+ type: ModelType;
15
+ label: string;
16
+ description: string;
17
+ parameters: Parameter[];
18
+ }