@letterstory/cli 0.70.0 → 0.70.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 +4 -0
- package/lib/cli.mjs +5 -3
- package/lib/commands/admin.mjs +8 -1
- package/lib/commands/outbound.mjs +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -398,6 +398,10 @@ export LETTERSTORY_STAFF_API_KEY=<your staff key with crm:read,crm:write>
|
|
|
398
398
|
letterstory admin crm signals --status new # the Inbound feed (unmatched signals)
|
|
399
399
|
letterstory admin crm record --source bookface --kind message \
|
|
400
400
|
--title "Asked about phantoms on Bookface" --name "Jane Doe" --company Acme --domain acme.com
|
|
401
|
+
# Re-running that is a no-op: with no --external-id the intake derives an idempotency key from
|
|
402
|
+
# the signal's content, so a retried agent loop cannot fill the feed with the same observation.
|
|
403
|
+
# Pass --external-id when the source has a stable id (a thread id, a tweet id), or to record that
|
|
404
|
+
# an otherwise identical signal happened AGAIN.
|
|
401
405
|
letterstory admin crm record --source twitter --kind social_engagement \
|
|
402
406
|
--title "Liked our launch tweet" --name "Pat" --linkedin https://linkedin.com/in/pat
|
|
403
407
|
letterstory admin crm signal <signal-id> qualify # link/create the account
|
package/lib/cli.mjs
CHANGED
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
} from "./commands.mjs";
|
|
57
57
|
|
|
58
58
|
// Keep in sync with cli/package.json.
|
|
59
|
-
export const VERSION = "0.70.
|
|
59
|
+
export const VERSION = "0.70.2";
|
|
60
60
|
|
|
61
61
|
// Flags that never take a value. Listing them explicitly means `deploy get --json <id>`
|
|
62
62
|
// can't accidentally swallow the id as --json's value.
|
|
@@ -826,13 +826,15 @@ Sequences (multi-step cold email sent from your mailers; approving or enrolling
|
|
|
826
826
|
sequences get <sequence-id> Flow, enrollments, who replied at each step
|
|
827
827
|
sequences create --name <n> (--flow '<json>'|--flow-file <path>) [--mailer <mailer-id>]...
|
|
828
828
|
[--[no-]opt-out-footer] [--[no-]postal-address-footer] [--[no-]unsubscribe-links] [--[no-]detect-reply-opt-outs]
|
|
829
|
-
[--[no-]test-mode] [--
|
|
829
|
+
[--[no-]test-mode] [--default-lede <fallback opener line>]
|
|
830
|
+
[--send-window-start <HH:MM>] [--send-window-end <HH:MM>] [--send-window-timezone <IANA tz>]
|
|
830
831
|
New draft sequence (nothing sends yet; rails default on, opt-out line off;
|
|
831
832
|
sends 9:00-17:00 in each recipient's inferred timezone, else the sender's)
|
|
832
833
|
sequences update <sequence-id> [--name <n>] [--flow '<json>'|--flow-file <path>]
|
|
833
834
|
[--status draft|active|paused|archived] [--mailer <mailer-id>]...
|
|
834
835
|
[--[no-]opt-out-footer] [--[no-]postal-address-footer] [--[no-]unsubscribe-links] [--[no-]detect-reply-opt-outs]
|
|
835
|
-
[--[no-]test-mode] [--
|
|
836
|
+
[--[no-]test-mode] [--default-lede <fallback opener line>]
|
|
837
|
+
[--send-window-start <HH:MM>] [--send-window-end <HH:MM>] [--send-window-timezone <IANA tz>]
|
|
836
838
|
--test-mode (internal accounts only): walks as live, sends nothing
|
|
837
839
|
sequences pause|resume <sequence-id> Stop / restart sending
|
|
838
840
|
sequences enroll <sequence-id> (--list <list-id> | --email <addr>... | --recipients '<json>'|--recipients-file <path>)
|
package/lib/commands/admin.mjs
CHANGED
|
@@ -1795,8 +1795,15 @@ async function cmdAdminCrm(ctx) {
|
|
|
1795
1795
|
});
|
|
1796
1796
|
if (!body.title)
|
|
1797
1797
|
throw new CliError(
|
|
1798
|
-
'Usage: admin crm record --title "Liked our launch tweet" [--source twitter] [--kind social_engagement] …'
|
|
1798
|
+
'Usage: admin crm record --title "Liked our launch tweet" [--source twitter] [--kind social_engagement] [--external-id <id>] …'
|
|
1799
1799
|
);
|
|
1800
|
+
// No local default for --external-id on purpose. The intake derives one
|
|
1801
|
+
// from the signal's content when none is sent (deriveExternalId in
|
|
1802
|
+
// src/lib/crm/signals-intake.ts), so a re-run is already a no-op and the
|
|
1803
|
+
// rule lives in ONE place. Computing a second fingerprint here would be a
|
|
1804
|
+
// copy that drifts, and it would differ from what a webhook or any other
|
|
1805
|
+
// agent sends for the same observation. Pass --external-id when the source
|
|
1806
|
+
// has a stable id of its own, or to say "this happened again".
|
|
1800
1807
|
const r = await staffPost(ctx, `${CRM}/signals`, body);
|
|
1801
1808
|
return out(r, (x) => `${x.duplicate ? "already recorded" : "recorded"}: ${signalLine(x.signal)}`);
|
|
1802
1809
|
}
|
|
@@ -61,6 +61,8 @@ const SEQUENCE_RAIL_ARGS = {
|
|
|
61
61
|
detect_reply_opt_outs: { flag: "detect-reply-opt-outs", type: "bool", negate: "no-detect-reply-opt-outs" },
|
|
62
62
|
// Staff-only to turn on (the server refuses it for anyone else): walks as live, sends nothing.
|
|
63
63
|
test_mode: { flag: "test-mode", type: "bool", negate: "no-test-mode" },
|
|
64
|
+
// The fallback opener line for recipients with no opener (blank clears it on update).
|
|
65
|
+
default_lede: "default-lede",
|
|
64
66
|
};
|
|
65
67
|
|
|
66
68
|
// A send-window edge from --<flag> HH:MM (or a raw minute of day) → the
|