orchajs 0.20.2 → 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 (99) hide show
  1. package/README.md +129 -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-agents-template.d.ts +1 -1
  7. package/dist/cli-agents-template.js +22 -0
  8. package/dist/cli.js +35 -9
  9. package/dist/compiler/build-project.d.ts +1 -0
  10. package/dist/compiler/build-project.js +75 -8
  11. package/dist/compiler/compile.d.ts +1 -1
  12. package/dist/compiler/compile.js +11 -9
  13. package/dist/file-content.js +42 -6
  14. package/dist/index.d.ts +1 -5
  15. package/dist/index.js +1 -2
  16. package/dist/integrations/esbuild.js +5 -2
  17. package/dist/integrations/expo.d.ts +1 -0
  18. package/dist/integrations/expo.js +1 -0
  19. package/dist/integrations/metro.d.ts +15 -0
  20. package/dist/integrations/metro.js +25 -0
  21. package/dist/integrations/next.d.ts +23 -0
  22. package/dist/integrations/next.js +53 -0
  23. package/dist/integrations/runtime-build.d.ts +4 -0
  24. package/dist/integrations/runtime-build.js +32 -0
  25. package/dist/integrations/vite.d.ts +23 -0
  26. package/dist/integrations/vite.js +32 -0
  27. package/dist/integrations/webpack.d.ts +24 -0
  28. package/dist/integrations/webpack.js +21 -0
  29. package/dist/orcha.js +17 -8
  30. package/dist/playground/server.js +57 -7
  31. package/dist/project-loader.js +3 -0
  32. package/dist/providers/browser.d.ts +2 -0
  33. package/dist/providers/browser.js +20 -0
  34. package/dist/react-native.d.ts +2 -0
  35. package/dist/react-native.js +12 -0
  36. package/dist/runtime/actions/browser-native.d.ts +3 -0
  37. package/dist/runtime/actions/browser-native.js +28 -0
  38. package/dist/runtime/actions/execute.d.ts +7 -0
  39. package/dist/runtime/actions/execute.js +9 -2
  40. package/dist/runtime/agent.d.ts +1 -0
  41. package/dist/runtime/agent.js +8 -5
  42. package/dist/runtime/compiler-hook.d.ts +5 -0
  43. package/dist/runtime/compiler-hook.js +8 -0
  44. package/dist/runtime/create-orcha.d.ts +2 -1
  45. package/dist/runtime/create-orcha.js +15 -19
  46. package/dist/runtime/platform-browser.d.ts +2 -0
  47. package/dist/runtime/platform-browser.js +15 -0
  48. package/dist/runtime/platform-node.d.ts +2 -0
  49. package/dist/runtime/platform-node.js +31 -0
  50. package/dist/runtime/platform-react-native.d.ts +2 -0
  51. package/dist/runtime/platform-react-native.js +15 -0
  52. package/dist/runtime/platform.d.ts +15 -0
  53. package/dist/runtime/platform.js +1 -0
  54. package/dist/runtime/random-id.d.ts +1 -0
  55. package/dist/runtime/random-id.js +26 -0
  56. package/dist/runtime-entry.d.ts +5 -0
  57. package/dist/runtime-entry.js +2 -0
  58. package/dist/storage/browser-indexeddb.d.ts +7 -16
  59. package/dist/storage/browser-indexeddb.js +102 -19
  60. package/dist/storage/react-native-jsonl.d.ts +7 -16
  61. package/dist/storage/react-native-jsonl.js +65 -19
  62. package/dist/types.d.ts +3 -1
  63. package/dist-cjs/browser.js +48 -0
  64. package/dist-cjs/cli-agents-template.js +22 -0
  65. package/dist-cjs/compiler/build-project.js +97 -8
  66. package/dist-cjs/compiler/compile.js +17 -9
  67. package/dist-cjs/file-content.js +42 -7
  68. package/dist-cjs/index.js +4 -9
  69. package/dist-cjs/integrations/esbuild.js +6 -2
  70. package/dist-cjs/integrations/expo.js +29 -0
  71. package/dist-cjs/integrations/metro.js +51 -0
  72. package/dist-cjs/integrations/next.js +75 -0
  73. package/dist-cjs/integrations/runtime-build.js +70 -0
  74. package/dist-cjs/integrations/vite.js +57 -0
  75. package/dist-cjs/integrations/webpack.js +51 -0
  76. package/dist-cjs/orcha.js +17 -12
  77. package/dist-cjs/playground/server.js +62 -9
  78. package/dist-cjs/project-loader.js +10 -0
  79. package/dist-cjs/providers/browser.js +61 -0
  80. package/dist-cjs/react-native.js +48 -0
  81. package/dist-cjs/runtime/actions/browser-native.js +68 -0
  82. package/dist-cjs/runtime/actions/execute.js +12 -2
  83. package/dist-cjs/runtime/agent.js +8 -6
  84. package/dist-cjs/runtime/compiler-hook.js +37 -0
  85. package/dist-cjs/runtime/create-orcha.js +18 -21
  86. package/dist-cjs/runtime/platform-browser.js +48 -0
  87. package/dist-cjs/runtime/platform-node.js +59 -0
  88. package/dist-cjs/runtime/platform-react-native.js +45 -0
  89. package/dist-cjs/runtime/platform.js +17 -0
  90. package/dist-cjs/runtime/random-id.js +55 -0
  91. package/dist-cjs/runtime-entry.js +34 -0
  92. package/dist-cjs/storage/browser-indexeddb.js +102 -5
  93. package/dist-cjs/storage/react-native-jsonl.js +73 -5
  94. package/dist-cjs/types/react-native-async-storage.d.js +2 -0
  95. package/package.json +69 -9
  96. package/dist/playground/public/app.css +0 -1
  97. package/dist/playground/public/app.js +0 -31
  98. package/dist/playground/public/index.html +0 -15
  99. package/dist/playground/public/orcha-logo.svg +0 -4
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;
@@ -1,7 +1,4 @@
1
- import { resolve } from "node:path";
2
1
  import { RuntimeAgent } from "./agent.js";
3
- import { createSessionStore } from "../storage/create-store.js";
4
- import { syncAmarsiaProject } from "../amarsia/sync.js";
5
2
  import { setOrchaRuntimeContext } from "./context.js";
6
3
  class OrchaRuntimeCore {
7
4
  #agents = new Map();
@@ -11,22 +8,21 @@ class OrchaRuntimeCore {
11
8
  #sessionControls = new Map();
12
9
  #resolveBundle;
13
10
  #generateProviderResponse;
14
- constructor(resolveBundle, generateProviderResponse) {
11
+ #platform;
12
+ constructor(resolveBundle, generateProviderResponse, platform) {
15
13
  this.#resolveBundle = resolveBundle;
16
14
  this.#generateProviderResponse = generateProviderResponse;
15
+ this.#platform = platform;
17
16
  }
18
17
  attachClient(client) {
19
18
  this.#client = client;
20
19
  }
21
20
  init(configuration) {
22
- const projectRoot = resolve(configuration.root ??
23
- process.env.ORCHA_PROJECT_ROOT ??
24
- process.cwd());
25
- const bundle = this.#resolveBundle(configuration);
26
- if (configuration.amarsia?.key) {
27
- syncAmarsiaProject({
28
- key: configuration.amarsia.key,
29
- endpoint: configuration.amarsia.endpoint,
21
+ const projectRoot = this.#platform.projectRoot(configuration);
22
+ const bundle = configuration.bundle ?? this.#resolveBundle(configuration);
23
+ if (configuration.amarsia?.key && this.#platform.syncProject) {
24
+ this.#platform.syncProject({
25
+ configuration,
30
26
  bundle,
31
27
  projectRoot,
32
28
  });
@@ -46,12 +42,10 @@ class OrchaRuntimeCore {
46
42
  runtimeConfiguration.actions?.runtime !== bundle.actionRuntime) {
47
43
  throw new Error(`Production bundle expects local action runtime "${bundle.actionRuntime}".`);
48
44
  }
49
- const storageDirectory = configuration.storage?.directory ?? ".orcha/sessions";
50
- const createStore = (manifest) => createSessionStore({
51
- strategy: configuration.storage?.strategy,
52
- directory: storageDirectory,
45
+ const createStore = (manifest) => this.#platform.createSessionStore({
46
+ configuration,
53
47
  projectRoot,
54
- agentName: manifest.key ?? manifest.name,
48
+ manifest,
55
49
  });
56
50
  const agents = new Map();
57
51
  for (const [name, manifest] of Object.entries(bundle.agents)) {
@@ -66,6 +60,7 @@ class OrchaRuntimeCore {
66
60
  generateProviderResponse: this.#generateProviderResponse,
67
61
  delegatedOnly: true,
68
62
  projectRoot,
63
+ randomUUID: this.#platform.randomUUID,
69
64
  }),
70
65
  ]));
71
66
  agents.set(name, new RuntimeAgent({
@@ -77,6 +72,7 @@ class OrchaRuntimeCore {
77
72
  generateProviderResponse: this.#generateProviderResponse,
78
73
  subagents,
79
74
  projectRoot,
75
+ randomUUID: this.#platform.randomUUID,
80
76
  }));
81
77
  }
82
78
  this.#bundle = bundle;
@@ -103,8 +99,8 @@ class OrchaRuntimeCore {
103
99
  return this.#agents.get(name);
104
100
  }
105
101
  }
106
- export function createOrcha(resolveBundle, generateProviderResponse) {
107
- const core = new OrchaRuntimeCore(resolveBundle, generateProviderResponse);
102
+ export function createOrcha(resolveBundle, generateProviderResponse, platform) {
103
+ const core = new OrchaRuntimeCore(resolveBundle, generateProviderResponse, platform);
108
104
  const client = new Proxy(core, {
109
105
  get(target, property) {
110
106
  if (typeof property === "string") {
@@ -0,0 +1,2 @@
1
+ import type { RuntimePlatform } from "./platform.js";
2
+ export declare const browserRuntimePlatform: RuntimePlatform;
@@ -0,0 +1,15 @@
1
+ import { BrowserIndexedDbSessionStore } from "../storage/browser-indexeddb.js";
2
+ import { portableRandomUUID } from "./random-id.js";
3
+ export const browserRuntimePlatform = {
4
+ randomUUID: portableRandomUUID,
5
+ projectRoot(configuration) {
6
+ return configuration.root ?? "/";
7
+ },
8
+ createSessionStore({ configuration, manifest }) {
9
+ const strategy = configuration.storage?.strategy ?? "indexeddb";
10
+ if (strategy !== "indexeddb") {
11
+ throw new Error(`Browser runtimes require storage strategy "indexeddb", received "${strategy}".`);
12
+ }
13
+ return new BrowserIndexedDbSessionStore(manifest.key ?? manifest.name, configuration.storage?.directory ?? "orchajs");
14
+ },
15
+ };
@@ -0,0 +1,2 @@
1
+ import type { RuntimePlatform } from "./platform.js";
2
+ export declare const nodeRuntimePlatform: RuntimePlatform;
@@ -0,0 +1,31 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { resolve } from "node:path";
3
+ import { syncAmarsiaProject } from "../amarsia/sync.js";
4
+ import { createSessionStore } from "../storage/create-store.js";
5
+ export const nodeRuntimePlatform = {
6
+ randomUUID,
7
+ projectRoot(configuration) {
8
+ return resolve(configuration.root ??
9
+ process.env.ORCHA_PROJECT_ROOT ??
10
+ process.cwd());
11
+ },
12
+ createSessionStore({ configuration, projectRoot, manifest }) {
13
+ return createSessionStore({
14
+ strategy: configuration.storage?.strategy,
15
+ directory: configuration.storage?.directory,
16
+ projectRoot,
17
+ agentName: manifest.key ?? manifest.name,
18
+ });
19
+ },
20
+ syncProject({ configuration, bundle, projectRoot }) {
21
+ if (!configuration.amarsia?.key) {
22
+ return;
23
+ }
24
+ syncAmarsiaProject({
25
+ key: configuration.amarsia.key,
26
+ endpoint: configuration.amarsia.endpoint,
27
+ bundle,
28
+ projectRoot,
29
+ });
30
+ },
31
+ };
@@ -0,0 +1,2 @@
1
+ import type { RuntimePlatform } from "./platform.js";
2
+ export declare const reactNativeRuntimePlatform: RuntimePlatform;
@@ -0,0 +1,15 @@
1
+ import { ReactNativeJsonlSessionStore } from "../storage/react-native-jsonl.js";
2
+ import { portableRandomUUID } from "./random-id.js";
3
+ export const reactNativeRuntimePlatform = {
4
+ randomUUID: portableRandomUUID,
5
+ projectRoot(configuration) {
6
+ return configuration.root ?? "/";
7
+ },
8
+ createSessionStore({ configuration, manifest }) {
9
+ const strategy = configuration.storage?.strategy ?? "react-native";
10
+ if (strategy !== "react-native") {
11
+ throw new Error(`React Native requires storage strategy "react-native", received "${strategy}".`);
12
+ }
13
+ return new ReactNativeJsonlSessionStore(manifest.key ?? manifest.name);
14
+ },
15
+ };
@@ -0,0 +1,15 @@
1
+ import type { CompiledAgentManifest, CompiledBundle, OrchaInitConfiguration, SessionStore } from "../types.js";
2
+ export interface RuntimePlatform {
3
+ randomUUID(): string;
4
+ projectRoot(configuration: OrchaInitConfiguration): string;
5
+ createSessionStore(options: {
6
+ configuration: OrchaInitConfiguration;
7
+ projectRoot: string;
8
+ manifest: CompiledAgentManifest;
9
+ }): SessionStore;
10
+ syncProject?(options: {
11
+ configuration: OrchaInitConfiguration;
12
+ bundle: CompiledBundle;
13
+ projectRoot: string;
14
+ }): void;
15
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export declare function portableRandomUUID(): string;
@@ -0,0 +1,26 @@
1
+ let fallbackSequence = 0;
2
+ export function portableRandomUUID() {
3
+ const crypto = globalThis.crypto;
4
+ if (typeof crypto?.randomUUID === "function") {
5
+ return crypto.randomUUID();
6
+ }
7
+ if (typeof crypto?.getRandomValues === "function") {
8
+ return formatUuid(crypto.getRandomValues(new Uint8Array(16)));
9
+ }
10
+ fallbackSequence = (fallbackSequence + 1) >>> 0;
11
+ const bytes = new Uint8Array(16);
12
+ let state = Date.now() ^
13
+ fallbackSequence ^
14
+ Math.floor(Math.random() * 0x1_0000_0000);
15
+ for (let index = 0; index < bytes.length; index += 1) {
16
+ state = (Math.imul(state, 1_664_525) + 1_013_904_223) >>> 0;
17
+ bytes[index] = state >>> 24;
18
+ }
19
+ return formatUuid(bytes);
20
+ }
21
+ function formatUuid(bytes) {
22
+ bytes[6] = (bytes[6] & 0x0f) | 0x40;
23
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
24
+ const value = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
25
+ return `${value.slice(0, 8)}-${value.slice(8, 12)}-${value.slice(12, 16)}-${value.slice(16, 20)}-${value.slice(20)}`;
26
+ }
@@ -0,0 +1,5 @@
1
+ export { OrchaError } from "./errors.js";
2
+ export type { Orcha, OrchaClient, } from "./runtime/create-orcha.js";
3
+ export { exportSessionJsonl, migrateSessionStore, } from "./storage/migrate.js";
4
+ export type { SessionStoreMigrationResult, } from "./storage/migrate.js";
5
+ export type { ActionConfiguration, AgentTestActionConfiguration, AgentTestActionExpectation, AgentTestActionResponse, AgentTestAssertionResult, AgentTestCaseConfiguration, AgentTestCaseReport, AgentTestCaseSummary, AgentTestExpectation, AgentTestReport, AgentTestTextExpectation, AgentTestValueExpectation, AgentTestWarning, ApiKeyProviderConfiguration, AwsCredentials, AgentContinueInput, AgentConfiguration, AgentContentInput, AgentInput, AgentRegistration, AgentRuntime, ClientCapability, ClientToolCall, CompletedRunResult, CompiledActionManifest, CompiledAgentManifest, CompiledBundle, CompiledEvaluationManifest, CompiledSkillManifest, EvaluationConfiguration, EvaluationMetricConfiguration, EvaluationMetricResult, EvaluationResult, Execution, ExecutionSnapshot, FailedRunResult, FileContent, FilePathContentInput, LocalFileContent, LocalActionRuntimeConfiguration, MessageContent, MessageContentInput, MetadataValue, OrchaErrorCode, OrchaInitConfiguration, PausedRunResult, PaginationOptions, ProjectConfiguration, ProviderConfiguration, ProviderInitConfigurations, ProviderName, BedrockProviderConfiguration, RunError, RunStatus, RunTestsOptions, ResumeInput, RunResult, SessionEvent, SessionEventListOptions, SessionEvents, SessionEventType, SessionHistory, SessionHistoryItem, SessionList, SessionListOptions, SessionMetadata, SessionSnapshot, SessionStatus, SessionStore, SkillConfiguration, SessionUpdate, StreamingRunSnapshot, SubagentConfiguration, TextContent, ToolResult, ToolResumeInput, UrlContentInput, Usage, VertexAIProviderConfiguration, GoogleServiceAccountCredentials, WaitingRunResult, WaitingForSubagentSnapshot, } from "./types.js";
@@ -0,0 +1,2 @@
1
+ export { OrchaError } from "./errors.js";
2
+ export { exportSessionJsonl, migrateSessionStore, } from "./storage/migrate.js";
@@ -1,20 +1,11 @@
1
1
  import type { SessionEvent, SessionStore } from "../types.js";
2
- /**
3
- * Future browser storage strategy.
4
- *
5
- * It will persist the same ordered SessionEvent records used by the JSONL
6
- * strategy in IndexedDB. Import and export will preserve the canonical JSONL
7
- * representation so a session can move between browser, Node, and remote
8
- * stores without changing the runtime or replay engine.
9
- *
10
- * Required before implementation:
11
- * - transactional sequence allocation;
12
- * - multi-tab writer coordination;
13
- * - quota and eviction handling;
14
- * - schema migrations and JSONL import/export.
15
- */
16
2
  export declare class BrowserIndexedDbSessionStore implements SessionStore {
17
- read(_sessionId: string): Promise<SessionEvent[]>;
18
- append(_sessionId: string, _events: SessionEvent[]): Promise<void>;
3
+ #private;
4
+ constructor(namespace: string, databaseName?: string);
5
+ read(sessionId: string): Promise<SessionEvent[]>;
6
+ append(sessionId: string, events: SessionEvent[]): Promise<void>;
19
7
  listSessionIds(): Promise<string[]>;
8
+ subscribe(sessionId: string, listener: (events: SessionEvent[]) => void): () => void;
9
+ subscribeAll(listener: (sessionId: string, events: SessionEvent[]) => void): () => void;
10
+ describeLocation(sessionId: string): Promise<string>;
20
11
  }