@series-a/cli 0.22.2 → 0.22.3
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/CHANGELOG.md +8 -0
- package/README.md +15 -1
- package/SKILLS.md +319 -0
- package/package.json +2 -1
- package/src/commands/resources.mjs +55 -5
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,14 @@ All notable changes to this package are documented here. This project follows
|
|
|
4
4
|
[Semantic Versioning](https://semver.org/) and uses
|
|
5
5
|
[Changesets](https://github.com/changesets/changesets) to manage releases.
|
|
6
6
|
|
|
7
|
+
## 0.22.3 — Sales Navigator imports from the CLI
|
|
8
|
+
|
|
9
|
+
- Import Sales Navigator lead lists straight from the CLI: `leads import-from sales_nav_url --url "<search-url>"` or `sales_nav_keywords --query "..."`. These queue as cap-aware background imports that drip-feed inside your LinkedIn read limits instead of blocking live campaigns.
|
|
10
|
+
- Track and control them: `leads import-schedules` (progress, ETA, waiting reason) and `leads import-schedule pause|resume|cancel <id>`. Resuming resets retries and nudges the scheduler immediately.
|
|
11
|
+
- Idempotent: re-running an identical import reuses the active schedule instead of duplicating it; match is per-source (URL for url imports, keywords for keyword imports).
|
|
12
|
+
- Options: `--limit` (1–1000, default 100), `--audience` (segment id or name; created if missing), `--priority normal|high|rush`.
|
|
13
|
+
- Docs updated in README and SKILLS.md; MCP gains `lead_import_schedules` and extended `import_leads`.
|
|
14
|
+
|
|
7
15
|
## 0.22.0 — Admin keys, analytics parity, safety hardening, Obsidian sync
|
|
8
16
|
|
|
9
17
|
- Admin keys work end-to-end. `login --admin` persists admin scope and reports reachable workspace count, `whoami` shows `scope: admin (cross-workspace)` plus reachable workspaces, and the caller identity is no longer hardcoded — override with `--as-agent <name>` or `ADVISOROS_AGENT_NAME`, persisted per profile.
|
package/README.md
CHANGED
|
@@ -95,7 +95,7 @@ advisoros leads verify <id>
|
|
|
95
95
|
|
|
96
96
|
`leads import` accepts CSV (header row), JSON array, or JSONL. Upserts on `(workspace_id, linkedin_url)`. Bulk requests are auto-chunked at 200/call (server cap: 500/call).
|
|
97
97
|
|
|
98
|
-
`leads import-from` runs any of the
|
|
98
|
+
`leads import-from` runs any of the import sources in **Get Leads → Import Leads**:
|
|
99
99
|
|
|
100
100
|
| source | required params | what it does |
|
|
101
101
|
|---|---|---|
|
|
@@ -105,9 +105,23 @@ advisoros leads verify <id>
|
|
|
105
105
|
| `paste_profiles` | `--file <path>` | name + LinkedIn URL lines; rest is enriched |
|
|
106
106
|
| `csv` | `--file <path>` | same CSV parser the UI uses |
|
|
107
107
|
| `heyreach` | `--file <path>` `--campaign <id>` | HeyReach campaign CSV, statuses preserved |
|
|
108
|
+
| `sales_nav_url` | `--url <sales-nav-search-url>` | queues a background Sales Navigator import, drip-fed inside the LinkedIn read limits |
|
|
109
|
+
| `sales_nav_keywords` | `--query` | same background queue, from Sales Navigator keywords |
|
|
108
110
|
|
|
109
111
|
All sources accept `--audience` to attach leads to a segment (created if missing). LinkedIn-backed sources run at bulk read priority so live campaigns are not starved. Long-running imports return a `job_id`; poll with `advisoros leads import-status <jobId>`.
|
|
110
112
|
|
|
113
|
+
Sales Navigator sources do not run inline — they create a **scheduled import** that the
|
|
114
|
+
cap-aware scheduler drip-feeds over hours or days:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
advisoros leads import-from sales_nav_url --url "https://www.linkedin.com/sales/search/people?..." \
|
|
118
|
+
--limit 500 --audience "Q3 ICP" --priority high
|
|
119
|
+
advisoros leads import-schedules
|
|
120
|
+
advisoros leads import-schedule pause|resume|cancel <id>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Cancelling keeps the leads already imported.
|
|
124
|
+
|
|
111
125
|
### Campaigns
|
|
112
126
|
|
|
113
127
|
```bash
|
package/SKILLS.md
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# AdvisorPro Skills Guide for AI Agents
|
|
2
|
+
|
|
3
|
+
This file teaches any AI agent — CLI user or MCP client — how to operate
|
|
4
|
+
AdvisorPro safely and effectively. It covers the mental model, the core
|
|
5
|
+
workflows (campaigns, content, brand), the safety rails you must respect,
|
|
6
|
+
and the tricks that separate a smooth run from a failed one.
|
|
7
|
+
|
|
8
|
+
Two surfaces, one backend:
|
|
9
|
+
|
|
10
|
+
- **CLI** — `advisoros` binary (`npm i -g @series-a/cli`), authenticates with
|
|
11
|
+
an API key saved per profile in `~/.advisoros/config.json`.
|
|
12
|
+
- **MCP server** — `advisoros-mcp`, 44 tools, OAuth for the signed-in user.
|
|
13
|
+
|
|
14
|
+
Both talk to the same `/agent-api` gateway. Everything is **scoped to one
|
|
15
|
+
workspace**. Every mutation is **audited** (who, when, what, outcome).
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 1. The non-negotiable first steps
|
|
20
|
+
|
|
21
|
+
### MCP
|
|
22
|
+
1. **Always call `list_workspaces` first.** Every other tool requires a
|
|
23
|
+
`workspace_id`. You can only see workspaces you belong to — never guess an
|
|
24
|
+
ID from another session.
|
|
25
|
+
2. Read the tool description before calling: destructive tools document their
|
|
26
|
+
own confirmation protocol.
|
|
27
|
+
|
|
28
|
+
### CLI
|
|
29
|
+
```bash
|
|
30
|
+
advisoros login --profile main # saves API key + workspace
|
|
31
|
+
advisoros whoami # confirm the active profile/workspace
|
|
32
|
+
```
|
|
33
|
+
Global flags on every command: `--json` (machine output — **always use this
|
|
34
|
+
when an AI is parsing the result**), `-w/--workspace`, `-p/--profile`,
|
|
35
|
+
`--api-key`, `--as-agent <name>` (labels your audit rows — set it to your
|
|
36
|
+
agent's name).
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 2. Mental model
|
|
41
|
+
|
|
42
|
+
- **Leads** are people. They enter via import and are enriched from LinkedIn
|
|
43
|
+
afterwards. Dedupe key is `(workspace_id, linkedin_url)` — re-importing the
|
|
44
|
+
same URL upserts, never duplicates.
|
|
45
|
+
- **Sequences** are message trees (steps with actions, delays, branches).
|
|
46
|
+
They are **not append-only** — steps can be edited, deleted, re-parented,
|
|
47
|
+
or wholesale replaced.
|
|
48
|
+
- **Campaigns** bind leads + a sequence + sender LinkedIn accounts + a daily
|
|
49
|
+
limit. Lifecycle: draft → launch → pause/resume → archive/delete.
|
|
50
|
+
- **Content** items are drafts until scheduled/published. Nothing is ever
|
|
51
|
+
auto-published from a draft.
|
|
52
|
+
- **Knowledge base** grounds all AI generation. Only **confirmed
|
|
53
|
+
human-authored** items train the voice and count as citable evidence.
|
|
54
|
+
- **Agents** run asynchronously: you get a `job_id` back, then poll.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 3. LinkedIn safety — read this before any outreach
|
|
59
|
+
|
|
60
|
+
LinkedIn account safety overrides everything else. The server (not the CLI or
|
|
61
|
+
MCP) is the enforcing authority; you are expected to check before acting.
|
|
62
|
+
|
|
63
|
+
Hard limits (server-enforced):
|
|
64
|
+
- Invite note: **200 characters**
|
|
65
|
+
- Direct message: **8,000 characters** (CLI caps client-side at 7,900)
|
|
66
|
+
- Comment: **1,250 characters**
|
|
67
|
+
- Per sender: **~25 invites/day, ~80 messages/day**
|
|
68
|
+
|
|
69
|
+
Rules for agents:
|
|
70
|
+
- **Before planning outreach or a bulk import, check capacity.**
|
|
71
|
+
CLI: `advisoros safety check` / `safety limits` / `safety reads`.
|
|
72
|
+
MCP: `linkedin_safety` (returns remaining capacity, cooldowns, and
|
|
73
|
+
`safe_bulk_import_size`).
|
|
74
|
+
- **A cooldown or a 429 is not a failure.** Back off using `Retry-After` /
|
|
75
|
+
`retry_after_seconds` and retry. Never hammer.
|
|
76
|
+
- `campaigns launch` and `sequences validate` run the same char-limit checks
|
|
77
|
+
the server enforces — **validate before launch**, not after.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 4. How to create a campaign (end to end)
|
|
82
|
+
|
|
83
|
+
### The fast path: `campaign-flow`
|
|
84
|
+
One command does import → sequence → launch → status:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
advisoros campaign-flow \
|
|
88
|
+
--name "Q3 CFO outreach" \
|
|
89
|
+
--file leads.csv \
|
|
90
|
+
--goal "Book discovery calls with CFOs" \
|
|
91
|
+
--senders <senderId1>,<senderId2> \
|
|
92
|
+
--daily-limit 25 \
|
|
93
|
+
--launch
|
|
94
|
+
```
|
|
95
|
+
Add `--dry-run` first to print the plan without touching the API.
|
|
96
|
+
|
|
97
|
+
### The step-by-step path
|
|
98
|
+
```bash
|
|
99
|
+
# 1. Check capacity
|
|
100
|
+
advisoros safety check
|
|
101
|
+
|
|
102
|
+
# 2. Import leads (auto-chunks at 200/call, upserts on linkedin_url)
|
|
103
|
+
advisoros leads import --file leads.csv
|
|
104
|
+
# or from a source:
|
|
105
|
+
advisoros leads import-from linkedin_search --query "CFO fintech London"
|
|
106
|
+
# Sales Navigator (queued in the background, cap-aware):
|
|
107
|
+
advisoros leads import-from sales_nav_url --url "<sales-nav-search-url>" --limit 500
|
|
108
|
+
advisoros leads import-schedules # progress, ETA, why it is waiting
|
|
109
|
+
advisoros leads import-schedule pause|resume|cancel <scheduleId>
|
|
110
|
+
|
|
111
|
+
# 3. Build or pick a sequence
|
|
112
|
+
advisoros sequences create --name "CFO 3-touch"
|
|
113
|
+
advisoros sequences add-step <seqId> --action sendInvitation --message "..."
|
|
114
|
+
advisoros sequences add-step <seqId> --action wait --days 3
|
|
115
|
+
advisoros sequences add-step <seqId> --action sendMessage --message "..."
|
|
116
|
+
advisoros sequences validate <seqId> # same checks as launch — do this
|
|
117
|
+
|
|
118
|
+
# 4. Create the campaign and attach everything
|
|
119
|
+
advisoros campaigns create --name "Q3 CFO outreach" \
|
|
120
|
+
--sequence <seqId> --senders <id1,id2> --daily-limit 25
|
|
121
|
+
advisoros campaigns add-leads <campaignId> --file leads.csv
|
|
122
|
+
|
|
123
|
+
# 5. Preflight, then launch (launch runs preflight itself and asks --confirm)
|
|
124
|
+
advisoros campaigns preflight <campaignId>
|
|
125
|
+
advisoros campaigns launch <campaignId> --confirm
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
MCP equivalent: `import_leads` → `manage_sequence` → `update_campaign` →
|
|
129
|
+
`manage_campaign` (`preflight`, then `launch`).
|
|
130
|
+
|
|
131
|
+
### After launch
|
|
132
|
+
```bash
|
|
133
|
+
advisoros campaigns stats <id> # funnel: invites → accepts → replies → meetings
|
|
134
|
+
advisoros campaigns health <id> # run state, stalls, retries, watchdog
|
|
135
|
+
advisoros campaigns events <id> # full event log
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 5. Sequences: the tricks
|
|
141
|
+
|
|
142
|
+
- Allowed step actions: `viewProfile`, `addReaction`, `sendInvitation`,
|
|
143
|
+
`sendMessage`, `wait`. Nothing else — the server rejects unknown actions.
|
|
144
|
+
- `sequences show <id>` accepts a **unique ID prefix**, not just full UUIDs.
|
|
145
|
+
- `replace-steps` is **atomic**: it swaps the whole tree from a JSON file,
|
|
146
|
+
validated server-side. Prefer it over many `add-step` calls when an AI is
|
|
147
|
+
generating a full sequence.
|
|
148
|
+
- `update-step` patches one step in place; `delete-step` re-parents its
|
|
149
|
+
children automatically.
|
|
150
|
+
- Message templates support `{first_name}`-style tokens; the server guards
|
|
151
|
+
against unfilled tokens (~20-char guard). Keep variables real.
|
|
152
|
+
- Waits can be expressed in days/hours/minutes. A lead who **replies is
|
|
153
|
+
removed from all further automation automatically** — never re-add them.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 6. Keeping a consistent brand
|
|
158
|
+
|
|
159
|
+
Brand consistency lives in three places; keep all three in sync.
|
|
160
|
+
|
|
161
|
+
### a) The brand record (visual identity)
|
|
162
|
+
```bash
|
|
163
|
+
advisoros brand show # colours, fonts, logos, tagline, imagery
|
|
164
|
+
advisoros brand set --primary-color "#1B4B8F" --font-heading "Inter"
|
|
165
|
+
advisoros brand fields # every editable field
|
|
166
|
+
advisoros brand imagery set --style "minimal editorial" --mood "calm, expert"
|
|
167
|
+
advisoros brand logos set --variant primary --url https://...
|
|
168
|
+
advisoros brand social set --linkedin https://linkedin.com/company/...
|
|
169
|
+
```
|
|
170
|
+
MCP: `manage_brand` (same fields; supports partial updates, add/remove of
|
|
171
|
+
motifs and reference URLs, logo upload, and the imagery direction that steers
|
|
172
|
+
**every generated image**).
|
|
173
|
+
|
|
174
|
+
### b) Tone of voice (written identity)
|
|
175
|
+
```bash
|
|
176
|
+
advisoros voice show # directive + apply-by-default flag
|
|
177
|
+
advisoros voice set --directive "..." --apply-default
|
|
178
|
+
advisoros voice sync # re-pull from Business Build
|
|
179
|
+
advisoros voice references # KB items used as writing samples
|
|
180
|
+
advisoros voice add-reference <knowledgeItemId>
|
|
181
|
+
advisoros voice set-primary <knowledgeItemId> # pin the benchmark sample
|
|
182
|
+
advisoros voice card # measured voice card (stylometric targets)
|
|
183
|
+
advisoros voice score --file draft.md # score text against the voice
|
|
184
|
+
advisoros voice redraft --file draft.md # rewrite in the author's voice
|
|
185
|
+
```
|
|
186
|
+
MCP: `tone_of_voice`.
|
|
187
|
+
|
|
188
|
+
**The rule that matters:** only knowledge items confirmed as human-authored
|
|
189
|
+
count as voice-training material. Confirm them first (`voice add-reference`,
|
|
190
|
+
or MCP `curate_knowledge` with `approve`). AI-authored items are down-weighted
|
|
191
|
+
and labelled in every retrieval — don't try to train the voice on them.
|
|
192
|
+
|
|
193
|
+
### c) Knowledge base (factual identity)
|
|
194
|
+
```bash
|
|
195
|
+
advisoros knowledge add --url https://... # auto-scraped + AI-classified
|
|
196
|
+
advisoros knowledge add --title "..." --text "..." --category positioning
|
|
197
|
+
advisoros knowledge list
|
|
198
|
+
advisoros knowledge reclassify <id>
|
|
199
|
+
```
|
|
200
|
+
Categories: positioning, proof-points, frameworks, personas, case-studies,
|
|
201
|
+
transcripts, market-intel, general. Generation is grounded in the KB — a thin
|
|
202
|
+
KB means generic output. Feed it real positioning and real proof points.
|
|
203
|
+
|
|
204
|
+
### Generating on-brand output
|
|
205
|
+
```bash
|
|
206
|
+
advisoros content generate --topic "..." --type linkedin_post # KB + reference
|
|
207
|
+
# grounded, URL-sanitised
|
|
208
|
+
advisoros content citations <id> # every source recorded for a draft
|
|
209
|
+
```
|
|
210
|
+
MCP: `generate_graphic` / `refine_graphic` for images (returns public URLs,
|
|
211
|
+
uses the brand imagery direction automatically), `create_content_draft` for
|
|
212
|
+
text (drafts only — nothing auto-publishes).
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## 7. Content strategy & calendar
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
advisoros strategies ideate --weeks 4 # multi-week arc from KB + signals
|
|
220
|
+
advisoros strategies create ...
|
|
221
|
+
advisoros strategies resume <id> # continue an interrupted build
|
|
222
|
+
advisoros content list / show / approve / schedule / publish
|
|
223
|
+
advisoros content bulk-approve # approve everything pending
|
|
224
|
+
advisoros calendar list / create
|
|
225
|
+
```
|
|
226
|
+
Scheduling routes through Taplio when connected, otherwise the built-in cron
|
|
227
|
+
scheduler. MCP: `content_strategy`, `content_strategy_posts`,
|
|
228
|
+
`schedule_content`, `manage_content`.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 8. Running agents (async jobs)
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
advisoros agents list
|
|
236
|
+
advisoros agents run <name> # returns a job_id immediately
|
|
237
|
+
advisoros agents job <jobId> # poll until terminal
|
|
238
|
+
```
|
|
239
|
+
MCP: `trigger_agent` (or `history: true` for recent runs).
|
|
240
|
+
|
|
241
|
+
Watch recipe:
|
|
242
|
+
```bash
|
|
243
|
+
JOB=$(advisoros agents run news-monitor --json | jq -r .job_id)
|
|
244
|
+
until advisoros agents job "$JOB" --json | jq -e '.status=="completed"'; do
|
|
245
|
+
sleep 15
|
|
246
|
+
done
|
|
247
|
+
```
|
|
248
|
+
A job ends in a **terminal state** (`completed` or `failed`). Content jobs
|
|
249
|
+
also carry `content_ids` and trace steps — if a job stays `running`, poll
|
|
250
|
+
longer (large articles take minutes); don't resubmit, dispatch is
|
|
251
|
+
exactly-once.
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 9. Destructive actions — the confirm protocol
|
|
256
|
+
|
|
257
|
+
Deletion is allowed but always two-step:
|
|
258
|
+
|
|
259
|
+
- CLI: `campaigns delete <id>` is dry-run by default; re-run with `--force`.
|
|
260
|
+
- MCP: `manage_campaign` / `manage_sequence` with `operation: "delete"`:
|
|
261
|
+
first `dry_run: true` to see the impact, then `confirm: true` to execute.
|
|
262
|
+
Campaigns that already dispatched activity also require `force: true`.
|
|
263
|
+
|
|
264
|
+
`archive` is the reversible alternative — prefer it when unsure.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## 10. Tricks & gotchas
|
|
269
|
+
|
|
270
|
+
1. **`--json` everywhere.** Human tables are for humans; parse JSON.
|
|
271
|
+
2. **`--as-agent <name>` on every call.** Your actions appear in
|
|
272
|
+
`advisoros audit list` — make them attributable.
|
|
273
|
+
3. **Mutation responses are live.** Every campaign/sequence mutation returns
|
|
274
|
+
the freshly re-read record with live counts. List `stats` snapshots can
|
|
275
|
+
lag — trust the `live` block after a mutation.
|
|
276
|
+
4. **Imports are idempotent.** Re-importing the same leads upserts on
|
|
277
|
+
`(workspace_id, linkedin_url)`. Safe to retry after a crash.
|
|
278
|
+
5. **Inbox sends are dry-run by default.** `inbox send`/`reply` exit code `2`
|
|
279
|
+
without `--confirm` — nothing hits LinkedIn until you confirm.
|
|
280
|
+
6. **Intelligence before content.** `signals list` and the watchlist (P0–P3
|
|
281
|
+
priorities) drive what the content agents write about. A tuned watchlist +
|
|
282
|
+
rich KB + confirmed voice references = on-topic, on-voice output.
|
|
283
|
+
7. **`export <resource> <action>`** turns any list into CSV for offline work.
|
|
284
|
+
8. **`kb sync`** mirrors the knowledge base into an Obsidian vault — one-way
|
|
285
|
+
push only, never a source of truth in the other direction.
|
|
286
|
+
9. **`integrations status`** is read-only health. It will never return
|
|
287
|
+
credentials — don't ask it to.
|
|
288
|
+
10. **Transcripts are anonymised** before storage. You will never see raw PII
|
|
289
|
+
from `meetings`/`list_transcripts`; that's by design.
|
|
290
|
+
11. **Rate limits:** per-key sliding window. On HTTP 429, respect
|
|
291
|
+
`Retry-After`. Empty results are never used as a throttle signal — if you
|
|
292
|
+
get an empty list, the data is genuinely empty.
|
|
293
|
+
12. **MCP writes are limited** to leads, knowledge items, drafts, and the
|
|
294
|
+
management tools above. Nothing auto-publishes; publishing is a deliberate
|
|
295
|
+
`manage_content publish_now` / `content publish` call.
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## 11. Cheatsheet
|
|
300
|
+
|
|
301
|
+
| Task | CLI | MCP tool |
|
|
302
|
+
|---|---|---|
|
|
303
|
+
| Discover workspaces | `workspaces list` (admin) | `list_workspaces` (first!) |
|
|
304
|
+
| Check LinkedIn capacity | `safety check` | `linkedin_safety` |
|
|
305
|
+
| Import leads | `leads import` / `import-from` | `import_leads` |
|
|
306
|
+
| Track Sales Nav imports | `leads import-schedules` / `import-schedule` | `lead_import_schedules` |
|
|
307
|
+
| Build a sequence | `sequences create/add-step/replace-steps/validate` | `manage_sequence` |
|
|
308
|
+
| Launch a campaign | `campaign-flow` or `campaigns create/add-leads/launch` | `manage_campaign` |
|
|
309
|
+
| Campaign funnel | `campaigns stats` | `campaign_analytics` |
|
|
310
|
+
| Brand identity | `brand show/set/imagery/logos/social` | `manage_brand` |
|
|
311
|
+
| Voice | `voice show/set/references/score` | `tone_of_voice` |
|
|
312
|
+
| Knowledge | `knowledge add/list/reclassify` | `add_knowledge_item`, `curate_knowledge` |
|
|
313
|
+
| Generate content | `content generate` | `create_content_draft`, `generate_graphic` |
|
|
314
|
+
| Schedule | `content schedule` / `calendar create` | `schedule_content` |
|
|
315
|
+
| Run an agent | `agents run` + `agents job` | `trigger_agent` |
|
|
316
|
+
| Who did what | `audit list` | `list_audit` |
|
|
317
|
+
|
|
318
|
+
When in doubt: `advisoros <command> --help`, `docs/cli.md`, and
|
|
319
|
+
`docs/agent-api.md` are the canonical references.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@series-a/cli",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.3",
|
|
4
4
|
"description": "AdvisorPro command-line interface — drive leads, campaigns, sequences and agents from your terminal.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"bin/",
|
|
11
11
|
"src/",
|
|
12
12
|
"README.md",
|
|
13
|
+
"SKILLS.md",
|
|
13
14
|
"CHANGELOG.md",
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
@@ -111,12 +111,14 @@ export function registerLeads(program) {
|
|
|
111
111
|
});
|
|
112
112
|
|
|
113
113
|
withCommonOpts(leads.command("import-from <source>"))
|
|
114
|
-
.description("Import leads from any source: linkedin_search | company_search | post_reactors | paste_profiles | csv | heyreach")
|
|
115
|
-
.option("--query <q>", "search keywords (linkedin_search / company_search)")
|
|
114
|
+
.description("Import leads from any source: linkedin_search | company_search | post_reactors | paste_profiles | csv | heyreach | sales_nav_url | sales_nav_keywords")
|
|
115
|
+
.option("--query <q>", "search keywords (linkedin_search / company_search / sales_nav_keywords)")
|
|
116
|
+
.option("--url <url>", "full Sales Navigator search URL (sales_nav_url)")
|
|
116
117
|
.option("--post <url>", "LinkedIn post URL (post_reactors)")
|
|
117
118
|
.option("--file <path>", "CSV or pasted-profile text file (csv / paste_profiles / heyreach)")
|
|
118
119
|
.option("--audience <name>", "audience (segment) name or id to attach to")
|
|
119
120
|
.option("--campaign <id>", "campaign id (required for heyreach)")
|
|
121
|
+
.option("--priority <p>", "queue priority for Sales Navigator imports: normal | high | rush")
|
|
120
122
|
.option("--limit <n>", "max prospects for LinkedIn sources", "50")
|
|
121
123
|
.option("--no-enrich", "skip the LinkedIn verify + enrich chain")
|
|
122
124
|
.action(async function (source) {
|
|
@@ -125,9 +127,11 @@ export function registerLeads(program) {
|
|
|
125
127
|
const params = {
|
|
126
128
|
source,
|
|
127
129
|
query: o.query,
|
|
130
|
+
search_url: o.url,
|
|
128
131
|
post_url: o.post,
|
|
129
132
|
audience: o.audience,
|
|
130
133
|
campaign_id: o.campaign,
|
|
134
|
+
priority: o.priority,
|
|
131
135
|
limit: Number(o.limit),
|
|
132
136
|
enrich: o.enrich !== false,
|
|
133
137
|
};
|
|
@@ -137,12 +141,58 @@ export function registerLeads(program) {
|
|
|
137
141
|
else params.csv = text;
|
|
138
142
|
}
|
|
139
143
|
const r = await call("leads", "import", params, ctxFrom(this));
|
|
140
|
-
emit(this, r, (d) =>
|
|
141
|
-
|
|
142
|
-
|
|
144
|
+
emit(this, r, (d) => {
|
|
145
|
+
if (d.schedule) {
|
|
146
|
+
process.stdout.write(
|
|
147
|
+
`${d.reused ? "↻ Reusing existing" : "✓ Queued"} background import — ${d.schedule.target_count} leads\n` +
|
|
148
|
+
` schedule: ${d.schedule.id} (${d.schedule.status})\n` +
|
|
149
|
+
` It drip-feeds inside your LinkedIn read limits. Track with \`advisoros leads import-schedules\`.\n`,
|
|
150
|
+
);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
process.stdout.write(
|
|
154
|
+
`✓ Imported ${d.imported ?? 0} leads (${d.duplicates ?? 0} duplicates, ${d.skipped ?? 0} skipped, ${d.failed ?? 0} failed)\n` +
|
|
155
|
+
(d.job_id ? ` job: ${d.job_id}\n` : ""));
|
|
156
|
+
});
|
|
157
|
+
} catch (e) { fail(e); }
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
withCommonOpts(leads.command("import-schedules"))
|
|
161
|
+
.description("List queued/running Sales Navigator background imports")
|
|
162
|
+
.option("--status <s>", "filter by status (queued|running|awaiting_capacity|paused|completed|failed|cancelled)")
|
|
163
|
+
.option("--all", "include finished imports")
|
|
164
|
+
.option("--limit <n>", "max rows", "25")
|
|
165
|
+
.action(async function () {
|
|
166
|
+
try {
|
|
167
|
+
const o = this.optsWithGlobals();
|
|
168
|
+
const r = await call("leads", "import_schedules", {
|
|
169
|
+
status: o.status,
|
|
170
|
+
active: o.all ? false : true,
|
|
171
|
+
limit: Number(o.limit),
|
|
172
|
+
}, ctxFrom(this));
|
|
173
|
+
emit(this, r, (d) => table(d.schedules ?? [], [
|
|
174
|
+
["id", (s) => s.id.slice(0, 8)],
|
|
175
|
+
["status", (s) => s.status],
|
|
176
|
+
["progress", (s) => `${s.imported_count}/${s.target_count}`],
|
|
177
|
+
["priority", (s) => s.priority],
|
|
178
|
+
["source", (s) => s.source],
|
|
179
|
+
["target", (s) => truncate(s.search_url || s.search_query || "", 48)],
|
|
180
|
+
["reason", (s) => truncate(s.last_reason || "", 40)],
|
|
181
|
+
]));
|
|
143
182
|
} catch (e) { fail(e); }
|
|
144
183
|
});
|
|
145
184
|
|
|
185
|
+
withCommonOpts(leads.command("import-schedule <action> <id>"))
|
|
186
|
+
.description("Pause, resume or cancel a scheduled import (action: pause|resume|cancel)")
|
|
187
|
+
.action(async function (action, id) {
|
|
188
|
+
try {
|
|
189
|
+
const r = await call("leads", "import_schedule_update", { id, action }, ctxFrom(this));
|
|
190
|
+
emit(this, r, (d) =>
|
|
191
|
+
process.stdout.write(`✓ Import ${d.schedule.id} is now ${d.schedule.status}\n`));
|
|
192
|
+
} catch (e) { fail(e); }
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
|
|
146
196
|
withCommonOpts(leads.command("import-status <jobId>"))
|
|
147
197
|
.description("Poll a running lead import")
|
|
148
198
|
.action(async function (jobId) {
|