@vruum/skills 0.6.24 → 0.6.26
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vruum",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.26",
|
|
4
4
|
"description": "Vruum AI skills + remote MCP server for B2B GTM teams. Slash commands for outreach triage, engagement triage, pipeline filling, prospect enrichment, and reply diagnosis, paired with the full Vruum MCP tool surface over OAuth 2.1.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Vruum AI",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vruum",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.26",
|
|
4
4
|
"description": "Vruum AI skills + remote MCP server for B2B GTM teams. Skills for outreach triage, engagement triage, pipeline filling, prospect enrichment, and reply diagnosis, paired with the full Vruum MCP tool surface over OAuth 2.1.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Vruum AI",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vruum/skills",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.26",
|
|
4
4
|
"description": "Vruum AI skills for Claude Code, Claude Desktop, Codex CLI, and any AI assistant with a skill directory. Slash commands for outreach triage, engagement triage, pipeline filling, prospect enrichment, and reply diagnosis. Pairs with the Vruum MCP server at https://api.vruum.ai/mcp.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"outreach",
|
|
43
43
|
"gtm"
|
|
44
44
|
],
|
|
45
|
-
"contentHash": "
|
|
45
|
+
"contentHash": "4526c646767cafd265c0236c3335076e1c8daa876a0994fc6134b3ef89e82879"
|
|
46
46
|
}
|
|
@@ -33,29 +33,35 @@ Turn the goal into targeting criteria and **preview before committing**:
|
|
|
33
33
|
- `search` with `type="people"` and the criteria (include `filters={research_status: "all"}` so stub imports are visible). Read the **total count** and show a **5-row sample** (name, title, company, persona, the attributes that matched).
|
|
34
34
|
- Iterate the criteria conversationally until the cohort is the right size and shape for the goal. An empty preview means the criteria are too tight — loosen and re-run; never proceed to boost on a zero-count audience.
|
|
35
35
|
|
|
36
|
-
This is the same segmentation conversation `/campaign-builder` runs — **do not reproduce its steps here.** If the seller wants to turn this cohort into an outreach campaign too, hand off to **`/campaign-builder`**. For the boost itself
|
|
36
|
+
This is the same segmentation conversation `/campaign-builder` runs — **do not reproduce its steps here.** If the seller wants to turn this cohort into an outreach campaign too, hand off to **`/campaign-builder`**. For the boost itself the audience is **firmographic facets** — LinkedIn-native attribute targeting (titles, seniorities, industries, locations, company sizes), the same way LinkedIn's own boost targets. Resolve names to entity URNs FIRST via `fetch type='ads' subtype='targeting_entities'` (facet + q), then hold the resolved `{facets}` map. **`locations` is required** — a campaign without a location facet is rejected. (`{matched_audience_id}` still works when a pre-uploaded audience exists; `{criteria}`-built matched audiences are partner-gated on LinkedIn's side and return a clear error pointing back to facets.)
|
|
37
37
|
|
|
38
|
-
Hold the settled audience (the `{
|
|
38
|
+
Hold the settled audience (the resolved `{facets}` map — shown to the seller as plain names with counts where available — or a `matched_audience_id`). It is one of the four things the seller approves in Step 4.
|
|
39
39
|
|
|
40
|
-
## Step 3: Creative — copy, then the visual
|
|
40
|
+
## Step 3: Creative — copy, then the visual (image OR video)
|
|
41
41
|
|
|
42
|
-
**Copy — hand off, don't write it here.** Invoke **`/create-content`** to co-produce the on-voice post. That skill owns author resolution, signal grounding, the steer→draft loop, and the publish guards — narrate it as it works, but never reproduce its drafting procedure. It leaves you a **draft** content post (its id is what Step 5 boosts). Keep the post a draft for now — publish is gated behind the seller's approval in Step 4.
|
|
42
|
+
**Copy — hand off, don't write it here.** Invoke **`/create-content`** to co-produce the on-voice post. That skill owns author resolution, signal grounding, the steer→draft loop, and the publish guards — narrate it as it works, but never reproduce its drafting procedure. It leaves you a **draft** content post (its id is what Step 5 boosts). Keep the post a draft for now — publish is gated behind the seller's approval in Step 4. Two post-level decisions to settle WITH the copy (both settable at draft/edit):
|
|
43
43
|
|
|
44
|
-
**
|
|
44
|
+
- **Identity** — `author_identity: 'member'` (a person's profile → the boost runs as a **Thought Leader Ad**, awareness/engagement only, and the author must be authorized via `manage_campaign` kind='ad' action='authorize_author') or `'organization'` (the **Company Page** → all objectives, incl. clicks; needs the Page set once via action='set_page').
|
|
45
|
+
- **Destination** — if the goal is clicks, put the `external_link` on the post NOW (UTMs are stamped automatically). WEBSITE_VISIT without a destination is rejected at boost time.
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
- Store it as a **draft** creative via `manage_campaign` kind='ad' action='store_creative', payload `{image_base64 (raw base64, no data: URL prefix), generation_prompt, generation_provenance: {model, tool, generated_at, notes}}`. It lands as a draft library asset (zero spend, approval is separate). Pass the real `generation_prompt` and provenance so the asset is auditable.
|
|
47
|
+
**Visual — generate or supply it, then store it as a draft.**
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
- **Image**: generate with your own image tools, then store via `manage_campaign` kind='ad' action='store_creative', payload `{image_base64 (raw base64, no data: URL prefix), generation_prompt, generation_provenance: {model, tool, generated_at, notes}}`.
|
|
50
|
+
- **Video** (mp4, ≤200MB, 3s–30min): store via the same action — `{media_url: <public https url>}` for a hosted file, or `{filename, size_bytes, content_type:'video/mp4'}` to get a **presigned upload URL** for a local file (PUT it with curl, then call store_creative again with `{creative_id}` to finalize). Optional `{thumbnail_base64}`. **Video stores are async** — poll `fetch type='ads' subtype='creative' id=<creative_id>` until `upload_status` leaves `'uploading'`; a `'failed'` status with a probe-code error means re-export the file, not retry.
|
|
51
|
+
- A stored **video** creative can be attached to the organic post at publish (`manage_content action=publish` with `creative_id`) — one asset serves the organic post AND the ad. Images remain library assets only (image attach stays out of scope for this loop).
|
|
52
|
+
|
|
53
|
+
A video creative can ALSO run without any post as **Direct Sponsored Content** (`boost` with `creative_id` instead of `content_post_id`) — but DSC is **metrics-only**: no organic post means no engager bridge. Prefer the published-post path when the bridge matters.
|
|
50
54
|
|
|
51
55
|
## Step 4: HARD approval gate — the money-and-feed checkpoint
|
|
52
56
|
|
|
53
|
-
This is the load-bearing step. **Before any publish or any spend**, lay out all
|
|
57
|
+
This is the load-bearing step. **Before any publish or any spend**, lay out all the pieces together and get the seller's explicit go-ahead on each — the original four PLUS the identity/objective pair VRU-659 added:
|
|
58
|
+
|
|
59
|
+
0. **Identity + objective** — which identity the ad runs under (`member` ⇒ Thought Leader Ad / `organization` ⇒ Company Page) and the LinkedIn objective (e.g. `WEBSITE_VISIT` for clicks — requires the destination link; `thought_leader` allows only BRAND_AWARENESS/ENGAGEMENT). Show the destination URL (with its UTMs) when there is one.
|
|
54
60
|
|
|
55
61
|
1. **Copy** — the exact post text from `/create-content`.
|
|
56
62
|
2. **Creative** — the stored visual (generation prompt + provenance).
|
|
57
63
|
3. **Budget** — the daily/total budget you're about to commit. Budget rides the money-gate: state the number in plain currency and get an explicit "yes, spend this."
|
|
58
|
-
4. **Audience** — the
|
|
64
|
+
4. **Audience** — the targeting (the facet names — titles/seniorities/industries/locations — or the `matched_audience_id`).
|
|
59
65
|
|
|
60
66
|
Invariants — these never bend:
|
|
61
67
|
|
|
@@ -69,10 +75,12 @@ If the seller hesitates on any of the four, stop at draft and leave the loop res
|
|
|
69
75
|
|
|
70
76
|
Only after the Step 4 approvals:
|
|
71
77
|
|
|
72
|
-
|
|
73
|
-
|
|
78
|
+
0. **Identity prerequisites (first run only)** — a Page campaign needs the Company Page set (`manage_campaign` kind='ad' action='set_page'; call with no organization_urn to discover the candidates); a Thought Leader Ad needs the author authorized (action='authorize_author'). Errors from boost name the exact fixing call — run it and retry rather than improvising.
|
|
79
|
+
1. **Publish the organic post** — `manage_content action=publish` on the draft from `/create-content` (pass `creative_id` to attach an approved video). This inherits `/create-content`'s author guard: if the chosen author's LinkedIn account isn't connected/healthy, publish fails hard rather than posting under another identity — surface that to the seller, don't retry blindly. **Wait for the post to actually be `published`** (a video publish transfers media and can take a while — re-read the post before boosting; never boost a still-publishing post).
|
|
80
|
+
2. **Boost the published post** — `manage_campaign` kind='ad' action='boost', payload `{content_post_id: <the just-published post id>, vehicle?, objective: <the approved objective>, budget: {daily_budget_cents | total_budget_cents}, audience: {facets} OR {matched_audience_id}, duration_days?, approval_mode}`. Vehicle is inferred from the post's identity — pass the objective explicitly (the default is BRAND_AWARENESS, which is NOT what a click campaign wants). Use the `approval_mode` the seller authorized in Step 4 — `draft` unless they explicitly approved the budget for `auto`. The boost double-submit case is handled for you (idempotent per source + audience + vehicle + objective), so don't paper over a retry with a second call. (DSC alternative: `creative_id` instead of `content_post_id` runs the video without a post — metrics-only, no bridge.)
|
|
81
|
+
3. **If the campaign involves a video ad**, the LinkedIn media upload runs in the background after approval — the response tells you; poll `fetch type='ads' subtype='campaign' id=<campaign_id>` (~every 30s) until it reports live or a failure with its cause.
|
|
74
82
|
|
|
75
|
-
Report back what went live: the published post and whether the boost is a draft awaiting approval in the queue or
|
|
83
|
+
Report back what went live: the published post and whether the boost is a draft awaiting approval in the queue, pushed live, or uploading video in the background.
|
|
76
84
|
|
|
77
85
|
## Step 6: Monitor + bridge to outreach
|
|
78
86
|
|