@fleox-agent-crm/agentcrm 0.3.0 → 0.3.2
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 +30 -0
- package/dist/admin/admin-files.json +8 -8
- package/dist/admin/assets/{chartsImpl-CE2akJat.js → chartsImpl-qlHW3VOv.js} +30 -30
- package/dist/admin/assets/firebase-U38f5kc9.js +2 -0
- package/dist/admin/assets/{gitJson-BulGh2KV.js → gitJson-wy2Tytfd.js} +1 -1
- package/dist/admin/assets/{index-DidVVK7L.js → index-BpaxrJx9.js} +265 -265
- package/dist/admin/assets/{index-hMXwHSvN.css → index-TcjySLVg.css} +1 -1
- package/dist/admin/assets/{lucide-react.min-DEDlHCPj.js → lucide-react.min-Djrg16BH.js} +1 -1
- package/dist/admin/assets/{sdk-CnrLnlRo.js → sdk-mu08RFtk.js} +1 -1
- package/dist/admin/index.html +2 -2
- package/dist/agent/agentcrm.mjs +334 -151
- package/dist/agent/chunks/{api-B6OqNVWp.mjs → api-Cz0Ubj-B.mjs} +4 -3
- package/dist/agent/chunks/api-Dwb4xz1k.mjs +27 -0
- package/dist/agent/chunks/{appearance-BaShelzt.mjs → appearance-BloHbiLA.mjs} +1 -1
- package/dist/agent/chunks/{automations-BWrvLqP6.mjs → automations-DwWruxmu.mjs} +3 -3
- package/dist/agent/chunks/{backup-ClSmxmFZ.mjs → backup-W3CjgkAJ.mjs} +16 -3
- package/dist/agent/chunks/{compact-CsFPaAAq.mjs → compact-BGHI92tm.mjs} +2 -2
- package/dist/agent/chunks/{exportCsv-B5hRvkNm.mjs → exportCsv-C6e6XEmB.mjs} +38 -3
- package/dist/agent/chunks/{extCheck--7lmVvl7.mjs → extCheck-GgHG1dYB.mjs} +16 -9
- package/dist/agent/chunks/{extPackage-BGl5Oqs8.mjs → extPackage-DuZ6GZhp.mjs} +2 -2
- package/dist/agent/chunks/{extScaffold-DqxI7R1e.mjs → extScaffold-Aqyjf1nr.mjs} +3 -3
- package/dist/agent/chunks/{extensions-BP1k60md.mjs → extensions-Bp72uZ9a.mjs} +19 -6
- package/dist/agent/chunks/{featureRegistry-C9nbVShp.mjs → featureRegistry-DSsZbhrh.mjs} +3 -3
- package/dist/agent/chunks/{files-q8Xu5bft.mjs → files-D1daDgY0.mjs} +1 -1
- package/dist/agent/chunks/{firebase-DxGVQV9E.mjs → firebase-BciZWdc6.mjs} +41 -17
- package/dist/agent/chunks/{forms-BKU5F9WF.mjs → forms-BfuWaQjA.mjs} +1 -1
- package/dist/agent/chunks/{hosting-Bme7LxPc.mjs → hosting-Dnn1k3cV.mjs} +1 -1
- package/dist/agent/chunks/{importCsv-DmE_sBch.mjs → importCsv-LVmMTaWU.mjs} +2 -2
- package/dist/agent/chunks/{index-DUSdTBkz.mjs → index-CNXq2Yk_.mjs} +1 -24
- package/dist/agent/chunks/index-Dio0aBWA.mjs +6920 -0
- package/dist/agent/chunks/{index-CRkw3_iF.mjs → index-rut-KC39.mjs} +1 -1
- package/dist/agent/chunks/{install-CpHoUFtL.mjs → install-BBTA4nMm.mjs} +16 -7
- package/dist/agent/chunks/{loader-C9nm3iwx.mjs → loader-MPD9iAvh.mjs} +20 -20
- package/dist/agent/chunks/{modules-CqdVQVJb.mjs → modules-clWdE-K2.mjs} +27 -2
- package/dist/agent/chunks/{nodeImport-BPCt5uMu.mjs → nodeImport-ylfRDvqt.mjs} +2 -2
- package/dist/agent/chunks/{package-DWbn3t2R.mjs → package-B7mI6HGi.mjs} +1 -1
- package/dist/agent/chunks/{papaparse-DjBYnQM2.mjs → papaparse-Df7i1dHr.mjs} +31 -7
- package/dist/agent/chunks/{pipelines-DCdRBNBV.mjs → pipelines-BAKpPk1w.mjs} +1 -1
- package/dist/agent/chunks/{plan-C0TBrU92.mjs → plan-BmTat6-T.mjs} +1 -1
- package/dist/agent/chunks/{records-DoqiT9xR.mjs → records-DcHFelq5.mjs} +5 -1
- package/dist/agent/chunks/{registry-Ceexawxl.mjs → registry-COfJrSmg.mjs} +18 -18
- package/dist/agent/chunks/{reports-BB59N6ke.mjs → reports-BACHGccj.mjs} +3 -3
- package/dist/agent/chunks/{runtime-DHo7ZEEO.mjs → runtime-C0Xf0Axi.mjs} +53 -32
- package/dist/agent/chunks/{schema-DlHt2PxI.mjs → schema-C4lSslXv.mjs} +10 -4
- package/dist/agent/chunks/{schema-7-4-qtSS.mjs → schema-DnLj8dUO.mjs} +10 -0
- package/dist/agent/chunks/{sdk-whvfg786.mjs → sdk-CYgNyuoK.mjs} +132 -7005
- package/dist/agent/chunks/{seed-CugPGYZL.mjs → seed-6MRmQQBR.mjs} +26 -8
- package/dist/agent/chunks/{server-ISwlDRCN.mjs → server-DC3t8r30.mjs} +5 -5
- package/dist/agent/chunks/{settings-BtvR_jdm.mjs → settings-Di8nzNEL.mjs} +35 -0
- package/dist/agent/chunks/{stats-CfeJssSS.mjs → stats-BfuLWhVV.mjs} +2 -2
- package/dist/agent/chunks/{tools-Bew8lxKx.mjs → tools-iSH-yMpl.mjs} +59 -19
- package/dist/agent/chunks/{views-fO_BM5U_.mjs → views-DH1n9Lrt.mjs} +1 -1
- 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/appearance.md +1 -1
- package/plugin/skills/agentcrm-admin/references/records.md +5 -5
- package/plugin/skills/agentcrm-admin/references/schema.md +20 -20
- package/plugin/skills/agentcrm-extensions/SKILL.md +9 -9
- package/plugin/skills/agentcrm-extensions/references/module-recipes.md +2 -2
- package/plugin/skills/agentcrm-extensions/references/testing.md +16 -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 +3 -3
- 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/admin/assets/firebase-BHSUggRo.js +0 -2
|
@@ -11,7 +11,7 @@ import { a as standardObjects, b as defaultPipeline, c as defaultViews } from ".
|
|
|
11
11
|
import { assertCan } from "./context-CxFfqS4D.mjs";
|
|
12
12
|
import { sha256Hex } from "./files-CjsPJSR6.mjs";
|
|
13
13
|
import { asDoc, objectOf, usersOf, settingsDoc } from "./store-5gqRSKXg.mjs";
|
|
14
|
-
import { DEFAULT_SETTINGS } from "./settings-
|
|
14
|
+
import { DEFAULT_SETTINGS } from "./settings-Di8nzNEL.mjs";
|
|
15
15
|
import "./pluginRegistry-DyHtlkcr.mjs";
|
|
16
16
|
import "./runtimeConfig-CCOFg1RM.mjs";
|
|
17
17
|
const PALETTES = [
|
|
@@ -362,6 +362,20 @@ const FIRST = ["Ada", "Alan", "Grace", "Linus", "Margaret", "Dennis", "Barbara",
|
|
|
362
362
|
const LAST = ["Lovelace", "Turing", "Hopper", "Torvalds", "Hamilton", "Ritchie", "Liskov", "Thompson", "Allen", "Berners-Lee", "Perlman", "Cerf", "Lamarr", "McCarthy", "Johnson", "van Rossum", "Martin", "Bernard", "Dubois", "Durand", "Lefebvre", "Moreau", "Laurent", "Simon", "Michel", "Garcia", "Roux", "Fournier", "Girard", "Bonnet", "Smith", "Brown", "Wilson", "Taylor", "Clark", "Lewis", "Walker", "Young", "King", "Wright"];
|
|
363
363
|
const TITLES = ["CEO", "CTO", "VP Sales", "Head of Marketing", "Procurement Manager", "Operations Director", "Product Manager", "Engineering Manager", "CFO", "Office Manager", "Account Executive", "Data Analyst"];
|
|
364
364
|
const CITIES = ["Paris", "London", "New York", "Berlin", "Lyon", "Madrid", "Amsterdam", "Montréal", "San Francisco", "Lisbon", "Brussels", "Toronto"];
|
|
365
|
+
const CITY_COUNTRY = {
|
|
366
|
+
Paris: ["France", "+33 1"],
|
|
367
|
+
London: ["United Kingdom", "+44 20"],
|
|
368
|
+
"New York": ["United States", "+1 212"],
|
|
369
|
+
Berlin: ["Germany", "+49 30"],
|
|
370
|
+
Lyon: ["France", "+33 4"],
|
|
371
|
+
Madrid: ["Spain", "+34 91"],
|
|
372
|
+
Amsterdam: ["Netherlands", "+31 20"],
|
|
373
|
+
Montréal: ["Canada", "+1 514"],
|
|
374
|
+
"San Francisco": ["United States", "+1 415"],
|
|
375
|
+
Lisbon: ["Portugal", "+351 21"],
|
|
376
|
+
Brussels: ["Belgium", "+32 2"],
|
|
377
|
+
Toronto: ["Canada", "+1 416"]
|
|
378
|
+
};
|
|
365
379
|
const DEAL_KINDS = ["Annual license", "Pilot", "Expansion", "Renewal", "Onboarding package", "Enterprise plan", "Support contract", "Consulting retainer"];
|
|
366
380
|
const LIFECYCLE = ["subscriber", "lead", "lead", "mql", "sql", "opportunity", "customer", "customer", "evangelist"];
|
|
367
381
|
const SOURCES = ["website", "referral", "event", "outbound", "partner", "ads", "social"];
|
|
@@ -405,19 +419,23 @@ async function seedDemoData(ctx, opts = {}) {
|
|
|
405
419
|
updatedAt: stamp(Math.max(0, daysAgo - rand() * daysAgo)),
|
|
406
420
|
...opts.ownerId ? { createdBy: opts.ownerId } : {}
|
|
407
421
|
});
|
|
408
|
-
const companies = COMPANIES.map(
|
|
409
|
-
|
|
422
|
+
const companies = COMPANIES.map(([name, domain, industry, employees], i) => {
|
|
423
|
+
const annualRevenue = Math.round(employees * (6e4 + rand() * 14e4) / 1e3) * 1e3;
|
|
424
|
+
const city = pick(CITIES);
|
|
425
|
+
rand();
|
|
426
|
+
const [country, dial] = CITY_COUNTRY[city];
|
|
427
|
+
return rec(seededId(`demo:company:${i}`), "companies", {
|
|
410
428
|
name,
|
|
411
429
|
domain: `https://${domain}`,
|
|
412
430
|
industry,
|
|
413
431
|
employees,
|
|
414
|
-
annualRevenue
|
|
415
|
-
address: { city
|
|
432
|
+
annualRevenue,
|
|
433
|
+
address: { city, country },
|
|
416
434
|
linkedin: `https://www.linkedin.com/company/${domain.split(".")[0]}`,
|
|
417
|
-
phone:
|
|
435
|
+
phone: `${dial} ${String(10 + i).padStart(2, "0")} ${String(Math.floor(rand() * 90) + 10)} ${String(Math.floor(rand() * 90) + 10)} ${String(Math.floor(rand() * 90) + 10)}`,
|
|
418
436
|
...rand() < 0.3 ? { tags: [pick(["vip", "partner", "strategic", "smb", "enterprise"])] } : {}
|
|
419
|
-
}, i, 30 + rand() * 300)
|
|
420
|
-
);
|
|
437
|
+
}, i, 30 + rand() * 300);
|
|
438
|
+
});
|
|
421
439
|
const people = [];
|
|
422
440
|
for (let i = 0; i < 80; i++) {
|
|
423
441
|
const firstName = FIRST[i % FIRST.length];
|
|
@@ -97,7 +97,7 @@ function createMcpServer(opts) {
|
|
|
97
97
|
try {
|
|
98
98
|
const run = async () => {
|
|
99
99
|
const ctx = await opts.backend.context();
|
|
100
|
-
const { callTool: call } = await import("./tools-
|
|
100
|
+
const { callTool: call } = await import("./tools-iSH-yMpl.mjs");
|
|
101
101
|
return call(ctx, name, args);
|
|
102
102
|
};
|
|
103
103
|
const result = tool.mutating ? await opts.backend.withWrite(run) : await run();
|
|
@@ -112,15 +112,15 @@ function createMcpServer(opts) {
|
|
|
112
112
|
async function readResource(id, uri) {
|
|
113
113
|
const ctx = await opts.backend.context();
|
|
114
114
|
let value;
|
|
115
|
-
if (uri === "agentcrm://schema") value = (await import("./schema-
|
|
115
|
+
if (uri === "agentcrm://schema") value = (await import("./schema-C4lSslXv.mjs")).describeSchema(ctx);
|
|
116
116
|
else if (uri === "agentcrm://pipelines") {
|
|
117
|
-
const { listPipelines, forecast } = await import("./pipelines-
|
|
117
|
+
const { listPipelines, forecast } = await import("./pipelines-BAKpPk1w.mjs");
|
|
118
118
|
value = listPipelines(ctx).map((p) => ({ ...p, forecast: forecast(ctx, { pipelineId: p.id }) }));
|
|
119
119
|
} else if (uri === "agentcrm://modules") {
|
|
120
|
-
const [{ listModules }, { listExtensions }] = await Promise.all([import("./modules-
|
|
120
|
+
const [{ listModules }, { listExtensions }] = await Promise.all([import("./modules-clWdE-K2.mjs"), import("./extensions-Bp72uZ9a.mjs")]);
|
|
121
121
|
value = { modules: listModules(ctx), extensions: listExtensions(ctx) };
|
|
122
122
|
} else if (uri === "agentcrm://appearance") {
|
|
123
|
-
const { getAppearance, listPresets } = await import("./appearance-
|
|
123
|
+
const { getAppearance, listPresets } = await import("./appearance-BloHbiLA.mjs");
|
|
124
124
|
const { logo, favicon, customCss, ...rest } = getAppearance(ctx);
|
|
125
125
|
value = { appearance: { ...rest, hasLogo: !!logo, hasFavicon: !!favicon, customCss: customCss ?? null }, presets: listPresets(ctx).map((p) => ({ id: p.id, name: p.name, source: p.source, description: p.description, ...p.enabled !== void 0 ? { enabled: p.enabled } : {} })) };
|
|
126
126
|
} else return fail(id, -32002, `Resource not found: ${uri}`, { uri });
|
|
@@ -20,8 +20,25 @@ function getSettings(ctx) {
|
|
|
20
20
|
assertCan(ctx, "settings.read");
|
|
21
21
|
return { ...DEFAULT_SETTINGS, ...settingsDoc(ctx.store) ?? {} };
|
|
22
22
|
}
|
|
23
|
+
const SETTINGS_KEYS = ["name", "defaultCurrency", "locale", "timezone", "weekStartsOn", "staleDealDays", "ownerUserId", "maxUploadMb"];
|
|
23
24
|
async function updateSettings(ctx, patch) {
|
|
24
25
|
assertCan(ctx, "settings.write");
|
|
26
|
+
const unknown = Object.keys(patch).filter((k) => !SETTINGS_KEYS.includes(k) && k !== "createdAt" && k !== "updatedAt" && k !== "id");
|
|
27
|
+
if (unknown.length) {
|
|
28
|
+
throw new OpsError("validation", `Unknown setting${unknown.length > 1 ? "s" : ""} ${unknown.map((k) => `"${k}"`).join(", ")}. Settings: ${SETTINGS_KEYS.join(", ")}.`);
|
|
29
|
+
}
|
|
30
|
+
if (patch.name !== void 0 && (typeof patch.name !== "string" || !patch.name.trim())) {
|
|
31
|
+
throw new OpsError("validation", "The CRM name can't be empty.");
|
|
32
|
+
}
|
|
33
|
+
if (patch.weekStartsOn !== void 0 && patch.weekStartsOn !== 0 && patch.weekStartsOn !== 1) {
|
|
34
|
+
throw new OpsError("validation", "Week start must be 0 (Sunday) or 1 (Monday).");
|
|
35
|
+
}
|
|
36
|
+
if (patch.locale !== void 0 && !validLocale(patch.locale)) {
|
|
37
|
+
throw new OpsError("validation", `"${String(patch.locale)}" is not a valid locale (BCP-47, e.g. en-US, fr-FR).`);
|
|
38
|
+
}
|
|
39
|
+
if (patch.timezone !== void 0 && patch.timezone !== null && !validTimeZone(patch.timezone)) {
|
|
40
|
+
throw new OpsError("validation", `"${String(patch.timezone)}" is not a valid time zone (IANA, e.g. Europe/Paris).`);
|
|
41
|
+
}
|
|
25
42
|
if (patch.defaultCurrency !== void 0 && !/^[A-Z]{3}$/.test(patch.defaultCurrency.toUpperCase())) {
|
|
26
43
|
throw new OpsError("validation", `"${patch.defaultCurrency}" is not an ISO 4217 currency code.`);
|
|
27
44
|
}
|
|
@@ -43,6 +60,23 @@ async function updateSettings(ctx, patch) {
|
|
|
43
60
|
await ctx.store.write([{ op: "set", collection: "settings", doc: asDoc(next) }], { message: "Update settings" });
|
|
44
61
|
return getSettings(ctx);
|
|
45
62
|
}
|
|
63
|
+
function validLocale(value) {
|
|
64
|
+
if (typeof value !== "string" || !value) return false;
|
|
65
|
+
try {
|
|
66
|
+
return Intl.getCanonicalLocales(value).length === 1;
|
|
67
|
+
} catch {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function validTimeZone(value) {
|
|
72
|
+
if (typeof value !== "string" || !value) return false;
|
|
73
|
+
try {
|
|
74
|
+
new Intl.DateTimeFormat("en-US", { timeZone: value });
|
|
75
|
+
return true;
|
|
76
|
+
} catch {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
46
80
|
function assertNoSecrets(value, path = "") {
|
|
47
81
|
if (!value || typeof value !== "object") return;
|
|
48
82
|
for (const [k, v] of Object.entries(value)) {
|
|
@@ -68,6 +102,7 @@ async function setConfigDoc(ctx, id, value) {
|
|
|
68
102
|
}
|
|
69
103
|
export {
|
|
70
104
|
DEFAULT_SETTINGS,
|
|
105
|
+
SETTINGS_KEYS,
|
|
71
106
|
assertNoSecrets,
|
|
72
107
|
getConfigDoc,
|
|
73
108
|
getSettings,
|
|
@@ -6,7 +6,7 @@ const __filename = __acrmPath(import.meta.url);
|
|
|
6
6
|
const __dirname = __acrmDirname(__filename);
|
|
7
7
|
import { A as ACTIVITY_TYPES } from "../agentcrm.mjs";
|
|
8
8
|
import { assertCan } from "./context-CxFfqS4D.mjs";
|
|
9
|
-
import { forecast } from "./pipelines-
|
|
9
|
+
import { forecast } from "./pipelines-BAKpPk1w.mjs";
|
|
10
10
|
import { activitiesOf, pipelinesOf, usersOf, objectsOf, recordsOf } from "./store-5gqRSKXg.mjs";
|
|
11
11
|
import "node:util";
|
|
12
12
|
import "node:fs";
|
|
@@ -20,7 +20,7 @@ import "./pluginRegistry-DyHtlkcr.mjs";
|
|
|
20
20
|
import "./fields-B0bitgmr.mjs";
|
|
21
21
|
import "./ids-CvnmrMJX.mjs";
|
|
22
22
|
import "./standardObjects-CheqfDqa.mjs";
|
|
23
|
-
import "./records-
|
|
23
|
+
import "./records-DcHFelq5.mjs";
|
|
24
24
|
import "./query-C5nJB_3C.mjs";
|
|
25
25
|
import "./relations-B9TynBmA.mjs";
|
|
26
26
|
function getStats(ctx) {
|
|
@@ -6,24 +6,24 @@ const __filename = __acrmPath(import.meta.url);
|
|
|
6
6
|
const __dirname = __acrmDirname(__filename);
|
|
7
7
|
import { recordLabel, normalizeEmail, formatFieldValue } from "./fields-B0bitgmr.mjs";
|
|
8
8
|
import { r as resolveField } from "./query-C5nJB_3C.mjs";
|
|
9
|
-
import { F as FILTER_OPS, A as ACTIVITY_TYPES,
|
|
9
|
+
import { F as FILTER_OPS, A as ACTIVITY_TYPES, a as FIELD_TYPES } from "../agentcrm.mjs";
|
|
10
10
|
import { OpsError } from "./context-CxFfqS4D.mjs";
|
|
11
11
|
import { listActivities, addNote, addActivity, createTask, completeTask, listTasks } from "./activities-Cj_SIOay.mjs";
|
|
12
12
|
import { mergeRecords } from "./dedupe-BepmsaHv.mjs";
|
|
13
|
-
import { importCsv } from "./importCsv-
|
|
14
|
-
import { moveStage, forecast, listPipelines } from "./pipelines-
|
|
15
|
-
import { getRecord, searchRecords, listRecords, getRecordDetails, createRecord, updateRecord, deleteRecord, queryContext } from "./records-
|
|
16
|
-
import { runReport, REPORTS } from "./reports-
|
|
17
|
-
import { describeSchema, createField } from "./schema-
|
|
13
|
+
import { importCsv } from "./importCsv-LVmMTaWU.mjs";
|
|
14
|
+
import { moveStage, forecast, listPipelines } from "./pipelines-BAKpPk1w.mjs";
|
|
15
|
+
import { getRecord, searchRecords, listRecords, getRecordDetails, createRecord, updateRecord, deleteRecord, queryContext } from "./records-DcHFelq5.mjs";
|
|
16
|
+
import { runReport, REPORTS } from "./reports-BACHGccj.mjs";
|
|
17
|
+
import { describeSchema, createField } from "./schema-C4lSslXv.mjs";
|
|
18
18
|
import { objectOf, recordOf, userOf, activitiesOf, fileOf } from "./store-5gqRSKXg.mjs";
|
|
19
|
-
import { ACTION_TYPES, TRIGGER_TYPES, listAutomationRuns, AUTOMATION_TEMPLATES, listAutomations, createAutomationFromTemplate, createAutomation, setAutomationEnabled, testAutomation, runScheduled } from "./automations-
|
|
20
|
-
import { listForms, ingestInbox } from "./forms-
|
|
21
|
-
import { B as BUTTON_STYLES, C as CONTRASTS, d as COLOR_MODES, S as SIDEBAR_STYLES, e as DENSITIES, R as RADII, N as NEUTRALS, F as FONTS } from "./schema-
|
|
22
|
-
import { listPresets, getAppearance, setAppearance, applyPreset } from "./appearance-
|
|
23
|
-
import { listExtensions, setExtensionEnabled } from "./extensions-
|
|
24
|
-
import { listModules, setModuleEnabled } from "./modules-
|
|
19
|
+
import { ACTION_TYPES, TRIGGER_TYPES, listAutomationRuns, AUTOMATION_TEMPLATES, listAutomations, createAutomationFromTemplate, createAutomation, setAutomationEnabled, testAutomation, runScheduled } from "./automations-DwWruxmu.mjs";
|
|
20
|
+
import { listForms, ingestInbox } from "./forms-BfuWaQjA.mjs";
|
|
21
|
+
import { B as BUTTON_STYLES, C as CONTRASTS, d as COLOR_MODES, S as SIDEBAR_STYLES, e as DENSITIES, R as RADII, N as NEUTRALS, F as FONTS } from "./schema-DnLj8dUO.mjs";
|
|
22
|
+
import { listPresets, getAppearance, setAppearance, applyPreset } from "./appearance-BloHbiLA.mjs";
|
|
23
|
+
import { listExtensions, setExtensionEnabled } from "./extensions-Bp72uZ9a.mjs";
|
|
24
|
+
import { listModules, setModuleEnabled } from "./modules-clWdE-K2.mjs";
|
|
25
25
|
import { inlineFileIds, formatBytes, fileKind } from "./files-CjsPJSR6.mjs";
|
|
26
|
-
import { listFiles, fileUsage } from "./files-
|
|
26
|
+
import { listFiles, fileUsage } from "./files-D1daDgY0.mjs";
|
|
27
27
|
import { l as labelOf } from "./relations-B9TynBmA.mjs";
|
|
28
28
|
import "node:util";
|
|
29
29
|
import "node:fs";
|
|
@@ -35,17 +35,17 @@ import "node:child_process";
|
|
|
35
35
|
import "node:http";
|
|
36
36
|
import "./pluginRegistry-DyHtlkcr.mjs";
|
|
37
37
|
import "./ids-CvnmrMJX.mjs";
|
|
38
|
-
import "./papaparse-
|
|
38
|
+
import "./papaparse-Df7i1dHr.mjs";
|
|
39
39
|
import "./_commonjsHelpers-ClciMIcB.mjs";
|
|
40
40
|
import "stream";
|
|
41
41
|
import "./utils-DmI8FtXP.mjs";
|
|
42
42
|
import "./standardObjects-CheqfDqa.mjs";
|
|
43
|
-
import "./settings-
|
|
43
|
+
import "./settings-Di8nzNEL.mjs";
|
|
44
44
|
import "./runtimeConfig-CCOFg1RM.mjs";
|
|
45
45
|
import "./extensionActions-D2HtpQz4.mjs";
|
|
46
46
|
import "./themes-DPZFv3yc.mjs";
|
|
47
|
-
import "./api-
|
|
48
|
-
import "./package-
|
|
47
|
+
import "./api-Cz0Ubj-B.mjs";
|
|
48
|
+
import "./package-B7mI6HGi.mjs";
|
|
49
49
|
import "./index-w03ReRs4.mjs";
|
|
50
50
|
import "events";
|
|
51
51
|
import "buffer";
|
|
@@ -824,18 +824,58 @@ function subscribeAiTools(listener) {
|
|
|
824
824
|
function findTool(name) {
|
|
825
825
|
return AI_TOOLS.find((t) => t.name === name) ?? extraTools.get(name);
|
|
826
826
|
}
|
|
827
|
+
function jsonTypeOf(value) {
|
|
828
|
+
if (value === null) return "null";
|
|
829
|
+
if (Array.isArray(value)) return "array";
|
|
830
|
+
return typeof value;
|
|
831
|
+
}
|
|
832
|
+
function checkToolInput(schema, value, path) {
|
|
833
|
+
const types = schema.type === void 0 ? [] : Array.isArray(schema.type) ? schema.type : [schema.type];
|
|
834
|
+
let v = value;
|
|
835
|
+
if (types.length && v !== null && v !== void 0) {
|
|
836
|
+
const actual = jsonTypeOf(v);
|
|
837
|
+
const accepts = (t) => t === actual || t === "integer" && actual === "number" && Number.isInteger(v);
|
|
838
|
+
if (!types.some(accepts)) {
|
|
839
|
+
if ((types.includes("number") || types.includes("integer")) && typeof v === "string" && v.trim() !== "" && Number.isFinite(Number(v))) v = Number(v);
|
|
840
|
+
else if (types.includes("boolean") && (v === "true" || v === "false")) v = v === "true";
|
|
841
|
+
else throw new OpsError("validation", `${path} must be ${types.map((t) => t === "array" || t === "object" || t === "integer" ? `an ${t}` : `a ${t}`).join(" or ")}, got ${actual === "array" || actual === "object" ? `an ${actual}` : `${actual} ${JSON.stringify(v)}`.slice(0, 80)}.`);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
if (v === null || v === void 0) return v;
|
|
845
|
+
if (schema.enum && !schema.enum.includes(v)) {
|
|
846
|
+
throw new OpsError("validation", `${path} must be one of ${schema.enum.map((e) => JSON.stringify(e)).join(", ")}, got ${JSON.stringify(v).slice(0, 80)}.`);
|
|
847
|
+
}
|
|
848
|
+
if (Array.isArray(v) && schema.items) {
|
|
849
|
+
const items = schema.items;
|
|
850
|
+
return v.map((item, i) => checkToolInput(items, item, `${path}[${i}]`));
|
|
851
|
+
}
|
|
852
|
+
if (jsonTypeOf(v) === "object" && (schema.properties || schema.required)) {
|
|
853
|
+
const obj = { ...v };
|
|
854
|
+
for (const key of schema.required ?? []) {
|
|
855
|
+
if (obj[key] === void 0 || obj[key] === null) throw new OpsError("validation", `${path}: missing required "${key}".`);
|
|
856
|
+
}
|
|
857
|
+
for (const [key, sub] of Object.entries(schema.properties ?? {})) {
|
|
858
|
+
if (obj[key] !== void 0) obj[key] = checkToolInput(sub, obj[key], `${path}.${key}`);
|
|
859
|
+
}
|
|
860
|
+
return obj;
|
|
861
|
+
}
|
|
862
|
+
return v;
|
|
863
|
+
}
|
|
827
864
|
async function callTool(ctx, name, input) {
|
|
828
865
|
const tool = findTool(name);
|
|
829
866
|
if (!tool) throw new OpsError("notFound", `Unknown tool "${name}". Tools: ${listAiTools().map((t) => t.name).join(", ")}.`);
|
|
830
|
-
|
|
867
|
+
if (input !== void 0 && input !== null && jsonTypeOf(input) !== "object") throw new OpsError("validation", `${name}: the input must be a JSON object, got ${jsonTypeOf(input) === "array" ? "an array" : `a ${jsonTypeOf(input)}`}.`);
|
|
868
|
+
const raw = input ?? {};
|
|
831
869
|
for (const key of tool.inputSchema.required ?? []) {
|
|
832
|
-
if (
|
|
870
|
+
if (raw[key] === void 0 || raw[key] === null) throw new OpsError("validation", `${name}: missing required "${key}".`);
|
|
833
871
|
}
|
|
872
|
+
const args = checkToolInput({ ...tool.inputSchema, required: [] }, raw, name);
|
|
834
873
|
return tool.handler(ctx, args);
|
|
835
874
|
}
|
|
836
875
|
export {
|
|
837
876
|
AI_TOOLS,
|
|
838
877
|
callTool,
|
|
878
|
+
checkToolInput,
|
|
839
879
|
findTool,
|
|
840
880
|
listAiTools,
|
|
841
881
|
registerAiTool,
|
|
@@ -7,7 +7,7 @@ const __dirname = __acrmDirname(__filename);
|
|
|
7
7
|
import { n as newId } from "./ids-CvnmrMJX.mjs";
|
|
8
8
|
import { F as FILTER_OPS } from "../agentcrm.mjs";
|
|
9
9
|
import { OpsError, assertCan, can } from "./context-CxFfqS4D.mjs";
|
|
10
|
-
import { listRecords } from "./records-
|
|
10
|
+
import { listRecords } from "./records-DcHFelq5.mjs";
|
|
11
11
|
import { requireObject, asDoc, viewsOf, thaw, pipelinesOf } from "./store-5gqRSKXg.mjs";
|
|
12
12
|
import "node:util";
|
|
13
13
|
import "node:fs";
|
package/dist/version.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fleox-agent-crm/agentcrm",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"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.",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentcrm",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Skills to install AgentCRM (the static CRM your AI agent can run), manage its sites, run and customise the CRM (modules, appearance, extensions), drive sales workflows and build extension modules and themes.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "fleox"
|
|
@@ -4,7 +4,7 @@ description: Run an AgentCRM like its admin does - find, list, create, update, d
|
|
|
4
4
|
license: PolyForm-Noncommercial-1.0.0
|
|
5
5
|
compatibility: Requires Node.js 20+.
|
|
6
6
|
metadata:
|
|
7
|
-
version: "0.3.
|
|
7
|
+
version: "0.3.2"
|
|
8
8
|
repository: "https://github.com/fleox/agentcrm"
|
|
9
9
|
allowed-tools: Bash Read Write
|
|
10
10
|
---
|
|
@@ -15,7 +15,7 @@ The CLI runs the admin's own engine headless: the same validation, roles and aut
|
|
|
15
15
|
|
|
16
16
|
**Language:** talk to the user in their language; keep commands and files in English.
|
|
17
17
|
|
|
18
|
-
Every command is `npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
18
|
+
Every command is `npx -y @fleox-agent-crm/agentcrm@0.3.2 <command> --json`; always pass `--site <alias>` (see `agentcrm-manage` to pick one). Read `error.hint` when `ok` is false. `npx -y @fleox-agent-crm/agentcrm@0.3.2 help records --json` lists any command's actions and options.
|
|
19
19
|
|
|
20
20
|
## Rules
|
|
21
21
|
|
|
@@ -27,13 +27,13 @@ Every command is `npx -y @fleox-agent-crm/agentcrm@0.3.0 <command> --json`; alwa
|
|
|
27
27
|
## Records
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
31
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
32
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
33
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
34
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
35
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
36
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
30
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records list --site acme --object deals --filter stage:in:proposal,negotiation --filter amount:gte:10000 --sort amount:desc --limit 20 --json
|
|
31
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records get <id> --site acme --json
|
|
32
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records search "globex" --site acme --json
|
|
33
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records create --site acme --object people --set firstName=Grace --set lastName=Hopper --set email=grace@globex.com --set company=<companyId> --json
|
|
34
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records update <id> --site acme --set jobTitle=CTO --json
|
|
35
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records delete <id> --site acme --json
|
|
36
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records restore <id> --site acme --json
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
- Filters: `--filter field:op:value`, repeatable. Ops: eq, neq, contains, notContains, empty, notEmpty, gt, gte, lt, lte, in, notIn, before, after, withinDays. Dates: `YYYY-MM-DD`, `today`, `+30d`. Also `id`, `ownerId`, `createdAt`, `updatedAt`.
|
|
@@ -46,13 +46,13 @@ More examples per object: references/records.md.
|
|
|
46
46
|
## Timeline and tasks
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
50
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
51
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
52
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
53
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
54
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
55
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
49
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 notes add <recordId> --site acme --body "Met at the expo; wants a demo in June." --json
|
|
50
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 activities add --site acme --type call --title "Discovery call" --record <personId> --record <dealId> --meta '{"durationMin":25}' --json
|
|
51
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 activities list --site acme --record <companyId> --related --json
|
|
52
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 tasks add --site acme --title "Send the proposal" --due 2026-11-10 --assignee me --record <dealId> --json
|
|
53
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 tasks list --site acme --assignee me --overdue --json
|
|
54
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 tasks done <taskId> --site acme --json
|
|
55
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 tasks reassign <taskId> --site acme --assignee sam@acme.com --json
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
Activity types: note, task, call, email, meeting. `--body @notes.md` reads a file.
|
|
@@ -62,18 +62,18 @@ Activity types: note, task, call, email, meeting. `--body @notes.md` reads a fil
|
|
|
62
62
|
People have a **photo** (`avatar` field) and companies a **logo** (`logo`), shown next to the name everywhere; custom objects get one by adding an `image` field (the first becomes the object's image). Files (any type: images, PDFs, Office documents…) attach to a record or to an activity (note, task, call, email, meeting).
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
66
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
67
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
68
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
69
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
70
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
71
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
72
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
73
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
74
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
75
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
76
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
65
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records image <personId> ./ada.jpg --site acme --json
|
|
66
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records image <companyId> ./logo.svg --site acme --json
|
|
67
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records image <personId> --remove --site acme --json
|
|
68
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 notes add <recordId> --body "Signed contract attached." --attach ./contract.pdf --site acme --json
|
|
69
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 tasks add --title "Review the quote" --record <dealId> --attach ./quote.xlsx --attach ./scope.pdf --site acme --json
|
|
70
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 activities add --type meeting --title "Workshop" --record <companyId> --attach ./whiteboard.png --site acme --json
|
|
71
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 files upload ./brochure.pdf ./photo.png --record <companyId> --site acme --json
|
|
72
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 files upload ./minutes.docx --activity <noteId> --site acme --json
|
|
73
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 files list --record <companyId> --related --site acme --json
|
|
74
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 files get <fileId> --out ./contract.pdf --site acme --json
|
|
75
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 files delete <fileId> --site acme --json
|
|
76
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 files usage --site acme --json
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
- Files live next to the data and are **encrypted with the same passphrase** on the journal backend; IndexedDB in local mode; the data repo (`files/`) for git-json (warn: history keeps them); Firebase Storage for Firebase (Storage must be enabled, see docs/files.md).
|
|
@@ -86,9 +86,9 @@ npx -y @fleox-agent-crm/agentcrm@0.3.0 files usage --site acme --json
|
|
|
86
86
|
## Pipelines
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
90
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
91
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
89
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 pipelines list --site acme --json
|
|
90
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 pipelines move <dealId> Negotiation --site acme --json
|
|
91
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 pipelines move <dealId> Lost --lost-reason "Budget" --site acme --json
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
Moving sets the deal's probability to the stage's. Adding / renaming stages is done in the admin (Settings → Data model).
|
|
@@ -102,10 +102,10 @@ See references/schema.md for objects, fields (types, options, relations), views,
|
|
|
102
102
|
Built-in modules: dashboard, deals (deals object + pipelines), reports, forms, tasks, automations, integrations (email and calendar), assistant (in-admin AI); records, search, settings, setup and customize are required. Installed extension modules are listed with `source: "extension"`. Disabling hides pages, navigation, widgets and owned objects for every user; it never deletes data, and enabling again brings everything back.
|
|
103
103
|
|
|
104
104
|
```bash
|
|
105
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
106
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
107
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
108
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
105
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 modules list --site acme --json
|
|
106
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 modules disable forms --site acme --json
|
|
107
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 modules disable forms --site acme --yes --json
|
|
108
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 modules enable deals --site acme --cascade --yes --json
|
|
109
109
|
```
|
|
110
110
|
|
|
111
111
|
- When the user says "we only manage contacts" or "hide what we don't use": list the modules, propose which to turn off (with what each hides), and apply only after they agree.
|
|
@@ -117,14 +117,14 @@ npx -y @fleox-agent-crm/agentcrm@0.3.0 modules enable deals --site acme --cascad
|
|
|
117
117
|
One accent color drives the whole palette (a 50 to 950 scale is generated). Applies live to every user.
|
|
118
118
|
|
|
119
119
|
```bash
|
|
120
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
121
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
122
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
123
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
124
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
125
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
126
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
127
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
120
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 appearance get --site acme --json
|
|
121
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 appearance presets --site acme --json
|
|
122
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 appearance set --site acme --accent "#0f766e" --neutral stone --radius lg --json
|
|
123
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 appearance preset ocean --site acme --yes --json
|
|
124
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 appearance logo ./logo.svg --site acme --yes --json
|
|
125
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 appearance favicon ./favicon.png --site acme --yes --json
|
|
126
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 appearance css ./brand.css --site acme --yes --json
|
|
127
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 appearance reset --site acme --json
|
|
128
128
|
```
|
|
129
129
|
|
|
130
130
|
- **Brand from a hex:** `appearance set --accent <hex>`, then pick `--neutral` by temperature (blue / teal brands: slate; warm brands: stone; otherwise zinc), `--buttons accent` for a colorful brand. **From a logo:** read the dominant non-gray color of the SVG (its `fill`) or the image, propose it as the accent, and upload the logo itself with `appearance logo`.
|
|
@@ -134,9 +134,9 @@ npx -y @fleox-agent-crm/agentcrm@0.3.0 appearance reset --site acme --json
|
|
|
134
134
|
## Extensions (installed modules and themes)
|
|
135
135
|
|
|
136
136
|
```bash
|
|
137
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
138
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
139
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
137
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 ext list --site acme --json
|
|
138
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 ext disable sales-goals --site acme --yes --json
|
|
139
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 ext enable sales-goals --site acme --yes --json
|
|
140
140
|
```
|
|
141
141
|
|
|
142
142
|
Installing, building or debugging extensions: the `agentcrm-extensions` skill. Installing runs third-party code with admin rights: always show the plan and ask. If the admin misbehaves after an extension change, `ext disable <id> --yes`, or open the admin with `?safe=1`; CLI commands accept `--safe` to skip extensions.
|
|
@@ -144,11 +144,11 @@ Installing, building or debugging extensions: the `agentcrm-extensions` skill. I
|
|
|
144
144
|
## Import and export
|
|
145
145
|
|
|
146
146
|
```bash
|
|
147
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
148
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
149
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
150
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
151
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
147
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 import csv contacts.csv --site acme --object people --json
|
|
148
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 import csv contacts.csv --site acme --object people --yes --json
|
|
149
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 export csv --site acme --object companies --out companies.csv --json
|
|
150
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 export json --site acme --out backup.json --json
|
|
151
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 export zip --site acme --out backup.zip --json
|
|
152
152
|
```
|
|
153
153
|
|
|
154
154
|
The import is a DRY RUN until `--yes`: read the report (mapping, per-row action, errors, new select options, companies to create) with the user before applying. Mapping, dedupe and coercion rules: references/import.md.
|
|
@@ -156,25 +156,25 @@ The import is a DRY RUN until `--yes`: read the report (mapping, per-row action,
|
|
|
156
156
|
## Reports and stats
|
|
157
157
|
|
|
158
158
|
```bash
|
|
159
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
160
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
161
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
162
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
163
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
164
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
165
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
166
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
159
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 report pipeline --site acme --json
|
|
160
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 report forecast --site acme --json
|
|
161
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 report won-lost --site acme --months 6 --json
|
|
162
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 report activity --site acme --days 30 --json
|
|
163
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 report lead-sources --site acme --json
|
|
164
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 report stale --site acme --days 21 --json
|
|
165
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 report conversion --site acme --json
|
|
166
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 stats --site acme --json
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
## Automations and lead forms
|
|
170
170
|
|
|
171
171
|
```bash
|
|
172
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
173
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
174
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
175
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
176
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
177
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
172
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 automations list --site acme --json
|
|
173
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 automations disable <id> --site acme --json
|
|
174
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 automations run --site acme --json
|
|
175
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 forms list --site acme --json
|
|
176
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 forms publish <formId> --site acme --json
|
|
177
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 forms ingest --site acme --json
|
|
178
178
|
```
|
|
179
179
|
|
|
180
180
|
Event automations (record created, field changed, stage changed) fire on every write, from the CLI too. Building automations and forms is done in the admin; the CLI enables / disables, runs the scheduled ones and ingests form submissions. For a cron, see the `agentcrm-manage` skill.
|
|
@@ -184,8 +184,8 @@ Event automations (record created, field changed, stage changed) fire on every w
|
|
|
184
184
|
The same tools the MCP server and the in-admin assistant expose, including the tools of enabled extension modules (`source: "extension"`) the customisation tools (`list_modules`, `set_module_enabled`, `get_appearance`, `set_appearance`, `apply_appearance_preset`, `list_extensions`, `set_extension_enabled`) and the file tools (`list_files`, `describe_attachments`):
|
|
185
185
|
|
|
186
186
|
```bash
|
|
187
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
188
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
187
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 tools list --site acme --json
|
|
188
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 tools call pipeline_summary --site acme --input '{}' --json
|
|
189
189
|
```
|
|
190
190
|
|
|
191
191
|
Useful when a tool returns exactly what you need in one call (`get_record` with relations and latest activities, `pipeline_summary`).
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
Changing a visual value marks the preset `custom`. Other actions:
|
|
19
19
|
|
|
20
20
|
- `appearance preset <id>`: default, ocean, forest, sunset, graphite, rose, high-contrast, or a theme extension id. Keeps logo, favicon, custom CSS and the default mode.
|
|
21
|
-
- `appearance logo <file>` / `appearance favicon <file>`: PNG, JPEG, GIF, WebP, SVG or ICO, at most 200 KB; `--remove` deletes it.
|
|
21
|
+
- `appearance logo <file>` / `appearance favicon <file>`: PNG, JPEG, GIF, WebP, SVG or ICO, at most 200 KB (SVGs with scripts or event handlers are refused); `--remove` deletes it.
|
|
22
22
|
- `appearance css <file|->`: plain CSS (no `<style>` / `<script>`), at most 50 KB, loaded last; `--remove` deletes it. Style through the CSS variables (`--acc-50` to `--acc-950`, `--srf-50` to `--srf-950`, `--primary`, `--radius-scale`, `--font-sans`, `--row-h`…) as `rgb(var(--acc-600))`.
|
|
23
23
|
- `appearance reset`: back to defaults, keeping logo and favicon (`--branding` removes them too).
|
|
24
24
|
- `appearance get --full` includes the logo / favicon data URLs and the custom CSS.
|
|
@@ -12,17 +12,17 @@ Always confirm with `objects get <object>`: admins add fields and options.
|
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
# A company and its contact
|
|
15
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
16
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
15
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records create --site acme --object companies --set name="Globex" --set domain=globex.com --set industry=software --json
|
|
16
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records create --site acme --object people --fields @grace.json --json
|
|
17
17
|
|
|
18
18
|
# A deal linked to both
|
|
19
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
19
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records create --site acme --object deals --fields '{"name":"Globex pilot","amount":12000,"closeDate":"2026-12-15","company":"<companyId>","contacts":["<personId>"]}' --json
|
|
20
20
|
|
|
21
21
|
# Leads created this week, without an owner
|
|
22
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
22
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records list --site acme --object people --filter lifecycleStage:eq:lead --filter createdAt:withinDays:-7 --filter ownerId:empty --json
|
|
23
23
|
|
|
24
24
|
# Assign an owner
|
|
25
|
-
npx -y @fleox-agent-crm/agentcrm@0.3.
|
|
25
|
+
npx -y @fleox-agent-crm/agentcrm@0.3.2 records update <id> --site acme --owner <userId> --json
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
`records get` returns `relations` (records this one points to) and `related` (records pointing to it, e.g. a company's people and deals) plus `activityCount`.
|