@erdoai/cli 0.111.0 → 0.114.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 +68 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -32,7 +32,7 @@ function describeRefreshWrites(strategy, mode, key, liveMode) {
|
|
|
32
32
|
import { readFileSync as readFileSync4 } from "fs";
|
|
33
33
|
import { basename } from "path";
|
|
34
34
|
import { password, select } from "@inquirer/prompts";
|
|
35
|
-
import { Command as Command2 } from "commander";
|
|
35
|
+
import { Command as Command2, Option as Option2 } from "commander";
|
|
36
36
|
|
|
37
37
|
// src/config.ts
|
|
38
38
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -1165,6 +1165,9 @@ var ErdoClient = class {
|
|
|
1165
1165
|
// separate program a human chose to run), which leaves the other carriers
|
|
1166
1166
|
// alone.
|
|
1167
1167
|
setDatasetPurpose(slug, input) {
|
|
1168
|
+
return this.updateDatasetSchema(slug, input);
|
|
1169
|
+
}
|
|
1170
|
+
updateDatasetSchema(slug, input) {
|
|
1168
1171
|
return this.request("POST", `/v1/datasets/${encodeURIComponent(slug)}/schema`, input);
|
|
1169
1172
|
}
|
|
1170
1173
|
// The endpoint's field is `question` (QueryDataNaturalLanguageInput). Sending // The endpoint's field is `question` (QueryDataNaturalLanguageInput). Sending
|
|
@@ -1293,6 +1296,15 @@ var ErdoClient = class {
|
|
|
1293
1296
|
input
|
|
1294
1297
|
);
|
|
1295
1298
|
}
|
|
1299
|
+
// Ends the lead's hold or close now, so the engine decides for it again on
|
|
1300
|
+
// its next pass. Answers the hold or close with resumed_at set.
|
|
1301
|
+
resumeLeadNextActions(datasetSlug, lead) {
|
|
1302
|
+
return this.request(
|
|
1303
|
+
"POST",
|
|
1304
|
+
`/v1/datasets/${encodeURIComponent(datasetSlug)}/leads/${encodeURIComponent(lead)}/next-actions/resume`,
|
|
1305
|
+
{}
|
|
1306
|
+
);
|
|
1307
|
+
}
|
|
1296
1308
|
// Everything the evaluation reads about one lead.
|
|
1297
1309
|
getLeadTimeline(datasetSlug, lead) {
|
|
1298
1310
|
return this.request(
|
|
@@ -6570,6 +6582,19 @@ datasetsCmd.command("ensure <purpose>").description(
|
|
|
6570
6582
|
fail(e);
|
|
6571
6583
|
}
|
|
6572
6584
|
});
|
|
6585
|
+
datasetsCmd.command("update-schema <slug>").description("Evolve an existing dataset's column contract. For populated lead-identity datasets, use add_column operations only; existing rows and lead ids are preserved.").requiredOption("--input <file>", "JSON request containing operations and optional class/purpose changes").action(async (slug, opts) => {
|
|
6586
|
+
try {
|
|
6587
|
+
const input = JSON.parse(readFileSync4(opts.input, "utf8"));
|
|
6588
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
6589
|
+
throw new Error("--input must contain a JSON object");
|
|
6590
|
+
}
|
|
6591
|
+
const result = await new ErdoClient().updateDatasetSchema(slug, input);
|
|
6592
|
+
console.log(JSON.stringify(result, null, 2));
|
|
6593
|
+
for (const warning of result.warnings ?? []) console.error(`warning: ${warning}`);
|
|
6594
|
+
} catch (e) {
|
|
6595
|
+
fail(e);
|
|
6596
|
+
}
|
|
6597
|
+
});
|
|
6573
6598
|
datasetsCmd.command("set-purpose <slug> [purpose]").description(
|
|
6574
6599
|
"Set (or with --clear, remove) the dataset's purpose \u2014 the org-vocabulary role `datasets purposes` reports. Use it to CORRECT a purpose that names the wrong dataset: one purpose maps to one dataset per org, so a purpose left on the wrong one points everything that resolves through the vocabulary at the wrong rows. Setting a purpose another dataset carries is an atomic MOVE: the old carrier is cleared in the same transaction, so one call on the right dataset lands it (the response says which dataset it moved from). Use --sibling only when deliberately running a parallel table for the same purpose."
|
|
6575
6600
|
).option("--clear", "remove the dataset's purpose instead of setting one").option(
|
|
@@ -7346,7 +7371,7 @@ leadPlaybookCmd.command("revision <revision>").description(
|
|
|
7346
7371
|
}
|
|
7347
7372
|
});
|
|
7348
7373
|
leadsCmd.command("timeline <dataset> <lead>").description(
|
|
7349
|
-
"Show everything the next-action evaluation reads about one lead: captures, sent emails, replies, SMS, calls, website chats, bookings and earlier suggestions in time order, plus the timing facts a follow-up rule matches on. <lead> is the canonical_lead_id UUID or the 22-character lead reference."
|
|
7374
|
+
"Show everything the next-action evaluation reads about one lead: their current and earlier answers, context-only row columns, captures, sent emails, replies, SMS, calls, website chats, bookings and earlier suggestions in time order, plus the timing facts a follow-up rule matches on. <lead> is the canonical_lead_id UUID or the 22-character lead reference."
|
|
7350
7375
|
).option("--json", "print the raw JSON result instead of a summary").action(async (dataset, lead, opts) => {
|
|
7351
7376
|
try {
|
|
7352
7377
|
const res = await new ErdoClient().getLeadTimeline(dataset, lead);
|
|
@@ -7357,6 +7382,31 @@ leadsCmd.command("timeline <dataset> <lead>").description(
|
|
|
7357
7382
|
console.log(`lead ${res.canonical_lead_id}`);
|
|
7358
7383
|
console.log(`reference ${res.lead_reference}`);
|
|
7359
7384
|
console.log(`dataset ${res.dataset_slug}`);
|
|
7385
|
+
if (res.details?.length) {
|
|
7386
|
+
console.log("\ndetails");
|
|
7387
|
+
printAlignedTable(
|
|
7388
|
+
["question", "answer", "source", "when", "quote"],
|
|
7389
|
+
res.details.flatMap((detail) => [
|
|
7390
|
+
[detail.label || detail.key, detail.value, detail.source_kind, detail.observed_at, detail.quote ?? ""],
|
|
7391
|
+
...(detail.earlier ?? []).map((earlier) => [
|
|
7392
|
+
"\u21B3 earlier",
|
|
7393
|
+
earlier.value,
|
|
7394
|
+
earlier.source_kind,
|
|
7395
|
+
earlier.observed_at,
|
|
7396
|
+
earlier.quote ?? ""
|
|
7397
|
+
])
|
|
7398
|
+
])
|
|
7399
|
+
);
|
|
7400
|
+
} else {
|
|
7401
|
+
console.log("\nNo lead details.");
|
|
7402
|
+
}
|
|
7403
|
+
if (res.context_columns?.length) {
|
|
7404
|
+
console.log("\ncontext columns (not lead answers)");
|
|
7405
|
+
printAlignedTable(
|
|
7406
|
+
["column", "value"],
|
|
7407
|
+
res.context_columns.map((column) => [column, res.row?.[column] ?? ""])
|
|
7408
|
+
);
|
|
7409
|
+
}
|
|
7360
7410
|
if (res.entries?.length) {
|
|
7361
7411
|
console.log("\nentries");
|
|
7362
7412
|
printAlignedTable(
|
|
@@ -7492,6 +7542,20 @@ leadNextActionsCmd.command("close <dataset> <lead>").description(
|
|
|
7492
7542
|
fail(e);
|
|
7493
7543
|
}
|
|
7494
7544
|
});
|
|
7545
|
+
leadNextActionsCmd.command("resume <dataset> <lead>").description(
|
|
7546
|
+
"End the lead's hold or close now, so Erdo works the lead again. Nothing is sent from here: Erdo decides for the lead on its next pass, within about fifteen minutes. Refused when the lead is not held or closed."
|
|
7547
|
+
).option("--json", "print the raw JSON result instead of a summary").action(async (dataset, lead, opts) => {
|
|
7548
|
+
try {
|
|
7549
|
+
const res = await new ErdoClient().resumeLeadNextActions(dataset, lead);
|
|
7550
|
+
if (opts.json) {
|
|
7551
|
+
print(res);
|
|
7552
|
+
return;
|
|
7553
|
+
}
|
|
7554
|
+
console.log(`Resumed lead ${res.lead_reference}: its ${res.action_kind} ended at ${res.resumed_at ?? "now"}. Erdo decides for it on its next pass.`);
|
|
7555
|
+
} catch (e) {
|
|
7556
|
+
fail(e);
|
|
7557
|
+
}
|
|
7558
|
+
});
|
|
7495
7559
|
leadNextActionsCmd.command("evaluate <dataset> <lead>").description(
|
|
7496
7560
|
"Dry-run the playbook on one lead: show the decision Erdo would make now, with the email or handoff it would write, the rule it cites and why. Nothing is stored and nothing is sent. --file tries a draft playbook instead of the saved one."
|
|
7497
7561
|
).option("-f, --file <path>", "a draft playbook text to evaluate with instead of the saved one").option("--agent-id <id>", "try the draft as that concierge, from `erdo voice agents`; only read alongside --file").option("--json", "print the raw JSON result instead of a summary").action(async (dataset, lead, opts) => {
|
|
@@ -8093,7 +8157,7 @@ autoCmd.command("run <id>").description("Trigger an automation now").action(asyn
|
|
|
8093
8157
|
fail(e);
|
|
8094
8158
|
}
|
|
8095
8159
|
});
|
|
8096
|
-
autoCmd.command("update <id>").description("Edit an automation \u2014 rename, reschedule, or replace its script/instructions").option("--name <name>", "New name").option("--description <text>", "New description").option("--instructions <text>", "Replacement instructions (agent automation)").option("--script-js <js>", "Replacement script body (scripted automation)").option(
|
|
8160
|
+
autoCmd.command("update <id>").description("Edit an automation \u2014 rename, reschedule, or replace its script/instructions").option("--name <name>", "New name").option("--description <text>", "New description").option("--instructions <text>", "Replacement instructions (agent automation)").addOption(new Option2("--agent-key <key>", "Executor for an agent automation; omit to keep current").choices(["erdo.heartbeat-executor", "erdo.workflow-executor"])).option("--script-js <js>", "Replacement script body (scripted automation)").option(
|
|
8097
8161
|
"--script-file <path>",
|
|
8098
8162
|
"Read the replacement script body from a file (scripted automation)"
|
|
8099
8163
|
).option("--interval <minutes>", "New interval in minutes (minimum 5)", (v) => parseInt(v, 10)).option("--timezone <tz>", "New scheduling timezone, e.g. America/New_York").action(
|
|
@@ -8108,6 +8172,7 @@ autoCmd.command("update <id>").description("Edit an automation \u2014 rename, re
|
|
|
8108
8172
|
name: opts.name,
|
|
8109
8173
|
description: opts.description,
|
|
8110
8174
|
instructions: opts.instructions,
|
|
8175
|
+
agent_key: opts.agentKey,
|
|
8111
8176
|
script_js: scriptJs,
|
|
8112
8177
|
interval_minutes: opts.interval,
|
|
8113
8178
|
timezone: opts.timezone
|