orchestrated 0.1.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 +114 -0
- package/chunk-1fxw3qys.js +131 -0
- package/chunk-1fxw3qys.js.map +10 -0
- package/chunk-41g79vhc.js +49 -0
- package/chunk-41g79vhc.js.map +10 -0
- package/chunk-5va59f7m.js +22 -0
- package/chunk-5va59f7m.js.map +9 -0
- package/chunk-83qdt756.js +424 -0
- package/chunk-83qdt756.js.map +15 -0
- package/index.js +1480 -0
- package/index.js.map +31 -0
- package/package.json +78 -0
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Orchestrated
|
|
2
|
+
|
|
3
|
+
> LLM evaluation framework with batch processing, data sources, and multi-backend export
|
|
4
|
+
|
|
5
|
+
Orchestrated is a comprehensive evaluation framework for LLM applications. It provides a simple API for running evaluations with support for custom scorers, data sources, batch processing, and multiple export backends.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 🎯 **Simple API** - Evaluate LLM outputs with a single function call
|
|
10
|
+
- 📊 **Built-in Scorers** - Effectiveness, GuardrailAdherence, Execution, Factuality, and more
|
|
11
|
+
- 🔧 **Custom Scorers** - Easy-to-define custom evaluation logic
|
|
12
|
+
- 📡 **Data Sources** - Built-in support for various data sources
|
|
13
|
+
- 🔄 **Batch Processing** - Efficient batch evaluation with resume support
|
|
14
|
+
- 📈 **Progress Reporting** - Beautiful terminal UI with progress bars
|
|
15
|
+
- 🔍 **OpenTelemetry** - Built-in tracing and telemetry support
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install orchestrated
|
|
21
|
+
# or
|
|
22
|
+
pnpm add orchestrated
|
|
23
|
+
# or
|
|
24
|
+
yarn add orchestrated
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { Eval } from "orchestrated";
|
|
31
|
+
|
|
32
|
+
// Simple evaluation
|
|
33
|
+
Eval("My First Eval", {
|
|
34
|
+
data: [
|
|
35
|
+
{ input: "What is 2+2?", output: "4", expected: "4" },
|
|
36
|
+
{
|
|
37
|
+
input: "What is the capital of France?",
|
|
38
|
+
output: "Paris",
|
|
39
|
+
expected: "Paris",
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
scores: ["Effectiveness", "Factuality"],
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Usage Examples
|
|
47
|
+
|
|
48
|
+
### With Custom Task Function
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { Eval } from "orchestrated";
|
|
52
|
+
import { generateAI } from "./my-ai-service";
|
|
53
|
+
|
|
54
|
+
Eval("LLM Evaluation", {
|
|
55
|
+
data: [
|
|
56
|
+
{ input: "Explain quantum computing" },
|
|
57
|
+
{ input: "What is machine learning?" },
|
|
58
|
+
],
|
|
59
|
+
task: async (input) => {
|
|
60
|
+
const output = await generateAI(input);
|
|
61
|
+
return output;
|
|
62
|
+
},
|
|
63
|
+
scores: ["Effectiveness", "Factuality"],
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### With Data Sources
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { Eval, interactions } from "orchestrated";
|
|
71
|
+
|
|
72
|
+
Eval("Production Eval", {
|
|
73
|
+
data: interactions({
|
|
74
|
+
tenantId: "my-tenant",
|
|
75
|
+
serviceName: "my-service",
|
|
76
|
+
environment: "production",
|
|
77
|
+
}),
|
|
78
|
+
scores: ["Effectiveness", "GuardrailAdherence"],
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Custom Scorers
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { projects } from "orchestrated";
|
|
86
|
+
import { z } from "zod";
|
|
87
|
+
|
|
88
|
+
const project = projects.create();
|
|
89
|
+
|
|
90
|
+
const ContentSafety = project.scorers.create({
|
|
91
|
+
name: "ContentSafety",
|
|
92
|
+
slug: "content-safety",
|
|
93
|
+
description: "Evaluates content for safety violations",
|
|
94
|
+
parameters: z.object({
|
|
95
|
+
input: z.string(),
|
|
96
|
+
output: z.string(),
|
|
97
|
+
}),
|
|
98
|
+
handler: async ({ input, output }) => {
|
|
99
|
+
// Your custom scoring logic
|
|
100
|
+
const isSafe = !output.includes("unsafe-content");
|
|
101
|
+
return {
|
|
102
|
+
name: "ContentSafety",
|
|
103
|
+
score: isSafe ? 1 : 0,
|
|
104
|
+
metadata: { flagged: !isSafe },
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Use in evaluation
|
|
110
|
+
Eval("Safety Check", {
|
|
111
|
+
data: [...],
|
|
112
|
+
scores: [ContentSafety],
|
|
113
|
+
});
|
|
114
|
+
```
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import"./chunk-5va59f7m.js";
|
|
2
|
+
|
|
3
|
+
// src/cli/credentials.ts
|
|
4
|
+
import {
|
|
5
|
+
chmodSync,
|
|
6
|
+
existsSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
readFileSync,
|
|
9
|
+
unlinkSync,
|
|
10
|
+
writeFileSync
|
|
11
|
+
} from "node:fs";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
var CREDENTIALS_DIR = join(homedir(), ".orcha");
|
|
15
|
+
var CREDENTIALS_FILE = join(CREDENTIALS_DIR, "credentials.json");
|
|
16
|
+
function ensureCredentialsDir() {
|
|
17
|
+
if (!existsSync(CREDENTIALS_DIR)) {
|
|
18
|
+
mkdirSync(CREDENTIALS_DIR, { recursive: true, mode: 448 });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function saveCredentials(credentials) {
|
|
22
|
+
ensureCredentialsDir();
|
|
23
|
+
writeFileSync(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2), {
|
|
24
|
+
mode: 384
|
|
25
|
+
});
|
|
26
|
+
try {
|
|
27
|
+
chmodSync(CREDENTIALS_FILE, 384);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.warn("Warning: Could not set file permissions:", error);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function loadCredentials() {
|
|
33
|
+
if (!existsSync(CREDENTIALS_FILE)) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const content = readFileSync(CREDENTIALS_FILE, "utf-8");
|
|
38
|
+
return JSON.parse(content);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error("Failed to load credentials:", error);
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function clearCredentials() {
|
|
45
|
+
if (existsSync(CREDENTIALS_FILE)) {
|
|
46
|
+
try {
|
|
47
|
+
unlinkSync(CREDENTIALS_FILE);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error("Failed to clear credentials:", error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function isTokenExpired(credentials) {
|
|
54
|
+
const now = Math.floor(Date.now() / 1000);
|
|
55
|
+
const buffer = 300;
|
|
56
|
+
return now >= credentials.expires_at - buffer;
|
|
57
|
+
}
|
|
58
|
+
async function getValidAccessToken(apiEndpoint) {
|
|
59
|
+
const credentials = loadCredentials();
|
|
60
|
+
if (!credentials) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
if (!isTokenExpired(credentials)) {
|
|
64
|
+
return credentials.id_token;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const refreshed = await refreshAccessToken(apiEndpoint, credentials.refresh_token);
|
|
68
|
+
if (refreshed) {
|
|
69
|
+
return refreshed.id_token;
|
|
70
|
+
}
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error("Failed to refresh token:", error);
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
async function refreshAccessToken(apiEndpoint, refreshToken) {
|
|
77
|
+
try {
|
|
78
|
+
const response = await fetch(`${apiEndpoint}/device/token`, {
|
|
79
|
+
method: "POST",
|
|
80
|
+
headers: { "Content-Type": "application/json" },
|
|
81
|
+
body: JSON.stringify({
|
|
82
|
+
grant_type: "refresh_token",
|
|
83
|
+
refresh_token: refreshToken
|
|
84
|
+
})
|
|
85
|
+
});
|
|
86
|
+
if (!response.ok) {
|
|
87
|
+
clearCredentials();
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const data = await response.json();
|
|
91
|
+
const expiresAt = Math.floor(Date.now() / 1000) + data.expires_in;
|
|
92
|
+
const credentials = {
|
|
93
|
+
access_token: data.access_token,
|
|
94
|
+
refresh_token: data.refresh_token || refreshToken,
|
|
95
|
+
id_token: data.id_token,
|
|
96
|
+
token_type: data.token_type || "Bearer",
|
|
97
|
+
expires_at: expiresAt,
|
|
98
|
+
scope: data.scope || "openid email profile"
|
|
99
|
+
};
|
|
100
|
+
saveCredentials(credentials);
|
|
101
|
+
return credentials;
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error("Error refreshing token:", error);
|
|
104
|
+
clearCredentials();
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function decodeIdToken(idToken) {
|
|
109
|
+
try {
|
|
110
|
+
const parts = idToken.split(".");
|
|
111
|
+
if (parts.length !== 3)
|
|
112
|
+
return null;
|
|
113
|
+
const payload = JSON.parse(Buffer.from(parts[1], "base64").toString("utf-8"));
|
|
114
|
+
return {
|
|
115
|
+
email: payload.email || "unknown",
|
|
116
|
+
sub: payload.sub || "unknown"
|
|
117
|
+
};
|
|
118
|
+
} catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export {
|
|
123
|
+
saveCredentials,
|
|
124
|
+
loadCredentials,
|
|
125
|
+
isTokenExpired,
|
|
126
|
+
getValidAccessToken,
|
|
127
|
+
decodeIdToken,
|
|
128
|
+
clearCredentials
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
//# debugId=66D1F8010187BA8564756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/cli/credentials.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import {\n\tchmodSync,\n\texistsSync,\n\tmkdirSync,\n\treadFileSync,\n\tunlinkSync,\n\twriteFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface Credentials {\n\taccess_token: string;\n\trefresh_token: string;\n\tid_token: string;\n\ttoken_type: string;\n\texpires_at: number; // Unix timestamp\n\tscope: string;\n}\n\nexport interface CredentialsWithUser extends Credentials {\n\tuser?: {\n\t\temail: string;\n\t\tsub: string;\n\t};\n}\n\nconst CREDENTIALS_DIR = join(homedir(), \".orcha\");\nconst CREDENTIALS_FILE = join(CREDENTIALS_DIR, \"credentials.json\");\n\n/**\n * Ensure credentials directory exists with secure permissions\n */\nfunction ensureCredentialsDir(): void {\n\tif (!existsSync(CREDENTIALS_DIR)) {\n\t\tmkdirSync(CREDENTIALS_DIR, { recursive: true, mode: 0o700 });\n\t}\n}\n\n/**\n * Save credentials to disk with secure permissions\n */\nexport function saveCredentials(credentials: Credentials): void {\n\tensureCredentialsDir();\n\n\t// Write file\n\twriteFileSync(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2), {\n\t\tmode: 0o600,\n\t});\n\n\t// Ensure permissions are set (some systems may not respect mode in writeFileSync)\n\ttry {\n\t\tchmodSync(CREDENTIALS_FILE, 0o600);\n\t} catch (error) {\n\t\tconsole.warn(\"Warning: Could not set file permissions:\", error);\n\t}\n}\n\n/**\n * Load credentials from disk\n */\nexport function loadCredentials(): Credentials | null {\n\tif (!existsSync(CREDENTIALS_FILE)) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(CREDENTIALS_FILE, \"utf-8\");\n\t\treturn JSON.parse(content);\n\t} catch (error) {\n\t\tconsole.error(\"Failed to load credentials:\", error);\n\t\treturn null;\n\t}\n}\n\n/**\n * Delete stored credentials\n */\nexport function clearCredentials(): void {\n\tif (existsSync(CREDENTIALS_FILE)) {\n\t\ttry {\n\t\t\tunlinkSync(CREDENTIALS_FILE);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to clear credentials:\", error);\n\t\t}\n\t}\n}\n\n/**\n * Check if access token is expired (with 5-minute buffer)\n */\nexport function isTokenExpired(credentials: Credentials): boolean {\n\tconst now = Math.floor(Date.now() / 1000);\n\tconst buffer = 300; // 5 minutes\n\treturn now >= credentials.expires_at - buffer;\n}\n\n/**\n * Get valid ID token for API Gateway authorization (refresh if needed)\n *\n * Note: API Gateway Cognito authorizers require ID tokens, not access tokens\n */\nexport async function getValidAccessToken(\n\tapiEndpoint: string,\n): Promise<string | null> {\n\tconst credentials = loadCredentials();\n\n\tif (!credentials) {\n\t\treturn null;\n\t}\n\n\t// If token is still valid, return ID token (required for API Gateway Cognito authorizer)\n\tif (!isTokenExpired(credentials)) {\n\t\treturn credentials.id_token;\n\t}\n\n\t// Token expired, try to refresh\n\ttry {\n\t\tconst refreshed = await refreshAccessToken(\n\t\t\tapiEndpoint,\n\t\t\tcredentials.refresh_token,\n\t\t);\n\n\t\tif (refreshed) {\n\t\t\treturn refreshed.id_token;\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(\"Failed to refresh token:\", error);\n\t}\n\n\treturn null;\n}\n\n/**\n * Refresh access token using refresh token\n */\nasync function refreshAccessToken(\n\tapiEndpoint: string,\n\trefreshToken: string,\n): Promise<Credentials | null> {\n\ttry {\n\t\tconst response = await fetch(`${apiEndpoint}/device/token`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tgrant_type: \"refresh_token\",\n\t\t\t\trefresh_token: refreshToken,\n\t\t\t}),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\t// Refresh token invalid or expired\n\t\t\tclearCredentials();\n\t\t\treturn null;\n\t\t}\n\n\t\tconst data = await response.json();\n\t\tconst expiresAt = Math.floor(Date.now() / 1000) + data.expires_in;\n\n\t\tconst credentials: Credentials = {\n\t\t\taccess_token: data.access_token,\n\t\t\trefresh_token: data.refresh_token || refreshToken, // May return new refresh token\n\t\t\tid_token: data.id_token,\n\t\t\ttoken_type: data.token_type || \"Bearer\",\n\t\t\texpires_at: expiresAt,\n\t\t\tscope: data.scope || \"openid email profile\",\n\t\t};\n\n\t\tsaveCredentials(credentials);\n\t\treturn credentials;\n\t} catch (error) {\n\t\tconsole.error(\"Error refreshing token:\", error);\n\t\tclearCredentials();\n\t\treturn null;\n\t}\n}\n\n/**\n * Decode JWT and extract user info (without verification)\n * Note: This is for display purposes only. Token verification happens on the server.\n */\nexport function decodeIdToken(\n\tidToken: string,\n): { email: string; sub: string } | null {\n\ttry {\n\t\tconst parts = idToken.split(\".\");\n\t\tif (parts.length !== 3) return null;\n\n\t\tconst payload = JSON.parse(\n\t\t\tBuffer.from(parts[1], \"base64\").toString(\"utf-8\"),\n\t\t);\n\n\t\treturn {\n\t\t\temail: payload.email || \"unknown\",\n\t\t\tsub: payload.sub || \"unknown\",\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "66D1F8010187BA8564756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import"./chunk-5va59f7m.js";
|
|
2
|
+
|
|
3
|
+
// src/state/config.ts
|
|
4
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { parse } from "yaml";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
var OrchestralConfigSchema = z.object({
|
|
9
|
+
apiUrl: z.string().optional().catch(undefined),
|
|
10
|
+
tenantId: z.string().optional().catch(undefined),
|
|
11
|
+
serviceName: z.string().optional().catch(undefined),
|
|
12
|
+
environment: z.string().optional().catch(undefined),
|
|
13
|
+
appUrl: z.string().optional().catch(undefined),
|
|
14
|
+
appClientId: z.string().optional().catch(undefined),
|
|
15
|
+
otelEndpoint: z.string().optional().catch(undefined),
|
|
16
|
+
sendNoLogs: z.boolean().optional().catch(undefined),
|
|
17
|
+
disableBundleCache: z.boolean().optional().catch(undefined)
|
|
18
|
+
});
|
|
19
|
+
var CONFIG_FILE_NAMES = [
|
|
20
|
+
"Orchestrated.yaml",
|
|
21
|
+
"Orchestrated.yml",
|
|
22
|
+
"orchestrated.yaml",
|
|
23
|
+
"orchestrated.yml"
|
|
24
|
+
];
|
|
25
|
+
function parseYaml(content) {
|
|
26
|
+
return parse(content);
|
|
27
|
+
}
|
|
28
|
+
function loadConfig(searchDir) {
|
|
29
|
+
const dir = searchDir || process.cwd();
|
|
30
|
+
for (const fileName of CONFIG_FILE_NAMES) {
|
|
31
|
+
const configPath = join(dir, fileName);
|
|
32
|
+
if (existsSync(configPath)) {
|
|
33
|
+
try {
|
|
34
|
+
const content = readFileSync(configPath, "utf-8");
|
|
35
|
+
const parsed = parseYaml(content);
|
|
36
|
+
const config = OrchestralConfigSchema.parse(parsed);
|
|
37
|
+
return config;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.warn(`Failed to load config from ${configPath}:`, error instanceof Error ? error.message : String(error));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
loadConfig
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
//# debugId=933DF374B1E5B60164756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/state/config.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Configuration file loader for Orchestrated.yaml\n *\n * Supports loading non-auth configuration values from a YAML config file.\n * Looks for Orchestrated.yaml in the current working directory.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parse } from \"yaml\";\nimport { z } from \"zod\";\n\n/**\n * Zod schema for configuration validation\n * Invalid types are filtered out (treated as undefined)\n * Unknown fields are stripped\n */\nconst OrchestralConfigSchema = z.object({\n\tapiUrl: z.string().optional().catch(undefined),\n\ttenantId: z.string().optional().catch(undefined),\n\tserviceName: z.string().optional().catch(undefined),\n\tenvironment: z.string().optional().catch(undefined),\n\tappUrl: z.string().optional().catch(undefined),\n\tappClientId: z.string().optional().catch(undefined),\n\totelEndpoint: z.string().optional().catch(undefined),\n\tsendNoLogs: z.boolean().optional().catch(undefined),\n\tdisableBundleCache: z.boolean().optional().catch(undefined),\n});\n\n/**\n * Configuration values that can be set in Orchestrated.yaml\n * Auth-related values (accessToken, loggedInUser) are excluded\n */\nexport type OrchestralConfig = z.infer<typeof OrchestralConfigSchema>;\n\nconst CONFIG_FILE_NAMES = [\n\t\"Orchestrated.yaml\",\n\t\"Orchestrated.yml\",\n\t\"orchestrated.yaml\",\n\t\"orchestrated.yml\",\n];\n\n/**\n * Parse YAML content into a JavaScript object\n */\nfunction parseYaml(content: string): unknown {\n\treturn parse(content);\n}\n\n/**\n * Load configuration from Orchestrated.yaml file\n *\n * Searches for config file in current working directory.\n * Tries multiple file name variants (case variations).\n *\n * @param searchDir - Directory to search for config file (defaults to cwd)\n * @returns Parsed configuration or null if file not found\n */\nexport function loadConfig(searchDir?: string): OrchestralConfig | null {\n\tconst dir = searchDir || process.cwd();\n\n\t// Try each config file name variant\n\tfor (const fileName of CONFIG_FILE_NAMES) {\n\t\tconst configPath = join(dir, fileName);\n\n\t\tif (existsSync(configPath)) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(configPath, \"utf-8\");\n\t\t\t\tconst parsed = parseYaml(content);\n\n\t\t\t\t// Validate and parse with Zod\n\t\t\t\tconst config = OrchestralConfigSchema.parse(parsed);\n\n\t\t\t\treturn config;\n\t\t\t} catch (error) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Failed to load config from ${configPath}:`,\n\t\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\t);\n\t\t\t\t// Continue trying other file names\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;AAOA;AACA;AACA;AACA;AAOA,IAAM,yBAAyB,EAAE,OAAO;AAAA,EACvC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS;AAAA,EAC7C,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS;AAAA,EAC/C,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS;AAAA,EAClD,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS;AAAA,EAClD,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS;AAAA,EAC7C,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS;AAAA,EAClD,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS;AAAA,EACnD,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,SAAS;AAAA,EAClD,oBAAoB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,SAAS;AAC3D,CAAC;AAQD,IAAM,oBAAoB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAKA,SAAS,SAAS,CAAC,SAA0B;AAAA,EAC5C,OAAO,MAAM,OAAO;AAAA;AAYd,SAAS,UAAU,CAAC,WAA6C;AAAA,EACvE,MAAM,MAAM,aAAa,QAAQ,IAAI;AAAA,EAGrC,WAAW,YAAY,mBAAmB;AAAA,IACzC,MAAM,aAAa,KAAK,KAAK,QAAQ;AAAA,IAErC,IAAI,WAAW,UAAU,GAAG;AAAA,MAC3B,IAAI;AAAA,QACH,MAAM,UAAU,aAAa,YAAY,OAAO;AAAA,QAChD,MAAM,SAAS,UAAU,OAAO;AAAA,QAGhC,MAAM,SAAS,uBAAuB,MAAM,MAAM;AAAA,QAElD,OAAO;AAAA,QACN,OAAO,OAAO;AAAA,QACf,QAAQ,KACP,8BAA8B,eAC9B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACtD;AAAA;AAAA,IAGF;AAAA,EACD;AAAA,EAEA,OAAO;AAAA;",
|
|
8
|
+
"debugId": "933DF374B1E5B60164756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
19
|
+
|
|
20
|
+
export { __toESM, __require };
|
|
21
|
+
|
|
22
|
+
//# debugId=139229FD8440C0D464756E2164756E21
|