@letterstory/cli 0.120.0 → 0.121.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/lib/cli.mjs +5 -2
- package/lib/commands/admin.mjs +25 -3
- package/package.json +1 -1
package/lib/cli.mjs
CHANGED
|
@@ -60,7 +60,7 @@ import {
|
|
|
60
60
|
} from "./commands.mjs";
|
|
61
61
|
|
|
62
62
|
// Keep in sync with cli/package.json.
|
|
63
|
-
export const VERSION = "0.
|
|
63
|
+
export const VERSION = "0.121.0";
|
|
64
64
|
|
|
65
65
|
// Flags that never take a value. Listing them explicitly means `deploy get --json <id>`
|
|
66
66
|
// can't accidentally swallow the id as --json's value. Every `type: "bool"` flag (and its
|
|
@@ -100,6 +100,8 @@ export const BOOLEAN_FLAGS = new Set([
|
|
|
100
100
|
"dry-run",
|
|
101
101
|
// admin crm record-outcome --draft
|
|
102
102
|
"draft",
|
|
103
|
+
// admin crm reach-outs --fresh
|
|
104
|
+
"fresh",
|
|
103
105
|
"prune",
|
|
104
106
|
// org git sync --force
|
|
105
107
|
"force",
|
|
@@ -769,7 +771,7 @@ Admin (STAFF key — --staff-key / LETTERSTORY_STAFF_API_KEY; acts before an org
|
|
|
769
771
|
| import <file.csv> [--vendor Concentrate] [--area A] [--ledger-key K] [--dry-run]
|
|
770
772
|
| import <file.csv> [--vendor Concentrate] [--area A] [--keep-ledger-key] [--dry-run]
|
|
771
773
|
| usage <events.json> per-call costs as kernels/lettertrace push them
|
|
772
|
-
| remove <entry-id> | services | service <slug> [--owner …] [--monthly N|none] [--renewal D]
|
|
774
|
+
| remove <entry-id> | services | service <slug> [--owner …] [--monthly N|none] [--renewal D] [--units N|none]
|
|
773
775
|
Where Letter's money goes (spending.letter.dev):
|
|
774
776
|
totals, run rate, area/vendor/provider/model/
|
|
775
777
|
key/operation/org breakdowns, every number's
|
|
@@ -795,6 +797,7 @@ Admin (STAFF key — --staff-key / LETTERSTORY_STAFF_API_KEY; acts before an org
|
|
|
795
797
|
[--at ISO] [--mrr-before N] [--mrr-after N] [--note "…"] [--save-offer …]
|
|
796
798
|
[--save-result …] [--draft]
|
|
797
799
|
| renewals [--days 90]
|
|
800
|
+
| reach-outs [--day YYYY-MM-DD] [--fresh] the day's reach-outs, N of 5 (#crm-reminders' count)
|
|
798
801
|
| track-record [--since YYYY-MM-DD] | at-risk | expansion-signals
|
|
799
802
|
| case <account-id> [--outcome <outcome-id>]
|
|
800
803
|
| onboard <account-id> --domain acme.com [--name "Acme"] [--site "<direction>"]… [--sites N]
|
package/lib/commands/admin.mjs
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// The old names — evals, eval-add, eval-set, proposals, propose-eval, capture-eval, reject-eval — still work.)
|
|
15
15
|
// admin evals scoreboard|cases|runs|run|triage|guard|retire … (fleet:read / tuning:experiment)
|
|
16
16
|
// admin fleet-experiments list|articles|clients|mark|unmark|new|assign|assign-eligible|assign-orgs|spin-up|apply|start|stop|decide … (fleet:read / fleet:experiment)
|
|
17
|
-
// admin crm import|capture|outreach|signals|record|signal|accounts|account|score|slack-channels|link-slack|white-glove|set-white-glove|churn|revenue|record-churn|draft-churn-reason|undo-churn|outcomes|record-outcome|renewals|track-record|at-risk|expansion-signals|case|onboard|onboarding|retry-onboarding|onboard-plan|payment-link … (crm:read / crm:write)
|
|
17
|
+
// admin crm import|capture|outreach|signals|record|signal|accounts|account|score|slack-channels|link-slack|white-glove|set-white-glove|churn|revenue|reach-outs|record-churn|draft-churn-reason|undo-churn|outcomes|record-outcome|renewals|track-record|at-risk|expansion-signals|case|onboard|onboarding|retry-onboarding|onboard-plan|payment-link … (crm:read / crm:write)
|
|
18
18
|
// admin spend summary|reconcile|pnl|entries|add|import|usage|remove|reference|stripe-sync|services|service … (spend:read / spend:write)
|
|
19
19
|
// admin brand-detection <org-id> (fleet:read)
|
|
20
20
|
// admin brand-detection <org-id> [--term t]... [--exact t]... [--exclude p]... [--note "…"] | --clear [--note "…"] (fleet:instrument)
|
|
@@ -3397,6 +3397,25 @@ async function cmdAdminCrm(ctx) {
|
|
|
3397
3397
|
].join("\n")
|
|
3398
3398
|
);
|
|
3399
3399
|
}
|
|
3400
|
+
case "reach-outs": {
|
|
3401
|
+
// admin crm reach-outs [--day YYYY-MM-DD] [--fresh] — the day's reach-out count toward
|
|
3402
|
+
// the target, the same number #crm-reminders posts (src/lib/crm/reach-out-day.ts).
|
|
3403
|
+
const params = new URLSearchParams(
|
|
3404
|
+
compact({ day: flagStr(flags.day), fresh: flagBool(flags.fresh) ? "1" : undefined })
|
|
3405
|
+
);
|
|
3406
|
+
return out(await staffRequest(ctx, "GET", `${CRM}/reach-outs/today?${params}`), (r) =>
|
|
3407
|
+
[
|
|
3408
|
+
`${r.day}: ${r.count} of ${r.target}${r.hit ? " — target hit" : ""}`,
|
|
3409
|
+
...r.leads.map(
|
|
3410
|
+
(l) =>
|
|
3411
|
+
` ${l.name} ${l.reachOuts.map((x) => `${x.channel}${x.byName || x.by ? ` by ${x.byName ?? "a teammate"}` : ""}`).join(", ")}`
|
|
3412
|
+
),
|
|
3413
|
+
r.slack.unread
|
|
3414
|
+
? `Slack: ${r.slack.unread} linked room${r.slack.unread === 1 ? "" : "s"} unread, so the count may be low`
|
|
3415
|
+
: `Slack: ${r.slack.read} room${r.slack.read === 1 ? "" : "s"} read`,
|
|
3416
|
+
].join("\n")
|
|
3417
|
+
);
|
|
3418
|
+
}
|
|
3400
3419
|
case "record-churn": {
|
|
3401
3420
|
// admin crm record-churn <account-id> <reason> [--note "…"] [--at ISO] [--mrr-cents N]
|
|
3402
3421
|
if (!id || !action) {
|
|
@@ -3629,7 +3648,7 @@ async function cmdAdminCrm(ctx) {
|
|
|
3629
3648
|
}
|
|
3630
3649
|
default:
|
|
3631
3650
|
throw new CliError(
|
|
3632
|
-
"Usage: admin crm import|capture|outreach|signals|record|signal|accounts|account|score|slack-channels|link-slack|white-glove|set-white-glove|churn|record-churn|draft-churn-reason|undo-churn|outcomes|record-outcome|renewals|track-record|at-risk|expansion-signals|case|onboard|onboarding|retry-onboarding|onboard-plan|payment-link … (see --help)"
|
|
3651
|
+
"Usage: admin crm import|capture|outreach|signals|record|signal|accounts|account|score|slack-channels|link-slack|white-glove|set-white-glove|churn|revenue|reach-outs|record-churn|draft-churn-reason|undo-churn|outcomes|record-outcome|renewals|track-record|at-risk|expansion-signals|case|onboard|onboarding|retry-onboarding|onboard-plan|payment-link … (see --help)"
|
|
3633
3652
|
);
|
|
3634
3653
|
}
|
|
3635
3654
|
}
|
|
@@ -4156,11 +4175,14 @@ async function cmdAdminSpend(ctx) {
|
|
|
4156
4175
|
renewal_date: flagStr(flags.renewal),
|
|
4157
4176
|
notes: flagStr(flags.notes),
|
|
4158
4177
|
billing_source: oneOf(flags, "billing", ["api", "invoice", "unknown"]),
|
|
4178
|
+
units_purchased: flags.units === "none" ? undefined : flagNum(flags.units),
|
|
4179
|
+
unit_label: flagStr(flags["unit-label"]),
|
|
4159
4180
|
});
|
|
4160
4181
|
if (flags.monthly === "none") update.monthly_cost_usd = null;
|
|
4182
|
+
if (flags.units === "none") update.units_purchased = null;
|
|
4161
4183
|
if (!slug || Object.keys(update).length === 0) {
|
|
4162
4184
|
throw new CliError(
|
|
4163
|
-
'Usage: admin spend service <slug> [--owner "Steve"] [--plan "Pro"] [--monthly 20|none] [--renewal 2026-11-01] [--notes "…"] [--billing api|invoice|unknown]'
|
|
4185
|
+
'Usage: admin spend service <slug> [--owner "Steve"] [--plan "Pro"] [--monthly 20|none] [--renewal 2026-11-01] [--notes "…"] [--billing api|invoice|unknown] [--units 30|none] [--unit-label "mailbox slots"]'
|
|
4164
4186
|
);
|
|
4165
4187
|
}
|
|
4166
4188
|
const result = await staffRequest(ctx, "PATCH", `${SPEND}/services/${encodeURIComponent(slug)}`, update);
|