@sellable/install 0.1.804 → 0.1.806
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/agents/post-find-leads-message-scout.md +4 -4
- package/agents/registry.json +1 -1
- package/bin/sellable-install.mjs +36 -20
- package/container/Dockerfile +7 -7
- package/container/README.md +1 -1
- package/lib/sellable-agent/default-profile-bundles/shared/manifest.fragment.json +1 -1
- package/lib/sellable-agent/default-profile-bundles/shared/skills/sellable/sellable-create-campaign/SKILL.md +3 -3
- package/lib/sellable-agent/external-runtime-builder.mjs +1 -1
- package/lib/sellable-agent/fly-admin-image/Dockerfile +1 -1
- package/lib/sellable-agent/fly-customer-image/Dockerfile +4 -4
- package/lib/sellable-agent/fly-customer-image/customer-runtime.mjs +2 -2
- package/lib/sellable-agent/host-bootstrap.mjs +2 -2
- package/lib/sellable-agent/host-worker.mjs +2 -2
- package/lib/sellable-agent/profile-materializer.mjs +2 -2
- package/lib/sellable-agent/provisioning-adapter.mjs +2 -2
- package/lib/sellable-agent/public-skills.json +4 -4
- package/lib/sellable-agent/public-skills.mjs +35 -0
- package/package.json +1 -1
- package/skill-templates/create-campaign.md +3 -3
- package/skill-templates/{conversation-chess.md → draft-message.md} +7 -6
- package/skill-templates/first-campaign-onboarding.md +8 -7
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
mkdirSync,
|
|
7
7
|
readFileSync,
|
|
8
8
|
renameSync,
|
|
9
|
+
rmdirSync,
|
|
9
10
|
rmSync,
|
|
10
11
|
writeFileSync,
|
|
11
12
|
} from "node:fs";
|
|
@@ -35,6 +36,37 @@ const bundleDigest = createHash("sha256")
|
|
|
35
36
|
.update(JSON.stringify(bundledFiles))
|
|
36
37
|
.digest("hex");
|
|
37
38
|
|
|
39
|
+
// Skill files this image owned under an earlier name. A renamed skill must not
|
|
40
|
+
// linger beside its replacement, so each is removed when it is a plain file
|
|
41
|
+
// inside plain directories; anything else is left alone.
|
|
42
|
+
const retiredFiles = Object.freeze([
|
|
43
|
+
// Renamed to sellable-draft-message on 2026-10-05.
|
|
44
|
+
"skills/sellable/sellable-conversation-chess/SKILL.md",
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
function isPlainDirectory(path) {
|
|
48
|
+
const stat = lstatSync(path, { throwIfNoEntry: false });
|
|
49
|
+
return Boolean(stat?.isDirectory() && !stat.isSymbolicLink());
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function removeRetiredFile(profileRoot, path) {
|
|
53
|
+
let directory = profileRoot;
|
|
54
|
+
for (const name of path.split("/").slice(0, -1)) {
|
|
55
|
+
directory = join(directory, name);
|
|
56
|
+
if (!isPlainDirectory(directory)) return false;
|
|
57
|
+
}
|
|
58
|
+
const target = join(profileRoot, path);
|
|
59
|
+
const stat = lstatSync(target, { throwIfNoEntry: false });
|
|
60
|
+
if (!stat?.isFile() || stat.isSymbolicLink()) return false;
|
|
61
|
+
rmSync(target);
|
|
62
|
+
try {
|
|
63
|
+
rmdirSync(directory);
|
|
64
|
+
} catch {
|
|
65
|
+
// The directory still holds something else; keep it.
|
|
66
|
+
}
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
38
70
|
function assertDirectory(path) {
|
|
39
71
|
const stat = lstatSync(path, { throwIfNoEntry: false });
|
|
40
72
|
if (!stat) return;
|
|
@@ -80,6 +112,9 @@ export function reconcilePublicHermesSkills({
|
|
|
80
112
|
}
|
|
81
113
|
}
|
|
82
114
|
let changed = false;
|
|
115
|
+
for (const path of retiredFiles) {
|
|
116
|
+
if (removeRetiredFile(profileRoot, path)) changed = true;
|
|
117
|
+
}
|
|
83
118
|
for (const file of bundledFiles) {
|
|
84
119
|
const target = join(profileRoot, file.path);
|
|
85
120
|
if (
|
package/package.json
CHANGED
|
@@ -216,8 +216,8 @@ preparation, the target is wrong, or status shows the wrong campaign/table, call
|
|
|
216
216
|
`cancel_campaign_message_preparation`; otherwise do not cancel a healthy prepare
|
|
217
217
|
run. Never call `start_campaign` from message preparation; final launch remains
|
|
218
218
|
a separate explicit user greenlight.
|
|
219
|
-
|
|
220
|
-
|
|
219
|
+
First messages use Conversations or Message Testing; name the one you pick
|
|
220
|
+
as create-campaign-v2 `references/message-approach.md` says.
|
|
221
221
|
|
|
222
222
|
## DNC And Blocklist Handling
|
|
223
223
|
|
|
@@ -598,7 +598,7 @@ Drafting finishes or the recommendation is reviewed. If the user skips filters,
|
|
|
598
598
|
first, then move to Messages/message review after it has started or returned a
|
|
599
599
|
ready recommendation. `update_campaign({ currentStep: "messages" })` is not
|
|
600
600
|
proof of kickoff. Enrichment/filtering and Generate Message cells wait for
|
|
601
|
-
message approval
|
|
601
|
+
message approval (Message Testing only; Conversations has no template).
|
|
602
602
|
|
|
603
603
|
The Message Drafting handoff must stay lean. Include only `campaignId`,
|
|
604
604
|
`workflowTableId`, a concise brief summary, concise source summary/source-use
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: Draft
|
|
2
|
+
name: draft-message
|
|
3
|
+
description: Draft one opener, reply or follow-up as the current sender, from their offer and the conversation. Nothing is sent. Start with the Sellable get_subskill_prompt tool for subskillName draft-message.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Sellable
|
|
6
|
+
# Sellable Draft Message
|
|
7
7
|
|
|
8
|
-
Use this skill for one
|
|
8
|
+
Use this skill for one message draft, in either campaign approach
|
|
9
|
+
(Conversations or Message Testing). It does not send messages, schedule,
|
|
9
10
|
book, approve templates, enroll prospects or change stored sender context.
|
|
10
11
|
Campaign creation and row persistence remain with their existing owners.
|
|
11
12
|
|
|
12
|
-
1. Load `mcp__sellable__get_subskill_prompt({ subskillName: "
|
|
13
|
+
1. Load `mcp__sellable__get_subskill_prompt({ subskillName: "draft-message" })`.
|
|
13
14
|
Read every page using its `nextOffset` until `hasMore` is false. Do not
|
|
14
15
|
reconstruct the prompt from memory, a repository or a plugin-cache path.
|
|
15
16
|
2. Load `core/input-contract.md` through
|
|
16
|
-
`mcp__sellable__get_subskill_asset({ subskillName: "
|
|
17
|
+
`mcp__sellable__get_subskill_asset({ subskillName: "draft-message", assetPath: "..." })`.
|
|
17
18
|
Then load the selected guide and examples from the root prompt:
|
|
18
19
|
OPENER uses `modes/opener.md` + `references/openers.md` + `references/rapport.md` +
|
|
19
20
|
`references/opener-editor.md`; REPLY uses
|
|
@@ -245,8 +245,8 @@ continue in the same conversation; do not ask the user to run another command.
|
|
|
245
245
|
sending account: the latter belongs at Settings, not before the draft.
|
|
246
246
|
The flow's order and state gates still hold: the campaign exists before
|
|
247
247
|
anyone is imported, the source is chosen before the import, sample rows
|
|
248
|
-
exist before filters and messages run, and
|
|
249
|
-
anything is queued. Who decides each one is set by the next section. Offer
|
|
248
|
+
exist before filters and messages run, and in Message Testing the template
|
|
249
|
+
is saved before anything is queued. Who decides each one is set by the next section. Offer
|
|
250
250
|
CRM or meeting integrations only as optional context when helpful.
|
|
251
251
|
4. Reuse an existing draft for the same goal. Never create a duplicate because
|
|
252
252
|
onboarding resumed in a new session.
|
|
@@ -304,11 +304,12 @@ for the message template: those are yours to decide and report.
|
|
|
304
304
|
**How the first message is written.** The first campaign uses the
|
|
305
305
|
Conversations approach from the workflow's `references/message-approach.md`:
|
|
306
306
|
create it with `messageApproach: "conversation"`, write no message template,
|
|
307
|
-
and let Sellable
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
307
|
+
and let Sellable write each first message for the person. Use Message Testing
|
|
308
|
+
(`"message_test"`, one approved message to everyone) only when the customer
|
|
309
|
+
asks to send the same message to everyone, to test copy, or to approve exact
|
|
310
|
+
wording; then the template steps of the workflow apply and you approve the
|
|
311
|
+
template yourself as before. Name the approach to the customer with the
|
|
312
|
+
one-line descriptions in `references/message-approach.md`.
|
|
312
313
|
|
|
313
314
|
**Approval 1: direction.** After research, write the brief, create the
|
|
314
315
|
campaign with it (`create_campaign`), and post one message in this shape. The
|