@flue/cli 0.0.6 → 0.0.7
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/flue.js +51 -4
- package/package.json +1 -1
package/dist/flue.js
CHANGED
|
@@ -7,7 +7,7 @@ import { pathToFileURL } from "node:url";
|
|
|
7
7
|
const OPENCODE_URL = "http://localhost:48765";
|
|
8
8
|
let openCodeProcess = null;
|
|
9
9
|
function printUsage() {
|
|
10
|
-
console.error("Usage: flue run <workflowPath> [--args <json>] [--branch <name>]");
|
|
10
|
+
console.error("Usage: flue run <workflowPath> [--args <json>] [--branch <name>] [--model <provider/model>]");
|
|
11
11
|
}
|
|
12
12
|
function parseArgs(argv) {
|
|
13
13
|
const [command, workflowPath, ...rest] = argv;
|
|
@@ -17,6 +17,7 @@ function parseArgs(argv) {
|
|
|
17
17
|
}
|
|
18
18
|
let argsJson;
|
|
19
19
|
let branch;
|
|
20
|
+
let model;
|
|
20
21
|
for (let i = 0; i < rest.length; i += 1) {
|
|
21
22
|
const arg = rest[i];
|
|
22
23
|
if (arg === "--args") {
|
|
@@ -37,6 +38,15 @@ function parseArgs(argv) {
|
|
|
37
38
|
i += 1;
|
|
38
39
|
continue;
|
|
39
40
|
}
|
|
41
|
+
if (arg === "--model") {
|
|
42
|
+
model = rest[i + 1];
|
|
43
|
+
if (!model) {
|
|
44
|
+
console.error("Missing value for --model");
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
i += 1;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
40
50
|
console.error(`Unknown argument: ${arg}`);
|
|
41
51
|
printUsage();
|
|
42
52
|
process.exit(1);
|
|
@@ -44,11 +54,24 @@ function parseArgs(argv) {
|
|
|
44
54
|
return {
|
|
45
55
|
workflowPath,
|
|
46
56
|
argsJson,
|
|
47
|
-
branch
|
|
57
|
+
branch,
|
|
58
|
+
model
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/** Parse "provider/model" string into { providerID, modelID }. */
|
|
62
|
+
function parseModel(modelStr) {
|
|
63
|
+
const slashIndex = modelStr.indexOf("/");
|
|
64
|
+
if (slashIndex === -1) {
|
|
65
|
+
console.error(`Invalid --model format: "${modelStr}". Expected "provider/model" (e.g. "anthropic/claude-sonnet-4-5").`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
providerID: modelStr.slice(0, slashIndex),
|
|
70
|
+
modelID: modelStr.slice(slashIndex + 1)
|
|
48
71
|
};
|
|
49
72
|
}
|
|
50
73
|
async function run() {
|
|
51
|
-
const { workflowPath, argsJson, branch } = parseArgs(process.argv.slice(2));
|
|
74
|
+
const { workflowPath, argsJson, branch, model: modelStr } = parseArgs(process.argv.slice(2));
|
|
52
75
|
const workdir = process.cwd();
|
|
53
76
|
let startedOpenCode = null;
|
|
54
77
|
if (branch) execFileSync("git", [
|
|
@@ -74,11 +97,14 @@ async function run() {
|
|
|
74
97
|
process.exit(1);
|
|
75
98
|
}
|
|
76
99
|
}
|
|
100
|
+
await preflight(workdir, modelStr);
|
|
101
|
+
const model = modelStr ? parseModel(modelStr) : void 0;
|
|
77
102
|
const flue = new Flue({
|
|
78
103
|
workdir,
|
|
79
104
|
args,
|
|
80
105
|
branch,
|
|
81
|
-
secrets: process.env
|
|
106
|
+
secrets: process.env,
|
|
107
|
+
model
|
|
82
108
|
});
|
|
83
109
|
try {
|
|
84
110
|
const workflow = await import(workflowUrl);
|
|
@@ -97,6 +123,27 @@ async function run() {
|
|
|
97
123
|
}
|
|
98
124
|
}
|
|
99
125
|
run();
|
|
126
|
+
async function preflight(workdir, modelOverride) {
|
|
127
|
+
const res = await fetch(`${OPENCODE_URL}/config/providers?directory=${encodeURIComponent(workdir)}`);
|
|
128
|
+
if (!res.ok) {
|
|
129
|
+
console.error(`[flue] preflight: failed to fetch providers (HTTP ${res.status})`);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
if (((await res.json()).providers || []).length === 0) {
|
|
133
|
+
console.error("[flue] Error: No LLM providers configured.\n\nOpenCode needs at least one provider with an API key to run workflows.\n\n - Set an API key env var (e.g. ANTHROPIC_API_KEY)\n - Or run \"opencode auth login\" to configure a provider\n");
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
if (modelOverride) return;
|
|
137
|
+
const configRes = await fetch(`${OPENCODE_URL}/config?directory=${encodeURIComponent(workdir)}`);
|
|
138
|
+
if (!configRes.ok) {
|
|
139
|
+
console.error(`[flue] preflight: failed to fetch config (HTTP ${configRes.status})`);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
if (!(await configRes.json()).model) {
|
|
143
|
+
console.error("[flue] Error: No default model configured.\n\nOpenCode needs a default model to run workflows. Either:\n\n - Pass --model to the flue CLI:\n flue run workflow.ts --model anthropic/claude-sonnet-4-5\n\n - Or set \"model\" in your project's opencode.json:\n { \"model\": \"anthropic/claude-sonnet-4-5\" }\n");
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
100
147
|
async function isOpenCodeRunning() {
|
|
101
148
|
try {
|
|
102
149
|
const controller = new AbortController();
|