@lumerahq/cli 0.30.0-dev.0 → 0.30.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/index.js
CHANGED
|
@@ -240,25 +240,25 @@ async function main() {
|
|
|
240
240
|
switch (command) {
|
|
241
241
|
// Resource commands
|
|
242
242
|
case "plan":
|
|
243
|
-
await import("./resources-
|
|
243
|
+
await import("./resources-5YWEX6DG.js").then((m) => m.plan(args.slice(1)));
|
|
244
244
|
break;
|
|
245
245
|
case "apply":
|
|
246
|
-
await import("./resources-
|
|
246
|
+
await import("./resources-5YWEX6DG.js").then((m) => m.apply(args.slice(1)));
|
|
247
247
|
break;
|
|
248
248
|
case "pull":
|
|
249
|
-
await import("./resources-
|
|
249
|
+
await import("./resources-5YWEX6DG.js").then((m) => m.pull(args.slice(1)));
|
|
250
250
|
break;
|
|
251
251
|
case "destroy":
|
|
252
|
-
await import("./resources-
|
|
252
|
+
await import("./resources-5YWEX6DG.js").then((m) => m.destroy(args.slice(1)));
|
|
253
253
|
break;
|
|
254
254
|
case "list":
|
|
255
|
-
await import("./resources-
|
|
255
|
+
await import("./resources-5YWEX6DG.js").then((m) => m.list(args.slice(1)));
|
|
256
256
|
break;
|
|
257
257
|
case "show":
|
|
258
|
-
await import("./resources-
|
|
258
|
+
await import("./resources-5YWEX6DG.js").then((m) => m.show(args.slice(1)));
|
|
259
259
|
break;
|
|
260
260
|
case "diff":
|
|
261
|
-
await import("./resources-
|
|
261
|
+
await import("./resources-5YWEX6DG.js").then((m) => m.diff(args.slice(1)));
|
|
262
262
|
break;
|
|
263
263
|
// Development
|
|
264
264
|
case "dev":
|
|
@@ -2578,7 +2578,7 @@ function remoteSkillsByLocalSlug(remoteSkills, appName) {
|
|
|
2578
2578
|
function projectSkillRefCandidates(refs, appName) {
|
|
2579
2579
|
return [...new Set(refs.flatMap((ref) => appName && SKILL_SLUG_RE.test(ref) ? [scopedProjectSkillSlug(appName, ref), ref] : [ref]))];
|
|
2580
2580
|
}
|
|
2581
|
-
async function resolveAgentSkillRefs(api, refs, projectId, appName,
|
|
2581
|
+
async function resolveAgentSkillRefs(api, refs, projectId, appName, localSourceSkillSlugs = /* @__PURE__ */ new Set()) {
|
|
2582
2582
|
const refToId = /* @__PURE__ */ new Map();
|
|
2583
2583
|
const skillIdToSlug = /* @__PURE__ */ new Map();
|
|
2584
2584
|
const blockedRefs = /* @__PURE__ */ new Set();
|
|
@@ -2605,7 +2605,7 @@ async function resolveAgentSkillRefs(api, refs, projectId, appName, pendingLocal
|
|
|
2605
2605
|
let selected = byID.get(ref);
|
|
2606
2606
|
if (!selected && SKILL_SLUG_RE.test(ref)) {
|
|
2607
2607
|
selected = projectByLocalSlug.get(ref);
|
|
2608
|
-
if (!selected &&
|
|
2608
|
+
if (!selected && localSourceSkillSlugs.has(ref)) {
|
|
2609
2609
|
continue;
|
|
2610
2610
|
}
|
|
2611
2611
|
}
|
|
@@ -2795,8 +2795,9 @@ function loadLocalAgents(platformDir, filterName, appName) {
|
|
|
2795
2795
|
}
|
|
2796
2796
|
return agents;
|
|
2797
2797
|
}
|
|
2798
|
-
async function planAgents(api, localAgents, projectId,
|
|
2798
|
+
async function planAgents(api, localAgents, projectId, localSourceSkillSlugs = /* @__PURE__ */ new Set(), pendingLocalSkillSlugs = /* @__PURE__ */ new Set(), appName) {
|
|
2799
2799
|
const changes = [];
|
|
2800
|
+
let validationErrors = 0;
|
|
2800
2801
|
const remoteAgents = await api.listAgents(projectId ? { project_id: projectId } : void 0);
|
|
2801
2802
|
const remoteByExternalId = new Map(
|
|
2802
2803
|
remoteAgents.filter((a) => a.external_id && !a.managed).map((a) => [a.external_id, a])
|
|
@@ -2814,7 +2815,7 @@ async function planAgents(api, localAgents, projectId, localSkillSlugs = /* @__P
|
|
|
2814
2815
|
outsideProjectRefs: /* @__PURE__ */ new Set()
|
|
2815
2816
|
};
|
|
2816
2817
|
try {
|
|
2817
|
-
resolution = await resolveAgentSkillRefs(api, planRefs, projectId, appName,
|
|
2818
|
+
resolution = await resolveAgentSkillRefs(api, planRefs, projectId, appName, localSourceSkillSlugs);
|
|
2818
2819
|
} catch (e) {
|
|
2819
2820
|
console.log(pc2.yellow(` \u26A0 Could not resolve skills for plan: ${e}`));
|
|
2820
2821
|
}
|
|
@@ -2824,10 +2825,17 @@ async function planAgents(api, localAgents, projectId, localSkillSlugs = /* @__P
|
|
|
2824
2825
|
for (const ref of agent.skills ?? []) {
|
|
2825
2826
|
if (outsideProjectRefs.has(ref)) {
|
|
2826
2827
|
console.log(pc2.red(` \u2717 Skill "${ref}" belongs to another project \u2014 apply will fail for this agent`));
|
|
2828
|
+
validationErrors++;
|
|
2827
2829
|
} else if (blockedRefs.has(ref)) {
|
|
2828
2830
|
console.log(pc2.red(` \u2717 Skill "${ref}" is a Lumera platform skill, only available to Lumera-built agents \u2014 apply will fail for this agent`));
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
+
validationErrors++;
|
|
2832
|
+
} else if (!refToId.has(ref) && !pendingLocalSkillSlugs.has(ref)) {
|
|
2833
|
+
if (localSourceSkillSlugs.has(ref)) {
|
|
2834
|
+
console.log(pc2.red(` \u2717 Skill "${ref}" exists in project source but is not deployed \u2014 run 'lumera apply skills' first or use 'lumera apply'`));
|
|
2835
|
+
} else {
|
|
2836
|
+
console.log(pc2.red(` \u2717 Skill "${ref}" not found \u2014 apply will fail for this agent`));
|
|
2837
|
+
}
|
|
2838
|
+
validationErrors++;
|
|
2831
2839
|
}
|
|
2832
2840
|
}
|
|
2833
2841
|
if (!remote) {
|
|
@@ -2844,14 +2852,14 @@ async function planAgents(api, localAgents, projectId, localSkillSlugs = /* @__P
|
|
|
2844
2852
|
if ((remote.policy_enabled || false) !== (agent.policy_enabled || false)) diffs.push("policy_enabled");
|
|
2845
2853
|
if ((remote.policy_description || "") !== (agent.policy_description || "")) diffs.push("policy_description");
|
|
2846
2854
|
const localSkillIds = (agent.skills || []).map((s) => refToId.get(s)).filter((id) => !!id).sort();
|
|
2847
|
-
const
|
|
2855
|
+
const pendingSkillSlugs = (agent.skills || []).filter((ref) => pendingLocalSkillSlugs.has(ref) && !refToId.has(ref));
|
|
2848
2856
|
const remoteSkillIds = [...remote.skill_ids || []].sort();
|
|
2849
|
-
if (localSkillIds.join(",") !== remoteSkillIds.join(",") ||
|
|
2857
|
+
if (localSkillIds.join(",") !== remoteSkillIds.join(",") || pendingSkillSlugs.length > 0) {
|
|
2850
2858
|
const addedSlugs = localSkillIds.filter((id) => !remoteSkillIds.includes(id)).map((id) => skillIdToSlug.get(id) || id);
|
|
2851
2859
|
const removedSlugs = remoteSkillIds.filter((id) => !localSkillIds.includes(id)).map((id) => skillIdToSlug.get(id) || id);
|
|
2852
2860
|
const parts = [];
|
|
2853
2861
|
if (addedSlugs.length) parts.push(`+${addedSlugs.join(", +")}`);
|
|
2854
|
-
if (
|
|
2862
|
+
if (pendingSkillSlugs.length) parts.push(`+${pendingSkillSlugs.join(", +")}`);
|
|
2855
2863
|
if (removedSlugs.length) parts.push(`-${removedSlugs.join(", -")}`);
|
|
2856
2864
|
diffs.push(`skills (${parts.join(", ")})`);
|
|
2857
2865
|
}
|
|
@@ -2867,14 +2875,14 @@ async function planAgents(api, localAgents, projectId, localSkillSlugs = /* @__P
|
|
|
2867
2875
|
}
|
|
2868
2876
|
}
|
|
2869
2877
|
}
|
|
2870
|
-
return changes;
|
|
2878
|
+
return { changes, validationErrors };
|
|
2871
2879
|
}
|
|
2872
2880
|
var TAG_AVAILABLE_TO_CUSTOM_AGENTS = "available_to_custom_agents";
|
|
2873
2881
|
function isAvailableToCustomAgents(skill) {
|
|
2874
2882
|
if (!skill.managed) return true;
|
|
2875
2883
|
return (skill.tags ?? []).includes(TAG_AVAILABLE_TO_CUSTOM_AGENTS);
|
|
2876
2884
|
}
|
|
2877
|
-
async function applyAgents(api, localAgents, projectId,
|
|
2885
|
+
async function applyAgents(api, localAgents, projectId, localSourceSkillSlugs = /* @__PURE__ */ new Set(), appName) {
|
|
2878
2886
|
let errors = 0;
|
|
2879
2887
|
const remoteAgents = await api.listAgents(projectId ? { project_id: projectId } : void 0);
|
|
2880
2888
|
const remoteByExternalId = new Map(
|
|
@@ -2888,7 +2896,7 @@ async function applyAgents(api, localAgents, projectId, localSkillSlugs = /* @__
|
|
|
2888
2896
|
outsideProjectRefs: /* @__PURE__ */ new Set()
|
|
2889
2897
|
};
|
|
2890
2898
|
try {
|
|
2891
|
-
resolution = await resolveAgentSkillRefs(api, refs, projectId, appName,
|
|
2899
|
+
resolution = await resolveAgentSkillRefs(api, refs, projectId, appName, localSourceSkillSlugs);
|
|
2892
2900
|
} catch (e) {
|
|
2893
2901
|
console.log(pc2.yellow(` \u26A0 Could not resolve skills: ${e}`));
|
|
2894
2902
|
}
|
|
@@ -2898,6 +2906,7 @@ async function applyAgents(api, localAgents, projectId, localSkillSlugs = /* @__
|
|
|
2898
2906
|
const skillIds = [];
|
|
2899
2907
|
const outsideProjectForAgent = [];
|
|
2900
2908
|
const blockedForAgent = [];
|
|
2909
|
+
const undeployedLocalForAgent = [];
|
|
2901
2910
|
const notFoundForAgent = [];
|
|
2902
2911
|
if (agent.skills) {
|
|
2903
2912
|
for (const ref of agent.skills) {
|
|
@@ -2908,12 +2917,14 @@ async function applyAgents(api, localAgents, projectId, localSkillSlugs = /* @__
|
|
|
2908
2917
|
outsideProjectForAgent.push(ref);
|
|
2909
2918
|
} else if (blockedRefs.has(ref)) {
|
|
2910
2919
|
blockedForAgent.push(ref);
|
|
2920
|
+
} else if (localSourceSkillSlugs.has(ref)) {
|
|
2921
|
+
undeployedLocalForAgent.push(ref);
|
|
2911
2922
|
} else {
|
|
2912
2923
|
notFoundForAgent.push(ref);
|
|
2913
2924
|
}
|
|
2914
2925
|
}
|
|
2915
2926
|
}
|
|
2916
|
-
if (outsideProjectForAgent.length > 0 || blockedForAgent.length > 0 || notFoundForAgent.length > 0) {
|
|
2927
|
+
if (outsideProjectForAgent.length > 0 || blockedForAgent.length > 0 || undeployedLocalForAgent.length > 0 || notFoundForAgent.length > 0) {
|
|
2917
2928
|
console.log(pc2.red(" \u2717"), `${agent.name}:`);
|
|
2918
2929
|
if (outsideProjectForAgent.length > 0) {
|
|
2919
2930
|
console.log(pc2.red(` skills outside the agent project: ${outsideProjectForAgent.join(", ")}`));
|
|
@@ -2921,10 +2932,14 @@ async function applyAgents(api, localAgents, projectId, localSkillSlugs = /* @__
|
|
|
2921
2932
|
if (blockedForAgent.length > 0) {
|
|
2922
2933
|
console.log(pc2.red(` skills not available for custom agents: ${blockedForAgent.join(", ")}`));
|
|
2923
2934
|
}
|
|
2935
|
+
if (undeployedLocalForAgent.length > 0) {
|
|
2936
|
+
console.log(pc2.red(` locally authored skills not deployed: ${undeployedLocalForAgent.join(", ")}`));
|
|
2937
|
+
console.log(pc2.dim(` run 'lumera apply skills' first, or use 'lumera apply' to deploy skills and agents together`));
|
|
2938
|
+
}
|
|
2924
2939
|
if (notFoundForAgent.length > 0) {
|
|
2925
2940
|
console.log(pc2.red(` skills not found: ${notFoundForAgent.join(", ")}`));
|
|
2941
|
+
console.log(pc2.dim(` pick skills from GET /api/skills (tags includes "available_to_custom_agents")`));
|
|
2926
2942
|
}
|
|
2927
|
-
console.log(pc2.dim(` pick skills from GET /api/skills (tags includes "available_to_custom_agents")`));
|
|
2928
2943
|
errors++;
|
|
2929
2944
|
continue;
|
|
2930
2945
|
}
|
|
@@ -3720,6 +3735,7 @@ async function plan(args) {
|
|
|
3720
3735
|
}
|
|
3721
3736
|
await syncDeps(projectRoot, { ignorePermissionDenied: true });
|
|
3722
3737
|
const allChanges = [];
|
|
3738
|
+
let planValidationErrors = 0;
|
|
3723
3739
|
let collections;
|
|
3724
3740
|
try {
|
|
3725
3741
|
const remoteCollections = await api.listCollections();
|
|
@@ -3750,15 +3766,18 @@ async function plan(args) {
|
|
|
3750
3766
|
}
|
|
3751
3767
|
}
|
|
3752
3768
|
const localSkills = !type || type === "skills" ? loadLocalSkills(platformDir, name || void 0) : [];
|
|
3753
|
-
const
|
|
3769
|
+
const sourceSkillsForAgentResolution = type === "agents" ? loadLocalSkills(platformDir) : localSkills;
|
|
3770
|
+
const localSourceSkillSlugs = new Set(sourceSkillsForAgentResolution.map((skill) => skill.slug));
|
|
3771
|
+
const pendingLocalSkillSlugs = new Set(localSkills.map((skill) => skill.slug));
|
|
3754
3772
|
if (localSkills.length > 0) {
|
|
3755
3773
|
allChanges.push(...await planSkills(api, localSkills, projectId, appName));
|
|
3756
3774
|
}
|
|
3757
3775
|
if (!type || type === "agents") {
|
|
3758
3776
|
const localAgents = loadLocalAgents(platformDir, name || void 0, appName);
|
|
3759
3777
|
if (localAgents.length > 0) {
|
|
3760
|
-
const
|
|
3761
|
-
allChanges.push(...changes);
|
|
3778
|
+
const result = await planAgents(api, localAgents, projectId, localSourceSkillSlugs, pendingLocalSkillSlugs, appName);
|
|
3779
|
+
allChanges.push(...result.changes);
|
|
3780
|
+
planValidationErrors += result.validationErrors;
|
|
3762
3781
|
}
|
|
3763
3782
|
}
|
|
3764
3783
|
if (!type || type === "mailboxes") {
|
|
@@ -3771,7 +3790,14 @@ async function plan(args) {
|
|
|
3771
3790
|
const lintWarnings = await safeLint(projectRoot, localAutomations);
|
|
3772
3791
|
if (allChanges.length === 0) {
|
|
3773
3792
|
if (jsonOutput) {
|
|
3774
|
-
console.log(JSON.stringify({ changes: [], warnings: [], lintWarnings: serializeLintWarnings(lintWarnings, projectRoot) }));
|
|
3793
|
+
console.log(JSON.stringify({ changes: [], warnings: [], validationErrors: planValidationErrors, lintWarnings: serializeLintWarnings(lintWarnings, projectRoot) }));
|
|
3794
|
+
if (planValidationErrors > 0) process.exitCode = 1;
|
|
3795
|
+
return;
|
|
3796
|
+
}
|
|
3797
|
+
if (planValidationErrors > 0) {
|
|
3798
|
+
console.log(pc2.red(` \u2717 Plan has ${planValidationErrors} agent skill validation error${planValidationErrors === 1 ? "" : "s"}.`));
|
|
3799
|
+
console.log();
|
|
3800
|
+
process.exitCode = 1;
|
|
3775
3801
|
return;
|
|
3776
3802
|
}
|
|
3777
3803
|
console.log(pc2.green(" \u2713 No changes detected"));
|
|
@@ -3789,7 +3815,8 @@ async function plan(args) {
|
|
|
3789
3815
|
}
|
|
3790
3816
|
}
|
|
3791
3817
|
}
|
|
3792
|
-
console.log(JSON.stringify({ changes: allChanges, warnings, lintWarnings: serializeLintWarnings(lintWarnings, projectRoot) }));
|
|
3818
|
+
console.log(JSON.stringify({ changes: allChanges, warnings, validationErrors: planValidationErrors, lintWarnings: serializeLintWarnings(lintWarnings, projectRoot) }));
|
|
3819
|
+
if (planValidationErrors > 0) process.exitCode = 1;
|
|
3793
3820
|
return;
|
|
3794
3821
|
}
|
|
3795
3822
|
console.log(pc2.bold(" Changes:"));
|
|
@@ -3830,7 +3857,12 @@ async function plan(args) {
|
|
|
3830
3857
|
}
|
|
3831
3858
|
console.log();
|
|
3832
3859
|
safePrintLint(lintWarnings, projectRoot);
|
|
3833
|
-
|
|
3860
|
+
if (planValidationErrors > 0) {
|
|
3861
|
+
console.log(pc2.red(` \u2717 Fix ${planValidationErrors} agent skill validation error${planValidationErrors === 1 ? "" : "s"} before applying.`));
|
|
3862
|
+
process.exitCode = 1;
|
|
3863
|
+
} else {
|
|
3864
|
+
console.log(pc2.dim(` Run 'lumera apply' to apply these changes.`));
|
|
3865
|
+
}
|
|
3834
3866
|
console.log();
|
|
3835
3867
|
}
|
|
3836
3868
|
async function apply(args) {
|
|
@@ -3877,18 +3909,25 @@ async function apply(args) {
|
|
|
3877
3909
|
collections = /* @__PURE__ */ new Map();
|
|
3878
3910
|
}
|
|
3879
3911
|
const allChanges = [];
|
|
3912
|
+
let planValidationErrors = 0;
|
|
3880
3913
|
const localCollections = !type || type === "collections" ? loadLocalCollections(platformDir, name || void 0) : [];
|
|
3881
3914
|
const localAutomations = !type || type === "automations" ? loadLocalAutomations(platformDir, name || void 0, appName) : [];
|
|
3882
3915
|
const localHooks = !type || type === "hooks" ? loadLocalHooks(platformDir, name || void 0, appName) : [];
|
|
3883
3916
|
const localSkills = !type || type === "skills" ? loadLocalSkills(platformDir, name || void 0) : [];
|
|
3884
|
-
const
|
|
3917
|
+
const sourceSkillsForAgentResolution = type === "agents" ? loadLocalSkills(platformDir) : localSkills;
|
|
3918
|
+
const localSourceSkillSlugs = new Set(sourceSkillsForAgentResolution.map((skill) => skill.slug));
|
|
3919
|
+
const pendingLocalSkillSlugs = new Set(localSkills.map((skill) => skill.slug));
|
|
3885
3920
|
const localAgents = !type || type === "agents" ? loadLocalAgents(platformDir, name || void 0, appName) : [];
|
|
3886
3921
|
const localMailboxes = !type || type === "mailboxes" ? loadLocalMailboxes(platformDir, name || void 0) : [];
|
|
3887
3922
|
if (localCollections.length > 0) allChanges.push(...await planCollections(api, localCollections, appName, projectId));
|
|
3888
3923
|
if (localAutomations.length > 0) allChanges.push(...await planAutomations(api, localAutomations, projectId));
|
|
3889
3924
|
if (localHooks.length > 0) allChanges.push(...await planHooks(api, localHooks, collections, projectId));
|
|
3890
3925
|
if (localSkills.length > 0) allChanges.push(...await planSkills(api, localSkills, projectId, appName));
|
|
3891
|
-
if (localAgents.length > 0)
|
|
3926
|
+
if (localAgents.length > 0) {
|
|
3927
|
+
const result = await planAgents(api, localAgents, projectId, localSourceSkillSlugs, pendingLocalSkillSlugs, appName);
|
|
3928
|
+
allChanges.push(...result.changes);
|
|
3929
|
+
planValidationErrors += result.validationErrors;
|
|
3930
|
+
}
|
|
3892
3931
|
if (localMailboxes.length > 0) allChanges.push(...await planMailboxes(api, localMailboxes));
|
|
3893
3932
|
if (name) {
|
|
3894
3933
|
const hasLocal = localCollections.length > 0 || localAutomations.length > 0 || localHooks.length > 0 || localSkills.length > 0 || localAgents.length > 0 || localMailboxes.length > 0;
|
|
@@ -3898,6 +3937,12 @@ async function apply(args) {
|
|
|
3898
3937
|
process.exit(1);
|
|
3899
3938
|
}
|
|
3900
3939
|
}
|
|
3940
|
+
if (planValidationErrors > 0) {
|
|
3941
|
+
console.log();
|
|
3942
|
+
console.log(pc2.red(` \u2717 Apply aborted: fix ${planValidationErrors} agent skill validation error${planValidationErrors === 1 ? "" : "s"} first.`));
|
|
3943
|
+
console.log();
|
|
3944
|
+
process.exit(1);
|
|
3945
|
+
}
|
|
3901
3946
|
let willDeployApp = false;
|
|
3902
3947
|
if (!type && !skipApp) {
|
|
3903
3948
|
try {
|
|
@@ -3985,7 +4030,7 @@ async function apply(args) {
|
|
|
3985
4030
|
}
|
|
3986
4031
|
if (localAgents.length > 0) {
|
|
3987
4032
|
console.log(pc2.bold(" Agents:"));
|
|
3988
|
-
totalErrors += await applyAgents(api, localAgents, projectId,
|
|
4033
|
+
totalErrors += await applyAgents(api, localAgents, projectId, localSourceSkillSlugs, appName);
|
|
3989
4034
|
console.log();
|
|
3990
4035
|
}
|
|
3991
4036
|
if (localMailboxes.length > 0) {
|
|
@@ -4050,11 +4095,13 @@ async function pull(args) {
|
|
|
4050
4095
|
if (!type || type === "agents") {
|
|
4051
4096
|
const localAgents = loadLocalAgents(platformDir, name || void 0, appName);
|
|
4052
4097
|
if (localAgents.length > 0) {
|
|
4053
|
-
const
|
|
4098
|
+
const localSkillSlugs = new Set(loadLocalSkills(platformDir).map((skill) => skill.slug));
|
|
4099
|
+
const { changes } = await planAgents(
|
|
4054
4100
|
api,
|
|
4055
4101
|
localAgents,
|
|
4056
4102
|
projectId,
|
|
4057
|
-
|
|
4103
|
+
localSkillSlugs,
|
|
4104
|
+
localSkillSlugs,
|
|
4058
4105
|
appName
|
|
4059
4106
|
);
|
|
4060
4107
|
for (const c of changes) {
|
|
@@ -4482,6 +4529,7 @@ export {
|
|
|
4482
4529
|
loadLocalSkills,
|
|
4483
4530
|
localProjectSkillSlug,
|
|
4484
4531
|
plan,
|
|
4532
|
+
planAgents,
|
|
4485
4533
|
planCollections,
|
|
4486
4534
|
planSkills,
|
|
4487
4535
|
projectSkillRefCandidates,
|