@axlsdk/studio 0.11.0 → 0.11.2

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/dist/cli.js CHANGED
@@ -1,12 +1,17 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ CONFIG_CANDIDATES,
4
+ findConfig,
5
+ importModule,
6
+ parseArgs
7
+ } from "./chunk-6VDX5CRP.js";
2
8
  import {
3
9
  createServer
4
10
  } from "./chunk-PUKOAXB3.js";
5
11
 
6
12
  // src/cli.ts
7
- import { resolve as resolve2, extname as extname2 } from "path";
8
- import { existsSync as existsSync2 } from "fs";
9
- import { pathToFileURL } from "url";
13
+ import { resolve, extname } from "path";
14
+ import { existsSync } from "fs";
10
15
  import { serve } from "@hono/node-server";
11
16
  import { createNodeWebSocket } from "@hono/node-ws";
12
17
 
@@ -16,59 +21,6 @@ function resolveRuntime(mod) {
16
21
  return def?.default ?? def ?? mod.runtime;
17
22
  }
18
23
 
19
- // src/cli-utils.ts
20
- import { resolve, extname } from "path";
21
- import { existsSync } from "fs";
22
- var CONFIG_CANDIDATES = [
23
- "axl.config.mts",
24
- "axl.config.ts",
25
- "axl.config.mjs",
26
- "axl.config.js"
27
- ];
28
- function findConfig(cwd) {
29
- for (const name of CONFIG_CANDIDATES) {
30
- const p = resolve(cwd, name);
31
- if (existsSync(p)) return p;
32
- }
33
- return void 0;
34
- }
35
- function parseArgs(argv) {
36
- let port = 4400;
37
- let config;
38
- let open = false;
39
- let help = false;
40
- let conditions = [];
41
- for (let i = 2; i < argv.length; i++) {
42
- const arg = argv[i];
43
- if (arg === "--port" && argv[i + 1]) {
44
- port = parseInt(argv[i + 1], 10);
45
- i++;
46
- } else if (arg === "--config" && argv[i + 1]) {
47
- config = argv[i + 1];
48
- i++;
49
- } else if (arg === "--conditions" && argv[i + 1]) {
50
- conditions = argv[i + 1].split(",").map((c) => c.trim()).filter(Boolean);
51
- i++;
52
- } else if (arg === "--open") {
53
- open = true;
54
- } else if (arg === "--help" || arg === "-h") {
55
- help = true;
56
- }
57
- }
58
- const result = { port, config, open, help, conditions };
59
- if (isNaN(port) || port < 1 || port > 65535) {
60
- result.portError = `Invalid port: ${port}. Must be between 1 and 65535.`;
61
- }
62
- return result;
63
- }
64
- function needsEsmForcing(configPath) {
65
- const ext = extname(configPath);
66
- return ext === ".ts" || ext === ".tsx";
67
- }
68
- function needsTsxLoader(configPath) {
69
- return /\.[mc]?tsx?$/.test(configPath);
70
- }
71
-
72
24
  // src/cli.ts
73
25
  async function main() {
74
26
  const args = parseArgs(process.argv);
@@ -99,8 +51,8 @@ Tip: Use .mts for configs with top-level await or in projects without "type": "m
99
51
  }
100
52
  let configPath;
101
53
  if (args.config) {
102
- configPath = resolve2(process.cwd(), args.config);
103
- if (!existsSync2(configPath)) {
54
+ configPath = resolve(process.cwd(), args.config);
55
+ if (!existsSync(configPath)) {
104
56
  console.error(`Config file not found: ${configPath}`);
105
57
  process.exit(1);
106
58
  }
@@ -113,42 +65,6 @@ Tip: Use .mts for configs with top-level await or in projects without "type": "m
113
65
  }
114
66
  configPath = found;
115
67
  }
116
- if (needsTsxLoader(configPath)) {
117
- let tsxLoaded = false;
118
- try {
119
- const tsxEsm = await import("tsx/esm/api");
120
- tsxEsm.register();
121
- tsxLoaded = true;
122
- } catch {
123
- }
124
- try {
125
- const tsxCjs = await import("tsx/cjs/api");
126
- tsxCjs.register();
127
- tsxLoaded = true;
128
- } catch {
129
- }
130
- if (!tsxLoaded) {
131
- console.warn(
132
- `[axl-studio] Warning: tsx is not installed. TypeScript config files require tsx as a dependency.
133
- Install it with: npm install -D tsx`
134
- );
135
- }
136
- }
137
- if (needsEsmForcing(configPath)) {
138
- try {
139
- const nodeModule = await import("module");
140
- const configUrl = pathToFileURL(configPath).href;
141
- const hookCode = [
142
- `export async function resolve(specifier, context, nextResolve) {`,
143
- ` const result = await nextResolve(specifier, context);`,
144
- ` if (result.url === ${JSON.stringify(configUrl)}) result.format = 'module';`,
145
- ` return result;`,
146
- `}`
147
- ].join("\n");
148
- nodeModule.register(`data:text/javascript,${encodeURIComponent(hookCode)}`);
149
- } catch {
150
- }
151
- }
152
68
  if (args.conditions.length > 0) {
153
69
  try {
154
70
  const nodeModule = await import("module");
@@ -168,9 +84,9 @@ Tip: Use .mts for configs with top-level await or in projects without "type": "m
168
84
  }
169
85
  console.log(`[axl-studio] Loading config from ${configPath}`);
170
86
  let runtime;
171
- const ext = extname2(configPath);
87
+ const ext = extname(configPath);
172
88
  try {
173
- const mod = await import(pathToFileURL(configPath).href);
89
+ const mod = await importModule(configPath, import.meta.url);
174
90
  runtime = resolveRuntime(mod);
175
91
  if (!runtime || typeof runtime.execute !== "function") {
176
92
  console.error(`Config must export a default AxlRuntime instance.`);
@@ -192,10 +108,8 @@ Tip: Use .mts for configs with top-level await or in projects without "type": "m
192
108
  )) {
193
109
  console.error(`[axl-studio] Config failed to load due to a CJS/ESM compatibility issue.`);
194
110
  if (ext === ".ts" || ext === ".tsx") {
195
- const mtsPath = configPath.slice(0, -ext.length) + ".mts";
196
111
  console.error(
197
- ` Tip: rename to .mts to force ESM format:
198
- mv ${configPath} ${mtsPath}`
112
+ ` Tip: try renaming to .mts to force ESM format, or ensure tsx is installed and up to date.`
199
113
  );
200
114
  } else {
201
115
  console.error(` Tip: add "type": "module" to your package.json.`);
@@ -205,8 +119,8 @@ Tip: Use .mts for configs with top-level await or in projects without "type": "m
205
119
  console.error(`Failed to load config:`, err);
206
120
  process.exit(1);
207
121
  }
208
- const staticRoot = resolve2(import.meta.dirname ?? __dirname, "client");
209
- const hasStaticAssets = existsSync2(resolve2(staticRoot, "index.html"));
122
+ const staticRoot = resolve(import.meta.dirname ?? __dirname, "client");
123
+ const hasStaticAssets = existsSync(resolve(staticRoot, "index.html"));
210
124
  const { app, createWsHandlers } = createServer({
211
125
  runtime,
212
126
  staticRoot: hasStaticAssets ? staticRoot : void 0
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/resolve-runtime.ts","../src/cli-utils.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { resolve, extname } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { pathToFileURL } from 'node:url';\nimport { serve } from '@hono/node-server';\nimport { createNodeWebSocket } from '@hono/node-ws';\nimport { createServer } from './server/index.js';\nimport { resolveRuntime } from './resolve-runtime.js';\nimport {\n parseArgs,\n findConfig,\n needsEsmForcing,\n needsTsxLoader,\n CONFIG_CANDIDATES,\n} from './cli-utils.js';\n\n// ── Main ────────────────────────────────────────────────────────────\n\nasync function main() {\n const args = parseArgs(process.argv);\n\n if (args.help) {\n console.log(`\nAxl Studio — Local development UI for Axl agents and workflows\n\nUsage:\n axl-studio [options]\n\nOptions:\n --port <number> Server port (default: 4400)\n --config <path> Path to config file (default: auto-detect)\n --conditions <list> Comma-separated Node.js import conditions (e.g., development)\n --open Auto-open browser\n -h, --help Show this help message\n\nConfig auto-detection order:\n ${CONFIG_CANDIDATES.join(' → ')}\n\nTip: Use .mts for configs with top-level await or in projects without \"type\": \"module\".\n`);\n process.exit(0);\n }\n\n if (args.portError) {\n console.error(args.portError);\n process.exit(1);\n }\n\n // Resolve config path: explicit --config or auto-detect\n let configPath: string;\n if (args.config) {\n configPath = resolve(process.cwd(), args.config);\n if (!existsSync(configPath)) {\n console.error(`Config file not found: ${configPath}`);\n process.exit(1);\n }\n } else {\n const found = findConfig(process.cwd());\n if (!found) {\n console.error(`No config file found. Searched for: ${CONFIG_CANDIDATES.join(', ')}`);\n console.error(`Create an axl.config.mts that exports a default AxlRuntime instance.`);\n process.exit(1);\n }\n configPath = found;\n }\n\n // Register tsx as a TypeScript loader so .ts config files can be imported.\n // Both ESM and CJS hooks are needed: if the config's nearest package.json\n // lacks \"type\": \"module\", Node routes the import through CJS where the ESM\n // hook alone can't intercept .ts resolution.\n if (needsTsxLoader(configPath)) {\n let tsxLoaded = false;\n try {\n const tsxEsm = await import('tsx/esm/api');\n tsxEsm.register();\n tsxLoaded = true;\n } catch {\n // ESM hook not available\n }\n try {\n const tsxCjs = await import('tsx/cjs/api');\n tsxCjs.register();\n tsxLoaded = true;\n } catch {\n // CJS hook not available\n }\n if (!tsxLoaded) {\n console.warn(\n `[axl-studio] Warning: tsx is not installed. TypeScript config files require tsx as a dependency.\\n` +\n ` Install it with: npm install -D tsx`,\n );\n }\n }\n\n // Force ESM format for .ts/.tsx config files so top-level await works\n // regardless of the nearest package.json \"type\" field. Without this,\n // tsx decides CJS vs ESM based on package.json — CJS doesn't support\n // top-level await. We register a resolve hook after tsx that overrides\n // the format for the config file specifically.\n // .mts/.cts have explicit format built into their extension; .mjs/.cjs\n // are plain JS with explicit format. Only .ts/.tsx are ambiguous.\n if (needsEsmForcing(configPath)) {\n try {\n const nodeModule = await import('node:module');\n const configUrl = pathToFileURL(configPath).href;\n const hookCode = [\n `export async function resolve(specifier, context, nextResolve) {`,\n ` const result = await nextResolve(specifier, context);`,\n ` if (result.url === ${JSON.stringify(configUrl)}) result.format = 'module';`,\n ` return result;`,\n `}`,\n ].join('\\n');\n nodeModule.register(`data:text/javascript,${encodeURIComponent(hookCode)}`);\n } catch {\n // module.register() not available (Node < 20.6) — fall through,\n // error handler below will suggest .mts if loading fails\n }\n }\n\n // Register custom import conditions (e.g., --conditions development).\n // In monorepos, package.json \"exports\" often use the \"development\" condition\n // to point at source (.ts) instead of built dist. Without this, Studio\n // configs that import workspace packages resolve to dist files, which may\n // not exist or be stale.\n if (args.conditions.length > 0) {\n try {\n const nodeModule = await import('node:module');\n const hookCode = [\n `const extra = ${JSON.stringify(args.conditions)};`,\n `export async function resolve(specifier, context, nextResolve) {`,\n ` return nextResolve(specifier, {`,\n ` ...context,`,\n ` conditions: [...new Set([...context.conditions, ...extra])],`,\n ` });`,\n `}`,\n ].join('\\n');\n nodeModule.register(`data:text/javascript,${encodeURIComponent(hookCode)}`);\n } catch {\n console.warn(`[axl-studio] Warning: --conditions requires Node.js 20.6+`);\n }\n }\n\n console.log(`[axl-studio] Loading config from ${configPath}`);\n\n // Import the user's config\n let runtime: import('@axlsdk/axl').AxlRuntime;\n const ext = extname(configPath);\n try {\n const mod = await import(pathToFileURL(configPath).href);\n // resolveRuntime handles ESM default, CJS-to-ESM interop, and named exports\n runtime = resolveRuntime(mod) as typeof runtime;\n\n if (!runtime || typeof runtime.execute !== 'function') {\n console.error(`Config must export a default AxlRuntime instance.`);\n if (runtime) {\n const keys = Object.keys(runtime as object)\n .slice(0, 5)\n .join(', ');\n console.error(` Got: ${typeof runtime}${keys ? ` with keys: { ${keys} }` : ''}`);\n }\n console.error(\n `Example:\\n import { AxlRuntime } from '@axlsdk/axl';\\n export default new AxlRuntime({ ... });`,\n );\n process.exit(1);\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (\n /Cannot use import statement|Unexpected reserved word|top-level await|exports is not defined/.test(\n msg,\n )\n ) {\n console.error(`[axl-studio] Config failed to load due to a CJS/ESM compatibility issue.`);\n if (ext === '.ts' || ext === '.tsx') {\n const mtsPath = configPath.slice(0, -ext.length) + '.mts';\n console.error(\n ` Tip: rename to .mts to force ESM format:\\n` + ` mv ${configPath} ${mtsPath}`,\n );\n } else {\n console.error(` Tip: add \"type\": \"module\" to your package.json.`);\n }\n console.error();\n }\n console.error(`Failed to load config:`, err);\n process.exit(1);\n }\n\n // Determine static root for pre-built SPA\n const staticRoot = resolve(import.meta.dirname ?? __dirname, 'client');\n const hasStaticAssets = existsSync(resolve(staticRoot, 'index.html'));\n\n const { app, createWsHandlers } = createServer({\n runtime,\n staticRoot: hasStaticAssets ? staticRoot : undefined,\n });\n\n // Set up WebSocket\n const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app });\n const wsHandlers = createWsHandlers();\n app.get(\n '/ws',\n upgradeWebSocket(() => wsHandlers),\n );\n\n const server = serve(\n {\n fetch: app.fetch,\n port: args.port,\n },\n (info) => {\n console.log(`[axl-studio] Server running at http://localhost:${info.port}`);\n console.log(`[axl-studio] Workflows: ${runtime.getWorkflowNames().join(', ') || '(none)'}`);\n console.log(\n `[axl-studio] Agents: ${\n runtime\n .getAgents()\n .map((a) => a._name)\n .join(', ') || '(none)'\n }`,\n );\n console.log(\n `[axl-studio] Tools: ${\n runtime\n .getTools()\n .map((t) => t.name)\n .join(', ') || '(none)'\n }`,\n );\n\n if (!hasStaticAssets) {\n console.log(\n `[axl-studio] No pre-built UI found. Run 'pnpm build:client' or use Vite dev server on port 4401.`,\n );\n }\n },\n );\n\n injectWebSocket(server);\n\n // Auto-open browser\n if (args.open) {\n const url = `http://localhost:${args.port}`;\n const { exec } = await import('node:child_process');\n const cmd =\n process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';\n exec(`${cmd} ${url}`);\n }\n\n // Graceful shutdown\n const shutdown = async () => {\n console.log('\\n[axl-studio] Shutting down...');\n await runtime.shutdown().catch(() => {});\n process.exit(0);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n}\n\nmain().catch((err) => {\n console.error('[axl-studio] Fatal error:', err);\n process.exit(1);\n});\n","/**\n * Resolve the AxlRuntime from a dynamically imported config module.\n * Handles ESM default exports, CJS-to-ESM interop wrapping, and named exports.\n *\n * Module shapes handled:\n * - ESM `export default runtime` → mod.default is the runtime\n * - CJS compiled from `export default runtime` → mod.default.default is the runtime\n * - CJS `module.exports = runtime` → mod.default is the runtime\n * - Named `export { runtime }` → mod.runtime is the runtime\n */\nexport function resolveRuntime(mod: Record<string, unknown>): unknown {\n const def = mod.default as Record<string, unknown> | undefined;\n return def?.default ?? def ?? mod.runtime;\n}\n","import { resolve, extname } from 'node:path';\nimport { existsSync } from 'node:fs';\n\n// ── Config auto-detection ──────────────────────────────────────────\n\nexport const CONFIG_CANDIDATES = [\n 'axl.config.mts',\n 'axl.config.ts',\n 'axl.config.mjs',\n 'axl.config.js',\n];\n\nexport function findConfig(cwd: string): string | undefined {\n for (const name of CONFIG_CANDIDATES) {\n const p = resolve(cwd, name);\n if (existsSync(p)) return p;\n }\n return undefined;\n}\n\n// ── Parse CLI args ──────────────────────────────────────────────────\n\nexport interface CliArgs {\n port: number;\n config?: string;\n open: boolean;\n conditions: string[];\n help: boolean;\n portError?: string;\n}\n\nexport function parseArgs(argv: string[]): CliArgs {\n let port = 4400;\n let config: string | undefined;\n let open = false;\n let help = false;\n let conditions: string[] = [];\n\n for (let i = 2; i < argv.length; i++) {\n const arg = argv[i];\n if (arg === '--port' && argv[i + 1]) {\n port = parseInt(argv[i + 1], 10);\n i++;\n } else if (arg === '--config' && argv[i + 1]) {\n config = argv[i + 1];\n i++;\n } else if (arg === '--conditions' && argv[i + 1]) {\n conditions = argv[i + 1]\n .split(',')\n .map((c) => c.trim())\n .filter(Boolean);\n i++;\n } else if (arg === '--open') {\n open = true;\n } else if (arg === '--help' || arg === '-h') {\n help = true;\n }\n }\n\n const result: CliArgs = { port, config, open, help, conditions };\n\n if (isNaN(port) || port < 1 || port > 65535) {\n result.portError = `Invalid port: ${port}. Must be between 1 and 65535.`;\n }\n\n return result;\n}\n\n// ── Extension helpers ──────────────────────────────────────────────\n\n/**\n * Returns true if the config path has an ambiguous TypeScript extension (.ts/.tsx)\n * that needs ESM forcing. Explicit extensions (.mts/.cts) are excluded.\n */\nexport function needsEsmForcing(configPath: string): boolean {\n const ext = extname(configPath);\n return ext === '.ts' || ext === '.tsx';\n}\n\n/**\n * Returns true if the config path is a TypeScript file that needs tsx loader hooks.\n */\nexport function needsTsxLoader(configPath: string): boolean {\n return /\\.[mc]?tsx?$/.test(configPath);\n}\n"],"mappings":"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","names":["resolve","extname","existsSync","resolve","existsSync","extname"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/resolve-runtime.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { resolve, extname } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { serve } from '@hono/node-server';\nimport { createNodeWebSocket } from '@hono/node-ws';\nimport { createServer } from './server/index.js';\nimport { resolveRuntime } from './resolve-runtime.js';\nimport { parseArgs, findConfig, importModule, CONFIG_CANDIDATES } from './cli-utils.js';\n\n// ── Main ────────────────────────────────────────────────────────────\n\nasync function main() {\n const args = parseArgs(process.argv);\n\n if (args.help) {\n console.log(`\nAxl Studio — Local development UI for Axl agents and workflows\n\nUsage:\n axl-studio [options]\n\nOptions:\n --port <number> Server port (default: 4400)\n --config <path> Path to config file (default: auto-detect)\n --conditions <list> Comma-separated Node.js import conditions (e.g., development)\n --open Auto-open browser\n -h, --help Show this help message\n\nConfig auto-detection order:\n ${CONFIG_CANDIDATES.join(' → ')}\n\nTip: Use .mts for configs with top-level await or in projects without \"type\": \"module\".\n`);\n process.exit(0);\n }\n\n if (args.portError) {\n console.error(args.portError);\n process.exit(1);\n }\n\n // Resolve config path: explicit --config or auto-detect\n let configPath: string;\n if (args.config) {\n configPath = resolve(process.cwd(), args.config);\n if (!existsSync(configPath)) {\n console.error(`Config file not found: ${configPath}`);\n process.exit(1);\n }\n } else {\n const found = findConfig(process.cwd());\n if (!found) {\n console.error(`No config file found. Searched for: ${CONFIG_CANDIDATES.join(', ')}`);\n console.error(`Create an axl.config.mts that exports a default AxlRuntime instance.`);\n process.exit(1);\n }\n configPath = found;\n }\n\n // Register custom import conditions (e.g., --conditions development).\n // In monorepos, package.json \"exports\" often use the \"development\" condition\n // to point at source (.ts) instead of built dist. Without this, Studio\n // configs that import workspace packages resolve to dist files, which may\n // not exist or be stale.\n if (args.conditions.length > 0) {\n try {\n const nodeModule = await import('node:module');\n const hookCode = [\n `const extra = ${JSON.stringify(args.conditions)};`,\n `export async function resolve(specifier, context, nextResolve) {`,\n ` return nextResolve(specifier, {`,\n ` ...context,`,\n ` conditions: [...new Set([...context.conditions, ...extra])],`,\n ` });`,\n `}`,\n ].join('\\n');\n nodeModule.register(`data:text/javascript,${encodeURIComponent(hookCode)}`);\n } catch {\n console.warn(`[axl-studio] Warning: --conditions requires Node.js 20.6+`);\n }\n }\n\n console.log(`[axl-studio] Loading config from ${configPath}`);\n\n // Import the user's config via tsImport (handles ESM/CJS correctly for\n // TypeScript files without process-wide side effects)\n let runtime: import('@axlsdk/axl').AxlRuntime;\n const ext = extname(configPath);\n try {\n const mod = await importModule(configPath, import.meta.url);\n // resolveRuntime handles ESM default, CJS-to-ESM interop, and named exports\n runtime = resolveRuntime(mod) as typeof runtime;\n\n if (!runtime || typeof runtime.execute !== 'function') {\n console.error(`Config must export a default AxlRuntime instance.`);\n if (runtime) {\n const keys = Object.keys(runtime as object)\n .slice(0, 5)\n .join(', ');\n console.error(` Got: ${typeof runtime}${keys ? ` with keys: { ${keys} }` : ''}`);\n }\n console.error(\n `Example:\\n import { AxlRuntime } from '@axlsdk/axl';\\n export default new AxlRuntime({ ... });`,\n );\n process.exit(1);\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (\n /Cannot use import statement|Unexpected reserved word|top-level await|exports is not defined/.test(\n msg,\n )\n ) {\n console.error(`[axl-studio] Config failed to load due to a CJS/ESM compatibility issue.`);\n if (ext === '.ts' || ext === '.tsx') {\n console.error(\n ` Tip: try renaming to .mts to force ESM format, or ensure tsx is installed and up to date.`,\n );\n } else {\n console.error(` Tip: add \"type\": \"module\" to your package.json.`);\n }\n console.error();\n }\n console.error(`Failed to load config:`, err);\n process.exit(1);\n }\n\n // Determine static root for pre-built SPA\n const staticRoot = resolve(import.meta.dirname ?? __dirname, 'client');\n const hasStaticAssets = existsSync(resolve(staticRoot, 'index.html'));\n\n const { app, createWsHandlers } = createServer({\n runtime,\n staticRoot: hasStaticAssets ? staticRoot : undefined,\n });\n\n // Set up WebSocket\n const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app });\n const wsHandlers = createWsHandlers();\n app.get(\n '/ws',\n upgradeWebSocket(() => wsHandlers),\n );\n\n const server = serve(\n {\n fetch: app.fetch,\n port: args.port,\n },\n (info) => {\n console.log(`[axl-studio] Server running at http://localhost:${info.port}`);\n console.log(`[axl-studio] Workflows: ${runtime.getWorkflowNames().join(', ') || '(none)'}`);\n console.log(\n `[axl-studio] Agents: ${\n runtime\n .getAgents()\n .map((a) => a._name)\n .join(', ') || '(none)'\n }`,\n );\n console.log(\n `[axl-studio] Tools: ${\n runtime\n .getTools()\n .map((t) => t.name)\n .join(', ') || '(none)'\n }`,\n );\n\n if (!hasStaticAssets) {\n console.log(\n `[axl-studio] No pre-built UI found. Run 'pnpm build:client' or use Vite dev server on port 4401.`,\n );\n }\n },\n );\n\n injectWebSocket(server);\n\n // Auto-open browser\n if (args.open) {\n const url = `http://localhost:${args.port}`;\n const { exec } = await import('node:child_process');\n const cmd =\n process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';\n exec(`${cmd} ${url}`);\n }\n\n // Graceful shutdown\n const shutdown = async () => {\n console.log('\\n[axl-studio] Shutting down...');\n await runtime.shutdown().catch(() => {});\n process.exit(0);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n}\n\nmain().catch((err) => {\n console.error('[axl-studio] Fatal error:', err);\n process.exit(1);\n});\n","/**\n * Resolve the AxlRuntime from a dynamically imported config module.\n * Handles ESM default exports, CJS-to-ESM interop wrapping, and named exports.\n *\n * Module shapes handled:\n * - ESM `export default runtime` → mod.default is the runtime\n * - CJS compiled from `export default runtime` → mod.default.default is the runtime\n * - CJS `module.exports = runtime` → mod.default is the runtime\n * - Named `export { runtime }` → mod.runtime is the runtime\n */\nexport function resolveRuntime(mod: Record<string, unknown>): unknown {\n const def = mod.default as Record<string, unknown> | undefined;\n return def?.default ?? def ?? mod.runtime;\n}\n"],"mappings":"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","names":[]}
@@ -34,8 +34,8 @@ __export(middleware_exports, {
34
34
  handleWsMessage: () => handleWsMessage
35
35
  });
36
36
  module.exports = __toCommonJS(middleware_exports);
37
- var import_node_path3 = require("path");
38
- var import_node_fs3 = require("fs");
37
+ var import_node_path4 = require("path");
38
+ var import_node_fs4 = require("fs");
39
39
  var import_node_url2 = require("url");
40
40
  var import_node_server = require("@hono/node-server");
41
41
  var import_ws = require("ws");
@@ -915,9 +915,39 @@ function createServer(options) {
915
915
  }
916
916
 
917
917
  // src/eval-loader.ts
918
+ var import_node_path3 = require("path");
919
+ var import_node_fs3 = require("fs");
920
+
921
+ // src/cli-utils.ts
918
922
  var import_node_path2 = require("path");
919
923
  var import_node_fs2 = require("fs");
920
924
  var import_node_url = require("url");
925
+ function needsTsxLoader(configPath) {
926
+ return /\.[mc]?tsx?$/.test(configPath);
927
+ }
928
+ var tsImportFn;
929
+ async function importModule(filePath, parentURL) {
930
+ if (needsTsxLoader(filePath)) {
931
+ if (tsImportFn === void 0) {
932
+ try {
933
+ const mod = await import("tsx/esm/api");
934
+ tsImportFn = mod.tsImport ?? null;
935
+ } catch {
936
+ tsImportFn = null;
937
+ console.warn(
938
+ "[axl-studio] Warning: tsx is not installed. TypeScript config files require tsx as a dependency.\n Install it with: npm install -D tsx"
939
+ );
940
+ }
941
+ }
942
+ if (tsImportFn) {
943
+ return await tsImportFn((0, import_node_url.pathToFileURL)(filePath).href, parentURL);
944
+ }
945
+ }
946
+ return await import((0, import_node_url.pathToFileURL)(filePath).href);
947
+ }
948
+
949
+ // src/eval-loader.ts
950
+ var import_meta = {};
921
951
  function createEvalLoader(config, runtime, cwd) {
922
952
  let loadPromise;
923
953
  const { patterns, conditions } = normalizeConfig(config);
@@ -941,13 +971,10 @@ async function loadEvalFiles(patterns, conditions, cwd, runtime) {
941
971
  console.warn(`[axl-studio] No eval files found matching: ${patterns.join(", ")}`);
942
972
  return;
943
973
  }
944
- if (files.some((f) => /\.[mc]?tsx?$/.test(f))) {
945
- await ensureTsxLoader();
946
- }
947
974
  for (const file of files) {
948
975
  try {
949
- const mod = await import((0, import_node_url.pathToFileURL)(file).href);
950
- const evalConfig = mod.default ?? mod.config ?? mod;
976
+ const mod = await importModule(file, import_meta.url);
977
+ const evalConfig = mod.default?.default ?? mod.default ?? mod.config ?? mod;
951
978
  if (!evalConfig.workflow || !evalConfig.dataset || !evalConfig.scorers) {
952
979
  console.warn(
953
980
  `[axl-studio] Skipping ${file}: not a valid eval config (missing workflow, dataset, or scorers)`
@@ -978,10 +1005,10 @@ function normalizeConfig(config) {
978
1005
  return { patterns: files, conditions: config.conditions ?? [] };
979
1006
  }
980
1007
  function deriveEvalName(filePath, cwd) {
981
- const rel = (0, import_node_path2.relative)(cwd, filePath);
1008
+ const rel = (0, import_node_path3.relative)(cwd, filePath);
982
1009
  const normalized = rel.replace(/\\/g, "/");
983
1010
  if (normalized.startsWith("../")) {
984
- const base = (0, import_node_path2.basename)(filePath);
1011
+ const base = (0, import_node_path3.basename)(filePath);
985
1012
  const stripped = base.replace(/\.eval\.[mc]?[jt]sx?$/, "");
986
1013
  return stripped !== base ? stripped : base.replace(/\.[mc]?[jt]sx?$/, "") || base;
987
1014
  }
@@ -994,7 +1021,7 @@ function resolvePatterns(patterns, cwd) {
994
1021
  const files = [];
995
1022
  const seen = /* @__PURE__ */ new Set();
996
1023
  for (const pattern of patterns) {
997
- const resolved = pattern.includes("*") ? expandGlob(pattern, cwd) : [(0, import_node_path2.resolve)(cwd, pattern)];
1024
+ const resolved = pattern.includes("*") ? expandGlob(pattern, cwd) : [(0, import_node_path3.resolve)(cwd, pattern)];
998
1025
  for (const file of resolved) {
999
1026
  if (!seen.has(file)) {
1000
1027
  seen.add(file);
@@ -1007,12 +1034,12 @@ function resolvePatterns(patterns, cwd) {
1007
1034
  function expandGlob(pattern, cwd) {
1008
1035
  if (pattern.includes("**/")) {
1009
1036
  const sepIdx = pattern.indexOf("**/");
1010
- const baseDir = (0, import_node_path2.resolve)(cwd, pattern.slice(0, sepIdx) || ".");
1037
+ const baseDir = (0, import_node_path3.resolve)(cwd, pattern.slice(0, sepIdx) || ".");
1011
1038
  const fileGlob2 = pattern.slice(sepIdx + 3) || "*";
1012
1039
  return findFiles(baseDir, fileGlob2, true);
1013
1040
  }
1014
- const dir = (0, import_node_path2.resolve)(cwd, (0, import_node_path2.dirname)(pattern));
1015
- const fileGlob = (0, import_node_path2.basename)(pattern);
1041
+ const dir = (0, import_node_path3.resolve)(cwd, (0, import_node_path3.dirname)(pattern));
1042
+ const fileGlob = (0, import_node_path3.basename)(pattern);
1016
1043
  return findFiles(dir, fileGlob, false);
1017
1044
  }
1018
1045
  var MAX_DEPTH = 20;
@@ -1021,11 +1048,11 @@ function findFiles(dir, fileGlob, recursive, depth = 0) {
1021
1048
  const matcher = globToRegex(fileGlob);
1022
1049
  const results = [];
1023
1050
  try {
1024
- const entries = (0, import_node_fs2.readdirSync)(dir);
1051
+ const entries = (0, import_node_fs3.readdirSync)(dir);
1025
1052
  for (const entry of entries) {
1026
- const full = (0, import_node_path2.resolve)(dir, entry);
1053
+ const full = (0, import_node_path3.resolve)(dir, entry);
1027
1054
  try {
1028
- const stat = (0, import_node_fs2.statSync)(full);
1055
+ const stat = (0, import_node_fs3.statSync)(full);
1029
1056
  if (stat.isFile() && matcher.test(entry)) {
1030
1057
  results.push(full);
1031
1058
  } else if (stat.isDirectory() && recursive) {
@@ -1042,29 +1069,6 @@ function globToRegex(glob) {
1042
1069
  const escaped = glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
1043
1070
  return new RegExp(`^${escaped}$`);
1044
1071
  }
1045
- var tsxRegistered = false;
1046
- async function ensureTsxLoader() {
1047
- if (tsxRegistered) return;
1048
- tsxRegistered = true;
1049
- let loaded = false;
1050
- try {
1051
- const tsxEsm = await import("tsx/esm/api");
1052
- tsxEsm.register();
1053
- loaded = true;
1054
- } catch {
1055
- }
1056
- try {
1057
- const tsxCjs = await import("tsx/cjs/api");
1058
- tsxCjs.register();
1059
- loaded = true;
1060
- } catch {
1061
- }
1062
- if (!loaded) {
1063
- console.warn(
1064
- "[axl-studio] Warning: tsx is not installed. TypeScript eval files require tsx.\n Install it with: npm install -D tsx"
1065
- );
1066
- }
1067
- }
1068
1072
  async function registerConditions(conditions) {
1069
1073
  try {
1070
1074
  const nodeModule = await import("module");
@@ -1084,15 +1088,15 @@ async function registerConditions(conditions) {
1084
1088
  }
1085
1089
 
1086
1090
  // src/middleware.ts
1087
- var import_meta = {};
1091
+ var import_meta2 = {};
1088
1092
  function createStudioMiddleware(options) {
1089
1093
  const { runtime, serveClient = true, verifyUpgrade, readOnly = false } = options;
1090
1094
  const basePath = normalizeBasePath(options.basePath);
1091
1095
  const staticRoot = serveClient ? resolveClientDist() : void 0;
1092
1096
  if (serveClient && !staticRoot) {
1093
- const dir = import_meta.dirname ?? (typeof __dirname !== "undefined" ? __dirname : (0, import_node_path3.dirname)((0, import_node_url2.fileURLToPath)(import_meta.url)));
1097
+ const dir = import_meta2.dirname ?? (typeof __dirname !== "undefined" ? __dirname : (0, import_node_path4.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url)));
1094
1098
  console.warn(
1095
- `[axl-studio] serveClient is true but no pre-built client found at ${(0, import_node_path3.resolve)(dir, "client")}. Studio UI will not be available. Set serveClient: false to suppress this warning.`
1099
+ `[axl-studio] serveClient is true but no pre-built client found at ${(0, import_node_path4.resolve)(dir, "client")}. Studio UI will not be available. Set serveClient: false to suppress this warning.`
1096
1100
  );
1097
1101
  }
1098
1102
  const evalLoader = options.evals ? createEvalLoader(options.evals, runtime) : void 0;
@@ -1240,9 +1244,9 @@ function normalizeBasePath(raw) {
1240
1244
  return normalized;
1241
1245
  }
1242
1246
  function resolveClientDist() {
1243
- const dir = import_meta.dirname ?? (typeof __dirname !== "undefined" ? __dirname : (0, import_node_path3.dirname)((0, import_node_url2.fileURLToPath)(import_meta.url)));
1244
- const candidate = (0, import_node_path3.resolve)(dir, "client");
1245
- return (0, import_node_fs3.existsSync)((0, import_node_path3.resolve)(candidate, "index.html")) ? candidate : void 0;
1247
+ const dir = import_meta2.dirname ?? (typeof __dirname !== "undefined" ? __dirname : (0, import_node_path4.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url)));
1248
+ const candidate = (0, import_node_path4.resolve)(dir, "client");
1249
+ return (0, import_node_fs4.existsSync)((0, import_node_path4.resolve)(candidate, "index.html")) ? candidate : void 0;
1246
1250
  }
1247
1251
  // Annotate the CommonJS export names for ESM import in node:
1248
1252
  0 && (module.exports = {