@reasonlayer/sdk 0.0.1

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 (117) 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/lint.d.ts +13 -0
  9. package/dist/bundler/lint.js +74 -0
  10. package/dist/bundler/node.d.ts +10 -0
  11. package/dist/bundler/node.js +55 -0
  12. package/dist/bundler/smoke.d.ts +12 -0
  13. package/dist/bundler/smoke.js +70 -0
  14. package/dist/bundler/worker.d.ts +31 -0
  15. package/dist/bundler/worker.js +214 -0
  16. package/dist/cli/args.d.ts +9 -0
  17. package/dist/cli/args.js +71 -0
  18. package/dist/cli/config.d.ts +38 -0
  19. package/dist/cli/config.js +94 -0
  20. package/dist/cli/convex.d.ts +9 -0
  21. package/dist/cli/convex.js +25 -0
  22. package/dist/cli/format.d.ts +11 -0
  23. package/dist/cli/format.js +140 -0
  24. package/dist/cli/index.d.ts +1 -0
  25. package/dist/cli/index.js +721 -0
  26. package/dist/cli/keychain.d.ts +21 -0
  27. package/dist/cli/keychain.js +100 -0
  28. package/dist/cli/login-browser.d.ts +22 -0
  29. package/dist/cli/login-browser.js +106 -0
  30. package/dist/cli/mcp.d.ts +3 -0
  31. package/dist/cli/mcp.js +36 -0
  32. package/dist/cli/operations.d.ts +106 -0
  33. package/dist/cli/operations.js +623 -0
  34. package/dist/cli/sdk-package.d.ts +18 -0
  35. package/dist/cli/sdk-package.js +45 -0
  36. package/dist/cli/storage-upload.d.ts +9 -0
  37. package/dist/cli/storage-upload.js +21 -0
  38. package/dist/cli/watcher-compile.d.ts +1 -0
  39. package/dist/cli/watcher-compile.js +20 -0
  40. package/dist/cli/watcher-process.d.ts +1 -0
  41. package/dist/cli/watcher-process.js +312 -0
  42. package/dist/cli/worker-host.d.ts +10 -0
  43. package/dist/cli/worker-host.js +120 -0
  44. package/dist/cli/workspace-files.d.ts +12 -0
  45. package/dist/cli/workspace-files.js +91 -0
  46. package/dist/cli/workspace-local.d.ts +27 -0
  47. package/dist/cli/workspace-local.js +310 -0
  48. package/dist/cli/workspace-session.d.ts +13 -0
  49. package/dist/cli/workspace-session.js +12 -0
  50. package/dist/compile.d.ts +27 -0
  51. package/dist/compile.js +834 -0
  52. package/dist/index.d.ts +10 -0
  53. package/dist/index.js +5 -0
  54. package/dist/schedule-validation.d.ts +1 -0
  55. package/dist/schedule-validation.js +16 -0
  56. package/dist/selector-schema.d.ts +26 -0
  57. package/dist/selector-schema.js +780 -0
  58. package/dist/selectors.d.ts +25 -0
  59. package/dist/selectors.js +99 -0
  60. package/dist/testkit.d.ts +32 -0
  61. package/dist/testkit.js +161 -0
  62. package/dist/types.d.ts +184 -0
  63. package/dist/types.js +110 -0
  64. package/node_modules/@reasonlayer/integrations/dist/catalog.d.ts +4937 -0
  65. package/node_modules/@reasonlayer/integrations/dist/catalog.js +20 -0
  66. package/node_modules/@reasonlayer/integrations/dist/generated/slack.d.ts +3014 -0
  67. package/node_modules/@reasonlayer/integrations/dist/generated/slack.js +3101 -0
  68. package/node_modules/@reasonlayer/integrations/dist/index.d.ts +2 -0
  69. package/node_modules/@reasonlayer/integrations/dist/index.js +1 -0
  70. package/node_modules/@reasonlayer/integrations/dist/internal/definitions.d.ts +44 -0
  71. package/node_modules/@reasonlayer/integrations/dist/internal/definitions.js +52 -0
  72. package/node_modules/@reasonlayer/integrations/dist/internal/transport.d.ts +7 -0
  73. package/node_modules/@reasonlayer/integrations/dist/internal/transport.js +48 -0
  74. package/node_modules/@reasonlayer/integrations/dist/testkit.d.ts +1 -0
  75. package/node_modules/@reasonlayer/integrations/dist/testkit.js +1 -0
  76. package/node_modules/@reasonlayer/integrations/package.json +26 -0
  77. package/node_modules/@reasonlayer/protocol/dist/dispatch.d.ts +10 -0
  78. package/node_modules/@reasonlayer/protocol/dist/dispatch.js +58 -0
  79. package/node_modules/@reasonlayer/protocol/dist/envelope.d.ts +9 -0
  80. package/node_modules/@reasonlayer/protocol/dist/envelope.js +1 -0
  81. package/node_modules/@reasonlayer/protocol/dist/environments.d.ts +7 -0
  82. package/node_modules/@reasonlayer/protocol/dist/environments.js +7 -0
  83. package/node_modules/@reasonlayer/protocol/dist/events.d.ts +313 -0
  84. package/node_modules/@reasonlayer/protocol/dist/events.js +20 -0
  85. package/node_modules/@reasonlayer/protocol/dist/index.d.ts +18 -0
  86. package/node_modules/@reasonlayer/protocol/dist/index.js +9 -0
  87. package/node_modules/@reasonlayer/protocol/dist/ir.d.ts +252 -0
  88. package/node_modules/@reasonlayer/protocol/dist/ir.js +116 -0
  89. package/node_modules/@reasonlayer/protocol/dist/permissions.d.ts +5 -0
  90. package/node_modules/@reasonlayer/protocol/dist/permissions.js +30 -0
  91. package/node_modules/@reasonlayer/protocol/dist/readmodels.d.ts +617 -0
  92. package/node_modules/@reasonlayer/protocol/dist/readmodels.js +36 -0
  93. package/node_modules/@reasonlayer/protocol/dist/runtime.d.ts +67 -0
  94. package/node_modules/@reasonlayer/protocol/dist/runtime.js +66 -0
  95. package/node_modules/@reasonlayer/protocol/dist/scheduling.d.ts +69 -0
  96. package/node_modules/@reasonlayer/protocol/dist/scheduling.js +126 -0
  97. package/node_modules/@reasonlayer/protocol/dist/selector.d.ts +23 -0
  98. package/node_modules/@reasonlayer/protocol/dist/selector.js +77 -0
  99. package/node_modules/@reasonlayer/protocol/dist/tasks.d.ts +69 -0
  100. package/node_modules/@reasonlayer/protocol/dist/tasks.js +6 -0
  101. package/node_modules/@reasonlayer/protocol/dist/validate.d.ts +6 -0
  102. package/node_modules/@reasonlayer/protocol/dist/validate.js +18 -0
  103. package/node_modules/@reasonlayer/protocol/package.json +21 -0
  104. package/node_modules/@reasonlayer/runner/dist/environment-materializer.d.ts +13 -0
  105. package/node_modules/@reasonlayer/runner/dist/environment-materializer.js +92 -0
  106. package/node_modules/@reasonlayer/runner/dist/flue-transcript.d.ts +17 -0
  107. package/node_modules/@reasonlayer/runner/dist/flue-transcript.js +182 -0
  108. package/node_modules/@reasonlayer/runner/dist/index.d.ts +184 -0
  109. package/node_modules/@reasonlayer/runner/dist/index.js +884 -0
  110. package/node_modules/@reasonlayer/runner/dist/mcp-supervisor.d.ts +15 -0
  111. package/node_modules/@reasonlayer/runner/dist/mcp-supervisor.js +142 -0
  112. package/node_modules/@reasonlayer/runner/dist/sandbox-env.d.ts +36 -0
  113. package/node_modules/@reasonlayer/runner/dist/sandbox-env.js +171 -0
  114. package/node_modules/@reasonlayer/runner/dist/task-child.d.ts +1 -0
  115. package/node_modules/@reasonlayer/runner/dist/task-child.js +72 -0
  116. package/node_modules/@reasonlayer/runner/package.json +21 -0
  117. package/package.json +65 -0
@@ -0,0 +1,55 @@
1
+ import * as esbuild from "esbuild";
2
+ async function buildNodeRunnerBundle(options) {
3
+ const { entryPath, outfile, sourcefile, startupLabel, exportName, compiledRef, errorPrefix, } = options;
4
+ const result = await esbuild.build({
5
+ stdin: {
6
+ contents: `
7
+ import definition from ${JSON.stringify(entryPath)};
8
+ import { compileWorkflow } from "@reasonlayer/sdk";
9
+ const compiled = compileWorkflow(definition, { omitEnvironments: true });
10
+ if (!compiled.ok) {
11
+ throw new Error(${JSON.stringify(startupLabel)} + JSON.stringify(compiled.errors));
12
+ }
13
+ export const ${exportName} = compiled.${compiledRef};
14
+ `,
15
+ resolveDir: new URL(".", `file://${entryPath}`).pathname,
16
+ sourcefile,
17
+ loader: "js",
18
+ },
19
+ bundle: true,
20
+ format: "esm",
21
+ platform: "node",
22
+ target: "node22",
23
+ treeShaking: true,
24
+ legalComments: "none",
25
+ external: ["@flue/runtime", "@flue/runtime/*"],
26
+ outfile,
27
+ logLevel: "silent",
28
+ write: true,
29
+ });
30
+ if (result.errors.length > 0) {
31
+ throw new Error(`${errorPrefix} failed: ${result.errors.map((e) => e.text).join("; ")}`);
32
+ }
33
+ }
34
+ /** Code bundle: re-exports compiled run functions for cloud/device runners. */
35
+ export async function buildStepsBundle(options) {
36
+ await buildNodeRunnerBundle({
37
+ ...options,
38
+ sourcefile: "rl-steps-entry.js",
39
+ startupLabel: "workflow failed to compile at runner start: ",
40
+ exportName: "STEP_RUNS",
41
+ compiledRef: "codeRefs",
42
+ errorPrefix: "steps bundle",
43
+ });
44
+ }
45
+ /** Agent bundle: re-exports compiled Flue defineAgent refs; the runner owns the runtime. */
46
+ export async function buildAgentsBundle(options) {
47
+ await buildNodeRunnerBundle({
48
+ ...options,
49
+ sourcefile: "rl-agents-entry.js",
50
+ startupLabel: "workflow failed to compile at agent runner start: ",
51
+ exportName: "AGENT_RUNS",
52
+ compiledRef: "agentRefs",
53
+ errorPrefix: "agent bundle",
54
+ });
55
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Build-time cold-start smoke test (spec §7.5, mechanism 3): evaluate the
3
+ * emitted Worker once in a subprocess with the Buffer global deleted (to
4
+ * match workerd) and a 10s guard against top-level-await hangs, then probe
5
+ * its manifest. Import-time Node use must fail the build, not every
6
+ * dispatch after deploy.
7
+ */
8
+ export interface SmokeResult {
9
+ workflowId: string;
10
+ steps: string[];
11
+ }
12
+ export declare function smokeTestWorker(workerPath: string): Promise<SmokeResult>;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Build-time cold-start smoke test (spec §7.5, mechanism 3): evaluate the
3
+ * emitted Worker once in a subprocess with the Buffer global deleted (to
4
+ * match workerd) and a 10s guard against top-level-await hangs, then probe
5
+ * its manifest. Import-time Node use must fail the build, not every
6
+ * dispatch after deploy.
7
+ */
8
+ import { execFile } from "node:child_process";
9
+ import { pathToFileURL } from "node:url";
10
+ const CHILD_SCRIPT = `
11
+ // Buffer is deleted for MODULE EVALUATION only — that matches workerd's
12
+ // missing global at cold start. It is restored before the probe because
13
+ // Node's own Request/Response (undici) needs it.
14
+ const savedBuffer = globalThis.Buffer;
15
+ delete globalThis.Buffer;
16
+ const workerUrl = process.env.RL_WORKER_URL;
17
+ const timer = setTimeout(() => {
18
+ console.error("worker module evaluation timed out after 10s — top-level await that never settles?");
19
+ process.exit(3);
20
+ }, 10_000);
21
+ try {
22
+ const mod = await import(workerUrl);
23
+ clearTimeout(timer);
24
+ globalThis.Buffer = savedBuffer;
25
+ const handler = mod.default && mod.default.fetch;
26
+ if (typeof handler !== "function") {
27
+ console.error("worker has no default { fetch } handler");
28
+ process.exit(4);
29
+ }
30
+ const res = await handler(
31
+ new Request("http://rl-smoke/", {
32
+ method: "POST",
33
+ headers: { "content-type": "application/json" },
34
+ body: JSON.stringify({ probe: "manifest" }),
35
+ }),
36
+ );
37
+ const body = await res.json();
38
+ if (!body || !body.manifest) {
39
+ console.error("manifest probe returned no manifest: " + JSON.stringify(body));
40
+ process.exit(5);
41
+ }
42
+ console.log(JSON.stringify(body.manifest));
43
+ process.exit(0);
44
+ } catch (err) {
45
+ clearTimeout(timer);
46
+ console.error(String((err && err.stack) || err));
47
+ process.exit(2);
48
+ }
49
+ `;
50
+ export async function smokeTestWorker(workerPath) {
51
+ return new Promise((resolve, reject) => {
52
+ const child = execFile(process.execPath, ["--input-type=module", "-e", CHILD_SCRIPT], {
53
+ env: { ...process.env, RL_WORKER_URL: pathToFileURL(workerPath).href },
54
+ timeout: 15_000,
55
+ }, (error, stdout, stderr) => {
56
+ if (error) {
57
+ reject(new Error(`worker cold-start smoke test failed — the Worker would crash at cold start in production.\n${stderr.trim()}`));
58
+ return;
59
+ }
60
+ try {
61
+ const manifest = JSON.parse(stdout.trim());
62
+ resolve(manifest);
63
+ }
64
+ catch {
65
+ reject(new Error(`smoke test produced unparseable output: ${stdout}`));
66
+ }
67
+ });
68
+ child.on("error", reject);
69
+ });
70
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The Workers-target build (spec §7.5): a self-contained ESM user Worker.
3
+ * Node builtins are stubbed to empty modules (mechanism 1) so the whole
4
+ * workflow module bundles even when device/sandbox-only steps use Node APIs
5
+ * — that code is inert behind entrypoints the Worker never calls. A
6
+ * process.env getter shim (banner) makes `process.env.FOO` read the
7
+ * per-invocation env.
8
+ */
9
+ import type { Plugin } from "esbuild";
10
+ export declare function nodeBuiltinStubPlugin(): Plugin;
11
+ export declare function flueRuntimeWorkerStubPlugin(): Plugin;
12
+ export interface WorkerBuildResult {
13
+ outfile: string;
14
+ bytes: number;
15
+ }
16
+ export declare function buildWorkerBundle(options: {
17
+ entryPath: string;
18
+ workflowId: string;
19
+ workerStepIds: string[];
20
+ outfile: string;
21
+ }): Promise<WorkerBuildResult>;
22
+ /** The Node-target steps bundle for sandbox/device runners (spec §7.1). */
23
+ export declare function buildStepsBundle(options: {
24
+ entryPath: string;
25
+ outfile: string;
26
+ }): Promise<void>;
27
+ /** Agent bundle: re-exports compiled Flue defineAgent refs; the runner owns the runtime. */
28
+ export declare function buildAgentsBundle(options: {
29
+ entryPath: string;
30
+ outfile: string;
31
+ }): Promise<void>;
@@ -0,0 +1,214 @@
1
+ /**
2
+ * The Workers-target build (spec §7.5): a self-contained ESM user Worker.
3
+ * Node builtins are stubbed to empty modules (mechanism 1) so the whole
4
+ * workflow module bundles even when device/sandbox-only steps use Node APIs
5
+ * — that code is inert behind entrypoints the Worker never calls. A
6
+ * process.env getter shim (banner) makes `process.env.FOO` read the
7
+ * per-invocation env.
8
+ */
9
+ import { builtinModules } from "node:module";
10
+ import * as esbuild from "esbuild";
11
+ const BUILTINS = new Set([
12
+ ...builtinModules,
13
+ ...builtinModules.map((m) => `node:${m}`),
14
+ ]);
15
+ export function nodeBuiltinStubPlugin() {
16
+ return {
17
+ name: "rl-node-builtin-stubs",
18
+ setup(build) {
19
+ build.onResolve({ filter: /.*/ }, (args) => {
20
+ if (BUILTINS.has(args.path)) {
21
+ return { path: args.path, namespace: "rl-node-stub" };
22
+ }
23
+ return null;
24
+ });
25
+ build.onLoad({ filter: /.*/, namespace: "rl-node-stub" }, () => ({
26
+ contents: "module.exports = {};",
27
+ loader: "js",
28
+ }));
29
+ },
30
+ };
31
+ }
32
+ export function flueRuntimeWorkerStubPlugin() {
33
+ return {
34
+ name: "rl-flue-runtime-worker-stub",
35
+ setup(build) {
36
+ build.onResolve({ filter: /^@flue\/runtime(?:\/.*)?$/ }, (args) => ({
37
+ path: args.path,
38
+ namespace: "rl-flue-runtime-stub",
39
+ }));
40
+ build.onLoad({ filter: /.*/, namespace: "rl-flue-runtime-stub" }, () => ({
41
+ contents: `
42
+ const unavailable = (name) => () => {
43
+ throw new Error("@flue/runtime " + name + " is not available in function-hosted Reasonlayer code steps");
44
+ };
45
+
46
+ export function defineAgent(initialize) {
47
+ return { __flueAgentDefinition: true, initialize };
48
+ }
49
+ export function createAgent(initialize) {
50
+ return defineAgent(initialize);
51
+ }
52
+ export function registerProvider() {}
53
+ export function registerApiProvider() {}
54
+ export function defineTool(config) {
55
+ return config;
56
+ }
57
+ export function defineSkill(config) {
58
+ return config;
59
+ }
60
+
61
+ export const bash = unavailable("bash");
62
+ export const connectMcpServer = unavailable("connectMcpServer");
63
+ export const createSandboxSessionEnv = unavailable("createSandboxSessionEnv");
64
+ export const dispatch = unavailable("dispatch");
65
+ export const getRun = unavailable("getRun");
66
+ export const instrument = unavailable("instrument");
67
+ export const invoke = unavailable("invoke");
68
+ export const listAgents = unavailable("listAgents");
69
+ export const listRuns = unavailable("listRuns");
70
+ export const observe = () => () => {};
71
+ `,
72
+ loader: "js",
73
+ }));
74
+ },
75
+ };
76
+ }
77
+ /**
78
+ * The per-invocation env shim: `process.env` resolves to the env posted with
79
+ * the request, reset after the call (spec §7.2 — secrets are never stored as
80
+ * Worker secrets).
81
+ */
82
+ const PROCESS_ENV_BANNER = `const process = { get env() { return globalThis.__RL_ENV ?? {}; } };`;
83
+ function workerEntrySource(entryPath, workflowId, workerStepIds) {
84
+ return `
85
+ import definition from ${JSON.stringify(entryPath)};
86
+ import { compileWorkflow } from "@reasonlayer/sdk";
87
+
88
+ const compiled = compileWorkflow(definition, { omitEnvironments: true });
89
+ if (!compiled.ok) {
90
+ throw new Error("workflow failed to compile at Worker cold start: " + JSON.stringify(compiled.errors));
91
+ }
92
+ const WORKER_STEPS = new Set(${JSON.stringify(workerStepIds)});
93
+ const MANIFEST = { workflowId: ${JSON.stringify(workflowId)}, steps: ${JSON.stringify(workerStepIds)} };
94
+
95
+ const json = (status, body) =>
96
+ new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
97
+
98
+ export default {
99
+ async fetch(request) {
100
+ if (request.method !== "POST") return json(405, { error: "POST only" });
101
+ let body;
102
+ try {
103
+ body = await request.json();
104
+ } catch {
105
+ return json(400, { error: "invalid JSON body" });
106
+ }
107
+ if (body && body.probe === "manifest") return json(200, { manifest: MANIFEST });
108
+
109
+ const { stepId, input, env } = body ?? {};
110
+ if (!WORKER_STEPS.has(stepId)) {
111
+ return json(404, {
112
+ status: "failed",
113
+ error: { message: "unknown Reasonlayer code step: " + stepId },
114
+ });
115
+ }
116
+ const run = compiled.codeRefs[stepId];
117
+ globalThis.__RL_ENV = env ?? {};
118
+ try {
119
+ const output = await run(input);
120
+ return json(200, { status: "succeeded", output });
121
+ } catch (err) {
122
+ return json(200, {
123
+ status: "failed",
124
+ error: { message: String(err && err.message ? err.message : err), stack: err && err.stack },
125
+ });
126
+ } finally {
127
+ globalThis.__RL_ENV = {};
128
+ }
129
+ },
130
+ };
131
+ `;
132
+ }
133
+ export async function buildWorkerBundle(options) {
134
+ const { entryPath, workflowId, workerStepIds, outfile } = options;
135
+ const result = await esbuild.build({
136
+ stdin: {
137
+ contents: workerEntrySource(entryPath, workflowId, workerStepIds),
138
+ resolveDir: new URL(".", `file://${entryPath}`).pathname,
139
+ sourcefile: "rl-worker-entry.js",
140
+ loader: "js",
141
+ },
142
+ bundle: true,
143
+ format: "esm",
144
+ platform: "browser",
145
+ target: "es2022",
146
+ treeShaking: true,
147
+ legalComments: "none",
148
+ banner: { js: PROCESS_ENV_BANNER },
149
+ plugins: [flueRuntimeWorkerStubPlugin(), nodeBuiltinStubPlugin()],
150
+ outfile,
151
+ logLevel: "silent",
152
+ write: true,
153
+ });
154
+ if (result.errors.length > 0) {
155
+ throw new Error(`worker bundle failed: ${result.errors.map((e) => e.text).join("; ")}`);
156
+ }
157
+ const { statSync } = await import("node:fs");
158
+ return { outfile, bytes: statSync(outfile).size };
159
+ }
160
+ /** The Node-target steps bundle for sandbox/device runners (spec §7.1). */
161
+ async function buildNodeRunnerBundle(options) {
162
+ const { entryPath, outfile, sourcefile, startupLabel, exportName, compiledRef, errorPrefix, } = options;
163
+ const result = await esbuild.build({
164
+ stdin: {
165
+ contents: `
166
+ import definition from ${JSON.stringify(entryPath)};
167
+ import { compileWorkflow } from "@reasonlayer/sdk";
168
+ const compiled = compileWorkflow(definition, { omitEnvironments: true });
169
+ if (!compiled.ok) {
170
+ throw new Error(${JSON.stringify(startupLabel)} + JSON.stringify(compiled.errors));
171
+ }
172
+ export const ${exportName} = compiled.${compiledRef};
173
+ `,
174
+ resolveDir: new URL(".", `file://${entryPath}`).pathname,
175
+ sourcefile,
176
+ loader: "js",
177
+ },
178
+ bundle: true,
179
+ format: "esm",
180
+ platform: "node",
181
+ target: "node22",
182
+ treeShaking: true,
183
+ legalComments: "none",
184
+ external: ["@flue/runtime", "@flue/runtime/*"],
185
+ outfile,
186
+ logLevel: "silent",
187
+ write: true,
188
+ });
189
+ if (result.errors.length > 0) {
190
+ throw new Error(`${errorPrefix} failed: ${result.errors.map((e) => e.text).join("; ")}`);
191
+ }
192
+ }
193
+ /** The Node-target steps bundle for sandbox/device runners (spec §7.1). */
194
+ export async function buildStepsBundle(options) {
195
+ await buildNodeRunnerBundle({
196
+ ...options,
197
+ sourcefile: "rl-steps-entry.js",
198
+ startupLabel: "workflow failed to compile at runner start: ",
199
+ exportName: "STEP_RUNS",
200
+ compiledRef: "codeRefs",
201
+ errorPrefix: "steps bundle",
202
+ });
203
+ }
204
+ /** Agent bundle: re-exports compiled Flue defineAgent refs; the runner owns the runtime. */
205
+ export async function buildAgentsBundle(options) {
206
+ await buildNodeRunnerBundle({
207
+ ...options,
208
+ sourcefile: "rl-agents-entry.js",
209
+ startupLabel: "workflow failed to compile at agent runner start: ",
210
+ exportName: "AGENT_RUNS",
211
+ compiledRef: "agentRefs",
212
+ errorPrefix: "agent bundle",
213
+ });
214
+ }
@@ -0,0 +1,9 @@
1
+ export interface ParsedCliArgs {
2
+ command: string | undefined;
3
+ positionals: string[];
4
+ flags: Record<string, string | boolean>;
5
+ }
6
+ export declare function parseCliArgs(argv: readonly string[]): ParsedCliArgs;
7
+ export declare function hasFlag(parsed: ParsedCliArgs, name: string): boolean;
8
+ export declare function stringFlag(parsed: ParsedCliArgs, name: string): string | undefined;
9
+ export declare function numberFlag(parsed: ParsedCliArgs, name: string): number | undefined;
@@ -0,0 +1,71 @@
1
+ const BOOLEAN_FLAGS = new Set([
2
+ "bootstrap",
3
+ "disable",
4
+ "enable",
5
+ "help",
6
+ "json",
7
+ "local",
8
+ "no-wait",
9
+ "once",
10
+ "value-stdin",
11
+ "version",
12
+ "watch",
13
+ "wait",
14
+ ]);
15
+ export function parseCliArgs(argv) {
16
+ let command;
17
+ const positionals = [];
18
+ const flags = {};
19
+ for (let i = 0; i < argv.length; i += 1) {
20
+ const arg = argv[i];
21
+ if (!command && !arg.startsWith("-")) {
22
+ command = arg;
23
+ continue;
24
+ }
25
+ if (arg === "--") {
26
+ positionals.push(...argv.slice(i + 1));
27
+ break;
28
+ }
29
+ if (!arg.startsWith("--")) {
30
+ positionals.push(arg);
31
+ continue;
32
+ }
33
+ const raw = arg.slice(2);
34
+ const eq = raw.indexOf("=");
35
+ if (eq !== -1) {
36
+ flags[raw.slice(0, eq)] = raw.slice(eq + 1);
37
+ continue;
38
+ }
39
+ if (BOOLEAN_FLAGS.has(raw)) {
40
+ flags[raw] = true;
41
+ continue;
42
+ }
43
+ const next = argv[i + 1];
44
+ if (next !== undefined && !next.startsWith("--")) {
45
+ flags[raw] = next;
46
+ i += 1;
47
+ }
48
+ else {
49
+ flags[raw] = true;
50
+ }
51
+ }
52
+ return { command, positionals, flags };
53
+ }
54
+ export function hasFlag(parsed, name) {
55
+ return parsed.flags[name] === true;
56
+ }
57
+ export function stringFlag(parsed, name) {
58
+ const value = parsed.flags[name];
59
+ if (typeof value === "string")
60
+ return value;
61
+ return undefined;
62
+ }
63
+ export function numberFlag(parsed, name) {
64
+ const value = stringFlag(parsed, name);
65
+ if (value === undefined)
66
+ return undefined;
67
+ const n = Number(value);
68
+ if (!Number.isFinite(n))
69
+ throw new Error(`--${name} must be a number`);
70
+ return n;
71
+ }
@@ -0,0 +1,38 @@
1
+ export declare const TOKEN_ONBOARDING_HINT: string;
2
+ /** What operations consume: a deployment URL plus a bearer token. */
3
+ export interface RlConfig {
4
+ convexUrl: string;
5
+ token: string;
6
+ }
7
+ /** Non-secret account metadata persisted for user-facing diagnostics. */
8
+ export interface RlAccount {
9
+ email?: string;
10
+ orgId?: string;
11
+ }
12
+ /**
13
+ * Global (per-user) config lives in `$HOME/.rl/config.json`. `RL_HOME`
14
+ * overrides the directory — production override and test isolation seam.
15
+ */
16
+ export declare function globalConfigPath(): string;
17
+ export declare function resolvedConvexUrl(): string;
18
+ export declare function resolvedTargetLabel(): "production" | "dev override";
19
+ export declare function loadConfig(options?: {
20
+ optional?: false;
21
+ }): Promise<RlConfig>;
22
+ export declare function loadConfig(options: {
23
+ optional: true;
24
+ }): Promise<RlConfig | undefined>;
25
+ export interface SavedLogin {
26
+ configPath: string;
27
+ }
28
+ /**
29
+ * Persist a successful login: token to the OS keychain, non-secret account
30
+ * metadata to the global config file. There is deliberately no plaintext-file
31
+ * fallback (spec §11) — if the keychain is unavailable we fail with guidance to
32
+ * use RL_TOKEN with a scoped `rl_pt_` token, which is the headless/CI path.
33
+ */
34
+ export declare function saveLogin(convexUrl: string, token: string, account?: RlAccount): Promise<SavedLogin>;
35
+ /** Remove the stored token for the currently resolved deployment. */
36
+ export declare function clearLogin(convexUrl?: string): Promise<{
37
+ convexUrl: string;
38
+ }>;
@@ -0,0 +1,94 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { PRODUCTION_CONVEX_URL } from "@reasonlayer/protocol";
5
+ import * as keychain from "./keychain.js";
6
+ import { KeychainAccessError, KeychainUnavailableError } from "./keychain.js";
7
+ export const TOKEN_ONBOARDING_HINT = "Create a platform token in the Reasonlayer console under Capabilities > Tokens, then " +
8
+ 'run "rl login --token <token>". Inside the repo, run "pnpm rl login --token <token>" ' +
9
+ "to log in to the local dev deployment.";
10
+ /**
11
+ * Global (per-user) config lives in `$HOME/.rl/config.json`. `RL_HOME`
12
+ * overrides the directory — production override and test isolation seam.
13
+ */
14
+ export function globalConfigPath() {
15
+ const home = process.env["RL_HOME"];
16
+ return home ? join(resolve(home), "config.json") : join(homedir(), ".rl", "config.json");
17
+ }
18
+ async function writeConfigFile(path, file) {
19
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
20
+ await writeFile(path, `${JSON.stringify(file, null, 2)}\n`, { mode: 0o600 });
21
+ }
22
+ function isKeychainError(err) {
23
+ return err instanceof KeychainUnavailableError || err instanceof KeychainAccessError;
24
+ }
25
+ export function resolvedConvexUrl() {
26
+ return process.env["RL_CONVEX_URL"] ?? PRODUCTION_CONVEX_URL;
27
+ }
28
+ export function resolvedTargetLabel() {
29
+ return process.env["RL_CONVEX_URL"] === undefined ? "production" : "dev override";
30
+ }
31
+ export async function loadConfig(options = {}) {
32
+ const convexUrl = resolvedConvexUrl();
33
+ const envToken = process.env["RL_TOKEN"];
34
+ if (envToken !== undefined)
35
+ return { convexUrl, token: envToken };
36
+ let token;
37
+ let keychainError;
38
+ try {
39
+ token = (await keychain.getToken(convexUrl)) ?? undefined;
40
+ }
41
+ catch (err) {
42
+ if (err instanceof KeychainAccessError)
43
+ keychainError = err;
44
+ else if (!(err instanceof KeychainUnavailableError))
45
+ throw err;
46
+ }
47
+ if (token !== undefined)
48
+ return { convexUrl, token };
49
+ if (options.optional)
50
+ return undefined;
51
+ // A keychain that holds the token but refused to read it is a distinct
52
+ // failure from "no login" — surface it rather than a misleading prompt.
53
+ if (keychainError) {
54
+ throw new Error(`${keychainError.message}. Your keychain may be locked or the access prompt was denied — ` +
55
+ "re-run and approve it, or set RL_TOKEN with a scoped token.");
56
+ }
57
+ throw notLoggedIn();
58
+ }
59
+ function notLoggedIn() {
60
+ return new Error(`not logged in: ${TOKEN_ONBOARDING_HINT}`);
61
+ }
62
+ /**
63
+ * Persist a successful login: token to the OS keychain, non-secret account
64
+ * metadata to the global config file. There is deliberately no plaintext-file
65
+ * fallback (spec §11) — if the keychain is unavailable we fail with guidance to
66
+ * use RL_TOKEN with a scoped `rl_pt_` token, which is the headless/CI path.
67
+ */
68
+ export async function saveLogin(convexUrl, token, account = {}) {
69
+ try {
70
+ await keychain.setToken(convexUrl, token);
71
+ }
72
+ catch (err) {
73
+ if (isKeychainError(err)) {
74
+ throw new Error(`${err.message}. Unlock your keychain and retry, or for headless/CI use ` +
75
+ "RL_TOKEN with a scoped token instead of an interactive login.");
76
+ }
77
+ throw err;
78
+ }
79
+ const path = globalConfigPath();
80
+ const hasAccount = account.email !== undefined || account.orgId !== undefined;
81
+ await writeConfigFile(path, hasAccount ? { account } : {});
82
+ return { configPath: path };
83
+ }
84
+ /** Remove the stored token for the currently resolved deployment. */
85
+ export async function clearLogin(convexUrl = resolvedConvexUrl()) {
86
+ try {
87
+ await keychain.deleteToken(convexUrl);
88
+ }
89
+ catch (err) {
90
+ if (!isKeychainError(err))
91
+ throw err;
92
+ }
93
+ return { convexUrl };
94
+ }
@@ -0,0 +1,9 @@
1
+ import type { RlConfig } from "./config.js";
2
+ export declare class RlConvexClient {
3
+ readonly config: RlConfig;
4
+ private readonly client;
5
+ constructor(config: RlConfig);
6
+ query<T>(name: string, args: Record<string, unknown>): Promise<T>;
7
+ mutation<T>(name: string, args: Record<string, unknown>): Promise<T>;
8
+ action<T>(name: string, args: Record<string, unknown>): Promise<T>;
9
+ }
@@ -0,0 +1,25 @@
1
+ import { ConvexHttpClient } from "convex/browser";
2
+ import { makeFunctionReference } from "convex/server";
3
+ function fn(kind, name) {
4
+ return makeFunctionReference(name);
5
+ }
6
+ export class RlConvexClient {
7
+ config;
8
+ client;
9
+ constructor(config) {
10
+ this.config = config;
11
+ this.client = new ConvexHttpClient(config.convexUrl, {
12
+ logger: false,
13
+ skipConvexDeploymentUrlCheck: true,
14
+ });
15
+ }
16
+ query(name, args) {
17
+ return this.client.query(fn("query", name), args);
18
+ }
19
+ mutation(name, args) {
20
+ return this.client.mutation(fn("mutation", name), args, { skipQueue: true });
21
+ }
22
+ action(name, args) {
23
+ return this.client.action(fn("action", name), args);
24
+ }
25
+ }
@@ -0,0 +1,11 @@
1
+ export declare function serializeCliValue(value: unknown, key?: string): unknown;
2
+ export declare function jsonText(value: unknown): string;
3
+ export declare function parseVariableValue(raw: string): unknown;
4
+ export declare function formatVariableList(value: unknown): string;
5
+ export declare function formatCompileErrors(result: {
6
+ errors: {
7
+ stepId?: string;
8
+ message: string;
9
+ }[];
10
+ }): string;
11
+ export declare function formatInspect(value: unknown): string;