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
@@ -1,25 +1,108 @@
1
- /**
2
- * Future browser storage strategy.
3
- *
4
- * It will persist the same ordered SessionEvent records used by the JSONL
5
- * strategy in IndexedDB. Import and export will preserve the canonical JSONL
6
- * representation so a session can move between browser, Node, and remote
7
- * stores without changing the runtime or replay engine.
8
- *
9
- * Required before implementation:
10
- * - transactional sequence allocation;
11
- * - multi-tab writer coordination;
12
- * - quota and eviction handling;
13
- * - schema migrations and JSONL import/export.
14
- */
1
+ const DATABASE_VERSION = 1;
2
+ const EVENT_STORE = "events";
15
3
  export class BrowserIndexedDbSessionStore {
16
- async read(_sessionId) {
17
- throw new Error("Browser IndexedDB session storage is not implemented yet.");
4
+ #databaseName;
5
+ #namespace;
6
+ #listeners = new Map();
7
+ #allListeners = new Set();
8
+ constructor(namespace, databaseName = "orchajs") {
9
+ this.#namespace = namespace;
10
+ this.#databaseName = databaseName;
18
11
  }
19
- async append(_sessionId, _events) {
20
- throw new Error("Browser IndexedDB session storage is not implemented yet.");
12
+ async read(sessionId) {
13
+ const database = await this.#open();
14
+ const transaction = database.transaction(EVENT_STORE, "readonly");
15
+ const index = transaction.objectStore(EVENT_STORE).index("session");
16
+ const records = await request(index.getAll(IDBKeyRange.only([this.#namespace, sessionId])));
17
+ await transactionComplete(transaction);
18
+ return records
19
+ .sort((left, right) => left.sequence - right.sequence)
20
+ .map((record) => record.event);
21
+ }
22
+ async append(sessionId, events) {
23
+ if (events.length === 0) {
24
+ return;
25
+ }
26
+ const database = await this.#open();
27
+ const transaction = database.transaction(EVENT_STORE, "readwrite");
28
+ const store = transaction.objectStore(EVENT_STORE);
29
+ for (const event of events) {
30
+ store.add({
31
+ id: eventId(this.#namespace, sessionId, event.sequence),
32
+ namespace: this.#namespace,
33
+ sessionId,
34
+ sequence: event.sequence,
35
+ event,
36
+ });
37
+ }
38
+ await transactionComplete(transaction);
39
+ this.#listeners.get(sessionId)?.forEach((listener) => listener(events));
40
+ this.#allListeners.forEach((listener) => listener(sessionId, events));
21
41
  }
22
42
  async listSessionIds() {
23
- throw new Error("Browser IndexedDB session storage is not implemented yet.");
43
+ const database = await this.#open();
44
+ const transaction = database.transaction(EVENT_STORE, "readonly");
45
+ const index = transaction.objectStore(EVENT_STORE).index("namespace");
46
+ const records = await request(index.getAll(IDBKeyRange.only(this.#namespace)));
47
+ await transactionComplete(transaction);
48
+ return [...new Set(records.map((record) => record.sessionId))].sort();
49
+ }
50
+ subscribe(sessionId, listener) {
51
+ const listeners = this.#listeners.get(sessionId) ?? new Set();
52
+ listeners.add(listener);
53
+ this.#listeners.set(sessionId, listeners);
54
+ return () => {
55
+ listeners.delete(listener);
56
+ if (listeners.size === 0) {
57
+ this.#listeners.delete(sessionId);
58
+ }
59
+ };
60
+ }
61
+ subscribeAll(listener) {
62
+ this.#allListeners.add(listener);
63
+ return () => this.#allListeners.delete(listener);
64
+ }
65
+ async describeLocation(sessionId) {
66
+ return `indexeddb://${this.#databaseName}/${this.#namespace}/${sessionId}`;
24
67
  }
68
+ #open() {
69
+ if (typeof indexedDB === "undefined") {
70
+ throw new Error("IndexedDB is unavailable in this runtime.");
71
+ }
72
+ return new Promise((resolve, reject) => {
73
+ const openRequest = indexedDB.open(this.#databaseName, DATABASE_VERSION);
74
+ openRequest.onupgradeneeded = () => {
75
+ const database = openRequest.result;
76
+ if (database.objectStoreNames.contains(EVENT_STORE)) {
77
+ return;
78
+ }
79
+ const store = database.createObjectStore(EVENT_STORE, {
80
+ keyPath: "id",
81
+ });
82
+ store.createIndex("session", ["namespace", "sessionId"]);
83
+ store.createIndex("namespace", "namespace");
84
+ };
85
+ openRequest.onsuccess = () => resolve(openRequest.result);
86
+ openRequest.onerror = () => reject(openRequest.error);
87
+ openRequest.onblocked = () => reject(new Error("Opening the Orcha IndexedDB database was blocked."));
88
+ });
89
+ }
90
+ }
91
+ function eventId(namespace, sessionId, sequence) {
92
+ return `${namespace}\u0000${sessionId}\u0000${sequence
93
+ .toString()
94
+ .padStart(12, "0")}`;
95
+ }
96
+ function request(value) {
97
+ return new Promise((resolve, reject) => {
98
+ value.onsuccess = () => resolve(value.result);
99
+ value.onerror = () => reject(value.error);
100
+ });
101
+ }
102
+ function transactionComplete(transaction) {
103
+ return new Promise((resolve, reject) => {
104
+ transaction.oncomplete = () => resolve();
105
+ transaction.onerror = () => reject(transaction.error);
106
+ transaction.onabort = () => reject(transaction.error ?? new Error("IndexedDB transaction aborted."));
107
+ });
25
108
  }
@@ -1,20 +1,11 @@
1
1
  import type { SessionEvent, SessionStore } from "../types.js";
2
- /**
3
- * Future React Native storage strategy.
4
- *
5
- * It will store one JSONL event stream per session inside the application's
6
- * private documents directory. The implementation must not assume Node's
7
- * `fs` module: Expo FileSystem and bare React Native filesystem bindings need
8
- * a small host adapter while retaining the exact SessionStore contract.
9
- *
10
- * Required before implementation:
11
- * - Expo and bare React Native filesystem adapters;
12
- * - atomic append/recovery behavior on iOS and Android;
13
- * - app lifecycle interruption handling;
14
- * - JSONL import/export conformance tests.
15
- */
16
2
  export declare class ReactNativeJsonlSessionStore implements SessionStore {
17
- read(_sessionId: string): Promise<SessionEvent[]>;
18
- append(_sessionId: string, _events: SessionEvent[]): Promise<void>;
3
+ #private;
4
+ constructor(namespace: 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
  }
@@ -1,25 +1,71 @@
1
- /**
2
- * Future React Native storage strategy.
3
- *
4
- * It will store one JSONL event stream per session inside the application's
5
- * private documents directory. The implementation must not assume Node's
6
- * `fs` module: Expo FileSystem and bare React Native filesystem bindings need
7
- * a small host adapter while retaining the exact SessionStore contract.
8
- *
9
- * Required before implementation:
10
- * - Expo and bare React Native filesystem adapters;
11
- * - atomic append/recovery behavior on iOS and Android;
12
- * - app lifecycle interruption handling;
13
- * - JSONL import/export conformance tests.
14
- */
1
+ import AsyncStorage from "@react-native-async-storage/async-storage";
2
+ const writes = new Map();
15
3
  export class ReactNativeJsonlSessionStore {
16
- async read(_sessionId) {
17
- throw new Error("React Native JSONL session storage is not implemented yet.");
4
+ #namespace;
5
+ #listeners = new Map();
6
+ #allListeners = new Set();
7
+ constructor(namespace) {
8
+ this.#namespace = namespace;
18
9
  }
19
- async append(_sessionId, _events) {
20
- throw new Error("React Native JSONL session storage is not implemented yet.");
10
+ async read(sessionId) {
11
+ const contents = await AsyncStorage.getItem(this.#key(sessionId));
12
+ if (!contents) {
13
+ return [];
14
+ }
15
+ return contents
16
+ .split("\n")
17
+ .filter(Boolean)
18
+ .map((line) => JSON.parse(line));
19
+ }
20
+ async append(sessionId, events) {
21
+ if (events.length === 0) {
22
+ return;
23
+ }
24
+ const key = this.#key(sessionId);
25
+ const previous = writes.get(key) ?? Promise.resolve();
26
+ const write = previous.then(async () => {
27
+ const existing = await AsyncStorage.getItem(key);
28
+ const appended = events.map((event) => JSON.stringify(event)).join("\n");
29
+ await AsyncStorage.setItem(key, `${existing ? `${existing.replace(/\n*$/, "")}\n` : ""}${appended}\n`);
30
+ });
31
+ writes.set(key, write);
32
+ try {
33
+ await write;
34
+ }
35
+ finally {
36
+ if (writes.get(key) === write) {
37
+ writes.delete(key);
38
+ }
39
+ }
40
+ this.#listeners.get(sessionId)?.forEach((listener) => listener(events));
41
+ this.#allListeners.forEach((listener) => listener(sessionId, events));
21
42
  }
22
43
  async listSessionIds() {
23
- throw new Error("React Native JSONL session storage is not implemented yet.");
44
+ const prefix = `@orchajs:${this.#namespace}:`;
45
+ return (await AsyncStorage.getAllKeys())
46
+ .filter((key) => key.startsWith(prefix))
47
+ .map((key) => key.slice(prefix.length))
48
+ .sort();
49
+ }
50
+ subscribe(sessionId, listener) {
51
+ const listeners = this.#listeners.get(sessionId) ?? new Set();
52
+ listeners.add(listener);
53
+ this.#listeners.set(sessionId, listeners);
54
+ return () => {
55
+ listeners.delete(listener);
56
+ if (listeners.size === 0) {
57
+ this.#listeners.delete(sessionId);
58
+ }
59
+ };
60
+ }
61
+ subscribeAll(listener) {
62
+ this.#allListeners.add(listener);
63
+ return () => this.#allListeners.delete(listener);
64
+ }
65
+ async describeLocation(sessionId) {
66
+ return `async-storage://${this.#key(sessionId)}`;
67
+ }
68
+ #key(sessionId) {
69
+ return `@orchajs:${this.#namespace}:${sessionId}`;
24
70
  }
25
71
  }
package/dist/types.d.ts CHANGED
@@ -43,7 +43,7 @@ export interface ProjectConfiguration {
43
43
  providers: ResolvedProviderConfigurations;
44
44
  actions?: LocalActionRuntimeConfiguration;
45
45
  storage?: {
46
- strategy?: "node-jsonl" | "sqlite";
46
+ strategy?: "node-jsonl" | "sqlite" | "indexeddb" | "react-native";
47
47
  directory?: string;
48
48
  };
49
49
  }
@@ -54,6 +54,8 @@ export type AgentRegistration = string | {
54
54
  export interface OrchaInitConfiguration {
55
55
  providers: ProviderInitConfigurations;
56
56
  agents: Record<string, AgentRegistration>;
57
+ /** Precompiled registry used by browser, React Native, and custom runtimes. */
58
+ bundle?: CompiledBundle;
57
59
  amarsia?: {
58
60
  key: string;
59
61
  endpoint?: string;
@@ -0,0 +1,48 @@
1
+ "use strict"; const __orchaImportMetaUrl = require("url").pathToFileURL(__filename).href;
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+ var browser_exports = {};
22
+ __export(browser_exports, {
23
+ orcha: () => orcha
24
+ });
25
+ module.exports = __toCommonJS(browser_exports);
26
+ var import_browser = require("./providers/browser.js");
27
+ var import_execute = require("./runtime/actions/execute.js");
28
+ var import_create_orcha = require("./runtime/create-orcha.js");
29
+ var import_platform_browser = require("./runtime/platform-browser.js");
30
+ __reExport(browser_exports, require("./runtime-entry.js"), module.exports);
31
+ (0, import_execute.setNativeRuntimeLoader)(async () => {
32
+ const modulePath = "./runtime/actions/browser-native.js";
33
+ return import(modulePath);
34
+ });
35
+ const orcha = (0, import_create_orcha.createOrcha)(
36
+ () => {
37
+ throw new Error(
38
+ "The browser runtime requires a precompiled Orcha bundle. Configure the Orcha integration for your application bundler."
39
+ );
40
+ },
41
+ import_browser.generateBrowserProviderResponse,
42
+ import_platform_browser.browserRuntimePlatform
43
+ );
44
+ // Annotate the CommonJS export names for ESM import in node:
45
+ 0 && (module.exports = {
46
+ orcha,
47
+ ...require("./runtime-entry.js")
48
+ });
@@ -52,6 +52,28 @@ credentials. \`dev\` and \`build\` are offline. Sessions use JSONL by default
52
52
  under \`.orcha/sessions/<agentName>/\`; opt-in SQLite stores all agents in
53
53
  \`.orcha/sessions/orcha-sqlite.db\`.
54
54
 
55
+ ## Production deployment
56
+
57
+ \`orcha build\` writes \`.orcha/dist/bundle.js\` for bundler integrations and
58
+ \`.orcha/dist/manifest.json\` for unbundled production runtimes. If deployment
59
+ uses plain \`tsc\`, \`serverless-plugin-typescript\`, or another packager that
60
+ does not use \`orchajs/esbuild\`, explicitly include \`.orcha/dist/**\` in the
61
+ deployment artifact. AWS Lambda loads the manifest automatically; other
62
+ unbundled environments require \`NODE_ENV=production\` or
63
+ \`ORCHA_USE_BUILD=1\`.
64
+
65
+ For Serverless Framework manual builds:
66
+
67
+ \`\`\`yaml
68
+ package:
69
+ patterns:
70
+ - ".orcha/dist/**"
71
+ \`\`\`
72
+
73
+ Do not assume that a successful \`orcha build\` means the generated files were
74
+ copied by a later packaging tool. Inspect the final ZIP or container image and
75
+ confirm that \`.orcha/dist/manifest.json\` is present.
76
+
55
77
  ## Registry
56
78
 
57
79
  \`orcha/index.ts\` initializes providers and explicitly registers agents:
@@ -28,9 +28,21 @@ var import_path = require("path");
28
28
  var import_url = require("url");
29
29
  var import_esbuild = require("esbuild");
30
30
  var import_orcha = require("../orcha.js");
31
+ var import_compiler_hook = require("../runtime/compiler-hook.js");
32
+ var import_compile = require("./compile.js");
31
33
  var import_catalog = require("../providers/catalog.js");
34
+ let registryImportSequence = 0;
32
35
  async function buildProject(options = {}) {
33
36
  const projectRoot = (0, import_path.resolve)(options.projectRoot ?? process.cwd());
37
+ const target = options.target ?? "node";
38
+ (0, import_compiler_hook.setRegistryCompiler)(
39
+ (configuration, compilerProjectRoot) => (0, import_compile.compileRegistry)(
40
+ configuration.agents,
41
+ (0, import_path.resolve)(compilerProjectRoot, "orcha"),
42
+ configuration.actions?.runtime ?? "native",
43
+ target
44
+ )
45
+ );
34
46
  const registryPath = (0, import_path.resolve)(projectRoot, "orcha/index.ts");
35
47
  if (!(0, import_fs.existsSync)(registryPath)) {
36
48
  throw new Error('Missing "orcha/index.ts". Run "orcha init" first.');
@@ -41,7 +53,10 @@ async function buildProject(options = {}) {
41
53
  temporaryDirectory,
42
54
  "production-entry.mjs"
43
55
  );
44
- const outputPath = (0, import_path.resolve)(projectRoot, ".orcha/dist/bundle.js");
56
+ const outputPath = (0, import_path.resolve)(
57
+ projectRoot,
58
+ `.orcha/dist/${bundleFileName(target)}`
59
+ );
45
60
  const manifestPath = (0, import_path.resolve)(
46
61
  projectRoot,
47
62
  ".orcha/dist/manifest.json"
@@ -64,7 +79,7 @@ async function buildProject(options = {}) {
64
79
  process.env.ORCHA_COMPILING = "1";
65
80
  process.env.ORCHA_PROJECT_ROOT = projectRoot;
66
81
  try {
67
- await import(`${(0, import_url.pathToFileURL)(registryBundlePath).href}?time=${Date.now()}`);
82
+ await import(`${(0, import_url.pathToFileURL)(registryBundlePath).href}?build=${Date.now()}-${registryImportSequence++}`);
68
83
  } finally {
69
84
  if (previousCompiling === void 0) {
70
85
  delete process.env.ORCHA_COMPILING;
@@ -78,15 +93,30 @@ async function buildProject(options = {}) {
78
93
  }
79
94
  }
80
95
  const compiledBundle = import_orcha.orcha.getCompiledBundle();
96
+ if (target !== "node" && compiledBundle.actionRuntime === "sandbox") {
97
+ throw new Error(
98
+ `The ${target} target supports precompiled native actions only. Set actions.runtime to "native".`
99
+ );
100
+ }
81
101
  const runtimeFactoryPath = (0, import_path.resolve)(
82
102
  (0, import_path.dirname)((0, import_url.fileURLToPath)(__orchaImportMetaUrl)),
83
103
  "../runtime/create-orcha.js"
84
104
  ).replaceAll("\\", "/");
105
+ const runtimePlatformPath = (0, import_path.resolve)(
106
+ (0, import_path.dirname)((0, import_url.fileURLToPath)(__orchaImportMetaUrl)),
107
+ `../runtime/platform-${target}.js`
108
+ ).replaceAll("\\", "/");
109
+ const runtimeEntryPath = (0, import_path.resolve)(
110
+ (0, import_path.dirname)((0, import_url.fileURLToPath)(__orchaImportMetaUrl)),
111
+ "../runtime-entry.js"
112
+ ).replaceAll("\\", "/");
85
113
  const providerDispatcherPath = (0, import_path.resolve)(
86
114
  (0, import_path.dirname)((0, import_url.fileURLToPath)(__orchaImportMetaUrl)),
87
115
  "../providers/dispatcher.js"
88
116
  ).replaceAll("\\", "/");
89
117
  const sandboxRuntimeSource = compiledBundle.actionRuntime === "sandbox" ? createSandboxRuntimeSource() : "";
118
+ const platformActionRuntimeSource = createPlatformActionRuntimeSource(target);
119
+ const nodeStorageExports = target === "node" ? createNodeStorageExports() : "";
90
120
  const includedProviders = [
91
121
  ...new Set(
92
122
  allCompiledAgents(compiledBundle.agents).flatMap(
@@ -97,18 +127,22 @@ async function buildProject(options = {}) {
97
127
  )
98
128
  )
99
129
  ];
100
- const providerRuntimeSource = createProviderRuntimeSource(includedProviders);
130
+ const providerRuntimeSource = createProviderRuntimeSource(includedProviders, target);
101
131
  const needsNodeRequire = compiledBundle.actionRuntime === "sandbox" || includedProviders.includes("vertexai") || includedProviders.includes("bedrock");
102
132
  await (0, import_promises.writeFile)(
103
133
  productionEntryPath,
104
134
  [
105
135
  `import { createOrcha } from ${JSON.stringify(runtimeFactoryPath)};`,
136
+ `import { ${runtimePlatformExport(target)} as runtimePlatform } from ${JSON.stringify(runtimePlatformPath)};`,
106
137
  `import { createProviderResponseGenerator } from ${JSON.stringify(providerDispatcherPath)};`,
138
+ `export * from ${JSON.stringify(runtimeEntryPath)};`,
139
+ nodeStorageExports,
107
140
  providerRuntimeSource,
141
+ platformActionRuntimeSource,
108
142
  sandboxRuntimeSource,
109
143
  `const compiledBundle = ${JSON.stringify(compiledBundle)};`,
110
144
  "const generateProviderResponse = createProviderResponseGenerator(includedProviders);",
111
- "export const orcha = createOrcha(() => compiledBundle, generateProviderResponse);",
145
+ "export const orcha = createOrcha(() => compiledBundle, generateProviderResponse, runtimePlatform);",
112
146
  "export default orcha;",
113
147
  ""
114
148
  ].join("\n"),
@@ -119,8 +153,8 @@ async function buildProject(options = {}) {
119
153
  outfile: outputPath,
120
154
  bundle: true,
121
155
  format: "esm",
122
- platform: "node",
123
- target: "node18",
156
+ platform: target === "node" ? "node" : "browser",
157
+ target: target === "node" ? "node18" : target === "browser" ? ["chrome110", "firefox110", "safari16"] : "es2022",
124
158
  minify: true,
125
159
  legalComments: "none",
126
160
  define: {
@@ -128,7 +162,7 @@ async function buildProject(options = {}) {
128
162
  compiledBundle.actionRuntime === "sandbox" ? "1" : "0"
129
163
  )
130
164
  },
131
- ...needsNodeRequire ? {
165
+ ...needsNodeRequire && target === "node" ? {
132
166
  banner: {
133
167
  js: [
134
168
  'import { createRequire as __orchaCreateRequire } from "module";',
@@ -136,6 +170,11 @@ async function buildProject(options = {}) {
136
170
  ].join("\n")
137
171
  }
138
172
  } : {},
173
+ ...target === "react-native" ? {
174
+ external: [
175
+ "@react-native-async-storage/async-storage"
176
+ ]
177
+ } : {},
139
178
  logLevel: "silent"
140
179
  });
141
180
  await (0, import_promises.writeFile)(
@@ -152,6 +191,18 @@ async function buildProject(options = {}) {
152
191
  });
153
192
  }
154
193
  }
194
+ function bundleFileName(target) {
195
+ return target === "node" ? "bundle.js" : `bundle.${target}.js`;
196
+ }
197
+ function runtimePlatformExport(target) {
198
+ if (target === "browser") {
199
+ return "browserRuntimePlatform";
200
+ }
201
+ if (target === "react-native") {
202
+ return "reactNativeRuntimePlatform";
203
+ }
204
+ return "nodeRuntimePlatform";
205
+ }
155
206
  function createSandboxRuntimeSource() {
156
207
  const runtimeDirectory = (0, import_path.dirname)((0, import_url.fileURLToPath)(__orchaImportMetaUrl));
157
208
  const executePath = (0, import_path.resolve)(
@@ -169,13 +220,46 @@ function createSandboxRuntimeSource() {
169
220
  ""
170
221
  ].join("\n");
171
222
  }
223
+ function createPlatformActionRuntimeSource(target) {
224
+ const runtimeDirectory = (0, import_path.dirname)((0, import_url.fileURLToPath)(__orchaImportMetaUrl));
225
+ const executePath = (0, import_path.resolve)(
226
+ runtimeDirectory,
227
+ "../runtime/actions/execute.js"
228
+ ).replaceAll("\\", "/");
229
+ const nativePath = (0, import_path.resolve)(
230
+ runtimeDirectory,
231
+ target === "node" ? "../runtime/actions/native.js" : "../runtime/actions/browser-native.js"
232
+ ).replaceAll("\\", "/");
233
+ return [
234
+ `import { setNativeRuntimeLoader } from ${JSON.stringify(executePath)};`,
235
+ `import { executeNativeAction } from ${JSON.stringify(nativePath)};`,
236
+ "setNativeRuntimeLoader(async () => ({ executeNativeAction }));",
237
+ ""
238
+ ].join("\n");
239
+ }
240
+ function createNodeStorageExports() {
241
+ const sourceRoot = (0, import_path.dirname)((0, import_url.fileURLToPath)(__orchaImportMetaUrl));
242
+ const jsonlPath = (0, import_path.resolve)(
243
+ sourceRoot,
244
+ "../storage/node-jsonl.js"
245
+ ).replaceAll("\\", "/");
246
+ const sqlitePath = (0, import_path.resolve)(
247
+ sourceRoot,
248
+ "../storage/node-sqlite.js"
249
+ ).replaceAll("\\", "/");
250
+ return [
251
+ `export { NodeJsonlSessionStore } from ${JSON.stringify(jsonlPath)};`,
252
+ `export { NodeSqliteSessionStore } from ${JSON.stringify(sqlitePath)};`,
253
+ ""
254
+ ].join("\n");
255
+ }
172
256
  function allCompiledAgents(agents) {
173
257
  return Object.values(agents).flatMap((agent) => [
174
258
  agent,
175
259
  ...Object.values(agent.subagents ?? {})
176
260
  ]);
177
261
  }
178
- function createProviderRuntimeSource(providerNames) {
262
+ function createProviderRuntimeSource(providerNames, target) {
179
263
  const providersDirectory = (0, import_path.resolve)(
180
264
  (0, import_path.dirname)((0, import_url.fileURLToPath)(__orchaImportMetaUrl)),
181
265
  "../providers"
@@ -186,6 +270,11 @@ function createProviderRuntimeSource(providerNames) {
186
270
  if (!(0, import_catalog.isBuiltInProvider)(name)) {
187
271
  throw new Error(`Provider "${name}" is not built in.`);
188
272
  }
273
+ if (target !== "node" && (name === "bedrock" || name === "vertexai")) {
274
+ throw new Error(
275
+ `Provider "${name}" is not available for the ${target} target.`
276
+ );
277
+ }
189
278
  const descriptor = import_catalog.builtInProviderCatalog[name];
190
279
  const localName = `provider${index}`;
191
280
  imports.push(
@@ -28,7 +28,7 @@ var import_fs = require("fs");
28
28
  var import_path = require("path");
29
29
  var import_esbuild = require("esbuild");
30
30
  var import_catalog = require("../providers/catalog.js");
31
- function compileRegistry(registrations, registryRoot, actionRuntime = "native") {
31
+ function compileRegistry(registrations, registryRoot, actionRuntime = "native", target = "node") {
32
32
  if (!registrations || typeof registrations !== "object" || Array.isArray(registrations)) {
33
33
  throw new TypeError(
34
34
  'orcha.init() requires an "agents" object of registered folder paths.'
@@ -51,14 +51,16 @@ function compileRegistry(registrations, registryRoot, actionRuntime = "native")
51
51
  subagentKey,
52
52
  registeredPath,
53
53
  registryRoot,
54
- actionRuntime
54
+ actionRuntime,
55
+ target
55
56
  );
56
57
  }
57
58
  const parent = compileAgent(
58
59
  key,
59
60
  normalized.path,
60
61
  registryRoot,
61
- actionRuntime
62
+ actionRuntime,
63
+ target
62
64
  );
63
65
  agents[key] = Object.freeze({
64
66
  ...parent,
@@ -108,7 +110,7 @@ function normalizeAgentRegistration(key, registration) {
108
110
  subagents: registration.subagents ?? {}
109
111
  };
110
112
  }
111
- function compileAgent(key, registeredPath, registryRoot, actionRuntime) {
113
+ function compileAgent(key, registeredPath, registryRoot, actionRuntime, target) {
112
114
  const name = key;
113
115
  const sourceDirectory = (0, import_path.resolve)(registryRoot, registeredPath);
114
116
  const configPath = (0, import_path.resolve)(sourceDirectory, "index.json");
@@ -195,14 +197,19 @@ function compileAgent(key, registeredPath, registryRoot, actionRuntime) {
195
197
  reasoningLevel: configuration.reasoningLevel,
196
198
  outputType: configuration.outputType ?? "text",
197
199
  outputSchema: configuration.outputSchema,
198
- actions: compileActions(name, sourceDirectory, actionRuntime),
200
+ actions: compileActions(
201
+ name,
202
+ sourceDirectory,
203
+ actionRuntime,
204
+ target
205
+ ),
199
206
  skills: compileSkills(name, sourceDirectory),
200
207
  evaluations: compileEvaluations(name, sourceDirectory),
201
208
  subagentPolicy: configuration.subagents ? Object.freeze({ ...configuration.subagents }) : void 0,
202
209
  subagents: Object.freeze({})
203
210
  });
204
211
  }
205
- function compileActions(agentName, sourceDirectory, actionRuntime) {
212
+ function compileActions(agentName, sourceDirectory, actionRuntime, target) {
206
213
  const actionsDirectory = (0, import_path.resolve)(sourceDirectory, "actions");
207
214
  if (!(0, import_fs.existsSync)(actionsDirectory)) {
208
215
  return {};
@@ -306,7 +313,8 @@ function compileActions(agentName, sourceDirectory, actionRuntime) {
306
313
  agentName,
307
314
  entry.name,
308
315
  actionsDirectory,
309
- actionRuntime
316
+ actionRuntime,
317
+ target
310
318
  ) : void 0;
311
319
  actions[configuration.name] = Object.freeze({
312
320
  ...configuration,
@@ -498,7 +506,7 @@ function validateEvaluationConfiguration(agentName, registrationName, configurat
498
506
  names.add(metric.name);
499
507
  }
500
508
  }
501
- function compileLocalAction(agentName, directoryName, actionsDirectory, actionRuntime) {
509
+ function compileLocalAction(agentName, directoryName, actionsDirectory, actionRuntime, target) {
502
510
  const entryPath = (0, import_path.resolve)(actionsDirectory, directoryName, "index.js");
503
511
  if (!(0, import_fs.existsSync)(entryPath)) {
504
512
  throw new Error(
@@ -513,7 +521,7 @@ function compileLocalAction(agentName, directoryName, actionsDirectory, actionRu
513
521
  write: false,
514
522
  format: "iife",
515
523
  globalName: "__orchaActionModule",
516
- platform: actionRuntime === "native" ? "node" : "neutral",
524
+ platform: actionRuntime === "native" && target === "node" ? "node" : "browser",
517
525
  target: "es2022",
518
526
  logLevel: "silent"
519
527
  });