@axlsdk/studio 0.11.0 → 0.11.1
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 +1 -1
- package/dist/chunk-6VDX5CRP.js +77 -0
- package/dist/chunk-6VDX5CRP.js.map +1 -0
- package/dist/cli.cjs +23 -45
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +15 -101
- package/dist/cli.js.map +1 -1
- package/dist/middleware.cjs +48 -44
- package/dist/middleware.cjs.map +1 -1
- package/dist/middleware.js +4 -28
- package/dist/middleware.js.map +1 -1
- package/package.json +4 -4
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
|
|
8
|
-
import { existsSync
|
|
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 =
|
|
103
|
-
if (!
|
|
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 =
|
|
87
|
+
const ext = extname(configPath);
|
|
172
88
|
try {
|
|
173
|
-
const mod = await
|
|
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:
|
|
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 =
|
|
209
|
-
const hasStaticAssets =
|
|
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":[]}
|
package/dist/middleware.cjs
CHANGED
|
@@ -34,8 +34,8 @@ __export(middleware_exports, {
|
|
|
34
34
|
handleWsMessage: () => handleWsMessage
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(middleware_exports);
|
|
37
|
-
var
|
|
38
|
-
var
|
|
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,12 +971,9 @@ 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
|
|
976
|
+
const mod = await importModule(file, import_meta.url);
|
|
950
977
|
const evalConfig = mod.default ?? mod.config ?? mod;
|
|
951
978
|
if (!evalConfig.workflow || !evalConfig.dataset || !evalConfig.scorers) {
|
|
952
979
|
console.warn(
|
|
@@ -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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
1015
|
-
const fileGlob = (0,
|
|
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,
|
|
1051
|
+
const entries = (0, import_node_fs3.readdirSync)(dir);
|
|
1025
1052
|
for (const entry of entries) {
|
|
1026
|
-
const full = (0,
|
|
1053
|
+
const full = (0, import_node_path3.resolve)(dir, entry);
|
|
1027
1054
|
try {
|
|
1028
|
-
const stat = (0,
|
|
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
|
|
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 =
|
|
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,
|
|
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 =
|
|
1244
|
-
const candidate = (0,
|
|
1245
|
-
return (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 = {
|