openagentflow 0.1.3 → 0.1.5
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/adapters/langgraph/templates.js +3 -3
- package/cli/env.js +37 -13
- package/cli/index.js +16 -11
- package/compiler/index.js +1 -0
- package/compiler/ir-generator.js +3 -1
- package/compiler/version.js +26 -0
- package/package.json +4 -1
|
@@ -224,7 +224,7 @@ export function generateLlmHelperTemplate({ defaultModel, defaultTemperature })
|
|
|
224
224
|
` raise RuntimeError("Missing package: pip install langchain-anthropic")`,
|
|
225
225
|
` else:`,
|
|
226
226
|
` raise RuntimeError(`,
|
|
227
|
-
` "No LLM provider available or configured.
|
|
227
|
+
` "No LLM provider available or configured. Run 'npx openagentflow auth' to set up credentials, or set GOOGLE_API_KEY / OPENAI_API_KEY / ANTHROPIC_API_KEY in your local .env file."`,
|
|
228
228
|
` )`,
|
|
229
229
|
``,
|
|
230
230
|
`def _parse_llm_output(raw_content, outputs):`,
|
|
@@ -431,8 +431,8 @@ export function generateMainTemplate({ workflowName, initialStateFields, require
|
|
|
431
431
|
` # Ensure at least one API key is set`,
|
|
432
432
|
` if not _LLM_PROVIDER:`,
|
|
433
433
|
` print("Error: No LLM provider configured.")`,
|
|
434
|
-
` print("
|
|
435
|
-
` print("
|
|
434
|
+
` print(" Run 'npx openagentflow auth' to configure credentials or edit your local .env file.")`,
|
|
435
|
+
` print(" Or set manually: export GOOGLE_API_KEY='AIza...'")`,
|
|
436
436
|
` exit(1)`,
|
|
437
437
|
``,
|
|
438
438
|
` print(f"Default fallback provider: {_LLM_PROVIDER}")`,
|
package/cli/env.js
CHANGED
|
@@ -55,6 +55,29 @@ export function parseDotEnv(content) {
|
|
|
55
55
|
return result;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Check if an environment variable value is a dummy placeholder string or unset.
|
|
60
|
+
* Returns true if val is null, undefined, empty, or contains typical template placeholder markers.
|
|
61
|
+
*/
|
|
62
|
+
export function isPlaceholder(val) {
|
|
63
|
+
if (val === null || val === undefined || typeof val !== 'string') {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
const trimmed = val.trim();
|
|
67
|
+
if (trimmed === '') {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
const lower = trimmed.toLowerCase();
|
|
71
|
+
return (
|
|
72
|
+
lower.startsWith('your_') ||
|
|
73
|
+
lower.startsWith('your-') ||
|
|
74
|
+
lower.includes('_here') ||
|
|
75
|
+
lower.includes('-here') ||
|
|
76
|
+
lower === 'todo' ||
|
|
77
|
+
lower === 'placeholder'
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
58
81
|
/**
|
|
59
82
|
* Resolve environment variables across the 4-tier hierarchy:
|
|
60
83
|
* 1. Inline CLI overrides & System Environment Variables (already in process.env)
|
|
@@ -82,23 +105,24 @@ export function resolveEnvHierarchy(targetFilePath = null) {
|
|
|
82
105
|
} catch (err) {}
|
|
83
106
|
}
|
|
84
107
|
|
|
85
|
-
let
|
|
86
|
-
|
|
87
|
-
|
|
108
|
+
let localEnv = {};
|
|
109
|
+
const cwdEnvPath = join(process.cwd(), '.env');
|
|
110
|
+
let localEnvPath = cwdEnvPath;
|
|
111
|
+
if (existsSync(cwdEnvPath)) {
|
|
88
112
|
try {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
} catch (err) {
|
|
92
|
-
localEnvPath = join(process.cwd(), '.env');
|
|
93
|
-
}
|
|
94
|
-
} else {
|
|
95
|
-
localEnvPath = join(process.cwd(), '.env');
|
|
113
|
+
localEnv = parseDotEnv(readFileSync(cwdEnvPath, 'utf-8'));
|
|
114
|
+
} catch (err) {}
|
|
96
115
|
}
|
|
97
116
|
|
|
98
|
-
|
|
99
|
-
|
|
117
|
+
if (targetFilePath && existsSync(targetFilePath)) {
|
|
118
|
+
const absTarget = resolve(targetFilePath);
|
|
100
119
|
try {
|
|
101
|
-
|
|
120
|
+
const dir = statSync(absTarget).isDirectory() ? absTarget : dirname(absTarget);
|
|
121
|
+
const targetEnvPath = join(dir, '.env');
|
|
122
|
+
if (resolve(targetEnvPath) !== resolve(cwdEnvPath) && existsSync(targetEnvPath)) {
|
|
123
|
+
localEnvPath = targetEnvPath;
|
|
124
|
+
Object.assign(localEnv, parseDotEnv(readFileSync(targetEnvPath, 'utf-8')));
|
|
125
|
+
}
|
|
102
126
|
} catch (err) {}
|
|
103
127
|
}
|
|
104
128
|
|
package/cli/index.js
CHANGED
|
@@ -23,8 +23,9 @@ import { fileURLToPath } from 'url';
|
|
|
23
23
|
import { execSync, spawn } from 'child_process';
|
|
24
24
|
import os from 'os';
|
|
25
25
|
import { Compiler } from '../compiler/compiler.js';
|
|
26
|
+
import { VERSION } from '../compiler/version.js';
|
|
26
27
|
import { LangGraphAdapter } from '../adapters/langgraph/index.js';
|
|
27
|
-
import { resolveEnvHierarchy, setupAuth } from './env.js';
|
|
28
|
+
import { resolveEnvHierarchy, setupAuth, isPlaceholder } from './env.js';
|
|
28
29
|
|
|
29
30
|
// ─── ANSI Colors ───────────────────────────────────────────────────────────────
|
|
30
31
|
|
|
@@ -42,7 +43,7 @@ const colors = {
|
|
|
42
43
|
// ─── Helpers ───────────────────────────────────────────────────────────────────
|
|
43
44
|
|
|
44
45
|
function printBanner() {
|
|
45
|
-
console.log(`${colors.cyan}${colors.bold}OpenAgentFlow${colors.reset} ${colors.dim}
|
|
46
|
+
console.log(`${colors.cyan}${colors.bold}OpenAgentFlow${colors.reset} ${colors.dim}v${VERSION}${colors.reset}`);
|
|
46
47
|
console.log();
|
|
47
48
|
}
|
|
48
49
|
|
|
@@ -332,44 +333,48 @@ function cmdRun(filePath, flags, positional = []) {
|
|
|
332
333
|
else if (targetModel.startsWith('gemini-') || targetModel.startsWith('gemma-')) provider = 'gemini';
|
|
333
334
|
}
|
|
334
335
|
|
|
335
|
-
if (provider === 'anthropic' && !process.env.ANTHROPIC_API_KEY) {
|
|
336
|
+
if (provider === 'anthropic' && (!process.env.ANTHROPIC_API_KEY || isPlaceholder(process.env.ANTHROPIC_API_KEY))) {
|
|
336
337
|
console.error(`${colors.red}Error:${colors.reset} Missing required API key "ANTHROPIC_API_KEY" for agent "${agent.id}" (provider: anthropic).`);
|
|
337
338
|
console.error(`Looked in order of priority:`);
|
|
338
339
|
console.error(` 1. Inline CLI overrides`);
|
|
339
340
|
console.error(` 2. Local Project .env`);
|
|
340
341
|
console.error(` 3. System Environment Variables`);
|
|
341
342
|
console.error(` 4. Global OAF Store (~/.oaf/.env)`);
|
|
342
|
-
console.error(`Run \`oaf auth\` to set up your
|
|
343
|
+
console.error(`Run \`npx openagentflow auth\` (or \`oaf auth\` if globally installed) to set up your credentials or edit your local .env file.`);
|
|
343
344
|
process.exit(1);
|
|
344
|
-
} else if (provider === 'openai' && !process.env.OPENAI_API_KEY) {
|
|
345
|
+
} else if (provider === 'openai' && (!process.env.OPENAI_API_KEY || isPlaceholder(process.env.OPENAI_API_KEY))) {
|
|
345
346
|
console.error(`${colors.red}Error:${colors.reset} Missing required API key "OPENAI_API_KEY" for agent "${agent.id}" (provider: openai).`);
|
|
346
347
|
console.error(`Looked in order of priority:`);
|
|
347
348
|
console.error(` 1. Inline CLI overrides`);
|
|
348
349
|
console.error(` 2. Local Project .env`);
|
|
349
350
|
console.error(` 3. System Environment Variables`);
|
|
350
351
|
console.error(` 4. Global OAF Store (~/.oaf/.env)`);
|
|
351
|
-
console.error(`Run \`oaf auth\` to set up your
|
|
352
|
+
console.error(`Run \`npx openagentflow auth\` (or \`oaf auth\` if globally installed) to set up your credentials or edit your local .env file.`);
|
|
352
353
|
process.exit(1);
|
|
353
|
-
} else if (provider === 'gemini' && !process.env.GOOGLE_API_KEY) {
|
|
354
|
+
} else if (provider === 'gemini' && (!process.env.GOOGLE_API_KEY || isPlaceholder(process.env.GOOGLE_API_KEY))) {
|
|
354
355
|
console.error(`${colors.red}Error:${colors.reset} Missing required API key "GOOGLE_API_KEY" for agent "${agent.id}" (provider: gemini).`);
|
|
355
356
|
console.error(`Looked in order of priority:`);
|
|
356
357
|
console.error(` 1. Inline CLI overrides`);
|
|
357
358
|
console.error(` 2. Local Project .env`);
|
|
358
359
|
console.error(` 3. System Environment Variables`);
|
|
359
360
|
console.error(` 4. Global OAF Store (~/.oaf/.env)`);
|
|
360
|
-
console.error(`Run \`oaf auth\` to set up your
|
|
361
|
+
console.error(`Run \`npx openagentflow auth\` (or \`oaf auth\` if globally installed) to set up your credentials or edit your local .env file.`);
|
|
361
362
|
process.exit(1);
|
|
362
363
|
}
|
|
363
364
|
}
|
|
364
365
|
|
|
365
|
-
|
|
366
|
+
const hasValidGoogle = process.env.GOOGLE_API_KEY && !isPlaceholder(process.env.GOOGLE_API_KEY);
|
|
367
|
+
const hasValidOpenAI = process.env.OPENAI_API_KEY && !isPlaceholder(process.env.OPENAI_API_KEY);
|
|
368
|
+
const hasValidAnthropic = process.env.ANTHROPIC_API_KEY && !isPlaceholder(process.env.ANTHROPIC_API_KEY);
|
|
369
|
+
|
|
370
|
+
if (!hasValidGoogle && !hasValidOpenAI && !hasValidAnthropic && result.ir.agents.length > 0) {
|
|
366
371
|
console.error(`${colors.red}Error:${colors.reset} No LLM API key configured. Set GOOGLE_API_KEY (Gemini), OPENAI_API_KEY (OpenAI), or ANTHROPIC_API_KEY (Anthropic) to execute workflows.`);
|
|
367
372
|
console.error(`Looked in order of priority:`);
|
|
368
373
|
console.error(` 1. Inline CLI overrides`);
|
|
369
374
|
console.error(` 2. Local Project .env`);
|
|
370
375
|
console.error(` 3. System Environment Variables`);
|
|
371
376
|
console.error(` 4. Global OAF Store (~/.oaf/.env)`);
|
|
372
|
-
console.error(`Run \`oaf auth\` to set up your
|
|
377
|
+
console.error(`Run \`npx openagentflow auth\` (or \`oaf auth\` if globally installed) to set up your credentials or edit your local .env file.`);
|
|
373
378
|
process.exit(1);
|
|
374
379
|
}
|
|
375
380
|
}
|
|
@@ -546,7 +551,7 @@ function main() {
|
|
|
546
551
|
}
|
|
547
552
|
|
|
548
553
|
if (rawArgs.includes('--version') || rawArgs.includes('-v')) {
|
|
549
|
-
console.log(
|
|
554
|
+
console.log(VERSION);
|
|
550
555
|
process.exit(0);
|
|
551
556
|
}
|
|
552
557
|
|
package/compiler/index.js
CHANGED
package/compiler/ir-generator.js
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAgentFlow Version Utility
|
|
3
|
+
*
|
|
4
|
+
* Dynamically loads and caches the current version from package.json
|
|
5
|
+
* to ensure a single source of truth across the compiler, CLI, and adapters.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readFileSync } from 'fs';
|
|
9
|
+
import { resolve, dirname } from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
|
|
12
|
+
let cachedVersion = null;
|
|
13
|
+
|
|
14
|
+
export function getVersion() {
|
|
15
|
+
if (cachedVersion !== null) return cachedVersion;
|
|
16
|
+
try {
|
|
17
|
+
const pkgPath = resolve(dirname(fileURLToPath(import.meta.url)), '..', 'package.json');
|
|
18
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
19
|
+
cachedVersion = pkg.version || '0.1.0';
|
|
20
|
+
} catch {
|
|
21
|
+
cachedVersion = '0.1.0';
|
|
22
|
+
}
|
|
23
|
+
return cachedVersion;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const VERSION = getVersion();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openagentflow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "An open, portable specification for describing AI agent workflows using a human-readable text language.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "compiler/index.js",
|
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
26
|
"test": "node --test tests/**/*.test.js",
|
|
27
|
+
"test:update-snapshots": "node -e \"process.env.UPDATE_SNAPSHOTS='1'; import('./tests/snapshot.test.js')\"",
|
|
28
|
+
"preversion": "npm test",
|
|
29
|
+
"version": "npm run test:update-snapshots && git add tests/snapshots",
|
|
27
30
|
"oaf": "node cli/index.js"
|
|
28
31
|
},
|
|
29
32
|
"keywords": [
|