orchajs 0.20.3 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +103 -0
  2. package/dist/bin.d.ts +2 -0
  3. package/dist/bin.js +13 -0
  4. package/dist/browser.d.ts +2 -0
  5. package/dist/browser.js +12 -0
  6. package/dist/cli.js +35 -9
  7. package/dist/compiler/build-project.d.ts +1 -0
  8. package/dist/compiler/build-project.js +75 -8
  9. package/dist/compiler/compile.d.ts +1 -1
  10. package/dist/compiler/compile.js +11 -9
  11. package/dist/file-content.js +42 -6
  12. package/dist/index.d.ts +1 -5
  13. package/dist/index.js +1 -2
  14. package/dist/integrations/esbuild.js +5 -2
  15. package/dist/integrations/expo.d.ts +1 -0
  16. package/dist/integrations/expo.js +1 -0
  17. package/dist/integrations/metro.d.ts +15 -0
  18. package/dist/integrations/metro.js +25 -0
  19. package/dist/integrations/next.d.ts +23 -0
  20. package/dist/integrations/next.js +53 -0
  21. package/dist/integrations/runtime-build.d.ts +4 -0
  22. package/dist/integrations/runtime-build.js +32 -0
  23. package/dist/integrations/vite.d.ts +23 -0
  24. package/dist/integrations/vite.js +32 -0
  25. package/dist/integrations/webpack.d.ts +24 -0
  26. package/dist/integrations/webpack.js +21 -0
  27. package/dist/orcha.js +17 -8
  28. package/dist/playground/server.js +57 -7
  29. package/dist/project-loader.js +3 -0
  30. package/dist/providers/browser.d.ts +2 -0
  31. package/dist/providers/browser.js +20 -0
  32. package/dist/react-native.d.ts +2 -0
  33. package/dist/react-native.js +12 -0
  34. package/dist/runtime/actions/browser-native.d.ts +3 -0
  35. package/dist/runtime/actions/browser-native.js +28 -0
  36. package/dist/runtime/actions/execute.d.ts +7 -0
  37. package/dist/runtime/actions/execute.js +9 -2
  38. package/dist/runtime/agent.d.ts +1 -0
  39. package/dist/runtime/agent.js +8 -5
  40. package/dist/runtime/compiler-hook.d.ts +5 -0
  41. package/dist/runtime/compiler-hook.js +8 -0
  42. package/dist/runtime/create-orcha.d.ts +2 -1
  43. package/dist/runtime/create-orcha.js +15 -19
  44. package/dist/runtime/platform-browser.d.ts +2 -0
  45. package/dist/runtime/platform-browser.js +15 -0
  46. package/dist/runtime/platform-node.d.ts +2 -0
  47. package/dist/runtime/platform-node.js +31 -0
  48. package/dist/runtime/platform-react-native.d.ts +2 -0
  49. package/dist/runtime/platform-react-native.js +15 -0
  50. package/dist/runtime/platform.d.ts +15 -0
  51. package/dist/runtime/platform.js +1 -0
  52. package/dist/runtime/random-id.d.ts +1 -0
  53. package/dist/runtime/random-id.js +26 -0
  54. package/dist/runtime-entry.d.ts +5 -0
  55. package/dist/runtime-entry.js +2 -0
  56. package/dist/storage/browser-indexeddb.d.ts +7 -16
  57. package/dist/storage/browser-indexeddb.js +102 -19
  58. package/dist/storage/react-native-jsonl.d.ts +7 -16
  59. package/dist/storage/react-native-jsonl.js +65 -19
  60. package/dist/types.d.ts +3 -1
  61. package/dist-cjs/browser.js +48 -0
  62. package/dist-cjs/compiler/build-project.js +97 -8
  63. package/dist-cjs/compiler/compile.js +17 -9
  64. package/dist-cjs/file-content.js +42 -7
  65. package/dist-cjs/index.js +4 -9
  66. package/dist-cjs/integrations/esbuild.js +6 -2
  67. package/dist-cjs/integrations/expo.js +29 -0
  68. package/dist-cjs/integrations/metro.js +51 -0
  69. package/dist-cjs/integrations/next.js +75 -0
  70. package/dist-cjs/integrations/runtime-build.js +70 -0
  71. package/dist-cjs/integrations/vite.js +57 -0
  72. package/dist-cjs/integrations/webpack.js +51 -0
  73. package/dist-cjs/orcha.js +17 -12
  74. package/dist-cjs/playground/server.js +62 -9
  75. package/dist-cjs/project-loader.js +10 -0
  76. package/dist-cjs/providers/browser.js +61 -0
  77. package/dist-cjs/react-native.js +48 -0
  78. package/dist-cjs/runtime/actions/browser-native.js +68 -0
  79. package/dist-cjs/runtime/actions/execute.js +12 -2
  80. package/dist-cjs/runtime/agent.js +8 -6
  81. package/dist-cjs/runtime/compiler-hook.js +37 -0
  82. package/dist-cjs/runtime/create-orcha.js +18 -21
  83. package/dist-cjs/runtime/platform-browser.js +48 -0
  84. package/dist-cjs/runtime/platform-node.js +59 -0
  85. package/dist-cjs/runtime/platform-react-native.js +45 -0
  86. package/dist-cjs/runtime/platform.js +17 -0
  87. package/dist-cjs/runtime/random-id.js +55 -0
  88. package/dist-cjs/runtime-entry.js +34 -0
  89. package/dist-cjs/storage/browser-indexeddb.js +102 -5
  90. package/dist-cjs/storage/react-native-jsonl.js +73 -5
  91. package/dist-cjs/types/react-native-async-storage.d.js +2 -0
  92. package/package.json +69 -9
  93. package/dist/playground/public/app.css +0 -1
  94. package/dist/playground/public/app.js +0 -31
  95. package/dist/playground/public/index.html +0 -15
  96. package/dist/playground/public/orcha-logo.svg +0 -4
@@ -0,0 +1,25 @@
1
+ import { resolve } from "node:path";
2
+ import { generatedBundlePath, queueRuntimeBuild, watchRuntimeTargets, } from "./runtime-build.js";
3
+ export async function withOrchaMetro(configuration, options = {}) {
4
+ const projectRoot = resolve(options.projectRoot ?? process.cwd());
5
+ await queueRuntimeBuild(projectRoot, "react-native");
6
+ if (process.env.NODE_ENV !== "production") {
7
+ watchRuntimeTargets(projectRoot, ["react-native"]);
8
+ }
9
+ const existingResolver = configuration.resolver?.resolveRequest;
10
+ return {
11
+ ...configuration,
12
+ resolver: {
13
+ ...configuration.resolver,
14
+ resolveRequest(context, moduleName, platform) {
15
+ const requestedModule = moduleName === "orchajs"
16
+ ? generatedBundlePath(projectRoot, "react-native")
17
+ : moduleName;
18
+ if (existingResolver) {
19
+ return existingResolver(context, requestedModule, platform);
20
+ }
21
+ return context.resolveRequest(context, requestedModule, platform);
22
+ },
23
+ },
24
+ };
25
+ }
@@ -0,0 +1,23 @@
1
+ export interface OrchaNextOptions {
2
+ projectRoot?: string;
3
+ }
4
+ interface NextWebpackContext {
5
+ isServer: boolean;
6
+ nextRuntime?: string;
7
+ }
8
+ interface WebpackConfiguration {
9
+ plugins?: unknown[];
10
+ resolve?: {
11
+ alias?: Record<string, unknown>;
12
+ };
13
+ }
14
+ interface NextConfiguration {
15
+ turbopack?: {
16
+ resolveAlias?: Record<string, unknown>;
17
+ [key: string]: unknown;
18
+ };
19
+ webpack?: (configuration: WebpackConfiguration, context: NextWebpackContext) => WebpackConfiguration;
20
+ [key: string]: unknown;
21
+ }
22
+ export declare function withOrcha<T extends NextConfiguration>(configuration?: T, options?: OrchaNextOptions): Promise<T>;
23
+ export {};
@@ -0,0 +1,53 @@
1
+ import { resolve } from "node:path";
2
+ import { generatedBundlePath, queueRuntimeBuild, watchRuntimeTargets, } from "./runtime-build.js";
3
+ import { OrchaWebpackPlugin } from "./webpack.js";
4
+ export async function withOrcha(configuration = {}, options = {}) {
5
+ const projectRoot = resolve(options.projectRoot ?? process.cwd());
6
+ await queueRuntimeBuild(projectRoot, "browser");
7
+ await queueRuntimeBuild(projectRoot, "node");
8
+ if (process.env.NODE_ENV !== "production") {
9
+ watchRuntimeTargets(projectRoot, ["browser", "node"]);
10
+ }
11
+ const existingWebpack = configuration.webpack;
12
+ return {
13
+ ...configuration,
14
+ turbopack: {
15
+ ...configuration.turbopack,
16
+ resolveAlias: {
17
+ ...configuration.turbopack?.resolveAlias,
18
+ orchajs: {
19
+ browser: generatedBundlePath(projectRoot, "browser"),
20
+ },
21
+ },
22
+ },
23
+ webpack(webpackConfiguration, context) {
24
+ const target = nextTarget(context);
25
+ if (target === "node") {
26
+ return existingWebpack
27
+ ? existingWebpack(webpackConfiguration, context)
28
+ : webpackConfiguration;
29
+ }
30
+ const plugin = new OrchaWebpackPlugin({
31
+ projectRoot,
32
+ target,
33
+ });
34
+ webpackConfiguration.resolve ??= {};
35
+ webpackConfiguration.resolve.alias = {
36
+ ...webpackConfiguration.resolve.alias,
37
+ orchajs$: plugin.bundlePath,
38
+ };
39
+ webpackConfiguration.plugins = [
40
+ ...(webpackConfiguration.plugins ?? []),
41
+ plugin,
42
+ ];
43
+ return existingWebpack
44
+ ? existingWebpack(webpackConfiguration, context)
45
+ : webpackConfiguration;
46
+ },
47
+ };
48
+ }
49
+ function nextTarget(context) {
50
+ return context.isServer && context.nextRuntime !== "edge"
51
+ ? "node"
52
+ : "browser";
53
+ }
@@ -0,0 +1,4 @@
1
+ export type RuntimeBuildTarget = "node" | "browser" | "react-native";
2
+ export declare function generatedBundlePath(projectRoot: string, target: RuntimeBuildTarget): string;
3
+ export declare function queueRuntimeBuild(projectRoot: string, target: RuntimeBuildTarget): Promise<void>;
4
+ export declare function watchRuntimeTargets(projectRoot: string, targets: RuntimeBuildTarget[]): void;
@@ -0,0 +1,32 @@
1
+ import { resolve } from "node:path";
2
+ import { watch } from "chokidar";
3
+ import { buildProject } from "../compiler/build-project.js";
4
+ import { loadProjectEnvironment } from "../env.js";
5
+ let buildQueue = Promise.resolve();
6
+ const watchedTargets = new Set();
7
+ export function generatedBundlePath(projectRoot, target) {
8
+ const fileName = target === "node" ? "bundle.js" : `bundle.${target}.js`;
9
+ return resolve(projectRoot, ".orcha/dist", fileName);
10
+ }
11
+ export function queueRuntimeBuild(projectRoot, target) {
12
+ const build = buildQueue.then(async () => {
13
+ loadProjectEnvironment(projectRoot);
14
+ await buildProject({ projectRoot, target });
15
+ });
16
+ buildQueue = build.catch(() => undefined);
17
+ return build;
18
+ }
19
+ export function watchRuntimeTargets(projectRoot, targets) {
20
+ const key = `${projectRoot}:${targets.join(",")}`;
21
+ if (watchedTargets.has(key)) {
22
+ return;
23
+ }
24
+ watchedTargets.add(key);
25
+ let timer;
26
+ watch(resolve(projectRoot, "orcha"), { ignoreInitial: true }).on("all", () => {
27
+ clearTimeout(timer);
28
+ timer = setTimeout(() => {
29
+ void targets.reduce((pending, target) => pending.then(() => queueRuntimeBuild(projectRoot, target)), Promise.resolve());
30
+ }, 75);
31
+ });
32
+ }
@@ -0,0 +1,23 @@
1
+ export interface OrchaVitePluginOptions {
2
+ projectRoot?: string;
3
+ }
4
+ export declare function orchaVitePlugin(options?: OrchaVitePluginOptions): {
5
+ name: string;
6
+ enforce: "pre";
7
+ configResolved(config: {
8
+ root: string;
9
+ }): void;
10
+ buildStart(): Promise<void>;
11
+ configureServer(server: {
12
+ watcher: {
13
+ add(path: string): void;
14
+ on(event: "all", listener: (_event: string, path: string) => void): void;
15
+ };
16
+ ws: {
17
+ send(message: {
18
+ type: "full-reload";
19
+ }): void;
20
+ };
21
+ }): void;
22
+ resolveId(source: string): string | undefined;
23
+ };
@@ -0,0 +1,32 @@
1
+ import { resolve, sep } from "node:path";
2
+ import { generatedBundlePath, queueRuntimeBuild, } from "./runtime-build.js";
3
+ export function orchaVitePlugin(options = {}) {
4
+ let projectRoot = resolve(options.projectRoot ?? process.cwd());
5
+ return {
6
+ name: "orchajs",
7
+ enforce: "pre",
8
+ configResolved(config) {
9
+ projectRoot = resolve(options.projectRoot ?? config.root);
10
+ },
11
+ async buildStart() {
12
+ await queueRuntimeBuild(projectRoot, "browser");
13
+ },
14
+ configureServer(server) {
15
+ const registryDirectory = resolve(projectRoot, "orcha");
16
+ server.watcher.add(registryDirectory);
17
+ server.watcher.on("all", (_event, path) => {
18
+ if (path === registryDirectory ||
19
+ path.startsWith(`${registryDirectory}${sep}`)) {
20
+ void queueRuntimeBuild(projectRoot, "browser").then(() => {
21
+ server.ws.send({ type: "full-reload" });
22
+ });
23
+ }
24
+ });
25
+ },
26
+ resolveId(source) {
27
+ return source === "orchajs"
28
+ ? generatedBundlePath(projectRoot, "browser")
29
+ : undefined;
30
+ },
31
+ };
32
+ }
@@ -0,0 +1,24 @@
1
+ import { type RuntimeBuildTarget } from "./runtime-build.js";
2
+ export interface OrchaWebpackPluginOptions {
3
+ projectRoot?: string;
4
+ target?: RuntimeBuildTarget;
5
+ }
6
+ interface WebpackCompiler {
7
+ hooks: {
8
+ beforeCompile: {
9
+ tapPromise(name: string, callback: () => Promise<void>): void;
10
+ };
11
+ afterCompile: {
12
+ tap(name: string, callback: (compilation: {
13
+ contextDependencies: Set<string>;
14
+ }) => void): void;
15
+ };
16
+ };
17
+ }
18
+ export declare class OrchaWebpackPlugin {
19
+ #private;
20
+ constructor(options?: OrchaWebpackPluginOptions);
21
+ get bundlePath(): string;
22
+ apply(compiler: WebpackCompiler): void;
23
+ }
24
+ export {};
@@ -0,0 +1,21 @@
1
+ import { resolve } from "node:path";
2
+ import { generatedBundlePath, queueRuntimeBuild, } from "./runtime-build.js";
3
+ export class OrchaWebpackPlugin {
4
+ #projectRoot;
5
+ #target;
6
+ constructor(options = {}) {
7
+ this.#projectRoot = resolve(options.projectRoot ?? process.cwd());
8
+ this.#target = options.target ?? "browser";
9
+ }
10
+ get bundlePath() {
11
+ return generatedBundlePath(this.#projectRoot, this.#target);
12
+ }
13
+ apply(compiler) {
14
+ compiler.hooks.beforeCompile.tapPromise("orchajs", async () => {
15
+ await queueRuntimeBuild(this.#projectRoot, this.#target);
16
+ });
17
+ compiler.hooks.afterCompile.tap("orchajs", (compilation) => {
18
+ compilation.contextDependencies.add(resolve(this.#projectRoot, "orcha"));
19
+ });
20
+ }
21
+ }
package/dist/orcha.js CHANGED
@@ -1,9 +1,12 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { resolve } from "node:path";
3
- import { compileRegistry } from "./compiler/compile.js";
4
3
  import { generateProviderResponse } from "./providers/index.js";
5
- import { setSandboxRuntimeLoader } from "./runtime/actions/execute.js";
4
+ import { setNativeRuntimeLoader, setSandboxRuntimeLoader, } from "./runtime/actions/execute.js";
5
+ import { executeNativeAction } from "./runtime/actions/native.js";
6
+ import { getRegistryCompiler } from "./runtime/compiler-hook.js";
6
7
  import { createOrcha } from "./runtime/create-orcha.js";
8
+ import { nodeRuntimePlatform } from "./runtime/platform-node.js";
9
+ setNativeRuntimeLoader(async () => ({ executeNativeAction }));
7
10
  setSandboxRuntimeLoader(async () => {
8
11
  const modulePath = "./runtime/actions/sandbox.js";
9
12
  return import(modulePath);
@@ -12,13 +15,16 @@ export const orcha = createOrcha((configuration) => {
12
15
  const projectRoot = resolve(configuration.root ??
13
16
  process.env.ORCHA_PROJECT_ROOT ??
14
17
  process.cwd());
15
- if (process.env.ORCHA_COMPILING !== "1" &&
16
- isPrecompiledRuntime()) {
18
+ const compiler = getRegistryCompiler();
19
+ if (process.env.ORCHA_COMPILING === "1" && compiler) {
20
+ return compiler(configuration, projectRoot);
21
+ }
22
+ if (isPrecompiledRuntime() ||
23
+ existsSync(compiledManifestPath(projectRoot))) {
17
24
  return loadCompiledManifest(projectRoot, configuration);
18
25
  }
19
- const registryRoot = resolve(projectRoot, "orcha");
20
- return compileRegistry(configuration.agents, registryRoot, configuration.actions?.runtime ?? "native");
21
- }, generateProviderResponse);
26
+ throw new Error('Orcha agents must be compiled before runtime initialization. Run "npx orcha dev" during development or "npx orcha build" before starting the application.');
27
+ }, generateProviderResponse, nodeRuntimePlatform);
22
28
  function isPrecompiledRuntime() {
23
29
  return (process.env.ORCHA_USE_BUILD === "1" ||
24
30
  process.env.NODE_ENV === "production" ||
@@ -26,7 +32,7 @@ function isPrecompiledRuntime() {
26
32
  process.env.AWS_EXECUTION_ENV?.startsWith("AWS_Lambda_") === true);
27
33
  }
28
34
  function loadCompiledManifest(projectRoot, configuration) {
29
- const manifestPath = resolve(projectRoot, ".orcha/dist/manifest.json");
35
+ const manifestPath = compiledManifestPath(projectRoot);
30
36
  if (!existsSync(manifestPath)) {
31
37
  throw new Error(`ORCHA_PRODUCTION_BUNDLE_MISSING: "${manifestPath}" was not found. Run "npx orcha build" before packaging, include ".orcha/dist" in the deployment, or configure the Orcha build integration.`);
32
38
  }
@@ -56,3 +62,6 @@ function loadCompiledManifest(projectRoot, configuration) {
56
62
  }
57
63
  return bundle;
58
64
  }
65
+ function compiledManifestPath(projectRoot) {
66
+ return resolve(projectRoot, ".orcha/dist/manifest.json");
67
+ }
@@ -1,11 +1,12 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { randomBytes } from "node:crypto";
3
3
  import { existsSync } from "node:fs";
4
- import { readFile } from "node:fs/promises";
5
- import { dirname, extname, isAbsolute, relative, resolve } from "node:path";
6
- import { fileURLToPath } from "node:url";
4
+ import { copyFile, mkdir, readFile, writeFile, } from "node:fs/promises";
5
+ import { createRequire } from "node:module";
6
+ import { extname, isAbsolute, relative, resolve } from "node:path";
7
7
  import { createServer, } from "node:http";
8
8
  import { watch } from "chokidar";
9
+ import { build } from "esbuild";
9
10
  import { orcha } from "../orcha.js";
10
11
  import { loadProject } from "../project-loader.js";
11
12
  import { listTests, runTests } from "../testing.js";
@@ -20,6 +21,7 @@ export async function startPlayground(options = {}) {
20
21
  const mutationToken = randomBytes(32).toString("base64url");
21
22
  const allowedHosts = playgroundHosts(host, port);
22
23
  await loadProject(projectRoot);
24
+ const publicRoot = await buildPlaygroundAssets(projectRoot);
23
25
  const projectClients = new Set();
24
26
  const server = createServer(async (request, response) => {
25
27
  try {
@@ -32,6 +34,7 @@ export async function startPlayground(options = {}) {
32
34
  projectClients,
33
35
  mutationToken,
34
36
  allowedHosts,
37
+ publicRoot,
35
38
  });
36
39
  }
37
40
  catch (error) {
@@ -312,7 +315,7 @@ async function routeRequest(context) {
312
315
  return;
313
316
  }
314
317
  if (method === "GET") {
315
- await serveAsset(response, url.pathname);
318
+ await serveAsset(response, url.pathname, context.publicRoot);
316
319
  return;
317
320
  }
318
321
  sendJson(response, 404, { error: "Not found." });
@@ -444,8 +447,7 @@ async function readAllEventPages(read) {
444
447
  }
445
448
  return pages.flat();
446
449
  }
447
- async function serveAsset(response, pathname) {
448
- const publicRoot = resolve(dirname(fileURLToPath(import.meta.url)), "public");
450
+ async function serveAsset(response, pathname, publicRoot) {
449
451
  const requested = pathname === "/" ? "index.html" : pathname.slice(1);
450
452
  const path = resolve(publicRoot, requested);
451
453
  const relativePath = relative(publicRoot, path);
@@ -455,7 +457,7 @@ async function serveAsset(response, pathname) {
455
457
  const indexPath = resolve(publicRoot, "index.html");
456
458
  if (!existsSync(indexPath)) {
457
459
  sendJson(response, 503, {
458
- error: "Playground assets are missing. Rebuild orchajs.",
460
+ error: "Playground assets are missing. Restart the Orcha playground.",
459
461
  });
460
462
  return;
461
463
  }
@@ -472,6 +474,54 @@ async function serveAsset(response, pathname) {
472
474
  });
473
475
  response.end(await readFile(path));
474
476
  }
477
+ async function buildPlaygroundAssets(projectRoot) {
478
+ const require = createRequire(import.meta.url);
479
+ let entryPath;
480
+ let logoPath;
481
+ try {
482
+ entryPath = require.resolve("@orchajs/playground-ui/mount");
483
+ logoPath = require.resolve("@orchajs/playground-ui/orcha-logo.svg");
484
+ }
485
+ catch (error) {
486
+ throw new Error('The playground requires the optional "@orchajs/playground-ui" package. Install it as a development dependency.', { cause: error });
487
+ }
488
+ const publicRoot = resolve(projectRoot, ".orcha/playground");
489
+ await mkdir(publicRoot, { recursive: true });
490
+ await Promise.all([
491
+ build({
492
+ entryPoints: [entryPath],
493
+ outfile: resolve(publicRoot, "app.js"),
494
+ bundle: true,
495
+ format: "esm",
496
+ platform: "browser",
497
+ target: ["chrome110", "firefox110", "safari16"],
498
+ minify: true,
499
+ sourcemap: false,
500
+ legalComments: "none",
501
+ define: {
502
+ "process.env.NODE_ENV": JSON.stringify("production"),
503
+ },
504
+ }),
505
+ copyFile(logoPath, resolve(publicRoot, "orcha-logo.svg")),
506
+ writeFile(resolve(publicRoot, "index.html"), `<!doctype html>
507
+ <html lang="en">
508
+ <head>
509
+ <meta charset="UTF-8" />
510
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
511
+ <meta name="color-scheme" content="light" />
512
+ <link rel="icon" href="/orcha-logo.svg" type="image/svg+xml" />
513
+ <title>Orcha Playground</title>
514
+ <link rel="stylesheet" href="/app.css" />
515
+ </head>
516
+ <body>
517
+ <div id="root"></div>
518
+ <script type="module" src="/app.js"></script>
519
+ </body>
520
+ </html>
521
+ `, "utf8"),
522
+ ]);
523
+ return publicRoot;
524
+ }
475
525
  function contentType(path) {
476
526
  switch (extname(path)) {
477
527
  case ".html":
@@ -3,9 +3,12 @@ import { mkdir, rm } from "node:fs/promises";
3
3
  import { resolve } from "node:path";
4
4
  import { pathToFileURL } from "node:url";
5
5
  import { build as bundleEntry } from "esbuild";
6
+ import { compileRegistry } from "./compiler/compile.js";
6
7
  import { loadProjectEnvironment } from "./env.js";
7
8
  import { orcha } from "./orcha.js";
9
+ import { setRegistryCompiler } from "./runtime/compiler-hook.js";
8
10
  export async function loadProject(projectRoot) {
11
+ setRegistryCompiler((configuration, compilerProjectRoot) => compileRegistry(configuration.agents, resolve(compilerProjectRoot, "orcha"), configuration.actions?.runtime ?? "native", "node"));
9
12
  loadProjectEnvironment(projectRoot);
10
13
  const registryPath = resolve(projectRoot, "orcha/index.ts");
11
14
  if (!existsSync(registryPath)) {
@@ -0,0 +1,2 @@
1
+ import type { ProviderResponseGenerator } from "./types.js";
2
+ export declare const generateBrowserProviderResponse: ProviderResponseGenerator;
@@ -0,0 +1,20 @@
1
+ import { OrchaError } from "../errors.js";
2
+ const loadedProviders = new Map();
3
+ const loaders = {
4
+ anthropic: () => import("./anthropic.js").then((module) => module.anthropicProvider),
5
+ deepseek: () => import("./deepseek.js").then((module) => module.deepSeekProvider),
6
+ googlegenai: () => import("./google-genai.js").then((module) => module.googleGenAIProvider),
7
+ openai: () => import("./openai.js").then((module) => module.openAIProvider),
8
+ };
9
+ export const generateBrowserProviderResponse = async (name, configuration, request) => {
10
+ const loader = loaders[name];
11
+ if (!loader) {
12
+ throw new OrchaError("provider_error", `Provider "${name}" is not available in browser or React Native runtimes.`);
13
+ }
14
+ let provider = loadedProviders.get(name);
15
+ if (!provider) {
16
+ provider = loader();
17
+ loadedProviders.set(name, provider);
18
+ }
19
+ return (await provider).generate(configuration, request);
20
+ };
@@ -0,0 +1,2 @@
1
+ export declare const orcha: import("./runtime-entry.js").OrchaClient;
2
+ export * from "./runtime-entry.js";
@@ -0,0 +1,12 @@
1
+ import { generateBrowserProviderResponse } from "./providers/browser.js";
2
+ import { setNativeRuntimeLoader } from "./runtime/actions/execute.js";
3
+ import { createOrcha } from "./runtime/create-orcha.js";
4
+ import { reactNativeRuntimePlatform } from "./runtime/platform-react-native.js";
5
+ setNativeRuntimeLoader(async () => {
6
+ const modulePath = "./runtime/actions/browser-native.js";
7
+ return import(modulePath);
8
+ });
9
+ export const orcha = createOrcha(() => {
10
+ throw new Error("The React Native runtime requires a precompiled Orcha bundle. Configure the Orcha Metro integration.");
11
+ }, generateBrowserProviderResponse, reactNativeRuntimePlatform);
12
+ export * from "./runtime-entry.js";
@@ -0,0 +1,3 @@
1
+ import type { CompiledActionManifest } from "../../types.js";
2
+ import type { LocalActionContext } from "./context.js";
3
+ export declare function executeNativeAction(action: CompiledActionManifest, parameters: Record<string, unknown>, context: LocalActionContext): Promise<unknown>;
@@ -0,0 +1,28 @@
1
+ export async function executeNativeAction(action, parameters, context) {
2
+ if (!action.source) {
3
+ throw new Error(`Action "${action.name}" has no compiled source.`);
4
+ }
5
+ if (/\brequire\s*\(/.test(action.source)) {
6
+ throw new Error(`Browser action "${action.name}" contains a Node.js require() call. Rebuild it for the browser target.`);
7
+ }
8
+ const loadAction = new Function(`"use strict";\n${action.source}\nreturn __orchaActionModule.default;`);
9
+ const executable = loadAction();
10
+ if (typeof executable !== "function") {
11
+ throw new Error(`Action "${action.name}" index.js must export a default function.`);
12
+ }
13
+ const timeoutMs = action.timeoutMs ?? 10_000;
14
+ let timeout;
15
+ try {
16
+ return await Promise.race([
17
+ Promise.resolve(executable(parameters, context)),
18
+ new Promise((_resolve, reject) => {
19
+ timeout = setTimeout(() => reject(new Error(`Action timed out after ${timeoutMs}ms.`)), timeoutMs);
20
+ }),
21
+ ]);
22
+ }
23
+ finally {
24
+ if (timeout) {
25
+ clearTimeout(timeout);
26
+ }
27
+ }
28
+ }
@@ -1,8 +1,15 @@
1
1
  import type { CompiledActionManifest, LocalActionRuntimeConfiguration, SessionMetadata } from "../../types.js";
2
+ import { type LocalActionContext } from "./context.js";
2
3
  type SandboxRuntime = typeof import("./sandbox.js");
3
4
  type SandboxRuntimeLoader = () => Promise<SandboxRuntime>;
5
+ interface NativeRuntime {
6
+ executeNativeAction(action: CompiledActionManifest, parameters: Record<string, unknown>, context: LocalActionContext): Promise<unknown>;
7
+ }
8
+ type NativeRuntimeLoader = () => Promise<NativeRuntime>;
4
9
  /** @internal Supplies the statically bundled sandbox in production builds. */
5
10
  export declare function setSandboxRuntimeLoader(loader: SandboxRuntimeLoader): void;
11
+ /** @internal Supplies the platform-specific native action executor. */
12
+ export declare function setNativeRuntimeLoader(loader: NativeRuntimeLoader): void;
6
13
  export declare function executeLocalAction(options: {
7
14
  action: CompiledActionManifest;
8
15
  parameters: Record<string, unknown>;
@@ -1,5 +1,7 @@
1
- import { createLocalActionContext } from "./context.js";
2
- import { executeNativeAction } from "./native.js";
1
+ import { createLocalActionContext, } from "./context.js";
2
+ let loadConfiguredNativeRuntime = async () => {
3
+ throw new Error("The native action runtime was not included in this Orcha build.");
4
+ };
3
5
  let loadConfiguredSandboxRuntime = async () => {
4
6
  throw new Error("The QuickJS sandbox runtime was not included in this Orcha build.");
5
7
  };
@@ -7,9 +9,14 @@ let loadConfiguredSandboxRuntime = async () => {
7
9
  export function setSandboxRuntimeLoader(loader) {
8
10
  loadConfiguredSandboxRuntime = loader;
9
11
  }
12
+ /** @internal Supplies the platform-specific native action executor. */
13
+ export function setNativeRuntimeLoader(loader) {
14
+ loadConfiguredNativeRuntime = loader;
15
+ }
10
16
  export async function executeLocalAction(options) {
11
17
  const context = createLocalActionContext(options);
12
18
  if (options.configuration.runtime === "native") {
19
+ const { executeNativeAction } = await loadConfiguredNativeRuntime();
13
20
  return executeNativeAction(options.action, options.parameters, context);
14
21
  }
15
22
  if (process.env.ORCHA_INCLUDE_SANDBOX !== "0") {
@@ -17,6 +17,7 @@ export declare class RuntimeAgent implements AgentRuntime {
17
17
  delegatedOnly?: boolean;
18
18
  sessionIdPrefix?: string;
19
19
  projectRoot?: string;
20
+ randomUUID?: () => string;
20
21
  });
21
22
  get agent(): string;
22
23
  get clientTools(): CompiledActionManifest[];
@@ -1,10 +1,10 @@
1
- import { randomUUID } from "node:crypto";
2
1
  import { OrchaError } from "../errors.js";
3
2
  import { normalizeLocalFile, normalizeUrlContent, } from "../file-content.js";
4
3
  import { messagesFromEvents, normalizePersistedToolResults, SessionEventWriter, } from "./session-events.js";
5
4
  import { validateStructuredValue } from "./structured-output.js";
6
5
  import { executeLocalAction } from "./actions/execute.js";
7
6
  import { createExecution, } from "./execution.js";
7
+ import { portableRandomUUID } from "./random-id.js";
8
8
  const LOAD_SKILL_TOOL_NAME = "load_skill";
9
9
  const RUN_AGENT_TOOL_NAME = "run_agent";
10
10
  const RESUME_AGENT_TOOL_NAME = "resume_agent";
@@ -27,6 +27,7 @@ export class RuntimeAgent {
27
27
  #agentKey;
28
28
  #sessionIdPrefix;
29
29
  #projectRoot;
30
+ #randomUUID;
30
31
  #evaluationTasks = new Map();
31
32
  #sessionIdleWaiters = new Map();
32
33
  constructor(options) {
@@ -40,7 +41,8 @@ export class RuntimeAgent {
40
41
  this.#delegatedOnly = options.delegatedOnly ?? false;
41
42
  this.#agentKey = options.manifest.key ?? options.manifest.name;
42
43
  this.#sessionIdPrefix = options.sessionIdPrefix ?? "ses_";
43
- this.#projectRoot = options.projectRoot ?? process.cwd();
44
+ this.#projectRoot = options.projectRoot ?? ".";
45
+ this.#randomUUID = options.randomUUID ?? portableRandomUUID;
44
46
  }
45
47
  get agent() {
46
48
  return this.#agentKey;
@@ -65,7 +67,7 @@ export class RuntimeAgent {
65
67
  return this.#run(input);
66
68
  }
67
69
  createDelegatedSessionId() {
68
- return createSessionId(this.#sessionIdPrefix);
70
+ return createSessionId(this.#sessionIdPrefix, this.#randomUUID);
69
71
  }
70
72
  runAsChild(sessionId, input, lineage) {
71
73
  const normalized = typeof input === "string" ? { content: input } : input;
@@ -76,7 +78,8 @@ export class RuntimeAgent {
76
78
  }
77
79
  #run(input, lineage, requestedSessionId) {
78
80
  const normalized = typeof input === "string" ? { content: input } : input;
79
- const sessionId = requestedSessionId ?? createSessionId(this.#sessionIdPrefix);
81
+ const sessionId = requestedSessionId ??
82
+ createSessionId(this.#sessionIdPrefix, this.#randomUUID);
80
83
  if (typeof normalized === "object" &&
81
84
  normalized !== null &&
82
85
  "sessionId" in normalized) {
@@ -1836,7 +1839,7 @@ function normalizeMetadata(metadata) {
1836
1839
  }
1837
1840
  return normalized;
1838
1841
  }
1839
- function createSessionId(prefix) {
1842
+ function createSessionId(prefix, randomUUID) {
1840
1843
  const utcTimestamp = new Date()
1841
1844
  .toISOString()
1842
1845
  .replace(/\.\d{3}Z$/, "")
@@ -0,0 +1,5 @@
1
+ import type { CompiledBundle, OrchaInitConfiguration } from "../types.js";
2
+ export type RegistryCompiler = (configuration: OrchaInitConfiguration, projectRoot: string) => CompiledBundle;
3
+ /** @internal Installed by Node development tooling, never by runtime bundles. */
4
+ export declare function setRegistryCompiler(compiler: RegistryCompiler): void;
5
+ export declare function getRegistryCompiler(): RegistryCompiler | undefined;
@@ -0,0 +1,8 @@
1
+ let registryCompiler;
2
+ /** @internal Installed by Node development tooling, never by runtime bundles. */
3
+ export function setRegistryCompiler(compiler) {
4
+ registryCompiler = compiler;
5
+ }
6
+ export function getRegistryCompiler() {
7
+ return registryCompiler;
8
+ }
@@ -1,4 +1,5 @@
1
1
  import type { ProviderResponseGenerator } from "../providers/types.js";
2
+ import type { RuntimePlatform } from "./platform.js";
2
3
  import type { AgentRuntime, CompiledBundle, OrchaInitConfiguration } from "../types.js";
3
4
  export interface Orcha {
4
5
  init(configuration: OrchaInitConfiguration): OrchaClient;
@@ -8,4 +9,4 @@ export interface Orcha {
8
9
  }
9
10
  export type OrchaClient = Orcha & Record<string, AgentRuntime>;
10
11
  export type BundleResolver = (configuration: OrchaInitConfiguration) => CompiledBundle;
11
- export declare function createOrcha(resolveBundle: BundleResolver, generateProviderResponse: ProviderResponseGenerator): OrchaClient;
12
+ export declare function createOrcha(resolveBundle: BundleResolver, generateProviderResponse: ProviderResponseGenerator, platform: RuntimePlatform): OrchaClient;