@opsrev/acculynx-cli 1.14.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +45 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -102,9 +102,16 @@ async function scanJobs(client, filters) {
|
|
|
102
102
|
});
|
|
103
103
|
return { jobs, scanned: fetched.length, serverCount, complete, ...pageError ? { pageError } : {} };
|
|
104
104
|
}
|
|
105
|
-
var ENRICHERS = ["financials", "reps", "dates"];
|
|
105
|
+
var ENRICHERS = ["financials", "reps", "dates", "messages"];
|
|
106
106
|
var asRecord = (v) => v !== null && typeof v === "object" ? v : {};
|
|
107
|
-
async function
|
|
107
|
+
async function defaultLoadMessagesTool() {
|
|
108
|
+
const { createRequire: createRequire2 } = await import("module");
|
|
109
|
+
const require3 = createRequire2(import.meta.url);
|
|
110
|
+
const resolved = require3.resolve("@opsrev/acculynx-cli-unofficial");
|
|
111
|
+
const mod = await import(resolved);
|
|
112
|
+
return mod.handleExtendedToolCall;
|
|
113
|
+
}
|
|
114
|
+
async function enrichJobs(client, jobs, enrich, concurrency = 5, deps = {}) {
|
|
108
115
|
let userNames = /* @__PURE__ */ new Map();
|
|
109
116
|
if (enrich.includes("reps")) {
|
|
110
117
|
try {
|
|
@@ -114,6 +121,8 @@ async function enrichJobs(client, jobs, enrich, concurrency = 5) {
|
|
|
114
121
|
}
|
|
115
122
|
}
|
|
116
123
|
const nameOf = (id) => userNames.get(String(id)) || String(id ?? "").slice(0, 8);
|
|
124
|
+
let messagesToolPromise = null;
|
|
125
|
+
const getMessagesTool = () => messagesToolPromise ??= (deps.loadMessagesTool ?? defaultLoadMessagesTool)();
|
|
117
126
|
const out = jobs.map((job) => ({ job, errors: [] }));
|
|
118
127
|
let next = 0;
|
|
119
128
|
async function enrichOne(entry) {
|
|
@@ -143,6 +152,17 @@ async function enrichJobs(client, jobs, enrich, concurrency = 5) {
|
|
|
143
152
|
name: String(i.name ?? ""),
|
|
144
153
|
date: String(i.date ?? "")
|
|
145
154
|
}));
|
|
155
|
+
} else if (source === "messages") {
|
|
156
|
+
const tool = await getMessagesTool();
|
|
157
|
+
const res = await tool({ name: "acculynx_jobs_messages", args: { jobId } });
|
|
158
|
+
const text = String(res.content?.[0]?.text ?? "");
|
|
159
|
+
if (res.isError) throw new Error(text.slice(0, 200) || "messages tool error");
|
|
160
|
+
const data = asRecord(JSON.parse(text || "{}"));
|
|
161
|
+
entry.messages = (data.messages ?? []).slice(0, 3).map((msg) => ({
|
|
162
|
+
date: String(msg.createdDate ?? ""),
|
|
163
|
+
by: String(msg.createdBy ?? ""),
|
|
164
|
+
text: String(msg.message ?? "").replace(/\s+/g, " ").trim().slice(0, 200)
|
|
165
|
+
}));
|
|
146
166
|
}
|
|
147
167
|
} catch (error) {
|
|
148
168
|
entry.errors.push({ jobId, source, message: error instanceof Error ? error.message : String(error) });
|
|
@@ -211,6 +231,14 @@ function headerLine2(report) {
|
|
|
211
231
|
}
|
|
212
232
|
return line;
|
|
213
233
|
}
|
|
234
|
+
function messagesLine(entry, enrich) {
|
|
235
|
+
if (!enrich.includes("messages")) return null;
|
|
236
|
+
if (entry.errors.some((e) => e.source === "messages")) return " note ERR:messages";
|
|
237
|
+
const m = entry.messages?.[0];
|
|
238
|
+
if (!m) return " note: -";
|
|
239
|
+
const text = m.text.slice(0, 110) || "-";
|
|
240
|
+
return ` note ${mmdd(m.date)} ${m.by || "-"}: ${text}`;
|
|
241
|
+
}
|
|
214
242
|
function jobLine(entry, enrich) {
|
|
215
243
|
const job = entry.job;
|
|
216
244
|
const id8 = String(job.id ?? "").slice(0, 8);
|
|
@@ -245,11 +273,23 @@ function jobLine(entry, enrich) {
|
|
|
245
273
|
}
|
|
246
274
|
function formatScanDigest(report) {
|
|
247
275
|
const lines = [headerLine1(report), headerLine2(report)];
|
|
248
|
-
for (const entry of report.jobs)
|
|
276
|
+
for (const entry of report.jobs) {
|
|
277
|
+
lines.push(jobLine(entry, report.enrich));
|
|
278
|
+
const note = messagesLine(entry, report.enrich);
|
|
279
|
+
if (note !== null) lines.push(note);
|
|
280
|
+
}
|
|
249
281
|
const allErrors = report.jobs.flatMap((j) => j.errors);
|
|
250
282
|
if (allErrors.length > 0) {
|
|
251
283
|
lines.push("errors:");
|
|
252
|
-
|
|
284
|
+
const groups = /* @__PURE__ */ new Map();
|
|
285
|
+
for (const e of allErrors) {
|
|
286
|
+
const key = `${e.source}: ${e.message}`;
|
|
287
|
+
const ids = groups.get(key) ?? [];
|
|
288
|
+
ids.push(e.jobId.slice(0, 8));
|
|
289
|
+
groups.set(key, ids);
|
|
290
|
+
}
|
|
291
|
+
for (const [key, ids] of groups)
|
|
292
|
+
lines.push(ids.length > 3 ? ` ${key} (${ids.length} jobs)` : ` ${ids.join(",")} ${key}`);
|
|
253
293
|
}
|
|
254
294
|
return lines.join("\n");
|
|
255
295
|
}
|
|
@@ -278,7 +318,7 @@ function registerJobsCommands(parentCmd, getClient2) {
|
|
|
278
318
|
});
|
|
279
319
|
console.log(JSON.stringify(result));
|
|
280
320
|
});
|
|
281
|
-
jobs.command("scan").description("Fetch ALL matching jobs and print a digest with a coverage receipt").option("--start-date <date>", "Start date (YYYY-MM-DD)").option("--end-date <date>", "End date (YYYY-MM-DD)").option("--date-filter-type <type>", "Date field to filter on").option("--milestones <milestones>", "Filter by milestones (comma-separated)").option("--assignment <type>", "Filter by assignment: assigned, unassigned").option("--trade-type <name>", "Client-side trade-type filter (repeatable)", collect, []).option("--enrich <list>", "Comma-separated: financials,reps,dates").option("--format <fmt>", "digest or jsonl", "digest").option("--out <path>", "Also write full jsonl to this file").action(async (opts) => {
|
|
321
|
+
jobs.command("scan").description("Fetch ALL matching jobs and print a digest with a coverage receipt").option("--start-date <date>", "Start date (YYYY-MM-DD)").option("--end-date <date>", "End date (YYYY-MM-DD)").option("--date-filter-type <type>", "Date field to filter on").option("--milestones <milestones>", "Filter by milestones (comma-separated)").option("--assignment <type>", "Filter by assignment: assigned, unassigned").option("--trade-type <name>", "Client-side trade-type filter (repeatable)", collect, []).option("--enrich <list>", "Comma-separated: financials,reps,dates,messages").option("--format <fmt>", "digest or jsonl", "digest").option("--out <path>", "Also write full jsonl to this file").action(async (opts) => {
|
|
282
322
|
const enrich = String(opts.enrich ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
283
323
|
const badEnricher = enrich.find((e) => !ENRICHERS.includes(e));
|
|
284
324
|
if (badEnricher) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opsrev/acculynx-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"description": "AccuLynx MCP server & CLI — use the AccuLynx roofing CRM in Claude Desktop, Cursor, and any MCP client. Also a JSON CLI for scripts and AI agents.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|