@dench.com/cli 3.5.4-staging.335 → 3.5.5-staging.342

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/app-sdk.d.ts CHANGED
@@ -1941,7 +1941,7 @@ export interface ApiRequests {
1941
1941
  onlyIf?: "always" | "connected" | "not_connected";
1942
1942
  /** Legacy LinkedIn step sender. Pool campaigns use the campaign's linkedinAccountIds instead. */
1943
1943
  linkedinAccountId?: string;
1944
- /** linkedin_connection: the invite note (optional); linkedin_message: the message (up to 3000 chars). */
1944
+ /** linkedin_connection: the invite note (optional, up to 300 chars; sent without it if LinkedIn refuses the note); linkedin_message: the message (up to 3000 chars). */
1945
1945
  linkedinMessageBody?: string;
1946
1946
  /** linkedin_message: what to do when the invite is still pending. */
1947
1947
  linkedinMessageMode?: "skip_if_not_connected" | "wait_until_connected";
@@ -4862,7 +4862,7 @@ export interface ApiResponses {
4862
4862
  onlyIf?: "always" | "connected" | "not_connected";
4863
4863
  /** Legacy LinkedIn step sender. Pool campaigns use the campaign's linkedinAccountIds instead. */
4864
4864
  linkedinAccountId?: string;
4865
- /** linkedin_connection: the invite note (optional); linkedin_message: the message (up to 3000 chars). */
4865
+ /** linkedin_connection: the invite note (optional, up to 300 chars; sent without it if LinkedIn refuses the note); linkedin_message: the message (up to 3000 chars). */
4866
4866
  linkedinMessageBody?: string;
4867
4867
  /** linkedin_message: what to do when the invite is still pending. */
4868
4868
  linkedinMessageMode?: "skip_if_not_connected" | "wait_until_connected";
package/campaign.ts CHANGED
@@ -1342,7 +1342,7 @@ async function runGet(ctx: CampaignCliContext): Promise<void> {
1342
1342
  );
1343
1343
  }
1344
1344
  lines.push(
1345
- ` Replied ${a.replied ?? 0} (${pct(a.replyRate)} of enrolled)`,
1345
+ ` Replied ${a.replied ?? 0} (${pct(a.replyRate)} of contacted)`,
1346
1346
  );
1347
1347
  lines.push(
1348
1348
  ` Done finished ${a.finished ?? 0} · stopped ${a.stopped ?? 0} · failed ${a.failed ?? 0}`,
package/crm.ts CHANGED
@@ -4654,10 +4654,10 @@ Sidebar (progressive disclosure — Library + home Pinned strip; layout is WORKS
4654
4654
  and a row inside a group is pulled out to the top level. This
4655
4655
  does NOT add a home-level tab. Nav ids come from 'sidebar list'
4656
4656
  — e.g. 'crm-object:task', 'crm-view:task:Due%20today',
4657
- 'crm-people', 'group:abc123'. To-Do(s), Automations, Inbox,
4658
- Meetings, Outreach, and Library are fixed home-level tabs, not
4659
- Library rows. ADMIN-ONLY: the Library order is shared by every
4660
- member.
4657
+ 'crm-people', 'group:abc123'. To-Do(s), Automations, Meetings,
4658
+ Outreach (with Inbox inside it), and Library are fixed home-level
4659
+ tabs, not Library rows. ADMIN-ONLY: the Library order is shared by
4660
+ every member.
4661
4661
  dench crm sidebar group create <name>
4662
4662
  New named group (e.g. "Hiring") at the bottom of the Library.
4663
4663
  Open to any member; prints the group id.
@@ -4670,8 +4670,8 @@ Sidebar (progressive disclosure — Library + home Pinned strip; layout is WORKS
4670
4670
  Move a row out of its group, back to the top level.
4671
4671
  dench crm sidebar pin <nav-id> | unpin <nav-id>
4672
4672
  Pin/unpin a Library row — or a whole group (group id) — on the
4673
- home Pinned strip (under To-Do(s)/Automations/Inbox/Meetings/
4674
- Outreach/Library). This is "add a tab on the left". A pin is a
4673
+ home Pinned strip (under To-Do(s)/Automations/Meetings/Outreach/
4674
+ Library). This is "add a tab on the left". A pin is a
4675
4675
  shared shortcut, not a Library move; open to any member.
4676
4676
 
4677
4677
  Fields (columns):
@@ -449,7 +449,7 @@ const campaignStepInput = z
449
449
  .string()
450
450
  .optional()
451
451
  .describe(
452
- "linkedin_connection: the invite note (optional); linkedin_message: the message (up to 3000 chars).",
452
+ "linkedin_connection: the invite note (optional, up to 300 chars; sent without it if LinkedIn refuses the note); linkedin_message: the message (up to 3000 chars).",
453
453
  ),
454
454
  linkedinMessageMode: z
455
455
  .enum(["skip_if_not_connected", "wait_until_connected"])
@@ -143,6 +143,62 @@ export type SearchJobsBody = {
143
143
  pageToken?: string;
144
144
  };
145
145
 
146
+ export type SignalKind =
147
+ | "post_engagement"
148
+ | "keyword"
149
+ | "hiring"
150
+ | "funding"
151
+ | "launch"
152
+ | "new_leader";
153
+
154
+ export type SearchSignalsBody = {
155
+ signal: SignalKind;
156
+ titles?: string[];
157
+ market?: string;
158
+ locations?: string[];
159
+ headcountRanges?: string[];
160
+ excludeDomains?: string[];
161
+ excludeCompanies?: string[];
162
+ postedAfter: string;
163
+ limit?: number;
164
+ terms?: string[];
165
+ recency?: "week" | "month";
166
+ mode?: "search" | "volume";
167
+ };
168
+
169
+ export type SignalRow = {
170
+ signal: SignalKind;
171
+ companyName: string;
172
+ companyDomain: string;
173
+ companyLinkedinUrl?: string;
174
+ headline: string;
175
+ occurredAt?: string;
176
+ detail: {
177
+ jobTitles?: string[];
178
+ jobCount?: number;
179
+ jobUrl?: string;
180
+ role?: string;
181
+ roundType?: string;
182
+ amount?: string;
183
+ product?: string;
184
+ sourceUrl?: string;
185
+ personName?: string;
186
+ personTitle?: string;
187
+ personLinkedinUrl?: string;
188
+ term?: string;
189
+ postUrl?: string;
190
+ postText?: string;
191
+ engagement?: "reaction" | "comment" | "post";
192
+ };
193
+ };
194
+
195
+ export type SearchSignalsResponse = {
196
+ signals: SignalRow[];
197
+ creditsCharged: number;
198
+ volume?: { term: string; count: number; saturated?: true }[];
199
+ metadata?: { warnings?: string[] };
200
+ };
201
+
146
202
  /**
147
203
  * FullEnrich hard cases run 40–120s end to end; a 90s budget produced
148
204
  * spurious "No data returned" failures for jobs that later completed (and
@@ -1544,6 +1600,125 @@ export async function searchJobs(
1544
1600
  });
1545
1601
  }
1546
1602
 
1603
+ export async function searchSignals(
1604
+ body: SearchSignalsBody,
1605
+ options: EnrichmentGatewayOptions = {},
1606
+ ): Promise<SearchSignalsResponse> {
1607
+ const payload: Record<string, unknown> = {
1608
+ signal: body.signal,
1609
+ postedAfter: body.postedAfter,
1610
+ };
1611
+ if (body.titles?.length) payload.titles = body.titles;
1612
+ if (body.locations?.length) payload.locations = body.locations;
1613
+ if (body.market) payload.market = body.market;
1614
+ if (body.headcountRanges?.length)
1615
+ payload.headcountRanges = body.headcountRanges;
1616
+ if (body.excludeDomains?.length) payload.excludeDomains = body.excludeDomains;
1617
+ if (body.excludeCompanies?.length)
1618
+ payload.excludeCompanies = body.excludeCompanies;
1619
+ if (body.limit !== undefined) payload.limit = body.limit;
1620
+ if (body.terms?.length) payload.terms = body.terms;
1621
+ if (body.recency) payload.recency = body.recency;
1622
+ if (body.mode) payload.mode = body.mode;
1623
+ return (await callGatewayJson("/v1/enrichment/signals/search", {
1624
+ method: "POST",
1625
+ body: payload,
1626
+ options: {
1627
+ ...options,
1628
+ signal: withTimeout(
1629
+ options.signal,
1630
+ body.mode === "volume"
1631
+ ? SIGNAL_GATEWAY_TIMEOUTS_MS.volume
1632
+ : SIGNAL_GATEWAY_TIMEOUTS_MS.search,
1633
+ ),
1634
+ },
1635
+ })) as SearchSignalsResponse;
1636
+ }
1637
+
1638
+ export const SIGNAL_GATEWAY_TIMEOUTS_MS = {
1639
+ search: 140_000,
1640
+ volume: 75_000,
1641
+ buyer: 75_000,
1642
+ reveal: 75_000,
1643
+ } as const;
1644
+
1645
+ function withTimeout(signal: AbortSignal | undefined, ms: number): AbortSignal {
1646
+ const timeout = AbortSignal.timeout(ms);
1647
+ return signal && typeof AbortSignal.any === "function"
1648
+ ? AbortSignal.any([signal, timeout])
1649
+ : (signal ?? timeout);
1650
+ }
1651
+
1652
+ export type SignalBuyerBody = {
1653
+ companyDomain: string;
1654
+ titles?: string[];
1655
+ withEmail?: boolean;
1656
+ };
1657
+
1658
+ export type SignalBuyer = {
1659
+ name: string;
1660
+ firstName?: string;
1661
+ title?: string;
1662
+ linkedinUrl?: string;
1663
+ email?: string;
1664
+ };
1665
+
1666
+ export type SignalBuyerResponse = {
1667
+ buyer: SignalBuyer | null;
1668
+ reveal?: "found" | "not_found" | "failed";
1669
+ };
1670
+
1671
+ export type SignalPersonRevealBody = {
1672
+ companyDomain: string;
1673
+ person: {
1674
+ name: string;
1675
+ linkedinUrl: string;
1676
+ title?: string;
1677
+ firstName?: string;
1678
+ };
1679
+ };
1680
+
1681
+ export async function findSignalBuyer(
1682
+ body: SignalBuyerBody,
1683
+ options: EnrichmentGatewayOptions = {},
1684
+ ): Promise<SignalBuyerResponse> {
1685
+ const payload: Record<string, unknown> = {
1686
+ companyDomain: body.companyDomain,
1687
+ };
1688
+ if (body.titles?.length) payload.titles = body.titles;
1689
+ if (body.withEmail !== undefined) payload.withEmail = body.withEmail;
1690
+ return (await callGatewayJson("/v1/enrichment/signals/buyer", {
1691
+ method: "POST",
1692
+ body: payload,
1693
+ options: {
1694
+ ...options,
1695
+ signal: withTimeout(options.signal, SIGNAL_GATEWAY_TIMEOUTS_MS.buyer),
1696
+ },
1697
+ })) as SignalBuyerResponse;
1698
+ }
1699
+
1700
+ export async function revealSignalPersonEmail(
1701
+ body: SignalPersonRevealBody,
1702
+ options: EnrichmentGatewayOptions = {},
1703
+ ): Promise<SignalBuyerResponse> {
1704
+ return (await callGatewayJson("/v1/enrichment/signals/buyer", {
1705
+ method: "POST",
1706
+ body: {
1707
+ companyDomain: body.companyDomain,
1708
+ person: {
1709
+ name: body.person.name,
1710
+ linkedinUrl: body.person.linkedinUrl,
1711
+ ...(body.person.title ? { title: body.person.title } : {}),
1712
+ ...(body.person.firstName ? { firstName: body.person.firstName } : {}),
1713
+ },
1714
+ },
1715
+ options: {
1716
+ ...options,
1717
+ signal: withTimeout(options.signal, SIGNAL_GATEWAY_TIMEOUTS_MS.reveal),
1718
+ },
1719
+ })) as SignalBuyerResponse;
1720
+ }
1721
+
1547
1722
  /**
1548
1723
  * Number of Exa candidates to pull when resolving ONE person for enrichment.
1549
1724
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dench.com/cli",
3
- "version": "3.5.4-staging.335",
3
+ "version": "3.5.5-staging.342",
4
4
  "description": "Dench agent workspace CLI.",
5
5
  "type": "module",
6
6
  "bin": {