orchajs 0.23.2 → 0.23.4

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.
@@ -31,9 +31,25 @@ export function createAmarsiaProjectMetadata(bundle, projectRoot) {
31
31
  };
32
32
  }
33
33
  function flattenAgents(agents) {
34
- const result = [];
34
+ const rootIds = new Set(Object.values(agents).map((manifest) => manifest.key));
35
+ const manifests = new Map();
36
+ const parentIds = new Map();
37
+ const orderedIds = [];
38
+ const traversed = new WeakSet();
35
39
  const visit = (manifest, parentExternalId) => {
36
- result.push(agentMetadata(manifest, parentExternalId));
40
+ if (!manifests.has(manifest.key)) {
41
+ manifests.set(manifest.key, manifest);
42
+ orderedIds.push(manifest.key);
43
+ }
44
+ if (parentExternalId) {
45
+ const parents = parentIds.get(manifest.key) ?? new Set();
46
+ parents.add(parentExternalId);
47
+ parentIds.set(manifest.key, parents);
48
+ }
49
+ if (traversed.has(manifest)) {
50
+ return;
51
+ }
52
+ traversed.add(manifest);
37
53
  for (const subagent of Object.values(manifest.subagents ?? {})) {
38
54
  visit(subagent, manifest.key);
39
55
  }
@@ -41,7 +57,17 @@ function flattenAgents(agents) {
41
57
  for (const manifest of Object.values(agents)) {
42
58
  visit(manifest);
43
59
  }
44
- return result;
60
+ return orderedIds.map((externalId) => {
61
+ const manifest = manifests.get(externalId);
62
+ if (!manifest) {
63
+ throw new Error(`Missing compiled agent "${externalId}".`);
64
+ }
65
+ const parents = parentIds.get(externalId);
66
+ const parentExternalId = !rootIds.has(externalId) && parents?.size === 1
67
+ ? parents.values().next().value
68
+ : undefined;
69
+ return agentMetadata(manifest, parentExternalId);
70
+ });
45
71
  }
46
72
  function agentMetadata(manifest, parentExternalId) {
47
73
  return {
package/dist/bin.js CHANGED
@@ -1,13 +1,122 @@
1
1
  #!/usr/bin/env node
2
- void import("./cli.js").catch((error) => {
2
+ import { spawn } from "node:child_process";
3
+ import { existsSync } from "node:fs";
4
+ import { resolve } from "node:path";
5
+ const TOOLING_PACKAGES = [
6
+ "@orchajs/playground-ui@^0.2.3",
7
+ "esbuild@^0.25",
8
+ "chokidar@^4",
9
+ "dotenv@^16",
10
+ ];
11
+ const BOOTSTRAP_ENV = "ORCHA_TOOLING_BOOTSTRAPPED";
12
+ void run();
13
+ async function run() {
14
+ try {
15
+ await import("./cli.js");
16
+ }
17
+ catch (error) {
18
+ if (process.argv[2] === "playground" &&
19
+ process.env[BOOTSTRAP_ENV] !== "1" &&
20
+ isMissingToolingError(error)) {
21
+ await bootstrapPlayground();
22
+ return;
23
+ }
24
+ reportError(error);
25
+ }
26
+ }
27
+ async function bootstrapPlayground() {
28
+ const packageManager = detectPackageManager();
29
+ const installation = installCommand(packageManager);
30
+ console.log(`[orcha] Installing development-only playground tooling with ${packageManager}...`);
31
+ const installCode = await runProcess(installation.command, installation.arguments);
32
+ if (installCode !== 0) {
33
+ process.exitCode = installCode;
34
+ return;
35
+ }
36
+ const retryCode = await runProcess(process.execPath, [process.argv[1], ...process.argv.slice(2)], {
37
+ ...process.env,
38
+ [BOOTSTRAP_ENV]: "1",
39
+ });
40
+ process.exitCode = retryCode;
41
+ }
42
+ function detectPackageManager() {
43
+ const userAgent = process.env.npm_config_user_agent;
44
+ if (userAgent?.startsWith("yarn/")) {
45
+ return "yarn";
46
+ }
47
+ if (userAgent?.startsWith("pnpm/")) {
48
+ return "pnpm";
49
+ }
50
+ if (userAgent?.startsWith("bun/")) {
51
+ return "bun";
52
+ }
53
+ if (existsSync(resolve("yarn.lock"))) {
54
+ return "yarn";
55
+ }
56
+ if (existsSync(resolve("pnpm-lock.yaml"))) {
57
+ return "pnpm";
58
+ }
59
+ if (existsSync(resolve("bun.lock")) ||
60
+ existsSync(resolve("bun.lockb"))) {
61
+ return "bun";
62
+ }
63
+ return "npm";
64
+ }
65
+ function installCommand(packageManager) {
66
+ switch (packageManager) {
67
+ case "yarn":
68
+ return {
69
+ command: executable("yarn"),
70
+ arguments: ["add", "--dev", ...TOOLING_PACKAGES],
71
+ };
72
+ case "pnpm":
73
+ return {
74
+ command: executable("pnpm"),
75
+ arguments: ["add", "--save-dev", ...TOOLING_PACKAGES],
76
+ };
77
+ case "bun":
78
+ return {
79
+ command: executable("bun"),
80
+ arguments: ["add", "--dev", ...TOOLING_PACKAGES],
81
+ };
82
+ default:
83
+ return {
84
+ command: executable("npm"),
85
+ arguments: ["install", "--save-dev", ...TOOLING_PACKAGES],
86
+ };
87
+ }
88
+ }
89
+ function executable(command) {
90
+ return process.platform === "win32" ? `${command}.cmd` : command;
91
+ }
92
+ function runProcess(command, arguments_, env = process.env) {
93
+ return new Promise((resolveProcess, reject) => {
94
+ const child = spawn(command, arguments_, {
95
+ cwd: process.cwd(),
96
+ env,
97
+ stdio: "inherit",
98
+ });
99
+ child.once("error", reject);
100
+ child.once("exit", (code, signal) => {
101
+ if (signal) {
102
+ process.kill(process.pid, signal);
103
+ return;
104
+ }
105
+ resolveProcess(code ?? 1);
106
+ });
107
+ });
108
+ }
109
+ function isMissingToolingError(error) {
110
+ const message = error instanceof Error ? error.message : String(error);
111
+ return ["@orchajs/playground-ui", "esbuild", "chokidar", "dotenv"].some((name) => message.includes(`"${name}"`) || message.includes(`'${name}'`));
112
+ }
113
+ function reportError(error) {
3
114
  const message = error instanceof Error ? error.message : String(error);
4
- const dependency = ["esbuild", "chokidar", "dotenv"].find((name) => message.includes(`"${name}"`) || message.includes(`'${name}'`));
5
- if (dependency) {
6
- console.error(`Orcha development tooling requires optional dependencies. Install them with:\n\n npm install --save-dev esbuild chokidar dotenv`);
115
+ if (isMissingToolingError(error)) {
116
+ console.error(`Orcha development tooling is missing. Run "orcha playground" to install the development-only playground dependencies automatically.`);
7
117
  }
8
118
  else {
9
119
  console.error(message);
10
120
  }
11
121
  process.exitCode = 1;
12
- });
13
- export {};
122
+ }
@@ -6,7 +6,6 @@ import { extname, isAbsolute, relative, resolve } from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import { createServer, } from "node:http";
8
8
  import { watch } from "chokidar";
9
- import { build } from "esbuild";
10
9
  import { orcha } from "../orcha.js";
11
10
  import { loadProject } from "../project-loader.js";
12
11
  import { listTests, runTests } from "../testing.js";
@@ -475,10 +474,12 @@ async function serveAsset(response, pathname, publicRoot) {
475
474
  response.end(await readFile(path));
476
475
  }
477
476
  async function buildPlaygroundAssets(projectRoot) {
478
- let entryPath;
477
+ let scriptPath;
478
+ let stylesheetPath;
479
479
  let logoPath;
480
480
  try {
481
- entryPath = fileURLToPath(import.meta.resolve("@orchajs/playground-ui/mount"));
481
+ scriptPath = fileURLToPath(import.meta.resolve("@orchajs/playground-ui/app.js"));
482
+ stylesheetPath = fileURLToPath(import.meta.resolve("@orchajs/playground-ui/app.css"));
482
483
  logoPath = fileURLToPath(import.meta.resolve("@orchajs/playground-ui/orcha-logo.svg"));
483
484
  }
484
485
  catch (error) {
@@ -487,20 +488,8 @@ async function buildPlaygroundAssets(projectRoot) {
487
488
  const publicRoot = resolve(projectRoot, ".orcha/playground");
488
489
  await mkdir(publicRoot, { recursive: true });
489
490
  await Promise.all([
490
- build({
491
- entryPoints: [entryPath],
492
- outfile: resolve(publicRoot, "app.js"),
493
- bundle: true,
494
- format: "esm",
495
- platform: "browser",
496
- target: ["chrome110", "firefox110", "safari16"],
497
- minify: true,
498
- sourcemap: false,
499
- legalComments: "none",
500
- define: {
501
- "process.env.NODE_ENV": JSON.stringify("production"),
502
- },
503
- }),
491
+ copyFile(scriptPath, resolve(publicRoot, "app.js")),
492
+ copyFile(stylesheetPath, resolve(publicRoot, "app.css")),
504
493
  copyFile(logoPath, resolve(publicRoot, "orcha-logo.svg")),
505
494
  writeFile(resolve(publicRoot, "index.html"), `<!doctype html>
506
495
  <html lang="en">
@@ -628,7 +628,7 @@ export class RuntimeAgent {
628
628
  reasoningLevel: this.#manifest.reasoningLevel,
629
629
  outputType: this.#manifest.outputType,
630
630
  outputSchema: this.#manifest.outputSchema,
631
- systemPrompt: buildSystemPrompt(this.#manifest, previousEvents, variables),
631
+ systemPrompt: buildSystemPrompt(this.#manifest, previousEvents, variables, availableToolNames),
632
632
  messages,
633
633
  tools: providerTools,
634
634
  publishOutput: (output) => {
@@ -1895,8 +1895,18 @@ function renderPrompt(template, variables) {
1895
1895
  return variables[name];
1896
1896
  });
1897
1897
  }
1898
- function buildSystemPrompt(manifest, events, variables) {
1898
+ function buildSystemPrompt(manifest, events, variables, availableActionNames) {
1899
1899
  const sections = [renderPrompt(manifest.systemPrompt, variables)];
1900
+ if (availableActionNames.length > 0) {
1901
+ sections.push([
1902
+ "## Available actions",
1903
+ "The following actions are available in this run. Invoke the relevant action when the workflow requires it; do not claim it is unavailable.",
1904
+ ...availableActionNames.map((name) => {
1905
+ const action = manifest.actions[name];
1906
+ return `- ${action.name}: ${action.description}`;
1907
+ }),
1908
+ ].join("\n"));
1909
+ }
1900
1910
  const skills = manifest.skills ?? {};
1901
1911
  const availableSkills = Object.values(skills);
1902
1912
  if (availableSkills.length > 0) {
@@ -55,9 +55,27 @@ function createAmarsiaProjectMetadata(bundle, projectRoot) {
55
55
  };
56
56
  }
57
57
  function flattenAgents(agents) {
58
- const result = [];
58
+ const rootIds = new Set(
59
+ Object.values(agents).map((manifest) => manifest.key)
60
+ );
61
+ const manifests = /* @__PURE__ */ new Map();
62
+ const parentIds = /* @__PURE__ */ new Map();
63
+ const orderedIds = [];
64
+ const traversed = /* @__PURE__ */ new WeakSet();
59
65
  const visit = (manifest, parentExternalId) => {
60
- result.push(agentMetadata(manifest, parentExternalId));
66
+ if (!manifests.has(manifest.key)) {
67
+ manifests.set(manifest.key, manifest);
68
+ orderedIds.push(manifest.key);
69
+ }
70
+ if (parentExternalId) {
71
+ const parents = parentIds.get(manifest.key) ?? /* @__PURE__ */ new Set();
72
+ parents.add(parentExternalId);
73
+ parentIds.set(manifest.key, parents);
74
+ }
75
+ if (traversed.has(manifest)) {
76
+ return;
77
+ }
78
+ traversed.add(manifest);
61
79
  for (const subagent of Object.values(manifest.subagents ?? {})) {
62
80
  visit(subagent, manifest.key);
63
81
  }
@@ -65,7 +83,15 @@ function flattenAgents(agents) {
65
83
  for (const manifest of Object.values(agents)) {
66
84
  visit(manifest);
67
85
  }
68
- return result;
86
+ return orderedIds.map((externalId) => {
87
+ const manifest = manifests.get(externalId);
88
+ if (!manifest) {
89
+ throw new Error(`Missing compiled agent "${externalId}".`);
90
+ }
91
+ const parents = parentIds.get(externalId);
92
+ const parentExternalId = !rootIds.has(externalId) && parents?.size === 1 ? parents.values().next().value : void 0;
93
+ return agentMetadata(manifest, parentExternalId);
94
+ });
69
95
  }
70
96
  function agentMetadata(manifest, parentExternalId) {
71
97
  return {
@@ -30,7 +30,6 @@ var import_path = require("path");
30
30
  var import_url = require("url");
31
31
  var import_http = require("http");
32
32
  var import_chokidar = require("chokidar");
33
- var import_esbuild = require("esbuild");
34
33
  var import_orcha = require("../orcha.js");
35
34
  var import_project_loader = require("../project-loader.js");
36
35
  var import_testing = require("../testing.js");
@@ -502,11 +501,15 @@ async function serveAsset(response, pathname, publicRoot) {
502
501
  response.end(await (0, import_promises.readFile)(path));
503
502
  }
504
503
  async function buildPlaygroundAssets(projectRoot) {
505
- let entryPath;
504
+ let scriptPath;
505
+ let stylesheetPath;
506
506
  let logoPath;
507
507
  try {
508
- entryPath = (0, import_url.fileURLToPath)(
509
- import_meta.resolve("@orchajs/playground-ui/mount")
508
+ scriptPath = (0, import_url.fileURLToPath)(
509
+ import_meta.resolve("@orchajs/playground-ui/app.js")
510
+ );
511
+ stylesheetPath = (0, import_url.fileURLToPath)(
512
+ import_meta.resolve("@orchajs/playground-ui/app.css")
510
513
  );
511
514
  logoPath = (0, import_url.fileURLToPath)(
512
515
  import_meta.resolve("@orchajs/playground-ui/orcha-logo.svg")
@@ -520,20 +523,8 @@ async function buildPlaygroundAssets(projectRoot) {
520
523
  const publicRoot = (0, import_path.resolve)(projectRoot, ".orcha/playground");
521
524
  await (0, import_promises.mkdir)(publicRoot, { recursive: true });
522
525
  await Promise.all([
523
- (0, import_esbuild.build)({
524
- entryPoints: [entryPath],
525
- outfile: (0, import_path.resolve)(publicRoot, "app.js"),
526
- bundle: true,
527
- format: "esm",
528
- platform: "browser",
529
- target: ["chrome110", "firefox110", "safari16"],
530
- minify: true,
531
- sourcemap: false,
532
- legalComments: "none",
533
- define: {
534
- "process.env.NODE_ENV": JSON.stringify("production")
535
- }
536
- }),
526
+ (0, import_promises.copyFile)(scriptPath, (0, import_path.resolve)(publicRoot, "app.js")),
527
+ (0, import_promises.copyFile)(stylesheetPath, (0, import_path.resolve)(publicRoot, "app.css")),
537
528
  (0, import_promises.copyFile)(logoPath, (0, import_path.resolve)(publicRoot, "orcha-logo.svg")),
538
529
  (0, import_promises.writeFile)(
539
530
  (0, import_path.resolve)(publicRoot, "index.html"),
@@ -826,7 +826,8 @@ class RuntimeAgent {
826
826
  systemPrompt: buildSystemPrompt(
827
827
  this.#manifest,
828
828
  previousEvents,
829
- variables
829
+ variables,
830
+ availableToolNames
830
831
  ),
831
832
  messages,
832
833
  tools: providerTools,
@@ -2197,8 +2198,20 @@ function renderPrompt(template, variables) {
2197
2198
  }
2198
2199
  );
2199
2200
  }
2200
- function buildSystemPrompt(manifest, events, variables) {
2201
+ function buildSystemPrompt(manifest, events, variables, availableActionNames) {
2201
2202
  const sections = [renderPrompt(manifest.systemPrompt, variables)];
2203
+ if (availableActionNames.length > 0) {
2204
+ sections.push(
2205
+ [
2206
+ "## Available actions",
2207
+ "The following actions are available in this run. Invoke the relevant action when the workflow requires it; do not claim it is unavailable.",
2208
+ ...availableActionNames.map((name) => {
2209
+ const action = manifest.actions[name];
2210
+ return `- ${action.name}: ${action.description}`;
2211
+ })
2212
+ ].join("\n")
2213
+ );
2214
+ }
2202
2215
  const skills = manifest.skills ?? {};
2203
2216
  const availableSkills = Object.values(skills);
2204
2217
  if (availableSkills.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orchajs",
3
- "version": "0.23.2",
3
+ "version": "0.23.4",
4
4
  "description": "A filesystem-convention, stateful agent framework for JavaScript.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -124,7 +124,7 @@
124
124
  "node": ">=18.20.8"
125
125
  },
126
126
  "peerDependencies": {
127
- "@orchajs/playground-ui": ">=0.2.3",
127
+ "@orchajs/playground-ui": ">=0.2.4",
128
128
  "@react-native-async-storage/async-storage": ">=2 <3",
129
129
  "@aws-sdk/client-bedrock-runtime": ">=3.864.0 <4",
130
130
  "@google/genai": ">=2.22.0 <3",