tubeless 0.2.12 → 0.2.13

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 (195) hide show
  1. package/dist/core/child-execution.d.ts +0 -23
  2. package/dist/core/child-execution.js +10 -12
  3. package/dist/core/child-execution.js.map +1 -1
  4. package/dist/core/child-progress.js +7 -2
  5. package/dist/core/child-progress.js.map +1 -1
  6. package/dist/core/iteration.d.ts +27 -0
  7. package/dist/core/iteration.js +111 -0
  8. package/dist/core/iteration.js.map +1 -0
  9. package/dist/core/lifecycle.d.ts +7 -5
  10. package/dist/core/lifecycle.js +36 -4
  11. package/dist/core/lifecycle.js.map +1 -1
  12. package/dist/core/pipeline-artifacts.d.ts +11 -0
  13. package/dist/core/pipeline-artifacts.js +2 -0
  14. package/dist/core/pipeline-artifacts.js.map +1 -0
  15. package/dist/core/pipeline-compiler.d.ts +1 -0
  16. package/dist/core/pipeline-compiler.js +1 -0
  17. package/dist/core/pipeline-compiler.js.map +1 -1
  18. package/dist/core/pipeline-definition-identity.d.ts +2 -2
  19. package/dist/core/pipeline-definition-identity.js +28 -5
  20. package/dist/core/pipeline-definition-identity.js.map +1 -1
  21. package/dist/core/pipeline-execute.d.ts +1 -6
  22. package/dist/core/pipeline-execute.js +28 -215
  23. package/dist/core/pipeline-execute.js.map +1 -1
  24. package/dist/core/pipeline-execution-error.d.ts +35 -0
  25. package/dist/core/pipeline-execution-error.js +195 -0
  26. package/dist/core/pipeline-execution-error.js.map +1 -0
  27. package/dist/core/pipeline-identity.d.ts +1 -0
  28. package/dist/core/pipeline-identity.js +1 -0
  29. package/dist/core/pipeline-identity.js.map +1 -1
  30. package/dist/core/pipeline-mermaid.js +4 -1
  31. package/dist/core/pipeline-mermaid.js.map +1 -1
  32. package/dist/core/pipeline-run-state.d.ts +4 -4
  33. package/dist/core/pipeline-run-state.js +10 -16
  34. package/dist/core/pipeline-run-state.js.map +1 -1
  35. package/dist/core/pipeline-step-executor.d.ts +2 -0
  36. package/dist/core/pipeline-step-executor.js +11 -3
  37. package/dist/core/pipeline-step-executor.js.map +1 -1
  38. package/dist/core/pipeline-steps.d.ts +20 -0
  39. package/dist/core/pipeline-steps.js +62 -0
  40. package/dist/core/pipeline-steps.js.map +1 -1
  41. package/dist/core/pipeline-types.d.ts +15 -2
  42. package/dist/core/pipeline-types.js.map +1 -1
  43. package/dist/core/pipeline.d.ts +4 -1
  44. package/dist/core/pipeline.js +18 -3
  45. package/dist/core/pipeline.js.map +1 -1
  46. package/dist/project/project-compiler.d.ts +3 -31
  47. package/dist/project/project-compiler.js +11 -180
  48. package/dist/project/project-compiler.js.map +1 -1
  49. package/dist/project/project-registry.d.ts +44 -0
  50. package/dist/project/project-registry.js +107 -0
  51. package/dist/project/project-registry.js.map +1 -0
  52. package/dist/project/project-step-graph.d.ts +9 -0
  53. package/dist/project/project-step-graph.js +99 -0
  54. package/dist/project/project-step-graph.js.map +1 -0
  55. package/dist/render/render.js +1 -1
  56. package/dist/render/render.js.map +1 -1
  57. package/dist/reporter/interactive-reporter.js +6 -3
  58. package/dist/reporter/interactive-reporter.js.map +1 -1
  59. package/dist/reporter/live-ticker-frame.d.ts +21 -0
  60. package/dist/reporter/live-ticker-frame.js +196 -0
  61. package/dist/reporter/live-ticker-frame.js.map +1 -0
  62. package/dist/reporter/live-ticker-protocol.d.ts +41 -0
  63. package/dist/reporter/live-ticker-protocol.js +59 -0
  64. package/dist/reporter/live-ticker-protocol.js.map +1 -0
  65. package/dist/reporter/live-ticker-worker.js +11 -25
  66. package/dist/reporter/live-ticker-worker.js.map +1 -1
  67. package/dist/reporter/live-ticker.d.ts +0 -15
  68. package/dist/reporter/live-ticker.js +11 -216
  69. package/dist/reporter/live-ticker.js.map +1 -1
  70. package/dist/reporter/reporter.js +7 -6
  71. package/dist/reporter/reporter.js.map +1 -1
  72. package/dist/run-store/definition-projection.d.ts +8 -0
  73. package/dist/run-store/definition-projection.js +89 -0
  74. package/dist/run-store/definition-projection.js.map +1 -0
  75. package/dist/run-store/run-projection.d.ts +15 -0
  76. package/dist/run-store/run-projection.js +203 -0
  77. package/dist/run-store/run-projection.js.map +1 -0
  78. package/dist/run-store/run-store-codec.d.ts +2 -0
  79. package/dist/run-store/run-store-codec.js +11 -0
  80. package/dist/run-store/run-store-codec.js.map +1 -1
  81. package/dist/run-store/run-store-event-decoder.js +3 -0
  82. package/dist/run-store/run-store-event-decoder.js.map +1 -1
  83. package/dist/run-store/run-store-reader.d.ts +7 -0
  84. package/dist/run-store/run-store-reader.js +31 -0
  85. package/dist/run-store/run-store-reader.js.map +1 -0
  86. package/dist/run-store/run-store-sqlite.js +23 -7
  87. package/dist/run-store/run-store-sqlite.js.map +1 -1
  88. package/dist/run-store/run-store.d.ts +16 -4
  89. package/dist/run-store/run-store.js +14 -263
  90. package/dist/run-store/run-store.js.map +1 -1
  91. package/dist/studio/run-store-ui-api.d.ts +13 -0
  92. package/dist/studio/run-store-ui-api.js +163 -0
  93. package/dist/studio/run-store-ui-api.js.map +1 -0
  94. package/dist/studio/run-store-ui-client-browser.js +2 -2
  95. package/dist/studio/run-store-ui-client-transport.js +28 -3
  96. package/dist/studio/run-store-ui-client-transport.js.map +1 -1
  97. package/dist/studio/run-store-ui-client.d.ts +2 -1
  98. package/dist/studio/run-store-ui-client.js +15 -9
  99. package/dist/studio/run-store-ui-client.js.map +1 -1
  100. package/dist/studio/run-store-ui-http.d.ts +11 -0
  101. package/dist/studio/run-store-ui-http.js +52 -0
  102. package/dist/studio/run-store-ui-http.js.map +1 -1
  103. package/dist/studio/run-store-ui-state.d.ts +1 -1
  104. package/dist/studio/run-store-ui-state.js +10 -28
  105. package/dist/studio/run-store-ui-state.js.map +1 -1
  106. package/dist/studio/run-store-ui.d.ts +5 -11
  107. package/dist/studio/run-store-ui.js +5 -203
  108. package/dist/studio/run-store-ui.js.map +1 -1
  109. package/dist/testing/testing.d.ts +18 -2
  110. package/dist/testing/testing.js +35 -2
  111. package/dist/testing/testing.js.map +1 -1
  112. package/dist/tracing/artifact-metadata.d.ts +28 -0
  113. package/dist/tracing/artifact-metadata.js +105 -0
  114. package/dist/tracing/artifact-metadata.js.map +1 -0
  115. package/dist/tracing/tracing-codec.d.ts +1 -1
  116. package/dist/tracing/tracing-codec.js +1 -1
  117. package/dist/tracing/tracing-codec.js.map +1 -1
  118. package/dist/tracing/tracing-constants.d.ts +1 -1
  119. package/dist/tracing/tracing-constants.js +1 -1
  120. package/dist/tracing/tracing-constants.js.map +1 -1
  121. package/dist/tracing/tracing-contracts.d.ts +3 -1
  122. package/dist/tracing/tracing-contracts.js.map +1 -1
  123. package/dist/tracing/tracing-internal.d.ts +2 -0
  124. package/dist/tracing/tracing-internal.js +36 -13
  125. package/dist/tracing/tracing-internal.js.map +1 -1
  126. package/dist/tracing/tracing-schema.d.ts +330 -49
  127. package/dist/tracing/tracing-schema.js +102 -10
  128. package/dist/tracing/tracing-schema.js.map +1 -1
  129. package/dist/workbench/workbench-command-execution.d.ts +6 -0
  130. package/dist/workbench/workbench-command-execution.js +48 -0
  131. package/dist/workbench/workbench-command-execution.js.map +1 -0
  132. package/dist/workbench/workbench-history.js +11 -18
  133. package/dist/workbench/workbench-history.js.map +1 -1
  134. package/dist/workbench/workbench-launch-session.d.ts +2 -2
  135. package/dist/workbench/workbench-launch-session.js.map +1 -1
  136. package/dist/workbench/workbench-run.d.ts +0 -4
  137. package/dist/workbench/workbench-run.js +3 -47
  138. package/dist/workbench/workbench-run.js.map +1 -1
  139. package/dist/workbench/workbench-studio-launcher.d.ts +27 -0
  140. package/dist/workbench/workbench-studio-launcher.js +95 -0
  141. package/dist/workbench/workbench-studio-launcher.js.map +1 -0
  142. package/dist/workbench/workbench-ui.js +10 -83
  143. package/dist/workbench/workbench-ui.js.map +1 -1
  144. package/docs/README.md +13 -7
  145. package/docs/agent-guide.md +69 -6
  146. package/docs/airflow.md +187 -0
  147. package/docs/api-reference.md +87 -76
  148. package/docs/api-report.json +17 -6
  149. package/docs/artifacts.md +173 -0
  150. package/docs/child-pipeline-composition.md +65 -2
  151. package/docs/comparison.md +20 -0
  152. package/docs/concepts.md +70 -2
  153. package/docs/dagster.md +161 -0
  154. package/docs/inngest.md +163 -0
  155. package/docs/llms.txt +30 -1
  156. package/docs/recipes.md +82 -33
  157. package/docs/remote-step-composition.md +6 -0
  158. package/docs/step-functions.md +190 -0
  159. package/docs/studio.md +31 -12
  160. package/docs/temporal.md +183 -0
  161. package/examples/airflow/contract.ts +46 -0
  162. package/examples/airflow/hosted.ts +70 -0
  163. package/examples/airflow/remote.ts +175 -0
  164. package/examples/airflow/tubeless_example.py +49 -0
  165. package/examples/airflow/worker.ts +24 -0
  166. package/examples/artifact-lineage.ts +70 -0
  167. package/examples/dagster/definitions.py +59 -0
  168. package/examples/dagster/hosted.ts +78 -0
  169. package/examples/dagster/pipeline.ts +62 -0
  170. package/examples/dagster/test_definitions.py +47 -0
  171. package/examples/dagster/tsconfig.build.json +10 -0
  172. package/examples/dagster/worker.ts +22 -0
  173. package/examples/inngest/client.ts +4 -0
  174. package/examples/inngest/functions.ts +65 -0
  175. package/examples/inngest/pipeline.ts +41 -0
  176. package/examples/inngest/send.ts +11 -0
  177. package/examples/inngest/server.ts +17 -0
  178. package/examples/inngest/tsconfig.build.json +10 -0
  179. package/examples/iteration.ts +52 -0
  180. package/examples/parameterized-steps.ts +96 -0
  181. package/examples/project/tubeless.project.ts +46 -0
  182. package/examples/step-functions/handler.ts +110 -0
  183. package/examples/step-functions/input.json +1 -0
  184. package/examples/step-functions/pipeline.ts +41 -0
  185. package/examples/step-functions/state-machine.asl.json +41 -0
  186. package/examples/step-functions/template.json +42 -0
  187. package/examples/step-output-overrides.ts +41 -0
  188. package/examples/temporal/activities.ts +94 -0
  189. package/examples/temporal/client.ts +19 -0
  190. package/examples/temporal/pipeline.ts +41 -0
  191. package/examples/temporal/tsconfig.build.json +10 -0
  192. package/examples/temporal/worker.ts +21 -0
  193. package/examples/temporal/workflows.ts +16 -0
  194. package/package.json +13 -4
  195. package/skills/tubeless/SKILL.md +30 -3
@@ -0,0 +1,44 @@
1
+ import type { MappedChildProgressOptions, PipelineExecutionContext, PipelineRun, PipelineRunControls, PipelineStepContext, StandardSchemaV1, StepSkipDecision } from "../core/pipeline.js";
2
+ /** Dependency values are checked at runtime rather than inferred from a project document. */
3
+ type PipelineDocumentHandler = (inputs: Record<string, unknown>, context: PipelineStepContext<object>) => unknown;
4
+ type PipelineDocumentFinalizer = (outputs: Record<string, unknown>, context: PipelineExecutionContext<object>) => unknown;
5
+ type PipelineDocumentSkipPredicate = (inputs: Record<string, unknown>, context: PipelineExecutionContext<object>) => StepSkipDecision | Promise<StepSkipDecision>;
6
+ /** Application-owned wiring for one declarative `fromPipeline` step. */
7
+ interface PipelineDocumentFromPipelineAdapter {
8
+ controls?: PipelineRunControls | ((inputs: Record<string, unknown>, context: PipelineExecutionContext<object>) => PipelineRunControls);
9
+ mapOptions(inputs: Record<string, unknown>, context: PipelineExecutionContext<object>): object;
10
+ mapResult?(value: unknown, result: PipelineRun<unknown>, context: PipelineStepContext<object>): unknown;
11
+ }
12
+ /** Application-owned wiring for one declarative `forEachPipeline` step. */
13
+ interface PipelineDocumentForEachPipelineAdapter {
14
+ controls?: PipelineRunControls | ((item: unknown, index: number, inputs: Record<string, unknown>, context: PipelineExecutionContext<object>) => PipelineRunControls);
15
+ items(inputs: Record<string, unknown>, context: PipelineExecutionContext<object>): readonly unknown[] | Promise<readonly unknown[]>;
16
+ key(item: unknown, index: number): string;
17
+ concurrency?: number | ((inputs: Record<string, unknown>, context: PipelineExecutionContext<object>) => number);
18
+ progress?: MappedChildProgressOptions;
19
+ mapOptions(item: unknown, index: number, inputs: Record<string, unknown>, context: PipelineExecutionContext<object>): object;
20
+ mapResult?(value: unknown, result: PipelineRun<unknown>, item: unknown, index: number, context: PipelineStepContext<object>): unknown;
21
+ }
22
+ /** Only explicitly registered functions and schemas can be referenced by a document. */
23
+ export interface ProjectRegistry {
24
+ steps: Readonly<Record<string, PipelineDocumentHandler>>;
25
+ finalizers: Readonly<Record<string, PipelineDocumentFinalizer>>;
26
+ skipPredicates?: Readonly<Record<string, PipelineDocumentSkipPredicate>>;
27
+ fromPipelineAdapters?: Readonly<Record<string, PipelineDocumentFromPipelineAdapter>>;
28
+ forEachPipelineAdapters?: Readonly<Record<string, PipelineDocumentForEachPipelineAdapter>>;
29
+ optionsSchemas?: Readonly<Record<string, StandardSchemaV1<object, object>>>;
30
+ schemas?: Readonly<Record<string, StandardSchemaV1>>;
31
+ }
32
+ /** Resolve application wiring without constructing pipelines or invoking application code. */
33
+ export declare class ProjectRegistryResolver {
34
+ #private;
35
+ constructor(registry: ProjectRegistry);
36
+ step(name: string, path: string): PipelineDocumentHandler;
37
+ finalizer(name: string, path: string): PipelineDocumentFinalizer;
38
+ skip(name: string | undefined, path: string): PipelineDocumentSkipPredicate | undefined;
39
+ optionsSchema(name: string | undefined, path: string): StandardSchemaV1<object, object> | undefined;
40
+ outputSchema(name: string | undefined, path: string): StandardSchemaV1 | undefined;
41
+ singleChild(name: string, path: string): PipelineDocumentFromPipelineAdapter;
42
+ mappedChild(name: string, path: string): PipelineDocumentForEachPipelineAdapter;
43
+ }
44
+ export {};
@@ -0,0 +1,107 @@
1
+ import { PipelineDocumentError } from "./project-document.js";
2
+ function resolve(registry, name, path) {
3
+ if (!registry || !Object.hasOwn(registry, name)) {
4
+ throw new PipelineDocumentError(path, `Unknown registered name ${JSON.stringify(name)}`);
5
+ }
6
+ return registry[name];
7
+ }
8
+ function handler(registry, name, path) {
9
+ const value = resolve(registry, name, path);
10
+ if (typeof value !== "function")
11
+ throw new PipelineDocumentError(path, "Expected a registered function");
12
+ return value;
13
+ }
14
+ function schema(registry, name, path) {
15
+ if (name === undefined)
16
+ return undefined;
17
+ const value = resolve(registry, name, path);
18
+ if (!value ||
19
+ value["~standard"]?.version !== 1 ||
20
+ typeof value["~standard"].validate !== "function") {
21
+ throw new PipelineDocumentError(path, "Expected a Standard Schema v1 schema");
22
+ }
23
+ return value;
24
+ }
25
+ function registeredObject(registry, name, path) {
26
+ const value = resolve(registry, name, path);
27
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
28
+ throw new PipelineDocumentError(path, "Expected a registered adapter object");
29
+ }
30
+ return value;
31
+ }
32
+ function validateAdapterMapping(adapter, path) {
33
+ if (adapter.controls !== undefined &&
34
+ typeof adapter.controls !== "function" &&
35
+ (typeof adapter.controls !== "object" || adapter.controls === null)) {
36
+ throw new PipelineDocumentError(path, "Expected adapter controls to be an object or function");
37
+ }
38
+ if (adapter.mapResult !== undefined && typeof adapter.mapResult !== "function") {
39
+ throw new PipelineDocumentError(path, "Expected adapter mapResult to be a function");
40
+ }
41
+ }
42
+ function fromPipelineAdapter(registry, name, path) {
43
+ const adapter = registeredObject(registry, name, path);
44
+ if (typeof adapter.mapOptions !== "function") {
45
+ throw new PipelineDocumentError(path, "Expected an adapter with mapOptions");
46
+ }
47
+ validateAdapterMapping(adapter, path);
48
+ return {
49
+ controls: adapter.controls,
50
+ mapOptions: adapter.mapOptions,
51
+ mapResult: adapter.mapResult,
52
+ };
53
+ }
54
+ function forEachPipelineAdapter(registry, name, path) {
55
+ const adapter = registeredObject(registry, name, path);
56
+ if (typeof adapter.items !== "function" ||
57
+ typeof adapter.key !== "function" ||
58
+ typeof adapter.mapOptions !== "function") {
59
+ throw new PipelineDocumentError(path, "Expected an adapter with items, key, and mapOptions");
60
+ }
61
+ if (adapter.concurrency !== undefined &&
62
+ typeof adapter.concurrency !== "number" &&
63
+ typeof adapter.concurrency !== "function") {
64
+ throw new PipelineDocumentError(path, "Expected adapter concurrency to be a number or function");
65
+ }
66
+ validateAdapterMapping(adapter, path);
67
+ return {
68
+ items: adapter.items,
69
+ key: adapter.key,
70
+ controls: adapter.controls,
71
+ concurrency: adapter.concurrency,
72
+ progress: adapter.progress,
73
+ mapOptions: adapter.mapOptions,
74
+ mapResult: adapter.mapResult,
75
+ };
76
+ }
77
+ /** Resolve application wiring without constructing pipelines or invoking application code. */
78
+ export class ProjectRegistryResolver {
79
+ #registry;
80
+ constructor(registry) {
81
+ this.#registry = registry;
82
+ }
83
+ step(name, path) {
84
+ return handler(this.#registry.steps, name, path);
85
+ }
86
+ finalizer(name, path) {
87
+ return handler(this.#registry.finalizers, name, path);
88
+ }
89
+ skip(name, path) {
90
+ return name === undefined
91
+ ? undefined
92
+ : handler(this.#registry.skipPredicates ?? {}, name, path);
93
+ }
94
+ optionsSchema(name, path) {
95
+ return schema(this.#registry.optionsSchemas, name, path);
96
+ }
97
+ outputSchema(name, path) {
98
+ return schema(this.#registry.schemas, name, path);
99
+ }
100
+ singleChild(name, path) {
101
+ return fromPipelineAdapter(this.#registry.fromPipelineAdapters, name, path);
102
+ }
103
+ mappedChild(name, path) {
104
+ return forEachPipelineAdapter(this.#registry.forEachPipelineAdapters, name, path);
105
+ }
106
+ }
107
+ //# sourceMappingURL=project-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-registry.js","sourceRoot":"","sources":["../../src/project/project-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n MappedChildProgressOptions,\n PipelineExecutionContext,\n PipelineRun,\n PipelineRunControls,\n PipelineStepContext,\n StandardSchemaV1,\n StepSkipDecision,\n} from \"../core/pipeline.js\";\nimport { PipelineDocumentError } from \"./project-document.js\";\n\n/** Dependency values are checked at runtime rather than inferred from a project document. */\ntype PipelineDocumentHandler = (\n inputs: Record<string, unknown>,\n context: PipelineStepContext<object>\n) => unknown;\n\ntype PipelineDocumentFinalizer = (\n outputs: Record<string, unknown>,\n context: PipelineExecutionContext<object>\n) => unknown;\n\ntype PipelineDocumentSkipPredicate = (\n inputs: Record<string, unknown>,\n context: PipelineExecutionContext<object>\n) => StepSkipDecision | Promise<StepSkipDecision>;\n\n/** Application-owned wiring for one declarative `fromPipeline` step. */\ninterface PipelineDocumentFromPipelineAdapter {\n controls?:\n | PipelineRunControls\n | ((\n inputs: Record<string, unknown>,\n context: PipelineExecutionContext<object>\n ) => PipelineRunControls);\n mapOptions(inputs: Record<string, unknown>, context: PipelineExecutionContext<object>): object;\n mapResult?(\n value: unknown,\n result: PipelineRun<unknown>,\n context: PipelineStepContext<object>\n ): unknown;\n}\n\n/** Application-owned wiring for one declarative `forEachPipeline` step. */\ninterface PipelineDocumentForEachPipelineAdapter {\n controls?:\n | PipelineRunControls\n | ((\n item: unknown,\n index: number,\n inputs: Record<string, unknown>,\n context: PipelineExecutionContext<object>\n ) => PipelineRunControls);\n items(\n inputs: Record<string, unknown>,\n context: PipelineExecutionContext<object>\n ): readonly unknown[] | Promise<readonly unknown[]>;\n key(item: unknown, index: number): string;\n concurrency?:\n | number\n | ((inputs: Record<string, unknown>, context: PipelineExecutionContext<object>) => number);\n progress?: MappedChildProgressOptions;\n mapOptions(\n item: unknown,\n index: number,\n inputs: Record<string, unknown>,\n context: PipelineExecutionContext<object>\n ): object;\n mapResult?(\n value: unknown,\n result: PipelineRun<unknown>,\n item: unknown,\n index: number,\n context: PipelineStepContext<object>\n ): unknown;\n}\n\n/** Only explicitly registered functions and schemas can be referenced by a document. */\nexport interface ProjectRegistry {\n steps: Readonly<Record<string, PipelineDocumentHandler>>;\n finalizers: Readonly<Record<string, PipelineDocumentFinalizer>>;\n skipPredicates?: Readonly<Record<string, PipelineDocumentSkipPredicate>>;\n fromPipelineAdapters?: Readonly<Record<string, PipelineDocumentFromPipelineAdapter>>;\n forEachPipelineAdapters?: Readonly<Record<string, PipelineDocumentForEachPipelineAdapter>>;\n optionsSchemas?: Readonly<Record<string, StandardSchemaV1<object, object>>>;\n schemas?: Readonly<Record<string, StandardSchemaV1>>;\n}\n\nfunction resolve<T>(\n registry: Readonly<Record<string, T>> | undefined,\n name: string,\n path: string\n): T {\n if (!registry || !Object.hasOwn(registry, name)) {\n throw new PipelineDocumentError(path, `Unknown registered name ${JSON.stringify(name)}`);\n }\n return registry[name];\n}\n\nfunction handler<T extends PipelineDocumentHandler | PipelineDocumentFinalizer>(\n registry: Readonly<Record<string, T>>,\n name: string,\n path: string\n): T {\n const value = resolve(registry, name, path);\n if (typeof value !== \"function\")\n throw new PipelineDocumentError(path, \"Expected a registered function\");\n return value;\n}\n\nfunction schema<T extends StandardSchemaV1>(\n registry: Readonly<Record<string, T>> | undefined,\n name: string | undefined,\n path: string\n): T | undefined {\n if (name === undefined) return undefined;\n const value = resolve(registry, name, path);\n if (\n !value ||\n value[\"~standard\"]?.version !== 1 ||\n typeof value[\"~standard\"].validate !== \"function\"\n ) {\n throw new PipelineDocumentError(path, \"Expected a Standard Schema v1 schema\");\n }\n return value;\n}\n\nfunction registeredObject<T extends object>(\n registry: Readonly<Record<string, T>> | undefined,\n name: string,\n path: string\n): T {\n const value = resolve(registry, name, path);\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new PipelineDocumentError(path, \"Expected a registered adapter object\");\n }\n return value;\n}\n\nfunction validateAdapterMapping(\n adapter: { controls?: unknown; mapResult?: unknown },\n path: string\n): void {\n if (\n adapter.controls !== undefined &&\n typeof adapter.controls !== \"function\" &&\n (typeof adapter.controls !== \"object\" || adapter.controls === null)\n ) {\n throw new PipelineDocumentError(path, \"Expected adapter controls to be an object or function\");\n }\n if (adapter.mapResult !== undefined && typeof adapter.mapResult !== \"function\") {\n throw new PipelineDocumentError(path, \"Expected adapter mapResult to be a function\");\n }\n}\n\nfunction fromPipelineAdapter(\n registry: ProjectRegistry[\"fromPipelineAdapters\"],\n name: string,\n path: string\n): PipelineDocumentFromPipelineAdapter {\n const adapter = registeredObject(registry, name, path);\n if (typeof adapter.mapOptions !== \"function\") {\n throw new PipelineDocumentError(path, \"Expected an adapter with mapOptions\");\n }\n validateAdapterMapping(adapter, path);\n return {\n controls: adapter.controls,\n mapOptions: adapter.mapOptions,\n mapResult: adapter.mapResult,\n };\n}\n\nfunction forEachPipelineAdapter(\n registry: ProjectRegistry[\"forEachPipelineAdapters\"],\n name: string,\n path: string\n): PipelineDocumentForEachPipelineAdapter {\n const adapter = registeredObject(registry, name, path);\n if (\n typeof adapter.items !== \"function\" ||\n typeof adapter.key !== \"function\" ||\n typeof adapter.mapOptions !== \"function\"\n ) {\n throw new PipelineDocumentError(path, \"Expected an adapter with items, key, and mapOptions\");\n }\n if (\n adapter.concurrency !== undefined &&\n typeof adapter.concurrency !== \"number\" &&\n typeof adapter.concurrency !== \"function\"\n ) {\n throw new PipelineDocumentError(\n path,\n \"Expected adapter concurrency to be a number or function\"\n );\n }\n validateAdapterMapping(adapter, path);\n return {\n items: adapter.items,\n key: adapter.key,\n controls: adapter.controls,\n concurrency: adapter.concurrency,\n progress: adapter.progress,\n mapOptions: adapter.mapOptions,\n mapResult: adapter.mapResult,\n };\n}\n\n/** Resolve application wiring without constructing pipelines or invoking application code. */\nexport class ProjectRegistryResolver {\n readonly #registry: ProjectRegistry;\n\n constructor(registry: ProjectRegistry) {\n this.#registry = registry;\n }\n\n step(name: string, path: string): PipelineDocumentHandler {\n return handler(this.#registry.steps, name, path);\n }\n\n finalizer(name: string, path: string): PipelineDocumentFinalizer {\n return handler(this.#registry.finalizers, name, path);\n }\n\n skip(name: string | undefined, path: string): PipelineDocumentSkipPredicate | undefined {\n return name === undefined\n ? undefined\n : handler(this.#registry.skipPredicates ?? {}, name, path);\n }\n\n optionsSchema(\n name: string | undefined,\n path: string\n ): StandardSchemaV1<object, object> | undefined {\n return schema(this.#registry.optionsSchemas, name, path);\n }\n\n outputSchema(name: string | undefined, path: string): StandardSchemaV1 | undefined {\n return schema(this.#registry.schemas, name, path);\n }\n\n singleChild(name: string, path: string): PipelineDocumentFromPipelineAdapter {\n return fromPipelineAdapter(this.#registry.fromPipelineAdapters, name, path);\n }\n\n mappedChild(name: string, path: string): PipelineDocumentForEachPipelineAdapter {\n return forEachPipelineAdapter(this.#registry.forEachPipelineAdapters, name, path);\n }\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { type Pipeline, type StandardSchemaV1 } from "../core/pipeline.js";
2
+ import type { AnyStep } from "../core/pipeline-steps.js";
3
+ import { type PipelineDocumentStep } from "./project-document.js";
4
+ import type { ProjectRegistryResolver } from "./project-registry.js";
5
+ /** Build and link one document's step graph; mutable forward-reference arrays stay local. */
6
+ export declare function compileDocumentSteps(definitions: readonly PipelineDocumentStep[], optionsSchema: StandardSchemaV1<object, object> | undefined, registry: ProjectRegistryResolver, resolvePipeline: (id: string, path: string) => Pipeline<object, unknown>, path: string): {
7
+ readonly steps: readonly AnyStep[];
8
+ resolve(ids: readonly string[] | undefined, fieldPath: string): AnyStep[];
9
+ };
@@ -0,0 +1,99 @@
1
+ import { createSteps, } from "../core/pipeline.js";
2
+ import { PipelineDocumentError } from "./project-document.js";
3
+ /** Build and link one document's step graph; mutable forward-reference arrays stay local. */
4
+ export function compileDocumentSteps(definitions, optionsSchema, registry, resolvePipeline, path) {
5
+ const factory = createSteps(optionsSchema);
6
+ const entries = definitions.map((definition, index) => {
7
+ const stepPath = `${path}.steps[${index}]`;
8
+ // Populate these arrays after all steps exist, allowing forward references
9
+ // and leaving cycle detection to the existing definition validator.
10
+ const dependsOn = [];
11
+ const optionalDependsOn = [];
12
+ const skipAfterFailureOf = [];
13
+ const dryRun = definition.dryRun === undefined || definition.dryRun === "skip"
14
+ ? definition.dryRun
15
+ : registry.step(definition.dryRun.run, `${stepPath}.dryRun.run`);
16
+ const outputSchema = registry.outputSchema(definition.outputSchema, `${stepPath}.outputSchema`);
17
+ const common = {
18
+ name: definition.name,
19
+ description: definition.description,
20
+ dependsOn,
21
+ optionalDependsOn,
22
+ skipAfterFailureOf,
23
+ };
24
+ const skip = registry.skip(definition.skip, `${stepPath}.skip`);
25
+ let built;
26
+ if (definition.run !== undefined) {
27
+ const config = {
28
+ ...common,
29
+ dryRun,
30
+ run: registry.step(definition.run, `${stepPath}.run`),
31
+ skip,
32
+ };
33
+ built = outputSchema
34
+ ? factory.step(definition.id, { ...config, outputSchema })
35
+ : factory.step(definition.id, config);
36
+ }
37
+ else if (definition.fromPipeline !== undefined) {
38
+ const reference = definition.fromPipeline;
39
+ const adapter = registry.singleChild(reference.adapter, `${stepPath}.fromPipeline.adapter`);
40
+ const config = {
41
+ ...common,
42
+ dryRun: definition.dryRun,
43
+ pipeline: resolvePipeline(reference.pipeline, `${stepPath}.fromPipeline.pipeline`),
44
+ controls: adapter.controls,
45
+ mapOptions: adapter.mapOptions,
46
+ skip,
47
+ };
48
+ built =
49
+ adapter.mapResult === undefined
50
+ ? factory.fromPipeline(definition.id, config)
51
+ : factory.fromPipeline(definition.id, { ...config, mapResult: adapter.mapResult });
52
+ }
53
+ else {
54
+ const reference = definition.forEachPipeline;
55
+ const adapter = registry.mappedChild(reference.adapter, `${stepPath}.forEachPipeline.adapter`);
56
+ // SAFETY: document pipelines publish unknown values. The fan-out builder
57
+ // still represents a valued skip as the complete unknown result array.
58
+ const fanOutSkip = skip;
59
+ const config = {
60
+ ...common,
61
+ dryRun: definition.dryRun,
62
+ pipeline: resolvePipeline(reference.pipeline, `${stepPath}.forEachPipeline.pipeline`),
63
+ items: adapter.items,
64
+ key: adapter.key,
65
+ concurrency: adapter.concurrency,
66
+ controls: adapter.controls,
67
+ progress: adapter.progress,
68
+ mapOptions: adapter.mapOptions,
69
+ skip: fanOutSkip,
70
+ };
71
+ built =
72
+ adapter.mapResult === undefined
73
+ ? factory.forEachPipeline(definition.id, config)
74
+ : factory.forEachPipeline(definition.id, { ...config, mapResult: adapter.mapResult });
75
+ }
76
+ return {
77
+ definition,
78
+ path: stepPath,
79
+ dependsOn,
80
+ optionalDependsOn,
81
+ skipAfterFailureOf,
82
+ step: built,
83
+ };
84
+ });
85
+ const byId = new Map(entries.map((entry) => [entry.step.id, entry.step]));
86
+ const resolveSteps = (ids = [], fieldPath) => ids.map((stepId, index) => {
87
+ const found = byId.get(stepId);
88
+ if (!found)
89
+ throw new PipelineDocumentError(`${fieldPath}[${index}]`, `Unknown step ${JSON.stringify(stepId)}`);
90
+ return found;
91
+ });
92
+ for (const entry of entries) {
93
+ for (const field of ["dependsOn", "optionalDependsOn", "skipAfterFailureOf"]) {
94
+ entry[field].push(...resolveSteps(entry.definition[field], `${entry.path}.${field}`));
95
+ }
96
+ }
97
+ return { steps: entries.map(({ step }) => step), resolve: resolveSteps };
98
+ }
99
+ //# sourceMappingURL=project-step-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-step-graph.js","sourceRoot":"","sources":["../../src/project/project-step-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,GAKZ,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,qBAAqB,EAA6B,MAAM,uBAAuB,CAAC;AAGzF,6FAA6F;AAC7F,MAAM,UAAU,oBAAoB,CAClC,WAA4C,EAC5C,aAA2D,EAC3D,QAAiC,EACjC,eAAwE,EACxE,IAAY;IAKZ,MAAM,OAAO,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE;QACpD,MAAM,QAAQ,GAAG,GAAG,IAAI,UAAU,KAAK,GAAG,CAAC;QAC3C,2EAA2E;QAC3E,oEAAoE;QACpE,MAAM,SAAS,GAAc,EAAE,CAAC;QAChC,MAAM,iBAAiB,GAAc,EAAE,CAAC;QACxC,MAAM,kBAAkB,GAAc,EAAE,CAAC;QACzC,MAAM,MAAM,GACV,UAAU,CAAC,MAAM,KAAK,SAAS,IAAI,UAAU,CAAC,MAAM,KAAK,MAAM;YAC7D,CAAC,CAAC,UAAU,CAAC,MAAM;YACnB,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,QAAQ,aAAa,CAAC,CAAC;QACrE,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC,YAAY,EAAE,GAAG,QAAQ,eAAe,CAAC,CAAC;QAChG,MAAM,MAAM,GAAG;YACb,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,WAAW,EAAE,UAAU,CAAC,WAAW;YACnC,SAAS;YACT,iBAAiB;YACjB,kBAAkB;SACnB,CAAC;QACF,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,QAAQ,OAAO,CAAC,CAAC;QAChE,IAAI,KAAsB,CAAC;QAC3B,IAAI,UAAU,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG;gBACb,GAAG,MAAM;gBACT,MAAM;gBACN,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,QAAQ,MAAM,CAAC;gBACrD,IAAI;aACL,CAAC;YACF,KAAK,GAAG,YAAY;gBAClB,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,CAAC;gBAC1D,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC1C,CAAC;aAAM,IAAI,UAAU,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACjD,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,CAAC;YAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,QAAQ,uBAAuB,CAAC,CAAC;YAC5F,MAAM,MAAM,GAAG;gBACb,GAAG,MAAM;gBACT,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,QAAQ,EAAE,eAAe,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,QAAQ,wBAAwB,CAAC;gBAClF,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,IAAI;aACL,CAAC;YACF,KAAK;gBACH,OAAO,CAAC,SAAS,KAAK,SAAS;oBAC7B,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,EAAE,MAAM,CAAC;oBAC7C,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QACzF,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,GAAG,UAAU,CAAC,eAAe,CAAC;YAC7C,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,CAClC,SAAS,CAAC,OAAO,EACjB,GAAG,QAAQ,0BAA0B,CACtC,CAAC;YACF,yEAAyE;YACzE,uEAAuE;YACvE,MAAM,UAAU,GAAG,IAKN,CAAC;YACd,MAAM,MAAM,GAAG;gBACb,GAAG,MAAM;gBACT,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,QAAQ,EAAE,eAAe,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,QAAQ,2BAA2B,CAAC;gBACrF,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,IAAI,EAAE,UAAU;aACjB,CAAC;YACF,KAAK;gBACH,OAAO,CAAC,SAAS,KAAK,SAAS;oBAC7B,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,EAAE,MAAM,CAAC;oBAChD,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,OAAO;YACL,UAAU;YACV,IAAI,EAAE,QAAQ;YACd,SAAS;YACT,iBAAiB;YACjB,kBAAkB;YAClB,IAAI,EAAE,KAAK;SACZ,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,YAAY,GAAG,CAAC,GAAG,GAAsB,EAAE,EAAE,SAAiB,EAAa,EAAE,CACjF,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK;YACR,MAAM,IAAI,qBAAqB,CAC7B,GAAG,SAAS,IAAI,KAAK,GAAG,EACxB,gBAAgB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CACzC,CAAC;QACJ,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;IACL,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,KAAK,MAAM,KAAK,IAAI,CAAC,WAAW,EAAE,mBAAmB,EAAE,oBAAoB,CAAU,EAAE,CAAC;YACtF,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;AAC3E,CAAC","sourcesContent":["import {\n createSteps,\n type Pipeline,\n type PipelineExecutionContext,\n type StandardSchemaV1,\n type StepSkipDecision,\n} from \"../core/pipeline.js\";\nimport type { AnyStep } from \"../core/pipeline-steps.js\";\nimport { PipelineDocumentError, type PipelineDocumentStep } from \"./project-document.js\";\nimport type { ProjectRegistryResolver } from \"./project-registry.js\";\n\n/** Build and link one document's step graph; mutable forward-reference arrays stay local. */\nexport function compileDocumentSteps(\n definitions: readonly PipelineDocumentStep[],\n optionsSchema: StandardSchemaV1<object, object> | undefined,\n registry: ProjectRegistryResolver,\n resolvePipeline: (id: string, path: string) => Pipeline<object, unknown>,\n path: string\n): {\n readonly steps: readonly AnyStep[];\n resolve(ids: readonly string[] | undefined, fieldPath: string): AnyStep[];\n} {\n const factory = createSteps(optionsSchema);\n const entries = definitions.map((definition, index) => {\n const stepPath = `${path}.steps[${index}]`;\n // Populate these arrays after all steps exist, allowing forward references\n // and leaving cycle detection to the existing definition validator.\n const dependsOn: AnyStep[] = [];\n const optionalDependsOn: AnyStep[] = [];\n const skipAfterFailureOf: AnyStep[] = [];\n const dryRun =\n definition.dryRun === undefined || definition.dryRun === \"skip\"\n ? definition.dryRun\n : registry.step(definition.dryRun.run, `${stepPath}.dryRun.run`);\n const outputSchema = registry.outputSchema(definition.outputSchema, `${stepPath}.outputSchema`);\n const common = {\n name: definition.name,\n description: definition.description,\n dependsOn,\n optionalDependsOn,\n skipAfterFailureOf,\n };\n const skip = registry.skip(definition.skip, `${stepPath}.skip`);\n let built: AnyStep<object>;\n if (definition.run !== undefined) {\n const config = {\n ...common,\n dryRun,\n run: registry.step(definition.run, `${stepPath}.run`),\n skip,\n };\n built = outputSchema\n ? factory.step(definition.id, { ...config, outputSchema })\n : factory.step(definition.id, config);\n } else if (definition.fromPipeline !== undefined) {\n const reference = definition.fromPipeline;\n const adapter = registry.singleChild(reference.adapter, `${stepPath}.fromPipeline.adapter`);\n const config = {\n ...common,\n dryRun: definition.dryRun,\n pipeline: resolvePipeline(reference.pipeline, `${stepPath}.fromPipeline.pipeline`),\n controls: adapter.controls,\n mapOptions: adapter.mapOptions,\n skip,\n };\n built =\n adapter.mapResult === undefined\n ? factory.fromPipeline(definition.id, config)\n : factory.fromPipeline(definition.id, { ...config, mapResult: adapter.mapResult });\n } else {\n const reference = definition.forEachPipeline;\n const adapter = registry.mappedChild(\n reference.adapter,\n `${stepPath}.forEachPipeline.adapter`\n );\n // SAFETY: document pipelines publish unknown values. The fan-out builder\n // still represents a valued skip as the complete unknown result array.\n const fanOutSkip = skip as\n | ((\n inputs: Record<string, unknown>,\n context: PipelineExecutionContext<object>\n ) => StepSkipDecision<readonly unknown[]> | Promise<StepSkipDecision<readonly unknown[]>>)\n | undefined;\n const config = {\n ...common,\n dryRun: definition.dryRun,\n pipeline: resolvePipeline(reference.pipeline, `${stepPath}.forEachPipeline.pipeline`),\n items: adapter.items,\n key: adapter.key,\n concurrency: adapter.concurrency,\n controls: adapter.controls,\n progress: adapter.progress,\n mapOptions: adapter.mapOptions,\n skip: fanOutSkip,\n };\n built =\n adapter.mapResult === undefined\n ? factory.forEachPipeline(definition.id, config)\n : factory.forEachPipeline(definition.id, { ...config, mapResult: adapter.mapResult });\n }\n return {\n definition,\n path: stepPath,\n dependsOn,\n optionalDependsOn,\n skipAfterFailureOf,\n step: built,\n };\n });\n const byId = new Map(entries.map((entry) => [entry.step.id, entry.step]));\n const resolveSteps = (ids: readonly string[] = [], fieldPath: string): AnyStep[] =>\n ids.map((stepId, index) => {\n const found = byId.get(stepId);\n if (!found)\n throw new PipelineDocumentError(\n `${fieldPath}[${index}]`,\n `Unknown step ${JSON.stringify(stepId)}`\n );\n return found;\n });\n for (const entry of entries) {\n for (const field of [\"dependsOn\", \"optionalDependsOn\", \"skipAfterFailureOf\"] as const) {\n entry[field].push(...resolveSteps(entry.definition[field], `${entry.path}.${field}`));\n }\n }\n return { steps: entries.map(({ step }) => step), resolve: resolveSteps };\n}\n"]}
@@ -57,7 +57,7 @@ function renderHumanPlan(plan, options) {
57
57
  }
58
58
  const disposition = `${step.skipReason ? `skip: ${step.skipReason}` : "run"}${annotations.length > 0 ? ` (${annotations.join("; ")})` : ""}`;
59
59
  const nested = step.nestedPipeline
60
- ? ` -> ${step.nestedPipeline.mode === "for-each" ? "fan-out" : "child"} pipeline ${step.nestedPipeline.pipelineId} (${step.nestedPipeline.stepIds.length} declared steps)`
60
+ ? ` -> ${step.nestedPipeline.mode === "iterate" ? `iteration (at most ${step.nestedPipeline.maxIterations})` : step.nestedPipeline.mode === "for-each" ? "fan-out" : "child"} pipeline ${step.nestedPipeline.pipelineId} (${step.nestedPipeline.stepIds.length} declared steps)`
61
61
  : "";
62
62
  const remote = describeRemote(step, plan.dryRun);
63
63
  lines.push(` - ${displayName}: ${disposition}${nested}${remote}${step.description ? ` - ${step.description}` : ""}`);
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/render/render.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAkBtE,SAAS,UAAU,CAAI,KAAQ,EAAE,MAAM,GAAG,KAAK;IAC7C,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AAC7D,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAe;IAC1C,OAAQ,OAAgC,CAAC,MAAM,KAAK,MAAM,CAAC;AAC7D,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,mBAAmB,CACjC,KAAoB,EACpB,OAAO,GAA0B,EAAE;IAEnC,IAAI,mBAAmB,CAAC,OAAO,CAAC;QAAE,OAAO,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3E,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,cAAc,CAAC,IAAsB,EAAE,UAAmB;IACjE,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACpE,MAAM,KAAK,GAAG,UAAU,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;IACtD,MAAM,cAAc,GAClB,UAAU,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC;IACxF,OAAO,cAAc,CAAC,CAAC,CAAC,OAAO,KAAK,2BAA2B,CAAC,CAAC,CAAC,OAAO,KAAK,EAAE,CAAC;AACnF,CAAC;AAED,SAAS,uBAAuB,CAAC,MAAmC;IAClE,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,KAAK;YACR,OAAO,SAAS,CAAC;QACnB,KAAK,OAAO;YACV,OAAO,iBAAiB,CAAC;QAC3B,KAAK,QAAQ;YACX,OAAO,UAAU,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrC,KAAK,qBAAqB;YACxB,OAAO,eAAe,MAAM,CAAC,WAAW,eAAe,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC3E,KAAK,cAAc;YACjB,OAAO,oBAAoB,MAAM,CAAC,WAAW,eAAe,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChF,KAAK,eAAe;YAClB,OAAO,0BAA0B,MAAM,CAAC,WAAW,eAAe,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtF,KAAK,wBAAwB;YAC3B,OAAO,wBAAwB,CAAC;QAClC,KAAK,cAAc;YACjB,OAAO,cAAc,CAAC;IAC1B,CAAC;AACH,CAAC;AAKD,0EAA0E;AAC1E,SAAS,eAAe,CAAC,IAAkB,EAAE,OAA+B;IAC1E,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC;IAC1C,MAAM,KAAK,GAAG;QACZ,YAAY,IAAI,CAAC,UAAU,cAAc,IAAI,CAAC,EAAE,YAAY,IAAI,CAAC,MAAM,WAAW,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG;KACvG,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QACtE,MAAM,WAAW,GAAG,OAAO;YACzB,CAAC,CAAC,IAAI,CAAC,gBAAgB;iBAClB,GAAG,CAAC,uBAAuB,CAAC;iBAC5B,MAAM,CAAC,CAAC,MAAM,EAAoB,EAAE,CAAC,MAAM,KAAK,SAAS,CAAC;YAC/D,CAAC,CAAC,EAAE,CAAC;QACP,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC5D,WAAW,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,WAAW,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,KAAK,GACzE,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAC5D,EAAE,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc;YAChC,CAAC,CAAC,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,aAAa,IAAI,CAAC,cAAc,CAAC,UAAU,KAAK,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,kBAAkB;YAC1K,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACjD,KAAK,CAAC,IAAI,CACR,OAAO,WAAW,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAC1G,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,OAAO,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,kBAAkB,CAChC,IAAkB,EAClB,OAAO,GAA8B,EAAE;IAEvC,IAAI,mBAAmB,CAAC,OAAO,CAAC;QAAE,OAAO,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1E,OAAO,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC","sourcesContent":["import type {\n PipelineError,\n PipelinePlan,\n PipelinePlanStep,\n PipelineStepSelectionReason,\n} from \"../core/pipeline.js\";\nimport { formatPipelineError } from \"../core/pipeline-diagnostics.js\";\n\nexport interface PipelineJsonRenderOptions {\n /** Machine-readable output containing the original structured fields. */\n format: \"json\";\n /** Indent JSON output by two spaces. Defaults to false for stream-friendly output. */\n pretty?: boolean;\n}\n\nexport type PipelineRenderOptions = PipelineJsonRenderOptions | Record<string, never>;\n\nexport type PipelinePlanRenderOptions =\n | {\n /** Include structured selection provenance and runtime-skip annotations. Defaults to true. */\n explain?: boolean;\n }\n | PipelineJsonRenderOptions;\n\nfunction renderJson<T>(value: T, pretty = false): string {\n return JSON.stringify(value, null, pretty ? 2 : undefined);\n}\n\nfunction isJsonRenderOptions(options: object): options is PipelineJsonRenderOptions {\n return (options as { format?: unknown }).format === \"json\";\n}\n\n/** Render one structured diagnostic for a person or a machine consumer. */\nexport function renderPipelineError(\n error: PipelineError,\n options: PipelineRenderOptions = {}\n): string {\n if (isJsonRenderOptions(options)) return renderJson(error, options.pretty);\n return formatPipelineError(error);\n}\n\nfunction describeRemote(step: PipelinePlanStep, planDryRun: boolean): string {\n if (!step.remote) return \"\";\n const target = step.remote.target ? ` (${step.remote.target})` : \"\";\n const label = `remote ${step.remote.engine}${target}`;\n const contactsEngine =\n planDryRun && step.dryRun === \"run\" && step.selected && step.skipReason === undefined;\n return contactsEngine ? ` -> ${label}; dry-run contacts engine` : ` -> ${label}`;\n}\n\nfunction describeSelectionReason(reason: PipelineStepSelectionReason): string | undefined {\n switch (reason.kind) {\n case \"all\":\n return undefined;\n case \"exact\":\n return \"exact selection\";\n case \"target\":\n return `target ${reason.targetId}`;\n case \"required-dependency\":\n return `required by ${reason.dependentId} for target ${reason.targetId}`;\n case \"failure-gate\":\n return `failure gate for ${reason.dependentId} for target ${reason.targetId}`;\n case \"optional-only\":\n return `optional-only input to ${reason.dependentId} for target ${reason.targetId}`;\n case \"outside-target-closure\":\n return \"outside target closure\";\n case \"not-selected\":\n return \"not selected\";\n }\n}\n\n/** Human-readable plan options (the JSON member excluded). */\ntype HumanPlanRenderOptions = Exclude<PipelinePlanRenderOptions, PipelineJsonRenderOptions>;\n\n/** Human-readable plan body; the JSON branch is handled by the caller. */\nfunction renderHumanPlan(plan: PipelinePlan, options: HumanPlanRenderOptions): string {\n const explain = options.explain !== false;\n const lines = [\n `Pipeline ${plan.pipelineId}: plan (ok=${plan.ok}, dryRun=${plan.dryRun}, steps=${plan.steps.length})`,\n ];\n for (const step of plan.steps) {\n const displayName = step.name ? `${step.name} [${step.id}]` : step.id;\n const annotations = explain\n ? step.selectionReasons\n .map(describeSelectionReason)\n .filter((detail): detail is string => detail !== undefined)\n : [];\n if (explain && !step.skipReason && step.runtimeSkipPossible) {\n annotations.unshift(\"policy may skip\");\n }\n const disposition = `${step.skipReason ? `skip: ${step.skipReason}` : \"run\"}${\n annotations.length > 0 ? ` (${annotations.join(\"; \")})` : \"\"\n }`;\n const nested = step.nestedPipeline\n ? ` -> ${step.nestedPipeline.mode === \"for-each\" ? \"fan-out\" : \"child\"} pipeline ${step.nestedPipeline.pipelineId} (${step.nestedPipeline.stepIds.length} declared steps)`\n : \"\";\n const remote = describeRemote(step, plan.dryRun);\n lines.push(\n ` - ${displayName}: ${disposition}${nested}${remote}${step.description ? ` - ${step.description}` : \"\"}`\n );\n }\n for (const error of plan.errors) {\n lines.push(` ! ${renderPipelineError(error)}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** Render an execution plan without recomputing selection or dependency provenance. */\nexport function renderPipelinePlan(\n plan: PipelinePlan,\n options: PipelinePlanRenderOptions = {}\n): string {\n if (isJsonRenderOptions(options)) return renderJson(plan, options.pretty);\n return renderHumanPlan(plan, options);\n}\n"]}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/render/render.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n PipelineError,\n PipelinePlan,\n PipelinePlanStep,\n PipelineStepSelectionReason,\n} from \"../core/pipeline.js\";\nimport { formatPipelineError } from \"../core/pipeline-diagnostics.js\";\n\nexport interface PipelineJsonRenderOptions {\n /** Machine-readable output containing the original structured fields. */\n format: \"json\";\n /** Indent JSON output by two spaces. Defaults to false for stream-friendly output. */\n pretty?: boolean;\n}\n\nexport type PipelineRenderOptions = PipelineJsonRenderOptions | Record<string, never>;\n\nexport type PipelinePlanRenderOptions =\n | {\n /** Include structured selection provenance and runtime-skip annotations. Defaults to true. */\n explain?: boolean;\n }\n | PipelineJsonRenderOptions;\n\nfunction renderJson<T>(value: T, pretty = false): string {\n return JSON.stringify(value, null, pretty ? 2 : undefined);\n}\n\nfunction isJsonRenderOptions(options: object): options is PipelineJsonRenderOptions {\n return (options as { format?: unknown }).format === \"json\";\n}\n\n/** Render one structured diagnostic for a person or a machine consumer. */\nexport function renderPipelineError(\n error: PipelineError,\n options: PipelineRenderOptions = {}\n): string {\n if (isJsonRenderOptions(options)) return renderJson(error, options.pretty);\n return formatPipelineError(error);\n}\n\nfunction describeRemote(step: PipelinePlanStep, planDryRun: boolean): string {\n if (!step.remote) return \"\";\n const target = step.remote.target ? ` (${step.remote.target})` : \"\";\n const label = `remote ${step.remote.engine}${target}`;\n const contactsEngine =\n planDryRun && step.dryRun === \"run\" && step.selected && step.skipReason === undefined;\n return contactsEngine ? ` -> ${label}; dry-run contacts engine` : ` -> ${label}`;\n}\n\nfunction describeSelectionReason(reason: PipelineStepSelectionReason): string | undefined {\n switch (reason.kind) {\n case \"all\":\n return undefined;\n case \"exact\":\n return \"exact selection\";\n case \"target\":\n return `target ${reason.targetId}`;\n case \"required-dependency\":\n return `required by ${reason.dependentId} for target ${reason.targetId}`;\n case \"failure-gate\":\n return `failure gate for ${reason.dependentId} for target ${reason.targetId}`;\n case \"optional-only\":\n return `optional-only input to ${reason.dependentId} for target ${reason.targetId}`;\n case \"outside-target-closure\":\n return \"outside target closure\";\n case \"not-selected\":\n return \"not selected\";\n }\n}\n\n/** Human-readable plan options (the JSON member excluded). */\ntype HumanPlanRenderOptions = Exclude<PipelinePlanRenderOptions, PipelineJsonRenderOptions>;\n\n/** Human-readable plan body; the JSON branch is handled by the caller. */\nfunction renderHumanPlan(plan: PipelinePlan, options: HumanPlanRenderOptions): string {\n const explain = options.explain !== false;\n const lines = [\n `Pipeline ${plan.pipelineId}: plan (ok=${plan.ok}, dryRun=${plan.dryRun}, steps=${plan.steps.length})`,\n ];\n for (const step of plan.steps) {\n const displayName = step.name ? `${step.name} [${step.id}]` : step.id;\n const annotations = explain\n ? step.selectionReasons\n .map(describeSelectionReason)\n .filter((detail): detail is string => detail !== undefined)\n : [];\n if (explain && !step.skipReason && step.runtimeSkipPossible) {\n annotations.unshift(\"policy may skip\");\n }\n const disposition = `${step.skipReason ? `skip: ${step.skipReason}` : \"run\"}${\n annotations.length > 0 ? ` (${annotations.join(\"; \")})` : \"\"\n }`;\n const nested = step.nestedPipeline\n ? ` -> ${step.nestedPipeline.mode === \"iterate\" ? `iteration (at most ${step.nestedPipeline.maxIterations})` : step.nestedPipeline.mode === \"for-each\" ? \"fan-out\" : \"child\"} pipeline ${step.nestedPipeline.pipelineId} (${step.nestedPipeline.stepIds.length} declared steps)`\n : \"\";\n const remote = describeRemote(step, plan.dryRun);\n lines.push(\n ` - ${displayName}: ${disposition}${nested}${remote}${step.description ? ` - ${step.description}` : \"\"}`\n );\n }\n for (const error of plan.errors) {\n lines.push(` ! ${renderPipelineError(error)}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** Render an execution plan without recomputing selection or dependency provenance. */\nexport function renderPipelinePlan(\n plan: PipelinePlan,\n options: PipelinePlanRenderOptions = {}\n): string {\n if (isJsonRenderOptions(options)) return renderJson(plan, options.pretty);\n return renderHumanPlan(plan, options);\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import { format } from "node:util";
2
2
  import { hasVisibleStepProgress } from "../core/progress.js";
3
- import { createLiveTicker, elapsedToken, shimmerToken, SPINNER_TOKEN, } from "./live-ticker.js";
3
+ import { elapsedToken, shimmerToken, SPINNER_TOKEN } from "./live-ticker-frame.js";
4
+ import { createLiveTicker } from "./live-ticker.js";
4
5
  import { createReporterTheme, createRunReporter, formatDurationMs, } from "./reporter.js";
5
6
  import { safeTerminalLog, safeTerminalText } from "./terminal-text.js";
6
7
  function autoInteractiveAllowed(output, config) {
@@ -49,7 +50,8 @@ function renderProgressDetail(detail, theme, spinner, progressBarWidth, parentSt
49
50
  ? theme.styled.description(theme.symbols.pending)
50
51
  : theme.styled.start(spinner);
51
52
  const id = safeTerminalText(detail.name ?? detail.id);
52
- const label = detail.label ? safeTerminalText(detail.label) : "";
53
+ const label = (detail.label ? safeTerminalText(detail.label) : "") +
54
+ (detail.outputSource === "override" ? " (overridden)" : "");
53
55
  const labelText = status === "cancelled" ? `cancelled${label ? `: ${label}` : ""}` : label;
54
56
  const running = status === "running";
55
57
  const body = labelText ? `${id} ${labelText}` : id;
@@ -64,7 +66,8 @@ function renderProgressDetail(detail, theme, spinner, progressBarWidth, parentSt
64
66
  }
65
67
  function renderStep(state, theme, spinner, progressBarWidth) {
66
68
  const { step } = state;
67
- const displayName = safeTerminalText(step.name ?? step.id);
69
+ const displayName = safeTerminalText(step.name ?? step.id) +
70
+ (state.status !== "planned" && state.outputSource === "override" ? " (overridden)" : "");
68
71
  switch (state.status) {
69
72
  case "running": {
70
73
  const progress = state.progress && hasVisibleStepProgress(state.progress)
@@ -1 +1 @@
1
- {"version":3,"file":"interactive-reporter.js","sourceRoot":"","sources":["../../src/reporter/interactive-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAUnC,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,aAAa,GAEd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,GAGjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AA0DvE,SAAS,sBAAsB,CAAC,MAAsB,EAAE,MAA8B;IACpF,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC;IAC9D,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,OAAO,CAAC;IAC3E,OAAO,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC;AACvD,CAAC;AAED,SAAS,WAAW,CAClB,MAAsB,EACtB,MAA8B;IAE9B,IAAI,MAAM,CAAC,IAAI,KAAK,aAAa;QAAE,OAAO,aAAa,CAAC;IACxD,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5C,OAAO,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC;AAC1E,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,cAAc,CAAC,QAA8B,EAAE,KAAa,EAAE,OAAgB;IACrF,4EAA4E;IAC5E,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACjF,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpE,OAAO,GAAG,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC;IACpE,CAAC;IACD,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAC9D,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAClE,EAAE,CAAC;IACH,OAAO,IAAI,GAAG,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,WAAW,CAAC,SAAS,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,GAAG,OAAO,EAAE,CAAC;AAC1G,CAAC;AAED,SAAS,oBAAoB,CAC3B,MAA4D,EAC5D,KAAoB,EACpB,OAAe,EACf,gBAAwB,EACxB,YAA0C;IAE1C,MAAM,MAAM,GACV,CAAC,MAAM,CAAC,MAAM,IAAI,SAAS,CAAC,KAAK,SAAS,IAAI,YAAY,KAAK,SAAS;QACtE,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC;IACnC,MAAM,MAAM,GACV,MAAM,KAAK,WAAW;QACpB,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC/C,CAAC,CAAC,MAAM,KAAK,QAAQ;YACnB,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YACvC,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,WAAW;gBAC9C,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;gBACvC,CAAC,CAAC,MAAM,KAAK,SAAS;oBACpB,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;oBACjD,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,gBAAgB,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,MAAM,SAAS,GAAG,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3F,MAAM,OAAO,GAAG,MAAM,KAAK,SAAS,CAAC;IACrC,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACnD,MAAM,WAAW,GACf,OAAO,IAAI,KAAK,CAAC,YAAY;QAC3B,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC;QACpB,CAAC,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC3E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,MAAM,QAAQ,GACZ,MAAM,CAAC,SAAS,KAAK,SAAS;QAC5B,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,IAAI,cAAc,CAChB,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,EACpD,gBAAgB,EAChB,KAAK,CAAC,cAAc,CACrB,EAAE,CAAC;IACV,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,MAAM,IAAI,WAAW,GAAG,QAAQ,EAAE,CAAC;AACxE,CAAC;AAED,SAAS,UAAU,CACjB,KAAgB,EAChB,KAAoB,EACpB,OAAe,EACf,gBAAwB;IAExB,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACvB,MAAM,WAAW,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3D,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;QACrB,KAAK,SAAS,EAAE,CAAC;YACf,MAAM,QAAQ,GACZ,KAAK,CAAC,QAAQ,IAAI,sBAAsB,CAAC,KAAK,CAAC,QAAQ,CAAC;gBACtD,CAAC,CAAC,IAAI,cAAc,CAAC,KAAK,CAAC,QAAQ,EAAE,gBAAgB,EAAE,KAAK,CAAC,cAAc,CAAC,EAAE;gBAC9E,CAAC,CAAC,EAAE,CAAC;YACT,MAAM,OAAO,GACX,KAAK,CAAC,WAAW,KAAK,SAAS;gBAC7B,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE;gBAC9D,CAAC,CAAC,EAAE,CAAC;YACT,MAAM,KAAK,GAAG;gBACZ,KAAK,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,YAAY,CAAC,WAAW,CAAC,GAAG,QAAQ,GAAG,OAAO,EAAE;aACrF,CAAC;YACF,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,WAAW;YACd,OAAO;gBACL,KAAK,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,CACxF,IAAI,gBAAgB,CAAC,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAChE,EAAE;aACJ,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO;gBACL,KAAK,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,WAAW,KAAK,gBAAgB,CAC5E,KAAK,CAAC,KAAK,CAAC,OAAO,CACpB,EAAE;aACJ,CAAC;QACJ,KAAK,WAAW;YACd,OAAO;gBACL,KAAK,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,WAAW,gBAAgB,gBAAgB,CACvF,KAAK,CAAC,KAAK,CAAC,OAAO,CACpB,EAAE;aACJ,CAAC;QACJ,KAAK,SAAS;YACZ,OAAO;gBACL,KAAK,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,CAChF,IAAI,gBAAgB,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CACvD,EAAE;aACJ,CAAC;QACJ,KAAK,SAAS;YACZ,OAAO;gBACL,KAAK,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE;aAC7G,CAAC;IACN,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAsB;IAC9C,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACpF,OAAO,EAAE,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9E,CAAC;AAED,SAAS,yBAAyB,CAChC,OAAgC,EAChC,MAAsB;IAEtB,MAAM,aAAa,GAAG,OAAO,CAAC,QAAQ,EAAE,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC;IACvE,MAAM,KAAK,GAAG,mBAAmB,CAAC;QAChC,GAAG,OAAO;QACV,QAAQ,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE;KACxD,CAAC,CAAC;IACH,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,CAAC;IACjF,yEAAyE;IACzE,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,CAAC;IACpF,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC3C,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,IAA8B,CAAC;IACnC,IAAI,MAAwC,CAAC;IAC7C,IAAI,QAAQ,GAAkB,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjD,IAAI,oBAAoB,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACpD,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,MAA8B,CAAC;IACnC,IAAI,aAAwD,CAAC;IAC7D,IAAI,YAAsC,CAAC;IAC3C,IAAI,YAA4C,CAAC;IAEjD,MAAM,UAAU,GAAG,GAAa,EAAE;QAChC,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;QACrB,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,MAAM;gBACnB,CAAC,CAAC,OAAO,CAAC,UAAU,KAAK,KAAK;oBAC5B,CAAC,CAAC,YAAY,gBAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;oBACnD,CAAC,CAAC,YAAY,gBAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,aAAa,gBAAgB,CAAC,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC,YAAY,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,KAAK,CAAC,MAAM,YAAY,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG;gBACpN,CAAC,CAAC,YAAY,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,kBAAkB,IAAI,CAAC,MAAM,GAAG,CAAC;YACxG,KAAK,CAAC,IAAI,CACR,MAAM,EAAE,MAAM,KAAK,WAAW;gBAC5B,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAC/B,CAAC,CAAC,MAAM;oBACN,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;oBAC3B,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CACpC,CAAC;QACJ,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,gBAAgB,CAAC,CAAC,CAAC;YACzE,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;gBACzC,KAAK,CAAC,IAAI,CACR,oBAAoB,CAAC,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,CACnF,CAAC;YACJ,CAAC;QACH,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACnF,CAAC;aAAM,IAAI,QAAQ,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAC3C,KAAK,CAAC,IAAI,CACR,KAAK,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,KAAK,CAAC,MAAM,CAAC,QAAQ,CAClF,IAAI,gBAAgB,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAC7C,EAAE,CACJ,CAAC;QACJ,CAAC;aAAM,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,CACR,KAAK,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,gBAAgB,CACtE,QAAQ,CAAC,KAAK,CAAC,OAAO,CACvB,EAAE,CACJ,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,GAAe,EAAE;QACpC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,gBAAgB,CAAC;gBACxB,KAAK,EAAE,KAAK,CAAC,YAAY;gBACzB,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO;gBAChC,EAAE,EAAE,gBAAgB,CAAC,MAAM,CAAC;gBAC5B,iBAAiB;gBACjB,OAAO,EAAE,KAAK,CAAC,cAAc;gBAC7B,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE;oBACf,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACtB,CAAC;aACF,CAAC,CAAC;QACL,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,GAAY,EAAE,CACnC,IAAI,KAAK,SAAS;QAClB,CAAC,MAAM;QACP,OAAO,CAAC,OAAO,KAAK,KAAK;QACzB,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,GAAG;QAC5B,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;IAE1B,MAAM,MAAM,GAAG,GAAS,EAAE;QACxB,IAAI,QAAQ;YAAE,OAAO;QACrB,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;YAC5C,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,MAAM,OAAO,GAAG,cAAc,EAAE;YAC9B,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;gBACrB,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACjD,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,qBAAqB,CAAC;YACxE,CAAC,CAAC,SAAS,CAAC;QACd,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;YAC1D,YAAY,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YACxC,OAAO;QACT,CAAC;QACD,IAAI,MAAM,EAAE,CAAC;YACX,+EAA+E;YAC/E,YAAY,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC5B,YAAY,EAAE,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjD,OAAO;QACT,CAAC;QACD,MAAM,QAAQ,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;QACpD,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACb,YAAY,EAAE,CAAC,QAAQ,CACrB,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CACjF,CAAC;YACF,OAAO;QACT,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC;QAC3B,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAC5C,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAAE,KAAK,GAAG,KAAK,CAAC;QAClD,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,CAAC,EACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CACtE,CAAC;QACF,MAAM,GAAG,GAAG,KAAK,GAAG,SAAS,CAAC;QAC9B,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;QAC5B,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,QAAQ,IAAI,KAAK,GAAG,CAAC,aAAa,CAAC,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QACzC,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,aAAa,CAAC,CAAC;QACvF,YAAY,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,GAAS,EAAE;QAC/B,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,YAAY,CAAC,aAAa,CAAC,CAAC;YAC5B,aAAa,GAAG,SAAS,CAAC;QAC5B,CAAC;QACD,IAAI,CAAC,aAAa;YAAE,OAAO;QAC3B,aAAa,GAAG,KAAK,CAAC;QACtB,oBAAoB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAClC,MAAM,EAAE,CAAC;IACX,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,GAAS,EAAE;QACzB,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,YAAY,CAAC,aAAa,CAAC,CAAC;YAC5B,aAAa,GAAG,SAAS,CAAC;QAC5B,CAAC;QACD,MAAM,EAAE,OAAO,EAAE,CAAC;QAClB,MAAM,GAAG,SAAS,CAAC;QACnB,IAAI,YAAY;YAAE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QACpD,YAAY,GAAG,SAAS,CAAC;QACzB,YAAY,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpC,YAAY,GAAG,SAAS,CAAC;IAC3B,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,CAAC,KAA+B,EAAE,OAAiB,EAAE,GAAG,IAAe,EAAE,EAAE;QAC1F,MAAM,QAAQ,GAAG,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;QAC5F,MAAM,YAAY,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC/C,MAAM,MAAM,GACV,KAAK,KAAK,OAAO;YACf,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG;YAC7C,CAAC,CAAC,KAAK,KAAK,MAAM;gBAChB,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG;gBAC9B,CAAC,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,GAAG,GAAG,MAAM,GAAG,YAAY,IAAI,CAAC;QAC1C,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QACD,8EAA8E;QAC9E,UAAU,CAAC,IAAI,CACb,GAAG,GAAG,MAAM,GAAG,YAAY,EAAE;aAC1B,KAAK,CAAC,IAAI,CAAC;aACX,KAAK,CAAC,CAAC,CAAC,CAAC;aACT,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CACtC,CAAC;QACF,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,cAAc,EAAE;YAAE,YAAY,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrD,aAAa,GAAG,KAAK,CAAC;QACtB,oBAAoB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAClC,MAAM,EAAE,CAAC;IACX,CAAC,CAAC;IAEF,MAAM,GAAG,GAAmB;QAC1B,KAAK,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAChE,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAC5D,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;KAC/D,CAAC;IAEF,MAAM,KAAK,GAA2B;QACpC,eAAe,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC5B,IAAI,GAAG,QAAQ,CAAC;YAChB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAClC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACnF,CAAC;YACD,IAAI,MAAM,KAAK,OAAO,CAAC,MAAM,IAAI,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;gBAC3D,YAAY,GAAG,OAAO,CAAC;gBACvB,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;gBACnC,YAAY,GAAG,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;gBAC3E,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACpC,CAAC;YACD,MAAM,EAAE,CAAC;QACX,CAAC;QACD,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE;YACtB,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC1C,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC/B,uEAAuE;gBACvE,sEAAsE;gBACtE,MAAM,QAAQ,GACZ,KAAK,CAAC,QAAQ,IAAI,sBAAsB,CAAC,KAAK,CAAC,QAAQ,CAAC;oBACtD,CAAC,CAAC,KAAK,CAAC,QAAQ;oBAChB,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,SAAS;wBAC9B,CAAC,CAAC,QAAQ,CAAC,QAAQ;wBACnB,CAAC,CAAC,SAAS,CAAC;gBAClB,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE;oBACvB,GAAG,KAAK;oBACR,QAAQ;oBACR,OAAO,EAAE,QAAQ,EAAE,OAAO;oBAC1B,WAAW,EAAE,QAAQ,EAAE,WAAW,IAAI,IAAI,CAAC,GAAG,EAAE;iBACjD,CAAC,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACvB,IAAI,GAAG,GAAG,oBAAoB,IAAI,iBAAiB,EAAE,CAAC;oBACpD,aAAa,GAAG,KAAK,CAAC;oBACtB,oBAAoB,GAAG,GAAG,CAAC;oBAC3B,MAAM,EAAE,CAAC;gBACX,CAAC;qBAAM,CAAC;oBACN,aAAa,GAAG,IAAI,CAAC;oBACrB,aAAa,KAAK,UAAU,CAC1B,GAAG,EAAE;wBACH,aAAa,GAAG,SAAS,CAAC;wBAC1B,IAAI,CAAC,QAAQ;4BAAE,aAAa,EAAE,CAAC;oBACjC,CAAC,EACD,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,iBAAiB,GAAG,CAAC,GAAG,GAAG,oBAAoB,CAAC,CAAC,CAC9D,CAAC;oBACF,aAAa,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC1B,CAAC;gBACD,OAAO;YACT,CAAC;YACD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;gBAAE,aAAa,EAAE,CAAC;YAChD,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;YACnE,MAAM,EAAE,CAAC;QACX,CAAC;QACD,eAAe,EAAE,GAAG,EAAE;YACpB,QAAQ,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;YACjC,MAAM,EAAE,CAAC;QACX,CAAC;QACD,kBAAkB,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE;YACrC,QAAQ,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;YAC/C,MAAM,EAAE,CAAC;QACX,CAAC;QACD,eAAe,EAAE,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE;YACzC,QAAQ,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;YACnD,MAAM,EAAE,CAAC;QACX,CAAC;QACD,kBAAkB,EAAE,CAAC,UAAU,EAAE,EAAE;YACjC,MAAM,GAAG,UAAU,CAAC;YACpB,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;QACZ,CAAC;KACF,CAAC;IAEF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;AACtD,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,sBAAsB,CACpC,OAAgC;IAEhC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAChD,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;QAC3B,OAAO,yBAAyB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC;IACD,OAAO;QACL,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;QACxB,KAAK,EAAE,iBAAiB,CAAU,OAAO,CAAC;QAC1C,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,IAAI,EAAE,OAAO;KACd,CAAC;AACJ,CAAC","sourcesContent":["import { format } from \"node:util\";\nimport type {\n PipelineError,\n PipelineHooks,\n PipelineLogger,\n PipelinePlan,\n PipelineRun,\n PipelineStepProgress,\n PipelineStepStatus,\n} from \"../core/pipeline.js\";\nimport { hasVisibleStepProgress } from \"../core/progress.js\";\nimport {\n createLiveTicker,\n elapsedToken,\n shimmerToken,\n SPINNER_TOKEN,\n type LiveTicker,\n} from \"./live-ticker.js\";\nimport {\n createReporterTheme,\n createRunReporter,\n formatDurationMs,\n type ReporterTheme,\n type RunReporterConfig,\n} from \"./reporter.js\";\nimport { safeTerminalLog, safeTerminalText } from \"./terminal-text.js\";\n\n/** Rendering mode selected for pipeline lifecycle reporting. */\nexport type PipelineReporterMode = \"auto\" | \"interactive\" | \"plain\";\nexport type ResolvedPipelineReporterMode = Exclude<PipelineReporterMode, \"auto\">;\n\n/** Writable terminal-like destination used by the interactive reporter. */\nexport interface ReporterOutput {\n readonly columns?: number;\n readonly rows?: number;\n /**\n * File descriptor for live frames. When set, spinner, elapsed time, and shimmer\n * paint on a worker thread so they keep moving during CPU-bound steps. Defaults\n * to stdout's fd when `output` is `process.stdout`.\n */\n readonly fd?: number;\n readonly isTTY?: boolean;\n write(chunk: string): unknown;\n}\n\n/** Rendering and output settings for automatic, plain, or interactive reporting. */\nexport interface PipelineReporterConfig extends RunReporterConfig {\n /** Auto selects the interactive renderer only for a capable, non-CI TTY. */\n mode?: PipelineReporterMode;\n /** Terminal stream used by the interactive renderer. Defaults to stdout. */\n output?: ReporterOutput;\n /** Spinner redraw cadence. Defaults to 80ms. */\n refreshIntervalMs?: number;\n /** Filled/empty character width for determinate progress. Defaults to 20. */\n progressBarWidth?: number;\n /** Show recent logs beside progress in TTYs at least 120 columns by 8 rows. Defaults to auto. */\n logPane?: \"auto\" | \"off\";\n}\n\nexport interface PipelineReporterOptions extends PipelineReporterConfig {\n log: PipelineLogger;\n}\n\nexport interface PipelineReporterController<TResult = unknown> {\n readonly hooks: PipelineHooks<TResult>;\n readonly log: PipelineLogger;\n readonly mode: ResolvedPipelineReporterMode;\n /** Stop redraws and restore terminal state. Safe to call more than once. */\n dispose(): void;\n}\n\ntype StepState = PipelineStepStatus & {\n /** Wall-clock ms from Date.now() when the step entered the running state. */\n startedAtMs?: number;\n details?: PipelineStepProgress[\"details\"];\n};\n\ntype FinalizeState =\n | { status: \"idle\" }\n | { status: \"running\" }\n | { durationMs: number; status: \"completed\" }\n | { durationMs: number; error: PipelineError; status: \"failed\" };\n\nfunction autoInteractiveAllowed(output: ReporterOutput, config: PipelineReporterConfig): boolean {\n const isTTY = config.terminal?.isTTY ?? output.isTTY === true;\n const ci = process.env.CI;\n const isCI = ci !== undefined && ci !== \"\" && ci !== \"0\" && ci !== \"false\";\n return isTTY && process.env.TERM !== \"dumb\" && !isCI;\n}\n\nfunction resolveMode(\n output: ReporterOutput,\n config: PipelineReporterConfig\n): ResolvedPipelineReporterMode {\n if (config.mode === \"interactive\") return \"interactive\";\n if (config.mode === \"plain\") return \"plain\";\n return autoInteractiveAllowed(output, config) ? \"interactive\" : \"plain\";\n}\n\nfunction safeNumber(value: number): number {\n return Number.isFinite(value) ? value : 0;\n}\n\nfunction formatCount(value: number): string {\n return Number.isInteger(value) ? String(value) : value.toFixed(1);\n}\n\nfunction renderProgress(progress: PipelineStepProgress, width: number, unicode: boolean): string {\n // Parent line keeps the summary message only; per-item work uses `details`.\n const message = progress.message ? ` ${safeTerminalText(progress.message)}` : \"\";\n if (progress.total === undefined || safeNumber(progress.total) <= 0) {\n return `${formatCount(safeNumber(progress.completed))}${message}`;\n }\n const completed = safeNumber(progress.completed);\n const total = safeNumber(progress.total);\n const ratio = Math.max(0, Math.min(1, completed / total));\n const filled = Math.round(ratio * width);\n const bar = `${unicode ? \"█\".repeat(filled) : \"=\".repeat(filled)}${\n unicode ? \"░\".repeat(width - filled) : \"-\".repeat(width - filled)\n }`;\n return `[${bar}] ${Math.round(ratio * 100)}% ${formatCount(completed)}/${formatCount(total)}${message}`;\n}\n\nfunction renderProgressDetail(\n detail: NonNullable<PipelineStepProgress[\"details\"]>[number],\n theme: ReporterTheme,\n spinner: string,\n progressBarWidth: number,\n parentStatus: PipelineStepStatus[\"status\"]\n): string {\n const status =\n (detail.status ?? \"running\") === \"running\" && parentStatus !== \"running\"\n ? parentStatus\n : (detail.status ?? \"running\");\n const symbol =\n status === \"completed\"\n ? theme.styled.complete(theme.symbols.complete)\n : status === \"failed\"\n ? theme.styled.fail(theme.symbols.fail)\n : status === \"skipped\" || status === \"cancelled\"\n ? theme.styled.skip(theme.symbols.skip)\n : status === \"pending\"\n ? theme.styled.description(theme.symbols.pending)\n : theme.styled.start(spinner);\n const id = safeTerminalText(detail.name ?? detail.id);\n const label = detail.label ? safeTerminalText(detail.label) : \"\";\n const labelText = status === \"cancelled\" ? `cancelled${label ? `: ${label}` : \"\"}` : label;\n const running = status === \"running\";\n const body = labelText ? `${id} ${labelText}` : id;\n const paintedBody =\n running && theme.colorEnabled\n ? shimmerToken(body)\n : `${id}${labelText ? ` ${theme.styled.description(labelText)}` : \"\"}`;\n const depth = Math.max(0, Math.min(32, Math.floor(safeNumber(detail.depth ?? 0))));\n const progress =\n detail.completed === undefined\n ? \"\"\n : ` ${renderProgress(\n { completed: detail.completed, total: detail.total },\n progressBarWidth,\n theme.unicodeEnabled\n )}`;\n return `${\" \".repeat(depth + 2)}${symbol} ${paintedBody}${progress}`;\n}\n\nfunction renderStep(\n state: StepState,\n theme: ReporterTheme,\n spinner: string,\n progressBarWidth: number\n): string[] {\n const { step } = state;\n const displayName = safeTerminalText(step.name ?? step.id);\n switch (state.status) {\n case \"running\": {\n const progress =\n state.progress && hasVisibleStepProgress(state.progress)\n ? ` ${renderProgress(state.progress, progressBarWidth, theme.unicodeEnabled)}`\n : \"\";\n const elapsed =\n state.startedAtMs !== undefined\n ? ` ${theme.styled.duration(elapsedToken(state.startedAtMs))}`\n : \"\";\n const lines = [\n ` ${theme.styled.start(spinner)} ${shimmerToken(displayName)}${progress}${elapsed}`,\n ];\n return lines;\n }\n case \"completed\":\n return [\n ` ${theme.styled.complete(theme.symbols.complete)} ${displayName} ${theme.styled.duration(\n `(${formatDurationMs(state.finishedAtMs - state.startedAtMs)})`\n )}`,\n ];\n case \"failed\":\n return [\n ` ${theme.styled.fail(theme.symbols.fail)} ${displayName}: ${safeTerminalText(\n state.error.message\n )}`,\n ];\n case \"cancelled\":\n return [\n ` ${theme.styled.skip(theme.symbols.skip)} ${displayName}: cancelled: ${safeTerminalText(\n state.error.message\n )}`,\n ];\n case \"skipped\":\n return [\n ` ${theme.styled.skip(theme.symbols.skip)} ${displayName} ${theme.styled.duration(\n `(${safeTerminalText(state.message ?? state.reason)})`\n )}`,\n ];\n case \"planned\":\n return [\n ` ${theme.styled.description(theme.symbols.pending)} ${displayName} ${theme.styled.description(\"waiting\")}`,\n ];\n }\n}\n\nfunction reporterOutputFd(output: ReporterOutput): number | undefined {\n const fd = output.fd ?? (output === process.stdout ? process.stdout.fd : undefined);\n return fd !== undefined && Number.isInteger(fd) && fd >= 0 ? fd : undefined;\n}\n\nfunction createInteractiveReporter<TResult>(\n options: PipelineReporterOptions,\n output: ReporterOutput\n): PipelineReporterController<TResult> {\n const terminalIsTTY = options.terminal?.isTTY ?? output.isTTY === true;\n const theme = createReporterTheme({\n ...options,\n terminal: { isTTY: terminalIsTTY, ...options.terminal },\n });\n const progressBarWidth = Math.max(4, Math.floor(options.progressBarWidth ?? 20));\n // ~12.5 fps keeps braille spinners smooth without flooding the terminal.\n const refreshIntervalMs = Math.max(16, Math.floor(options.refreshIntervalMs ?? 80));\n const steps = new Map<string, StepState>();\n const recentLogs: string[] = [];\n let plan: PipelinePlan | undefined;\n let result: PipelineRun<TResult> | undefined;\n let finalize: FinalizeState = { status: \"idle\" };\n let lastProgressRedrawAt = Number.NEGATIVE_INFINITY;\n let progressDirty = false;\n let disposed = false;\n let ticker: LiveTicker | undefined;\n let trailingFlush: ReturnType<typeof setTimeout> | undefined;\n let exitListener: (() => void) | undefined;\n let resizeOutput: NodeJS.WriteStream | undefined;\n\n const frameLines = (): string[] => {\n if (!plan) return [];\n const lines: string[] = [];\n if (options.logPlan !== false) {\n const header = result\n ? options.logSummary === false\n ? `Pipeline ${safeTerminalText(result.pipelineId)}`\n : `Pipeline ${safeTerminalText(result.pipelineId)}: done in ${formatDurationMs(result.finishedAtMs - result.startedAtMs)} (status=${result.status}, steps=${result.steps.length}, errors=${result.errors.length})`\n : `Pipeline ${safeTerminalText(plan.pipelineId)} (${plan.steps.length} steps, dryRun=${plan.dryRun})`;\n lines.push(\n result?.status === \"completed\"\n ? theme.styled.complete(header)\n : result\n ? theme.styled.fail(header)\n : theme.styled.pipeline(header)\n );\n }\n for (const state of steps.values()) {\n lines.push(...renderStep(state, theme, SPINNER_TOKEN, progressBarWidth));\n for (const detail of state.details ?? []) {\n lines.push(\n renderProgressDetail(detail, theme, SPINNER_TOKEN, progressBarWidth, state.status)\n );\n }\n }\n if (finalize.status === \"running\") {\n lines.push(` ${theme.styled.start(SPINNER_TOKEN)} ${shimmerToken(\"finalize\")}`);\n } else if (finalize.status === \"completed\") {\n lines.push(\n ` ${theme.styled.complete(theme.symbols.complete)} finalize ${theme.styled.duration(\n `(${formatDurationMs(finalize.durationMs)})`\n )}`\n );\n } else if (finalize.status === \"failed\") {\n lines.push(\n ` ${theme.styled.fail(theme.symbols.fail)} finalize: ${safeTerminalText(\n finalize.error.message\n )}`\n );\n }\n return lines;\n };\n\n const ensureTicker = (): LiveTicker => {\n if (!ticker) {\n ticker = createLiveTicker({\n color: theme.colorEnabled,\n columns: output.columns,\n getColumns: () => output.columns,\n fd: reporterOutputFd(output),\n refreshIntervalMs,\n unicode: theme.unicodeEnabled,\n write: (chunk) => {\n output.write(chunk);\n },\n });\n }\n return ticker;\n };\n\n const logPaneVisible = (): boolean =>\n plan !== undefined &&\n !result &&\n options.logPane !== \"off\" &&\n (output.columns ?? 0) >= 120 &&\n (output.rows ?? 0) >= 8;\n\n const redraw = (): void => {\n if (disposed) return;\n const lines = frameLines();\n if (lines.length === 0 && !logPaneVisible()) {\n ticker?.setLines([]);\n return;\n }\n const rows = output.rows;\n const logPane = logPaneVisible()\n ? recentLogs.length > 0\n ? recentLogs.slice(-Math.min(8, (rows ?? 0) - 3))\n : [theme.unicodeEnabled ? \"Waiting for logs…\" : \"Waiting for logs...\"]\n : undefined;\n if (rows === undefined || rows < 2 || lines.length < rows) {\n ensureTicker().setLines(lines, logPane);\n return;\n }\n if (result) {\n // A finished tree can scroll normally; never try to erase beyond the viewport.\n ensureTicker().setLines([]);\n ensureTicker().writeLog(`${lines.join(\"\\n\")}\\n`);\n return;\n }\n const ellipsis = theme.unicodeEnabled ? \"…\" : \"...\";\n if (rows < 5) {\n ensureTicker().setLines(\n [lines[0]!, ` ${ellipsis} ${lines.length - 1} rows omitted`].slice(0, rows - 1)\n );\n return;\n }\n const available = rows - 4;\n let focus = 0;\n for (const [index, line] of lines.entries()) {\n if (line.includes(SPINNER_TOKEN)) focus = index;\n }\n const start = Math.max(\n 1,\n Math.min(lines.length - available, focus - Math.floor(available / 2))\n );\n const end = start + available;\n const visible = [lines[0]!];\n if (start > 1) visible.push(` ${ellipsis} ${start - 1} rows above`);\n visible.push(...lines.slice(start, end));\n if (end < lines.length) visible.push(` ${ellipsis} ${lines.length - end} rows below`);\n ensureTicker().setLines(visible, logPane);\n };\n\n const flushProgress = (): void => {\n if (trailingFlush !== undefined) {\n clearTimeout(trailingFlush);\n trailingFlush = undefined;\n }\n if (!progressDirty) return;\n progressDirty = false;\n lastProgressRedrawAt = Date.now();\n redraw();\n };\n\n const dispose = (): void => {\n if (disposed) return;\n disposed = true;\n if (trailingFlush !== undefined) {\n clearTimeout(trailingFlush);\n trailingFlush = undefined;\n }\n ticker?.dispose();\n ticker = undefined;\n if (exitListener) process.off(\"exit\", exitListener);\n exitListener = undefined;\n resizeOutput?.off(\"resize\", redraw);\n resizeOutput = undefined;\n };\n\n const writeLog = (level: \"error\" | \"log\" | \"warn\", message?: unknown, ...args: unknown[]) => {\n const rendered = message === undefined && args.length === 0 ? \"\" : format(message, ...args);\n const safeRendered = safeTerminalLog(rendered);\n const prefix =\n level === \"error\"\n ? `${theme.styled.fail(theme.symbols.fail)} `\n : level === \"warn\"\n ? `${theme.styled.skip(\"!\")} `\n : \"\";\n const text = `${prefix}${safeRendered}\\n`;\n if (disposed) {\n output.write(text);\n return;\n }\n // Retain a bounded tail for the pane, including when the terminal is resized.\n recentLogs.push(\n ...`${prefix}${safeRendered}`\n .split(\"\\n\")\n .slice(-8)\n .map((line) => line.slice(0, 2048))\n );\n recentLogs.splice(0, Math.max(0, recentLogs.length - 8));\n if (!logPaneVisible()) ensureTicker().writeLog(text);\n progressDirty = false;\n lastProgressRedrawAt = Date.now();\n redraw();\n };\n\n const log: PipelineLogger = {\n error: (message, ...args) => writeLog(\"error\", message, ...args),\n log: (message, ...args) => writeLog(\"log\", message, ...args),\n warn: (message, ...args) => writeLog(\"warn\", message, ...args),\n };\n\n const hooks: PipelineHooks<TResult> = {\n onPipelineStart: (nextPlan) => {\n plan = nextPlan;\n for (const step of nextPlan.steps) {\n steps.set(step.id, { pipelineId: nextPlan.pipelineId, status: \"planned\", step });\n }\n if (output === process.stdout || output === process.stderr) {\n exitListener = dispose;\n process.once(\"exit\", exitListener);\n resizeOutput = output === process.stdout ? process.stdout : process.stderr;\n resizeOutput.on(\"resize\", redraw);\n }\n redraw();\n },\n onStepStatus: (event) => {\n const previous = steps.get(event.step.id);\n if (event.status === \"running\") {\n // Empty/non-visible progress only refreshes the frame; retain the last\n // visible progress snapshot while still publishing one running state.\n const progress =\n event.progress && hasVisibleStepProgress(event.progress)\n ? event.progress\n : previous?.status === \"running\"\n ? previous.progress\n : undefined;\n steps.set(event.step.id, {\n ...event,\n progress,\n details: progress?.details,\n startedAtMs: previous?.startedAtMs ?? Date.now(),\n });\n const now = Date.now();\n if (now - lastProgressRedrawAt >= refreshIntervalMs) {\n progressDirty = false;\n lastProgressRedrawAt = now;\n redraw();\n } else {\n progressDirty = true;\n trailingFlush ??= setTimeout(\n () => {\n trailingFlush = undefined;\n if (!disposed) flushProgress();\n },\n Math.max(0, refreshIntervalMs - (now - lastProgressRedrawAt))\n );\n trailingFlush.unref?.();\n }\n return;\n }\n if (event.status !== \"planned\") flushProgress();\n steps.set(event.step.id, { ...event, details: previous?.details });\n redraw();\n },\n onFinalizeStart: () => {\n finalize = { status: \"running\" };\n redraw();\n },\n onFinalizeComplete: ({ durationMs }) => {\n finalize = { durationMs, status: \"completed\" };\n redraw();\n },\n onFinalizeError: ({ durationMs, error }) => {\n finalize = { durationMs, error, status: \"failed\" };\n redraw();\n },\n onPipelineComplete: (nextResult) => {\n result = nextResult;\n redraw();\n dispose();\n },\n };\n\n return { dispose, hooks, log, mode: \"interactive\" };\n}\n\n/** Create the plain or interactive reporter selected by the configured terminal mode. */\nexport function createPipelineReporter<TResult = unknown>(\n options: PipelineReporterOptions\n): PipelineReporterController<TResult> {\n const output = options.output ?? process.stdout;\n const mode = resolveMode(output, options);\n if (mode === \"interactive\") {\n return createInteractiveReporter(options, output);\n }\n return {\n dispose: () => undefined,\n hooks: createRunReporter<TResult>(options),\n log: options.log,\n mode: \"plain\",\n };\n}\n"]}
1
+ {"version":3,"file":"interactive-reporter.js","sourceRoot":"","sources":["../../src/reporter/interactive-reporter.ts"],"names":[],"mappings":"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","sourcesContent":["import { format } from \"node:util\";\nimport type {\n PipelineError,\n PipelineHooks,\n PipelineLogger,\n PipelinePlan,\n PipelineRun,\n PipelineStepProgress,\n PipelineStepStatus,\n} from \"../core/pipeline.js\";\nimport { hasVisibleStepProgress } from \"../core/progress.js\";\nimport { elapsedToken, shimmerToken, SPINNER_TOKEN } from \"./live-ticker-frame.js\";\nimport { createLiveTicker, type LiveTicker } from \"./live-ticker.js\";\nimport {\n createReporterTheme,\n createRunReporter,\n formatDurationMs,\n type ReporterTheme,\n type RunReporterConfig,\n} from \"./reporter.js\";\nimport { safeTerminalLog, safeTerminalText } from \"./terminal-text.js\";\n\n/** Rendering mode selected for pipeline lifecycle reporting. */\nexport type PipelineReporterMode = \"auto\" | \"interactive\" | \"plain\";\nexport type ResolvedPipelineReporterMode = Exclude<PipelineReporterMode, \"auto\">;\n\n/** Writable terminal-like destination used by the interactive reporter. */\nexport interface ReporterOutput {\n readonly columns?: number;\n readonly rows?: number;\n /**\n * File descriptor for live frames. When set, spinner, elapsed time, and shimmer\n * paint on a worker thread so they keep moving during CPU-bound steps. Defaults\n * to stdout's fd when `output` is `process.stdout`.\n */\n readonly fd?: number;\n readonly isTTY?: boolean;\n write(chunk: string): unknown;\n}\n\n/** Rendering and output settings for automatic, plain, or interactive reporting. */\nexport interface PipelineReporterConfig extends RunReporterConfig {\n /** Auto selects the interactive renderer only for a capable, non-CI TTY. */\n mode?: PipelineReporterMode;\n /** Terminal stream used by the interactive renderer. Defaults to stdout. */\n output?: ReporterOutput;\n /** Spinner redraw cadence. Defaults to 80ms. */\n refreshIntervalMs?: number;\n /** Filled/empty character width for determinate progress. Defaults to 20. */\n progressBarWidth?: number;\n /** Show recent logs beside progress in TTYs at least 120 columns by 8 rows. Defaults to auto. */\n logPane?: \"auto\" | \"off\";\n}\n\nexport interface PipelineReporterOptions extends PipelineReporterConfig {\n log: PipelineLogger;\n}\n\nexport interface PipelineReporterController<TResult = unknown> {\n readonly hooks: PipelineHooks<TResult>;\n readonly log: PipelineLogger;\n readonly mode: ResolvedPipelineReporterMode;\n /** Stop redraws and restore terminal state. Safe to call more than once. */\n dispose(): void;\n}\n\ntype StepState = PipelineStepStatus & {\n /** Wall-clock ms from Date.now() when the step entered the running state. */\n startedAtMs?: number;\n details?: PipelineStepProgress[\"details\"];\n};\n\ntype FinalizeState =\n | { status: \"idle\" }\n | { status: \"running\" }\n | { durationMs: number; status: \"completed\" }\n | { durationMs: number; error: PipelineError; status: \"failed\" };\n\nfunction autoInteractiveAllowed(output: ReporterOutput, config: PipelineReporterConfig): boolean {\n const isTTY = config.terminal?.isTTY ?? output.isTTY === true;\n const ci = process.env.CI;\n const isCI = ci !== undefined && ci !== \"\" && ci !== \"0\" && ci !== \"false\";\n return isTTY && process.env.TERM !== \"dumb\" && !isCI;\n}\n\nfunction resolveMode(\n output: ReporterOutput,\n config: PipelineReporterConfig\n): ResolvedPipelineReporterMode {\n if (config.mode === \"interactive\") return \"interactive\";\n if (config.mode === \"plain\") return \"plain\";\n return autoInteractiveAllowed(output, config) ? \"interactive\" : \"plain\";\n}\n\nfunction safeNumber(value: number): number {\n return Number.isFinite(value) ? value : 0;\n}\n\nfunction formatCount(value: number): string {\n return Number.isInteger(value) ? String(value) : value.toFixed(1);\n}\n\nfunction renderProgress(progress: PipelineStepProgress, width: number, unicode: boolean): string {\n // Parent line keeps the summary message only; per-item work uses `details`.\n const message = progress.message ? ` ${safeTerminalText(progress.message)}` : \"\";\n if (progress.total === undefined || safeNumber(progress.total) <= 0) {\n return `${formatCount(safeNumber(progress.completed))}${message}`;\n }\n const completed = safeNumber(progress.completed);\n const total = safeNumber(progress.total);\n const ratio = Math.max(0, Math.min(1, completed / total));\n const filled = Math.round(ratio * width);\n const bar = `${unicode ? \"█\".repeat(filled) : \"=\".repeat(filled)}${\n unicode ? \"░\".repeat(width - filled) : \"-\".repeat(width - filled)\n }`;\n return `[${bar}] ${Math.round(ratio * 100)}% ${formatCount(completed)}/${formatCount(total)}${message}`;\n}\n\nfunction renderProgressDetail(\n detail: NonNullable<PipelineStepProgress[\"details\"]>[number],\n theme: ReporterTheme,\n spinner: string,\n progressBarWidth: number,\n parentStatus: PipelineStepStatus[\"status\"]\n): string {\n const status =\n (detail.status ?? \"running\") === \"running\" && parentStatus !== \"running\"\n ? parentStatus\n : (detail.status ?? \"running\");\n const symbol =\n status === \"completed\"\n ? theme.styled.complete(theme.symbols.complete)\n : status === \"failed\"\n ? theme.styled.fail(theme.symbols.fail)\n : status === \"skipped\" || status === \"cancelled\"\n ? theme.styled.skip(theme.symbols.skip)\n : status === \"pending\"\n ? theme.styled.description(theme.symbols.pending)\n : theme.styled.start(spinner);\n const id = safeTerminalText(detail.name ?? detail.id);\n const label =\n (detail.label ? safeTerminalText(detail.label) : \"\") +\n (detail.outputSource === \"override\" ? \" (overridden)\" : \"\");\n const labelText = status === \"cancelled\" ? `cancelled${label ? `: ${label}` : \"\"}` : label;\n const running = status === \"running\";\n const body = labelText ? `${id} ${labelText}` : id;\n const paintedBody =\n running && theme.colorEnabled\n ? shimmerToken(body)\n : `${id}${labelText ? ` ${theme.styled.description(labelText)}` : \"\"}`;\n const depth = Math.max(0, Math.min(32, Math.floor(safeNumber(detail.depth ?? 0))));\n const progress =\n detail.completed === undefined\n ? \"\"\n : ` ${renderProgress(\n { completed: detail.completed, total: detail.total },\n progressBarWidth,\n theme.unicodeEnabled\n )}`;\n return `${\" \".repeat(depth + 2)}${symbol} ${paintedBody}${progress}`;\n}\n\nfunction renderStep(\n state: StepState,\n theme: ReporterTheme,\n spinner: string,\n progressBarWidth: number\n): string[] {\n const { step } = state;\n const displayName =\n safeTerminalText(step.name ?? step.id) +\n (state.status !== \"planned\" && state.outputSource === \"override\" ? \" (overridden)\" : \"\");\n switch (state.status) {\n case \"running\": {\n const progress =\n state.progress && hasVisibleStepProgress(state.progress)\n ? ` ${renderProgress(state.progress, progressBarWidth, theme.unicodeEnabled)}`\n : \"\";\n const elapsed =\n state.startedAtMs !== undefined\n ? ` ${theme.styled.duration(elapsedToken(state.startedAtMs))}`\n : \"\";\n const lines = [\n ` ${theme.styled.start(spinner)} ${shimmerToken(displayName)}${progress}${elapsed}`,\n ];\n return lines;\n }\n case \"completed\":\n return [\n ` ${theme.styled.complete(theme.symbols.complete)} ${displayName} ${theme.styled.duration(\n `(${formatDurationMs(state.finishedAtMs - state.startedAtMs)})`\n )}`,\n ];\n case \"failed\":\n return [\n ` ${theme.styled.fail(theme.symbols.fail)} ${displayName}: ${safeTerminalText(\n state.error.message\n )}`,\n ];\n case \"cancelled\":\n return [\n ` ${theme.styled.skip(theme.symbols.skip)} ${displayName}: cancelled: ${safeTerminalText(\n state.error.message\n )}`,\n ];\n case \"skipped\":\n return [\n ` ${theme.styled.skip(theme.symbols.skip)} ${displayName} ${theme.styled.duration(\n `(${safeTerminalText(state.message ?? state.reason)})`\n )}`,\n ];\n case \"planned\":\n return [\n ` ${theme.styled.description(theme.symbols.pending)} ${displayName} ${theme.styled.description(\"waiting\")}`,\n ];\n }\n}\n\nfunction reporterOutputFd(output: ReporterOutput): number | undefined {\n const fd = output.fd ?? (output === process.stdout ? process.stdout.fd : undefined);\n return fd !== undefined && Number.isInteger(fd) && fd >= 0 ? fd : undefined;\n}\n\nfunction createInteractiveReporter<TResult>(\n options: PipelineReporterOptions,\n output: ReporterOutput\n): PipelineReporterController<TResult> {\n const terminalIsTTY = options.terminal?.isTTY ?? output.isTTY === true;\n const theme = createReporterTheme({\n ...options,\n terminal: { isTTY: terminalIsTTY, ...options.terminal },\n });\n const progressBarWidth = Math.max(4, Math.floor(options.progressBarWidth ?? 20));\n // ~12.5 fps keeps braille spinners smooth without flooding the terminal.\n const refreshIntervalMs = Math.max(16, Math.floor(options.refreshIntervalMs ?? 80));\n const steps = new Map<string, StepState>();\n const recentLogs: string[] = [];\n let plan: PipelinePlan | undefined;\n let result: PipelineRun<TResult> | undefined;\n let finalize: FinalizeState = { status: \"idle\" };\n let lastProgressRedrawAt = Number.NEGATIVE_INFINITY;\n let progressDirty = false;\n let disposed = false;\n let ticker: LiveTicker | undefined;\n let trailingFlush: ReturnType<typeof setTimeout> | undefined;\n let exitListener: (() => void) | undefined;\n let resizeOutput: NodeJS.WriteStream | undefined;\n\n const frameLines = (): string[] => {\n if (!plan) return [];\n const lines: string[] = [];\n if (options.logPlan !== false) {\n const header = result\n ? options.logSummary === false\n ? `Pipeline ${safeTerminalText(result.pipelineId)}`\n : `Pipeline ${safeTerminalText(result.pipelineId)}: done in ${formatDurationMs(result.finishedAtMs - result.startedAtMs)} (status=${result.status}, steps=${result.steps.length}, errors=${result.errors.length})`\n : `Pipeline ${safeTerminalText(plan.pipelineId)} (${plan.steps.length} steps, dryRun=${plan.dryRun})`;\n lines.push(\n result?.status === \"completed\"\n ? theme.styled.complete(header)\n : result\n ? theme.styled.fail(header)\n : theme.styled.pipeline(header)\n );\n }\n for (const state of steps.values()) {\n lines.push(...renderStep(state, theme, SPINNER_TOKEN, progressBarWidth));\n for (const detail of state.details ?? []) {\n lines.push(\n renderProgressDetail(detail, theme, SPINNER_TOKEN, progressBarWidth, state.status)\n );\n }\n }\n if (finalize.status === \"running\") {\n lines.push(` ${theme.styled.start(SPINNER_TOKEN)} ${shimmerToken(\"finalize\")}`);\n } else if (finalize.status === \"completed\") {\n lines.push(\n ` ${theme.styled.complete(theme.symbols.complete)} finalize ${theme.styled.duration(\n `(${formatDurationMs(finalize.durationMs)})`\n )}`\n );\n } else if (finalize.status === \"failed\") {\n lines.push(\n ` ${theme.styled.fail(theme.symbols.fail)} finalize: ${safeTerminalText(\n finalize.error.message\n )}`\n );\n }\n return lines;\n };\n\n const ensureTicker = (): LiveTicker => {\n if (!ticker) {\n ticker = createLiveTicker({\n color: theme.colorEnabled,\n columns: output.columns,\n getColumns: () => output.columns,\n fd: reporterOutputFd(output),\n refreshIntervalMs,\n unicode: theme.unicodeEnabled,\n write: (chunk) => {\n output.write(chunk);\n },\n });\n }\n return ticker;\n };\n\n const logPaneVisible = (): boolean =>\n plan !== undefined &&\n !result &&\n options.logPane !== \"off\" &&\n (output.columns ?? 0) >= 120 &&\n (output.rows ?? 0) >= 8;\n\n const redraw = (): void => {\n if (disposed) return;\n const lines = frameLines();\n if (lines.length === 0 && !logPaneVisible()) {\n ticker?.setLines([]);\n return;\n }\n const rows = output.rows;\n const logPane = logPaneVisible()\n ? recentLogs.length > 0\n ? recentLogs.slice(-Math.min(8, (rows ?? 0) - 3))\n : [theme.unicodeEnabled ? \"Waiting for logs…\" : \"Waiting for logs...\"]\n : undefined;\n if (rows === undefined || rows < 2 || lines.length < rows) {\n ensureTicker().setLines(lines, logPane);\n return;\n }\n if (result) {\n // A finished tree can scroll normally; never try to erase beyond the viewport.\n ensureTicker().setLines([]);\n ensureTicker().writeLog(`${lines.join(\"\\n\")}\\n`);\n return;\n }\n const ellipsis = theme.unicodeEnabled ? \"…\" : \"...\";\n if (rows < 5) {\n ensureTicker().setLines(\n [lines[0]!, ` ${ellipsis} ${lines.length - 1} rows omitted`].slice(0, rows - 1)\n );\n return;\n }\n const available = rows - 4;\n let focus = 0;\n for (const [index, line] of lines.entries()) {\n if (line.includes(SPINNER_TOKEN)) focus = index;\n }\n const start = Math.max(\n 1,\n Math.min(lines.length - available, focus - Math.floor(available / 2))\n );\n const end = start + available;\n const visible = [lines[0]!];\n if (start > 1) visible.push(` ${ellipsis} ${start - 1} rows above`);\n visible.push(...lines.slice(start, end));\n if (end < lines.length) visible.push(` ${ellipsis} ${lines.length - end} rows below`);\n ensureTicker().setLines(visible, logPane);\n };\n\n const flushProgress = (): void => {\n if (trailingFlush !== undefined) {\n clearTimeout(trailingFlush);\n trailingFlush = undefined;\n }\n if (!progressDirty) return;\n progressDirty = false;\n lastProgressRedrawAt = Date.now();\n redraw();\n };\n\n const dispose = (): void => {\n if (disposed) return;\n disposed = true;\n if (trailingFlush !== undefined) {\n clearTimeout(trailingFlush);\n trailingFlush = undefined;\n }\n ticker?.dispose();\n ticker = undefined;\n if (exitListener) process.off(\"exit\", exitListener);\n exitListener = undefined;\n resizeOutput?.off(\"resize\", redraw);\n resizeOutput = undefined;\n };\n\n const writeLog = (level: \"error\" | \"log\" | \"warn\", message?: unknown, ...args: unknown[]) => {\n const rendered = message === undefined && args.length === 0 ? \"\" : format(message, ...args);\n const safeRendered = safeTerminalLog(rendered);\n const prefix =\n level === \"error\"\n ? `${theme.styled.fail(theme.symbols.fail)} `\n : level === \"warn\"\n ? `${theme.styled.skip(\"!\")} `\n : \"\";\n const text = `${prefix}${safeRendered}\\n`;\n if (disposed) {\n output.write(text);\n return;\n }\n // Retain a bounded tail for the pane, including when the terminal is resized.\n recentLogs.push(\n ...`${prefix}${safeRendered}`\n .split(\"\\n\")\n .slice(-8)\n .map((line) => line.slice(0, 2048))\n );\n recentLogs.splice(0, Math.max(0, recentLogs.length - 8));\n if (!logPaneVisible()) ensureTicker().writeLog(text);\n progressDirty = false;\n lastProgressRedrawAt = Date.now();\n redraw();\n };\n\n const log: PipelineLogger = {\n error: (message, ...args) => writeLog(\"error\", message, ...args),\n log: (message, ...args) => writeLog(\"log\", message, ...args),\n warn: (message, ...args) => writeLog(\"warn\", message, ...args),\n };\n\n const hooks: PipelineHooks<TResult> = {\n onPipelineStart: (nextPlan) => {\n plan = nextPlan;\n for (const step of nextPlan.steps) {\n steps.set(step.id, { pipelineId: nextPlan.pipelineId, status: \"planned\", step });\n }\n if (output === process.stdout || output === process.stderr) {\n exitListener = dispose;\n process.once(\"exit\", exitListener);\n resizeOutput = output === process.stdout ? process.stdout : process.stderr;\n resizeOutput.on(\"resize\", redraw);\n }\n redraw();\n },\n onStepStatus: (event) => {\n const previous = steps.get(event.step.id);\n if (event.status === \"running\") {\n // Empty/non-visible progress only refreshes the frame; retain the last\n // visible progress snapshot while still publishing one running state.\n const progress =\n event.progress && hasVisibleStepProgress(event.progress)\n ? event.progress\n : previous?.status === \"running\"\n ? previous.progress\n : undefined;\n steps.set(event.step.id, {\n ...event,\n progress,\n details: progress?.details,\n startedAtMs: previous?.startedAtMs ?? Date.now(),\n });\n const now = Date.now();\n if (now - lastProgressRedrawAt >= refreshIntervalMs) {\n progressDirty = false;\n lastProgressRedrawAt = now;\n redraw();\n } else {\n progressDirty = true;\n trailingFlush ??= setTimeout(\n () => {\n trailingFlush = undefined;\n if (!disposed) flushProgress();\n },\n Math.max(0, refreshIntervalMs - (now - lastProgressRedrawAt))\n );\n trailingFlush.unref?.();\n }\n return;\n }\n if (event.status !== \"planned\") flushProgress();\n steps.set(event.step.id, { ...event, details: previous?.details });\n redraw();\n },\n onFinalizeStart: () => {\n finalize = { status: \"running\" };\n redraw();\n },\n onFinalizeComplete: ({ durationMs }) => {\n finalize = { durationMs, status: \"completed\" };\n redraw();\n },\n onFinalizeError: ({ durationMs, error }) => {\n finalize = { durationMs, error, status: \"failed\" };\n redraw();\n },\n onPipelineComplete: (nextResult) => {\n result = nextResult;\n redraw();\n dispose();\n },\n };\n\n return { dispose, hooks, log, mode: \"interactive\" };\n}\n\n/** Create the plain or interactive reporter selected by the configured terminal mode. */\nexport function createPipelineReporter<TResult = unknown>(\n options: PipelineReporterOptions\n): PipelineReporterController<TResult> {\n const output = options.output ?? process.stdout;\n const mode = resolveMode(output, options);\n if (mode === \"interactive\") {\n return createInteractiveReporter(options, output);\n }\n return {\n dispose: () => undefined,\n hooks: createRunReporter<TResult>(options),\n log: options.log,\n mode: \"plain\",\n };\n}\n"]}
@@ -0,0 +1,21 @@
1
+ export declare const SPINNER_TOKEN = "\u0001";
2
+ export declare const TICKER_ANSI: {
3
+ readonly clearDown: "\u001B[J";
4
+ readonly hideCursor: "\u001B[?25l";
5
+ readonly reset: "\u001B[0m";
6
+ readonly showCursor: "\u001B[?25h";
7
+ };
8
+ export declare function elapsedToken(startedAtMs: number): string;
9
+ export declare function shimmerToken(value: string): string;
10
+ export declare function paintLiveLines(lines: readonly string[], spinner: string, nowMs: number, columns?: number, color?: boolean, unicode?: boolean, logPane?: readonly string[]): string[];
11
+ export declare class TickerFrame {
12
+ private readonly write;
13
+ private paintedLines;
14
+ private cursorHidden;
15
+ constructor(write: (chunk: string) => void, paintedLines?: readonly string[]);
16
+ showCursor(): void;
17
+ clear(columns?: number): void;
18
+ redraw(lines: readonly string[], columns?: number): void;
19
+ }
20
+ export declare function currentSpinner(unicode: boolean, refreshIntervalMs: number): string;
21
+ export declare function hasLiveAnimation(lines: readonly string[]): boolean;