orchajs 0.20.3 → 0.22.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 (107) hide show
  1. package/README.md +103 -0
  2. package/dist/amarsia/analytics.d.ts +21 -0
  3. package/dist/amarsia/analytics.js +457 -0
  4. package/dist/amarsia/endpoint.d.ts +1 -0
  5. package/dist/amarsia/endpoint.js +8 -0
  6. package/dist/amarsia/sync.js +1 -4
  7. package/dist/bin.d.ts +2 -0
  8. package/dist/bin.js +13 -0
  9. package/dist/browser.d.ts +2 -0
  10. package/dist/browser.js +12 -0
  11. package/dist/cli.js +35 -9
  12. package/dist/compiler/build-project.d.ts +1 -0
  13. package/dist/compiler/build-project.js +75 -8
  14. package/dist/compiler/compile.d.ts +1 -1
  15. package/dist/compiler/compile.js +11 -9
  16. package/dist/errors.d.ts +5 -0
  17. package/dist/errors.js +102 -0
  18. package/dist/file-content.js +42 -6
  19. package/dist/index.d.ts +1 -5
  20. package/dist/index.js +1 -2
  21. package/dist/integrations/esbuild.js +5 -2
  22. package/dist/integrations/expo.d.ts +1 -0
  23. package/dist/integrations/expo.js +1 -0
  24. package/dist/integrations/metro.d.ts +15 -0
  25. package/dist/integrations/metro.js +25 -0
  26. package/dist/integrations/next.d.ts +23 -0
  27. package/dist/integrations/next.js +53 -0
  28. package/dist/integrations/runtime-build.d.ts +4 -0
  29. package/dist/integrations/runtime-build.js +32 -0
  30. package/dist/integrations/vite.d.ts +23 -0
  31. package/dist/integrations/vite.js +32 -0
  32. package/dist/integrations/webpack.d.ts +24 -0
  33. package/dist/integrations/webpack.js +21 -0
  34. package/dist/orcha.js +17 -8
  35. package/dist/playground/server.js +57 -7
  36. package/dist/project-loader.js +3 -0
  37. package/dist/providers/browser.d.ts +2 -0
  38. package/dist/providers/browser.js +20 -0
  39. package/dist/react-native.d.ts +2 -0
  40. package/dist/react-native.js +12 -0
  41. package/dist/runtime/actions/browser-native.d.ts +3 -0
  42. package/dist/runtime/actions/browser-native.js +28 -0
  43. package/dist/runtime/actions/execute.d.ts +7 -0
  44. package/dist/runtime/actions/execute.js +9 -2
  45. package/dist/runtime/agent.d.ts +1 -0
  46. package/dist/runtime/agent.js +38 -10
  47. package/dist/runtime/compiler-hook.d.ts +5 -0
  48. package/dist/runtime/compiler-hook.js +8 -0
  49. package/dist/runtime/create-orcha.d.ts +6 -1
  50. package/dist/runtime/create-orcha.js +35 -21
  51. package/dist/runtime/platform-browser.d.ts +2 -0
  52. package/dist/runtime/platform-browser.js +15 -0
  53. package/dist/runtime/platform-node.d.ts +2 -0
  54. package/dist/runtime/platform-node.js +31 -0
  55. package/dist/runtime/platform-react-native.d.ts +2 -0
  56. package/dist/runtime/platform-react-native.js +15 -0
  57. package/dist/runtime/platform.d.ts +15 -0
  58. package/dist/runtime/platform.js +1 -0
  59. package/dist/runtime/random-id.d.ts +1 -0
  60. package/dist/runtime/random-id.js +26 -0
  61. package/dist/runtime-entry.d.ts +5 -0
  62. package/dist/runtime-entry.js +2 -0
  63. package/dist/storage/browser-indexeddb.d.ts +7 -16
  64. package/dist/storage/browser-indexeddb.js +102 -19
  65. package/dist/storage/react-native-jsonl.d.ts +7 -16
  66. package/dist/storage/react-native-jsonl.js +65 -19
  67. package/dist/types.d.ts +54 -1
  68. package/dist-cjs/amarsia/analytics.js +447 -0
  69. package/dist-cjs/amarsia/endpoint.js +32 -0
  70. package/dist-cjs/amarsia/sync.js +2 -5
  71. package/dist-cjs/browser.js +48 -0
  72. package/dist-cjs/compiler/build-project.js +97 -8
  73. package/dist-cjs/compiler/compile.js +17 -9
  74. package/dist-cjs/errors.js +92 -2
  75. package/dist-cjs/file-content.js +42 -7
  76. package/dist-cjs/index.js +4 -9
  77. package/dist-cjs/integrations/esbuild.js +6 -2
  78. package/dist-cjs/integrations/expo.js +29 -0
  79. package/dist-cjs/integrations/metro.js +51 -0
  80. package/dist-cjs/integrations/next.js +75 -0
  81. package/dist-cjs/integrations/runtime-build.js +70 -0
  82. package/dist-cjs/integrations/vite.js +57 -0
  83. package/dist-cjs/integrations/webpack.js +51 -0
  84. package/dist-cjs/orcha.js +17 -12
  85. package/dist-cjs/playground/server.js +62 -9
  86. package/dist-cjs/project-loader.js +10 -0
  87. package/dist-cjs/providers/browser.js +61 -0
  88. package/dist-cjs/react-native.js +48 -0
  89. package/dist-cjs/runtime/actions/browser-native.js +68 -0
  90. package/dist-cjs/runtime/actions/execute.js +12 -2
  91. package/dist-cjs/runtime/agent.js +37 -14
  92. package/dist-cjs/runtime/compiler-hook.js +37 -0
  93. package/dist-cjs/runtime/create-orcha.js +34 -23
  94. package/dist-cjs/runtime/platform-browser.js +48 -0
  95. package/dist-cjs/runtime/platform-node.js +59 -0
  96. package/dist-cjs/runtime/platform-react-native.js +45 -0
  97. package/dist-cjs/runtime/platform.js +17 -0
  98. package/dist-cjs/runtime/random-id.js +55 -0
  99. package/dist-cjs/runtime-entry.js +34 -0
  100. package/dist-cjs/storage/browser-indexeddb.js +102 -5
  101. package/dist-cjs/storage/react-native-jsonl.js +73 -5
  102. package/dist-cjs/types/react-native-async-storage.d.js +2 -0
  103. package/package.json +69 -9
  104. package/dist/playground/public/app.css +0 -1
  105. package/dist/playground/public/app.js +0 -31
  106. package/dist/playground/public/index.html +0 -15
  107. package/dist/playground/public/orcha-logo.svg +0 -4
@@ -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
- import { OrchaError } from "../errors.js";
1
+ import { describeProviderError, isRetryableProviderConnectionError, 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) {
@@ -617,7 +620,8 @@ export class RuntimeAgent {
617
620
  }
618
621
  providerTools.push(...this.#subagentToolDefinitions());
619
622
  try {
620
- response = await this.#generateProviderResponse(this.#manifest.provider, provider, {
623
+ const signal = this.#sessionControls.get(sessionId)?.controller.signal;
624
+ response = await withProviderConnectionRetry(() => this.#generateProviderResponse(this.#manifest.provider, provider, {
621
625
  model: this.#manifest.model,
622
626
  region: this.#manifest.region,
623
627
  maxTokens: this.#manifest.maxTokens,
@@ -631,8 +635,8 @@ export class RuntimeAgent {
631
635
  streamedOutput = output;
632
636
  publishOutput?.(output);
633
637
  },
634
- signal: this.#sessionControls.get(sessionId)?.controller.signal,
635
- });
638
+ signal,
639
+ }), signal);
636
640
  }
637
641
  catch (error) {
638
642
  if (this.#sessionControls.get(sessionId)?.pauseRequested) {
@@ -662,7 +666,16 @@ export class RuntimeAgent {
662
666
  if (error instanceof OrchaError) {
663
667
  throw error;
664
668
  }
665
- throw new OrchaError("provider_error", error instanceof Error ? error.message : String(error), { retryable: true, cause: error });
669
+ const providerError = describeProviderError(error);
670
+ throw new OrchaError("provider_error", providerError.message, {
671
+ retryable: true,
672
+ cause: error,
673
+ details: {
674
+ provider: this.#manifest.provider,
675
+ model: this.#manifest.model,
676
+ ...providerError.details,
677
+ },
678
+ });
666
679
  }
667
680
  const modelDurationMs = Math.round(performance.now() - modelStartedAt);
668
681
  const usage = aggregateUsage(previousEvents, writer.run, response.usage);
@@ -1836,7 +1849,7 @@ function normalizeMetadata(metadata) {
1836
1849
  }
1837
1850
  return normalized;
1838
1851
  }
1839
- function createSessionId(prefix) {
1852
+ function createSessionId(prefix, randomUUID) {
1840
1853
  const utcTimestamp = new Date()
1841
1854
  .toISOString()
1842
1855
  .replace(/\.\d{3}Z$/, "")
@@ -2606,6 +2619,21 @@ function findLast(events, predicate) {
2606
2619
  }
2607
2620
  return undefined;
2608
2621
  }
2622
+ async function withProviderConnectionRetry(operation, signal) {
2623
+ try {
2624
+ return await operation();
2625
+ }
2626
+ catch (error) {
2627
+ if (signal?.aborted ||
2628
+ !isRetryableProviderConnectionError(error)) {
2629
+ throw error;
2630
+ }
2631
+ await new Promise((resolve) => setTimeout(resolve, 250));
2632
+ if (signal?.aborted)
2633
+ throw error;
2634
+ return operation();
2635
+ }
2636
+ }
2609
2637
  function failure(sessionId, code, message, options = {}) {
2610
2638
  const retryable = options.retryable ??
2611
2639
  (code === "session_busy" ||
@@ -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;