@lumerahq/cli 0.19.6 → 0.19.8-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-WY6UMJNI.js → chunk-BAQROJO7.js} +11 -0
- package/dist/{chunk-RUJRTLHA.js → chunk-ZDN32JTT.js} +1 -1
- package/dist/{deps-73XZXRYP.js → deps-DPB3L3EJ.js} +2 -2
- package/dist/{dev-YYMFCXZ5.js → dev-GNZ22LKP.js} +2 -2
- package/dist/index.js +12 -12
- package/dist/{init-7YWMMTBF.js → init-RS2ET656.js} +1 -1
- package/dist/{register-KJMSMMD6.js → register-MLYFAODC.js} +1 -1
- package/dist/{resources-P7WAHOHR.js → resources-VM42NAMH.js} +61 -24
- package/dist/{run-C23KZI4Z.js → run-QRFSRZXJ.js} +1 -1
- package/package.json +1 -1
- package/templates/default/AGENTS.md +21 -1
|
@@ -246,6 +246,17 @@ var ApiClient = class {
|
|
|
246
246
|
const result = await this.request("/api/lm_agent_skills?limit=100");
|
|
247
247
|
return result.skills || [];
|
|
248
248
|
}
|
|
249
|
+
// Resolve a list of refs (slugs or IDs) to skill records. Unlike
|
|
250
|
+
// listAgentSkills, this returns managed skills as well — the caller has
|
|
251
|
+
// already named them, so there is no broad enumeration concern.
|
|
252
|
+
async lookupAgentSkills(refs) {
|
|
253
|
+
if (!refs || refs.length === 0) return [];
|
|
254
|
+
const result = await this.request("/api/lm_agent_skills/lookup", {
|
|
255
|
+
method: "POST",
|
|
256
|
+
body: JSON.stringify({ refs })
|
|
257
|
+
});
|
|
258
|
+
return result.skills || [];
|
|
259
|
+
}
|
|
249
260
|
// Agent Invoke
|
|
250
261
|
async invokeAgent(agentId, message, sessionId) {
|
|
251
262
|
const body = { message };
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
deps,
|
|
3
3
|
projectResourceDepsEnabled,
|
|
4
4
|
syncDeps
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZDN32JTT.js";
|
|
6
6
|
import "./chunk-2CR762KB.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-BAQROJO7.js";
|
|
8
8
|
import "./chunk-ZH3NVYEQ.js";
|
|
9
9
|
import "./chunk-FJFIWC7G.js";
|
|
10
10
|
import "./chunk-PNKVD2UK.js";
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
projectResourceDepsEnabled,
|
|
6
6
|
syncDeps
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ZDN32JTT.js";
|
|
8
8
|
import {
|
|
9
9
|
loadEnv
|
|
10
10
|
} from "./chunk-2CR762KB.js";
|
|
11
11
|
import {
|
|
12
12
|
createApiClient
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-BAQROJO7.js";
|
|
14
14
|
import {
|
|
15
15
|
findProjectRoot,
|
|
16
16
|
getApiUrl,
|
package/dist/index.js
CHANGED
|
@@ -219,39 +219,39 @@ async function main() {
|
|
|
219
219
|
switch (command) {
|
|
220
220
|
// Resource commands
|
|
221
221
|
case "plan":
|
|
222
|
-
await import("./resources-
|
|
222
|
+
await import("./resources-VM42NAMH.js").then((m) => m.plan(args.slice(1)));
|
|
223
223
|
break;
|
|
224
224
|
case "apply":
|
|
225
|
-
await import("./resources-
|
|
225
|
+
await import("./resources-VM42NAMH.js").then((m) => m.apply(args.slice(1)));
|
|
226
226
|
break;
|
|
227
227
|
case "pull":
|
|
228
|
-
await import("./resources-
|
|
228
|
+
await import("./resources-VM42NAMH.js").then((m) => m.pull(args.slice(1)));
|
|
229
229
|
break;
|
|
230
230
|
case "destroy":
|
|
231
|
-
await import("./resources-
|
|
231
|
+
await import("./resources-VM42NAMH.js").then((m) => m.destroy(args.slice(1)));
|
|
232
232
|
break;
|
|
233
233
|
case "list":
|
|
234
|
-
await import("./resources-
|
|
234
|
+
await import("./resources-VM42NAMH.js").then((m) => m.list(args.slice(1)));
|
|
235
235
|
break;
|
|
236
236
|
case "show":
|
|
237
|
-
await import("./resources-
|
|
237
|
+
await import("./resources-VM42NAMH.js").then((m) => m.show(args.slice(1)));
|
|
238
238
|
break;
|
|
239
239
|
case "diff":
|
|
240
|
-
await import("./resources-
|
|
240
|
+
await import("./resources-VM42NAMH.js").then((m) => m.diff(args.slice(1)));
|
|
241
241
|
break;
|
|
242
242
|
// Development
|
|
243
243
|
case "dev":
|
|
244
|
-
await import("./dev-
|
|
244
|
+
await import("./dev-GNZ22LKP.js").then((m) => m.dev(args.slice(1)));
|
|
245
245
|
break;
|
|
246
246
|
case "run":
|
|
247
|
-
await import("./run-
|
|
247
|
+
await import("./run-QRFSRZXJ.js").then((m) => m.run(args.slice(1)));
|
|
248
248
|
break;
|
|
249
249
|
// Project
|
|
250
250
|
case "init":
|
|
251
|
-
await import("./init-
|
|
251
|
+
await import("./init-RS2ET656.js").then((m) => m.init(args.slice(1)));
|
|
252
252
|
break;
|
|
253
253
|
case "register":
|
|
254
|
-
await import("./register-
|
|
254
|
+
await import("./register-MLYFAODC.js").then((m) => m.register(args.slice(1)));
|
|
255
255
|
break;
|
|
256
256
|
case "templates":
|
|
257
257
|
await import("./templates-LNUOTNLN.js").then((m) => m.templates(subcommand, args.slice(2)));
|
|
@@ -268,7 +268,7 @@ async function main() {
|
|
|
268
268
|
break;
|
|
269
269
|
// Dependencies
|
|
270
270
|
case "deps":
|
|
271
|
-
await import("./deps-
|
|
271
|
+
await import("./deps-DPB3L3EJ.js").then((m) => m.deps(args.slice(1)));
|
|
272
272
|
break;
|
|
273
273
|
// Auth
|
|
274
274
|
case "login":
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
projectResourceDepsEnabled,
|
|
6
6
|
syncDeps
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ZDN32JTT.js";
|
|
8
8
|
import {
|
|
9
9
|
loadEnv
|
|
10
10
|
} from "./chunk-2CR762KB.js";
|
|
11
11
|
import {
|
|
12
12
|
createApiClient
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-BAQROJO7.js";
|
|
14
14
|
import {
|
|
15
15
|
findProjectRoot,
|
|
16
16
|
getApiUrl,
|
|
@@ -1847,19 +1847,37 @@ async function planAgents(api, localAgents, projectId) {
|
|
|
1847
1847
|
const remoteByExternalId = new Map(
|
|
1848
1848
|
remoteAgents.filter((a) => a.external_id && !a.managed).map((a) => [a.external_id, a])
|
|
1849
1849
|
);
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
const
|
|
1853
|
-
|
|
1850
|
+
const skillSlugToId = /* @__PURE__ */ new Map();
|
|
1851
|
+
const skillIdToSlug = /* @__PURE__ */ new Map();
|
|
1852
|
+
const blockedRefs = /* @__PURE__ */ new Set();
|
|
1853
|
+
const planRefs = [
|
|
1854
|
+
.../* @__PURE__ */ new Set([
|
|
1855
|
+
...localAgents.flatMap((a) => a.agent.skills ?? []),
|
|
1856
|
+
...remoteAgents.flatMap((a) => a.skill_ids ?? [])
|
|
1857
|
+
])
|
|
1858
|
+
];
|
|
1859
|
+
if (planRefs.length > 0) {
|
|
1854
1860
|
try {
|
|
1855
|
-
const skills = await api.
|
|
1856
|
-
|
|
1857
|
-
|
|
1861
|
+
const skills = await api.lookupAgentSkills(planRefs);
|
|
1862
|
+
for (const s of skills) {
|
|
1863
|
+
skillIdToSlug.set(s.id, s.slug);
|
|
1864
|
+
if (isAvailableToCustomAgents(s)) {
|
|
1865
|
+
skillSlugToId.set(s.slug, s.id);
|
|
1866
|
+
} else {
|
|
1867
|
+
blockedRefs.add(s.slug);
|
|
1868
|
+
blockedRefs.add(s.id);
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1858
1871
|
} catch {
|
|
1859
1872
|
}
|
|
1860
1873
|
}
|
|
1861
1874
|
for (const { agent, systemPrompt, policyScript } of localAgents) {
|
|
1862
1875
|
const remote = remoteByExternalId.get(agent.external_id);
|
|
1876
|
+
for (const ref of agent.skills ?? []) {
|
|
1877
|
+
if (blockedRefs.has(ref)) {
|
|
1878
|
+
console.log(pc2.yellow(` \u26A0 Skill "${ref}" is a Lumera platform skill, only available to Lumera-built agents \u2014 will be skipped on apply`));
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1863
1881
|
if (!remote) {
|
|
1864
1882
|
changes.push({ type: "create", resource: "agent", id: agent.external_id, name: agent.name });
|
|
1865
1883
|
} else {
|
|
@@ -1871,7 +1889,7 @@ async function planAgents(api, localAgents, projectId) {
|
|
|
1871
1889
|
if ((remote.policy_script || "").trim() !== (policyScript || "").trim()) diffs.push("policy_script");
|
|
1872
1890
|
if ((remote.policy_enabled || false) !== (agent.policy_enabled || false)) diffs.push("policy_enabled");
|
|
1873
1891
|
if ((remote.policy_description || "") !== (agent.policy_description || "")) diffs.push("policy_description");
|
|
1874
|
-
const localSkillIds = (agent.skills || []).map((s) => skillSlugToId.get(s) || s).sort();
|
|
1892
|
+
const localSkillIds = (agent.skills || []).filter((s) => !blockedRefs.has(s)).map((s) => skillSlugToId.get(s) || s).sort();
|
|
1875
1893
|
const remoteSkillIds = [...remote.skill_ids || []].sort();
|
|
1876
1894
|
if (localSkillIds.join(",") !== remoteSkillIds.join(",")) {
|
|
1877
1895
|
const addedSlugs = localSkillIds.filter((id) => !remoteSkillIds.includes(id)).map((id) => skillIdToSlug.get(id) || id);
|
|
@@ -1895,32 +1913,48 @@ async function planAgents(api, localAgents, projectId) {
|
|
|
1895
1913
|
}
|
|
1896
1914
|
return changes;
|
|
1897
1915
|
}
|
|
1916
|
+
var TAG_AVAILABLE_TO_CUSTOM_AGENTS = "available_to_custom_agents";
|
|
1917
|
+
function isAvailableToCustomAgents(skill) {
|
|
1918
|
+
if (!skill.managed) return true;
|
|
1919
|
+
return (skill.tags ?? []).includes(TAG_AVAILABLE_TO_CUSTOM_AGENTS);
|
|
1920
|
+
}
|
|
1898
1921
|
async function applyAgents(api, localAgents, projectId) {
|
|
1899
1922
|
let errors = 0;
|
|
1900
1923
|
const remoteAgents = await api.listAgents(projectId ? { project_id: projectId } : void 0);
|
|
1901
1924
|
const remoteByExternalId = new Map(
|
|
1902
1925
|
remoteAgents.filter((a) => a.external_id && !a.managed).map((a) => [a.external_id, a])
|
|
1903
1926
|
);
|
|
1904
|
-
|
|
1905
|
-
const
|
|
1906
|
-
|
|
1927
|
+
const refToId = /* @__PURE__ */ new Map();
|
|
1928
|
+
const blockedRefs = /* @__PURE__ */ new Set();
|
|
1929
|
+
const refs = [...new Set(localAgents.flatMap((a) => a.agent.skills ?? []))];
|
|
1930
|
+
if (refs.length > 0) {
|
|
1907
1931
|
try {
|
|
1908
|
-
const skills = await api.
|
|
1909
|
-
|
|
1932
|
+
const skills = await api.lookupAgentSkills(refs);
|
|
1933
|
+
for (const s of skills) {
|
|
1934
|
+
if (isAvailableToCustomAgents(s)) {
|
|
1935
|
+
refToId.set(s.slug, s.id);
|
|
1936
|
+
refToId.set(s.id, s.id);
|
|
1937
|
+
} else {
|
|
1938
|
+
blockedRefs.add(s.slug);
|
|
1939
|
+
blockedRefs.add(s.id);
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1910
1942
|
} catch (e) {
|
|
1911
|
-
console.log(pc2.yellow(` \u26A0 Could not
|
|
1943
|
+
console.log(pc2.yellow(` \u26A0 Could not resolve skills: ${e}`));
|
|
1912
1944
|
}
|
|
1913
1945
|
}
|
|
1914
1946
|
for (const { agent, systemPrompt, policyScript } of localAgents) {
|
|
1915
1947
|
const remote = remoteByExternalId.get(agent.external_id);
|
|
1916
1948
|
const skillIds = [];
|
|
1917
1949
|
if (agent.skills) {
|
|
1918
|
-
for (const
|
|
1919
|
-
const id =
|
|
1950
|
+
for (const ref of agent.skills) {
|
|
1951
|
+
const id = refToId.get(ref);
|
|
1920
1952
|
if (id) {
|
|
1921
1953
|
skillIds.push(id);
|
|
1954
|
+
} else if (blockedRefs.has(ref)) {
|
|
1955
|
+
console.log(pc2.yellow(` \u26A0 Skill "${ref}" is a Lumera platform skill, only available to Lumera-built agents \u2014 skipping`));
|
|
1922
1956
|
} else {
|
|
1923
|
-
console.log(pc2.yellow(` \u26A0 Skill "${
|
|
1957
|
+
console.log(pc2.yellow(` \u26A0 Skill "${ref}" not found, skipping (use the slug, e.g. "using-collections")`));
|
|
1924
1958
|
}
|
|
1925
1959
|
}
|
|
1926
1960
|
}
|
|
@@ -1955,11 +1989,14 @@ async function pullAgents(api, platformDir, filterName, projectId) {
|
|
|
1955
1989
|
const agentsDir = join2(platformDir, "agents");
|
|
1956
1990
|
mkdirSync(agentsDir, { recursive: true });
|
|
1957
1991
|
const agents = await api.listAgents(projectId ? { project_id: projectId } : void 0);
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1992
|
+
const skillIdToSlug = /* @__PURE__ */ new Map();
|
|
1993
|
+
const pullRefs = [...new Set(agents.flatMap((a) => a.skill_ids ?? []))];
|
|
1994
|
+
if (pullRefs.length > 0) {
|
|
1995
|
+
try {
|
|
1996
|
+
const skills = await api.lookupAgentSkills(pullRefs);
|
|
1997
|
+
for (const s of skills) skillIdToSlug.set(s.id, s.slug);
|
|
1998
|
+
} catch {
|
|
1999
|
+
}
|
|
1963
2000
|
}
|
|
1964
2001
|
for (const agent of agents) {
|
|
1965
2002
|
if (!agent.external_id || agent.managed) continue;
|
package/package.json
CHANGED
|
@@ -128,7 +128,27 @@ Follow the user's lead. If they tell you exactly what to build, build it. The wo
|
|
|
128
128
|
### Rules
|
|
129
129
|
7. **Code is source of truth** — Edit files in `platform/`, then deploy with `lumera apply`. Don't edit in the Lumera UI.
|
|
130
130
|
8. **Keep docs current** — After each slice, update `architecture.md` with what was built (data models, relationships, hook logic, design decisions). Also update the project description at the top of this file (`AGENTS.md`) so it reflects what the project actually does now — not the original template description.
|
|
131
|
-
9. **Commit and push** — After each slice or significant change
|
|
131
|
+
9. **Commit and push** — After each slice or significant change, stage your changes, create a meaningful commit with both a title and description, then push. The sandbox is ephemeral — uncommitted work is lost if recycled.
|
|
132
|
+
- Use a conventional subject (`feat:`, `fix:`, `chore:`, `docs:`, `test:`) that explains the user-visible change, not just the filenames.
|
|
133
|
+
- Include a body that describes why the change was needed, what you changed, and the main areas covered.
|
|
134
|
+
- Avoid generic messages like `update files`, `changes`, `WIP`, or filename-only summaries.
|
|
135
|
+
- Prefer a HEREDOC so multi-line messages are reliable:
|
|
136
|
+
```bash
|
|
137
|
+
git add -A
|
|
138
|
+
git commit -m "$(cat <<'EOF'
|
|
139
|
+
feat: add invoice approval dashboard
|
|
140
|
+
|
|
141
|
+
Adds the first invoice review slice with a collection schema, seeded
|
|
142
|
+
example data, and a dashboard for approving or rejecting invoices.
|
|
143
|
+
|
|
144
|
+
Covers:
|
|
145
|
+
- invoice collection fields and statuses
|
|
146
|
+
- approval actions in the UI
|
|
147
|
+
- project documentation updates
|
|
148
|
+
EOF
|
|
149
|
+
)"
|
|
150
|
+
git push
|
|
151
|
+
```
|
|
132
152
|
10. **Deploy marker** — When your changes need `lumera apply`, include at the end of your response: `<!-- DEPLOY: short commit message -->`. Skip for frontend-only changes.
|
|
133
153
|
|
|
134
154
|
## File Artifacts
|