conduyt 1.71.0 → 1.72.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 +12 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2121,6 +2121,10 @@ messages
|
|
|
2121
2121
|
})}`);
|
|
2122
2122
|
}));
|
|
2123
2123
|
// ---- appointments ----
|
|
2124
|
+
/** (app 10-13) a booking can name the deal (card) it came from */
|
|
2125
|
+
const APPOINTMENT_DEAL_NOTE = " contactId is looked up as a contact of your account first; when no contact has that id it is looked up as a deal (card), so a deal id may be passed there. dealId names the deal explicitly. A named deal must be open, in your account, and visible AND editable to the key (deals scope; seeing it is not enough): the appointment takes the deal's contact, is linked to the deal, and appointment.booked carries dealId; no other card is created. Errors: 400 deal_id_conflict / deal_contact_mismatch / invalid_deal_id / contact_not_found (contactId is neither a contact nor a deal you can use), 404 deal_not_found / deal_deleted, 403 deal_not_editable (you can see the deal but not change it), 409 deal_closed, 409 deal_contact_gone (the deal's contact was merged or deleted), 409 deal_changed (the deal moved to another contact while booking: retry the request).";
|
|
2126
|
+
/** (app 10-13) the catalog does not carry automation action config: find_opportunity v2, link_appointment_to_deal, update_deal_field systemField source */
|
|
2127
|
+
const DEAL_NODES_NOTE = " Deal nodes: find_opportunity config {version: 2, pipelineIds (ordered; the first pipeline holding a match wins; empty = every pipeline), status (open default | won | lost | abandoned | any), excludeSources (lead sources never matched, case-insensitive), excludeCreatedByAutomationIds (automations whose create_deal cards are skipped; cards created from 2026-10-13 on), matchField {fieldKey, value} (searches the WHOLE WORKSPACE, any contact, for the card whose deal custom field equals the value, merge fields allowed e.g. {{trigger.oes}}; a card is found when its field holds the searched value (trimmed) as the same text exactly (no case folding); a value written with separators such as dashes or spaces also matches its digits as text; it matches a stored number only when the value (or those digits) is a plain number with no leading zero and at most 15 significant digits that a number holds exactly (007 is text and does not match the number 7; a 16-digit value, 1e-400 or 3e-324 is text only); booleans and differently formatted stored values never match; status, pipelines and exclusions still apply; exactly one match is found, several are ambiguous and take not found; a found card becomes the run's contact when the run has none; the field must exist; an empty rendered value finds nothing), resolution}: searches the run's contact's cards; FOUND makes the card the run's deal and follows nextIfTrue (else next), NOT FOUND is a normal outcome that follows nextIfFalse (else next) and leaves the run's existing deal unchanged; without version 2 the step keeps the original single-pipeline lookup (a miss fails the step). Prerequisite: a version 2 find needs step cursors on this workspace; publishing refuses (find_needs_step_cursors) with \"Find opportunity needs step cursors on this workspace; ask support\", so a workflow can validate and import yet fail at publish; every version 2 find must hold its own live step cursor or it hard-stops the run without selecting or routing. A version 2 find cannot be retried on its own: retrying a failed one alone answers 409, so re-trigger the automation for the contact. An automation definition that touches deals needs the `deals` scope on an API key (403 without it). link_appointment_to_deal config {stageId, pipelineId (needs stageId), lostReason}: in an appointment-triggered run, links the trigger's appointment to the run's deal (its appointment fields follow it; a newer booking is never displaced; the appointment must be the deal's contact's), then optionally moves the card; it needs an appointment trigger and the run's deal (find_opportunity first, or a booking made with a deal id). update_deal_field config {systemField: \"source\", value, overwriteExisting}: sets the deal's own lead source instead of a custom field (a value only, trimmed, at most 500 characters; overwriteExisting false writes only while the source is the Unknown label).";
|
|
2124
2128
|
const appointments = program.command("appointments").description("Manage appointments");
|
|
2125
2129
|
appointments
|
|
2126
2130
|
.command("list")
|
|
@@ -2154,13 +2158,14 @@ appointments
|
|
|
2154
2158
|
}));
|
|
2155
2159
|
appointments
|
|
2156
2160
|
.command("create")
|
|
2157
|
-
.description("Create an appointment. --start/--end must be ISO-8601 WITH a timezone offset (e.g. 2026-07-10T15:00:00-07:00)")
|
|
2161
|
+
.description("Create an appointment. --start/--end must be ISO-8601 WITH a timezone offset (e.g. 2026-07-10T15:00:00-07:00)." + APPOINTMENT_DEAL_NOTE)
|
|
2158
2162
|
.option("--title <title>", "title (required)")
|
|
2159
2163
|
.option("--start <iso>", "start time, ISO-8601 with tz offset (required)")
|
|
2160
2164
|
.option("--end <iso>", "end time, ISO-8601 with tz offset (required)")
|
|
2161
2165
|
.option("--description <text>", "description")
|
|
2162
2166
|
.option("--calendar <id>", "calendar UUID")
|
|
2163
|
-
.option("--contact <id>", "contact UUID")
|
|
2167
|
+
.option("--contact <id>", "contact UUID, or a deal UUID (looked up as a deal when no contact has it)")
|
|
2168
|
+
.option("--deal <id>", "deal UUID: book for this deal (card; open, visible and editable to you); the appointment takes its contact and is linked to it")
|
|
2164
2169
|
.option("--assigned <id>", "assignee user UUID")
|
|
2165
2170
|
.option("--location <location>", "location")
|
|
2166
2171
|
.option("--status <status>", "status (default confirmed)")
|
|
@@ -2179,6 +2184,8 @@ appointments
|
|
|
2179
2184
|
body.calendarId = opts.calendar;
|
|
2180
2185
|
if (opts.contact !== undefined)
|
|
2181
2186
|
body.contactId = opts.contact;
|
|
2187
|
+
if (opts.deal !== undefined)
|
|
2188
|
+
body.dealId = opts.deal;
|
|
2182
2189
|
if (opts.assigned !== undefined)
|
|
2183
2190
|
body.assignedTo = opts.assigned;
|
|
2184
2191
|
if (opts.location !== undefined)
|
|
@@ -2331,13 +2338,13 @@ automations
|
|
|
2331
2338
|
}));
|
|
2332
2339
|
automations
|
|
2333
2340
|
.command("validate")
|
|
2334
|
-
.description("Validate a workflow graph before saving. Provide the body via --json or --file (needs triggerEvent + graph). A delay node waits for a fixed duration by default; waitType \"until_field_date\" (with fieldKey = a deal DATE / DATETIME custom field key and offsetHours = signed hours added to its date, default 0, e.g. 24 = a day after it) waits until that date stored on the deal, re-read at every wake (an empty or past value continues immediately). Card ownership per lane: assign_to_user config {userId | userIds (round robin) | groupId, target|applyTo: contact|deal|both, overwriteExisting, laneSource, lanePipelineId, laneStageId}: laneSource names a card lane (the Deal.source its Auto-Create step wrote, e.g. \"GSM\", max 500 chars) and makes the deal leg assign the contact's newest OPEN card from that lane (inside lanePipelineId when set) instead of the run's deal; when the contact has none and lanePipelineId is set, the card is created there (laneStageId, else the pipeline's first stage) already owned by the user; lanePipelineId or laneStageId without laneSource, or laneStageId without lanePipelineId, is refused; a lane never applies to an Assign-to-contact step. create_deal config {pipelineId (required), stageId, dealName, dealValue, allowDuplicates, status, source, assignedTo, leaveUnassigned}: leaveUnassigned true leaves the card unassigned when no assignee is set (default false: the card goes to the lead's owner). close_other_open_deals config {lostReason (required)}: closes the contact's OTHER open cards as lost with that reason, keeping the run's own card (each moves to its pipeline's lost stage with the usual stage-change effects; cards already won/lost, in the DPP Post-Close pipeline or in a pipeline with no lost stage are skipped; a re-run closes nothing twice); it needs the run's own deal, so use a deal trigger or a find_opportunity step first." + AUTOMATION_KEY_REFUSALS_NOTE)
|
|
2341
|
+
.description("Validate a workflow graph before saving. Provide the body via --json or --file (needs triggerEvent + graph). A delay node waits for a fixed duration by default; waitType \"until_field_date\" (with fieldKey = a deal DATE / DATETIME custom field key and offsetHours = signed hours added to its date, default 0, e.g. 24 = a day after it) waits until that date stored on the deal, re-read at every wake (an empty or past value continues immediately). Card ownership per lane: assign_to_user config {userId | userIds (round robin) | groupId, target|applyTo: contact|deal|both, overwriteExisting, laneSource, lanePipelineId, laneStageId}: laneSource names a card lane (the Deal.source its Auto-Create step wrote, e.g. \"GSM\", max 500 chars) and makes the deal leg assign the contact's newest OPEN card from that lane (inside lanePipelineId when set) instead of the run's deal; when the contact has none and lanePipelineId is set, the card is created there (laneStageId, else the pipeline's first stage) already owned by the user; lanePipelineId or laneStageId without laneSource, or laneStageId without lanePipelineId, is refused; a lane never applies to an Assign-to-contact step. create_deal config {pipelineId (required), stageId, dealName, dealValue, allowDuplicates, status, source, assignedTo, leaveUnassigned}: leaveUnassigned true leaves the card unassigned when no assignee is set (default false: the card goes to the lead's owner). close_other_open_deals config {lostReason (required)}: closes the contact's OTHER open cards as lost with that reason, keeping the run's own card (each moves to its pipeline's lost stage with the usual stage-change effects; cards already won/lost, in the DPP Post-Close pipeline or in a pipeline with no lost stage are skipped; a re-run closes nothing twice); it needs the run's own deal, so use a deal trigger or a find_opportunity step first." + DEAL_NODES_NOTE + AUTOMATION_KEY_REFUSALS_NOTE)
|
|
2335
2342
|
.option("--json <json>", "full request body as JSON")
|
|
2336
2343
|
.option("--file <path>", "read the request body from a JSON file")
|
|
2337
2344
|
.action(run(async (client, opts) => client.post("/api/v1/automations/validate", bodyFromJsonOrFile(opts))));
|
|
2338
2345
|
automations
|
|
2339
2346
|
.command("import")
|
|
2340
|
-
.description("Create a workflow (with optional name resolution). Provide the body via --json or --file (needs name + triggerEvent + graph). A sequence step is the action enroll_in_sequence with config {sequenceId, enrollAction: add (default) | remove}; add needs the sequence to allow automation enrollment. A delay node waits for a fixed duration by default; waitType \"until_field_date\" (with fieldKey = a deal DATE / DATETIME custom field key and offsetHours = signed hours added to its date, default 0, e.g. 24 = a day after it) waits until that date stored on the deal, re-read at every wake (an empty or past value continues immediately). Card ownership per lane: assign_to_user config {userId | userIds (round robin) | groupId, target|applyTo: contact|deal|both, overwriteExisting, laneSource, lanePipelineId, laneStageId}: laneSource names a card lane (the Deal.source its Auto-Create step wrote, e.g. \"GSM\", max 500 chars) and makes the deal leg assign the contact's newest OPEN card from that lane (inside lanePipelineId when set) instead of the run's deal; when the contact has none and lanePipelineId is set, the card is created there (laneStageId, else the pipeline's first stage) already owned by the user; lanePipelineId or laneStageId without laneSource, or laneStageId without lanePipelineId, is refused; a lane never applies to an Assign-to-contact step. create_deal config {pipelineId (required), stageId, dealName, dealValue, allowDuplicates, status, source, assignedTo, leaveUnassigned}: leaveUnassigned true leaves the card unassigned when no assignee is set (default false: the card goes to the lead's owner). close_other_open_deals config {lostReason (required)}: closes the contact's OTHER open cards as lost with that reason, keeping the run's own card (each moves to its pipeline's lost stage with the usual stage-change effects; cards already won/lost, in the DPP Post-Close pipeline or in a pipeline with no lost stage are skipped; a re-run closes nothing twice); it needs the run's own deal, so use a deal trigger or a find_opportunity step first." + AUTOMATION_KEY_REFUSALS_NOTE)
|
|
2347
|
+
.description("Create a workflow (with optional name resolution). Provide the body via --json or --file (needs name + triggerEvent + graph). A sequence step is the action enroll_in_sequence with config {sequenceId, enrollAction: add (default) | remove}; add needs the sequence to allow automation enrollment. A delay node waits for a fixed duration by default; waitType \"until_field_date\" (with fieldKey = a deal DATE / DATETIME custom field key and offsetHours = signed hours added to its date, default 0, e.g. 24 = a day after it) waits until that date stored on the deal, re-read at every wake (an empty or past value continues immediately). Card ownership per lane: assign_to_user config {userId | userIds (round robin) | groupId, target|applyTo: contact|deal|both, overwriteExisting, laneSource, lanePipelineId, laneStageId}: laneSource names a card lane (the Deal.source its Auto-Create step wrote, e.g. \"GSM\", max 500 chars) and makes the deal leg assign the contact's newest OPEN card from that lane (inside lanePipelineId when set) instead of the run's deal; when the contact has none and lanePipelineId is set, the card is created there (laneStageId, else the pipeline's first stage) already owned by the user; lanePipelineId or laneStageId without laneSource, or laneStageId without lanePipelineId, is refused; a lane never applies to an Assign-to-contact step. create_deal config {pipelineId (required), stageId, dealName, dealValue, allowDuplicates, status, source, assignedTo, leaveUnassigned}: leaveUnassigned true leaves the card unassigned when no assignee is set (default false: the card goes to the lead's owner). close_other_open_deals config {lostReason (required)}: closes the contact's OTHER open cards as lost with that reason, keeping the run's own card (each moves to its pipeline's lost stage with the usual stage-change effects; cards already won/lost, in the DPP Post-Close pipeline or in a pipeline with no lost stage are skipped; a re-run closes nothing twice); it needs the run's own deal, so use a deal trigger or a find_opportunity step first." + DEAL_NODES_NOTE + AUTOMATION_KEY_REFUSALS_NOTE)
|
|
2341
2348
|
.option("--json <json>", "full request body as JSON")
|
|
2342
2349
|
.option("--file <path>", "read the request body from a JSON file")
|
|
2343
2350
|
.option("--resolve-names", "set resolveNames=true so name fields in node configs are converted to ids")
|
|
@@ -2365,7 +2372,7 @@ automations
|
|
|
2365
2372
|
}));
|
|
2366
2373
|
automations
|
|
2367
2374
|
.command("publish <id>")
|
|
2368
|
-
.description("Publish a draft workflow to live. The API binds a publish to the draft you reviewed and answers 409 without its configRevision, so this reads GET /automations/<id> and POSTs its configRevision as expectedConfigRevision (--expected-config-revision N uses the revision you reviewed and skips the read; a draft changed since then is refused 409). A draft holding an action config key the action does not read, or an unregistered action type, is refused 422 with code unknown_action_config_key / unknown_action_type listed in data.errors (with a \"Did you mean\" suggestion); the error text prints the whole refusal")
|
|
2375
|
+
.description("Publish a draft workflow to live. The API binds a publish to the draft you reviewed and answers 409 without its configRevision, so this reads GET /automations/<id> and POSTs its configRevision as expectedConfigRevision (--expected-config-revision N uses the revision you reviewed and skips the read; a draft changed since then is refused 409). A draft holding an action config key the action does not read, or an unregistered action type, is refused 422 with code unknown_action_config_key / unknown_action_type listed in data.errors (with a \"Did you mean\" suggestion); the error text prints the whole refusal. A workflow with a find_opportunity version 2 step is refused 422 find_needs_step_cursors unless the workspace has step cursors (\"Find opportunity needs step cursors on this workspace; ask support\"); validate and import do not check this")
|
|
2369
2376
|
.option("--expected-config-revision <n>", "the configRevision of the draft you reviewed (from `automations` read / GET /automations/<id>); omit to read the current one")
|
|
2370
2377
|
.action(run(async (client, id, opts) => {
|
|
2371
2378
|
assertUuid(id, "automation id");
|
package/package.json
CHANGED