@funkai/agents 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/.generated/req.txt +1 -0
  2. package/.turbo/turbo-build.log +21 -0
  3. package/.turbo/turbo-test$colon$coverage.log +109 -0
  4. package/.turbo/turbo-test.log +141 -0
  5. package/.turbo/turbo-typecheck.log +4 -0
  6. package/CHANGELOG.md +16 -0
  7. package/ISSUES.md +540 -0
  8. package/LICENSE +21 -0
  9. package/README.md +128 -0
  10. package/banner.svg +97 -0
  11. package/coverage/lcov-report/base.css +224 -0
  12. package/coverage/lcov-report/block-navigation.js +87 -0
  13. package/coverage/lcov-report/core/agents/base/agent.ts.html +1705 -0
  14. package/coverage/lcov-report/core/agents/base/index.html +146 -0
  15. package/coverage/lcov-report/core/agents/base/output.ts.html +256 -0
  16. package/coverage/lcov-report/core/agents/base/utils.ts.html +694 -0
  17. package/coverage/lcov-report/core/agents/flow/engine.ts.html +928 -0
  18. package/coverage/lcov-report/core/agents/flow/flow-agent.ts.html +1462 -0
  19. package/coverage/lcov-report/core/agents/flow/index.html +146 -0
  20. package/coverage/lcov-report/core/agents/flow/messages.ts.html +508 -0
  21. package/coverage/lcov-report/core/agents/flow/steps/factory.ts.html +1975 -0
  22. package/coverage/lcov-report/core/agents/flow/steps/index.html +116 -0
  23. package/coverage/lcov-report/core/index.html +131 -0
  24. package/coverage/lcov-report/core/logger.ts.html +541 -0
  25. package/coverage/lcov-report/core/models/providers/index.html +116 -0
  26. package/coverage/lcov-report/core/models/providers/openai.ts.html +337 -0
  27. package/coverage/lcov-report/core/provider/index.html +131 -0
  28. package/coverage/lcov-report/core/provider/provider.ts.html +346 -0
  29. package/coverage/lcov-report/core/provider/usage.ts.html +376 -0
  30. package/coverage/lcov-report/core/tool.ts.html +577 -0
  31. package/coverage/lcov-report/favicon.png +0 -0
  32. package/coverage/lcov-report/index.html +221 -0
  33. package/coverage/lcov-report/lib/hooks.ts.html +262 -0
  34. package/coverage/lcov-report/lib/index.html +161 -0
  35. package/coverage/lcov-report/lib/middleware.ts.html +274 -0
  36. package/coverage/lcov-report/lib/runnable.ts.html +151 -0
  37. package/coverage/lcov-report/lib/trace.ts.html +520 -0
  38. package/coverage/lcov-report/prettify.css +1 -0
  39. package/coverage/lcov-report/prettify.js +2 -0
  40. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  41. package/coverage/lcov-report/sorter.js +210 -0
  42. package/coverage/lcov-report/utils/attempt.ts.html +199 -0
  43. package/coverage/lcov-report/utils/error.ts.html +421 -0
  44. package/coverage/lcov-report/utils/index.html +176 -0
  45. package/coverage/lcov-report/utils/resolve.ts.html +208 -0
  46. package/coverage/lcov-report/utils/result.ts.html +538 -0
  47. package/coverage/lcov-report/utils/zod.ts.html +178 -0
  48. package/coverage/lcov.info +1566 -0
  49. package/dist/index.d.mts +2883 -0
  50. package/dist/index.d.mts.map +1 -0
  51. package/dist/index.mjs +2312 -0
  52. package/dist/index.mjs.map +1 -0
  53. package/docs/core/agent.md +231 -0
  54. package/docs/core/hooks.md +95 -0
  55. package/docs/core/overview.md +87 -0
  56. package/docs/core/step.md +279 -0
  57. package/docs/core/tools.md +98 -0
  58. package/docs/core/workflow.md +235 -0
  59. package/docs/guides/create-agent.md +224 -0
  60. package/docs/guides/create-tool.md +137 -0
  61. package/docs/guides/create-workflow.md +374 -0
  62. package/docs/overview.md +244 -0
  63. package/docs/provider/models.md +55 -0
  64. package/docs/provider/overview.md +106 -0
  65. package/docs/provider/usage.md +100 -0
  66. package/docs/research/experimental-context.md +167 -0
  67. package/docs/research/gap-analysis.md +86 -0
  68. package/docs/research/prepare-step-and-active-tools.md +138 -0
  69. package/docs/research/sub-agent-model.md +249 -0
  70. package/docs/troubleshooting.md +60 -0
  71. package/logo.svg +17 -0
  72. package/models.config.json +18 -0
  73. package/package.json +60 -0
  74. package/scripts/generate-models.ts +324 -0
  75. package/src/core/agents/base/agent.test.ts +1522 -0
  76. package/src/core/agents/base/agent.ts +547 -0
  77. package/src/core/agents/base/output.test.ts +93 -0
  78. package/src/core/agents/base/output.ts +57 -0
  79. package/src/core/agents/base/types.test-d.ts +69 -0
  80. package/src/core/agents/base/types.ts +503 -0
  81. package/src/core/agents/base/utils.test.ts +397 -0
  82. package/src/core/agents/base/utils.ts +197 -0
  83. package/src/core/agents/flow/engine.test.ts +452 -0
  84. package/src/core/agents/flow/engine.ts +281 -0
  85. package/src/core/agents/flow/flow-agent.test.ts +1027 -0
  86. package/src/core/agents/flow/flow-agent.ts +473 -0
  87. package/src/core/agents/flow/messages.test.ts +198 -0
  88. package/src/core/agents/flow/messages.ts +141 -0
  89. package/src/core/agents/flow/steps/agent.test.ts +280 -0
  90. package/src/core/agents/flow/steps/agent.ts +87 -0
  91. package/src/core/agents/flow/steps/all.test.ts +300 -0
  92. package/src/core/agents/flow/steps/all.ts +73 -0
  93. package/src/core/agents/flow/steps/builder.ts +124 -0
  94. package/src/core/agents/flow/steps/each.test.ts +257 -0
  95. package/src/core/agents/flow/steps/each.ts +61 -0
  96. package/src/core/agents/flow/steps/factory.test-d.ts +50 -0
  97. package/src/core/agents/flow/steps/factory.test.ts +1025 -0
  98. package/src/core/agents/flow/steps/factory.ts +645 -0
  99. package/src/core/agents/flow/steps/map.test.ts +273 -0
  100. package/src/core/agents/flow/steps/map.ts +75 -0
  101. package/src/core/agents/flow/steps/race.test.ts +290 -0
  102. package/src/core/agents/flow/steps/race.ts +59 -0
  103. package/src/core/agents/flow/steps/reduce.test.ts +310 -0
  104. package/src/core/agents/flow/steps/reduce.ts +73 -0
  105. package/src/core/agents/flow/steps/result.ts +27 -0
  106. package/src/core/agents/flow/steps/step.test.ts +402 -0
  107. package/src/core/agents/flow/steps/step.ts +51 -0
  108. package/src/core/agents/flow/steps/while.test.ts +283 -0
  109. package/src/core/agents/flow/steps/while.ts +75 -0
  110. package/src/core/agents/flow/types.ts +348 -0
  111. package/src/core/logger.test.ts +163 -0
  112. package/src/core/logger.ts +152 -0
  113. package/src/core/models/index.test.ts +137 -0
  114. package/src/core/models/index.ts +152 -0
  115. package/src/core/models/providers/openai.ts +84 -0
  116. package/src/core/provider/provider.test.ts +128 -0
  117. package/src/core/provider/provider.ts +99 -0
  118. package/src/core/provider/types.ts +98 -0
  119. package/src/core/provider/usage.test.ts +304 -0
  120. package/src/core/provider/usage.ts +97 -0
  121. package/src/core/tool.test.ts +65 -0
  122. package/src/core/tool.ts +164 -0
  123. package/src/core/types.ts +66 -0
  124. package/src/index.ts +95 -0
  125. package/src/lib/context.test.ts +86 -0
  126. package/src/lib/context.ts +49 -0
  127. package/src/lib/hooks.test.ts +102 -0
  128. package/src/lib/hooks.ts +59 -0
  129. package/src/lib/middleware.test.ts +122 -0
  130. package/src/lib/middleware.ts +63 -0
  131. package/src/lib/runnable.test.ts +41 -0
  132. package/src/lib/runnable.ts +22 -0
  133. package/src/lib/trace.test.ts +291 -0
  134. package/src/lib/trace.ts +145 -0
  135. package/src/models/index.ts +123 -0
  136. package/src/models/providers/index.ts +15 -0
  137. package/src/models/providers/openai.ts +84 -0
  138. package/src/testing/context.ts +32 -0
  139. package/src/testing/index.ts +2 -0
  140. package/src/testing/logger.ts +19 -0
  141. package/src/utils/attempt.test.ts +127 -0
  142. package/src/utils/attempt.ts +38 -0
  143. package/src/utils/error.test.ts +179 -0
  144. package/src/utils/error.ts +112 -0
  145. package/src/utils/resolve.test.ts +38 -0
  146. package/src/utils/resolve.ts +41 -0
  147. package/src/utils/result.test.ts +79 -0
  148. package/src/utils/result.ts +151 -0
  149. package/src/utils/zod.test.ts +69 -0
  150. package/src/utils/zod.ts +31 -0
  151. package/tsconfig.json +25 -0
  152. package/tsdown.config.ts +15 -0
  153. package/vitest.config.ts +46 -0
@@ -0,0 +1,300 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+
3
+ import { createStepBuilder } from "@/core/agents/flow/steps/factory.js";
4
+ import { createMockCtx } from "@/testing/index.js";
5
+
6
+ describe("all()", () => {
7
+ it("resolves all entries concurrently", async () => {
8
+ const ctx = createMockCtx();
9
+ const $ = createStepBuilder({ ctx });
10
+
11
+ const result = await $.all({
12
+ id: "all-entries",
13
+ entries: [() => Promise.resolve("a"), () => Promise.resolve("b"), () => Promise.resolve("c")],
14
+ });
15
+
16
+ expect(result.ok).toBe(true);
17
+ if (!result.ok) {
18
+ return;
19
+ }
20
+ expect(result.value).toEqual(["a", "b", "c"]);
21
+ expect(result.step.type).toBe("all");
22
+ });
23
+
24
+ it("fails fast on first error", async () => {
25
+ const ctx = createMockCtx();
26
+ const $ = createStepBuilder({ ctx });
27
+
28
+ const result = await $.all({
29
+ id: "all-fail",
30
+ entries: [
31
+ () => Promise.resolve("a"),
32
+ () => Promise.reject(new Error("fail")),
33
+ () => Promise.resolve("c"),
34
+ ],
35
+ });
36
+
37
+ expect(result.ok).toBe(false);
38
+ if (result.ok) {
39
+ return;
40
+ }
41
+ expect(result.error.message).toBe("fail");
42
+ expect(result.error.stepId).toBe("all-fail");
43
+ });
44
+
45
+ it("passes abort signal to entry factories", async () => {
46
+ const ctx = createMockCtx();
47
+ const $ = createStepBuilder({ ctx });
48
+ const receivedSignals: AbortSignal[] = [];
49
+
50
+ await $.all({
51
+ id: "all-signal",
52
+ entries: [
53
+ (signal) => {
54
+ receivedSignals.push(signal);
55
+ return Promise.resolve("a");
56
+ },
57
+ (signal) => {
58
+ receivedSignals.push(signal);
59
+ return Promise.resolve("b");
60
+ },
61
+ ],
62
+ });
63
+
64
+ expect(receivedSignals).toHaveLength(2);
65
+ expect(receivedSignals[0]).toBeInstanceOf(AbortSignal);
66
+ expect(receivedSignals[1]).toBeInstanceOf(AbortSignal);
67
+ });
68
+
69
+ it("aborts signal on error", async () => {
70
+ const ctx = createMockCtx();
71
+ const $ = createStepBuilder({ ctx });
72
+ const signals: { entry: AbortSignal | undefined } = { entry: undefined };
73
+
74
+ await $.all({
75
+ id: "all-abort-on-err",
76
+ entries: [
77
+ () => Promise.reject(new Error("fail fast")),
78
+ (signal) => {
79
+ signals.entry = signal;
80
+ return new Promise((r) => setTimeout(() => r("late"), 500));
81
+ },
82
+ ],
83
+ });
84
+
85
+ if (signals.entry === undefined) {
86
+ throw new Error("Expected entry signal");
87
+ }
88
+ expect(signals.entry.aborted).toBe(true);
89
+ });
90
+
91
+ it("handles empty entries array", async () => {
92
+ const ctx = createMockCtx();
93
+ const $ = createStepBuilder({ ctx });
94
+
95
+ const result = await $.all({
96
+ id: "all-empty",
97
+ entries: [],
98
+ });
99
+
100
+ expect(result.ok).toBe(true);
101
+ if (!result.ok) {
102
+ return;
103
+ }
104
+ expect(result.value).toEqual([]);
105
+ });
106
+
107
+ it("handles single entry", async () => {
108
+ const ctx = createMockCtx();
109
+ const $ = createStepBuilder({ ctx });
110
+
111
+ const result = await $.all({
112
+ id: "all-single",
113
+ entries: [() => Promise.resolve(42)],
114
+ });
115
+
116
+ expect(result.ok).toBe(true);
117
+ if (!result.ok) {
118
+ return;
119
+ }
120
+ expect(result.value).toEqual([42]);
121
+ });
122
+
123
+ it("returns results in entry order", async () => {
124
+ const ctx = createMockCtx();
125
+ const $ = createStepBuilder({ ctx });
126
+
127
+ const result = await $.all({
128
+ id: "all-order",
129
+ entries: [
130
+ () => new Promise((r) => setTimeout(() => r("slow"), 30)),
131
+ () => Promise.resolve("fast"),
132
+ () => new Promise((r) => setTimeout(() => r("medium"), 10)),
133
+ ],
134
+ });
135
+
136
+ expect(result.ok).toBe(true);
137
+ if (!result.ok) {
138
+ return;
139
+ }
140
+ expect(result.value).toEqual(["slow", "fast", "medium"]);
141
+ });
142
+
143
+ it("propagates parent abort signal to child abort controller", async () => {
144
+ const controller = new AbortController();
145
+ const ctx = createMockCtx({ signal: controller.signal });
146
+ const $ = createStepBuilder({ ctx });
147
+ const signals: { entry: AbortSignal | undefined } = { entry: undefined };
148
+
149
+ const result = await $.all({
150
+ id: "all-parent-abort",
151
+ entries: [
152
+ (signal) => {
153
+ signals.entry = signal;
154
+ // Abort the parent after the factory captures the child signal
155
+ controller.abort();
156
+ return Promise.resolve("done");
157
+ },
158
+ ],
159
+ });
160
+
161
+ expect(result.ok).toBe(true);
162
+ if (signals.entry === undefined) {
163
+ throw new Error("Expected entry signal");
164
+ }
165
+ expect(signals.entry.aborted).toBe(true);
166
+ });
167
+
168
+ it("fires onStart and onFinish hooks", async () => {
169
+ const order: string[] = [];
170
+ const ctx = createMockCtx();
171
+ const $ = createStepBuilder({ ctx });
172
+
173
+ await $.all({
174
+ id: "all-hooks",
175
+ entries: [() => Promise.resolve("a")],
176
+ onStart: () => {
177
+ order.push("onStart");
178
+ },
179
+ onFinish: () => {
180
+ order.push("onFinish");
181
+ },
182
+ });
183
+
184
+ expect(order).toEqual(["onStart", "onFinish"]);
185
+ });
186
+
187
+ it("fires onError hook on failure", async () => {
188
+ const onError = vi.fn();
189
+ const ctx = createMockCtx();
190
+ const $ = createStepBuilder({ ctx });
191
+
192
+ await $.all({
193
+ id: "all-onerror",
194
+ entries: [() => Promise.reject(new Error("all failure"))],
195
+ onError,
196
+ });
197
+
198
+ expect(onError).toHaveBeenCalledTimes(1);
199
+ expect(onError).toHaveBeenCalledWith(
200
+ expect.objectContaining({
201
+ id: "all-onerror",
202
+ error: expect.any(Error),
203
+ }),
204
+ );
205
+ });
206
+
207
+ it("onFinish receives the results array", async () => {
208
+ const onFinish = vi.fn();
209
+ const ctx = createMockCtx();
210
+ const $ = createStepBuilder({ ctx });
211
+
212
+ await $.all({
213
+ id: "all-finish-result",
214
+ entries: [() => Promise.resolve(1), () => Promise.resolve(2)],
215
+ onFinish,
216
+ });
217
+
218
+ expect(onFinish).toHaveBeenCalledWith(
219
+ expect.objectContaining({
220
+ id: "all-finish-result",
221
+ result: [1, 2],
222
+ duration: expect.any(Number),
223
+ }),
224
+ );
225
+ });
226
+
227
+ it("records trace entry", async () => {
228
+ const ctx = createMockCtx();
229
+ const $ = createStepBuilder({ ctx });
230
+
231
+ await $.all({
232
+ id: "all-trace",
233
+ entries: [() => Promise.resolve("traced")],
234
+ });
235
+
236
+ const traceEntry = ctx.trace[0];
237
+ if (traceEntry === undefined) {
238
+ throw new Error("Expected trace entry");
239
+ }
240
+ expect(traceEntry.id).toBe("all-trace");
241
+ expect(traceEntry.type).toBe("all");
242
+ expect(traceEntry.output).toEqual(["traced"]);
243
+ });
244
+
245
+ it("passes child $ to entry factories", async () => {
246
+ const ctx = createMockCtx();
247
+ const $$ = createStepBuilder({ ctx });
248
+
249
+ await $$.all({
250
+ id: "all-child-$",
251
+ entries: [
252
+ async (_signal, $) => {
253
+ const inner = await $.step({
254
+ id: "inner-from-all",
255
+ execute: async () => "nested",
256
+ });
257
+ if (!inner.ok) {
258
+ throw new Error("inner failed");
259
+ }
260
+ return inner.value;
261
+ },
262
+ ],
263
+ });
264
+
265
+ const traceEntry = ctx.trace[0];
266
+ if (traceEntry === undefined) {
267
+ throw new Error("Expected trace entry");
268
+ }
269
+ expect(traceEntry.children).toHaveLength(1);
270
+ if (traceEntry.children === undefined) {
271
+ throw new Error("Expected children");
272
+ }
273
+ const child = traceEntry.children[0];
274
+ if (child === undefined) {
275
+ throw new Error("Expected child entry");
276
+ }
277
+ expect(child.id).toBe("inner-from-all");
278
+ });
279
+
280
+ it("handles heterogeneous return types", async () => {
281
+ const ctx = createMockCtx();
282
+ const $ = createStepBuilder({ ctx });
283
+
284
+ const result = await $.all({
285
+ id: "all-hetero",
286
+ entries: [
287
+ () => Promise.resolve("string"),
288
+ () => Promise.resolve(42),
289
+ () => Promise.resolve({ key: "value" }),
290
+ () => Promise.resolve([1, 2, 3]),
291
+ ],
292
+ });
293
+
294
+ expect(result.ok).toBe(true);
295
+ if (!result.ok) {
296
+ return;
297
+ }
298
+ expect(result.value).toEqual(["string", 42, { key: "value" }, [1, 2, 3]]);
299
+ });
300
+ });
@@ -0,0 +1,73 @@
1
+ import type { StepBuilder } from "@/core/agents/flow/steps/builder.js";
2
+
3
+ /**
4
+ * A factory that receives an abort signal and returns a promise.
5
+ *
6
+ * Used by `$.all()` and `$.race()` so the framework controls when
7
+ * work starts and can cancel entries via the signal.
8
+ *
9
+ * The optional `$` parameter provides a child step builder whose
10
+ * trace entries nest under the parent `all`/`race` step. Using it
11
+ * is recommended for correct trace hierarchy.
12
+ */
13
+ export type EntryFactory = (signal: AbortSignal, $: StepBuilder) => Promise<unknown>;
14
+
15
+ /**
16
+ * Configuration for `$.all()` — concurrent heterogeneous operations.
17
+ *
18
+ * Like `Promise.all` — takes an array of factory functions that the
19
+ * framework starts concurrently. Returns results as a tuple in the
20
+ * same order. Fails fast on the first error.
21
+ */
22
+ export interface AllConfig {
23
+ /**
24
+ * Unique step identifier.
25
+ *
26
+ * Appears in the execution trace.
27
+ */
28
+ id: string;
29
+
30
+ /**
31
+ * Array of factory functions to run concurrently.
32
+ *
33
+ * Each factory receives an `AbortSignal` and should return a
34
+ * promise. The framework starts all factories at the same time
35
+ * so timing and traces are accurate.
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * entries: [
40
+ * (signal) => $.step({ id: 'a', execute: () => fetchA(signal) }),
41
+ * (signal) => $.step({ id: 'b', execute: () => fetchB(signal) }),
42
+ * ]
43
+ * ```
44
+ */
45
+ entries: EntryFactory[];
46
+
47
+ /**
48
+ * Hook: fires when the all operation starts.
49
+ *
50
+ * @param event - Event containing the step id.
51
+ * @param event.id - The step's unique identifier.
52
+ */
53
+ onStart?: (event: { id: string }) => void | Promise<void>;
54
+
55
+ /**
56
+ * Hook: fires when all entries complete.
57
+ *
58
+ * @param event - Event containing the step id, results, and duration.
59
+ * @param event.id - The step's unique identifier.
60
+ * @param event.result - Array of results in entry order.
61
+ * @param event.duration - Wall-clock time in milliseconds.
62
+ */
63
+ onFinish?: (event: { id: string; result: unknown[]; duration: number }) => void | Promise<void>;
64
+
65
+ /**
66
+ * Hook: fires if any entry encounters an error.
67
+ *
68
+ * @param event - Event containing the step id and error.
69
+ * @param event.id - The step's unique identifier.
70
+ * @param event.error - The error that occurred.
71
+ */
72
+ onError?: (event: { id: string; error: Error }) => void | Promise<void>;
73
+ }
@@ -0,0 +1,124 @@
1
+ import type { GenerateResult } from "@/core/agents/base/types.js";
2
+ import type { AgentStepConfig } from "@/core/agents/flow/steps/agent.js";
3
+ import type { AllConfig } from "@/core/agents/flow/steps/all.js";
4
+ import type { EachConfig } from "@/core/agents/flow/steps/each.js";
5
+ import type { MapConfig } from "@/core/agents/flow/steps/map.js";
6
+ import type { RaceConfig } from "@/core/agents/flow/steps/race.js";
7
+ import type { ReduceConfig } from "@/core/agents/flow/steps/reduce.js";
8
+ import type { StepResult } from "@/core/agents/flow/steps/result.js";
9
+ import type { StepConfig } from "@/core/agents/flow/steps/step.js";
10
+ import type { WhileConfig } from "@/core/agents/flow/steps/while.js";
11
+
12
+ /**
13
+ * The `$` object — composable step utilities.
14
+ *
15
+ * Provides tracked operations that register data flow for observability.
16
+ * Every call through `$` becomes an entry in the execution trace.
17
+ *
18
+ * `$` is passed into every callback, enabling composition and nesting.
19
+ * You can always skip `$` and use plain imperative code — it just
20
+ * won't appear in the trace.
21
+ */
22
+ export interface StepBuilder {
23
+ /**
24
+ * Execute and register a single unit of work.
25
+ *
26
+ * @typeParam T - The return type of the step.
27
+ * @param config - Step configuration with id, execute function,
28
+ * and optional hooks.
29
+ * @returns A `StepResult` with `.value` containing the step's
30
+ * return value on success, or a `StepError` on failure.
31
+ */
32
+ step<T>(config: StepConfig<T>): Promise<StepResult<T>>;
33
+
34
+ /**
35
+ * Execute an agent call as a tracked operation.
36
+ *
37
+ * The framework records the agent name, input, and output in the
38
+ * trace. Calls `agent.generate()` internally and unwraps the result —
39
+ * agent errors become `StepError`, agent success becomes
40
+ * `StepResult<GenerateResult>`.
41
+ *
42
+ * @typeParam TInput - The agent's input type.
43
+ * @param config - Agent step configuration with id, agent, input,
44
+ * optional overrides, and optional hooks.
45
+ * @returns A `StepResult` wrapping the agent's `GenerateResult`.
46
+ */
47
+ agent<TInput>(config: AgentStepConfig<TInput>): Promise<StepResult<GenerateResult>>;
48
+
49
+ /**
50
+ * Parallel map — each item is a tracked operation.
51
+ *
52
+ * All items run concurrently (up to `concurrency` limit).
53
+ * Returns results in input order.
54
+ *
55
+ * @typeParam T - Input item type.
56
+ * @typeParam R - Output item type.
57
+ * @param config - Map configuration with id, input array, execute
58
+ * function, optional concurrency, and optional hooks.
59
+ * @returns A `StepResult` wrapping the array of results in input order.
60
+ */
61
+ map<T, R>(config: MapConfig<T, R>): Promise<StepResult<R[]>>;
62
+
63
+ /**
64
+ * Sequential side effects — runs one item at a time.
65
+ *
66
+ * Returns `void`. Use `$.reduce()` if you need accumulated results.
67
+ *
68
+ * @typeParam T - Input item type.
69
+ * @param config - Each configuration with id, input array, execute
70
+ * function, and optional hooks.
71
+ * @returns A `StepResult` wrapping void when all items are processed.
72
+ */
73
+ each<T>(config: EachConfig<T>): Promise<StepResult<void>>;
74
+
75
+ /**
76
+ * Sequential accumulation — each step depends on the previous result.
77
+ *
78
+ * @typeParam T - Input item type.
79
+ * @typeParam R - Accumulator/result type.
80
+ * @param config - Reduce configuration with id, input array, initial
81
+ * value, execute function, and optional hooks.
82
+ * @returns A `StepResult` wrapping the final accumulated value.
83
+ */
84
+ reduce<T, R>(config: ReduceConfig<T, R>): Promise<StepResult<R>>;
85
+
86
+ /**
87
+ * Conditional loop — runs while a condition holds.
88
+ *
89
+ * Returns the last value, or `undefined` if the condition was
90
+ * false on the first check.
91
+ *
92
+ * @typeParam T - The value type produced by each iteration.
93
+ * @param config - While configuration with id, condition, execute
94
+ * function, and optional hooks.
95
+ * @returns A `StepResult` wrapping the last iteration's value, or `undefined`.
96
+ */
97
+ while<T>(config: WhileConfig<T>): Promise<StepResult<T | undefined>>;
98
+
99
+ /**
100
+ * Run heterogeneous operations concurrently — like `Promise.all`.
101
+ *
102
+ * Entries are factory functions that receive an `AbortSignal` and
103
+ * return a promise. The framework starts all factories at the same
104
+ * time so timing and traces are accurate.
105
+ *
106
+ * @param config - All configuration with id, entry factories,
107
+ * and optional hooks.
108
+ * @returns A `StepResult` wrapping the array of results in entry order.
109
+ */
110
+ all(config: AllConfig): Promise<StepResult<unknown[]>>;
111
+
112
+ /**
113
+ * Run operations concurrently — first to finish wins.
114
+ *
115
+ * Entries are factory functions that receive an `AbortSignal`.
116
+ * The first to resolve wins; losers are cancelled by aborting
117
+ * the signal.
118
+ *
119
+ * @param config - Race configuration with id, entry factories,
120
+ * and optional hooks.
121
+ * @returns A `StepResult` wrapping the first resolved value.
122
+ */
123
+ race(config: RaceConfig): Promise<StepResult<unknown>>;
124
+ }