@fleox-agent-crm/agentcrm 0.4.0 → 0.5.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/README.md +16 -16
- package/changelog.json +9 -0
- package/dist/admin/admin-files.json +1 -1
- package/dist/agent/agentcrm.mjs +133 -61
- package/dist/agent/chunks/{automations-DwWruxmu.mjs → automations-BqY8EwfJ.mjs} +3 -3
- package/dist/agent/chunks/{backup-W3CjgkAJ.mjs → backup-CO0EzdF_.mjs} +3 -3
- package/dist/agent/chunks/{compact-BGHI92tm.mjs → compact-qF5t42ko.mjs} +3 -3
- package/dist/agent/chunks/{exportCsv-C6e6XEmB.mjs → exportCsv-C-fIHLm1.mjs} +2 -2
- package/dist/agent/chunks/{extCheck-GgHG1dYB.mjs → extCheck-BcbUc7eB.mjs} +4 -4
- package/dist/agent/chunks/{files-D1daDgY0.mjs → files-C4YONVqQ.mjs} +2 -2
- package/dist/agent/chunks/{forms-BfuWaQjA.mjs → forms-DJDop3XY.mjs} +2 -2
- package/dist/agent/chunks/{importCsv-LVmMTaWU.mjs → importCsv-XjQJ9QIR.mjs} +2 -2
- package/dist/agent/chunks/{install-BLNflFes.mjs → install-D1lgtRIH.mjs} +1 -1
- package/dist/agent/chunks/{loader-MPD9iAvh.mjs → loader-Cv0UJf6b.mjs} +11 -11
- package/dist/agent/chunks/{migrate-CsClnnN8.mjs → migrate-Cc_8MHZv.mjs} +1 -1
- package/dist/agent/chunks/{pipelines-BAKpPk1w.mjs → pipelines-DiJ2dLqQ.mjs} +3 -3
- package/dist/agent/chunks/{records-DcHFelq5.mjs → records-CCTxxMWF.mjs} +1 -1
- package/dist/agent/chunks/{registry-COfJrSmg.mjs → registry-ClzNZv9Z.mjs} +10 -10
- package/dist/agent/chunks/{reports-BACHGccj.mjs → reports-WlI_A5Nr.mjs} +3 -3
- package/dist/agent/chunks/{runtime-C0Xf0Axi.mjs → runtime-BAF5vU5D.mjs} +17 -17
- package/dist/agent/chunks/{schema-C4lSslXv.mjs → schema-DOnnH2zL.mjs} +3 -3
- package/dist/agent/chunks/schemaApply-DKHipylx.mjs +164 -0
- package/dist/agent/chunks/{seed-6MRmQQBR.mjs → seed-Bb26Zsni.mjs} +2 -2
- package/dist/agent/chunks/{server-DC3t8r30.mjs → server-Bch4TQon.mjs} +3 -3
- package/dist/agent/chunks/{standardObjects-CheqfDqa.mjs → standardObjects-vrmqIVLH.mjs} +1 -1
- package/dist/agent/chunks/{stats-BfuLWhVV.mjs → stats-DfmDP3tE.mjs} +3 -3
- package/dist/agent/chunks/{tools-iSH-yMpl.mjs → tools-CCk24tdh.mjs} +9 -9
- package/dist/agent/chunks/{views-DH1n9Lrt.mjs → views-BbhmQO3n.mjs} +4 -4
- package/dist/version.json +1 -1
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/skills/agentcrm-admin/SKILL.md +67 -67
- package/plugin/skills/agentcrm-admin/references/records.md +5 -5
- package/plugin/skills/agentcrm-admin/references/schema.md +19 -19
- package/plugin/skills/agentcrm-extensions/SKILL.md +8 -8
- package/plugin/skills/agentcrm-extensions/references/module-recipes.md +2 -2
- package/plugin/skills/agentcrm-extensions/references/testing.md +14 -14
- package/plugin/skills/agentcrm-extensions/references/theme-recipes.md +3 -3
- package/plugin/skills/agentcrm-install/SKILL.md +13 -13
- package/plugin/skills/agentcrm-install/references/firebase.md +1 -1
- package/plugin/skills/agentcrm-install/references/github.md +1 -1
- package/plugin/skills/agentcrm-install/references/mcp.md +2 -2
- package/plugin/skills/agentcrm-install/references/plans.md +1 -1
- package/plugin/skills/agentcrm-install/references/s3.md +1 -1
- package/plugin/skills/agentcrm-manage/SKILL.md +15 -15
- package/plugin/skills/agentcrm-sales/SKILL.md +18 -18
package/dist/agent/agentcrm.mjs
CHANGED
|
@@ -142,7 +142,7 @@ const output = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
|
|
|
142
142
|
toCliError
|
|
143
143
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
144
144
|
const name = "@fleox-agent-crm/agentcrm";
|
|
145
|
-
const version = "0.
|
|
145
|
+
const version = "0.5.0";
|
|
146
146
|
const type = "module";
|
|
147
147
|
const description = "The static CRM your AI agent can run: a Twenty / HubSpot-style CRM that runs entirely in the browser or headless through the agentcrm CLI, with data on storage you own.";
|
|
148
148
|
const license = "SEE LICENSE IN LICENSE";
|
|
@@ -524,7 +524,7 @@ function tmpFolder() {
|
|
|
524
524
|
return tmpBase;
|
|
525
525
|
}
|
|
526
526
|
async function nodeImportBundle() {
|
|
527
|
-
await import("./chunks/runtime-
|
|
527
|
+
await import("./chunks/runtime-BAF5vU5D.mjs");
|
|
528
528
|
const { createNodeImportBundle } = await import("./chunks/nodeImport-ylfRDvqt.mjs");
|
|
529
529
|
return createNodeImportBundle({ runtimeDir: runtimeDir(), tmpDir: tmpFolder() });
|
|
530
530
|
}
|
|
@@ -539,7 +539,7 @@ async function loadSessionExtensions(store, opts = {}) {
|
|
|
539
539
|
if (!loadedAny && !opts.force && !hasEnabledExtensions(store)) return null;
|
|
540
540
|
try {
|
|
541
541
|
const importBundle = await nodeImportBundle();
|
|
542
|
-
const { syncExtensions } = await import("./chunks/loader-
|
|
542
|
+
const { syncExtensions } = await import("./chunks/loader-Cv0UJf6b.mjs");
|
|
543
543
|
loadedAny = true;
|
|
544
544
|
return await syncExtensions(store, { importBundle, onError: () => void 0 });
|
|
545
545
|
} catch (err) {
|
|
@@ -553,7 +553,7 @@ async function loadSessionExtensions(store, opts = {}) {
|
|
|
553
553
|
sync,
|
|
554
554
|
async close() {
|
|
555
555
|
if (!loadedAny) return;
|
|
556
|
-
(await import("./chunks/registry-
|
|
556
|
+
(await import("./chunks/registry-ClzNZv9Z.mjs")).deactivateAllExtensions();
|
|
557
557
|
}
|
|
558
558
|
};
|
|
559
559
|
}
|
|
@@ -681,7 +681,7 @@ async function openSession(alias, opts = {}) {
|
|
|
681
681
|
const [{ createOpsContext }, { createPluginRegistry, plugins: defaultPlugins }, { installAutomations }] = await Promise.all([
|
|
682
682
|
import("./chunks/context-CxFfqS4D.mjs"),
|
|
683
683
|
import("./chunks/pluginRegistry-DyHtlkcr.mjs"),
|
|
684
|
-
import("./chunks/automations-
|
|
684
|
+
import("./chunks/automations-BqY8EwfJ.mjs")
|
|
685
685
|
]);
|
|
686
686
|
const own = createPluginRegistry((hook, err) => process.stderr.write(`[agentcrm] ${hook} handler failed: ${String(err?.message ?? err)}
|
|
687
687
|
`));
|
|
@@ -695,7 +695,7 @@ async function openSession(alias, opts = {}) {
|
|
|
695
695
|
const ctx = createOpsContext(store, user, { plugins, log });
|
|
696
696
|
const system = createOpsContext(store, null, { plugins, log });
|
|
697
697
|
if (opts.lock && (!user || user.role === "admin") && store.list("objects").length) {
|
|
698
|
-
const { migrateSchema } = await import("./chunks/migrate-
|
|
698
|
+
const { migrateSchema } = await import("./chunks/migrate-Cc_8MHZv.mjs").then((n) => n.c);
|
|
699
699
|
await migrateSchema(ctx).catch((err) => warnings.push(`Schema migration skipped: ${err.message}`));
|
|
700
700
|
}
|
|
701
701
|
if (site.hosting) {
|
|
@@ -714,7 +714,7 @@ async function openSession(alias, opts = {}) {
|
|
|
714
714
|
}
|
|
715
715
|
}
|
|
716
716
|
{
|
|
717
|
-
const forms = await import("./chunks/forms-
|
|
717
|
+
const forms = await import("./chunks/forms-DJDop3XY.mjs");
|
|
718
718
|
const { buildConnector } = await import("./chunks/hosting-C_UDyMkm.mjs");
|
|
719
719
|
forms.setInboxSourceResolver((_ctx, form) => {
|
|
720
720
|
if (form.inbox.kind !== "s3") return null;
|
|
@@ -914,6 +914,29 @@ function table(rows, columns) {
|
|
|
914
914
|
const SITE_OPTION = { name: "site", type: "string", description: "Site alias (default: $AGENTCRM_SITE, ./agentcrm.json, the only site, or `site use`)." };
|
|
915
915
|
const AS_OPTION = { name: "as", type: "string", description: "Act as this CRM user (email or id) instead of the site's user." };
|
|
916
916
|
const YES_OPTION = { name: "yes", type: "boolean", description: "Apply — only after the user confirmed the plan." };
|
|
917
|
+
const util = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
918
|
+
__proto__: null,
|
|
919
|
+
AS_OPTION,
|
|
920
|
+
SITE_OPTION,
|
|
921
|
+
YES_OPTION,
|
|
922
|
+
boolOpt,
|
|
923
|
+
fieldsInput,
|
|
924
|
+
jsonObjectOpt,
|
|
925
|
+
jsonOpt,
|
|
926
|
+
listOpt,
|
|
927
|
+
multiOpt,
|
|
928
|
+
numOpt,
|
|
929
|
+
parseFilters,
|
|
930
|
+
parseScalar,
|
|
931
|
+
parseSorts,
|
|
932
|
+
positional,
|
|
933
|
+
readTextValue,
|
|
934
|
+
requireStr,
|
|
935
|
+
strOpt,
|
|
936
|
+
table,
|
|
937
|
+
usage,
|
|
938
|
+
writeOutFile
|
|
939
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
917
940
|
function fileOut(f) {
|
|
918
941
|
return {
|
|
919
942
|
id: f.id,
|
|
@@ -936,7 +959,7 @@ function readLocalFile(path) {
|
|
|
936
959
|
return { name: basename(full), bytes: new Uint8Array(readFileSync(full)) };
|
|
937
960
|
}
|
|
938
961
|
async function uploadLocalFiles(ctx, paths, targets2 = []) {
|
|
939
|
-
const { uploadFile } = await import("./chunks/files-
|
|
962
|
+
const { uploadFile } = await import("./chunks/files-C4YONVqQ.mjs");
|
|
940
963
|
const { guessMime, imageDimensions } = await import("./chunks/files-CjsPJSR6.mjs");
|
|
941
964
|
const out = [];
|
|
942
965
|
for (const p of paths) {
|
|
@@ -984,7 +1007,7 @@ const filesCommand = {
|
|
|
984
1007
|
switch (action) {
|
|
985
1008
|
case "list":
|
|
986
1009
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
987
|
-
const { listFiles } = await import("./chunks/files-
|
|
1010
|
+
const { listFiles } = await import("./chunks/files-C4YONVqQ.mjs");
|
|
988
1011
|
const target = strOpt(options, "record") ?? strOpt(options, "activity") ?? null;
|
|
989
1012
|
const items = listFiles(ctx, target, { includeRelated: boolOpt(options, "related"), kind: strOpt(options, "kind"), search: strOpt(options, "search") });
|
|
990
1013
|
const limit = Math.min(1e3, numOpt(options, "limit") ?? 100);
|
|
@@ -999,7 +1022,7 @@ ${table(r.files, ["id", "name", "mime", "size", "createdAt"])}`);
|
|
|
999
1022
|
if (record && activity) usage("Give --record or --activity, not both.");
|
|
1000
1023
|
for (const p of args) readLocalFile(p);
|
|
1001
1024
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
1002
|
-
const { attachFile } = await import("./chunks/files-
|
|
1025
|
+
const { attachFile } = await import("./chunks/files-C4YONVqQ.mjs");
|
|
1003
1026
|
const files2 = await uploadLocalFiles(ctx, args, record ? [record] : []);
|
|
1004
1027
|
if (activity) for (const f of files2) await attachFile(ctx, f.id, { kind: "activity", id: activity });
|
|
1005
1028
|
const { requireFile } = await import("./chunks/store-5gqRSKXg.mjs");
|
|
@@ -1012,7 +1035,7 @@ ${table(r.uploaded, ["id", "name", "size"])}`);
|
|
|
1012
1035
|
const out = strOpt(options, "out");
|
|
1013
1036
|
if (!out) usage("files get needs --out <path>.");
|
|
1014
1037
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
1015
|
-
const { getFile, getFileBytes } = await import("./chunks/files-
|
|
1038
|
+
const { getFile, getFileBytes } = await import("./chunks/files-C4YONVqQ.mjs");
|
|
1016
1039
|
const meta = getFile(ctx, id);
|
|
1017
1040
|
const bytes = await getFileBytes(ctx, id, { thumb: boolOpt(options, "thumb") });
|
|
1018
1041
|
writeOutFile(out, bytes);
|
|
@@ -1022,7 +1045,7 @@ ${table(r.uploaded, ["id", "name", "size"])}`);
|
|
|
1022
1045
|
case "delete": {
|
|
1023
1046
|
const id = positional(args, 0, "file id", U$1.delete);
|
|
1024
1047
|
return withSession(io, options, { lock: options.yes === true }, async ({ ctx }) => {
|
|
1025
|
-
const { getFile, deleteFile } = await import("./chunks/files-
|
|
1048
|
+
const { getFile, deleteFile } = await import("./chunks/files-C4YONVqQ.mjs");
|
|
1026
1049
|
const meta = fileOut(getFile(ctx, id));
|
|
1027
1050
|
if (options.yes !== true) return { needsConfirmation: true, plan: { delete: meta } };
|
|
1028
1051
|
await deleteFile(ctx, id);
|
|
@@ -1030,7 +1053,7 @@ ${table(r.uploaded, ["id", "name", "size"])}`);
|
|
|
1030
1053
|
}, (r) => "plan" in r && r.plan ? `Would delete ${r.plan.delete.name} (${r.plan.delete.id}). Re-run with --yes once the user agrees.` : `Deleted ${"deleted" in r ? r.deleted : id} (bytes purged by \`agentcrm compact\`).`);
|
|
1031
1054
|
}
|
|
1032
1055
|
case "usage":
|
|
1033
|
-
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/files-
|
|
1056
|
+
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/files-C4YONVqQ.mjs")).fileUsage(ctx));
|
|
1034
1057
|
default:
|
|
1035
1058
|
usage(`Unknown files action "${action ?? ""}".`, "Use list, upload, get, delete or usage.");
|
|
1036
1059
|
}
|
|
@@ -1043,7 +1066,7 @@ async function recordImageAction(io, options, args) {
|
|
|
1043
1066
|
if (!remove && !path) usage("records image needs an image path (or --remove).");
|
|
1044
1067
|
const local = remove ? null : readLocalFile(path);
|
|
1045
1068
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
1046
|
-
const { setRecordImage, clearRecordImage } = await import("./chunks/files-
|
|
1069
|
+
const { setRecordImage, clearRecordImage } = await import("./chunks/files-C4YONVqQ.mjs");
|
|
1047
1070
|
const field = strOpt(options, "field");
|
|
1048
1071
|
if (!local) {
|
|
1049
1072
|
const r = await clearRecordImage(ctx, recordId, field);
|
|
@@ -1331,7 +1354,7 @@ const recordsCommand = {
|
|
|
1331
1354
|
const filters = parseFilters(multiOpt(options, "filter"), FILTER_OPS);
|
|
1332
1355
|
const sorts = parseSorts(multiOpt(options, "sort"));
|
|
1333
1356
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
1334
|
-
const { listRecords } = await import("./chunks/records-
|
|
1357
|
+
const { listRecords } = await import("./chunks/records-CCTxxMWF.mjs");
|
|
1335
1358
|
const page = listRecords(ctx, objectId, {
|
|
1336
1359
|
filters,
|
|
1337
1360
|
sorts,
|
|
@@ -1349,7 +1372,7 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1349
1372
|
case "get": {
|
|
1350
1373
|
const id = positional(args, 0, "record id", U.get);
|
|
1351
1374
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
1352
|
-
const { getRecordDetails } = await import("./chunks/records-
|
|
1375
|
+
const { getRecordDetails } = await import("./chunks/records-CCTxxMWF.mjs");
|
|
1353
1376
|
const d = getRecordDetails(ctx, id);
|
|
1354
1377
|
return { ...await recordOut(ctx, d.record), relations: d.relations, related: d.inverse.filter((i) => i.records.length), activityCount: d.activityCount };
|
|
1355
1378
|
});
|
|
@@ -1360,7 +1383,7 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1360
1383
|
if (!Object.keys(fields).length) usage("records create needs --fields or --set.", `Usage: agentcrm ${U.create}`);
|
|
1361
1384
|
const owner = strOpt(options, "owner");
|
|
1362
1385
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
1363
|
-
const { createRecord } = await import("./chunks/records-
|
|
1386
|
+
const { createRecord } = await import("./chunks/records-CCTxxMWF.mjs");
|
|
1364
1387
|
return recordOut(ctx, await createRecord(ctx, objectId, fields, owner ? { ownerId: owner } : {}));
|
|
1365
1388
|
}, (r) => `Created ${r.object} ${r.id} (${String(r.label)})`);
|
|
1366
1389
|
}
|
|
@@ -1370,7 +1393,7 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1370
1393
|
const owner = strOpt(options, "owner");
|
|
1371
1394
|
if (!Object.keys(fields).length && owner === void 0) usage("records update needs --fields, --set or --owner.");
|
|
1372
1395
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
1373
|
-
const { updateRecord } = await import("./chunks/records-
|
|
1396
|
+
const { updateRecord } = await import("./chunks/records-CCTxxMWF.mjs");
|
|
1374
1397
|
return recordOut(ctx, await updateRecord(ctx, id, fields, owner !== void 0 ? { ownerId: owner || null } : {}));
|
|
1375
1398
|
}, (r) => `Updated ${r.id} (${String(r.label)})`);
|
|
1376
1399
|
}
|
|
@@ -1378,7 +1401,7 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1378
1401
|
if (!args.length) usage("records delete needs at least one id.", `Usage: agentcrm ${U.delete}`);
|
|
1379
1402
|
const hard = boolOpt(options, "hard");
|
|
1380
1403
|
return withSession(io, options, { lock: options.yes === true }, async ({ ctx }) => {
|
|
1381
|
-
const { getRecord, deleteRecord, bulkDelete } = await import("./chunks/records-
|
|
1404
|
+
const { getRecord, deleteRecord, bulkDelete } = await import("./chunks/records-CCTxxMWF.mjs");
|
|
1382
1405
|
const { recordLabel } = await import("./chunks/fields-B0bitgmr.mjs");
|
|
1383
1406
|
const { objectOf } = await import("./chunks/store-5gqRSKXg.mjs");
|
|
1384
1407
|
const targets2 = args.map((id) => getRecord(ctx, id, { includeDeleted: true }));
|
|
@@ -1391,7 +1414,7 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1391
1414
|
case "restore": {
|
|
1392
1415
|
const id = positional(args, 0, "record id", U.restore);
|
|
1393
1416
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
1394
|
-
const { restoreRecord } = await import("./chunks/records-
|
|
1417
|
+
const { restoreRecord } = await import("./chunks/records-CCTxxMWF.mjs");
|
|
1395
1418
|
return recordOut(ctx, await restoreRecord(ctx, id));
|
|
1396
1419
|
});
|
|
1397
1420
|
}
|
|
@@ -1399,7 +1422,7 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1399
1422
|
const query = args.join(" ").trim();
|
|
1400
1423
|
if (!query) usage("records search needs a query.", `Usage: agentcrm ${U.search}`);
|
|
1401
1424
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
1402
|
-
const { searchRecords } = await import("./chunks/records-
|
|
1425
|
+
const { searchRecords } = await import("./chunks/records-CCTxxMWF.mjs");
|
|
1403
1426
|
return searchRecords(ctx, query, { objects: listOpt(options, "object"), limit: Math.min(100, numOpt(options, "limit") ?? 20) });
|
|
1404
1427
|
});
|
|
1405
1428
|
}
|
|
@@ -1416,7 +1439,7 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1416
1439
|
const [primary, ...dups] = args;
|
|
1417
1440
|
if (!primary || !dups.length) usage("records merge needs <primaryId> <duplicateId>….", `Usage: agentcrm ${U.merge}`);
|
|
1418
1441
|
return withSession(io, options, { lock: options.yes === true }, async ({ ctx }) => {
|
|
1419
|
-
const { getRecord } = await import("./chunks/records-
|
|
1442
|
+
const { getRecord } = await import("./chunks/records-CCTxxMWF.mjs");
|
|
1420
1443
|
const all = [primary, ...dups].map((id) => getRecord(ctx, id));
|
|
1421
1444
|
const plan = { primary: await recordOut(ctx, all[0]), duplicates: await Promise.all(all.slice(1).map((r) => recordOut(ctx, r))) };
|
|
1422
1445
|
if (options.yes !== true) return { needsConfirmation: true, plan };
|
|
@@ -1448,13 +1471,13 @@ const pipelinesCommand = {
|
|
|
1448
1471
|
io,
|
|
1449
1472
|
options,
|
|
1450
1473
|
{},
|
|
1451
|
-
async ({ ctx }) => (await import("./chunks/pipelines-
|
|
1474
|
+
async ({ ctx }) => (await import("./chunks/pipelines-DiJ2dLqQ.mjs")).listPipelines(ctx, strOpt(options, "object")),
|
|
1452
1475
|
(ps) => ps.map((p) => `${p.id} (${p.name}, ${p.object}): ${p.stages.map((s) => `${s.label} ${Math.round(s.probability * (s.probability <= 1 ? 100 : 1))}%`).join(" → ")}`).join("\n")
|
|
1453
1476
|
);
|
|
1454
1477
|
}
|
|
1455
1478
|
if (action === "move") {
|
|
1456
1479
|
if (!id || !stage.length) usage("pipelines move needs <recordId> <stage>.");
|
|
1457
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => recordOut(ctx, await (await import("./chunks/pipelines-
|
|
1480
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => recordOut(ctx, await (await import("./chunks/pipelines-DiJ2dLqQ.mjs")).moveStage(ctx, id, stage.join(" "), { lostReason: strOpt(options, "lost-reason") })));
|
|
1458
1481
|
}
|
|
1459
1482
|
usage(`Unknown pipelines action "${action}".`, "Use list or move.");
|
|
1460
1483
|
}
|
|
@@ -1486,7 +1509,7 @@ const viewsCommand = {
|
|
|
1486
1509
|
const [action = "list", id] = positionals;
|
|
1487
1510
|
switch (action) {
|
|
1488
1511
|
case "list":
|
|
1489
|
-
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/views-
|
|
1512
|
+
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/views-BbhmQO3n.mjs")).listViews(ctx, strOpt(options, "object")), (vs) => table(vs, ["id", "object", "name", "type", "shared"]));
|
|
1490
1513
|
case "create": {
|
|
1491
1514
|
const type2 = strOpt(options, "type") ?? "table";
|
|
1492
1515
|
if (type2 !== "table" && type2 !== "kanban") usage("--type must be table or kanban.");
|
|
@@ -1501,12 +1524,12 @@ const viewsCommand = {
|
|
|
1501
1524
|
...strOpt(options, "pipeline") ? { pipelineId: strOpt(options, "pipeline") } : {},
|
|
1502
1525
|
shared: boolOpt(options, "shared")
|
|
1503
1526
|
};
|
|
1504
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/views-
|
|
1527
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/views-BbhmQO3n.mjs")).createView(ctx, input));
|
|
1505
1528
|
}
|
|
1506
1529
|
case "delete":
|
|
1507
1530
|
if (!id) usage("views delete needs a view id.");
|
|
1508
1531
|
return withSession(io, options, { lock: options.yes === true }, async ({ ctx }) => {
|
|
1509
|
-
const { getView, deleteView } = await import("./chunks/views-
|
|
1532
|
+
const { getView, deleteView } = await import("./chunks/views-BbhmQO3n.mjs");
|
|
1510
1533
|
const v = getView(ctx, id);
|
|
1511
1534
|
if (options.yes !== true) return { needsConfirmation: true, plan: { delete: { id: v.id, name: v.name, object: v.object, shared: v.shared } } };
|
|
1512
1535
|
return deleteView(ctx, id);
|
|
@@ -1833,6 +1856,10 @@ async function dryRun(ctx, work) {
|
|
|
1833
1856
|
const copy = createOpsContext(store, ctx.user, { now: ctx.now, plugins: createPluginRegistry(() => void 0) });
|
|
1834
1857
|
return { result: await work(copy), store };
|
|
1835
1858
|
}
|
|
1859
|
+
const dryRun$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1860
|
+
__proto__: null,
|
|
1861
|
+
dryRun
|
|
1862
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1836
1863
|
const CASCADE_OPTION = { name: "cascade", type: "boolean", description: "enable / disable: also enable the dependencies / disable the dependents." };
|
|
1837
1864
|
function parseJsonValue(raw, name2) {
|
|
1838
1865
|
const text = readTextValue(raw, name2);
|
|
@@ -2097,7 +2124,7 @@ async function check({ io, options, positionals }) {
|
|
|
2097
2124
|
const kind = strOpt(options, "kind");
|
|
2098
2125
|
if (kind && kind !== "module" && kind !== "theme") usage("--kind is module or theme.");
|
|
2099
2126
|
const { readRawPackage } = await import("./chunks/extPackage-DuZ6GZhp.mjs");
|
|
2100
|
-
const { checkExtension } = await import("./chunks/extCheck-
|
|
2127
|
+
const { checkExtension } = await import("./chunks/extCheck-BcbUc7eB.mjs");
|
|
2101
2128
|
const raw = await readRawPackage(target);
|
|
2102
2129
|
const report = await checkExtension(raw, { kind, callTools: !boolOpt(options, "no-call") });
|
|
2103
2130
|
printResult(io, report, () => {
|
|
@@ -2144,7 +2171,7 @@ async function install({ io, options, positionals }) {
|
|
|
2144
2171
|
const apply = options.yes === true;
|
|
2145
2172
|
const disabled = boolOpt(options, "disabled");
|
|
2146
2173
|
if (!boolOpt(options, "force")) {
|
|
2147
|
-
const { checkExtension } = await import("./chunks/extCheck-
|
|
2174
|
+
const { checkExtension } = await import("./chunks/extCheck-BcbUc7eB.mjs");
|
|
2148
2175
|
const report = await checkExtension(raw, { callTools: false });
|
|
2149
2176
|
if (!report.valid) {
|
|
2150
2177
|
throw new CliError(
|
|
@@ -2180,7 +2207,7 @@ async function install({ io, options, positionals }) {
|
|
|
2180
2207
|
}
|
|
2181
2208
|
const result = await ext.installExtension(s.ctx, pkg2, disabled ? { enabled: false } : {});
|
|
2182
2209
|
const report = await s.extensions.sync();
|
|
2183
|
-
const { getLoadedExtension } = await import("./chunks/registry-
|
|
2210
|
+
const { getLoadedExtension } = await import("./chunks/registry-ClzNZv9Z.mjs");
|
|
2184
2211
|
const loaded = getLoadedExtension(m.id);
|
|
2185
2212
|
const failure = report?.failed.find((f) => f.id === m.id || f.id === "*");
|
|
2186
2213
|
if (failure && !loaded) return { ...result, author: m.author ?? null, load: { status: "error", error: failure.error } };
|
|
@@ -2242,7 +2269,7 @@ const extCommand = {
|
|
|
2242
2269
|
if (kind && kind !== "module" && kind !== "theme") usage("--kind is module or theme.");
|
|
2243
2270
|
return withSession(io, options, {}, async (s) => {
|
|
2244
2271
|
const { listExtensions } = await import("./chunks/extensions-Bp72uZ9a.mjs");
|
|
2245
|
-
const { getLoadedExtension } = await import("./chunks/registry-
|
|
2272
|
+
const { getLoadedExtension } = await import("./chunks/registry-ClzNZv9Z.mjs");
|
|
2246
2273
|
return listExtensions(s.ctx, kind ? { kind } : {}).map((e) => ({ ...e, load: s.extensions.safeMode ? "skipped" : getLoadedExtension(e.id)?.status ?? (e.enabled ? "not loaded" : "disabled"), ...getLoadedExtension(e.id)?.error ? { loadError: getLoadedExtension(e.id)?.error } : {} }));
|
|
2247
2274
|
}, (rows) => table(rows.map((r) => ({ ...r, enabled: r.enabled ? "yes" : "no" })), ["id", "kind", "name", "version", "enabled", "load", "author"]));
|
|
2248
2275
|
}
|
|
@@ -2357,7 +2384,7 @@ const importCommand = {
|
|
|
2357
2384
|
options,
|
|
2358
2385
|
{},
|
|
2359
2386
|
async ({ ctx }) => {
|
|
2360
|
-
const plan = await (await import("./chunks/backup-
|
|
2387
|
+
const plan = await (await import("./chunks/backup-CO0EzdF_.mjs")).planBackupZip(ctx, bytes, { mode: options.replace === true ? "replace" : "merge" });
|
|
2361
2388
|
return { needsConfirmation: true, plan: { restore: resolve(path), bytes: bytes.length, ...plan } };
|
|
2362
2389
|
},
|
|
2363
2390
|
(r) => [
|
|
@@ -2367,7 +2394,7 @@ const importCommand = {
|
|
|
2367
2394
|
].join("\n")
|
|
2368
2395
|
);
|
|
2369
2396
|
}
|
|
2370
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/backup-
|
|
2397
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/backup-CO0EzdF_.mjs")).importBackupZip(ctx, bytes, { mode: options.replace === true ? "replace" : "merge" }), (r) => `Restored ${r.written} document(s) and ${r.files} file(s)`);
|
|
2371
2398
|
}
|
|
2372
2399
|
if (kind !== "csv") usage('Only "import csv" and "import zip" are supported.', "Usage: agentcrm import csv <file> --object <id>");
|
|
2373
2400
|
const source = positional(positionals, 1, "CSV file (or -)", "import csv <file|-> --object <id>");
|
|
@@ -2378,7 +2405,7 @@ const importCommand = {
|
|
|
2378
2405
|
const apply = options.yes === true && options["dry-run"] !== true;
|
|
2379
2406
|
const shown = numOpt(options, "rows") ?? 100;
|
|
2380
2407
|
return withSession(io, options, { lock: apply }, async ({ ctx }) => {
|
|
2381
|
-
const { importCsv } = await import("./chunks/importCsv-
|
|
2408
|
+
const { importCsv } = await import("./chunks/importCsv-XjQJ9QIR.mjs");
|
|
2382
2409
|
const report = await importCsv(ctx, {
|
|
2383
2410
|
object: objectId,
|
|
2384
2411
|
csv,
|
|
@@ -2427,7 +2454,7 @@ const exportCommand = {
|
|
|
2427
2454
|
const file2 = strOpt(options, "out");
|
|
2428
2455
|
if (!file2) usage("export zip needs --out <file.zip>.");
|
|
2429
2456
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
2430
|
-
const { exportBackupZip } = await import("./chunks/backup-
|
|
2457
|
+
const { exportBackupZip } = await import("./chunks/backup-CO0EzdF_.mjs");
|
|
2431
2458
|
const { zip, report } = await exportBackupZip(ctx, { includeFiles: options["no-files"] !== true });
|
|
2432
2459
|
writeOutFile(file2, zip);
|
|
2433
2460
|
return { file: resolve(file2), zipBytes: zip.length, files: report.files, missing: report.missing, fileBytes: report.bytes };
|
|
@@ -2446,7 +2473,7 @@ const exportCommand = {
|
|
|
2446
2473
|
const filters = parseFilters(multiOpt(options, "filter"), FILTER_OPS);
|
|
2447
2474
|
const sorts = parseSorts(multiOpt(options, "sort"));
|
|
2448
2475
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
2449
|
-
const { exportCsv } = await import("./chunks/exportCsv-
|
|
2476
|
+
const { exportCsv } = await import("./chunks/exportCsv-C-fIHLm1.mjs");
|
|
2450
2477
|
const csv = exportCsv(ctx, objectId, {
|
|
2451
2478
|
viewId: strOpt(options, "view"),
|
|
2452
2479
|
filters,
|
|
@@ -2462,7 +2489,7 @@ const exportCommand = {
|
|
|
2462
2489
|
}
|
|
2463
2490
|
if (kind === "json") {
|
|
2464
2491
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
2465
|
-
const { exportJson } = await import("./chunks/exportCsv-
|
|
2492
|
+
const { exportJson } = await import("./chunks/exportCsv-C-fIHLm1.mjs");
|
|
2466
2493
|
const data = exportJson(ctx, { collections: listOpt(options, "collections") });
|
|
2467
2494
|
const text = JSON.stringify(data, null, 2);
|
|
2468
2495
|
if (out) return deliver(text, {});
|
|
@@ -2506,7 +2533,7 @@ const reportCommand = {
|
|
|
2506
2533
|
...strOpt(options, "pipeline") ? { pipelineId: strOpt(options, "pipeline") } : {},
|
|
2507
2534
|
...strOpt(options, "owner") ? { ownerId: strOpt(options, "owner") } : {}
|
|
2508
2535
|
};
|
|
2509
|
-
return withSession(io, options, {}, async ({ ctx }) => ({ report: name2, data: (await import("./chunks/reports-
|
|
2536
|
+
return withSession(io, options, {}, async ({ ctx }) => ({ report: name2, data: (await import("./chunks/reports-WlI_A5Nr.mjs")).runReport(ctx, internal, params) }));
|
|
2510
2537
|
}
|
|
2511
2538
|
};
|
|
2512
2539
|
const statsCommand = {
|
|
@@ -2516,7 +2543,7 @@ const statsCommand = {
|
|
|
2516
2543
|
options: [SITE_OPTION, AS_OPTION],
|
|
2517
2544
|
async run({ io, options }) {
|
|
2518
2545
|
return withSession(io, options, {}, async ({ ctx, store }) => {
|
|
2519
|
-
const stats = (await import("./chunks/stats-
|
|
2546
|
+
const stats = (await import("./chunks/stats-DfmDP3tE.mjs")).getStats(ctx);
|
|
2520
2547
|
const journal = store.stats;
|
|
2521
2548
|
return { ...stats, ...journal ? { journal: await journal.call(store) } : {} };
|
|
2522
2549
|
}, (s) => [`backend: ${s.backend}`, ...s.objects.map((o) => ` ${o.label}: ${o.count}${o.deleted ? ` (+${o.deleted} deleted)` : ""}`), `open tasks: ${s.openTasks} (${s.overdueTasks} overdue)`, `users: ${s.users}`].join("\n"));
|
|
@@ -2530,7 +2557,7 @@ const compactCommand = {
|
|
|
2530
2557
|
async run({ io, options }) {
|
|
2531
2558
|
const apply = options.yes === true;
|
|
2532
2559
|
return withSession(io, options, { lock: apply }, async ({ ctx }) => {
|
|
2533
|
-
const { compactData } = await import("./chunks/compact-
|
|
2560
|
+
const { compactData } = await import("./chunks/compact-qF5t42ko.mjs");
|
|
2534
2561
|
const report = await compactData(ctx, { olderThanDays: numOpt(options, "older-than"), keepRuns: numOpt(options, "keep-runs"), dryRun: !apply });
|
|
2535
2562
|
return apply ? report : { needsConfirmation: true, plan: report };
|
|
2536
2563
|
}, (r) => "plan" in r ? `Would purge ${r.plan.purgedRecords.length} record(s), ${r.plan.purgedActivities} activit(ies), ${r.plan.purgedRuns} run(s), ${r.plan.purgedFiles} file(s). Re-run with --yes once the user agrees.` : `Purged ${r.purgedRecords.length} record(s), ${r.purgedFiles} file(s); storage compacted: ${r.storageCompacted}`);
|
|
@@ -2551,19 +2578,19 @@ const automationsCommand = {
|
|
|
2551
2578
|
const [action = "list", id] = positionals;
|
|
2552
2579
|
switch (action) {
|
|
2553
2580
|
case "list":
|
|
2554
|
-
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/automations-
|
|
2581
|
+
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/automations-BqY8EwfJ.mjs")).listAutomations(ctx).map((a) => ({ id: a.id, name: a.name, enabled: a.enabled, object: a.object, trigger: a.trigger, actions: a.actions.map((x) => x.type), lastRunAt: a.lastRunAt ? new Date(a.lastRunAt).toISOString() : null })), (rows) => table(rows, ["id", "name", "enabled", "object", "lastRunAt"]));
|
|
2555
2582
|
case "enable":
|
|
2556
2583
|
case "disable": {
|
|
2557
2584
|
if (!id) usage(`automations ${action} needs an id.`);
|
|
2558
2585
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
2559
|
-
const mod = await import("./chunks/automations-
|
|
2586
|
+
const mod = await import("./chunks/automations-BqY8EwfJ.mjs");
|
|
2560
2587
|
return mod.setAutomationEnabled(ctx, id, action === "enable");
|
|
2561
2588
|
});
|
|
2562
2589
|
}
|
|
2563
2590
|
case "run": {
|
|
2564
2591
|
const apply = options.yes === true;
|
|
2565
2592
|
return withSession(io, options, { lock: apply }, async ({ ctx }) => {
|
|
2566
|
-
const { runScheduled } = await import("./chunks/automations-
|
|
2593
|
+
const { runScheduled } = await import("./chunks/automations-BqY8EwfJ.mjs");
|
|
2567
2594
|
const report = await runScheduled(ctx, { dryRun: !apply, automationId: strOpt(options, "id"), force: boolOpt(options, "force") });
|
|
2568
2595
|
return apply ? report : { needsConfirmation: true, ...report };
|
|
2569
2596
|
}, (r) => `${"needsConfirmation" in r ? "DRY RUN — " : ""}ran ${r.ran}, skipped ${r.skipped}, errors ${r.errors}`);
|
|
@@ -2587,11 +2614,11 @@ const formsCommand = {
|
|
|
2587
2614
|
const [action = "list", id] = positionals;
|
|
2588
2615
|
switch (action) {
|
|
2589
2616
|
case "list":
|
|
2590
|
-
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/forms-
|
|
2617
|
+
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/forms-DJDop3XY.mjs")).listForms(ctx), (fs) => table(fs, ["id", "name", "object", "publishedPath"]));
|
|
2591
2618
|
case "publish": {
|
|
2592
2619
|
if (!id) usage("forms publish needs a form id.");
|
|
2593
2620
|
return withSession(io, options, { lock: options.yes === true }, async (s) => {
|
|
2594
|
-
const forms = await import("./chunks/forms-
|
|
2621
|
+
const forms = await import("./chunks/forms-DJDop3XY.mjs");
|
|
2595
2622
|
const built = await forms.buildFormHtml(s.ctx, id);
|
|
2596
2623
|
const target = s.hostingTarget();
|
|
2597
2624
|
if (!target) usage(`${s.site.alias} has no hosting to publish the form to.`);
|
|
@@ -2605,7 +2632,7 @@ const formsCommand = {
|
|
|
2605
2632
|
case "ingest": {
|
|
2606
2633
|
const apply = options.yes === true;
|
|
2607
2634
|
return withSession(io, options, { lock: apply }, async ({ ctx }) => {
|
|
2608
|
-
const { ingestInbox } = await import("./chunks/forms-
|
|
2635
|
+
const { ingestInbox } = await import("./chunks/forms-DJDop3XY.mjs");
|
|
2609
2636
|
const report = await ingestInbox(ctx, strOpt(options, "form"), { dryRun: !apply, limit: numOpt(options, "limit") });
|
|
2610
2637
|
return apply ? report : { needsConfirmation: true, ...report };
|
|
2611
2638
|
}, (r) => `${"needsConfirmation" in r ? "DRY RUN — " : ""}processed ${r.processed}: ${r.created} created, ${r.updated} updated, ${r.failed} failed`);
|
|
@@ -2845,7 +2872,7 @@ async function runDoctor(site, opts = {}) {
|
|
|
2845
2872
|
installBrowserEnv();
|
|
2846
2873
|
try {
|
|
2847
2874
|
if (site.runtime.backend === "journal" && site.runtime.journal.connectorId === "git-pages") {
|
|
2848
|
-
const { probeTarget } = await import("./chunks/install-
|
|
2875
|
+
const { probeTarget } = await import("./chunks/install-D1lgtRIH.mjs");
|
|
2849
2876
|
const { dataTargetOf: dataTargetOf2 } = await Promise.resolve().then(() => session);
|
|
2850
2877
|
const probe = await probeTarget(dataTargetOf2(site), { requireSiteUrl: false, requirePrivate: true });
|
|
2851
2878
|
add(probe.ok ? { id: "data-repo", status: "ok", message: probe.detail } : { id: "data-repo", status: "fail", message: probe.detail, fix: "Make the data repository private and check the token's Contents permission." });
|
|
@@ -2871,7 +2898,7 @@ async function runDoctor(site, opts = {}) {
|
|
|
2871
2898
|
if (!settingsDoc(store)) missing.push("settings");
|
|
2872
2899
|
if (!usersOf(store).some((u) => u.role === "admin" && !u.disabled)) missing.push("an active admin user");
|
|
2873
2900
|
if (missing.length && opts.repair) {
|
|
2874
|
-
const { seedCrm } = await import("./chunks/seed-
|
|
2901
|
+
const { seedCrm } = await import("./chunks/seed-Bb26Zsni.mjs");
|
|
2875
2902
|
repaired = await seedCrm(session$1.system, { admin: site.user ? { name: site.user.split("@")[0], email: site.user } : void 0 });
|
|
2876
2903
|
add({ id: "dataset", status: "ok", message: `Repaired: seeded ${missing.join(", ")}.` });
|
|
2877
2904
|
} else {
|
|
@@ -3014,7 +3041,7 @@ const installCommand = {
|
|
|
3014
3041
|
const { resolvePlan } = await import("./chunks/plan-BmTat6-T.mjs");
|
|
3015
3042
|
const plan = resolvePlan(readPlan(planPath));
|
|
3016
3043
|
if (getSite(plan.alias)) throw new CliError("site-exists", `A site named "${plan.alias}" is already registered.`, "Use another alias, or `agentcrm site forget` it first.");
|
|
3017
|
-
const { checkPlan, runInstall } = await import("./chunks/install-
|
|
3044
|
+
const { checkPlan, runInstall } = await import("./chunks/install-D1lgtRIH.mjs");
|
|
3018
3045
|
io.err("Checking access…");
|
|
3019
3046
|
const checks = await checkPlan(plan);
|
|
3020
3047
|
const summary = {
|
|
@@ -3448,13 +3475,13 @@ const objectsCommand = {
|
|
|
3448
3475
|
switch (action) {
|
|
3449
3476
|
case "list":
|
|
3450
3477
|
return withSession(io, options, {}, async ({ ctx, store }) => {
|
|
3451
|
-
const { listObjects } = await import("./chunks/schema-
|
|
3478
|
+
const { listObjects } = await import("./chunks/schema-DOnnH2zL.mjs");
|
|
3452
3479
|
const { recordsOf } = await import("./chunks/store-5gqRSKXg.mjs");
|
|
3453
3480
|
return listObjects(ctx).map((o) => ({ id: o.id, labelSingular: o.labelSingular, labelPlural: o.labelPlural, standard: o.standard, labelField: o.labelField, fields: o.fields.length, records: recordsOf(store, o.id).length }));
|
|
3454
3481
|
}, (rows) => table(rows, ["id", "labelPlural", "fields", "records", "standard"]));
|
|
3455
3482
|
case "get": {
|
|
3456
3483
|
const objectId = positional(positionals, 1, "object id", "objects get <id>");
|
|
3457
|
-
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/schema-
|
|
3484
|
+
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/schema-DOnnH2zL.mjs")).describeSchema(ctx, objectId)[0]);
|
|
3458
3485
|
}
|
|
3459
3486
|
case "create": {
|
|
3460
3487
|
const data = jsonObjectOpt(options, "data") ?? {};
|
|
@@ -3467,7 +3494,7 @@ const objectsCommand = {
|
|
|
3467
3494
|
...strOpt(options, "color") ? { color: strOpt(options, "color") } : {}
|
|
3468
3495
|
};
|
|
3469
3496
|
if (!input.labelSingular || !input.labelPlural) usage("objects create needs --singular and --plural (or --data).");
|
|
3470
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-
|
|
3497
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-DOnnH2zL.mjs")).createObject(ctx, input));
|
|
3471
3498
|
}
|
|
3472
3499
|
case "update": {
|
|
3473
3500
|
const objectId = positional(positionals, 1, "object id", "objects update <id> …");
|
|
@@ -3479,12 +3506,12 @@ const objectsCommand = {
|
|
|
3479
3506
|
...strOpt(options, "label-field") ? { labelField: strOpt(options, "label-field") } : {}
|
|
3480
3507
|
};
|
|
3481
3508
|
if (!Object.keys(patch).length) usage("objects update needs --singular, --plural, --icon, --color or --label-field.");
|
|
3482
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-
|
|
3509
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-DOnnH2zL.mjs")).updateObject(ctx, objectId, patch));
|
|
3483
3510
|
}
|
|
3484
3511
|
case "delete": {
|
|
3485
3512
|
if (!id) usage("objects delete needs an object id.");
|
|
3486
3513
|
return withSession(io, options, { lock: options.yes === true }, async ({ ctx, store }) => {
|
|
3487
|
-
const { getObject, deleteObject } = await import("./chunks/schema-
|
|
3514
|
+
const { getObject, deleteObject } = await import("./chunks/schema-DOnnH2zL.mjs");
|
|
3488
3515
|
const { recordsOf } = await import("./chunks/store-5gqRSKXg.mjs");
|
|
3489
3516
|
const o = getObject(ctx, id);
|
|
3490
3517
|
const plan = { object: o.id, label: o.labelPlural, standard: o.standard, recordsDeleted: recordsOf(store, o.id, { includeDeleted: true }).length };
|
|
@@ -3542,7 +3569,7 @@ const fieldsCommand = {
|
|
|
3542
3569
|
...boolOpt(options, "unique") ? { unique: true } : {},
|
|
3543
3570
|
...strOpt(options, "description") ? { description: strOpt(options, "description") } : {}
|
|
3544
3571
|
};
|
|
3545
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-
|
|
3572
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-DOnnH2zL.mjs")).createField(ctx, objectId, input));
|
|
3546
3573
|
}
|
|
3547
3574
|
case "update": {
|
|
3548
3575
|
if (!fieldId) usage("fields update needs a field id.");
|
|
@@ -3559,12 +3586,12 @@ const fieldsCommand = {
|
|
|
3559
3586
|
...strOpt(options, "description") !== void 0 ? { description: strOpt(options, "description") } : {}
|
|
3560
3587
|
};
|
|
3561
3588
|
if (!Object.keys(patch).length) usage("fields update needs at least one change.");
|
|
3562
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-
|
|
3589
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-DOnnH2zL.mjs")).updateField(ctx, objectId, fieldId, patch));
|
|
3563
3590
|
}
|
|
3564
3591
|
case "delete": {
|
|
3565
3592
|
if (!fieldId) usage("fields delete needs a field id.");
|
|
3566
3593
|
return withSession(io, options, { lock: options.yes === true }, async ({ ctx, store }) => {
|
|
3567
|
-
const { getObject, deleteField } = await import("./chunks/schema-
|
|
3594
|
+
const { getObject, deleteField } = await import("./chunks/schema-DOnnH2zL.mjs");
|
|
3568
3595
|
const { recordsOf } = await import("./chunks/store-5gqRSKXg.mjs");
|
|
3569
3596
|
const field = getObject(ctx, objectId).fields.find((f) => f.id === fieldId);
|
|
3570
3597
|
if (!field) usage(`No field "${fieldId}" on ${objectId}.`, `\`agentcrm objects get ${objectId}\` lists them.`);
|
|
@@ -3578,6 +3605,50 @@ const fieldsCommand = {
|
|
|
3578
3605
|
}
|
|
3579
3606
|
}
|
|
3580
3607
|
};
|
|
3608
|
+
const schemaCommand = {
|
|
3609
|
+
name: "schema",
|
|
3610
|
+
usage: "schema apply <file|-> [--yes]",
|
|
3611
|
+
summary: "Bring the data model in line with a JSON description ({ objects: [{ id, labelSingular, labelPlural, icon, color, labelField, fields: [{ id, label, type, options, relation… }] }], pipelines: [{ id, name, object, stages }], views: [{ object, name, columns, filters, sorts, groupBy, shared }] }). Creates what is missing and updates what differs; never deletes, never changes a field type (reported as a conflict), never removes a select option or a stage; reports custom fields the description doesn't list. Prints the plan unless --yes.",
|
|
3612
|
+
subcommands: [{ name: "apply", usage: "schema apply <file|-> [--yes]", summary: "Apply a schema description (plan unless --yes).", writes: true }],
|
|
3613
|
+
options: [SITE_OPTION, AS_OPTION, YES_OPTION],
|
|
3614
|
+
async run({ io, options, positionals }) {
|
|
3615
|
+
const [action, source] = positionals;
|
|
3616
|
+
if (action !== "apply") usage(`Unknown schema action "${action ?? ""}".`, "Use schema apply <file|-> [--yes].");
|
|
3617
|
+
if (!source) usage("schema apply needs a file (or - for stdin).", "Example: agentcrm schema apply crm-schema.json");
|
|
3618
|
+
const { readTextValue: readTextValue2 } = await Promise.resolve().then(() => util);
|
|
3619
|
+
const text = readTextValue2(source === "-" ? "-" : `@${source}`, "schema");
|
|
3620
|
+
let raw;
|
|
3621
|
+
try {
|
|
3622
|
+
raw = JSON.parse(text);
|
|
3623
|
+
} catch (err) {
|
|
3624
|
+
usage(`The schema is not valid JSON: ${err.message}`);
|
|
3625
|
+
}
|
|
3626
|
+
const apply = options.yes === true;
|
|
3627
|
+
const { applySchema, parseSchemaSpec } = await import("./chunks/schemaApply-DKHipylx.mjs");
|
|
3628
|
+
const spec = parseSchemaSpec(raw);
|
|
3629
|
+
return withSession(
|
|
3630
|
+
io,
|
|
3631
|
+
options,
|
|
3632
|
+
{ lock: apply },
|
|
3633
|
+
async ({ ctx }) => {
|
|
3634
|
+
if (apply) return applySchema(ctx, spec);
|
|
3635
|
+
const { dryRun: dryRun2 } = await Promise.resolve().then(() => dryRun$1);
|
|
3636
|
+
const { result } = await dryRun2(ctx, (copy) => applySchema(copy, spec));
|
|
3637
|
+
return result.changes.length ? { needsConfirmation: true, plan: result } : { ...result, upToDate: true };
|
|
3638
|
+
},
|
|
3639
|
+
(r) => {
|
|
3640
|
+
const report = "needsConfirmation" in r ? r.plan : r;
|
|
3641
|
+
const lines = report.changes.map((c) => ` ${c.action} ${c.kind} ${c.target}${c.changes?.length ? ` (${c.changes.join(", ")})` : ""}`);
|
|
3642
|
+
const extra = [
|
|
3643
|
+
...report.conflicts.map((c) => ` conflict: ${c}`),
|
|
3644
|
+
...report.extraFields.length ? [` not in the schema (kept): ${report.extraFields.join(", ")}`] : []
|
|
3645
|
+
];
|
|
3646
|
+
if ("needsConfirmation" in r) return [`Would change ${report.changes.length} thing(s):`, ...lines, ...extra, "Nothing changed — re-run with --yes once the user agrees."].join("\n");
|
|
3647
|
+
return [report.changes.length ? `Applied ${report.changes.length} change(s):` : "The data model already matches the schema.", ...lines, ...extra].join("\n");
|
|
3648
|
+
}
|
|
3649
|
+
);
|
|
3650
|
+
}
|
|
3651
|
+
};
|
|
3581
3652
|
const MIME = {
|
|
3582
3653
|
".html": "text/html; charset=utf-8",
|
|
3583
3654
|
".js": "text/javascript; charset=utf-8",
|
|
@@ -3871,7 +3942,7 @@ const toolsCommand = {
|
|
|
3871
3942
|
async run({ io, options, positionals }) {
|
|
3872
3943
|
const [action = "list"] = positionals;
|
|
3873
3944
|
if (action === "list") {
|
|
3874
|
-
const { listAiTools, AI_TOOLS } = await import("./chunks/tools-
|
|
3945
|
+
const { listAiTools, AI_TOOLS } = await import("./chunks/tools-CCk24tdh.mjs");
|
|
3875
3946
|
const builtin = new Set(AI_TOOLS.map((t) => t.name));
|
|
3876
3947
|
const shape = () => listAiTools().map((t) => ({ name: t.name, description: t.description, mutating: t.mutating, source: builtin.has(t.name) ? "builtin" : "extension", inputSchema: t.inputSchema }));
|
|
3877
3948
|
const human = (r) => table(r.tools, ["name", "mutating", "source", "description"]);
|
|
@@ -3891,7 +3962,7 @@ const toolsCommand = {
|
|
|
3891
3962
|
}
|
|
3892
3963
|
if (action === "call") {
|
|
3893
3964
|
const name2 = positional(positionals, 1, "tool name", "tools call <name> --input <json>");
|
|
3894
|
-
const { findTool, callTool, listAiTools } = await import("./chunks/tools-
|
|
3965
|
+
const { findTool, callTool, listAiTools } = await import("./chunks/tools-CCk24tdh.mjs");
|
|
3895
3966
|
const input = jsonObjectOpt(options, "input") ?? {};
|
|
3896
3967
|
const builtin = findTool(name2);
|
|
3897
3968
|
return withSession(io, options, { lock: builtin ? builtin.mutating : true }, async ({ ctx }) => {
|
|
@@ -3913,8 +3984,8 @@ const mcpCommand = {
|
|
|
3913
3984
|
const log = (msg) => process.stderr.write(`${msg}
|
|
3914
3985
|
`);
|
|
3915
3986
|
for (const w of session2.warnings) log(`[agentcrm mcp] note: ${w}`);
|
|
3916
|
-
const { listAiTools } = await import("./chunks/tools-
|
|
3917
|
-
const { createMcpServer, serveStdio } = await import("./chunks/server-
|
|
3987
|
+
const { listAiTools } = await import("./chunks/tools-CCk24tdh.mjs");
|
|
3988
|
+
const { createMcpServer, serveStdio } = await import("./chunks/server-Bch4TQon.mjs");
|
|
3918
3989
|
let lastRefresh = Date.now();
|
|
3919
3990
|
const server = createMcpServer({
|
|
3920
3991
|
readOnly,
|
|
@@ -4016,6 +4087,7 @@ const COMMANDS = [
|
|
|
4016
4087
|
deployAdminCommand,
|
|
4017
4088
|
recordsCommand,
|
|
4018
4089
|
objectsCommand,
|
|
4090
|
+
schemaCommand,
|
|
4019
4091
|
fieldsCommand,
|
|
4020
4092
|
activitiesCommand,
|
|
4021
4093
|
notesCommand,
|
|
@@ -8,16 +8,16 @@ import { toIsoDate, recordLabel, formatFieldValue, normalizeEmail } from "./fiel
|
|
|
8
8
|
import { n as newId } from "./ids-CvnmrMJX.mjs";
|
|
9
9
|
import { plugins } from "./pluginRegistry-DyHtlkcr.mjs";
|
|
10
10
|
import { r as resolveField, m as matchesFilter } from "./query-C5nJB_3C.mjs";
|
|
11
|
-
import { queryContext, setRecordOwner, updateRecord } from "./records-
|
|
11
|
+
import { queryContext, setRecordOwner, updateRecord } from "./records-CCTxxMWF.mjs";
|
|
12
12
|
import { getSettings } from "./settings-Di8nzNEL.mjs";
|
|
13
13
|
import { userOf, automationRunsOf, asDoc, requireRecord, requireObject, automationsOf, objectOf, recordsOf, thaw, recordOf, usersOf } from "./store-5gqRSKXg.mjs";
|
|
14
14
|
import { F as FILTER_OPS } from "../agentcrm.mjs";
|
|
15
15
|
import { lastActivityAt, addNote, createTask } from "./activities-Cj_SIOay.mjs";
|
|
16
16
|
import { OpsError, assertCan } from "./context-CxFfqS4D.mjs";
|
|
17
|
-
import { pipelineOfRecord } from "./pipelines-
|
|
17
|
+
import { pipelineOfRecord } from "./pipelines-DiJ2dLqQ.mjs";
|
|
18
18
|
import { getAutomationAction, listAutomationActions } from "./extensionActions-D2HtpQz4.mjs";
|
|
19
19
|
import { registerAutomationAction, subscribeAutomationActions } from "./extensionActions-D2HtpQz4.mjs";
|
|
20
|
-
import "./standardObjects-
|
|
20
|
+
import "./standardObjects-vrmqIVLH.mjs";
|
|
21
21
|
import "./relations-B9TynBmA.mjs";
|
|
22
22
|
import "./runtimeConfig-CCOFg1RM.mjs";
|
|
23
23
|
import "node:util";
|