@fleox-agent-crm/agentcrm 0.5.0 → 0.7.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 +18 -0
- package/dist/admin/admin-files.json +7 -7
- package/dist/admin/assets/{chartsImpl-zjsXDhuy.js → chartsImpl-Cx0bQmYg.js} +1 -1
- package/dist/admin/assets/{firebase-C3h9mF8O.js → firebase-DyAT9e1o.js} +2 -2
- package/dist/admin/assets/{gitJson-nrOYgX0x.js → gitJson-BeyPO6eJ.js} +1 -1
- package/dist/admin/assets/{index-0ejjkW0z.js → index-Bp5AxImK.js} +172 -172
- package/dist/admin/assets/{lucide-react.min-CI5dCsSm.js → lucide-react.min-BXJHmaO2.js} +1 -1
- package/dist/admin/assets/{sdk-mepKXtVl.js → sdk-hs3heWPk.js} +1 -1
- package/dist/admin/index.html +1 -1
- package/dist/agent/agentcrm.mjs +113 -73
- package/dist/agent/chunks/{activities-Cj_SIOay.mjs → activities-be260oPg.mjs} +1 -1
- package/dist/agent/chunks/{automations-BqY8EwfJ.mjs → automations-gCDYNS88.mjs} +4 -4
- package/dist/agent/chunks/{backup-CO0EzdF_.mjs → backup-DDqTRbuW.mjs} +3 -3
- package/dist/agent/chunks/{compact-qF5t42ko.mjs → compact-BqTG5cvC.mjs} +4 -4
- package/dist/agent/chunks/{dedupe-BepmsaHv.mjs → dedupe-isAmKHQV.mjs} +1 -1
- package/dist/agent/chunks/{exportCsv-C-fIHLm1.mjs → exportCsv-9ZMyqTdH.mjs} +2 -2
- package/dist/agent/chunks/{extCheck-BcbUc7eB.mjs → extCheck-Bu8C87OV.mjs} +3 -3
- package/dist/agent/chunks/{files-C4YONVqQ.mjs → files-SMLUpCPs.mjs} +10 -6
- package/dist/agent/chunks/{forms-DJDop3XY.mjs → forms-Bb0zztBM.mjs} +3 -3
- package/dist/agent/chunks/{importCsv-XjQJ9QIR.mjs → importCsv-BuSYG4ja.mjs} +2 -2
- package/dist/agent/chunks/{loader-Cv0UJf6b.mjs → loader-CGIek5YG.mjs} +13 -13
- package/dist/agent/chunks/{pipelines-DiJ2dLqQ.mjs → pipelines-G-c23x-s.mjs} +2 -2
- package/dist/agent/chunks/{records-CCTxxMWF.mjs → records-BJLSmv0O.mjs} +1 -1
- package/dist/agent/chunks/{registry-ClzNZv9Z.mjs → registry-Bg8kGteS.mjs} +12 -12
- package/dist/agent/chunks/{relations-B9TynBmA.mjs → relations-bmUKPT0G.mjs} +4 -4
- package/dist/agent/chunks/{reports-WlI_A5Nr.mjs → reports-ogUa41jr.mjs} +4 -4
- package/dist/agent/chunks/{runtime-BAF5vU5D.mjs → runtime-Bmwgx2hK.mjs} +23 -20
- package/dist/agent/chunks/{schema-DOnnH2zL.mjs → schema-Cwi7iFp2.mjs} +4 -4
- package/dist/agent/chunks/{schemaApply-DKHipylx.mjs → schemaApply-tEIr5lFK.mjs} +15 -6
- package/dist/agent/chunks/{server-Bch4TQon.mjs → server-3awvGTvL.mjs} +3 -3
- package/dist/agent/chunks/{stats-DfmDP3tE.mjs → stats-bInarNLK.mjs} +3 -3
- package/dist/agent/chunks/syncRecords-69hcCgOK.mjs +102 -0
- package/dist/agent/chunks/{tools-CCk24tdh.mjs → tools-BR3X1Uvm.mjs} +11 -11
- package/dist/agent/chunks/{views-BbhmQO3n.mjs → views-zRdsphZl.mjs} +2 -2
- 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.7.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-Bmwgx2hK.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-CGIek5YG.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-Bg8kGteS.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-gCDYNS88.mjs")
|
|
685
685
|
]);
|
|
686
686
|
const own = createPluginRegistry((hook, err) => process.stderr.write(`[agentcrm] ${hook} handler failed: ${String(err?.message ?? err)}
|
|
687
687
|
`));
|
|
@@ -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-Bb0zztBM.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;
|
|
@@ -959,7 +959,7 @@ function readLocalFile(path) {
|
|
|
959
959
|
return { name: basename(full), bytes: new Uint8Array(readFileSync(full)) };
|
|
960
960
|
}
|
|
961
961
|
async function uploadLocalFiles(ctx, paths, targets2 = []) {
|
|
962
|
-
const { uploadFile } = await import("./chunks/files-
|
|
962
|
+
const { uploadFile } = await import("./chunks/files-SMLUpCPs.mjs");
|
|
963
963
|
const { guessMime, imageDimensions } = await import("./chunks/files-CjsPJSR6.mjs");
|
|
964
964
|
const out = [];
|
|
965
965
|
for (const p of paths) {
|
|
@@ -1007,7 +1007,7 @@ const filesCommand = {
|
|
|
1007
1007
|
switch (action) {
|
|
1008
1008
|
case "list":
|
|
1009
1009
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
1010
|
-
const { listFiles } = await import("./chunks/files-
|
|
1010
|
+
const { listFiles } = await import("./chunks/files-SMLUpCPs.mjs");
|
|
1011
1011
|
const target = strOpt(options, "record") ?? strOpt(options, "activity") ?? null;
|
|
1012
1012
|
const items = listFiles(ctx, target, { includeRelated: boolOpt(options, "related"), kind: strOpt(options, "kind"), search: strOpt(options, "search") });
|
|
1013
1013
|
const limit = Math.min(1e3, numOpt(options, "limit") ?? 100);
|
|
@@ -1022,7 +1022,7 @@ ${table(r.files, ["id", "name", "mime", "size", "createdAt"])}`);
|
|
|
1022
1022
|
if (record && activity) usage("Give --record or --activity, not both.");
|
|
1023
1023
|
for (const p of args) readLocalFile(p);
|
|
1024
1024
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
1025
|
-
const { attachFile } = await import("./chunks/files-
|
|
1025
|
+
const { attachFile } = await import("./chunks/files-SMLUpCPs.mjs");
|
|
1026
1026
|
const files2 = await uploadLocalFiles(ctx, args, record ? [record] : []);
|
|
1027
1027
|
if (activity) for (const f of files2) await attachFile(ctx, f.id, { kind: "activity", id: activity });
|
|
1028
1028
|
const { requireFile } = await import("./chunks/store-5gqRSKXg.mjs");
|
|
@@ -1035,7 +1035,7 @@ ${table(r.uploaded, ["id", "name", "size"])}`);
|
|
|
1035
1035
|
const out = strOpt(options, "out");
|
|
1036
1036
|
if (!out) usage("files get needs --out <path>.");
|
|
1037
1037
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
1038
|
-
const { getFile, getFileBytes } = await import("./chunks/files-
|
|
1038
|
+
const { getFile, getFileBytes } = await import("./chunks/files-SMLUpCPs.mjs");
|
|
1039
1039
|
const meta = getFile(ctx, id);
|
|
1040
1040
|
const bytes = await getFileBytes(ctx, id, { thumb: boolOpt(options, "thumb") });
|
|
1041
1041
|
writeOutFile(out, bytes);
|
|
@@ -1045,7 +1045,7 @@ ${table(r.uploaded, ["id", "name", "size"])}`);
|
|
|
1045
1045
|
case "delete": {
|
|
1046
1046
|
const id = positional(args, 0, "file id", U$1.delete);
|
|
1047
1047
|
return withSession(io, options, { lock: options.yes === true }, async ({ ctx }) => {
|
|
1048
|
-
const { getFile, deleteFile } = await import("./chunks/files-
|
|
1048
|
+
const { getFile, deleteFile } = await import("./chunks/files-SMLUpCPs.mjs");
|
|
1049
1049
|
const meta = fileOut(getFile(ctx, id));
|
|
1050
1050
|
if (options.yes !== true) return { needsConfirmation: true, plan: { delete: meta } };
|
|
1051
1051
|
await deleteFile(ctx, id);
|
|
@@ -1053,7 +1053,7 @@ ${table(r.uploaded, ["id", "name", "size"])}`);
|
|
|
1053
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\`).`);
|
|
1054
1054
|
}
|
|
1055
1055
|
case "usage":
|
|
1056
|
-
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/files-
|
|
1056
|
+
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/files-SMLUpCPs.mjs")).fileUsage(ctx));
|
|
1057
1057
|
default:
|
|
1058
1058
|
usage(`Unknown files action "${action ?? ""}".`, "Use list, upload, get, delete or usage.");
|
|
1059
1059
|
}
|
|
@@ -1066,7 +1066,7 @@ async function recordImageAction(io, options, args) {
|
|
|
1066
1066
|
if (!remove && !path) usage("records image needs an image path (or --remove).");
|
|
1067
1067
|
const local = remove ? null : readLocalFile(path);
|
|
1068
1068
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
1069
|
-
const { setRecordImage, clearRecordImage } = await import("./chunks/files-
|
|
1069
|
+
const { setRecordImage, clearRecordImage } = await import("./chunks/files-SMLUpCPs.mjs");
|
|
1070
1070
|
const field = strOpt(options, "field");
|
|
1071
1071
|
if (!local) {
|
|
1072
1072
|
const r = await clearRecordImage(ctx, recordId, field);
|
|
@@ -1160,7 +1160,7 @@ const activitiesCommand = {
|
|
|
1160
1160
|
const recs = multiOpt(options, "record");
|
|
1161
1161
|
if (!recs.length && type2 !== "task") usage("activities add needs --record <id> (repeatable).");
|
|
1162
1162
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
1163
|
-
const { addActivity } = await import("./chunks/activities-
|
|
1163
|
+
const { addActivity } = await import("./chunks/activities-be260oPg.mjs");
|
|
1164
1164
|
return activityOut(
|
|
1165
1165
|
await addActivity(ctx, {
|
|
1166
1166
|
type: type2,
|
|
@@ -1177,7 +1177,7 @@ const activitiesCommand = {
|
|
|
1177
1177
|
}
|
|
1178
1178
|
case "list":
|
|
1179
1179
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
1180
|
-
const { listActivities } = await import("./chunks/activities-
|
|
1180
|
+
const { listActivities } = await import("./chunks/activities-be260oPg.mjs");
|
|
1181
1181
|
const types = listOpt(options, "type");
|
|
1182
1182
|
const page = listActivities(ctx, { target: multiOpt(options, "record")[0], types, includeRelated: boolOpt(options, "related"), limit: Math.min(500, numOpt(options, "limit") ?? 50) });
|
|
1183
1183
|
return { total: page.total, activities: page.items.map(activityOut) };
|
|
@@ -1185,7 +1185,7 @@ const activitiesCommand = {
|
|
|
1185
1185
|
${table(r.activities, ["id", "type", "title", "createdAt"])}`);
|
|
1186
1186
|
case "done": {
|
|
1187
1187
|
if (!id) usage("activities done needs an id.");
|
|
1188
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => activityOut(await (await import("./chunks/activities-
|
|
1188
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => activityOut(await (await import("./chunks/activities-be260oPg.mjs")).completeTask(ctx, id, !boolOpt(options, "undo"))));
|
|
1189
1189
|
}
|
|
1190
1190
|
default:
|
|
1191
1191
|
usage(`Unknown activities action "${action ?? ""}".`, "Use add, list or done.");
|
|
@@ -1206,7 +1206,7 @@ const notesCommand = {
|
|
|
1206
1206
|
if (!text?.trim()) usage("notes add needs --body.");
|
|
1207
1207
|
const files2 = attachPaths(options);
|
|
1208
1208
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
1209
|
-
const ops = await import("./chunks/activities-
|
|
1209
|
+
const ops = await import("./chunks/activities-be260oPg.mjs");
|
|
1210
1210
|
const { recordOf } = await import("./chunks/store-5gqRSKXg.mjs");
|
|
1211
1211
|
const r = recordOf(ctx.store, id);
|
|
1212
1212
|
if (!files2.length || !r) return activityOut(await ops.addNote(ctx, id, text, strOpt(options, "title")));
|
|
@@ -1249,7 +1249,7 @@ const tasksCommand = {
|
|
|
1249
1249
|
switch (action) {
|
|
1250
1250
|
case "list":
|
|
1251
1251
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
1252
|
-
const { listTasks } = await import("./chunks/activities-
|
|
1252
|
+
const { listTasks } = await import("./chunks/activities-be260oPg.mjs");
|
|
1253
1253
|
const status = strOpt(options, "status") ?? "open";
|
|
1254
1254
|
if (!["open", "done", "all"].includes(status)) usage("--status must be open, done or all.");
|
|
1255
1255
|
const page = listTasks(ctx, { assigneeId: await assignee(ctx), target: multiOpt(options, "record")[0], status, overdue: boolOpt(options, "overdue"), dueWithinDays: numOpt(options, "due-within"), limit: Math.min(500, numOpt(options, "limit") ?? 50) });
|
|
@@ -1260,17 +1260,17 @@ ${table(r.tasks, ["id", "title", "dueAt", "assigneeId"])}`);
|
|
|
1260
1260
|
const title = requireStr(options, "title");
|
|
1261
1261
|
const files2 = attachPaths(options);
|
|
1262
1262
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
1263
|
-
const { addActivity } = await import("./chunks/activities-
|
|
1263
|
+
const { addActivity } = await import("./chunks/activities-be260oPg.mjs");
|
|
1264
1264
|
return activityOut(await addActivity(ctx, { type: "task", title, body: body(options), dueAt: strOpt(options, "due"), assigneeId: await assignee(ctx) ?? ctx.user?.id, targets: targets(multiOpt(options, "record")), attachments: await attachments(ctx, files2) }));
|
|
1265
1265
|
});
|
|
1266
1266
|
}
|
|
1267
1267
|
case "done":
|
|
1268
1268
|
if (!id) usage("tasks done needs a task id.");
|
|
1269
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => activityOut(await (await import("./chunks/activities-
|
|
1269
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => activityOut(await (await import("./chunks/activities-be260oPg.mjs")).completeTask(ctx, id, !boolOpt(options, "undo"))));
|
|
1270
1270
|
case "reassign":
|
|
1271
1271
|
if (!id) usage("tasks reassign needs a task id.");
|
|
1272
1272
|
requireStr(options, "assignee");
|
|
1273
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => activityOut(await (await import("./chunks/activities-
|
|
1273
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => activityOut(await (await import("./chunks/activities-be260oPg.mjs")).updateActivity(ctx, id, { assigneeId: await assignee(ctx) ?? null })));
|
|
1274
1274
|
default:
|
|
1275
1275
|
usage(`Unknown tasks action "${action ?? ""}".`, "Use list, add, done or reassign.");
|
|
1276
1276
|
}
|
|
@@ -1301,11 +1301,12 @@ const U = {
|
|
|
1301
1301
|
search: "records search <query> [--object <id>]… [--limit n]",
|
|
1302
1302
|
duplicates: "records duplicates --object <id> [--by email,domain,name,phone]",
|
|
1303
1303
|
merge: "records merge <primaryId> <duplicateId>… [--yes]",
|
|
1304
|
-
image: "records image <recordId> <path> | --remove [--field <imageFieldId>]"
|
|
1304
|
+
image: "records image <recordId> <path> | --remove [--field <imageFieldId>]",
|
|
1305
|
+
sync: "records sync --object <id> --key <fieldId> --rows <json|@file|-> [--archive-field <fieldId>] [--ref-key <fieldId>] [--yes]"
|
|
1305
1306
|
};
|
|
1306
1307
|
const recordsCommand = {
|
|
1307
1308
|
name: "records",
|
|
1308
|
-
usage: "records <list|get|create|update|delete|restore|search|duplicates|merge|image> …",
|
|
1309
|
+
usage: "records <list|get|create|update|delete|restore|search|duplicates|merge|image|sync> …",
|
|
1309
1310
|
summary: "Records of any object (companies, people, deals, custom objects): list with filters / sorts / pagination, get with relations and timeline counts, create, update (only the given fields), soft delete / restore, full-text search, find and merge duplicates.",
|
|
1310
1311
|
subcommands: [
|
|
1311
1312
|
{ name: "list", usage: U.list, summary: `List records. Filter ops: ${FILTER_OPS.join(", ")}. Values: in/notIn comma-separated; dates YYYY-MM-DD, today, +30d.` },
|
|
@@ -1317,7 +1318,13 @@ const recordsCommand = {
|
|
|
1317
1318
|
{ name: "search", usage: U.search, summary: "Full-text search (names, emails, domains, phones)." },
|
|
1318
1319
|
{ name: "duplicates", usage: U.duplicates, summary: "Groups of likely duplicates (same email / domain / name / phone)." },
|
|
1319
1320
|
{ name: "merge", usage: U.merge, summary: "Merge duplicates into the primary (empty fields filled, relations and activities moved). Plan unless --yes.", writes: true, destructive: true },
|
|
1320
|
-
{ name: "image", usage: U.image, summary: "Set the record's avatar / logo from a local image (the object's image field), or --remove it.", writes: true }
|
|
1321
|
+
{ name: "image", usage: U.image, summary: "Set the record's avatar / logo from a local image (the object's image field), or --remove it.", writes: true },
|
|
1322
|
+
{
|
|
1323
|
+
name: "sync",
|
|
1324
|
+
usage: U.sync,
|
|
1325
|
+
summary: 'Mirror an external source into one object: rows [{ key, fields }] matched on the --key field, created / updated only where a value differs; relation values reference other mirrored records by their key ({ "$key": "12" } or { "$key": ["12","13"] }); records whose key is missing get --archive-field = true (never deleted). No automation fires. Plan unless --yes.',
|
|
1326
|
+
writes: true
|
|
1327
|
+
}
|
|
1321
1328
|
],
|
|
1322
1329
|
options: [
|
|
1323
1330
|
SITE_OPTION,
|
|
@@ -1338,7 +1345,11 @@ const recordsCommand = {
|
|
|
1338
1345
|
{ name: "hard", type: "boolean", description: "delete: remove immediately (no restore)." },
|
|
1339
1346
|
{ name: "by", type: "string", description: "duplicates: email,domain,name,phone." },
|
|
1340
1347
|
{ name: "remove", type: "boolean", description: "image: remove the record's image." },
|
|
1341
|
-
{ name: "field", type: "string", description: "image: image field id (default: the object's image field)." }
|
|
1348
|
+
{ name: "field", type: "string", description: "image: image field id (default: the object's image field)." },
|
|
1349
|
+
{ name: "key", type: "string", description: "sync: field holding the source id (match key)." },
|
|
1350
|
+
{ name: "rows", type: "string", description: "sync: rows as a JSON array [{ key, fields }], @file.json or - (stdin)." },
|
|
1351
|
+
{ name: "archive-field", type: "string", description: "sync: boolean field set to true on records whose key is missing from the rows." },
|
|
1352
|
+
{ name: "ref-key", type: "string", description: 'sync: key field of related objects for { "$key": … } (default: --key).' }
|
|
1342
1353
|
],
|
|
1343
1354
|
async run({ io, options, positionals }) {
|
|
1344
1355
|
const [action, ...args] = positionals;
|
|
@@ -1354,7 +1365,7 @@ const recordsCommand = {
|
|
|
1354
1365
|
const filters = parseFilters(multiOpt(options, "filter"), FILTER_OPS);
|
|
1355
1366
|
const sorts = parseSorts(multiOpt(options, "sort"));
|
|
1356
1367
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
1357
|
-
const { listRecords } = await import("./chunks/records-
|
|
1368
|
+
const { listRecords } = await import("./chunks/records-BJLSmv0O.mjs");
|
|
1358
1369
|
const page = listRecords(ctx, objectId, {
|
|
1359
1370
|
filters,
|
|
1360
1371
|
sorts,
|
|
@@ -1372,7 +1383,7 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1372
1383
|
case "get": {
|
|
1373
1384
|
const id = positional(args, 0, "record id", U.get);
|
|
1374
1385
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
1375
|
-
const { getRecordDetails } = await import("./chunks/records-
|
|
1386
|
+
const { getRecordDetails } = await import("./chunks/records-BJLSmv0O.mjs");
|
|
1376
1387
|
const d = getRecordDetails(ctx, id);
|
|
1377
1388
|
return { ...await recordOut(ctx, d.record), relations: d.relations, related: d.inverse.filter((i) => i.records.length), activityCount: d.activityCount };
|
|
1378
1389
|
});
|
|
@@ -1383,7 +1394,7 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1383
1394
|
if (!Object.keys(fields).length) usage("records create needs --fields or --set.", `Usage: agentcrm ${U.create}`);
|
|
1384
1395
|
const owner = strOpt(options, "owner");
|
|
1385
1396
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
1386
|
-
const { createRecord } = await import("./chunks/records-
|
|
1397
|
+
const { createRecord } = await import("./chunks/records-BJLSmv0O.mjs");
|
|
1387
1398
|
return recordOut(ctx, await createRecord(ctx, objectId, fields, owner ? { ownerId: owner } : {}));
|
|
1388
1399
|
}, (r) => `Created ${r.object} ${r.id} (${String(r.label)})`);
|
|
1389
1400
|
}
|
|
@@ -1393,7 +1404,7 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1393
1404
|
const owner = strOpt(options, "owner");
|
|
1394
1405
|
if (!Object.keys(fields).length && owner === void 0) usage("records update needs --fields, --set or --owner.");
|
|
1395
1406
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
1396
|
-
const { updateRecord } = await import("./chunks/records-
|
|
1407
|
+
const { updateRecord } = await import("./chunks/records-BJLSmv0O.mjs");
|
|
1397
1408
|
return recordOut(ctx, await updateRecord(ctx, id, fields, owner !== void 0 ? { ownerId: owner || null } : {}));
|
|
1398
1409
|
}, (r) => `Updated ${r.id} (${String(r.label)})`);
|
|
1399
1410
|
}
|
|
@@ -1401,7 +1412,7 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1401
1412
|
if (!args.length) usage("records delete needs at least one id.", `Usage: agentcrm ${U.delete}`);
|
|
1402
1413
|
const hard = boolOpt(options, "hard");
|
|
1403
1414
|
return withSession(io, options, { lock: options.yes === true }, async ({ ctx }) => {
|
|
1404
|
-
const { getRecord, deleteRecord, bulkDelete } = await import("./chunks/records-
|
|
1415
|
+
const { getRecord, deleteRecord, bulkDelete } = await import("./chunks/records-BJLSmv0O.mjs");
|
|
1405
1416
|
const { recordLabel } = await import("./chunks/fields-B0bitgmr.mjs");
|
|
1406
1417
|
const { objectOf } = await import("./chunks/store-5gqRSKXg.mjs");
|
|
1407
1418
|
const targets2 = args.map((id) => getRecord(ctx, id, { includeDeleted: true }));
|
|
@@ -1414,7 +1425,7 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1414
1425
|
case "restore": {
|
|
1415
1426
|
const id = positional(args, 0, "record id", U.restore);
|
|
1416
1427
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
1417
|
-
const { restoreRecord } = await import("./chunks/records-
|
|
1428
|
+
const { restoreRecord } = await import("./chunks/records-BJLSmv0O.mjs");
|
|
1418
1429
|
return recordOut(ctx, await restoreRecord(ctx, id));
|
|
1419
1430
|
});
|
|
1420
1431
|
}
|
|
@@ -1422,14 +1433,14 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1422
1433
|
const query = args.join(" ").trim();
|
|
1423
1434
|
if (!query) usage("records search needs a query.", `Usage: agentcrm ${U.search}`);
|
|
1424
1435
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
1425
|
-
const { searchRecords } = await import("./chunks/records-
|
|
1436
|
+
const { searchRecords } = await import("./chunks/records-BJLSmv0O.mjs");
|
|
1426
1437
|
return searchRecords(ctx, query, { objects: listOpt(options, "object"), limit: Math.min(100, numOpt(options, "limit") ?? 20) });
|
|
1427
1438
|
});
|
|
1428
1439
|
}
|
|
1429
1440
|
case "duplicates": {
|
|
1430
1441
|
const objectId = object();
|
|
1431
1442
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
1432
|
-
const { findDuplicates } = await import("./chunks/dedupe-
|
|
1443
|
+
const { findDuplicates } = await import("./chunks/dedupe-isAmKHQV.mjs");
|
|
1433
1444
|
const by = listOpt(options, "by");
|
|
1434
1445
|
const groups = findDuplicates(ctx, objectId, by ? { by } : {});
|
|
1435
1446
|
return { object: objectId, groups: groups.length, duplicates: groups };
|
|
@@ -1439,19 +1450,48 @@ ${table(r.records, ["id", "label", "updatedAt"])}`);
|
|
|
1439
1450
|
const [primary, ...dups] = args;
|
|
1440
1451
|
if (!primary || !dups.length) usage("records merge needs <primaryId> <duplicateId>….", `Usage: agentcrm ${U.merge}`);
|
|
1441
1452
|
return withSession(io, options, { lock: options.yes === true }, async ({ ctx }) => {
|
|
1442
|
-
const { getRecord } = await import("./chunks/records-
|
|
1453
|
+
const { getRecord } = await import("./chunks/records-BJLSmv0O.mjs");
|
|
1443
1454
|
const all = [primary, ...dups].map((id) => getRecord(ctx, id));
|
|
1444
1455
|
const plan = { primary: await recordOut(ctx, all[0]), duplicates: await Promise.all(all.slice(1).map((r) => recordOut(ctx, r))) };
|
|
1445
1456
|
if (options.yes !== true) return { needsConfirmation: true, plan };
|
|
1446
|
-
const { mergeRecords } = await import("./chunks/dedupe-
|
|
1457
|
+
const { mergeRecords } = await import("./chunks/dedupe-isAmKHQV.mjs");
|
|
1447
1458
|
const res = await mergeRecords(ctx, primary, dups);
|
|
1448
1459
|
return { record: await recordOut(ctx, res.record), merged: res.merged, movedActivities: res.movedActivities };
|
|
1449
1460
|
}, (r) => "plan" in r && r.plan ? `Would merge ${r.plan.duplicates.length} duplicate(s) into ${r.plan.primary.id}. Re-run with --yes once the user agrees.` : "merged" in r ? `Merged ${r.merged.length} into ${r.record.id}` : "");
|
|
1450
1461
|
}
|
|
1451
1462
|
case "image":
|
|
1452
1463
|
return (await Promise.resolve().then(() => files)).recordImageAction(io, options, args);
|
|
1464
|
+
case "sync": {
|
|
1465
|
+
const objectId = Array.isArray(options.object) ? options.object[0] : options.object;
|
|
1466
|
+
const key = strOpt(options, "key");
|
|
1467
|
+
const rowsRaw = strOpt(options, "rows");
|
|
1468
|
+
if (!objectId || !key || !rowsRaw) usage("records sync needs --object, --key and --rows.", `Usage: agentcrm ${U.sync}`);
|
|
1469
|
+
const { readTextValue: readTextValue2 } = await Promise.resolve().then(() => util);
|
|
1470
|
+
let rows;
|
|
1471
|
+
try {
|
|
1472
|
+
rows = JSON.parse(readTextValue2(rowsRaw, "rows"));
|
|
1473
|
+
} catch (err) {
|
|
1474
|
+
usage(`--rows is not valid JSON: ${err.message}`);
|
|
1475
|
+
}
|
|
1476
|
+
if (!Array.isArray(rows)) usage("--rows must be a JSON array of { key, fields }.");
|
|
1477
|
+
const spec = { object: objectId, key, rows, archiveField: strOpt(options, "archive-field"), refKey: strOpt(options, "ref-key") };
|
|
1478
|
+
const apply = options.yes === true;
|
|
1479
|
+
return withSession(io, options, { lock: apply }, async ({ ctx }) => {
|
|
1480
|
+
const { syncRecords } = await import("./chunks/syncRecords-69hcCgOK.mjs");
|
|
1481
|
+
if (apply) return syncRecords(ctx, spec);
|
|
1482
|
+
const { dryRun: dryRun2 } = await Promise.resolve().then(() => dryRun$1);
|
|
1483
|
+
const { result } = await dryRun2(ctx, (copy) => syncRecords(copy, spec));
|
|
1484
|
+
const pending = result.created + result.updated + result.archived;
|
|
1485
|
+
return pending ? { needsConfirmation: true, plan: result } : result;
|
|
1486
|
+
}, (r) => {
|
|
1487
|
+
const s = "needsConfirmation" in r ? r.plan : r;
|
|
1488
|
+
const line = `${s.object}: ${s.rows} rows → ${s.created} new, ${s.updated} updated, ${s.unchanged} unchanged, ${s.archived} archived${s.unresolved ? `, ${s.unresolved} unresolved references` : ""}${s.errors.length ? `, ${s.errors.length} errors (first: ${s.errors[0].key}: ${s.errors[0].message})` : ""}`;
|
|
1489
|
+
return "needsConfirmation" in r ? `${line}
|
|
1490
|
+
Nothing changed — re-run with --yes once the user agrees.` : line;
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1453
1493
|
default:
|
|
1454
|
-
usage(`Unknown records action "${action ?? ""}".`, "Use list, get, create, update, delete, restore, search, duplicates, merge or
|
|
1494
|
+
usage(`Unknown records action "${action ?? ""}".`, "Use list, get, create, update, delete, restore, search, duplicates, merge, image or sync.");
|
|
1455
1495
|
}
|
|
1456
1496
|
}
|
|
1457
1497
|
};
|
|
@@ -1471,13 +1511,13 @@ const pipelinesCommand = {
|
|
|
1471
1511
|
io,
|
|
1472
1512
|
options,
|
|
1473
1513
|
{},
|
|
1474
|
-
async ({ ctx }) => (await import("./chunks/pipelines-
|
|
1514
|
+
async ({ ctx }) => (await import("./chunks/pipelines-G-c23x-s.mjs")).listPipelines(ctx, strOpt(options, "object")),
|
|
1475
1515
|
(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")
|
|
1476
1516
|
);
|
|
1477
1517
|
}
|
|
1478
1518
|
if (action === "move") {
|
|
1479
1519
|
if (!id || !stage.length) usage("pipelines move needs <recordId> <stage>.");
|
|
1480
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => recordOut(ctx, await (await import("./chunks/pipelines-
|
|
1520
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => recordOut(ctx, await (await import("./chunks/pipelines-G-c23x-s.mjs")).moveStage(ctx, id, stage.join(" "), { lostReason: strOpt(options, "lost-reason") })));
|
|
1481
1521
|
}
|
|
1482
1522
|
usage(`Unknown pipelines action "${action}".`, "Use list or move.");
|
|
1483
1523
|
}
|
|
@@ -1509,7 +1549,7 @@ const viewsCommand = {
|
|
|
1509
1549
|
const [action = "list", id] = positionals;
|
|
1510
1550
|
switch (action) {
|
|
1511
1551
|
case "list":
|
|
1512
|
-
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/views-
|
|
1552
|
+
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/views-zRdsphZl.mjs")).listViews(ctx, strOpt(options, "object")), (vs) => table(vs, ["id", "object", "name", "type", "shared"]));
|
|
1513
1553
|
case "create": {
|
|
1514
1554
|
const type2 = strOpt(options, "type") ?? "table";
|
|
1515
1555
|
if (type2 !== "table" && type2 !== "kanban") usage("--type must be table or kanban.");
|
|
@@ -1524,12 +1564,12 @@ const viewsCommand = {
|
|
|
1524
1564
|
...strOpt(options, "pipeline") ? { pipelineId: strOpt(options, "pipeline") } : {},
|
|
1525
1565
|
shared: boolOpt(options, "shared")
|
|
1526
1566
|
};
|
|
1527
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/views-
|
|
1567
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/views-zRdsphZl.mjs")).createView(ctx, input));
|
|
1528
1568
|
}
|
|
1529
1569
|
case "delete":
|
|
1530
1570
|
if (!id) usage("views delete needs a view id.");
|
|
1531
1571
|
return withSession(io, options, { lock: options.yes === true }, async ({ ctx }) => {
|
|
1532
|
-
const { getView, deleteView } = await import("./chunks/views-
|
|
1572
|
+
const { getView, deleteView } = await import("./chunks/views-zRdsphZl.mjs");
|
|
1533
1573
|
const v = getView(ctx, id);
|
|
1534
1574
|
if (options.yes !== true) return { needsConfirmation: true, plan: { delete: { id: v.id, name: v.name, object: v.object, shared: v.shared } } };
|
|
1535
1575
|
return deleteView(ctx, id);
|
|
@@ -2124,7 +2164,7 @@ async function check({ io, options, positionals }) {
|
|
|
2124
2164
|
const kind = strOpt(options, "kind");
|
|
2125
2165
|
if (kind && kind !== "module" && kind !== "theme") usage("--kind is module or theme.");
|
|
2126
2166
|
const { readRawPackage } = await import("./chunks/extPackage-DuZ6GZhp.mjs");
|
|
2127
|
-
const { checkExtension } = await import("./chunks/extCheck-
|
|
2167
|
+
const { checkExtension } = await import("./chunks/extCheck-Bu8C87OV.mjs");
|
|
2128
2168
|
const raw = await readRawPackage(target);
|
|
2129
2169
|
const report = await checkExtension(raw, { kind, callTools: !boolOpt(options, "no-call") });
|
|
2130
2170
|
printResult(io, report, () => {
|
|
@@ -2171,7 +2211,7 @@ async function install({ io, options, positionals }) {
|
|
|
2171
2211
|
const apply = options.yes === true;
|
|
2172
2212
|
const disabled = boolOpt(options, "disabled");
|
|
2173
2213
|
if (!boolOpt(options, "force")) {
|
|
2174
|
-
const { checkExtension } = await import("./chunks/extCheck-
|
|
2214
|
+
const { checkExtension } = await import("./chunks/extCheck-Bu8C87OV.mjs");
|
|
2175
2215
|
const report = await checkExtension(raw, { callTools: false });
|
|
2176
2216
|
if (!report.valid) {
|
|
2177
2217
|
throw new CliError(
|
|
@@ -2207,7 +2247,7 @@ async function install({ io, options, positionals }) {
|
|
|
2207
2247
|
}
|
|
2208
2248
|
const result = await ext.installExtension(s.ctx, pkg2, disabled ? { enabled: false } : {});
|
|
2209
2249
|
const report = await s.extensions.sync();
|
|
2210
|
-
const { getLoadedExtension } = await import("./chunks/registry-
|
|
2250
|
+
const { getLoadedExtension } = await import("./chunks/registry-Bg8kGteS.mjs");
|
|
2211
2251
|
const loaded = getLoadedExtension(m.id);
|
|
2212
2252
|
const failure = report?.failed.find((f) => f.id === m.id || f.id === "*");
|
|
2213
2253
|
if (failure && !loaded) return { ...result, author: m.author ?? null, load: { status: "error", error: failure.error } };
|
|
@@ -2269,7 +2309,7 @@ const extCommand = {
|
|
|
2269
2309
|
if (kind && kind !== "module" && kind !== "theme") usage("--kind is module or theme.");
|
|
2270
2310
|
return withSession(io, options, {}, async (s) => {
|
|
2271
2311
|
const { listExtensions } = await import("./chunks/extensions-Bp72uZ9a.mjs");
|
|
2272
|
-
const { getLoadedExtension } = await import("./chunks/registry-
|
|
2312
|
+
const { getLoadedExtension } = await import("./chunks/registry-Bg8kGteS.mjs");
|
|
2273
2313
|
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 } : {} }));
|
|
2274
2314
|
}, (rows) => table(rows.map((r) => ({ ...r, enabled: r.enabled ? "yes" : "no" })), ["id", "kind", "name", "version", "enabled", "load", "author"]));
|
|
2275
2315
|
}
|
|
@@ -2384,7 +2424,7 @@ const importCommand = {
|
|
|
2384
2424
|
options,
|
|
2385
2425
|
{},
|
|
2386
2426
|
async ({ ctx }) => {
|
|
2387
|
-
const plan = await (await import("./chunks/backup-
|
|
2427
|
+
const plan = await (await import("./chunks/backup-DDqTRbuW.mjs")).planBackupZip(ctx, bytes, { mode: options.replace === true ? "replace" : "merge" });
|
|
2388
2428
|
return { needsConfirmation: true, plan: { restore: resolve(path), bytes: bytes.length, ...plan } };
|
|
2389
2429
|
},
|
|
2390
2430
|
(r) => [
|
|
@@ -2394,7 +2434,7 @@ const importCommand = {
|
|
|
2394
2434
|
].join("\n")
|
|
2395
2435
|
);
|
|
2396
2436
|
}
|
|
2397
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/backup-
|
|
2437
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/backup-DDqTRbuW.mjs")).importBackupZip(ctx, bytes, { mode: options.replace === true ? "replace" : "merge" }), (r) => `Restored ${r.written} document(s) and ${r.files} file(s)`);
|
|
2398
2438
|
}
|
|
2399
2439
|
if (kind !== "csv") usage('Only "import csv" and "import zip" are supported.', "Usage: agentcrm import csv <file> --object <id>");
|
|
2400
2440
|
const source = positional(positionals, 1, "CSV file (or -)", "import csv <file|-> --object <id>");
|
|
@@ -2405,7 +2445,7 @@ const importCommand = {
|
|
|
2405
2445
|
const apply = options.yes === true && options["dry-run"] !== true;
|
|
2406
2446
|
const shown = numOpt(options, "rows") ?? 100;
|
|
2407
2447
|
return withSession(io, options, { lock: apply }, async ({ ctx }) => {
|
|
2408
|
-
const { importCsv } = await import("./chunks/importCsv-
|
|
2448
|
+
const { importCsv } = await import("./chunks/importCsv-BuSYG4ja.mjs");
|
|
2409
2449
|
const report = await importCsv(ctx, {
|
|
2410
2450
|
object: objectId,
|
|
2411
2451
|
csv,
|
|
@@ -2454,7 +2494,7 @@ const exportCommand = {
|
|
|
2454
2494
|
const file2 = strOpt(options, "out");
|
|
2455
2495
|
if (!file2) usage("export zip needs --out <file.zip>.");
|
|
2456
2496
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
2457
|
-
const { exportBackupZip } = await import("./chunks/backup-
|
|
2497
|
+
const { exportBackupZip } = await import("./chunks/backup-DDqTRbuW.mjs");
|
|
2458
2498
|
const { zip, report } = await exportBackupZip(ctx, { includeFiles: options["no-files"] !== true });
|
|
2459
2499
|
writeOutFile(file2, zip);
|
|
2460
2500
|
return { file: resolve(file2), zipBytes: zip.length, files: report.files, missing: report.missing, fileBytes: report.bytes };
|
|
@@ -2473,7 +2513,7 @@ const exportCommand = {
|
|
|
2473
2513
|
const filters = parseFilters(multiOpt(options, "filter"), FILTER_OPS);
|
|
2474
2514
|
const sorts = parseSorts(multiOpt(options, "sort"));
|
|
2475
2515
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
2476
|
-
const { exportCsv } = await import("./chunks/exportCsv-
|
|
2516
|
+
const { exportCsv } = await import("./chunks/exportCsv-9ZMyqTdH.mjs");
|
|
2477
2517
|
const csv = exportCsv(ctx, objectId, {
|
|
2478
2518
|
viewId: strOpt(options, "view"),
|
|
2479
2519
|
filters,
|
|
@@ -2489,7 +2529,7 @@ const exportCommand = {
|
|
|
2489
2529
|
}
|
|
2490
2530
|
if (kind === "json") {
|
|
2491
2531
|
return withSession(io, options, {}, async ({ ctx }) => {
|
|
2492
|
-
const { exportJson } = await import("./chunks/exportCsv-
|
|
2532
|
+
const { exportJson } = await import("./chunks/exportCsv-9ZMyqTdH.mjs");
|
|
2493
2533
|
const data = exportJson(ctx, { collections: listOpt(options, "collections") });
|
|
2494
2534
|
const text = JSON.stringify(data, null, 2);
|
|
2495
2535
|
if (out) return deliver(text, {});
|
|
@@ -2533,7 +2573,7 @@ const reportCommand = {
|
|
|
2533
2573
|
...strOpt(options, "pipeline") ? { pipelineId: strOpt(options, "pipeline") } : {},
|
|
2534
2574
|
...strOpt(options, "owner") ? { ownerId: strOpt(options, "owner") } : {}
|
|
2535
2575
|
};
|
|
2536
|
-
return withSession(io, options, {}, async ({ ctx }) => ({ report: name2, data: (await import("./chunks/reports-
|
|
2576
|
+
return withSession(io, options, {}, async ({ ctx }) => ({ report: name2, data: (await import("./chunks/reports-ogUa41jr.mjs")).runReport(ctx, internal, params) }));
|
|
2537
2577
|
}
|
|
2538
2578
|
};
|
|
2539
2579
|
const statsCommand = {
|
|
@@ -2543,7 +2583,7 @@ const statsCommand = {
|
|
|
2543
2583
|
options: [SITE_OPTION, AS_OPTION],
|
|
2544
2584
|
async run({ io, options }) {
|
|
2545
2585
|
return withSession(io, options, {}, async ({ ctx, store }) => {
|
|
2546
|
-
const stats = (await import("./chunks/stats-
|
|
2586
|
+
const stats = (await import("./chunks/stats-bInarNLK.mjs")).getStats(ctx);
|
|
2547
2587
|
const journal = store.stats;
|
|
2548
2588
|
return { ...stats, ...journal ? { journal: await journal.call(store) } : {} };
|
|
2549
2589
|
}, (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"));
|
|
@@ -2557,7 +2597,7 @@ const compactCommand = {
|
|
|
2557
2597
|
async run({ io, options }) {
|
|
2558
2598
|
const apply = options.yes === true;
|
|
2559
2599
|
return withSession(io, options, { lock: apply }, async ({ ctx }) => {
|
|
2560
|
-
const { compactData } = await import("./chunks/compact-
|
|
2600
|
+
const { compactData } = await import("./chunks/compact-BqTG5cvC.mjs");
|
|
2561
2601
|
const report = await compactData(ctx, { olderThanDays: numOpt(options, "older-than"), keepRuns: numOpt(options, "keep-runs"), dryRun: !apply });
|
|
2562
2602
|
return apply ? report : { needsConfirmation: true, plan: report };
|
|
2563
2603
|
}, (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}`);
|
|
@@ -2578,19 +2618,19 @@ const automationsCommand = {
|
|
|
2578
2618
|
const [action = "list", id] = positionals;
|
|
2579
2619
|
switch (action) {
|
|
2580
2620
|
case "list":
|
|
2581
|
-
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/automations-
|
|
2621
|
+
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/automations-gCDYNS88.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"]));
|
|
2582
2622
|
case "enable":
|
|
2583
2623
|
case "disable": {
|
|
2584
2624
|
if (!id) usage(`automations ${action} needs an id.`);
|
|
2585
2625
|
return withSession(io, options, { lock: true }, async ({ ctx }) => {
|
|
2586
|
-
const mod = await import("./chunks/automations-
|
|
2626
|
+
const mod = await import("./chunks/automations-gCDYNS88.mjs");
|
|
2587
2627
|
return mod.setAutomationEnabled(ctx, id, action === "enable");
|
|
2588
2628
|
});
|
|
2589
2629
|
}
|
|
2590
2630
|
case "run": {
|
|
2591
2631
|
const apply = options.yes === true;
|
|
2592
2632
|
return withSession(io, options, { lock: apply }, async ({ ctx }) => {
|
|
2593
|
-
const { runScheduled } = await import("./chunks/automations-
|
|
2633
|
+
const { runScheduled } = await import("./chunks/automations-gCDYNS88.mjs");
|
|
2594
2634
|
const report = await runScheduled(ctx, { dryRun: !apply, automationId: strOpt(options, "id"), force: boolOpt(options, "force") });
|
|
2595
2635
|
return apply ? report : { needsConfirmation: true, ...report };
|
|
2596
2636
|
}, (r) => `${"needsConfirmation" in r ? "DRY RUN — " : ""}ran ${r.ran}, skipped ${r.skipped}, errors ${r.errors}`);
|
|
@@ -2614,11 +2654,11 @@ const formsCommand = {
|
|
|
2614
2654
|
const [action = "list", id] = positionals;
|
|
2615
2655
|
switch (action) {
|
|
2616
2656
|
case "list":
|
|
2617
|
-
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/forms-
|
|
2657
|
+
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/forms-Bb0zztBM.mjs")).listForms(ctx), (fs) => table(fs, ["id", "name", "object", "publishedPath"]));
|
|
2618
2658
|
case "publish": {
|
|
2619
2659
|
if (!id) usage("forms publish needs a form id.");
|
|
2620
2660
|
return withSession(io, options, { lock: options.yes === true }, async (s) => {
|
|
2621
|
-
const forms = await import("./chunks/forms-
|
|
2661
|
+
const forms = await import("./chunks/forms-Bb0zztBM.mjs");
|
|
2622
2662
|
const built = await forms.buildFormHtml(s.ctx, id);
|
|
2623
2663
|
const target = s.hostingTarget();
|
|
2624
2664
|
if (!target) usage(`${s.site.alias} has no hosting to publish the form to.`);
|
|
@@ -2632,7 +2672,7 @@ const formsCommand = {
|
|
|
2632
2672
|
case "ingest": {
|
|
2633
2673
|
const apply = options.yes === true;
|
|
2634
2674
|
return withSession(io, options, { lock: apply }, async ({ ctx }) => {
|
|
2635
|
-
const { ingestInbox } = await import("./chunks/forms-
|
|
2675
|
+
const { ingestInbox } = await import("./chunks/forms-Bb0zztBM.mjs");
|
|
2636
2676
|
const report = await ingestInbox(ctx, strOpt(options, "form"), { dryRun: !apply, limit: numOpt(options, "limit") });
|
|
2637
2677
|
return apply ? report : { needsConfirmation: true, ...report };
|
|
2638
2678
|
}, (r) => `${"needsConfirmation" in r ? "DRY RUN — " : ""}processed ${r.processed}: ${r.created} created, ${r.updated} updated, ${r.failed} failed`);
|
|
@@ -3475,13 +3515,13 @@ const objectsCommand = {
|
|
|
3475
3515
|
switch (action) {
|
|
3476
3516
|
case "list":
|
|
3477
3517
|
return withSession(io, options, {}, async ({ ctx, store }) => {
|
|
3478
|
-
const { listObjects } = await import("./chunks/schema-
|
|
3518
|
+
const { listObjects } = await import("./chunks/schema-Cwi7iFp2.mjs");
|
|
3479
3519
|
const { recordsOf } = await import("./chunks/store-5gqRSKXg.mjs");
|
|
3480
3520
|
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 }));
|
|
3481
3521
|
}, (rows) => table(rows, ["id", "labelPlural", "fields", "records", "standard"]));
|
|
3482
3522
|
case "get": {
|
|
3483
3523
|
const objectId = positional(positionals, 1, "object id", "objects get <id>");
|
|
3484
|
-
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/schema-
|
|
3524
|
+
return withSession(io, options, {}, async ({ ctx }) => (await import("./chunks/schema-Cwi7iFp2.mjs")).describeSchema(ctx, objectId)[0]);
|
|
3485
3525
|
}
|
|
3486
3526
|
case "create": {
|
|
3487
3527
|
const data = jsonObjectOpt(options, "data") ?? {};
|
|
@@ -3494,7 +3534,7 @@ const objectsCommand = {
|
|
|
3494
3534
|
...strOpt(options, "color") ? { color: strOpt(options, "color") } : {}
|
|
3495
3535
|
};
|
|
3496
3536
|
if (!input.labelSingular || !input.labelPlural) usage("objects create needs --singular and --plural (or --data).");
|
|
3497
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-
|
|
3537
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-Cwi7iFp2.mjs")).createObject(ctx, input));
|
|
3498
3538
|
}
|
|
3499
3539
|
case "update": {
|
|
3500
3540
|
const objectId = positional(positionals, 1, "object id", "objects update <id> …");
|
|
@@ -3506,12 +3546,12 @@ const objectsCommand = {
|
|
|
3506
3546
|
...strOpt(options, "label-field") ? { labelField: strOpt(options, "label-field") } : {}
|
|
3507
3547
|
};
|
|
3508
3548
|
if (!Object.keys(patch).length) usage("objects update needs --singular, --plural, --icon, --color or --label-field.");
|
|
3509
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-
|
|
3549
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-Cwi7iFp2.mjs")).updateObject(ctx, objectId, patch));
|
|
3510
3550
|
}
|
|
3511
3551
|
case "delete": {
|
|
3512
3552
|
if (!id) usage("objects delete needs an object id.");
|
|
3513
3553
|
return withSession(io, options, { lock: options.yes === true }, async ({ ctx, store }) => {
|
|
3514
|
-
const { getObject, deleteObject } = await import("./chunks/schema-
|
|
3554
|
+
const { getObject, deleteObject } = await import("./chunks/schema-Cwi7iFp2.mjs");
|
|
3515
3555
|
const { recordsOf } = await import("./chunks/store-5gqRSKXg.mjs");
|
|
3516
3556
|
const o = getObject(ctx, id);
|
|
3517
3557
|
const plan = { object: o.id, label: o.labelPlural, standard: o.standard, recordsDeleted: recordsOf(store, o.id, { includeDeleted: true }).length };
|
|
@@ -3569,7 +3609,7 @@ const fieldsCommand = {
|
|
|
3569
3609
|
...boolOpt(options, "unique") ? { unique: true } : {},
|
|
3570
3610
|
...strOpt(options, "description") ? { description: strOpt(options, "description") } : {}
|
|
3571
3611
|
};
|
|
3572
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-
|
|
3612
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-Cwi7iFp2.mjs")).createField(ctx, objectId, input));
|
|
3573
3613
|
}
|
|
3574
3614
|
case "update": {
|
|
3575
3615
|
if (!fieldId) usage("fields update needs a field id.");
|
|
@@ -3586,12 +3626,12 @@ const fieldsCommand = {
|
|
|
3586
3626
|
...strOpt(options, "description") !== void 0 ? { description: strOpt(options, "description") } : {}
|
|
3587
3627
|
};
|
|
3588
3628
|
if (!Object.keys(patch).length) usage("fields update needs at least one change.");
|
|
3589
|
-
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-
|
|
3629
|
+
return withSession(io, options, { lock: true }, async ({ ctx }) => (await import("./chunks/schema-Cwi7iFp2.mjs")).updateField(ctx, objectId, fieldId, patch));
|
|
3590
3630
|
}
|
|
3591
3631
|
case "delete": {
|
|
3592
3632
|
if (!fieldId) usage("fields delete needs a field id.");
|
|
3593
3633
|
return withSession(io, options, { lock: options.yes === true }, async ({ ctx, store }) => {
|
|
3594
|
-
const { getObject, deleteField } = await import("./chunks/schema-
|
|
3634
|
+
const { getObject, deleteField } = await import("./chunks/schema-Cwi7iFp2.mjs");
|
|
3595
3635
|
const { recordsOf } = await import("./chunks/store-5gqRSKXg.mjs");
|
|
3596
3636
|
const field = getObject(ctx, objectId).fields.find((f) => f.id === fieldId);
|
|
3597
3637
|
if (!field) usage(`No field "${fieldId}" on ${objectId}.`, `\`agentcrm objects get ${objectId}\` lists them.`);
|
|
@@ -3624,7 +3664,7 @@ const schemaCommand = {
|
|
|
3624
3664
|
usage(`The schema is not valid JSON: ${err.message}`);
|
|
3625
3665
|
}
|
|
3626
3666
|
const apply = options.yes === true;
|
|
3627
|
-
const { applySchema, parseSchemaSpec } = await import("./chunks/schemaApply-
|
|
3667
|
+
const { applySchema, parseSchemaSpec } = await import("./chunks/schemaApply-tEIr5lFK.mjs");
|
|
3628
3668
|
const spec = parseSchemaSpec(raw);
|
|
3629
3669
|
return withSession(
|
|
3630
3670
|
io,
|
|
@@ -3942,7 +3982,7 @@ const toolsCommand = {
|
|
|
3942
3982
|
async run({ io, options, positionals }) {
|
|
3943
3983
|
const [action = "list"] = positionals;
|
|
3944
3984
|
if (action === "list") {
|
|
3945
|
-
const { listAiTools, AI_TOOLS } = await import("./chunks/tools-
|
|
3985
|
+
const { listAiTools, AI_TOOLS } = await import("./chunks/tools-BR3X1Uvm.mjs");
|
|
3946
3986
|
const builtin = new Set(AI_TOOLS.map((t) => t.name));
|
|
3947
3987
|
const shape = () => listAiTools().map((t) => ({ name: t.name, description: t.description, mutating: t.mutating, source: builtin.has(t.name) ? "builtin" : "extension", inputSchema: t.inputSchema }));
|
|
3948
3988
|
const human = (r) => table(r.tools, ["name", "mutating", "source", "description"]);
|
|
@@ -3962,7 +4002,7 @@ const toolsCommand = {
|
|
|
3962
4002
|
}
|
|
3963
4003
|
if (action === "call") {
|
|
3964
4004
|
const name2 = positional(positionals, 1, "tool name", "tools call <name> --input <json>");
|
|
3965
|
-
const { findTool, callTool, listAiTools } = await import("./chunks/tools-
|
|
4005
|
+
const { findTool, callTool, listAiTools } = await import("./chunks/tools-BR3X1Uvm.mjs");
|
|
3966
4006
|
const input = jsonObjectOpt(options, "input") ?? {};
|
|
3967
4007
|
const builtin = findTool(name2);
|
|
3968
4008
|
return withSession(io, options, { lock: builtin ? builtin.mutating : true }, async ({ ctx }) => {
|
|
@@ -3984,8 +4024,8 @@ const mcpCommand = {
|
|
|
3984
4024
|
const log = (msg) => process.stderr.write(`${msg}
|
|
3985
4025
|
`);
|
|
3986
4026
|
for (const w of session2.warnings) log(`[agentcrm mcp] note: ${w}`);
|
|
3987
|
-
const { listAiTools } = await import("./chunks/tools-
|
|
3988
|
-
const { createMcpServer, serveStdio } = await import("./chunks/server-
|
|
4027
|
+
const { listAiTools } = await import("./chunks/tools-BR3X1Uvm.mjs");
|
|
4028
|
+
const { createMcpServer, serveStdio } = await import("./chunks/server-3awvGTvL.mjs");
|
|
3989
4029
|
let lastRefresh = Date.now();
|
|
3990
4030
|
const server = createMcpServer({
|
|
3991
4031
|
readOnly,
|