llm-exe 3.0.0 → 3.1.0-beta.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/dist/chunk-2BUGTOKA.mjs +7194 -0
- package/dist/chunk-7W6GBE2Y.mjs +39 -0
- package/dist/chunk-PX2FFNZQ.mjs +40 -0
- package/dist/cli/cli.d.mts +1 -0
- package/dist/cli/cli.d.ts +1 -0
- package/dist/cli/cli.js +7090 -0
- package/dist/cli/cli.mjs +251 -0
- package/dist/config/node.d.mts +15 -0
- package/dist/config/node.d.ts +15 -0
- package/dist/config/node.js +6850 -0
- package/dist/config/node.mjs +11 -0
- package/dist/index.d.mts +94 -1160
- package/dist/index.d.ts +94 -1160
- package/dist/index.js +431 -6
- package/dist/index.mjs +503 -7175
- package/dist/types-CDOBItt6.d.mts +1223 -0
- package/dist/types-CDOBItt6.d.ts +1223 -0
- package/package.json +15 -3
- package/readme.md +1 -1
package/dist/cli/cli.mjs
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
loadConfigFromUrl
|
|
4
|
+
} from "../chunk-7W6GBE2Y.mjs";
|
|
5
|
+
import {
|
|
6
|
+
loadConfigFromFile
|
|
7
|
+
} from "../chunk-PX2FFNZQ.mjs";
|
|
8
|
+
import {
|
|
9
|
+
executorFromConfig,
|
|
10
|
+
isLlmExeError
|
|
11
|
+
} from "../chunk-2BUGTOKA.mjs";
|
|
12
|
+
|
|
13
|
+
// src/cli/cli.ts
|
|
14
|
+
import { readFileSync } from "node:fs";
|
|
15
|
+
import { dirname, resolve } from "node:path";
|
|
16
|
+
|
|
17
|
+
// src/cli/args.ts
|
|
18
|
+
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
19
|
+
var BOOLEAN_FLAGS = {
|
|
20
|
+
json: "json",
|
|
21
|
+
debug: "debug",
|
|
22
|
+
remote: "remote",
|
|
23
|
+
help: "help",
|
|
24
|
+
h: "help",
|
|
25
|
+
version: "version",
|
|
26
|
+
v: "version"
|
|
27
|
+
};
|
|
28
|
+
var VALUE_FLAGS = /* @__PURE__ */ new Set(["model", "provider", "parser", "stdin"]);
|
|
29
|
+
function isPlainObject(value) {
|
|
30
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
31
|
+
}
|
|
32
|
+
function setNested(target, dottedKey, value) {
|
|
33
|
+
const parts = dottedKey.split(".").filter((p) => p.length > 0);
|
|
34
|
+
if (parts.length === 0) {
|
|
35
|
+
throw new Error("Use --data.<key> <value>, e.g. --data.name World");
|
|
36
|
+
}
|
|
37
|
+
for (const part of parts) {
|
|
38
|
+
if (FORBIDDEN_KEYS.has(part)) {
|
|
39
|
+
throw new Error(`Illegal key "${part}" in --data.${dottedKey}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
let node = target;
|
|
43
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
44
|
+
const part = parts[i];
|
|
45
|
+
if (!isPlainObject(node[part])) {
|
|
46
|
+
node[part] = {};
|
|
47
|
+
}
|
|
48
|
+
node = node[part];
|
|
49
|
+
}
|
|
50
|
+
node[parts[parts.length - 1]] = value;
|
|
51
|
+
}
|
|
52
|
+
function parseArgs(argv) {
|
|
53
|
+
const result = {
|
|
54
|
+
data: {},
|
|
55
|
+
json: false,
|
|
56
|
+
debug: false,
|
|
57
|
+
remote: false,
|
|
58
|
+
help: false,
|
|
59
|
+
version: false
|
|
60
|
+
};
|
|
61
|
+
for (let i = 0; i < argv.length; i++) {
|
|
62
|
+
const token = argv[i];
|
|
63
|
+
if (!token.startsWith("-")) {
|
|
64
|
+
if (result.path !== void 0) {
|
|
65
|
+
throw new Error(`Unexpected argument: ${token}`);
|
|
66
|
+
}
|
|
67
|
+
result.path = token;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const raw = token.replace(/^--?/, "");
|
|
71
|
+
const eq = raw.indexOf("=");
|
|
72
|
+
const name = eq === -1 ? raw : raw.slice(0, eq);
|
|
73
|
+
const inlineValue = eq === -1 ? void 0 : raw.slice(eq + 1);
|
|
74
|
+
if (name in BOOLEAN_FLAGS) {
|
|
75
|
+
if (inlineValue !== void 0) {
|
|
76
|
+
throw new Error(`Option --${name} does not take a value`);
|
|
77
|
+
}
|
|
78
|
+
result[BOOLEAN_FLAGS[name]] = true;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const takeValue = () => {
|
|
82
|
+
if (inlineValue !== void 0) return inlineValue;
|
|
83
|
+
i++;
|
|
84
|
+
if (i >= argv.length) {
|
|
85
|
+
throw new Error(`Option --${name} requires a value`);
|
|
86
|
+
}
|
|
87
|
+
return argv[i];
|
|
88
|
+
};
|
|
89
|
+
if (name === "data") {
|
|
90
|
+
throw new Error("Use --data.<key> <value>, e.g. --data.name World");
|
|
91
|
+
}
|
|
92
|
+
if (name.startsWith("data.")) {
|
|
93
|
+
setNested(result.data, name.slice("data.".length), takeValue());
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (VALUE_FLAGS.has(name)) {
|
|
97
|
+
const value = takeValue();
|
|
98
|
+
if (name === "stdin") result.stdinKey = value;
|
|
99
|
+
else if (name === "model") result.model = value;
|
|
100
|
+
else if (name === "provider") result.provider = value;
|
|
101
|
+
else if (name === "parser") result.parser = value;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
throw new Error(`Unknown option: ${token}`);
|
|
105
|
+
}
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/cli/runCli.ts
|
|
110
|
+
var HELP = `llm-exe \u2014 run an llm-exe config file (no code required)
|
|
111
|
+
|
|
112
|
+
Usage:
|
|
113
|
+
llm-exe <path> [options]
|
|
114
|
+
cat input | llm-exe <path> --stdin <key>
|
|
115
|
+
|
|
116
|
+
Arguments:
|
|
117
|
+
<path> Path to a config file (.json, .yml, .yaml, .md),
|
|
118
|
+
or an http(s) URL with --remote
|
|
119
|
+
|
|
120
|
+
Options:
|
|
121
|
+
--data.<key> <value> Set a template variable (dotted keys nest)
|
|
122
|
+
--model <value> Override the config's model
|
|
123
|
+
--provider <value> Override the config's provider
|
|
124
|
+
--parser <value> Override the config's parser
|
|
125
|
+
--stdin <key> Bind piped stdin to a data variable
|
|
126
|
+
--json Print { result, metadata } as JSON to stdout
|
|
127
|
+
--debug Print execution metadata to stderr
|
|
128
|
+
--remote Allow fetching a config from an http(s) URL
|
|
129
|
+
-h, --help Show this help
|
|
130
|
+
-v, --version Show version
|
|
131
|
+
|
|
132
|
+
Auth uses the same environment variables as the package
|
|
133
|
+
(OPENAI_API_KEY, ANTHROPIC_API_KEY, ...). The result goes to stdout;
|
|
134
|
+
metadata and errors go to stderr, so it composes with pipes.`;
|
|
135
|
+
function isUrl(value) {
|
|
136
|
+
return /^https?:\/\//i.test(value);
|
|
137
|
+
}
|
|
138
|
+
function formatResult(result) {
|
|
139
|
+
if (typeof result === "string") return result;
|
|
140
|
+
return JSON.stringify(result, null, 2);
|
|
141
|
+
}
|
|
142
|
+
async function runCli(argv, io) {
|
|
143
|
+
let args;
|
|
144
|
+
try {
|
|
145
|
+
args = parseArgs(argv);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
io.stderr(error.message);
|
|
148
|
+
io.stderr("Run `llm-exe --help` for usage.");
|
|
149
|
+
return 1;
|
|
150
|
+
}
|
|
151
|
+
if (args.help) {
|
|
152
|
+
io.stdout(HELP);
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
if (args.version) {
|
|
156
|
+
io.stdout(io.version);
|
|
157
|
+
return 0;
|
|
158
|
+
}
|
|
159
|
+
if (!args.path) {
|
|
160
|
+
io.stderr("Missing config path.");
|
|
161
|
+
io.stderr("Usage: llm-exe <path> [options] \u2014 see `llm-exe --help`.");
|
|
162
|
+
return 1;
|
|
163
|
+
}
|
|
164
|
+
if (isUrl(args.path) && !args.remote) {
|
|
165
|
+
io.stderr(
|
|
166
|
+
`Refusing to fetch a remote config without --remote: ${args.path}`
|
|
167
|
+
);
|
|
168
|
+
return 1;
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
const data = { ...args.data };
|
|
172
|
+
if (args.stdinKey) {
|
|
173
|
+
data[args.stdinKey] = await io.readStdin();
|
|
174
|
+
}
|
|
175
|
+
const patch = {};
|
|
176
|
+
if (args.model !== void 0) patch.model = args.model;
|
|
177
|
+
if (args.provider !== void 0) patch.provider = args.provider;
|
|
178
|
+
if (args.parser !== void 0) patch.parser = args.parser;
|
|
179
|
+
if (Object.keys(data).length > 0) patch.data = data;
|
|
180
|
+
const config = isUrl(args.path) ? await loadConfigFromUrl(args.path, patch) : await loadConfigFromFile(args.path, patch);
|
|
181
|
+
let metadata;
|
|
182
|
+
const executor = executorFromConfig(config, {
|
|
183
|
+
hooks: {
|
|
184
|
+
onComplete(meta) {
|
|
185
|
+
metadata = meta;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
const result = await executor.execute(
|
|
190
|
+
config.data ?? {},
|
|
191
|
+
config.executorOptions
|
|
192
|
+
);
|
|
193
|
+
if (args.debug) {
|
|
194
|
+
io.stderr(JSON.stringify(metadata, null, 2));
|
|
195
|
+
}
|
|
196
|
+
if (args.json) {
|
|
197
|
+
io.stdout(JSON.stringify({ result, metadata }, null, 2));
|
|
198
|
+
} else {
|
|
199
|
+
io.stdout(formatResult(result));
|
|
200
|
+
}
|
|
201
|
+
return 0;
|
|
202
|
+
} catch (error) {
|
|
203
|
+
if (isLlmExeError(error)) {
|
|
204
|
+
io.stderr(`Error [${error.code}]: ${error.message}`);
|
|
205
|
+
} else {
|
|
206
|
+
io.stderr(`Error: ${error?.message ?? String(error)}`);
|
|
207
|
+
}
|
|
208
|
+
return 1;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// src/cli/cli.ts
|
|
213
|
+
function readVersion() {
|
|
214
|
+
try {
|
|
215
|
+
const scriptPath = process.argv[1];
|
|
216
|
+
const pkgPath = resolve(dirname(scriptPath), "../../package.json");
|
|
217
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
218
|
+
return pkg.version ?? "unknown";
|
|
219
|
+
} catch {
|
|
220
|
+
return "unknown";
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
function readStdin() {
|
|
224
|
+
return new Promise((resolveFn) => {
|
|
225
|
+
if (process.stdin.isTTY) {
|
|
226
|
+
resolveFn("");
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
let data = "";
|
|
230
|
+
process.stdin.setEncoding("utf8");
|
|
231
|
+
process.stdin.on("data", (chunk) => data += chunk);
|
|
232
|
+
process.stdin.on("end", () => resolveFn(data));
|
|
233
|
+
process.stdin.on("error", () => resolveFn(data));
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
function write(stream, text) {
|
|
237
|
+
stream.write(text.endsWith("\n") ? text : `${text}
|
|
238
|
+
`);
|
|
239
|
+
}
|
|
240
|
+
runCli(process.argv.slice(2), {
|
|
241
|
+
stdout: (text) => write(process.stdout, text),
|
|
242
|
+
stderr: (text) => write(process.stderr, text),
|
|
243
|
+
readStdin,
|
|
244
|
+
version: readVersion()
|
|
245
|
+
}).then((code) => {
|
|
246
|
+
process.exitCode = code;
|
|
247
|
+
}).catch((error) => {
|
|
248
|
+
process.stderr.write(`Fatal: ${error?.message ?? String(error)}
|
|
249
|
+
`);
|
|
250
|
+
process.exitCode = 1;
|
|
251
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { E as ExecutorConfigPatch, a as ExecutorConfig, b as ExecutorCreateOptions, L as LlmExecutor, R as RunOverrides } from '../types-CDOBItt6.mjs';
|
|
2
|
+
import 'json-schema-to-ts';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Read and normalize a config from a file path. Format is inferred from the
|
|
6
|
+
* extension, falling back to "auto". NODE-ONLY (`node:fs/promises`) — reached
|
|
7
|
+
* via the `llm-exe/node` subpath, never from the browser-safe root barrel.
|
|
8
|
+
*/
|
|
9
|
+
declare function loadConfigFromFile(path: string, patch?: ExecutorConfigPatch): Promise<ExecutorConfig>;
|
|
10
|
+
/** Assemble a native executor from a config file. Mirrors `executorFromConfig`. */
|
|
11
|
+
declare function executorFromFile(path: string, patch?: ExecutorConfigPatch, createOptions?: ExecutorCreateOptions): Promise<LlmExecutor<any, any, any, any>>;
|
|
12
|
+
/** Run a config file once, binding config defaults. The CLI's primitive. */
|
|
13
|
+
declare function runFile(path: string, patch?: ExecutorConfigPatch, overrides?: RunOverrides, createOptions?: ExecutorCreateOptions): Promise<unknown>;
|
|
14
|
+
|
|
15
|
+
export { executorFromFile, loadConfigFromFile, runFile };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { E as ExecutorConfigPatch, a as ExecutorConfig, b as ExecutorCreateOptions, L as LlmExecutor, R as RunOverrides } from '../types-CDOBItt6.js';
|
|
2
|
+
import 'json-schema-to-ts';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Read and normalize a config from a file path. Format is inferred from the
|
|
6
|
+
* extension, falling back to "auto". NODE-ONLY (`node:fs/promises`) — reached
|
|
7
|
+
* via the `llm-exe/node` subpath, never from the browser-safe root barrel.
|
|
8
|
+
*/
|
|
9
|
+
declare function loadConfigFromFile(path: string, patch?: ExecutorConfigPatch): Promise<ExecutorConfig>;
|
|
10
|
+
/** Assemble a native executor from a config file. Mirrors `executorFromConfig`. */
|
|
11
|
+
declare function executorFromFile(path: string, patch?: ExecutorConfigPatch, createOptions?: ExecutorCreateOptions): Promise<LlmExecutor<any, any, any, any>>;
|
|
12
|
+
/** Run a config file once, binding config defaults. The CLI's primitive. */
|
|
13
|
+
declare function runFile(path: string, patch?: ExecutorConfigPatch, overrides?: RunOverrides, createOptions?: ExecutorCreateOptions): Promise<unknown>;
|
|
14
|
+
|
|
15
|
+
export { executorFromFile, loadConfigFromFile, runFile };
|