orchajs 0.20.3 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +13 -0
- package/dist/browser.d.ts +2 -0
- package/dist/browser.js +12 -0
- package/dist/cli.js +35 -9
- package/dist/compiler/build-project.d.ts +1 -0
- package/dist/compiler/build-project.js +75 -8
- package/dist/compiler/compile.d.ts +1 -1
- package/dist/compiler/compile.js +11 -9
- package/dist/file-content.js +42 -6
- package/dist/index.d.ts +1 -5
- package/dist/index.js +1 -2
- package/dist/integrations/esbuild.js +5 -2
- package/dist/integrations/expo.d.ts +1 -0
- package/dist/integrations/expo.js +1 -0
- package/dist/integrations/metro.d.ts +15 -0
- package/dist/integrations/metro.js +25 -0
- package/dist/integrations/next.d.ts +23 -0
- package/dist/integrations/next.js +53 -0
- package/dist/integrations/runtime-build.d.ts +4 -0
- package/dist/integrations/runtime-build.js +32 -0
- package/dist/integrations/vite.d.ts +23 -0
- package/dist/integrations/vite.js +32 -0
- package/dist/integrations/webpack.d.ts +24 -0
- package/dist/integrations/webpack.js +21 -0
- package/dist/orcha.js +17 -8
- package/dist/playground/server.js +57 -7
- package/dist/project-loader.js +3 -0
- package/dist/providers/browser.d.ts +2 -0
- package/dist/providers/browser.js +20 -0
- package/dist/react-native.d.ts +2 -0
- package/dist/react-native.js +12 -0
- package/dist/runtime/actions/browser-native.d.ts +3 -0
- package/dist/runtime/actions/browser-native.js +28 -0
- package/dist/runtime/actions/execute.d.ts +7 -0
- package/dist/runtime/actions/execute.js +9 -2
- package/dist/runtime/agent.d.ts +1 -0
- package/dist/runtime/agent.js +8 -5
- package/dist/runtime/compiler-hook.d.ts +5 -0
- package/dist/runtime/compiler-hook.js +8 -0
- package/dist/runtime/create-orcha.d.ts +2 -1
- package/dist/runtime/create-orcha.js +15 -19
- package/dist/runtime/platform-browser.d.ts +2 -0
- package/dist/runtime/platform-browser.js +15 -0
- package/dist/runtime/platform-node.d.ts +2 -0
- package/dist/runtime/platform-node.js +31 -0
- package/dist/runtime/platform-react-native.d.ts +2 -0
- package/dist/runtime/platform-react-native.js +15 -0
- package/dist/runtime/platform.d.ts +15 -0
- package/dist/runtime/platform.js +1 -0
- package/dist/runtime/random-id.d.ts +1 -0
- package/dist/runtime/random-id.js +26 -0
- package/dist/runtime-entry.d.ts +5 -0
- package/dist/runtime-entry.js +2 -0
- package/dist/storage/browser-indexeddb.d.ts +7 -16
- package/dist/storage/browser-indexeddb.js +102 -19
- package/dist/storage/react-native-jsonl.d.ts +7 -16
- package/dist/storage/react-native-jsonl.js +65 -19
- package/dist/types.d.ts +3 -1
- package/dist-cjs/browser.js +48 -0
- package/dist-cjs/compiler/build-project.js +97 -8
- package/dist-cjs/compiler/compile.js +17 -9
- package/dist-cjs/file-content.js +42 -7
- package/dist-cjs/index.js +4 -9
- package/dist-cjs/integrations/esbuild.js +6 -2
- package/dist-cjs/integrations/expo.js +29 -0
- package/dist-cjs/integrations/metro.js +51 -0
- package/dist-cjs/integrations/next.js +75 -0
- package/dist-cjs/integrations/runtime-build.js +70 -0
- package/dist-cjs/integrations/vite.js +57 -0
- package/dist-cjs/integrations/webpack.js +51 -0
- package/dist-cjs/orcha.js +17 -12
- package/dist-cjs/playground/server.js +62 -9
- package/dist-cjs/project-loader.js +10 -0
- package/dist-cjs/providers/browser.js +61 -0
- package/dist-cjs/react-native.js +48 -0
- package/dist-cjs/runtime/actions/browser-native.js +68 -0
- package/dist-cjs/runtime/actions/execute.js +12 -2
- package/dist-cjs/runtime/agent.js +8 -6
- package/dist-cjs/runtime/compiler-hook.js +37 -0
- package/dist-cjs/runtime/create-orcha.js +18 -21
- package/dist-cjs/runtime/platform-browser.js +48 -0
- package/dist-cjs/runtime/platform-node.js +59 -0
- package/dist-cjs/runtime/platform-react-native.js +45 -0
- package/dist-cjs/runtime/platform.js +17 -0
- package/dist-cjs/runtime/random-id.js +55 -0
- package/dist-cjs/runtime-entry.js +34 -0
- package/dist-cjs/storage/browser-indexeddb.js +102 -5
- package/dist-cjs/storage/react-native-jsonl.js +73 -5
- package/dist-cjs/types/react-native-async-storage.d.js +2 -0
- package/package.json +69 -9
- package/dist/playground/public/app.css +0 -1
- package/dist/playground/public/app.js +0 -31
- package/dist/playground/public/index.html +0 -15
- package/dist/playground/public/orcha-logo.svg +0 -4
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { generatedBundlePath, queueRuntimeBuild, watchRuntimeTargets, } from "./runtime-build.js";
|
|
3
|
+
export async function withOrchaMetro(configuration, options = {}) {
|
|
4
|
+
const projectRoot = resolve(options.projectRoot ?? process.cwd());
|
|
5
|
+
await queueRuntimeBuild(projectRoot, "react-native");
|
|
6
|
+
if (process.env.NODE_ENV !== "production") {
|
|
7
|
+
watchRuntimeTargets(projectRoot, ["react-native"]);
|
|
8
|
+
}
|
|
9
|
+
const existingResolver = configuration.resolver?.resolveRequest;
|
|
10
|
+
return {
|
|
11
|
+
...configuration,
|
|
12
|
+
resolver: {
|
|
13
|
+
...configuration.resolver,
|
|
14
|
+
resolveRequest(context, moduleName, platform) {
|
|
15
|
+
const requestedModule = moduleName === "orchajs"
|
|
16
|
+
? generatedBundlePath(projectRoot, "react-native")
|
|
17
|
+
: moduleName;
|
|
18
|
+
if (existingResolver) {
|
|
19
|
+
return existingResolver(context, requestedModule, platform);
|
|
20
|
+
}
|
|
21
|
+
return context.resolveRequest(context, requestedModule, platform);
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface OrchaNextOptions {
|
|
2
|
+
projectRoot?: string;
|
|
3
|
+
}
|
|
4
|
+
interface NextWebpackContext {
|
|
5
|
+
isServer: boolean;
|
|
6
|
+
nextRuntime?: string;
|
|
7
|
+
}
|
|
8
|
+
interface WebpackConfiguration {
|
|
9
|
+
plugins?: unknown[];
|
|
10
|
+
resolve?: {
|
|
11
|
+
alias?: Record<string, unknown>;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
interface NextConfiguration {
|
|
15
|
+
turbopack?: {
|
|
16
|
+
resolveAlias?: Record<string, unknown>;
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
};
|
|
19
|
+
webpack?: (configuration: WebpackConfiguration, context: NextWebpackContext) => WebpackConfiguration;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
export declare function withOrcha<T extends NextConfiguration>(configuration?: T, options?: OrchaNextOptions): Promise<T>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { generatedBundlePath, queueRuntimeBuild, watchRuntimeTargets, } from "./runtime-build.js";
|
|
3
|
+
import { OrchaWebpackPlugin } from "./webpack.js";
|
|
4
|
+
export async function withOrcha(configuration = {}, options = {}) {
|
|
5
|
+
const projectRoot = resolve(options.projectRoot ?? process.cwd());
|
|
6
|
+
await queueRuntimeBuild(projectRoot, "browser");
|
|
7
|
+
await queueRuntimeBuild(projectRoot, "node");
|
|
8
|
+
if (process.env.NODE_ENV !== "production") {
|
|
9
|
+
watchRuntimeTargets(projectRoot, ["browser", "node"]);
|
|
10
|
+
}
|
|
11
|
+
const existingWebpack = configuration.webpack;
|
|
12
|
+
return {
|
|
13
|
+
...configuration,
|
|
14
|
+
turbopack: {
|
|
15
|
+
...configuration.turbopack,
|
|
16
|
+
resolveAlias: {
|
|
17
|
+
...configuration.turbopack?.resolveAlias,
|
|
18
|
+
orchajs: {
|
|
19
|
+
browser: generatedBundlePath(projectRoot, "browser"),
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
webpack(webpackConfiguration, context) {
|
|
24
|
+
const target = nextTarget(context);
|
|
25
|
+
if (target === "node") {
|
|
26
|
+
return existingWebpack
|
|
27
|
+
? existingWebpack(webpackConfiguration, context)
|
|
28
|
+
: webpackConfiguration;
|
|
29
|
+
}
|
|
30
|
+
const plugin = new OrchaWebpackPlugin({
|
|
31
|
+
projectRoot,
|
|
32
|
+
target,
|
|
33
|
+
});
|
|
34
|
+
webpackConfiguration.resolve ??= {};
|
|
35
|
+
webpackConfiguration.resolve.alias = {
|
|
36
|
+
...webpackConfiguration.resolve.alias,
|
|
37
|
+
orchajs$: plugin.bundlePath,
|
|
38
|
+
};
|
|
39
|
+
webpackConfiguration.plugins = [
|
|
40
|
+
...(webpackConfiguration.plugins ?? []),
|
|
41
|
+
plugin,
|
|
42
|
+
];
|
|
43
|
+
return existingWebpack
|
|
44
|
+
? existingWebpack(webpackConfiguration, context)
|
|
45
|
+
: webpackConfiguration;
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function nextTarget(context) {
|
|
50
|
+
return context.isServer && context.nextRuntime !== "edge"
|
|
51
|
+
? "node"
|
|
52
|
+
: "browser";
|
|
53
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type RuntimeBuildTarget = "node" | "browser" | "react-native";
|
|
2
|
+
export declare function generatedBundlePath(projectRoot: string, target: RuntimeBuildTarget): string;
|
|
3
|
+
export declare function queueRuntimeBuild(projectRoot: string, target: RuntimeBuildTarget): Promise<void>;
|
|
4
|
+
export declare function watchRuntimeTargets(projectRoot: string, targets: RuntimeBuildTarget[]): void;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { watch } from "chokidar";
|
|
3
|
+
import { buildProject } from "../compiler/build-project.js";
|
|
4
|
+
import { loadProjectEnvironment } from "../env.js";
|
|
5
|
+
let buildQueue = Promise.resolve();
|
|
6
|
+
const watchedTargets = new Set();
|
|
7
|
+
export function generatedBundlePath(projectRoot, target) {
|
|
8
|
+
const fileName = target === "node" ? "bundle.js" : `bundle.${target}.js`;
|
|
9
|
+
return resolve(projectRoot, ".orcha/dist", fileName);
|
|
10
|
+
}
|
|
11
|
+
export function queueRuntimeBuild(projectRoot, target) {
|
|
12
|
+
const build = buildQueue.then(async () => {
|
|
13
|
+
loadProjectEnvironment(projectRoot);
|
|
14
|
+
await buildProject({ projectRoot, target });
|
|
15
|
+
});
|
|
16
|
+
buildQueue = build.catch(() => undefined);
|
|
17
|
+
return build;
|
|
18
|
+
}
|
|
19
|
+
export function watchRuntimeTargets(projectRoot, targets) {
|
|
20
|
+
const key = `${projectRoot}:${targets.join(",")}`;
|
|
21
|
+
if (watchedTargets.has(key)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
watchedTargets.add(key);
|
|
25
|
+
let timer;
|
|
26
|
+
watch(resolve(projectRoot, "orcha"), { ignoreInitial: true }).on("all", () => {
|
|
27
|
+
clearTimeout(timer);
|
|
28
|
+
timer = setTimeout(() => {
|
|
29
|
+
void targets.reduce((pending, target) => pending.then(() => queueRuntimeBuild(projectRoot, target)), Promise.resolve());
|
|
30
|
+
}, 75);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface OrchaVitePluginOptions {
|
|
2
|
+
projectRoot?: string;
|
|
3
|
+
}
|
|
4
|
+
export declare function orchaVitePlugin(options?: OrchaVitePluginOptions): {
|
|
5
|
+
name: string;
|
|
6
|
+
enforce: "pre";
|
|
7
|
+
configResolved(config: {
|
|
8
|
+
root: string;
|
|
9
|
+
}): void;
|
|
10
|
+
buildStart(): Promise<void>;
|
|
11
|
+
configureServer(server: {
|
|
12
|
+
watcher: {
|
|
13
|
+
add(path: string): void;
|
|
14
|
+
on(event: "all", listener: (_event: string, path: string) => void): void;
|
|
15
|
+
};
|
|
16
|
+
ws: {
|
|
17
|
+
send(message: {
|
|
18
|
+
type: "full-reload";
|
|
19
|
+
}): void;
|
|
20
|
+
};
|
|
21
|
+
}): void;
|
|
22
|
+
resolveId(source: string): string | undefined;
|
|
23
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { resolve, sep } from "node:path";
|
|
2
|
+
import { generatedBundlePath, queueRuntimeBuild, } from "./runtime-build.js";
|
|
3
|
+
export function orchaVitePlugin(options = {}) {
|
|
4
|
+
let projectRoot = resolve(options.projectRoot ?? process.cwd());
|
|
5
|
+
return {
|
|
6
|
+
name: "orchajs",
|
|
7
|
+
enforce: "pre",
|
|
8
|
+
configResolved(config) {
|
|
9
|
+
projectRoot = resolve(options.projectRoot ?? config.root);
|
|
10
|
+
},
|
|
11
|
+
async buildStart() {
|
|
12
|
+
await queueRuntimeBuild(projectRoot, "browser");
|
|
13
|
+
},
|
|
14
|
+
configureServer(server) {
|
|
15
|
+
const registryDirectory = resolve(projectRoot, "orcha");
|
|
16
|
+
server.watcher.add(registryDirectory);
|
|
17
|
+
server.watcher.on("all", (_event, path) => {
|
|
18
|
+
if (path === registryDirectory ||
|
|
19
|
+
path.startsWith(`${registryDirectory}${sep}`)) {
|
|
20
|
+
void queueRuntimeBuild(projectRoot, "browser").then(() => {
|
|
21
|
+
server.ws.send({ type: "full-reload" });
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
resolveId(source) {
|
|
27
|
+
return source === "orchajs"
|
|
28
|
+
? generatedBundlePath(projectRoot, "browser")
|
|
29
|
+
: undefined;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type RuntimeBuildTarget } from "./runtime-build.js";
|
|
2
|
+
export interface OrchaWebpackPluginOptions {
|
|
3
|
+
projectRoot?: string;
|
|
4
|
+
target?: RuntimeBuildTarget;
|
|
5
|
+
}
|
|
6
|
+
interface WebpackCompiler {
|
|
7
|
+
hooks: {
|
|
8
|
+
beforeCompile: {
|
|
9
|
+
tapPromise(name: string, callback: () => Promise<void>): void;
|
|
10
|
+
};
|
|
11
|
+
afterCompile: {
|
|
12
|
+
tap(name: string, callback: (compilation: {
|
|
13
|
+
contextDependencies: Set<string>;
|
|
14
|
+
}) => void): void;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export declare class OrchaWebpackPlugin {
|
|
19
|
+
#private;
|
|
20
|
+
constructor(options?: OrchaWebpackPluginOptions);
|
|
21
|
+
get bundlePath(): string;
|
|
22
|
+
apply(compiler: WebpackCompiler): void;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { generatedBundlePath, queueRuntimeBuild, } from "./runtime-build.js";
|
|
3
|
+
export class OrchaWebpackPlugin {
|
|
4
|
+
#projectRoot;
|
|
5
|
+
#target;
|
|
6
|
+
constructor(options = {}) {
|
|
7
|
+
this.#projectRoot = resolve(options.projectRoot ?? process.cwd());
|
|
8
|
+
this.#target = options.target ?? "browser";
|
|
9
|
+
}
|
|
10
|
+
get bundlePath() {
|
|
11
|
+
return generatedBundlePath(this.#projectRoot, this.#target);
|
|
12
|
+
}
|
|
13
|
+
apply(compiler) {
|
|
14
|
+
compiler.hooks.beforeCompile.tapPromise("orchajs", async () => {
|
|
15
|
+
await queueRuntimeBuild(this.#projectRoot, this.#target);
|
|
16
|
+
});
|
|
17
|
+
compiler.hooks.afterCompile.tap("orchajs", (compilation) => {
|
|
18
|
+
compilation.contextDependencies.add(resolve(this.#projectRoot, "orcha"));
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
package/dist/orcha.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
-
import { compileRegistry } from "./compiler/compile.js";
|
|
4
3
|
import { generateProviderResponse } from "./providers/index.js";
|
|
5
|
-
import { setSandboxRuntimeLoader } from "./runtime/actions/execute.js";
|
|
4
|
+
import { setNativeRuntimeLoader, setSandboxRuntimeLoader, } from "./runtime/actions/execute.js";
|
|
5
|
+
import { executeNativeAction } from "./runtime/actions/native.js";
|
|
6
|
+
import { getRegistryCompiler } from "./runtime/compiler-hook.js";
|
|
6
7
|
import { createOrcha } from "./runtime/create-orcha.js";
|
|
8
|
+
import { nodeRuntimePlatform } from "./runtime/platform-node.js";
|
|
9
|
+
setNativeRuntimeLoader(async () => ({ executeNativeAction }));
|
|
7
10
|
setSandboxRuntimeLoader(async () => {
|
|
8
11
|
const modulePath = "./runtime/actions/sandbox.js";
|
|
9
12
|
return import(modulePath);
|
|
@@ -12,13 +15,16 @@ export const orcha = createOrcha((configuration) => {
|
|
|
12
15
|
const projectRoot = resolve(configuration.root ??
|
|
13
16
|
process.env.ORCHA_PROJECT_ROOT ??
|
|
14
17
|
process.cwd());
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
20
|
-
|
|
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 =
|
|
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 {
|
|
6
|
-
import {
|
|
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.
|
|
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":
|
package/dist/project-loader.js
CHANGED
|
@@ -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,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,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
|
-
|
|
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") {
|
package/dist/runtime/agent.d.ts
CHANGED
package/dist/runtime/agent.js
CHANGED
|
@@ -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 ??
|
|
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 ??
|
|
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;
|
|
@@ -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;
|