@reasonlayer/sdk 0.0.1-rc.3

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 (101) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +35 -0
  3. package/bin/rl.mjs +75 -0
  4. package/dist/builder.d.ts +38 -0
  5. package/dist/builder.js +41 -0
  6. package/dist/bundler/index.d.ts +32 -0
  7. package/dist/bundler/index.js +143 -0
  8. package/dist/bundler/node.d.ts +10 -0
  9. package/dist/bundler/node.js +55 -0
  10. package/dist/cli/args.d.ts +9 -0
  11. package/dist/cli/args.js +71 -0
  12. package/dist/cli/config.d.ts +38 -0
  13. package/dist/cli/config.js +94 -0
  14. package/dist/cli/convex.d.ts +9 -0
  15. package/dist/cli/convex.js +25 -0
  16. package/dist/cli/format.d.ts +11 -0
  17. package/dist/cli/format.js +140 -0
  18. package/dist/cli/index.d.ts +1 -0
  19. package/dist/cli/index.js +721 -0
  20. package/dist/cli/keychain.d.ts +21 -0
  21. package/dist/cli/keychain.js +100 -0
  22. package/dist/cli/operations.d.ts +106 -0
  23. package/dist/cli/operations.js +623 -0
  24. package/dist/cli/sdk-package.d.ts +18 -0
  25. package/dist/cli/sdk-package.js +45 -0
  26. package/dist/cli/storage-upload.d.ts +9 -0
  27. package/dist/cli/storage-upload.js +21 -0
  28. package/dist/cli/watcher-compile.d.ts +1 -0
  29. package/dist/cli/watcher-compile.js +20 -0
  30. package/dist/cli/watcher-process.d.ts +1 -0
  31. package/dist/cli/watcher-process.js +312 -0
  32. package/dist/cli/workspace-files.d.ts +12 -0
  33. package/dist/cli/workspace-files.js +91 -0
  34. package/dist/cli/workspace-local.d.ts +27 -0
  35. package/dist/cli/workspace-local.js +310 -0
  36. package/dist/cli/workspace-session.d.ts +13 -0
  37. package/dist/cli/workspace-session.js +12 -0
  38. package/dist/compile.d.ts +27 -0
  39. package/dist/compile.js +834 -0
  40. package/dist/index.d.ts +10 -0
  41. package/dist/index.js +5 -0
  42. package/dist/schedule-validation.d.ts +1 -0
  43. package/dist/schedule-validation.js +16 -0
  44. package/dist/selector-schema.d.ts +26 -0
  45. package/dist/selector-schema.js +780 -0
  46. package/dist/selectors.d.ts +25 -0
  47. package/dist/selectors.js +99 -0
  48. package/dist/testkit.d.ts +32 -0
  49. package/dist/testkit.js +161 -0
  50. package/dist/types.d.ts +184 -0
  51. package/dist/types.js +110 -0
  52. package/node_modules/@reasonlayer/integrations/dist/catalog.d.ts +4937 -0
  53. package/node_modules/@reasonlayer/integrations/dist/catalog.js +20 -0
  54. package/node_modules/@reasonlayer/integrations/dist/generated/slack.d.ts +3014 -0
  55. package/node_modules/@reasonlayer/integrations/dist/generated/slack.js +3101 -0
  56. package/node_modules/@reasonlayer/integrations/dist/index.d.ts +2 -0
  57. package/node_modules/@reasonlayer/integrations/dist/index.js +1 -0
  58. package/node_modules/@reasonlayer/integrations/dist/internal/definitions.d.ts +44 -0
  59. package/node_modules/@reasonlayer/integrations/dist/internal/definitions.js +52 -0
  60. package/node_modules/@reasonlayer/integrations/dist/internal/transport.d.ts +7 -0
  61. package/node_modules/@reasonlayer/integrations/dist/internal/transport.js +48 -0
  62. package/node_modules/@reasonlayer/integrations/dist/testkit.d.ts +1 -0
  63. package/node_modules/@reasonlayer/integrations/dist/testkit.js +1 -0
  64. package/node_modules/@reasonlayer/integrations/package.json +26 -0
  65. package/node_modules/@reasonlayer/protocol/dist/environments.d.ts +7 -0
  66. package/node_modules/@reasonlayer/protocol/dist/environments.js +7 -0
  67. package/node_modules/@reasonlayer/protocol/dist/events.d.ts +313 -0
  68. package/node_modules/@reasonlayer/protocol/dist/events.js +20 -0
  69. package/node_modules/@reasonlayer/protocol/dist/index.d.ts +18 -0
  70. package/node_modules/@reasonlayer/protocol/dist/index.js +9 -0
  71. package/node_modules/@reasonlayer/protocol/dist/ir.d.ts +252 -0
  72. package/node_modules/@reasonlayer/protocol/dist/ir.js +116 -0
  73. package/node_modules/@reasonlayer/protocol/dist/permissions.d.ts +5 -0
  74. package/node_modules/@reasonlayer/protocol/dist/permissions.js +30 -0
  75. package/node_modules/@reasonlayer/protocol/dist/readmodels.d.ts +617 -0
  76. package/node_modules/@reasonlayer/protocol/dist/readmodels.js +36 -0
  77. package/node_modules/@reasonlayer/protocol/dist/runtime.d.ts +67 -0
  78. package/node_modules/@reasonlayer/protocol/dist/runtime.js +66 -0
  79. package/node_modules/@reasonlayer/protocol/dist/scheduling.d.ts +69 -0
  80. package/node_modules/@reasonlayer/protocol/dist/scheduling.js +126 -0
  81. package/node_modules/@reasonlayer/protocol/dist/selector.d.ts +23 -0
  82. package/node_modules/@reasonlayer/protocol/dist/selector.js +77 -0
  83. package/node_modules/@reasonlayer/protocol/dist/tasks.d.ts +69 -0
  84. package/node_modules/@reasonlayer/protocol/dist/tasks.js +6 -0
  85. package/node_modules/@reasonlayer/protocol/dist/validate.d.ts +6 -0
  86. package/node_modules/@reasonlayer/protocol/dist/validate.js +18 -0
  87. package/node_modules/@reasonlayer/protocol/package.json +21 -0
  88. package/node_modules/@reasonlayer/runner/dist/environment-materializer.d.ts +13 -0
  89. package/node_modules/@reasonlayer/runner/dist/environment-materializer.js +92 -0
  90. package/node_modules/@reasonlayer/runner/dist/flue-transcript.d.ts +17 -0
  91. package/node_modules/@reasonlayer/runner/dist/flue-transcript.js +182 -0
  92. package/node_modules/@reasonlayer/runner/dist/index.d.ts +184 -0
  93. package/node_modules/@reasonlayer/runner/dist/index.js +884 -0
  94. package/node_modules/@reasonlayer/runner/dist/mcp-supervisor.d.ts +15 -0
  95. package/node_modules/@reasonlayer/runner/dist/mcp-supervisor.js +142 -0
  96. package/node_modules/@reasonlayer/runner/dist/sandbox-env.d.ts +36 -0
  97. package/node_modules/@reasonlayer/runner/dist/sandbox-env.js +171 -0
  98. package/node_modules/@reasonlayer/runner/dist/task-child.d.ts +1 -0
  99. package/node_modules/@reasonlayer/runner/dist/task-child.js +72 -0
  100. package/node_modules/@reasonlayer/runner/package.json +21 -0
  101. package/package.json +65 -0
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Proxy wiring → SelectorIR (spec §4.2). Wiring callbacks run at compile
3
+ * time against proxies that record property accesses; lowering turns the
4
+ * recorded accesses (plus plain objects/arrays/literals) into SelectorIR.
5
+ */
6
+ import type { SelectorIR } from "@reasonlayer/protocol";
7
+ /** Compile-time stand-in for a value of type T; property access is recorded, nothing else is allowed. */
8
+ export type Wire<T> = T extends object ? {
9
+ [K in keyof T]: Wire<T[K]>;
10
+ } : T;
11
+ export declare class WiringError extends Error {
12
+ }
13
+ export declare function inputProxy(): unknown;
14
+ export declare function stepProxy(stepId: string): unknown;
15
+ export declare function variableProxy(name: string): unknown;
16
+ export declare function mapItemProxy(): unknown;
17
+ /**
18
+ * The `steps` argument handed to wiring callbacks: exposes exactly the
19
+ * steps declared so far — later steps are invisible (spec §4.2), and an
20
+ * unknown id is a compile error with the known ids listed.
21
+ */
22
+ export declare function stepsProxy(knownStepIds: readonly string[]): unknown;
23
+ /** Lower a wiring result to SelectorIR. Throws WiringError on non-serializable leaves. */
24
+ export declare function lower(value: unknown): SelectorIR;
25
+ export { referencedStepIds, usesMapItem } from "@reasonlayer/protocol";
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Proxy wiring → SelectorIR (spec §4.2). Wiring callbacks run at compile
3
+ * time against proxies that record property accesses; lowering turns the
4
+ * recorded accesses (plus plain objects/arrays/literals) into SelectorIR.
5
+ */
6
+ const NODE = Symbol.for("reasonlayer.selectorNode");
7
+ export class WiringError extends Error {
8
+ }
9
+ function makeProxy(node) {
10
+ return new Proxy(Object.create(null), {
11
+ get(_target, prop) {
12
+ if (prop === NODE)
13
+ return node;
14
+ // Wiring values are opaque at compile time; block the traps that
15
+ // silently corrupt recording (await, spread, JSON.stringify).
16
+ if (prop === "then" || prop === Symbol.toPrimitive || prop === "toJSON") {
17
+ return undefined;
18
+ }
19
+ if (typeof prop === "symbol")
20
+ return undefined;
21
+ return makeProxy({ ...node, path: [...node.path, prop] });
22
+ },
23
+ has(_target, prop) {
24
+ return prop === NODE;
25
+ },
26
+ ownKeys() {
27
+ throw new WiringError("wiring values cannot be spread or enumerated — wire whole values or individual fields");
28
+ },
29
+ set() {
30
+ throw new WiringError("wiring values are read-only");
31
+ },
32
+ });
33
+ }
34
+ export function inputProxy() {
35
+ return makeProxy({ kind: "input", path: [] });
36
+ }
37
+ export function stepProxy(stepId) {
38
+ return makeProxy({ kind: "step", stepId, path: [] });
39
+ }
40
+ export function variableProxy(name) {
41
+ return makeProxy({ kind: "variable", name, path: [] });
42
+ }
43
+ export function mapItemProxy() {
44
+ return makeProxy({ kind: "mapItem", path: [] });
45
+ }
46
+ /**
47
+ * The `steps` argument handed to wiring callbacks: exposes exactly the
48
+ * steps declared so far — later steps are invisible (spec §4.2), and an
49
+ * unknown id is a compile error with the known ids listed.
50
+ */
51
+ export function stepsProxy(knownStepIds) {
52
+ const known = new Set(knownStepIds);
53
+ return new Proxy(Object.create(null), {
54
+ get(_target, prop) {
55
+ if (typeof prop === "symbol")
56
+ return undefined;
57
+ if (!known.has(prop)) {
58
+ throw new WiringError(`unknown step "${prop}" — steps declared so far: ${knownStepIds.length > 0 ? knownStepIds.join(", ") : "(none)"}. Steps can only wire to earlier steps.`);
59
+ }
60
+ return stepProxy(prop);
61
+ },
62
+ });
63
+ }
64
+ function nodeOf(value) {
65
+ if (value === null || (typeof value !== "object" && typeof value !== "function")) {
66
+ return undefined;
67
+ }
68
+ return value[NODE];
69
+ }
70
+ function isPlainObject(value) {
71
+ if (value === null || typeof value !== "object")
72
+ return false;
73
+ const proto = Object.getPrototypeOf(value);
74
+ return proto === Object.prototype || proto === null;
75
+ }
76
+ /** Lower a wiring result to SelectorIR. Throws WiringError on non-serializable leaves. */
77
+ export function lower(value) {
78
+ const node = nodeOf(value);
79
+ if (node)
80
+ return node;
81
+ if (Array.isArray(value)) {
82
+ return { kind: "array", items: value.map(lower) };
83
+ }
84
+ if (isPlainObject(value)) {
85
+ const fields = {};
86
+ for (const [key, field] of Object.entries(value)) {
87
+ fields[key] = lower(field);
88
+ }
89
+ return { kind: "object", fields };
90
+ }
91
+ if (value === null ||
92
+ typeof value === "string" ||
93
+ typeof value === "number" ||
94
+ typeof value === "boolean") {
95
+ return { kind: "literal", value };
96
+ }
97
+ throw new WiringError(`cannot wire a value of type ${typeof value} — wiring supports step/input references, plain objects, arrays, and JSON literals`);
98
+ }
99
+ export { referencedStepIds, usesMapItem } from "@reasonlayer/protocol";
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The workflow test kit (spec §4.6): run a compiled workflow in-process with
3
+ * a fake task executor — no Convex, no workflow component, no network. This
4
+ * consumes the same scheduling core as the Convex engine for readiness waves,
5
+ * map dedupe/fan-out, and output evaluation.
6
+ */
7
+ export { setIntegrationTransport, type IntegrationTransport, type IntegrationTransportRequest, } from "@reasonlayer/integrations/testkit";
8
+ import { type MapChildStepIR, type StepIR, type WorkflowIR } from "@reasonlayer/protocol";
9
+ import type { WorkflowDefinition } from "./types.js";
10
+ export interface TestRunOptions {
11
+ input: unknown;
12
+ /**
13
+ * Executes one task (code, agent, or catalog action step). Defaults to calling the
14
+ * workflow's own code-step functions; agent and action steps must be supplied here
15
+ * or via `stepOutputs`.
16
+ */
17
+ executeTask?: (step: StepIR | MapChildStepIR, input: unknown) => Promise<unknown> | unknown;
18
+ /** Hard overrides: step id → output. Skips execution entirely for that step. */
19
+ stepOutputs?: Record<string, unknown>;
20
+ /** Workflow-variable overrides; undeclared names and schema-invalid values are rejected. */
21
+ variables?: Record<string, unknown>;
22
+ /** Resolves review steps; receives an output-shaped draft and returns its approved or edited value. */
23
+ onReview?: (stepId: string, content: unknown) => Promise<unknown> | unknown;
24
+ }
25
+ export interface TestRunResult {
26
+ output: unknown;
27
+ stepOutputs: Record<string, unknown>;
28
+ /** Step ids in the order they completed (waves are deterministic: declaration order within a wave). */
29
+ completionOrder: string[];
30
+ }
31
+ export declare function runWorkflowTest(definition: WorkflowDefinition, options: TestRunOptions): Promise<TestRunResult>;
32
+ export declare function runCompiledWorkflowTest(ir: WorkflowIR, codeRefs: Record<string, (input: never) => unknown>, options: TestRunOptions): Promise<TestRunResult>;
@@ -0,0 +1,161 @@
1
+ /**
2
+ * The workflow test kit (spec §4.6): run a compiled workflow in-process with
3
+ * a fake task executor — no Convex, no workflow component, no network. This
4
+ * consumes the same scheduling core as the Convex engine for readiness waves,
5
+ * map dedupe/fan-out, and output evaluation.
6
+ */
7
+ export { setIntegrationTransport, } from "@reasonlayer/integrations/testkit";
8
+ import { collapseMapChildren, evaluateStepInput, evaluateWorkflowOutput, expandMapStep, readySteps, validateAgainstSchema, } from "@reasonlayer/protocol";
9
+ import { compileWorkflow } from "./compile.js";
10
+ export async function runWorkflowTest(definition, options) {
11
+ const compiled = compileWorkflow(definition);
12
+ if (!compiled.ok) {
13
+ throw new Error(`workflow does not compile:\n${compiled.errors
14
+ .map((e) => ` ${e.stepId ? `[${e.stepId}] ` : ""}${e.message}`)
15
+ .join("\n")}`);
16
+ }
17
+ return runCompiledWorkflowTest(compiled.ir, compiled.codeRefs, options);
18
+ }
19
+ export async function runCompiledWorkflowTest(ir, codeRefs, options) {
20
+ const variables = resolveTestVariables(ir, options.variables);
21
+ const selectorVariables = variables !== undefined ? { variables } : {};
22
+ const outputs = { ...options.stepOutputs };
23
+ const completionOrder = [];
24
+ const stepById = new Map(Object.values(ir.steps).map((step) => [step.id, step]));
25
+ for (const [stepId, output] of Object.entries(outputs)) {
26
+ const step = stepById.get(stepId);
27
+ if (!step)
28
+ throw new Error(`unknown stepOutputs key "${stepId}"`);
29
+ validateStepOutput(step, output);
30
+ }
31
+ const executeTask = options.executeTask ??
32
+ ((step, input) => {
33
+ if (step.kind === "code") {
34
+ const run = codeRefs[step.id];
35
+ if (!run)
36
+ throw new Error(`no code ref for step "${step.id}"`);
37
+ return run(input);
38
+ }
39
+ throw new Error(`step "${step.id}" is an ${step.kind} step — supply executeTask or a stepOutputs override`);
40
+ });
41
+ const runStep = async (step) => {
42
+ switch (step.kind) {
43
+ case "code":
44
+ case "agent":
45
+ case "action": {
46
+ const input = evaluateStepInput(step, { input: options.input, stepOutputs: outputs, ...selectorVariables });
47
+ return executeTask(step, input);
48
+ }
49
+ case "review": {
50
+ const content = evaluateStepInput(step, { input: options.input, stepOutputs: outputs, ...selectorVariables });
51
+ if (!options.onReview) {
52
+ throw new Error(`review step "${step.id}" reached but no onReview handler supplied`);
53
+ }
54
+ return options.onReview(step.id, content);
55
+ }
56
+ case "map": {
57
+ const children = [];
58
+ for (const { key, item, childIndex } of expandMapStep(step, {
59
+ input: options.input,
60
+ stepOutputs: outputs,
61
+ ...selectorVariables,
62
+ })) {
63
+ const childInput = evaluateStepInput(step.step, {
64
+ input: options.input,
65
+ stepOutputs: outputs,
66
+ mapItem: item,
67
+ ...selectorVariables,
68
+ });
69
+ let output;
70
+ if (step.step.kind === "review") {
71
+ if (!options.onReview) {
72
+ throw new Error(`review child of "${step.id}" reached but no onReview handler`);
73
+ }
74
+ output = await options.onReview(step.step.id, childInput);
75
+ }
76
+ else {
77
+ try {
78
+ output = await executeTask(step.step, childInput);
79
+ }
80
+ catch (err) {
81
+ children.push({
82
+ status: "failed",
83
+ invocationKey: key,
84
+ childIndex,
85
+ error: err.message,
86
+ });
87
+ continue;
88
+ }
89
+ }
90
+ try {
91
+ validateStepOutput(step.step, output);
92
+ children.push({ status: "succeeded", invocationKey: key, childIndex, output });
93
+ }
94
+ catch (err) {
95
+ children.push({
96
+ status: "failed",
97
+ invocationKey: key,
98
+ childIndex,
99
+ error: err.message,
100
+ });
101
+ }
102
+ }
103
+ const collapsed = collapseMapChildren(children);
104
+ if (!collapsed.ok) {
105
+ throw new Error(`map step "${step.id}" failed: ${collapsed.error}`);
106
+ }
107
+ return collapsed.output;
108
+ }
109
+ }
110
+ };
111
+ const stepList = Object.values(ir.steps);
112
+ const completed = new Set(stepList.map((s) => s.id).filter((id) => id in outputs));
113
+ while (completed.size < stepList.length) {
114
+ const wave = readySteps(ir, { outputs, startedStepIds: completed });
115
+ if (wave.length === 0) {
116
+ const pending = stepList.map((s) => s.id).filter((id) => !completed.has(id));
117
+ throw new Error(`no step is ready but ${pending.length} remain (${pending.join(", ")}) — dependency deadlock`);
118
+ }
119
+ for (const step of wave) {
120
+ outputs[step.id] = await runStep(step);
121
+ if (step.kind !== "map")
122
+ validateStepOutput(step, outputs[step.id]);
123
+ completionOrder.push(step.id);
124
+ completed.add(step.id);
125
+ }
126
+ }
127
+ const output = evaluateWorkflowOutput(ir, { input: options.input, stepOutputs: outputs, ...selectorVariables });
128
+ validateAgainstSchema(output, ir.outputSchemaJson, "workflow output");
129
+ return { output, stepOutputs: outputs, completionOrder };
130
+ }
131
+ function resolveTestVariables(ir, overrides) {
132
+ const declarations = ir.variables ?? [];
133
+ if (declarations.length === 0 && !overrides)
134
+ return undefined;
135
+ const declared = new Map(declarations.map((variable) => [variable.name, variable]));
136
+ const resolved = Object.create(null);
137
+ for (const variable of declarations)
138
+ resolved[variable.name] = variable.defaultJson;
139
+ for (const [name, value] of Object.entries(overrides ?? {})) {
140
+ const variable = declared.get(name);
141
+ if (!variable)
142
+ throw new Error(`unknown variable override "${name}"`);
143
+ validateAgainstSchema(value, variable.schemaJson, `variable "${name}" override`);
144
+ resolved[name] = value;
145
+ }
146
+ return resolved;
147
+ }
148
+ function validateStepOutput(step, output) {
149
+ try {
150
+ validateAgainstSchema(output, stepOutputSchema(step), "step output");
151
+ }
152
+ catch (err) {
153
+ throw new Error(`step "${step.id}" failed output validation: ${err.message}`);
154
+ }
155
+ }
156
+ function stepOutputSchema(step) {
157
+ if (step.kind === "map") {
158
+ return { type: "array", items: step.step.outputSchemaJson };
159
+ }
160
+ return step.outputSchemaJson;
161
+ }
@@ -0,0 +1,184 @@
1
+ import * as v from "valibot";
2
+ import type { CatalogActionDescriptor, CatalogActionInput } from "@reasonlayer/integrations";
3
+ import type { HostIR, JsonSchema, RetryPolicyIR, ReviewViewIR } from "@reasonlayer/protocol";
4
+ import type { Wire } from "./selectors.js";
5
+ export type AnySchema = v.GenericSchema<any, any>;
6
+ export type Out<S extends AnySchema> = v.InferOutput<S>;
7
+ export interface VariableConfig<S extends AnySchema> {
8
+ schema: S;
9
+ default: Out<S>;
10
+ description?: string;
11
+ }
12
+ export interface VariableDefinition {
13
+ schemaJson: JsonSchema;
14
+ defaultJson: unknown;
15
+ description?: string;
16
+ }
17
+ export declare function defineVariable<const S extends AnySchema>(name: string, config: VariableConfig<S>): Wire<Out<S>>;
18
+ export declare function variableDefinitionForCompile(name: string): VariableDefinition | undefined;
19
+ export declare function resetVariableRegistryForTests(): void;
20
+ /** A declared secret dependency (spec §11); the value is injected as env at run time, never held in the definition. */
21
+ export interface SecretRef {
22
+ readonly __rlSecret: string;
23
+ }
24
+ export declare function secret(name: string): SecretRef;
25
+ /** A declared org-side placement handle (spec §4.3); source never names a physical device. */
26
+ export interface DeviceRef {
27
+ readonly __rlDeviceHandle: string;
28
+ }
29
+ export declare function device(handle: string): DeviceRef;
30
+ export interface ScheduleTrigger {
31
+ readonly __rlTrigger: "schedule";
32
+ readonly name: string;
33
+ readonly cron: string;
34
+ readonly timezone?: string;
35
+ }
36
+ export declare function schedule(name: string, config: {
37
+ cron: string;
38
+ timezone?: string;
39
+ }): ScheduleTrigger;
40
+ export interface EnvironmentDefinition<McpNames extends string = string> {
41
+ readonly __rlEnvironment: true;
42
+ readonly config: EnvironmentConfig;
43
+ readonly __rlMcpNames?: McpNames;
44
+ }
45
+ export interface LocalMcpServerConfig {
46
+ command: string;
47
+ transport: "http";
48
+ env?: Record<string, SecretRef>;
49
+ }
50
+ export interface RemoteMcpServerConfig {
51
+ url: string;
52
+ headers?: Record<string, SecretRef>;
53
+ }
54
+ export type McpServerConfig = LocalMcpServerConfig | RemoteMcpServerConfig;
55
+ export interface EnvironmentConfig {
56
+ npm?: string[];
57
+ pip?: string[];
58
+ apt?: string[];
59
+ /** Executables to verify on PATH, e.g. apt package "ripgrep" provides binary "rg". */
60
+ binaries?: string[];
61
+ /** local source path -> absolute path inside the sandbox template */
62
+ files?: Record<string, string>;
63
+ setup?: string[];
64
+ mcp?: Record<string, McpServerConfig>;
65
+ }
66
+ export declare function defineEnvironment<const Config extends EnvironmentConfig>(config: Config): EnvironmentDefinition<Extract<keyof NonNullable<Config["mcp"]>, string>>;
67
+ export type EnvironmentMcpName<Env extends EnvironmentDefinition> = Env extends EnvironmentDefinition<infer Name> ? Name : never;
68
+ export declare function mcpUrl<const Env extends EnvironmentDefinition>(environment: Env, name: EnvironmentMcpName<Env>): string;
69
+ export declare function mcpUrl(name: string): string;
70
+ /** `steps` as seen by wiring callbacks: earlier steps only, typed by their output schemas. */
71
+ export type StepsOf<Steps> = {
72
+ readonly [K in keyof Steps]: Wire<Steps[K]>;
73
+ };
74
+ export type InputWiring<Steps, Input, T> = (steps: StepsOf<Steps>, input: Wire<Input>) => Wire<T>;
75
+ export interface WorkflowConfig<InS extends AnySchema, OutS extends AnySchema> {
76
+ id: string;
77
+ input: InS;
78
+ output: OutS;
79
+ description?: string;
80
+ secrets?: SecretRef[];
81
+ devices?: DeviceRef[];
82
+ triggers?: ScheduleTrigger[];
83
+ }
84
+ export interface CodeStepConfig<Steps, Input, TIn, OutS extends AnySchema> {
85
+ input?: InputWiring<Steps, Input, TIn>;
86
+ output: OutS;
87
+ run: (input: TIn) => Out<OutS> | Promise<Out<OutS>>;
88
+ host: HostIR;
89
+ browserProfile?: string;
90
+ timeoutMs?: number;
91
+ retries?: RetryPolicyIR;
92
+ secrets?: SecretRef[];
93
+ environment?: EnvironmentDefinition;
94
+ }
95
+ export interface AgentStepConfig<Steps, Input, TIn, OutS extends AnySchema> {
96
+ /** A Flue `defineAgent` — imported directly from @flue/runtime, never wrapped (spec §1.4). */
97
+ agent: unknown;
98
+ input?: InputWiring<Steps, Input, TIn>;
99
+ output: OutS;
100
+ tools?: readonly CatalogActionDescriptor[];
101
+ host: HostIR;
102
+ browserProfile?: string;
103
+ timeoutMs?: number;
104
+ retries?: RetryPolicyIR;
105
+ secrets?: SecretRef[];
106
+ environment?: EnvironmentDefinition;
107
+ }
108
+ export interface ReviewStepConfig<Steps, Input, OutS extends AnySchema> {
109
+ input: InputWiring<Steps, Input, NoInfer<Out<OutS>>>;
110
+ output: OutS;
111
+ view?: ReviewViewIR;
112
+ deadlineMs?: number;
113
+ }
114
+ export interface ActionStepConfig<Steps, Input, Action extends CatalogActionDescriptor> {
115
+ action: Action;
116
+ input: InputWiring<Steps, Input, CatalogActionInput<Action>>;
117
+ timeoutMs?: number;
118
+ retries?: RetryPolicyIR;
119
+ }
120
+ /** Child-step configs (inside map) take a composed wire VALUE, not a wiring callback (spec §4.1). */
121
+ interface ChildExecutableStepConfig<TIn, OutS extends AnySchema> {
122
+ input: Wire<TIn>;
123
+ output: OutS;
124
+ host: HostIR;
125
+ browserProfile?: string;
126
+ timeoutMs?: number;
127
+ retries?: RetryPolicyIR;
128
+ secrets?: SecretRef[];
129
+ environment?: EnvironmentDefinition;
130
+ }
131
+ export interface ChildCodeStepConfig<TIn, OutS extends AnySchema> extends ChildExecutableStepConfig<TIn, OutS> {
132
+ run: (input: TIn) => Out<OutS> | Promise<Out<OutS>>;
133
+ }
134
+ export interface ChildAgentStepConfig<TIn, OutS extends AnySchema> extends ChildExecutableStepConfig<TIn, OutS> {
135
+ agent: unknown;
136
+ tools?: readonly CatalogActionDescriptor[];
137
+ }
138
+ export interface ChildReviewStepConfig<OutS extends AnySchema> {
139
+ input: Wire<NoInfer<Out<OutS>>>;
140
+ output: OutS;
141
+ view?: ReviewViewIR;
142
+ deadlineMs?: number;
143
+ }
144
+ /** Built by the standalone code/agent/review constructors. */
145
+ export interface ChildStepDef<OutS extends AnySchema = AnySchema> {
146
+ readonly __rlChildStep: "code" | "agent" | "review";
147
+ readonly config: ChildCodeStepConfig<any, OutS> | ChildAgentStepConfig<any, OutS> | ChildReviewStepConfig<OutS>;
148
+ }
149
+ export interface MapStepConfig<Steps, Input, Item, ChildOutS extends AnySchema> {
150
+ over: InputWiring<Steps, Input, Item[]>;
151
+ /** Per-item identity for dedupe + resume (spec §4.1); must select a string off the item. */
152
+ key: (item: Wire<Item>) => Wire<string>;
153
+ step: (item: Wire<Item>) => ChildStepDef<ChildOutS>;
154
+ concurrency?: number;
155
+ retries?: RetryPolicyIR;
156
+ }
157
+ /** Internal accumulated step record; wiring callbacks run at compile time. */
158
+ export interface InternalStepDef {
159
+ kind: "code" | "agent" | "review" | "action" | "map";
160
+ id: string;
161
+ config: unknown;
162
+ }
163
+ export interface WorkflowDefinition<Input = unknown, Output = unknown> {
164
+ readonly __rlWorkflow: true;
165
+ readonly config: WorkflowConfig<AnySchema, AnySchema>;
166
+ readonly steps: readonly InternalStepDef[];
167
+ readonly outputWiring: (steps: unknown, input: unknown) => unknown;
168
+ }
169
+ export interface CompileError {
170
+ stepId?: string;
171
+ message: string;
172
+ }
173
+ export type CompileResult = {
174
+ ok: true;
175
+ ir: import("@reasonlayer/protocol").WorkflowIR;
176
+ /** stepId → the concrete run function the bundler emits into steps.js. */
177
+ codeRefs: Record<string, (input: never) => unknown>;
178
+ /** stepId → the concrete defineAgent the bundler emits into agents.js. */
179
+ agentRefs: Record<string, unknown>;
180
+ } | {
181
+ ok: false;
182
+ errors: CompileError[];
183
+ };
184
+ export {};
package/dist/types.js ADDED
@@ -0,0 +1,110 @@
1
+ import * as v from "valibot";
2
+ import { toJsonSchema } from "@valibot/to-json-schema";
3
+ import { VARIABLE_NAME_PATTERN, mcpUrlEnvName, stableJson, } from "@reasonlayer/protocol";
4
+ import { variableProxy } from "./selectors.js";
5
+ const VARIABLE_REGISTRY = Symbol.for("reasonlayer.variableRegistry");
6
+ const globals = globalThis;
7
+ const variableRegistry = (() => {
8
+ const existing = globals[VARIABLE_REGISTRY];
9
+ if (existing instanceof Map)
10
+ return existing;
11
+ const registry = new Map();
12
+ globals[VARIABLE_REGISTRY] = registry;
13
+ return registry;
14
+ })();
15
+ const MAX_VARIABLE_JSON_LENGTH = 16 * 1024;
16
+ export function defineVariable(name, config) {
17
+ if (!VARIABLE_NAME_PATTERN.test(name)) {
18
+ throw new Error(`variable name "${name}" must match ${VARIABLE_NAME_PATTERN}`);
19
+ }
20
+ let parsed;
21
+ try {
22
+ parsed = v.parse(config.schema, config.default);
23
+ }
24
+ catch (error) {
25
+ throw new Error(`variable "${name}" default does not match schema — ${error.message}`);
26
+ }
27
+ let schemaJson;
28
+ try {
29
+ schemaJson = toJsonSchema(config.schema);
30
+ }
31
+ catch (error) {
32
+ throw new Error(`variable "${name}" schema cannot convert to JSON Schema — ${error.message}`);
33
+ }
34
+ let serialized;
35
+ try {
36
+ const json = JSON.stringify(parsed);
37
+ if (json === undefined)
38
+ throw new Error("value is not JSON-serializable");
39
+ serialized = json;
40
+ }
41
+ catch (error) {
42
+ throw new Error(`variable "${name}" default is not JSON-serializable — ${error.message}`);
43
+ }
44
+ if (serialized.length > MAX_VARIABLE_JSON_LENGTH) {
45
+ throw new Error(`variable "${name}" default exceeds the 16KB serialized limit`);
46
+ }
47
+ const defaultJson = JSON.parse(serialized);
48
+ try {
49
+ v.parse(config.schema, defaultJson);
50
+ }
51
+ catch (error) {
52
+ throw new Error(`variable "${name}" default changes during JSON serialization — ${error.message}`);
53
+ }
54
+ const definition = {
55
+ schemaJson,
56
+ defaultJson,
57
+ ...(config.description !== undefined ? { description: config.description } : {}),
58
+ };
59
+ const existing = variableRegistry.get(name);
60
+ if (existing) {
61
+ if (stableJson(existing) !== stableJson(definition)) {
62
+ throw new Error(`variable "${name}" is already defined with a different configuration`);
63
+ }
64
+ }
65
+ else {
66
+ variableRegistry.set(name, definition);
67
+ }
68
+ return variableProxy(name);
69
+ }
70
+ export function variableDefinitionForCompile(name) {
71
+ return variableRegistry.get(name);
72
+ }
73
+ export function resetVariableRegistryForTests() {
74
+ variableRegistry.clear();
75
+ }
76
+ export function secret(name) {
77
+ if (!name)
78
+ throw new Error("secret() requires a name");
79
+ return { __rlSecret: name };
80
+ }
81
+ export function device(handle) {
82
+ if (!handle)
83
+ throw new Error("device() requires a handle");
84
+ return { __rlDeviceHandle: handle };
85
+ }
86
+ export function schedule(name, config) {
87
+ if (!name)
88
+ throw new Error("schedule() requires a name");
89
+ if (!config.cron.trim())
90
+ throw new Error("schedule() requires a cron expression");
91
+ return {
92
+ __rlTrigger: "schedule",
93
+ name,
94
+ cron: config.cron,
95
+ ...(config.timezone !== undefined ? { timezone: config.timezone } : {}),
96
+ };
97
+ }
98
+ export function defineEnvironment(config) {
99
+ return { __rlEnvironment: true, config };
100
+ }
101
+ export function mcpUrl(environmentOrName, maybeName) {
102
+ const name = typeof environmentOrName === "string" ? environmentOrName : maybeName;
103
+ if (!name)
104
+ throw new Error("mcpUrl() requires an MCP server name");
105
+ const key = mcpUrlEnvName(name);
106
+ const value = process.env[key];
107
+ if (!value)
108
+ throw new Error(`MCP server "${name}" is not available in this task`);
109
+ return value;
110
+ }