@lumerahq/cli 0.18.13 → 0.19.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-IBE6ACPE.js → chunk-GKI2HQJC.js} +11 -5
- package/dist/{chunk-MVUNFAVL.js → chunk-XDTWVFPE.js} +1 -1
- package/dist/{deps-AVTV7FP3.js → deps-ULTIIDYK.js} +2 -2
- package/dist/{dev-R2CZ7IYR.js → dev-EVREBGR6.js} +1 -1
- package/dist/index.js +12 -12
- package/dist/{init-F4UYW6LD.js → init-37XOMJLU.js} +1 -1
- package/dist/{register-QPUXYBZ7.js → register-JJUMS4FI.js} +1 -1
- package/dist/{resources-KPRAWMQN.js → resources-MKCLJUH3.js} +203 -64
- package/dist/{run-JZX3E4UX.js → run-5ZOSPBGO.js} +1 -1
- package/package.json +1 -1
|
@@ -184,6 +184,17 @@ var ApiClient = class {
|
|
|
184
184
|
method: "DELETE"
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
|
+
// Mailboxes
|
|
188
|
+
async listMailboxes() {
|
|
189
|
+
const result = await this.request("/api/mailboxes");
|
|
190
|
+
return result.mailboxes || [];
|
|
191
|
+
}
|
|
192
|
+
async createMailbox(def) {
|
|
193
|
+
return this.request("/api/mailboxes", {
|
|
194
|
+
method: "POST",
|
|
195
|
+
body: JSON.stringify(def)
|
|
196
|
+
});
|
|
197
|
+
}
|
|
187
198
|
// Agents
|
|
188
199
|
async listAgents(opts) {
|
|
189
200
|
const params = new URLSearchParams({ limit: "100" });
|
|
@@ -208,11 +219,6 @@ var ApiClient = class {
|
|
|
208
219
|
method: "DELETE"
|
|
209
220
|
});
|
|
210
221
|
}
|
|
211
|
-
// MCP Servers
|
|
212
|
-
async listMCPServers() {
|
|
213
|
-
const result = await this.request("/api/mcp-servers");
|
|
214
|
-
return result.servers || [];
|
|
215
|
-
}
|
|
216
222
|
// Agent Skills (for slug-to-ID resolution)
|
|
217
223
|
async listAgentSkills() {
|
|
218
224
|
const result = await this.request("/api/lm_agent_skills?limit=100");
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deps,
|
|
3
3
|
syncDeps
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-XDTWVFPE.js";
|
|
5
5
|
import "./chunk-2CR762KB.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-GKI2HQJC.js";
|
|
7
7
|
import "./chunk-ZH3NVYEQ.js";
|
|
8
8
|
import "./chunk-FJFIWC7G.js";
|
|
9
9
|
import "./chunk-PNKVD2UK.js";
|
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-MKCLJUH3.js").then((m) => m.plan(args.slice(1)));
|
|
223
223
|
break;
|
|
224
224
|
case "apply":
|
|
225
|
-
await import("./resources-
|
|
225
|
+
await import("./resources-MKCLJUH3.js").then((m) => m.apply(args.slice(1)));
|
|
226
226
|
break;
|
|
227
227
|
case "pull":
|
|
228
|
-
await import("./resources-
|
|
228
|
+
await import("./resources-MKCLJUH3.js").then((m) => m.pull(args.slice(1)));
|
|
229
229
|
break;
|
|
230
230
|
case "destroy":
|
|
231
|
-
await import("./resources-
|
|
231
|
+
await import("./resources-MKCLJUH3.js").then((m) => m.destroy(args.slice(1)));
|
|
232
232
|
break;
|
|
233
233
|
case "list":
|
|
234
|
-
await import("./resources-
|
|
234
|
+
await import("./resources-MKCLJUH3.js").then((m) => m.list(args.slice(1)));
|
|
235
235
|
break;
|
|
236
236
|
case "show":
|
|
237
|
-
await import("./resources-
|
|
237
|
+
await import("./resources-MKCLJUH3.js").then((m) => m.show(args.slice(1)));
|
|
238
238
|
break;
|
|
239
239
|
case "diff":
|
|
240
|
-
await import("./resources-
|
|
240
|
+
await import("./resources-MKCLJUH3.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-EVREBGR6.js").then((m) => m.dev(args.slice(1)));
|
|
245
245
|
break;
|
|
246
246
|
case "run":
|
|
247
|
-
await import("./run-
|
|
247
|
+
await import("./run-5ZOSPBGO.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-37XOMJLU.js").then((m) => m.init(args.slice(1)));
|
|
252
252
|
break;
|
|
253
253
|
case "register":
|
|
254
|
-
await import("./register-
|
|
254
|
+
await import("./register-JJUMS4FI.js").then((m) => m.register(args.slice(1)));
|
|
255
255
|
break;
|
|
256
256
|
case "templates":
|
|
257
257
|
await import("./templates-M3RDNDDY.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-ULTIIDYK.js").then((m) => m.deps(args.slice(1)));
|
|
272
272
|
break;
|
|
273
273
|
// Auth
|
|
274
274
|
case "login":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
syncDeps
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XDTWVFPE.js";
|
|
4
4
|
import {
|
|
5
5
|
deploy
|
|
6
6
|
} from "./chunk-SU26C4GL.js";
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from "./chunk-2CR762KB.js";
|
|
10
10
|
import {
|
|
11
11
|
createApiClient
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GKI2HQJC.js";
|
|
13
13
|
import {
|
|
14
14
|
findProjectRoot,
|
|
15
15
|
getApiUrl,
|
|
@@ -282,12 +282,15 @@ ${pc.dim("Resources:")}
|
|
|
282
282
|
hooks Plan only hooks
|
|
283
283
|
agents Plan only agents
|
|
284
284
|
agents/<name> Plan single agent
|
|
285
|
+
mailboxes Plan only mailboxes
|
|
286
|
+
mailboxes/<slug> Plan single mailbox
|
|
285
287
|
app Plan app deployment
|
|
286
288
|
|
|
287
289
|
${pc.dim("Examples:")}
|
|
288
290
|
lumera plan # Plan all resources
|
|
289
291
|
lumera plan collections # Plan only collections
|
|
290
292
|
lumera plan automations/sync # Plan single automation
|
|
293
|
+
lumera plan mailboxes # Plan mailbox configs
|
|
291
294
|
`);
|
|
292
295
|
}
|
|
293
296
|
function showApplyHelp() {
|
|
@@ -307,6 +310,8 @@ ${pc.dim("Resources:")}
|
|
|
307
310
|
hooks Apply only hooks
|
|
308
311
|
agents Apply only agents
|
|
309
312
|
agents/<name> Apply single agent
|
|
313
|
+
mailboxes Apply only mailboxes
|
|
314
|
+
mailboxes/<slug> Apply single mailbox
|
|
310
315
|
app Deploy the frontend app
|
|
311
316
|
|
|
312
317
|
${pc.dim("Options:")}
|
|
@@ -344,6 +349,8 @@ ${pc.dim("Resources:")}
|
|
|
344
349
|
hooks Pull only hooks
|
|
345
350
|
agents Pull only agents
|
|
346
351
|
agents/<name> Pull single agent
|
|
352
|
+
mailboxes Pull only mailboxes
|
|
353
|
+
mailboxes/<slug> Pull single mailbox
|
|
347
354
|
|
|
348
355
|
${pc.dim("Examples:")}
|
|
349
356
|
lumera pull # Pull all (safe \u2014 warns on conflicts)
|
|
@@ -395,6 +402,7 @@ ${pc.dim("Types:")}
|
|
|
395
402
|
automations List only automations
|
|
396
403
|
hooks List only hooks
|
|
397
404
|
agents List only agents
|
|
405
|
+
mailboxes List only mailboxes
|
|
398
406
|
|
|
399
407
|
${pc.dim("Options:")}
|
|
400
408
|
--all Include remote-only resources
|
|
@@ -418,6 +426,7 @@ ${pc.dim("Resources:")}
|
|
|
418
426
|
automations/<name> Show automation details
|
|
419
427
|
hooks/<name> Show hook details
|
|
420
428
|
agents/<name> Show agent details
|
|
429
|
+
mailboxes/<slug> Show mailbox details
|
|
421
430
|
app Show app details
|
|
422
431
|
|
|
423
432
|
${pc.dim("Examples:")}
|
|
@@ -433,7 +442,7 @@ function parseResource(resourcePath) {
|
|
|
433
442
|
const parts = resourcePath.split("/");
|
|
434
443
|
const type = parts[0];
|
|
435
444
|
const name = parts.slice(1).join("/") || null;
|
|
436
|
-
const validTypes = ["collections", "automations", "hooks", "agents", "app"];
|
|
445
|
+
const validTypes = ["collections", "automations", "hooks", "agents", "mailboxes", "app"];
|
|
437
446
|
if (!validTypes.includes(type)) {
|
|
438
447
|
console.log(pc.red(` Unknown resource type "${type}". Valid types: ${validTypes.join(", ")}`));
|
|
439
448
|
process.exit(1);
|
|
@@ -898,6 +907,122 @@ async function planAutomations(api, localAutomations) {
|
|
|
898
907
|
}
|
|
899
908
|
return changes;
|
|
900
909
|
}
|
|
910
|
+
function loadLocalMailboxes(platformDir, filterName) {
|
|
911
|
+
const mailboxesDir = join(platformDir, "mailboxes");
|
|
912
|
+
if (!existsSync(mailboxesDir)) {
|
|
913
|
+
return [];
|
|
914
|
+
}
|
|
915
|
+
const mailboxes = [];
|
|
916
|
+
for (const file of readdirSync(mailboxesDir)) {
|
|
917
|
+
if (!file.endsWith(".json")) continue;
|
|
918
|
+
const slug = file.replace(/\.json$/, "").trim();
|
|
919
|
+
if (!slug) {
|
|
920
|
+
console.log(pc.yellow(` \u26A0 Skipping ${file}: empty filename`));
|
|
921
|
+
continue;
|
|
922
|
+
}
|
|
923
|
+
if (filterName && slug !== filterName) {
|
|
924
|
+
continue;
|
|
925
|
+
}
|
|
926
|
+
const filePath = join(mailboxesDir, file);
|
|
927
|
+
let raw;
|
|
928
|
+
try {
|
|
929
|
+
raw = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
930
|
+
} catch (e) {
|
|
931
|
+
console.log(pc.yellow(` \u26A0 Skipping ${file}: invalid JSON (${e.message})`));
|
|
932
|
+
continue;
|
|
933
|
+
}
|
|
934
|
+
if (!isPlainObject(raw)) {
|
|
935
|
+
console.log(pc.yellow(` \u26A0 Skipping ${file}: top-level value must be an object`));
|
|
936
|
+
continue;
|
|
937
|
+
}
|
|
938
|
+
const descriptionRaw = raw["description"];
|
|
939
|
+
const description = typeof descriptionRaw === "string" ? descriptionRaw : void 0;
|
|
940
|
+
mailboxes.push({ slug, description });
|
|
941
|
+
}
|
|
942
|
+
return mailboxes;
|
|
943
|
+
}
|
|
944
|
+
async function planMailboxes(api, localMailboxes) {
|
|
945
|
+
const changes = [];
|
|
946
|
+
if (localMailboxes.length === 0) return changes;
|
|
947
|
+
const remote = await api.listMailboxes();
|
|
948
|
+
const remoteBySlug = new Map(remote.map((m) => [m.slug, m]));
|
|
949
|
+
for (const mb of localMailboxes) {
|
|
950
|
+
const existing = remoteBySlug.get(mb.slug);
|
|
951
|
+
if (!existing) {
|
|
952
|
+
changes.push({
|
|
953
|
+
type: "create",
|
|
954
|
+
resource: "mailbox",
|
|
955
|
+
id: mb.slug,
|
|
956
|
+
name: mb.slug,
|
|
957
|
+
details: mb.description ? `description: ${mb.description}` : void 0
|
|
958
|
+
});
|
|
959
|
+
continue;
|
|
960
|
+
}
|
|
961
|
+
const localDesc = (mb.description ?? "").trim();
|
|
962
|
+
const remoteDesc = (existing.description ?? "").trim();
|
|
963
|
+
if (localDesc !== remoteDesc) {
|
|
964
|
+
changes.push({
|
|
965
|
+
type: "update",
|
|
966
|
+
resource: "mailbox",
|
|
967
|
+
id: existing.id,
|
|
968
|
+
name: mb.slug,
|
|
969
|
+
details: "description differs (read-only remotely; update in UI or DB)"
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
return changes;
|
|
974
|
+
}
|
|
975
|
+
async function applyMailboxes(api, localMailboxes) {
|
|
976
|
+
if (localMailboxes.length === 0) return 0;
|
|
977
|
+
let errors = 0;
|
|
978
|
+
const remote = await api.listMailboxes();
|
|
979
|
+
const remoteBySlug = new Map(remote.map((m) => [m.slug, m]));
|
|
980
|
+
for (const mb of localMailboxes) {
|
|
981
|
+
const existing = remoteBySlug.get(mb.slug);
|
|
982
|
+
if (existing) {
|
|
983
|
+
const localDesc = (mb.description ?? "").trim();
|
|
984
|
+
const remoteDesc = (existing.description ?? "").trim();
|
|
985
|
+
if (localDesc !== remoteDesc) {
|
|
986
|
+
console.log(pc.yellow(" \u26A0"), `mailbox ${mb.slug}: description drift not reconcilable by CLI (no PATCH endpoint yet) \u2014 update in the UI or DB`);
|
|
987
|
+
} else {
|
|
988
|
+
console.log(pc.green(" \u2713"), pc.dim(`mailbox ${mb.slug} already exists (${existing.email})`));
|
|
989
|
+
}
|
|
990
|
+
continue;
|
|
991
|
+
}
|
|
992
|
+
try {
|
|
993
|
+
const created = await api.createMailbox({ slug: mb.slug, description: mb.description });
|
|
994
|
+
console.log(pc.green(" \u2713"), `created mailbox ${mb.slug} ${pc.dim(`\u2192 ${created.email}`)}`);
|
|
995
|
+
} catch (e) {
|
|
996
|
+
console.log(pc.red(" \u2717"), `mailbox ${mb.slug}: ${e.message}`);
|
|
997
|
+
errors++;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
return errors;
|
|
1001
|
+
}
|
|
1002
|
+
async function pullMailboxes(api, platformDir, filterName) {
|
|
1003
|
+
const mailboxes = await api.listMailboxes();
|
|
1004
|
+
if (mailboxes.length === 0) {
|
|
1005
|
+
console.log(pc.dim(" (no mailboxes)"));
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
1008
|
+
const outDir = join(platformDir, "mailboxes");
|
|
1009
|
+
if (!existsSync(outDir)) {
|
|
1010
|
+
mkdirSync(outDir, { recursive: true });
|
|
1011
|
+
}
|
|
1012
|
+
let count = 0;
|
|
1013
|
+
for (const mb of mailboxes) {
|
|
1014
|
+
if (filterName && mb.slug !== filterName) continue;
|
|
1015
|
+
const body = {};
|
|
1016
|
+
if (mb.description) body.description = mb.description;
|
|
1017
|
+
const file = join(outDir, `${toSafeFilename(mb.slug)}.json`);
|
|
1018
|
+
writeFileSync(file, JSON.stringify(body, null, 2) + "\n");
|
|
1019
|
+
console.log(pc.green(" \u2713"), `pulled mailbox ${mb.slug} ${pc.dim(`\u2192 ${file}`)}`);
|
|
1020
|
+
count++;
|
|
1021
|
+
}
|
|
1022
|
+
if (count === 0 && filterName) {
|
|
1023
|
+
console.log(pc.yellow(` \u26A0 mailbox '${filterName}' not found on remote`));
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
901
1026
|
async function planHooks(api, localHooks, collections) {
|
|
902
1027
|
const changes = [];
|
|
903
1028
|
const remoteHooks = await api.listHooks();
|
|
@@ -1308,6 +1433,13 @@ function loadLocalAgents(platformDir, filterName, appName) {
|
|
|
1308
1433
|
if (filterName && config.external_id !== filterName && config.name !== filterName && entry.name !== filterName) {
|
|
1309
1434
|
continue;
|
|
1310
1435
|
}
|
|
1436
|
+
if (config.mcp_servers !== void 0) {
|
|
1437
|
+
console.log(
|
|
1438
|
+
pc.yellow(
|
|
1439
|
+
` \u26A0 ${entry.name}: "mcp_servers" is deprecated and ignored \u2014 MCP servers are now scoped per project in Platform \u2192 Integrations.`
|
|
1440
|
+
)
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1311
1443
|
if (!config.external_id) {
|
|
1312
1444
|
if (appName) {
|
|
1313
1445
|
config.external_id = `${appName}:${entry.name}`;
|
|
@@ -1357,17 +1489,6 @@ async function planAgents(api, localAgents, projectId) {
|
|
|
1357
1489
|
} catch {
|
|
1358
1490
|
}
|
|
1359
1491
|
}
|
|
1360
|
-
let mcpNameToId = /* @__PURE__ */ new Map();
|
|
1361
|
-
let mcpIdToName = /* @__PURE__ */ new Map();
|
|
1362
|
-
const hasMcpRefs = localAgents.some((a) => a.agent.mcp_servers && a.agent.mcp_servers.length > 0) || remoteAgents.some((a) => a.mcp_server_ids && a.mcp_server_ids.length > 0);
|
|
1363
|
-
if (hasMcpRefs) {
|
|
1364
|
-
try {
|
|
1365
|
-
const servers = await api.listMCPServers();
|
|
1366
|
-
mcpNameToId = new Map(servers.map((s) => [s.name, s.id]));
|
|
1367
|
-
mcpIdToName = new Map(servers.map((s) => [s.id, s.name]));
|
|
1368
|
-
} catch {
|
|
1369
|
-
}
|
|
1370
|
-
}
|
|
1371
1492
|
for (const { agent, systemPrompt, policyScript } of localAgents) {
|
|
1372
1493
|
const remote = remoteByExternalId.get(agent.external_id);
|
|
1373
1494
|
if (!remote) {
|
|
@@ -1391,16 +1512,6 @@ async function planAgents(api, localAgents, projectId) {
|
|
|
1391
1512
|
if (removedSlugs.length) parts.push(`-${removedSlugs.join(", -")}`);
|
|
1392
1513
|
diffs.push(`skills (${parts.join(", ")})`);
|
|
1393
1514
|
}
|
|
1394
|
-
const localMcpIds = (agent.mcp_servers || []).map((n) => mcpNameToId.get(n) || n).sort();
|
|
1395
|
-
const remoteMcpIds = [...remote.mcp_server_ids || []].sort();
|
|
1396
|
-
if (localMcpIds.join(",") !== remoteMcpIds.join(",")) {
|
|
1397
|
-
const addedNames = localMcpIds.filter((id) => !remoteMcpIds.includes(id)).map((id) => mcpIdToName.get(id) || id);
|
|
1398
|
-
const removedNames = remoteMcpIds.filter((id) => !localMcpIds.includes(id)).map((id) => mcpIdToName.get(id) || id);
|
|
1399
|
-
const parts = [];
|
|
1400
|
-
if (addedNames.length) parts.push(`+${addedNames.join(", +")}`);
|
|
1401
|
-
if (removedNames.length) parts.push(`-${removedNames.join(", -")}`);
|
|
1402
|
-
diffs.push(`mcp_servers (${parts.join(", ")})`);
|
|
1403
|
-
}
|
|
1404
1515
|
if (diffs.length > 0) {
|
|
1405
1516
|
const textDiffs = [];
|
|
1406
1517
|
if (diffs.includes("system_prompt")) {
|
|
@@ -1431,16 +1542,6 @@ async function applyAgents(api, localAgents, projectId) {
|
|
|
1431
1542
|
console.log(pc.yellow(` \u26A0 Could not fetch skills for resolution: ${e}`));
|
|
1432
1543
|
}
|
|
1433
1544
|
}
|
|
1434
|
-
let mcpMap = /* @__PURE__ */ new Map();
|
|
1435
|
-
const hasMcpRefs = localAgents.some((a) => a.agent.mcp_servers && a.agent.mcp_servers.length > 0);
|
|
1436
|
-
if (hasMcpRefs) {
|
|
1437
|
-
try {
|
|
1438
|
-
const servers = await api.listMCPServers();
|
|
1439
|
-
mcpMap = new Map(servers.map((s) => [s.name, s.id]));
|
|
1440
|
-
} catch (e) {
|
|
1441
|
-
console.log(pc.yellow(` \u26A0 Could not fetch MCP servers for resolution: ${e}`));
|
|
1442
|
-
}
|
|
1443
|
-
}
|
|
1444
1545
|
for (const { agent, systemPrompt, policyScript } of localAgents) {
|
|
1445
1546
|
const remote = remoteByExternalId.get(agent.external_id);
|
|
1446
1547
|
const skillIds = [];
|
|
@@ -1454,17 +1555,6 @@ async function applyAgents(api, localAgents, projectId) {
|
|
|
1454
1555
|
}
|
|
1455
1556
|
}
|
|
1456
1557
|
}
|
|
1457
|
-
const mcpServerIds = [];
|
|
1458
|
-
if (agent.mcp_servers) {
|
|
1459
|
-
for (const name of agent.mcp_servers) {
|
|
1460
|
-
const id = mcpMap.get(name);
|
|
1461
|
-
if (id) {
|
|
1462
|
-
mcpServerIds.push(id);
|
|
1463
|
-
} else {
|
|
1464
|
-
console.log(pc.yellow(` \u26A0 MCP server "${name}" not found, skipping`));
|
|
1465
|
-
}
|
|
1466
|
-
}
|
|
1467
|
-
}
|
|
1468
1558
|
const payload = {
|
|
1469
1559
|
external_id: agent.external_id,
|
|
1470
1560
|
name: agent.name,
|
|
@@ -1472,7 +1562,6 @@ async function applyAgents(api, localAgents, projectId) {
|
|
|
1472
1562
|
system_prompt: systemPrompt,
|
|
1473
1563
|
model: agent.model || "",
|
|
1474
1564
|
skill_ids: skillIds,
|
|
1475
|
-
mcp_server_ids: mcpServerIds,
|
|
1476
1565
|
policy_script: policyScript || "",
|
|
1477
1566
|
policy_enabled: agent.policy_enabled || false,
|
|
1478
1567
|
policy_description: agent.policy_description || ""
|
|
@@ -1503,12 +1592,6 @@ async function pullAgents(api, platformDir, filterName, projectId) {
|
|
|
1503
1592
|
skillIdToSlug = new Map(skills.map((s) => [s.id, s.slug]));
|
|
1504
1593
|
} catch {
|
|
1505
1594
|
}
|
|
1506
|
-
let mcpIdToName = /* @__PURE__ */ new Map();
|
|
1507
|
-
try {
|
|
1508
|
-
const servers = await api.listMCPServers();
|
|
1509
|
-
mcpIdToName = new Map(servers.map((s) => [s.id, s.name]));
|
|
1510
|
-
} catch {
|
|
1511
|
-
}
|
|
1512
1595
|
for (const agent of agents) {
|
|
1513
1596
|
if (!agent.external_id || agent.managed) continue;
|
|
1514
1597
|
if (filterName && agent.external_id !== filterName && agent.name !== filterName) {
|
|
@@ -1524,13 +1607,6 @@ async function pullAgents(api, platformDir, filterName, projectId) {
|
|
|
1524
1607
|
if (slug) skillSlugs.push(slug);
|
|
1525
1608
|
}
|
|
1526
1609
|
}
|
|
1527
|
-
const mcpServerNames = [];
|
|
1528
|
-
if (agent.mcp_server_ids) {
|
|
1529
|
-
for (const id of agent.mcp_server_ids) {
|
|
1530
|
-
const name = mcpIdToName.get(id);
|
|
1531
|
-
if (name) mcpServerNames.push(name);
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
1610
|
const config = {
|
|
1535
1611
|
external_id: agent.external_id,
|
|
1536
1612
|
name: agent.name
|
|
@@ -1538,7 +1614,6 @@ async function pullAgents(api, platformDir, filterName, projectId) {
|
|
|
1538
1614
|
if (agent.description) config.description = agent.description;
|
|
1539
1615
|
if (agent.model) config.model = agent.model;
|
|
1540
1616
|
if (skillSlugs.length > 0) config.skills = skillSlugs;
|
|
1541
|
-
if (mcpServerNames.length > 0) config.mcp_servers = mcpServerNames;
|
|
1542
1617
|
if (agent.policy_enabled) config.policy_enabled = true;
|
|
1543
1618
|
writeFileSync(join(agentDir, "config.json"), JSON.stringify(config, null, 2) + "\n");
|
|
1544
1619
|
writeFileSync(join(agentDir, "system_prompt.md"), agent.system_prompt || "");
|
|
@@ -1663,6 +1738,30 @@ async function listResources(api, platformDir, filterType, appName, projectId) {
|
|
|
1663
1738
|
}
|
|
1664
1739
|
}
|
|
1665
1740
|
}
|
|
1741
|
+
if (!filterType || filterType === "mailboxes") {
|
|
1742
|
+
const localMailboxes = loadLocalMailboxes(platformDir);
|
|
1743
|
+
const remoteMailboxes = await api.listMailboxes();
|
|
1744
|
+
const remoteBySlug = new Map(remoteMailboxes.map((m) => [m.slug, m]));
|
|
1745
|
+
const localSlugs = new Set(localMailboxes.map((m) => m.slug));
|
|
1746
|
+
for (const mb of localMailboxes) {
|
|
1747
|
+
const remote = remoteBySlug.get(mb.slug);
|
|
1748
|
+
if (!remote) {
|
|
1749
|
+
results.push({ name: mb.slug, type: "mailboxes", status: "local-only" });
|
|
1750
|
+
continue;
|
|
1751
|
+
}
|
|
1752
|
+
const descChanged = (mb.description ?? "").trim() !== (remote.description ?? "").trim();
|
|
1753
|
+
if (descChanged) {
|
|
1754
|
+
results.push({ name: mb.slug, type: "mailboxes", status: "changed", details: "description" });
|
|
1755
|
+
} else {
|
|
1756
|
+
results.push({ name: mb.slug, type: "mailboxes", status: "synced" });
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
for (const remote of remoteMailboxes) {
|
|
1760
|
+
if (!localSlugs.has(remote.slug)) {
|
|
1761
|
+
results.push({ name: remote.slug, type: "mailboxes", status: "remote-only" });
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1666
1765
|
return results;
|
|
1667
1766
|
}
|
|
1668
1767
|
function planCollectionDelete(collections, platformDir) {
|
|
@@ -2077,11 +2176,32 @@ async function showResource(api, platformDir, resourceType, resourceName, appNam
|
|
|
2077
2176
|
const skills = local?.agent.skills || remote?.skill_ids || [];
|
|
2078
2177
|
console.log(` Skills: ${skills.join(", ")}`);
|
|
2079
2178
|
}
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2179
|
+
console.log();
|
|
2180
|
+
} else if (resourceType === "mailboxes") {
|
|
2181
|
+
const localMailboxes = loadLocalMailboxes(platformDir, resourceName);
|
|
2182
|
+
const remoteMailboxes = await api.listMailboxes();
|
|
2183
|
+
const local = localMailboxes[0];
|
|
2184
|
+
const remote = remoteMailboxes.find((m) => m.slug === resourceName);
|
|
2185
|
+
if (!local && !remote) {
|
|
2186
|
+
console.log(pc.red(` Mailbox "${resourceName}" not found`));
|
|
2187
|
+
process.exit(1);
|
|
2083
2188
|
}
|
|
2084
2189
|
console.log();
|
|
2190
|
+
console.log(pc.bold(` Mailbox: ${local?.slug || remote?.slug}`));
|
|
2191
|
+
console.log();
|
|
2192
|
+
if (local && remote) {
|
|
2193
|
+
const descChanged = (local.description ?? "").trim() !== (remote.description ?? "").trim();
|
|
2194
|
+
console.log(` Status: ${descChanged ? pc.yellow("changed") : pc.green("synced")}`);
|
|
2195
|
+
} else if (local) {
|
|
2196
|
+
console.log(` Status: ${pc.yellow("local only")}`);
|
|
2197
|
+
} else {
|
|
2198
|
+
console.log(` Status: ${pc.cyan("remote only")}`);
|
|
2199
|
+
}
|
|
2200
|
+
if (remote?.email) console.log(` Email: ${remote.email}`);
|
|
2201
|
+
const desc = local?.description || remote?.description;
|
|
2202
|
+
if (desc) console.log(` Description: ${desc}`);
|
|
2203
|
+
if (remote?.project_id) console.log(` Project: ${remote.project_id}`);
|
|
2204
|
+
console.log();
|
|
2085
2205
|
} else if (resourceType === "app") {
|
|
2086
2206
|
const projectRoot = findProjectRoot();
|
|
2087
2207
|
loadEnv(projectRoot);
|
|
@@ -2173,6 +2293,13 @@ async function plan(args) {
|
|
|
2173
2293
|
allChanges.push(...changes);
|
|
2174
2294
|
}
|
|
2175
2295
|
}
|
|
2296
|
+
if (!type || type === "mailboxes") {
|
|
2297
|
+
const localMailboxes = loadLocalMailboxes(platformDir, name || void 0);
|
|
2298
|
+
if (localMailboxes.length > 0) {
|
|
2299
|
+
const changes = await planMailboxes(api, localMailboxes);
|
|
2300
|
+
allChanges.push(...changes);
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2176
2303
|
if (allChanges.length === 0) {
|
|
2177
2304
|
if (jsonOutput) {
|
|
2178
2305
|
console.log(JSON.stringify({ changes: [], warnings: [] }));
|
|
@@ -2274,12 +2401,14 @@ async function apply(args) {
|
|
|
2274
2401
|
const localAutomations = !type || type === "automations" ? loadLocalAutomations(platformDir, name || void 0, appName) : [];
|
|
2275
2402
|
const localHooks = !type || type === "hooks" ? loadLocalHooks(platformDir, name || void 0, appName) : [];
|
|
2276
2403
|
const localAgents = !type || type === "agents" ? loadLocalAgents(platformDir, name || void 0, appName) : [];
|
|
2404
|
+
const localMailboxes = !type || type === "mailboxes" ? loadLocalMailboxes(platformDir, name || void 0) : [];
|
|
2277
2405
|
if (localCollections.length > 0) allChanges.push(...await planCollections(api, localCollections));
|
|
2278
2406
|
if (localAutomations.length > 0) allChanges.push(...await planAutomations(api, localAutomations));
|
|
2279
2407
|
if (localHooks.length > 0) allChanges.push(...await planHooks(api, localHooks, collections));
|
|
2280
2408
|
if (localAgents.length > 0) allChanges.push(...await planAgents(api, localAgents, projectId));
|
|
2409
|
+
if (localMailboxes.length > 0) allChanges.push(...await planMailboxes(api, localMailboxes));
|
|
2281
2410
|
if (name) {
|
|
2282
|
-
const hasLocal = localCollections.length > 0 || localAutomations.length > 0 || localHooks.length > 0 || localAgents.length > 0;
|
|
2411
|
+
const hasLocal = localCollections.length > 0 || localAutomations.length > 0 || localHooks.length > 0 || localAgents.length > 0 || localMailboxes.length > 0;
|
|
2283
2412
|
if (!hasLocal) {
|
|
2284
2413
|
console.log();
|
|
2285
2414
|
console.log(pc.red(` Resource "${name}" not found locally`));
|
|
@@ -2370,6 +2499,11 @@ async function apply(args) {
|
|
|
2370
2499
|
totalErrors += await applyAgents(api, localAgents, projectId);
|
|
2371
2500
|
console.log();
|
|
2372
2501
|
}
|
|
2502
|
+
if (localMailboxes.length > 0) {
|
|
2503
|
+
console.log(pc.bold(" Mailboxes:"));
|
|
2504
|
+
totalErrors += await applyMailboxes(api, localMailboxes);
|
|
2505
|
+
console.log();
|
|
2506
|
+
}
|
|
2373
2507
|
if (willDeployApp) {
|
|
2374
2508
|
console.log(pc.bold(" App:"));
|
|
2375
2509
|
await applyApp(args);
|
|
@@ -2476,6 +2610,11 @@ async function pull(args) {
|
|
|
2476
2610
|
await pullAgents(api, platformDir, name || void 0, projectId);
|
|
2477
2611
|
console.log();
|
|
2478
2612
|
}
|
|
2613
|
+
if (!type || type === "mailboxes") {
|
|
2614
|
+
console.log(pc.bold(" Mailboxes:"));
|
|
2615
|
+
await pullMailboxes(api, platformDir, name || void 0);
|
|
2616
|
+
console.log();
|
|
2617
|
+
}
|
|
2479
2618
|
console.log(pc.green(" Done!"));
|
|
2480
2619
|
console.log();
|
|
2481
2620
|
}
|