@lumerahq/cli 0.30.2 → 0.30.3-dev.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/dist/{chunk-YMWDIAUG.js → chunk-2K2LYH5O.js} +1 -1
- package/dist/{chunk-LVIIWE44.js → chunk-ASPEK3I6.js} +1 -1
- package/dist/{chunk-U3ZLIXGD.js → chunk-KZEOP5YF.js} +6 -0
- package/dist/{deps-NHVL4DMD.js → deps-22CUIP2M.js} +2 -2
- package/dist/{dev-IWTA5G5M.js → dev-XBOHUDPR.js} +3 -3
- package/dist/index.js +12 -12
- package/dist/{init-I4FECTEL.js → init-L6D5OHMY.js} +1 -1
- package/dist/{register-OBQZPOGC.js → register-SBXONOFY.js} +1 -1
- package/dist/{resources-5YWEX6DG.js → resources-ZSFI5CJM.js} +128 -31
- package/dist/{run-SLLDX3RF.js → run-EBTA3FKD.js} +1 -1
- package/package.json +1 -1
|
@@ -282,6 +282,12 @@ var ApiClient = class {
|
|
|
282
282
|
const result = await this.request(`/api/agents?${params}`);
|
|
283
283
|
return result.agents || [];
|
|
284
284
|
}
|
|
285
|
+
async compileAgentPolicy(script) {
|
|
286
|
+
await this.request("/api/agents/policy/compile", {
|
|
287
|
+
method: "POST",
|
|
288
|
+
body: JSON.stringify({ script })
|
|
289
|
+
});
|
|
290
|
+
}
|
|
285
291
|
async createAgent(def) {
|
|
286
292
|
return this.request("/api/agents", {
|
|
287
293
|
method: "POST",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deps,
|
|
3
3
|
syncDeps
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2K2LYH5O.js";
|
|
5
5
|
import "./chunk-2CR762KB.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-KZEOP5YF.js";
|
|
7
7
|
import "./chunk-JLVVHTBY.js";
|
|
8
8
|
import "./chunk-FJFIWC7G.js";
|
|
9
9
|
import "./chunk-PNKVD2UK.js";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
dev
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ASPEK3I6.js";
|
|
4
4
|
import {
|
|
5
5
|
syncDeps
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2K2LYH5O.js";
|
|
7
7
|
import {
|
|
8
8
|
loadEnv
|
|
9
9
|
} from "./chunk-2CR762KB.js";
|
|
10
10
|
import {
|
|
11
11
|
createApiClient
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-KZEOP5YF.js";
|
|
13
13
|
import {
|
|
14
14
|
findProjectRoot,
|
|
15
15
|
getApiUrl,
|
package/dist/index.js
CHANGED
|
@@ -240,32 +240,32 @@ async function main() {
|
|
|
240
240
|
switch (command) {
|
|
241
241
|
// Resource commands
|
|
242
242
|
case "plan":
|
|
243
|
-
await import("./resources-
|
|
243
|
+
await import("./resources-ZSFI5CJM.js").then((m) => m.plan(args.slice(1)));
|
|
244
244
|
break;
|
|
245
245
|
case "apply":
|
|
246
|
-
await import("./resources-
|
|
246
|
+
await import("./resources-ZSFI5CJM.js").then((m) => m.apply(args.slice(1)));
|
|
247
247
|
break;
|
|
248
248
|
case "pull":
|
|
249
|
-
await import("./resources-
|
|
249
|
+
await import("./resources-ZSFI5CJM.js").then((m) => m.pull(args.slice(1)));
|
|
250
250
|
break;
|
|
251
251
|
case "destroy":
|
|
252
|
-
await import("./resources-
|
|
252
|
+
await import("./resources-ZSFI5CJM.js").then((m) => m.destroy(args.slice(1)));
|
|
253
253
|
break;
|
|
254
254
|
case "list":
|
|
255
|
-
await import("./resources-
|
|
255
|
+
await import("./resources-ZSFI5CJM.js").then((m) => m.list(args.slice(1)));
|
|
256
256
|
break;
|
|
257
257
|
case "show":
|
|
258
|
-
await import("./resources-
|
|
258
|
+
await import("./resources-ZSFI5CJM.js").then((m) => m.show(args.slice(1)));
|
|
259
259
|
break;
|
|
260
260
|
case "diff":
|
|
261
|
-
await import("./resources-
|
|
261
|
+
await import("./resources-ZSFI5CJM.js").then((m) => m.diff(args.slice(1)));
|
|
262
262
|
break;
|
|
263
263
|
// Development
|
|
264
264
|
case "dev":
|
|
265
|
-
await import("./dev-
|
|
265
|
+
await import("./dev-XBOHUDPR.js").then((m) => m.dev(args.slice(1)));
|
|
266
266
|
break;
|
|
267
267
|
case "run":
|
|
268
|
-
await import("./run-
|
|
268
|
+
await import("./run-EBTA3FKD.js").then((m) => m.run(args.slice(1)));
|
|
269
269
|
break;
|
|
270
270
|
case "functions":
|
|
271
271
|
await import("./functions-55J6E2RF.js").then(
|
|
@@ -279,10 +279,10 @@ async function main() {
|
|
|
279
279
|
break;
|
|
280
280
|
// Project
|
|
281
281
|
case "init":
|
|
282
|
-
await import("./init-
|
|
282
|
+
await import("./init-L6D5OHMY.js").then((m) => m.init(args.slice(1)));
|
|
283
283
|
break;
|
|
284
284
|
case "register":
|
|
285
|
-
await import("./register-
|
|
285
|
+
await import("./register-SBXONOFY.js").then((m) => m.register(args.slice(1)));
|
|
286
286
|
break;
|
|
287
287
|
case "templates":
|
|
288
288
|
await import("./templates-LNUOTNLN.js").then((m) => m.templates(subcommand, args.slice(2)));
|
|
@@ -299,7 +299,7 @@ async function main() {
|
|
|
299
299
|
break;
|
|
300
300
|
// Dependencies
|
|
301
301
|
case "deps":
|
|
302
|
-
await import("./deps-
|
|
302
|
+
await import("./deps-22CUIP2M.js").then((m) => m.deps(args.slice(1)));
|
|
303
303
|
break;
|
|
304
304
|
// Feature flags (read the in-sandbox snapshot)
|
|
305
305
|
case "flags":
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deploy
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ASPEK3I6.js";
|
|
4
4
|
import {
|
|
5
5
|
syncDeps
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2K2LYH5O.js";
|
|
7
7
|
import {
|
|
8
8
|
loadEnv
|
|
9
9
|
} from "./chunk-2CR762KB.js";
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
createApiClient,
|
|
13
13
|
isApiErrorStatus,
|
|
14
14
|
validateCollectionNameLength
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-KZEOP5YF.js";
|
|
16
16
|
import {
|
|
17
17
|
findProjectRoot,
|
|
18
18
|
getApiUrl,
|
|
@@ -38,6 +38,32 @@ import { join as join2, resolve } from "path";
|
|
|
38
38
|
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
39
39
|
import { basename, dirname, join } from "path";
|
|
40
40
|
|
|
41
|
+
// src/lib/lint/rules/agent-policy-compile.ts
|
|
42
|
+
function compileError(target, message) {
|
|
43
|
+
return {
|
|
44
|
+
ruleId: "agent-policy-compile",
|
|
45
|
+
target,
|
|
46
|
+
severity: "error",
|
|
47
|
+
message
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
var agentPolicyCompileRule = {
|
|
51
|
+
id: "agent-policy-compile",
|
|
52
|
+
description: "Verifies agent policy scripts compile with the backend runtime compiler.",
|
|
53
|
+
appliesTo: ["agent-policy"],
|
|
54
|
+
async check(target, ctx) {
|
|
55
|
+
if (!target.source.trim() || !ctx.api) return [];
|
|
56
|
+
const script = ctx.appName ? target.source.replaceAll("{{app}}", ctx.appName) : target.source;
|
|
57
|
+
try {
|
|
58
|
+
await ctx.api.compileAgentPolicy(script);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
const detail = err instanceof ApiError ? err.body.trim() : err instanceof Error ? err.message : String(err);
|
|
61
|
+
return [compileError(target, `Agent policy failed to compile on the backend: ${detail}`)];
|
|
62
|
+
}
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
41
67
|
// src/lib/lint/rules/automation-config.ts
|
|
42
68
|
function isRecord(value) {
|
|
43
69
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -776,6 +802,7 @@ var llmImportRule = {
|
|
|
776
802
|
|
|
777
803
|
// src/lib/lint/registry.ts
|
|
778
804
|
var ALL_RULES = [
|
|
805
|
+
agentPolicyCompileRule,
|
|
779
806
|
automationConfigRule,
|
|
780
807
|
automationMainGuardRule,
|
|
781
808
|
collectionSchemaRule,
|
|
@@ -889,6 +916,42 @@ function buildHookTargets(platformDir, filterName) {
|
|
|
889
916
|
}
|
|
890
917
|
return targets;
|
|
891
918
|
}
|
|
919
|
+
function buildAgentPolicyTargets(platformDir, filterName, appName) {
|
|
920
|
+
const agentsDir = join(platformDir, "agents");
|
|
921
|
+
if (!existsSync(agentsDir)) return [];
|
|
922
|
+
const targets = [];
|
|
923
|
+
for (const entry of readdirSync(agentsDir, { withFileTypes: true })) {
|
|
924
|
+
if (!entry.isDirectory()) continue;
|
|
925
|
+
const agentDir = join(agentsDir, entry.name);
|
|
926
|
+
const policyPath = join(agentDir, "policy.js");
|
|
927
|
+
if (!existsSync(policyPath)) continue;
|
|
928
|
+
let externalID = appName ? `${appName}:${entry.name}` : "";
|
|
929
|
+
let displayName = "";
|
|
930
|
+
const configPath = join(agentDir, "config.json");
|
|
931
|
+
if (existsSync(configPath)) {
|
|
932
|
+
try {
|
|
933
|
+
const config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
934
|
+
if (typeof config.external_id === "string" && config.external_id.trim()) {
|
|
935
|
+
externalID = config.external_id;
|
|
936
|
+
}
|
|
937
|
+
if (typeof config.name === "string") {
|
|
938
|
+
displayName = config.name;
|
|
939
|
+
}
|
|
940
|
+
} catch {
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
if (filterName && entry.name !== filterName && externalID !== filterName && displayName !== filterName) {
|
|
944
|
+
continue;
|
|
945
|
+
}
|
|
946
|
+
targets.push({
|
|
947
|
+
kind: "agent-policy",
|
|
948
|
+
name: externalID || displayName || entry.name,
|
|
949
|
+
filePath: policyPath,
|
|
950
|
+
source: readFileSync(policyPath, "utf-8")
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
return targets;
|
|
954
|
+
}
|
|
892
955
|
|
|
893
956
|
// src/commands/resources.ts
|
|
894
957
|
init_auth();
|
|
@@ -940,6 +1003,18 @@ async function lintHookFiles(api, projectRoot, platformDir, appName, filterName)
|
|
|
940
1003
|
throw new Error(`Found ${result.errors.length} hook lint error(s)`);
|
|
941
1004
|
}
|
|
942
1005
|
}
|
|
1006
|
+
async function lintAgentPolicyFiles(api, projectRoot, platformDir, appName, filterName) {
|
|
1007
|
+
const result = await safeLintPass("agent policy", async () => {
|
|
1008
|
+
const targets = buildAgentPolicyTargets(platformDir, filterName, appName);
|
|
1009
|
+
if (targets.length === 0) return [];
|
|
1010
|
+
return runLint({ projectRoot, targets, api, appName });
|
|
1011
|
+
});
|
|
1012
|
+
if (!result || result.issues.length === 0) return;
|
|
1013
|
+
safePrintLint(result.issues, projectRoot);
|
|
1014
|
+
if (result.errors.length > 0) {
|
|
1015
|
+
throw new Error(`Found ${result.errors.length} agent policy lint error(s)`);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
943
1018
|
var PACKAGE_MANAGERS = ["bun", "pnpm", "yarn", "npm"];
|
|
944
1019
|
var PACKAGE_MANAGER_VALUE_FLAGS = /* @__PURE__ */ new Set(["--package-manager"]);
|
|
945
1020
|
function isPackageManager(value) {
|
|
@@ -2177,6 +2252,8 @@ async function applyAutomations(api, localAutomations, projectId) {
|
|
|
2177
2252
|
const remoteByExternalId = new Map(remoteAutomations.filter((a) => a.external_id).map((a) => [a.external_id, a]));
|
|
2178
2253
|
for (const { automation, code } of localAutomations) {
|
|
2179
2254
|
const remote = remoteByExternalId.get(automation.external_id);
|
|
2255
|
+
const appliedAction = remote ? "updated" : "created";
|
|
2256
|
+
let baseApplied = false;
|
|
2180
2257
|
const payload = {
|
|
2181
2258
|
external_id: automation.external_id,
|
|
2182
2259
|
name: automation.name,
|
|
@@ -2194,35 +2271,35 @@ async function applyAutomations(api, localAutomations, projectId) {
|
|
|
2194
2271
|
if (remote) {
|
|
2195
2272
|
await api.updateAutomation(remote.id, payload);
|
|
2196
2273
|
automationId = remote.id;
|
|
2197
|
-
console.log(pc2.green(" \u2713"), `${automation.name} (updated)`);
|
|
2198
2274
|
} else {
|
|
2199
2275
|
const created = await api.createAutomation(payload);
|
|
2200
2276
|
automationId = created.id;
|
|
2201
|
-
console.log(pc2.green(" \u2713"), `${automation.name} (created)`);
|
|
2202
2277
|
}
|
|
2278
|
+
baseApplied = true;
|
|
2203
2279
|
const localPresets = automation.inputs?.presets;
|
|
2280
|
+
let current;
|
|
2204
2281
|
if (localPresets) {
|
|
2205
2282
|
await syncPresets(api, automationId, localPresets);
|
|
2206
2283
|
}
|
|
2207
2284
|
if (automation.schedule) {
|
|
2208
|
-
await setSchedule(api, automationId, automation.schedule, localPresets || {});
|
|
2285
|
+
current = await setSchedule(api, automationId, automation.schedule, localPresets || {});
|
|
2209
2286
|
} else if (remote?.schedule) {
|
|
2210
2287
|
await api.updateAutomation(automationId, { schedule: "", schedule_tz: "" });
|
|
2211
2288
|
console.log(pc2.dim(` Cleared schedule`));
|
|
2212
2289
|
}
|
|
2213
2290
|
if (localPresets) {
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
);
|
|
2222
|
-
}
|
|
2291
|
+
current ??= await api.getAutomation(automationId);
|
|
2292
|
+
await deleteStalePresets(
|
|
2293
|
+
api,
|
|
2294
|
+
automationId,
|
|
2295
|
+
localPresets,
|
|
2296
|
+
current.schedule_preset_id ? /* @__PURE__ */ new Set([current.schedule_preset_id]) : /* @__PURE__ */ new Set()
|
|
2297
|
+
);
|
|
2223
2298
|
}
|
|
2299
|
+
console.log(pc2.green(" \u2713"), `${automation.name} (${appliedAction})`);
|
|
2224
2300
|
} catch (e) {
|
|
2225
|
-
|
|
2301
|
+
const partialState = baseApplied ? ` (${appliedAction}, configuration failed)` : "";
|
|
2302
|
+
console.log(pc2.red(" \u2717"), `${automation.name}${partialState}: ${e}`);
|
|
2226
2303
|
errors++;
|
|
2227
2304
|
}
|
|
2228
2305
|
}
|
|
@@ -2234,16 +2311,20 @@ async function syncPresets(api, automationId, localPresets) {
|
|
|
2234
2311
|
for (const [presetKey, preset] of Object.entries(localPresets)) {
|
|
2235
2312
|
const presetName = preset.label || presetKey;
|
|
2236
2313
|
const existing = remoteByName.get(presetName);
|
|
2237
|
-
|
|
2238
|
-
|
|
2314
|
+
if (existing) {
|
|
2315
|
+
try {
|
|
2239
2316
|
await api.updatePreset(existing.id, { name: presetName, inputs: preset.inputs });
|
|
2240
2317
|
console.log(pc2.dim(` Updated preset: ${presetName}`));
|
|
2241
|
-
}
|
|
2318
|
+
} catch (e) {
|
|
2319
|
+
throw new Error(`Failed to update preset '${presetName}': ${String(e)}`);
|
|
2320
|
+
}
|
|
2321
|
+
} else {
|
|
2322
|
+
try {
|
|
2242
2323
|
await api.createPreset(automationId, { name: presetName, inputs: preset.inputs });
|
|
2243
2324
|
console.log(pc2.dim(` Created preset: ${presetName}`));
|
|
2325
|
+
} catch (e) {
|
|
2326
|
+
throw new Error(`Failed to create preset '${presetName}': ${String(e)}`);
|
|
2244
2327
|
}
|
|
2245
|
-
} catch (e) {
|
|
2246
|
-
console.log(pc2.yellow(` \u26A0 Failed to sync preset ${presetName}: ${e}`));
|
|
2247
2328
|
}
|
|
2248
2329
|
}
|
|
2249
2330
|
}
|
|
@@ -2260,7 +2341,7 @@ async function deleteStalePresets(api, automationId, localPresets, preservePrese
|
|
|
2260
2341
|
await api.deletePreset(remote.id);
|
|
2261
2342
|
console.log(pc2.dim(` Deleted preset: ${remote.name}`));
|
|
2262
2343
|
} catch (e) {
|
|
2263
|
-
|
|
2344
|
+
throw new Error(`Failed to delete preset '${remote.name}': ${String(e)}`);
|
|
2264
2345
|
}
|
|
2265
2346
|
}
|
|
2266
2347
|
}
|
|
@@ -2269,19 +2350,28 @@ async function setSchedule(api, automationId, schedule, localPresets) {
|
|
|
2269
2350
|
const remotePresets = await api.listPresets(automationId);
|
|
2270
2351
|
const preset = remotePresets.find((p) => p.name === presetName);
|
|
2271
2352
|
if (!preset) {
|
|
2272
|
-
|
|
2273
|
-
return;
|
|
2353
|
+
throw new Error(`Schedule preset '${presetName}' not found`);
|
|
2274
2354
|
}
|
|
2355
|
+
const expectedSchedule = {
|
|
2356
|
+
schedule: schedule.cron,
|
|
2357
|
+
schedule_tz: schedule.timezone || "UTC",
|
|
2358
|
+
schedule_preset_id: preset.id
|
|
2359
|
+
};
|
|
2360
|
+
await api.updateAutomation(automationId, expectedSchedule);
|
|
2361
|
+
let persisted;
|
|
2275
2362
|
try {
|
|
2276
|
-
await api.
|
|
2277
|
-
schedule: schedule.cron,
|
|
2278
|
-
schedule_tz: schedule.timezone || "UTC",
|
|
2279
|
-
schedule_preset_id: preset.id
|
|
2280
|
-
});
|
|
2281
|
-
console.log(pc2.dim(` Set schedule: ${schedule.cron}`));
|
|
2363
|
+
persisted = await api.getAutomation(automationId);
|
|
2282
2364
|
} catch (e) {
|
|
2283
|
-
|
|
2365
|
+
throw new Error(`Failed to verify persisted schedule: ${String(e)}`);
|
|
2366
|
+
}
|
|
2367
|
+
const mismatches = Object.keys(expectedSchedule).filter((field) => persisted[field] !== expectedSchedule[field]).map(
|
|
2368
|
+
(field) => `${field} expected ${JSON.stringify(expectedSchedule[field])}, got ${JSON.stringify(persisted[field])}`
|
|
2369
|
+
);
|
|
2370
|
+
if (mismatches.length > 0) {
|
|
2371
|
+
throw new Error(`Schedule update was not persisted: ${mismatches.join("; ")}`);
|
|
2284
2372
|
}
|
|
2373
|
+
console.log(pc2.dim(` Set schedule: ${schedule.cron}`));
|
|
2374
|
+
return persisted;
|
|
2285
2375
|
}
|
|
2286
2376
|
async function applyHooks(api, localHooks, collections, projectId) {
|
|
2287
2377
|
let errors = 0;
|
|
@@ -3733,6 +3823,9 @@ async function plan(args) {
|
|
|
3733
3823
|
if (!type || type === "hooks") {
|
|
3734
3824
|
await lintHookFiles(api, projectRoot, platformDir, appName, name || void 0);
|
|
3735
3825
|
}
|
|
3826
|
+
if (!type || type === "agents") {
|
|
3827
|
+
await lintAgentPolicyFiles(api, projectRoot, platformDir, appName, name || void 0);
|
|
3828
|
+
}
|
|
3736
3829
|
await syncDeps(projectRoot, { ignorePermissionDenied: true });
|
|
3737
3830
|
const allChanges = [];
|
|
3738
3831
|
let planValidationErrors = 0;
|
|
@@ -3900,6 +3993,9 @@ async function apply(args) {
|
|
|
3900
3993
|
if (!type || type === "hooks") {
|
|
3901
3994
|
await lintHookFiles(api, projectRoot, platformDir, appName, name || void 0);
|
|
3902
3995
|
}
|
|
3996
|
+
if (!type || type === "agents") {
|
|
3997
|
+
await lintAgentPolicyFiles(api, projectRoot, platformDir, appName, name || void 0);
|
|
3998
|
+
}
|
|
3903
3999
|
await syncDeps(projectRoot, { ignorePermissionDenied: true });
|
|
3904
4000
|
let collections;
|
|
3905
4001
|
try {
|
|
@@ -4519,6 +4615,7 @@ async function diff(args) {
|
|
|
4519
4615
|
export {
|
|
4520
4616
|
apply,
|
|
4521
4617
|
applyAgents,
|
|
4618
|
+
applyAutomations,
|
|
4522
4619
|
applyCollections,
|
|
4523
4620
|
applySkills,
|
|
4524
4621
|
convertCollectionToApiFormat,
|