@elaraai/e3-types 1.0.79 → 1.0.80

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 (153) hide show
  1. package/README.md +1 -1
  2. package/dist/src/api.d.ts +569 -36
  3. package/dist/src/api.d.ts.map +1 -1
  4. package/dist/src/api.js +257 -32
  5. package/dist/src/api.js.map +1 -1
  6. package/dist/src/collection-manifest.d.ts +37 -0
  7. package/dist/src/collection-manifest.d.ts.map +1 -0
  8. package/dist/src/collection-manifest.js +37 -0
  9. package/dist/src/collection-manifest.js.map +1 -0
  10. package/dist/src/dataflow.d.ts +264 -19
  11. package/dist/src/dataflow.d.ts.map +1 -1
  12. package/dist/src/dataflow.js +156 -15
  13. package/dist/src/dataflow.js.map +1 -1
  14. package/dist/src/dataflow.spec.js +184 -27
  15. package/dist/src/dataflow.spec.js.map +1 -1
  16. package/dist/src/dataset-blob.d.ts +75 -15
  17. package/dist/src/dataset-blob.d.ts.map +1 -1
  18. package/dist/src/dataset-blob.js +95 -28
  19. package/dist/src/dataset-blob.js.map +1 -1
  20. package/dist/src/dataset-blob.spec.d.ts +6 -0
  21. package/dist/src/dataset-blob.spec.d.ts.map +1 -0
  22. package/dist/src/dataset-blob.spec.js +92 -0
  23. package/dist/src/dataset-blob.spec.js.map +1 -0
  24. package/dist/src/dataset-ref.d.ts +5 -4
  25. package/dist/src/dataset-ref.d.ts.map +1 -1
  26. package/dist/src/dataset-ref.js +5 -4
  27. package/dist/src/dataset-ref.js.map +1 -1
  28. package/dist/src/environment.d.ts +3 -2
  29. package/dist/src/environment.d.ts.map +1 -1
  30. package/dist/src/environment.js +3 -2
  31. package/dist/src/environment.js.map +1 -1
  32. package/dist/src/execution.d.ts +112 -18
  33. package/dist/src/execution.d.ts.map +1 -1
  34. package/dist/src/execution.js +174 -45
  35. package/dist/src/execution.js.map +1 -1
  36. package/dist/src/execution.spec.d.ts +6 -0
  37. package/dist/src/execution.spec.d.ts.map +1 -0
  38. package/dist/src/execution.spec.js +108 -0
  39. package/dist/src/execution.spec.js.map +1 -0
  40. package/dist/src/function.d.ts +14 -12
  41. package/dist/src/function.d.ts.map +1 -1
  42. package/dist/src/function.js +17 -32
  43. package/dist/src/function.js.map +1 -1
  44. package/dist/src/index.d.ts +16 -12
  45. package/dist/src/index.d.ts.map +1 -1
  46. package/dist/src/index.js +25 -20
  47. package/dist/src/index.js.map +1 -1
  48. package/dist/src/lock.d.ts +68 -22
  49. package/dist/src/lock.d.ts.map +1 -1
  50. package/dist/src/lock.js +33 -22
  51. package/dist/src/lock.js.map +1 -1
  52. package/dist/src/names.d.ts +21 -0
  53. package/dist/src/names.d.ts.map +1 -0
  54. package/dist/src/names.js +31 -0
  55. package/dist/src/names.js.map +1 -0
  56. package/dist/src/package.d.ts +11 -78
  57. package/dist/src/package.d.ts.map +1 -1
  58. package/dist/src/package.js +13 -66
  59. package/dist/src/package.js.map +1 -1
  60. package/dist/src/record.d.ts +582 -18
  61. package/dist/src/record.d.ts.map +1 -1
  62. package/dist/src/record.js +405 -7
  63. package/dist/src/record.js.map +1 -1
  64. package/dist/src/{stream.spec.d.ts → record.spec.d.ts} +1 -1
  65. package/dist/src/record.spec.d.ts.map +1 -0
  66. package/dist/src/record.spec.js +143 -0
  67. package/dist/src/record.spec.js.map +1 -0
  68. package/dist/src/release.d.ts +36 -0
  69. package/dist/src/release.d.ts.map +1 -0
  70. package/dist/src/release.js +71 -0
  71. package/dist/src/release.js.map +1 -0
  72. package/dist/src/release.spec.d.ts +6 -0
  73. package/dist/src/release.spec.d.ts.map +1 -0
  74. package/dist/src/release.spec.js +42 -0
  75. package/dist/src/release.spec.js.map +1 -0
  76. package/dist/src/repository.d.ts +64 -0
  77. package/dist/src/repository.d.ts.map +1 -0
  78. package/dist/src/repository.js +49 -0
  79. package/dist/src/repository.js.map +1 -0
  80. package/dist/src/runner.d.ts +16 -62
  81. package/dist/src/runner.d.ts.map +1 -1
  82. package/dist/src/runner.js +16 -79
  83. package/dist/src/runner.js.map +1 -1
  84. package/dist/src/runner.spec.js +11 -85
  85. package/dist/src/runner.spec.js.map +1 -1
  86. package/dist/src/structure.d.ts +0 -57
  87. package/dist/src/structure.d.ts.map +1 -1
  88. package/dist/src/structure.js +0 -3
  89. package/dist/src/structure.js.map +1 -1
  90. package/dist/src/task.d.ts +210 -318
  91. package/dist/src/task.d.ts.map +1 -1
  92. package/dist/src/task.js +117 -472
  93. package/dist/src/task.js.map +1 -1
  94. package/dist/src/task.spec.js +62 -154
  95. package/dist/src/task.spec.js.map +1 -1
  96. package/dist/src/transfer.d.ts +16 -22
  97. package/dist/src/transfer.d.ts.map +1 -1
  98. package/dist/src/transfer.js +16 -22
  99. package/dist/src/transfer.js.map +1 -1
  100. package/dist/src/transfer.spec.js +4 -34
  101. package/dist/src/transfer.spec.js.map +1 -1
  102. package/dist/src/unit-plan.d.ts +130 -0
  103. package/dist/src/unit-plan.d.ts.map +1 -0
  104. package/dist/src/unit-plan.js +107 -0
  105. package/dist/src/unit-plan.js.map +1 -0
  106. package/dist/src/unit-plan.spec.d.ts +6 -0
  107. package/dist/src/unit-plan.spec.d.ts.map +1 -0
  108. package/dist/src/unit-plan.spec.js +29 -0
  109. package/dist/src/unit-plan.spec.js.map +1 -0
  110. package/dist/src/workspace.d.ts +22 -11
  111. package/dist/src/workspace.d.ts.map +1 -1
  112. package/dist/src/workspace.js +10 -11
  113. package/dist/src/workspace.js.map +1 -1
  114. package/package.json +3 -3
  115. package/src/api.ts +276 -32
  116. package/src/collection-manifest.ts +53 -0
  117. package/src/dataflow.spec.ts +223 -31
  118. package/src/dataflow.ts +183 -26
  119. package/src/dataset-blob.spec.ts +117 -0
  120. package/src/dataset-blob.ts +157 -21
  121. package/src/dataset-ref.ts +5 -4
  122. package/src/environment.ts +3 -2
  123. package/src/execution.spec.ts +114 -0
  124. package/src/execution.ts +175 -51
  125. package/src/function.ts +19 -32
  126. package/src/index.ts +122 -39
  127. package/src/lock.ts +39 -22
  128. package/src/names.ts +39 -0
  129. package/src/package.ts +15 -71
  130. package/src/record.spec.ts +195 -0
  131. package/src/record.ts +489 -7
  132. package/src/release.spec.ts +47 -0
  133. package/src/release.ts +69 -0
  134. package/src/repository.ts +67 -0
  135. package/src/runner.spec.ts +11 -94
  136. package/src/runner.ts +16 -80
  137. package/src/structure.ts +0 -8
  138. package/src/task.spec.ts +67 -188
  139. package/src/task.ts +140 -522
  140. package/src/transfer.spec.ts +4 -51
  141. package/src/transfer.ts +16 -22
  142. package/src/unit-plan.spec.ts +31 -0
  143. package/src/unit-plan.ts +121 -0
  144. package/src/workspace.ts +13 -11
  145. package/dist/src/stream.d.ts +0 -97
  146. package/dist/src/stream.d.ts.map +0 -1
  147. package/dist/src/stream.js +0 -134
  148. package/dist/src/stream.js.map +0 -1
  149. package/dist/src/stream.spec.d.ts.map +0 -1
  150. package/dist/src/stream.spec.js +0 -60
  151. package/dist/src/stream.spec.js.map +0 -1
  152. package/src/stream.spec.ts +0 -88
  153. package/src/stream.ts +0 -170
@@ -4,25 +4,14 @@
4
4
  */
5
5
 
6
6
  /**
7
- * The dataset transfer protocol's two invariants that live in e3-types.
8
- *
9
- * Part arithmetic is shared by the client that cuts the bytes and the server
10
- * that places them, so an off-by-one on either side would corrupt uploads
11
- * silently until the commit's hash check. And protocol 2 only adds variant
12
- * cases: a version-1 client decodes a version-1 answer from a new server, and a
13
- * new client decodes an old server's answers, only while every added case sorts
14
- * after the version-1 cases and so leaves their tags unchanged.
7
+ * The dataset transfer protocol's part arithmetic, which the client that cuts
8
+ * the bytes and the server that places them share, so an off-by-one on either
9
+ * side would corrupt uploads silently until the commit's hash check.
15
10
  */
16
11
 
17
12
  import { describe, it } from 'node:test';
18
13
  import * as assert from 'node:assert';
19
- import { NullType, StringType, StructType, VariantType, decodeBeast2For, encodeBeast2For, variant } from '@elaraai/east';
20
- import {
21
- TransferDoneResponseType,
22
- TransferUploadResponseType,
23
- transferPartCount,
24
- transferPartRange,
25
- } from './transfer.js';
14
+ import { transferPartCount, transferPartRange } from './transfer.js';
26
15
 
27
16
  describe('transferPartCount / transferPartRange', () => {
28
17
  it('cuts an upload into full parts and a remainder', () => {
@@ -60,39 +49,3 @@ describe('transferPartCount / transferPartRange', () => {
60
49
  });
61
50
  });
62
51
  });
63
-
64
- describe('transfer wire compatibility across protocol versions', () => {
65
- // The version-1 shapes, as a client and server built before protocol 2 hold them.
66
- const UploadResponseV1 = VariantType({
67
- completed: NullType,
68
- upload: StructType({ id: StringType, uploadUrl: StringType }),
69
- });
70
- const DoneResponseV1 = VariantType({
71
- completed: NullType,
72
- error: StructType({ message: StringType }),
73
- });
74
-
75
- it('keeps the init answers a version-1 client decodes', () => {
76
- const upload = variant('upload', { id: 'abc', uploadUrl: 'http://h/api/uploads/abc' });
77
- assert.deepStrictEqual(
78
- decodeBeast2For(UploadResponseV1)(encodeBeast2For(TransferUploadResponseType)(upload)),
79
- upload,
80
- );
81
- assert.deepStrictEqual(
82
- decodeBeast2For(TransferUploadResponseType)(encodeBeast2For(UploadResponseV1)(upload)),
83
- upload,
84
- );
85
- const completed = variant('completed', null);
86
- assert.deepStrictEqual(
87
- decodeBeast2For(UploadResponseV1)(encodeBeast2For(TransferUploadResponseType)(completed)),
88
- completed,
89
- );
90
- });
91
-
92
- it('keeps the commit answers a version-1 client decodes', () => {
93
- for (const done of [variant('completed', null), variant('error', { message: 'hash mismatch' })] as const) {
94
- assert.deepStrictEqual(decodeBeast2For(DoneResponseV1)(encodeBeast2For(TransferDoneResponseType)(done)), done);
95
- assert.deepStrictEqual(decodeBeast2For(TransferDoneResponseType)(encodeBeast2For(DoneResponseV1)(done)), done);
96
- }
97
- });
98
- });
package/src/transfer.ts CHANGED
@@ -9,24 +9,24 @@
9
9
  * Used by both the API server and client for large dataset uploads
10
10
  * that exceed inline body size limits.
11
11
  *
12
- * Two protocol versions share these types. A client names the version it speaks
13
- * with `?protocol=N` on the init and commit requests (a request without it is
14
- * version 1), and a server answers only in the forms that version understands —
15
- * every case version 2 adds sorts after the version-1 cases, so the tags a
16
- * version-1 client decodes keep their numbers.
12
+ * A client names the protocol version it speaks with `?protocol=N` on the init
13
+ * and commit requests, and its release beside it (`&release=`). A server
14
+ * refuses a request that names another version, or none, naming both
15
+ * releases and the fix. The release decides nothing, so an older client and a
16
+ * newer server that speak one version work together.
17
17
  */
18
18
 
19
19
  import { VariantType, StructType, StringType, IntegerType, NullType, DictType, type ValueTypeOf } from '@elaraai/east';
20
20
 
21
21
  /**
22
- * The dataset transfer protocol version this build speaks.
22
+ * The dataset transfer protocol version this build speaks, and the only one.
23
23
  *
24
24
  * @remarks
25
- * Version 2 lets the server plan an upload as parts — each sent to its own URL
26
- * with the request headers the server names, so an object store can bind a
27
- * checksum to a single PUT or take a multipart upload larger than one PUT
28
- * allows — and lets a commit answer `processing` while the server verifies the
29
- * bytes, for the client to poll.
25
+ * The server plans an upload as parts — each sent to its own URL with the
26
+ * request headers the server names, so an object store can bind a checksum to
27
+ * a single PUT or take a multipart upload larger than one PUT allows — and a
28
+ * commit may answer `processing` while the server verifies the bytes, for the
29
+ * client to poll.
30
30
  */
31
31
  export const TRANSFER_PROTOCOL_VERSION = 2;
32
32
 
@@ -81,11 +81,9 @@ export type TransferUploadRequest = ValueTypeOf<typeof TransferUploadRequestType
81
81
  * Transfer upload init response.
82
82
  *
83
83
  * - `completed`: Object already exists (dedup), dataset ref updated
84
- * - `upload`: Staging slot created; the client PUTs every byte to `uploadUrl`,
85
- * then commits
86
- * - `upload_parts` (protocol 2): the client sends the bytes as parts of
87
- * `partBytes` bytes each (the last part holds the remainder, and an upload no
88
- * larger than `partBytes` is one part). Part `n` (1-based) is the byte range
84
+ * - `upload_parts`: the client sends the bytes as parts of `partBytes` bytes
85
+ * each (the last part holds the remainder, and an upload no larger than
86
+ * `partBytes` is one part). Part `n` (1-based) is the byte range
89
87
  * `[(n - 1) * partBytes, min(size, n * partBytes))`; its URL and required
90
88
  * headers come from `GET …/upload/<id>/parts/<n>`. Parts may be sent in any
91
89
  * order and concurrently, and re-sending a part replaces it. The client
@@ -93,10 +91,6 @@ export type TransferUploadRequest = ValueTypeOf<typeof TransferUploadRequestType
93
91
  */
94
92
  export const TransferUploadResponseType = VariantType({
95
93
  completed: NullType,
96
- upload: StructType({
97
- id: StringType,
98
- uploadUrl: StringType,
99
- }),
100
94
  upload_parts: StructType({
101
95
  id: StringType,
102
96
  partBytes: IntegerType,
@@ -105,7 +99,7 @@ export const TransferUploadResponseType = VariantType({
105
99
  export type TransferUploadResponse = ValueTypeOf<typeof TransferUploadResponseType>;
106
100
 
107
101
  /**
108
- * Where and how to send one part of a protocol-2 upload.
102
+ * Where and how to send one part of an upload.
109
103
  *
110
104
  * @property url - The URL the client PUTs the part's bytes to, without an
111
105
  * `Authorization` header (it may be a presigned object-store URL)
@@ -124,7 +118,7 @@ export type TransferPartResponse = ValueTypeOf<typeof TransferPartResponseType>;
124
118
  *
125
119
  * - `completed`: Hash verified, object stored, dataset ref updated
126
120
  * - `error`: Hash mismatch or other failure
127
- * - `processing` (protocol 2): the server is still verifying the bytes; poll
121
+ * - `processing`: the server is still verifying the bytes; poll
128
122
  * `GET …/upload/<id>` until it answers `completed` or `error`
129
123
  */
130
124
  export const TransferDoneResponseType = VariantType({
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+
6
+ import { describe, it } from 'node:test';
7
+ import assert from 'node:assert/strict';
8
+ import { encodeBeast2For, equalFor, none, some, variant } from '@elaraai/east';
9
+ import { UNIT_PLAN_KIND, UnitPlanType, decodeUnitPlan, encodeUnitPlan, type UnitPlan } from './unit-plan.js';
10
+
11
+ describe('unit plans', () => {
12
+ it('round-trips each stage', () => {
13
+ const plans: UnitPlan[] = [
14
+ { kind: UNIT_PLAN_KIND, task: 'a1', inputs: 'b2', stage: variant('pieces', [['c3', 'd4'], ['e5', 'd4']]), previous: none, peakBytes: none },
15
+ {
16
+ kind: UNIT_PLAN_KIND, task: 'a1', inputs: 'b2',
17
+ stage: variant('merge', { level: 1n, levels: 2n, groups: [{ range: some('f6'), entries: ['g7', 'h8'] }, { range: none, entries: ['i9'] }] }),
18
+ previous: some('j0'),
19
+ peakBytes: some(52_428_800n),
20
+ },
21
+ ];
22
+ for (const plan of plans) {
23
+ assert.ok(equalFor(UnitPlanType)(decodeUnitPlan(encodeUnitPlan(plan)), plan));
24
+ }
25
+ });
26
+
27
+ it('refuses an object of another kind', () => {
28
+ const other = encodeBeast2For(UnitPlanType)({ kind: 'task', task: 'a1', inputs: 'b2', stage: variant('pieces', []), previous: none, peakBytes: none });
29
+ assert.throws(() => decodeUnitPlan(other), { message: "the object is not a unit plan: its kind is 'task', not '$plan'" });
30
+ });
31
+ });
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+
6
+ /**
7
+ * The unit graph of a task split into pieces, a stage at a time.
8
+ *
9
+ * A split task runs in stages: its pieces, and then, for a set, a dict or a
10
+ * fold, each level of the merges that assemble their outputs. Each stage's
11
+ * units are one of these objects, written when the stage starts and named by
12
+ * the task's entry in the dataflow's execution state. So resuming a stage reads
13
+ * this object back, and finds the units that finished in the execution cache.
14
+ * Each names the plan of the stage before it, and the task's `success` record
15
+ * names the last, so every stage the task ran is found from its record, and
16
+ * with them the units gc keeps beside it.
17
+ *
18
+ * It names other objects, so it carries a `kind` tag the garbage collector
19
+ * dispatches on.
20
+ *
21
+ * @packageDocumentation
22
+ */
23
+
24
+ import { ArrayType, IntegerType, OptionType, StringType, StructType, VariantType, decodeBeast2For, encodeBeast2For, type ValueTypeOf } from '@elaraai/east';
25
+
26
+ /** The kind tag every unit plan carries. */
27
+ export const UNIT_PLAN_KIND = '$plan';
28
+
29
+ /** Parts a merge level assembles into one: a group of the pieces' outputs
30
+ * whose keys overlap, over one key range, or a fold's partials. */
31
+ export const UnitPlanGroupType = StructType({
32
+ /** The hash of the key range the group's merges run over — `{from, to}`
33
+ * over the parts' key type — or `none` to merge the parts whole. */
34
+ range: OptionType(StringType),
35
+ /** The parts, in the order they fold: each unit of the level merges a run
36
+ * of them, and a run of one passes through. */
37
+ entries: ArrayType(StringType),
38
+ });
39
+ export type UnitPlanGroupType = typeof UnitPlanGroupType;
40
+ export type UnitPlanGroup = ValueTypeOf<typeof UnitPlanGroupType>;
41
+
42
+ /**
43
+ * A stage of a split task.
44
+ *
45
+ * - `pieces`: each piece's inputs, in the task's input order — a partitioned
46
+ * input's piece of it, and every other input as it is.
47
+ * - `merge`: one level of the merges that assemble the pieces' outputs, and
48
+ * the groups it merges, in key order.
49
+ */
50
+ export const UnitPlanStageType = VariantType({
51
+ pieces: ArrayType(ArrayType(StringType)),
52
+ merge: StructType({
53
+ /** The level, from 1. */
54
+ level: IntegerType,
55
+ /** The number of levels the merges take. */
56
+ levels: IntegerType,
57
+ /** The groups, in key order. */
58
+ groups: ArrayType(UnitPlanGroupType),
59
+ }),
60
+ });
61
+ export type UnitPlanStageType = typeof UnitPlanStageType;
62
+ export type UnitPlanStage = ValueTypeOf<typeof UnitPlanStageType>;
63
+
64
+ /**
65
+ * A stage of a split task's unit graph, stored as an object.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * import { none, variant } from '@elaraai/east';
70
+ *
71
+ * const plan: UnitPlan = {
72
+ * kind: UNIT_PLAN_KIND,
73
+ * task: '5e7a3b…',
74
+ * inputs: '9c01de…',
75
+ * stage: variant('pieces', [['a1b2…'], ['c3d4…']]),
76
+ * previous: none,
77
+ * peakBytes: none,
78
+ * };
79
+ * ```
80
+ */
81
+ export const UnitPlanType = StructType({
82
+ /** Always {@link UNIT_PLAN_KIND}. */
83
+ kind: StringType,
84
+ /** The task object's hash. */
85
+ task: StringType,
86
+ /** The task's inputs hash: the execution the plan belongs to. */
87
+ inputs: StringType,
88
+ /** The stage. */
89
+ stage: UnitPlanStageType,
90
+ /** The plan of the stage before this one; `none` for the pieces. */
91
+ previous: OptionType(StringType),
92
+ /** The largest peak resident memory, in bytes, a unit of the stages before
93
+ * this one reached, as their execution records hold it; `none` for the
94
+ * pieces, or when no unit reported one. A task taken up at this stage
95
+ * starts its own peak from it, so its record counts every stage wherever
96
+ * it was taken up. */
97
+ peakBytes: OptionType(IntegerType),
98
+ });
99
+ export type UnitPlanType = typeof UnitPlanType;
100
+ export type UnitPlan = ValueTypeOf<typeof UnitPlanType>;
101
+
102
+ /** Encodes a {@link UnitPlanType} object for the object store. */
103
+ export const encodeUnitPlan: (plan: UnitPlan) => Uint8Array = encodeBeast2For(UnitPlanType);
104
+
105
+ const decodeUnitPlanValue = decodeBeast2For(UnitPlanType);
106
+
107
+ /**
108
+ * Decodes a unit plan.
109
+ *
110
+ * @param data - the stored bytes
111
+ * @returns the plan
112
+ * @throws {Error} When the bytes are not a unit plan, or carry another kind
113
+ * tag.
114
+ */
115
+ export function decodeUnitPlan(data: Uint8Array): UnitPlan {
116
+ const plan = decodeUnitPlanValue(data);
117
+ if (plan.kind !== UNIT_PLAN_KIND) {
118
+ throw new Error(`the object is not a unit plan: its kind is '${plan.kind}', not '${UNIT_PLAN_KIND}'`);
119
+ }
120
+ return plan;
121
+ }
package/src/workspace.ts CHANGED
@@ -6,23 +6,17 @@
6
6
  /**
7
7
  * Workspace state type definitions.
8
8
  *
9
- * A workspace is a mutable working copy of a package. The state tracks:
10
- * - Which package was deployed (immutable reference via hash)
11
- * - When the deployment occurred
12
- * - Current root data tree hash
13
- * - When the root was last updated
9
+ * A workspace is a mutable working copy of a package. Its record is `none`
10
+ * from its creation until a package is deployed to it, and then its state:
11
+ * which package was deployed, when, and the latest dataflow run.
14
12
  *
15
- * State file location: workspaces/<name>/state.beast2
16
- * No state file = workspace exists but not yet deployed.
13
+ * A local repository keeps the record at `workspaces/<name>.beast2`.
17
14
  */
18
15
 
19
16
  import { StructType, StringType, DateTimeType, OptionType, ValueTypeOf } from '@elaraai/east';
20
17
 
21
18
  /**
22
- * Workspace state stored in workspaces/<name>/state.beast2
23
- *
24
- * Contains both deployment info and current data root in a single
25
- * atomic unit to ensure consistency.
19
+ * A deployed workspace's state.
26
20
  *
27
21
  * Future audit trail support:
28
22
  * When we implement full audit trail, this state will move to the object
@@ -48,3 +42,11 @@ export const WorkspaceStateType = StructType({
48
42
  });
49
43
 
50
44
  export type WorkspaceState = ValueTypeOf<typeof WorkspaceStateType>;
45
+
46
+ /**
47
+ * A workspace's record: `none` until a package is deployed to it, and then
48
+ * its state.
49
+ */
50
+ export const WorkspaceRecordType = OptionType(WorkspaceStateType);
51
+
52
+ export type WorkspaceRecord = ValueTypeOf<typeof WorkspaceRecordType>;
@@ -1,97 +0,0 @@
1
- /**
2
- * Copyright (c) 2025 Elara AI Pty Ltd
3
- * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
- */
5
- /**
6
- * The stream and merge commands (issue #770) — the builders of every argv a
7
- * stream execution spawns (an authored `streamTask`'s) and of the merge
8
- * command a partitioned task's keyed fan-in runs per key range, both built
9
- * at export time and carried in the package like any other command IR.
10
- */
11
- import { EastIR } from '@elaraai/east';
12
- import { type RunnerValue } from './runner.js';
13
- /**
14
- * How a stream execution's emit sink treats equal keys: `none` — a duplicate
15
- * is an error; `function` — the merge IR (wire input 1) folds adjacent equal
16
- * Dict keys, passed to the runner as `--merge`; `union` — adjacent equal Set
17
- * elements collapse to the first, `--union`.
18
- */
19
- export type StreamMergeMode = 'none' | 'function' | 'union';
20
- /**
21
- * The shape of a stream command.
22
- *
23
- * @remarks
24
- * The wire inputs a stream execution stages are laid out `[body IR, merge IR
25
- * (function mode only), ...-i inputs]`; `stream` names whether the first of
26
- * the `-i` inputs is the one the runner opens lazily.
27
- */
28
- export interface StreamCommandSpec {
29
- /** The output collection kind the emit sink writes. */
30
- emit: 'array' | 'set' | 'dict';
31
- /** How equal keys fold — see {@link StreamMergeMode}. */
32
- merge: StreamMergeMode;
33
- /** The `-i` input the runner feeds lazily: none, or the first. */
34
- stream: 'none' | 'first';
35
- }
36
- /**
37
- * Builds the command IR of a stream execution: `(input_paths, output_path)
38
- * -> argv`.
39
- *
40
- * The argv is `[...runner, '--emit', <emit>, '--merge' <merge IR path> |
41
- * '--union', '--stream' '0' when the first -i input streams, '-i' <path> for
42
- * each -i input, '-o', <output>, <body IR path>]` — the body IR is wire
43
- * input 0, the merge IR wire input 1 in function mode, and the `-i` inputs
44
- * follow. Built with `East.function` exactly as a task command is.
45
- *
46
- * @param runner - the stock runner the execution spawns
47
- * @param spec - the emit kind, the merge mode and the streamed input
48
- * @returns the command IR
49
- *
50
- * @example
51
- * ```ts
52
- * import { variant } from '@elaraai/east';
53
- *
54
- * const command = streamCommandIr(variant('east_c', { platforms: [] }), { emit: 'dict', merge: 'function', stream: 'first' });
55
- * command.compile([])(['body.beast2', 'merge.beast2', 'a.beast2'], 'out.beast2');
56
- * // ['east-c', 'run', '--emit', 'dict', '--merge', 'merge.beast2', '--stream', '0',
57
- * // '-i', 'a.beast2', '-o', 'out.beast2', 'body.beast2']
58
- * ```
59
- */
60
- export declare function streamCommandIr(runner: RunnerValue, spec: StreamCommandSpec): EastIR<[string[], string], string[]>;
61
- /**
62
- * Builds the command IR of a merge execution — the runner's `merge` command
63
- * over sorted partials of one Set or Dict type, within a key range:
64
- * `(input_paths, output_path) -> argv`.
65
- *
66
- * The argv is `[...runner merge, '--merge' <merge IR path> | '--union',
67
- * '--range' <range path>, '-i' <path> for each partial, '-o', <output>]`. In
68
- * `function` mode wire input 0 is the merge IR `(K, V, V) -> V`, wire input
69
- * 1 the key range and the partials follow; in `union` mode wire input 0 is
70
- * the key range and every other wire input is a partial. The key range is a
71
- * blob of `Struct{from: Option<K>, to: Option<K>}` over the output's key
72
- * type: only the keys in `[from, to)` merge, each partial sought to the
73
- * segment owning `from`, and an absent bound is open — a component that
74
- * merges whole takes the open range. Equal keys across partials fold in
75
- * input order, and the output is byte-identical to what the runner's emit
76
- * sink writes for the same entries emitted ascending. A partitioned task's
77
- * SDK writes this IR into its metadata at export, and the orchestrator runs
78
- * it as an ordinary execution per key range of a group of partials.
79
- *
80
- * @param runner - the stock runner whose `merge` command runs
81
- * @param mode - `function` (a Dict output, folded with the merge IR) or
82
- * `union` (a Set output, the first of equal elements standing)
83
- * @returns the command IR
84
- * @throws {Error} When the runner is `custom` — it has no merge command.
85
- *
86
- * @example
87
- * ```ts
88
- * import { variant } from '@elaraai/east';
89
- *
90
- * const command = mergeCommandIr(variant('east_c', { platforms: [] }), 'function');
91
- * command.compile([])(['merge.beast2', 'range.beast2', 'p0.beast2', 'p1.beast2'], 'out.beast2');
92
- * // ['east-c', 'merge', '--merge', 'merge.beast2', '--range', 'range.beast2',
93
- * // '-i', 'p0.beast2', '-i', 'p1.beast2', '-o', 'out.beast2']
94
- * ```
95
- */
96
- export declare function mergeCommandIr(runner: RunnerValue, mode: 'function' | 'union'): EastIR<[string[], string], string[]>;
97
- //# sourceMappingURL=stream.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/stream.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AAEH,OAAO,EAAmB,MAAM,EAAc,MAAM,eAAe,CAAC;AACpE,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;AAE5D;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,IAAI,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IAC/B,yDAAyD;IACzD,KAAK,EAAE,eAAe,CAAC;IACvB,kEAAkE;IAClE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAqClH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CA+BpH"}
@@ -1,134 +0,0 @@
1
- /**
2
- * Copyright (c) 2025 Elara AI Pty Ltd
3
- * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
- */
5
- /**
6
- * The stream and merge commands (issue #770) — the builders of every argv a
7
- * stream execution spawns (an authored `streamTask`'s) and of the merge
8
- * command a partitioned task's keyed fan-in runs per key range, both built
9
- * at export time and carried in the package like any other command IR.
10
- */
11
- import { ArrayType, East, StringType } from '@elaraai/east';
12
- import { runnerToArgv } from './runner.js';
13
- /**
14
- * Builds the command IR of a stream execution: `(input_paths, output_path)
15
- * -> argv`.
16
- *
17
- * The argv is `[...runner, '--emit', <emit>, '--merge' <merge IR path> |
18
- * '--union', '--stream' '0' when the first -i input streams, '-i' <path> for
19
- * each -i input, '-o', <output>, <body IR path>]` — the body IR is wire
20
- * input 0, the merge IR wire input 1 in function mode, and the `-i` inputs
21
- * follow. Built with `East.function` exactly as a task command is.
22
- *
23
- * @param runner - the stock runner the execution spawns
24
- * @param spec - the emit kind, the merge mode and the streamed input
25
- * @returns the command IR
26
- *
27
- * @example
28
- * ```ts
29
- * import { variant } from '@elaraai/east';
30
- *
31
- * const command = streamCommandIr(variant('east_c', { platforms: [] }), { emit: 'dict', merge: 'function', stream: 'first' });
32
- * command.compile([])(['body.beast2', 'merge.beast2', 'a.beast2'], 'out.beast2');
33
- * // ['east-c', 'run', '--emit', 'dict', '--merge', 'merge.beast2', '--stream', '0',
34
- * // '-i', 'a.beast2', '-o', 'out.beast2', 'body.beast2']
35
- * ```
36
- */
37
- export function streamCommandIr(runner, spec) {
38
- const prefix = [
39
- ...runnerToArgv(runner),
40
- '--emit', spec.emit,
41
- ...(spec.merge === 'union' ? ['--union'] : []),
42
- ];
43
- // The merge mode and the streamed input are known here, so the flags they
44
- // add are emitted by branching at build time — only the merge IR's PATH is
45
- // a run-time value, and only the -i inputs need a loop.
46
- const mergeInput = spec.merge === 'function' ? 1n : null;
47
- const firstInput = mergeInput === null ? 1n : 2n;
48
- const command = East.function([ArrayType(StringType), StringType], ArrayType(StringType), ($, input_paths, output_path) => {
49
- const argv = $.let(prefix, ArrayType(StringType));
50
- if (mergeInput !== null) {
51
- $(argv.pushLast('--merge'));
52
- $(argv.pushLast(input_paths.get(mergeInput)));
53
- }
54
- if (spec.stream === 'first') {
55
- $(argv.pushLast('--stream'));
56
- $(argv.pushLast('0'));
57
- }
58
- const i = $.let(firstInput);
59
- $.while(East.less(i, input_paths.size()), $ => {
60
- $(argv.pushLast('-i'));
61
- $(argv.pushLast(input_paths.get(i)));
62
- $.assign(i, i.add(1n));
63
- });
64
- $(argv.pushLast('-o'));
65
- $(argv.pushLast(output_path));
66
- $(argv.pushLast(input_paths.get(0n)));
67
- $.return(argv);
68
- });
69
- return command.toIR();
70
- }
71
- /**
72
- * Builds the command IR of a merge execution — the runner's `merge` command
73
- * over sorted partials of one Set or Dict type, within a key range:
74
- * `(input_paths, output_path) -> argv`.
75
- *
76
- * The argv is `[...runner merge, '--merge' <merge IR path> | '--union',
77
- * '--range' <range path>, '-i' <path> for each partial, '-o', <output>]`. In
78
- * `function` mode wire input 0 is the merge IR `(K, V, V) -> V`, wire input
79
- * 1 the key range and the partials follow; in `union` mode wire input 0 is
80
- * the key range and every other wire input is a partial. The key range is a
81
- * blob of `Struct{from: Option<K>, to: Option<K>}` over the output's key
82
- * type: only the keys in `[from, to)` merge, each partial sought to the
83
- * segment owning `from`, and an absent bound is open — a component that
84
- * merges whole takes the open range. Equal keys across partials fold in
85
- * input order, and the output is byte-identical to what the runner's emit
86
- * sink writes for the same entries emitted ascending. A partitioned task's
87
- * SDK writes this IR into its metadata at export, and the orchestrator runs
88
- * it as an ordinary execution per key range of a group of partials.
89
- *
90
- * @param runner - the stock runner whose `merge` command runs
91
- * @param mode - `function` (a Dict output, folded with the merge IR) or
92
- * `union` (a Set output, the first of equal elements standing)
93
- * @returns the command IR
94
- * @throws {Error} When the runner is `custom` — it has no merge command.
95
- *
96
- * @example
97
- * ```ts
98
- * import { variant } from '@elaraai/east';
99
- *
100
- * const command = mergeCommandIr(variant('east_c', { platforms: [] }), 'function');
101
- * command.compile([])(['merge.beast2', 'range.beast2', 'p0.beast2', 'p1.beast2'], 'out.beast2');
102
- * // ['east-c', 'merge', '--merge', 'merge.beast2', '--range', 'range.beast2',
103
- * // '-i', 'p0.beast2', '-i', 'p1.beast2', '-o', 'out.beast2']
104
- * ```
105
- */
106
- export function mergeCommandIr(runner, mode) {
107
- const prefix = [
108
- ...runnerToArgv(runner, 'merge'),
109
- ...(mode === 'union' ? ['--union'] : []),
110
- ];
111
- const mergeInput = mode === 'function' ? 0n : null;
112
- const rangeInput = mergeInput === null ? 0n : 1n;
113
- const firstInput = rangeInput + 1n;
114
- const command = East.function([ArrayType(StringType), StringType], ArrayType(StringType), ($, input_paths, output_path) => {
115
- const argv = $.let(prefix, ArrayType(StringType));
116
- if (mergeInput !== null) {
117
- $(argv.pushLast('--merge'));
118
- $(argv.pushLast(input_paths.get(mergeInput)));
119
- }
120
- $(argv.pushLast('--range'));
121
- $(argv.pushLast(input_paths.get(rangeInput)));
122
- const i = $.let(firstInput);
123
- $.while(East.less(i, input_paths.size()), $ => {
124
- $(argv.pushLast('-i'));
125
- $(argv.pushLast(input_paths.get(i)));
126
- $.assign(i, i.add(1n));
127
- });
128
- $(argv.pushLast('-o'));
129
- $(argv.pushLast(output_path));
130
- $.return(argv);
131
- });
132
- return command.toIR();
133
- }
134
- //# sourceMappingURL=stream.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/stream.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"stream.spec.d.ts","sourceRoot":"","sources":["../../src/stream.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -1,60 +0,0 @@
1
- /**
2
- * Copyright (c) 2025 Elara AI Pty Ltd
3
- * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
- */
5
- /**
6
- * The stream and merge command builders (issue #770): the argv a stream
7
- * execution spawns for each merge mode and streamed-input choice, and the
8
- * argv a merge execution spawns over sorted partials within a key range.
9
- */
10
- import { describe, it } from 'node:test';
11
- import assert from 'node:assert/strict';
12
- import { variant } from '@elaraai/east';
13
- import { mergeCommandIr, streamCommandIr } from './stream.js';
14
- const EAST_C = variant('east_c', { platforms: ['east-c-std'] });
15
- /** The argv a stream command evaluates to for the staged `inputs`. */
16
- function argvOf(runner, spec, inputs) {
17
- return streamCommandIr(runner, spec).compile([])(inputs, 'out.beast2');
18
- }
19
- /** The argv a merge command evaluates to for the staged `inputs`. */
20
- function mergeArgvOf(runner, mode, inputs) {
21
- return mergeCommandIr(runner, mode).compile([])(inputs, 'out.beast2');
22
- }
23
- describe('streamCommandIr', () => {
24
- it('builds a folding dict argv: the merge IR as --merge, the first input streamed', () => {
25
- assert.deepEqual(argvOf(EAST_C, { emit: 'dict', merge: 'function', stream: 'first' }, ['body.beast2', 'merge.beast2', 'rows.beast2', 'other.beast2']), ['east-c', 'run', '-p', 'east-c-std', '--emit', 'dict', '--merge', 'merge.beast2', '--stream', '0',
26
- '-i', 'rows.beast2', '-i', 'other.beast2', '-o', 'out.beast2', 'body.beast2']);
27
- });
28
- it('builds a union set argv streaming the first input', () => {
29
- assert.deepEqual(argvOf(EAST_C, { emit: 'set', merge: 'union', stream: 'first' }, ['body.beast2', 'stream.beast2', 'other.beast2']), ['east-c', 'run', '-p', 'east-c-std', '--emit', 'set', '--union', '--stream', '0',
30
- '-i', 'stream.beast2', '-i', 'other.beast2', '-o', 'out.beast2', 'body.beast2']);
31
- });
32
- it('builds a producer argv with no merge flag and no streamed input', () => {
33
- assert.deepEqual(argvOf(EAST_C, { emit: 'array', merge: 'none', stream: 'none' }, ['body.beast2', 'config.beast2']), ['east-c', 'run', '-p', 'east-c-std', '--emit', 'array', '-i', 'config.beast2', '-o', 'out.beast2', 'body.beast2']);
34
- });
35
- it('starts from the runner argv of every stock runtime', () => {
36
- const node = variant('east_node', { platforms: ['@elaraai/east-node-std'] });
37
- const argv = argvOf(node, { emit: 'set', merge: 'none', stream: 'first' }, ['body.beast2', 'rows.beast2']);
38
- assert.deepEqual(argv.slice(0, 6), ['east-node', 'run', '-p', '@elaraai/east-node-std', '--emit', 'set']);
39
- });
40
- });
41
- describe('mergeCommandIr', () => {
42
- it('builds a dict merge argv: the merge IR as --merge, the key range as --range, every other input a partial', () => {
43
- assert.deepEqual(mergeArgvOf(EAST_C, 'function', ['merge.beast2', 'range.beast2', 'p0.beast2', 'p1.beast2', 'p2.beast2']), ['east-c', 'merge', '-p', 'east-c-std', '--merge', 'merge.beast2', '--range', 'range.beast2',
44
- '-i', 'p0.beast2', '-i', 'p1.beast2', '-i', 'p2.beast2', '-o', 'out.beast2']);
45
- });
46
- it('builds a set union argv: the key range first, every other input a partial', () => {
47
- assert.deepEqual(mergeArgvOf(EAST_C, 'union', ['range.beast2', 'p0.beast2', 'p1.beast2']), ['east-c', 'merge', '-p', 'east-c-std', '--union', '--range', 'range.beast2', '-i', 'p0.beast2', '-i', 'p1.beast2', '-o', 'out.beast2']);
48
- });
49
- it('runs the merge command of every stock runtime', () => {
50
- const py = variant('east_py', { platforms: ['east-py-std'] });
51
- assert.deepEqual(mergeArgvOf(py, 'union', ['range.beast2', 'p0.beast2']).slice(0, 4), ['east-py', 'merge', '-p', 'east-py-std']);
52
- const node = variant('east_node', { platforms: [] });
53
- assert.deepEqual(mergeArgvOf(node, 'function', ['merge.beast2', 'range.beast2', 'p0.beast2']).slice(0, 2), ['east-node', 'merge']);
54
- });
55
- it('refuses a custom runner, which has no merge command', () => {
56
- const custom = variant('custom', { command: ['uv', 'run', 'east-py', 'run'] });
57
- assert.throws(() => mergeCommandIr(custom, 'union'), { message: 'a custom runner has no merge command' });
58
- });
59
- });
60
- //# sourceMappingURL=stream.spec.js.map