@sellable/mcp 0.1.557 → 0.1.558
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/README.md +2 -13
- package/agents/registry.json +2 -2
- package/dist/api.js +6 -3
- package/dist/auth.d.ts +6 -0
- package/dist/auth.js +44 -2
- package/dist/refill-contract.d.ts +157 -0
- package/dist/refill-contract.js +487 -0
- package/dist/refill-run-client.d.ts +10 -0
- package/dist/refill-run-client.js +22 -0
- package/dist/refill-run-loop.d.ts +14 -2
- package/dist/refill-run-loop.js +160 -15
- package/dist/server.js +0 -23
- package/dist/tools/auth.d.ts +5 -0
- package/dist/tools/auth.js +49 -12
- package/dist/tools/campaign-message-preparation.d.ts +62 -0
- package/dist/tools/campaign-message-preparation.js +41 -0
- package/dist/tools/campaigns.js +2 -2
- package/dist/tools/csv-dnc.js +2 -2
- package/dist/tools/evergreen-refill-plan.d.ts +3 -0
- package/dist/tools/evergreen-refill-plan.js +29 -7
- package/dist/tools/leads.d.ts +32 -317
- package/dist/tools/leads.js +10 -171
- package/dist/tools/model-quality.js +6 -4
- package/dist/tools/prompts.d.ts +3 -3
- package/dist/tools/prompts.js +15 -7
- package/dist/tools/provider-preflight.d.ts +2 -65
- package/dist/tools/provider-preflight.js +10 -97
- package/dist/tools/readiness.d.ts +5 -89
- package/dist/tools/readiness.js +0 -66
- package/dist/tools/refill-executors.d.ts +38 -0
- package/dist/tools/refill-executors.js +222 -3
- package/dist/tools/refill-sends-v2.d.ts +118 -1
- package/dist/tools/refill-sends-v2.js +312 -3
- package/dist/tools/refill-sends.d.ts +678 -32
- package/dist/tools/refill-sends.js +274 -13
- package/dist/tools/refill-target-plan.js +486 -14
- package/dist/tools/registry.d.ts +115 -330
- package/dist/tools/registry.js +1 -7
- package/dist/tools/scheduler-fill-capacity.js +1 -1
- package/dist/tools/scheduler-run.d.ts +71 -0
- package/dist/tools/scheduler-run.js +203 -1
- package/dist/tools/setup-evergreen-campaigns.js +1 -1
- package/dist/tools/workspace-context.d.ts +1 -1
- package/dist/tools/workspace-context.js +8 -3
- package/dist/tools/workspace-export.js +2 -2
- package/dist/tools/workspaces.d.ts +48 -2
- package/dist/tools/workspaces.js +48 -5
- package/package.json +1 -1
- package/skills/create-campaign/SKILL.md +3 -3
- package/skills/create-campaign-v2/SKILL.md +1 -1
- package/skills/create-evergreen-campaigns/SKILL.md +16 -16
- package/skills/find-leads/SKILL.md +630 -48
- package/skills/refill-sends/SKILL.md +91 -353
- package/skills/refill-sends-v2/SKILL.md +6 -6
- package/skills/refill-sends-v2-workflow/SKILL.md +5 -5
- package/skills/refill-sends-v2-workflow/core/flow.v1.json +8 -8
- package/skills/refill-sends-workflow/SKILL.md +100 -743
- package/skills/refill-sends-workflow/core/contract.v2.json +543 -0
- package/skills/refill-sends-workflow/core/flow.v1.json +185 -1
- package/dist/tools/find-leads-runs.d.ts +0 -151
- package/dist/tools/find-leads-runs.js +0 -98
- package/skills/find-leads-v2/SKILL.md +0 -70
- package/skills/find-leads-v2/core/flow.v1.json +0 -31
|
@@ -30,6 +30,22 @@
|
|
|
30
30
|
"yoloMode"
|
|
31
31
|
]
|
|
32
32
|
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"tool": "get_subskill_asset",
|
|
36
|
+
"requiredValues": {
|
|
37
|
+
"subskillName": "refill-sends-workflow",
|
|
38
|
+
"assetPath": "core/contract.v2.json"
|
|
39
|
+
},
|
|
40
|
+
"mustReadUntil": {
|
|
41
|
+
"hasMore": false
|
|
42
|
+
},
|
|
43
|
+
"validation": {
|
|
44
|
+
"supportedMajor": 2,
|
|
45
|
+
"contractVersion": "2.0.0",
|
|
46
|
+
"cacheVersion": "refill-contract-v1",
|
|
47
|
+
"contractHash": "e54ba0f80bc534fd70fd8c10c1caab109fe9a91c205cfc423f5f6735cd53fdc1"
|
|
48
|
+
}
|
|
33
49
|
}
|
|
34
50
|
],
|
|
35
51
|
"gateOrder": [
|
|
@@ -61,6 +77,44 @@
|
|
|
61
77
|
"scheduled",
|
|
62
78
|
"projected"
|
|
63
79
|
],
|
|
80
|
+
"scopeContract": {
|
|
81
|
+
"immutableApprovalEnvelope": [
|
|
82
|
+
"workspaceId",
|
|
83
|
+
"targetDate",
|
|
84
|
+
"senderIds",
|
|
85
|
+
"actionTypes",
|
|
86
|
+
"campaignIds",
|
|
87
|
+
"tableIds",
|
|
88
|
+
"sourceIds",
|
|
89
|
+
"targetShapeRevision",
|
|
90
|
+
"actionKey"
|
|
91
|
+
],
|
|
92
|
+
"mutableProgress": [
|
|
93
|
+
"stateRevision",
|
|
94
|
+
"sent",
|
|
95
|
+
"scheduled",
|
|
96
|
+
"readyToSchedule",
|
|
97
|
+
"remainingProjectedGap"
|
|
98
|
+
],
|
|
99
|
+
"executionRules": [
|
|
100
|
+
"Execute only target.globalActionQueue[0].",
|
|
101
|
+
"Execute one action, then perform a full authoritative reread before selecting any next action.",
|
|
102
|
+
"Mutable progress must not be treated as approval-scope drift while targetShapeRevision remains stable."
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
"interruptionRecovery": {
|
|
106
|
+
"rules": [
|
|
107
|
+
"On resume, reread the canonical target plan and reconcile scheduler status or receipt with the matching requestKey and actionKey before retrying.",
|
|
108
|
+
"A matching terminal receipt must replay without a second scheduler execution.",
|
|
109
|
+
"An uncertain_outcome requires reconciliation; do not schedule again with the same or a replacement key until a canonical read resolves it."
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
"multiDayOrdering": {
|
|
113
|
+
"rules": [
|
|
114
|
+
"For multiple target dates, finish D1 execution and the full D1 reread before planning D2.",
|
|
115
|
+
"Do not pre-plan or execute a later date from stale earlier-date state."
|
|
116
|
+
]
|
|
117
|
+
},
|
|
64
118
|
"states": [
|
|
65
119
|
{
|
|
66
120
|
"id": "target_plan_read",
|
|
@@ -188,7 +242,7 @@
|
|
|
188
242
|
},
|
|
189
243
|
{
|
|
190
244
|
"id": "scheduler_wait_readback",
|
|
191
|
-
"description": "
|
|
245
|
+
"description": "Exact-date scheduler sweep or read-only polling after rows are ready and paid-credit facts are fresh.",
|
|
192
246
|
"allowedTools": [
|
|
193
247
|
"get_refill_target_plan",
|
|
194
248
|
"get_scheduler_fill_capacity",
|
|
@@ -203,6 +257,9 @@
|
|
|
203
257
|
"rules": [
|
|
204
258
|
"Poll every 60-120 seconds or on the host continuation interval.",
|
|
205
259
|
"Use run_scheduler_sweep with the explicit workspaceId when ready rows need scheduler pickup now; it places cells only inside existing gates and never sends.",
|
|
260
|
+
"A scheduler sweep is a visible workspace-wide scheduling side effect; the packet limits expected target changes but must disclose that unrelated eligible workspace work may also be scheduled.",
|
|
261
|
+
"For an explicit targetDate, execute only the request-scoped run_scheduler_sweep from target.globalActionQueue[0], then perform a full authoritative target-plan reread before any next action.",
|
|
262
|
+
"Reuse the matching requestKey and actionKey only for status or receipt reconciliation; replay a matching terminal receipt and stop on uncertain_outcome rather than scheduling again.",
|
|
206
263
|
"cellsConsidered is allocation-attempt count; inspect campaignScopeSummary before assuming the selected refill campaign/table was included or ready-but-blocked.",
|
|
207
264
|
"Read prefiltered, skipped, and deferred separately: prefiltered ready closed-InMail cells with stale paid-credit facts require refresh_paid_inmail_credits_then_rerun once, then rerun/status.",
|
|
208
265
|
"wait_for_capacity_or_window means report loaded/capped/waiting and do not source or prep more rows; no_ready_cells_continue_refill_prep means return to the refill/prep ladder.",
|
|
@@ -211,6 +268,11 @@
|
|
|
211
268
|
"Do not mark complete or blocked only because awaiting_scheduler_after_ready_buffer persists."
|
|
212
269
|
],
|
|
213
270
|
"transitions": [
|
|
271
|
+
{
|
|
272
|
+
"when": "explicit targetDate and target.globalActionQueue[0] is request-scoped run_scheduler_sweep",
|
|
273
|
+
"action": "execute exactly one request-scoped run_scheduler_sweep, capture its complete receipt, and do not execute a returned next action",
|
|
274
|
+
"to": "target_plan_read"
|
|
275
|
+
},
|
|
214
276
|
{
|
|
215
277
|
"when": "projected coverage fills target",
|
|
216
278
|
"to": "completion_or_blocker"
|
|
@@ -243,6 +305,7 @@
|
|
|
243
305
|
"start_campaign_message_preparation",
|
|
244
306
|
"same_source_copy",
|
|
245
307
|
"bounded_generated_message_approval",
|
|
308
|
+
"run_scheduler_sweep",
|
|
246
309
|
"wait_for_scheduler"
|
|
247
310
|
],
|
|
248
311
|
"neverAutoExecute": [
|
|
@@ -271,16 +334,137 @@
|
|
|
271
334
|
"verification": {
|
|
272
335
|
"requiredProof": [
|
|
273
336
|
"final get_refill_target_plan",
|
|
337
|
+
"get_campaign_refill_state for selected campaign/table facts",
|
|
338
|
+
"get_scheduler_fill_capacity for the exact sender/action/date",
|
|
339
|
+
"run_scheduler_sweep status or receipt for any executed sweep",
|
|
274
340
|
"projected coverage sent + scheduled",
|
|
275
341
|
"scheduler-owned cells with non-null scheduledFor when claiming scheduled",
|
|
276
342
|
"paid-InMail freshness status clean before scheduler wait",
|
|
277
343
|
"refresh receipt for each refreshed sender"
|
|
278
344
|
],
|
|
345
|
+
"forbiddenProof": [
|
|
346
|
+
"individual cell ids",
|
|
347
|
+
"Prisma",
|
|
348
|
+
"SQL",
|
|
349
|
+
"direct database access",
|
|
350
|
+
"production-environment scripts"
|
|
351
|
+
],
|
|
352
|
+
"completionRules": [
|
|
353
|
+
"Report already sent actions separately from future scheduled actions.",
|
|
354
|
+
"Only scheduler-owned future scheduled actions count as scheduled coverage.",
|
|
355
|
+
"Prepared, approved, and ready rows remain intermediate evidence."
|
|
356
|
+
],
|
|
279
357
|
"notCompletionProof": [
|
|
280
358
|
"prepared rows alone",
|
|
281
359
|
"approved rows alone",
|
|
282
360
|
"ready-to-schedule rows alone",
|
|
283
361
|
"awaiting_scheduler_after_ready_buffer"
|
|
284
362
|
]
|
|
363
|
+
},
|
|
364
|
+
"refillContract": {
|
|
365
|
+
"contractVersion": "2.0.0",
|
|
366
|
+
"cacheVersion": "refill-contract-v1",
|
|
367
|
+
"contractHash": "e54ba0f80bc534fd70fd8c10c1caab109fe9a91c205cfc423f5f6735cd53fdc1",
|
|
368
|
+
"semanticIds": {
|
|
369
|
+
"scope": [
|
|
370
|
+
"workspace_id",
|
|
371
|
+
"target_date",
|
|
372
|
+
"sender_selectors",
|
|
373
|
+
"campaign_selectors",
|
|
374
|
+
"approval_mode",
|
|
375
|
+
"contract_identity",
|
|
376
|
+
"installed_identity"
|
|
377
|
+
],
|
|
378
|
+
"gates": [
|
|
379
|
+
"workspace_access",
|
|
380
|
+
"approval_packet",
|
|
381
|
+
"source_family",
|
|
382
|
+
"threshold",
|
|
383
|
+
"scheduler",
|
|
384
|
+
"campaign_lifecycle",
|
|
385
|
+
"send_time",
|
|
386
|
+
"no_direct_send",
|
|
387
|
+
"one_primitive",
|
|
388
|
+
"fresh_reread",
|
|
389
|
+
"normalized_accounting",
|
|
390
|
+
"prep_circuit",
|
|
391
|
+
"terminal_truth"
|
|
392
|
+
],
|
|
393
|
+
"states": [
|
|
394
|
+
"planning",
|
|
395
|
+
"awaiting_approval",
|
|
396
|
+
"executing",
|
|
397
|
+
"settling",
|
|
398
|
+
"replanning",
|
|
399
|
+
"terminal"
|
|
400
|
+
],
|
|
401
|
+
"actions": [
|
|
402
|
+
"prepare_messages",
|
|
403
|
+
"approve_messages",
|
|
404
|
+
"rerun_errored_cells",
|
|
405
|
+
"start_paused_campaign",
|
|
406
|
+
"run_scheduler_sweep",
|
|
407
|
+
"scheduler_first_settle",
|
|
408
|
+
"wait_for_scheduler",
|
|
409
|
+
"wait_for_active_work",
|
|
410
|
+
"wait_for_source_import",
|
|
411
|
+
"copy_selected_source_rows",
|
|
412
|
+
"continue_signal_discovery_source",
|
|
413
|
+
"continue_sales_nav_source",
|
|
414
|
+
"continue_prospeo_source",
|
|
415
|
+
"manual_source_replenishment",
|
|
416
|
+
"refresh_paid_inmail_credits",
|
|
417
|
+
"lower_paid_inmail_threshold",
|
|
418
|
+
"switch_to_connection_lane",
|
|
419
|
+
"create_connection_campaign",
|
|
420
|
+
"next_campaign",
|
|
421
|
+
"done"
|
|
422
|
+
],
|
|
423
|
+
"receipts": [
|
|
424
|
+
"target_plan_receipt",
|
|
425
|
+
"preparation_receipt",
|
|
426
|
+
"scheduler_receipt",
|
|
427
|
+
"run_receipt"
|
|
428
|
+
],
|
|
429
|
+
"sideEffectClasses": [
|
|
430
|
+
"read_only",
|
|
431
|
+
"message_preparation",
|
|
432
|
+
"message_approval",
|
|
433
|
+
"source_replenishment",
|
|
434
|
+
"credit_refresh",
|
|
435
|
+
"campaign_start",
|
|
436
|
+
"scheduler_placement"
|
|
437
|
+
],
|
|
438
|
+
"forbiddenActions": [
|
|
439
|
+
"direct_send",
|
|
440
|
+
"raw_scheduler_write",
|
|
441
|
+
"campaign_create",
|
|
442
|
+
"campaign_archive_delete",
|
|
443
|
+
"threshold_lowering",
|
|
444
|
+
"unselected_source_mutation",
|
|
445
|
+
"unapproved_campaign_start",
|
|
446
|
+
"sender_config_write"
|
|
447
|
+
],
|
|
448
|
+
"terminalReasons": [
|
|
449
|
+
"projected_full",
|
|
450
|
+
"concrete_blocker",
|
|
451
|
+
"deadline_reached",
|
|
452
|
+
"iteration_limit",
|
|
453
|
+
"operator_stopped",
|
|
454
|
+
"capped_by_scheduler",
|
|
455
|
+
"loaded_awaiting_scheduler",
|
|
456
|
+
"lanes_exhausted",
|
|
457
|
+
"not_an_evergreen_workspace",
|
|
458
|
+
"no_refillable_campaigns"
|
|
459
|
+
],
|
|
460
|
+
"transitions": [
|
|
461
|
+
"",
|
|
462
|
+
"",
|
|
463
|
+
"",
|
|
464
|
+
"",
|
|
465
|
+
"",
|
|
466
|
+
""
|
|
467
|
+
]
|
|
468
|
+
}
|
|
285
469
|
}
|
|
286
470
|
}
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
type FindLeadsSnapshot = {
|
|
2
|
-
runId: string;
|
|
3
|
-
leadListId?: string;
|
|
4
|
-
version?: number;
|
|
5
|
-
status: string;
|
|
6
|
-
terminal?: boolean;
|
|
7
|
-
cancelled?: boolean;
|
|
8
|
-
[key: string]: unknown;
|
|
9
|
-
};
|
|
10
|
-
export declare const findLeadsRunToolDefinitions: readonly [{
|
|
11
|
-
readonly name: "bootstrap_find_leads";
|
|
12
|
-
readonly description: "Create or resume a durable campaignless Find Leads run and its lead list. No campaign or workingCampaignId is required.";
|
|
13
|
-
readonly inputSchema: {
|
|
14
|
-
readonly type: "object";
|
|
15
|
-
readonly properties: {
|
|
16
|
-
readonly bootstrapKey: {
|
|
17
|
-
readonly type: "string";
|
|
18
|
-
};
|
|
19
|
-
readonly name: {
|
|
20
|
-
readonly type: "string";
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
readonly required: readonly ["bootstrapKey"];
|
|
24
|
-
readonly additionalProperties: false;
|
|
25
|
-
};
|
|
26
|
-
}, {
|
|
27
|
-
readonly name: "get_find_leads_run";
|
|
28
|
-
readonly description: "Read the authoritative durable Find Leads snapshot.";
|
|
29
|
-
readonly inputSchema: {
|
|
30
|
-
readonly type: "object";
|
|
31
|
-
readonly properties: {
|
|
32
|
-
readonly runId: {
|
|
33
|
-
readonly type: "string";
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
readonly required: readonly ["runId"];
|
|
37
|
-
readonly additionalProperties: false;
|
|
38
|
-
};
|
|
39
|
-
}, {
|
|
40
|
-
readonly name: "update_find_leads_run";
|
|
41
|
-
readonly description: "Persist a provider/source/import approval receipt using optimistic concurrency.";
|
|
42
|
-
readonly inputSchema: {
|
|
43
|
-
readonly type: "object";
|
|
44
|
-
readonly properties: {
|
|
45
|
-
readonly runId: {
|
|
46
|
-
readonly type: "string";
|
|
47
|
-
};
|
|
48
|
-
readonly version: {
|
|
49
|
-
readonly type: "number";
|
|
50
|
-
};
|
|
51
|
-
readonly action: {
|
|
52
|
-
readonly type: "string";
|
|
53
|
-
readonly enum: readonly ["approve_provider", "approve_source_plan", "approve_import"];
|
|
54
|
-
};
|
|
55
|
-
readonly provider: {
|
|
56
|
-
readonly type: "string";
|
|
57
|
-
readonly enum: readonly ["sales-nav", "prospeo", "signal-discovery"];
|
|
58
|
-
};
|
|
59
|
-
readonly receipt: {
|
|
60
|
-
readonly type: "object";
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
readonly required: readonly ["runId", "version", "action", "receipt"];
|
|
64
|
-
readonly additionalProperties: false;
|
|
65
|
-
};
|
|
66
|
-
}, {
|
|
67
|
-
readonly name: "wait_for_find_leads_run";
|
|
68
|
-
readonly description: "Poll durable Find Leads state until it changes or reaches a terminal state. Progress notifications are optional hints only.";
|
|
69
|
-
readonly inputSchema: {
|
|
70
|
-
readonly type: "object";
|
|
71
|
-
readonly properties: {
|
|
72
|
-
readonly runId: {
|
|
73
|
-
readonly type: "string";
|
|
74
|
-
};
|
|
75
|
-
readonly timeoutMs: {
|
|
76
|
-
readonly type: "number";
|
|
77
|
-
};
|
|
78
|
-
readonly intervalMs: {
|
|
79
|
-
readonly type: "number";
|
|
80
|
-
};
|
|
81
|
-
};
|
|
82
|
-
readonly required: readonly ["runId"];
|
|
83
|
-
readonly additionalProperties: false;
|
|
84
|
-
};
|
|
85
|
-
}, {
|
|
86
|
-
readonly name: "cancel_find_leads";
|
|
87
|
-
readonly description: "Cancel a mutable Find Leads run with its current version.";
|
|
88
|
-
readonly inputSchema: {
|
|
89
|
-
readonly type: "object";
|
|
90
|
-
readonly properties: {
|
|
91
|
-
readonly runId: {
|
|
92
|
-
readonly type: "string";
|
|
93
|
-
};
|
|
94
|
-
readonly version: {
|
|
95
|
-
readonly type: "number";
|
|
96
|
-
};
|
|
97
|
-
};
|
|
98
|
-
readonly required: readonly ["runId", "version"];
|
|
99
|
-
readonly additionalProperties: false;
|
|
100
|
-
};
|
|
101
|
-
}, {
|
|
102
|
-
readonly name: "reissue_find_leads_watch_link";
|
|
103
|
-
readonly description: "Rotate and return a fresh one-time live Find Leads watch handoff. Old links are revoked and cannot be reconstructed.";
|
|
104
|
-
readonly inputSchema: {
|
|
105
|
-
readonly type: "object";
|
|
106
|
-
readonly properties: {
|
|
107
|
-
readonly runId: {
|
|
108
|
-
readonly type: "string";
|
|
109
|
-
};
|
|
110
|
-
readonly mode: {
|
|
111
|
-
readonly type: "string";
|
|
112
|
-
readonly enum: readonly ["claude", "codex", "hermes"];
|
|
113
|
-
};
|
|
114
|
-
};
|
|
115
|
-
readonly required: readonly ["runId"];
|
|
116
|
-
readonly additionalProperties: false;
|
|
117
|
-
};
|
|
118
|
-
}];
|
|
119
|
-
export declare function bootstrapFindLeads(input: {
|
|
120
|
-
bootstrapKey: string;
|
|
121
|
-
name?: string;
|
|
122
|
-
}): Promise<FindLeadsSnapshot>;
|
|
123
|
-
export declare function getFindLeadsRun(input: {
|
|
124
|
-
runId: string;
|
|
125
|
-
}): Promise<FindLeadsSnapshot>;
|
|
126
|
-
export declare function updateFindLeadsRun(input: {
|
|
127
|
-
runId: string;
|
|
128
|
-
version: number;
|
|
129
|
-
action: "approve_provider" | "approve_source_plan" | "approve_import";
|
|
130
|
-
provider?: "sales-nav" | "prospeo" | "signal-discovery";
|
|
131
|
-
receipt: Record<string, unknown>;
|
|
132
|
-
}): Promise<FindLeadsSnapshot>;
|
|
133
|
-
export declare function cancelFindLeads(input: {
|
|
134
|
-
runId: string;
|
|
135
|
-
version: number;
|
|
136
|
-
}): Promise<FindLeadsSnapshot>;
|
|
137
|
-
export declare function reissueFindLeadsWatchLink(input: {
|
|
138
|
-
runId: string;
|
|
139
|
-
mode?: "claude" | "codex" | "hermes";
|
|
140
|
-
}): Promise<{
|
|
141
|
-
runId: string;
|
|
142
|
-
leadListId: string;
|
|
143
|
-
watchUrl: string;
|
|
144
|
-
expiresAt: string;
|
|
145
|
-
}>;
|
|
146
|
-
export declare function waitForFindLeadsRun(input: {
|
|
147
|
-
runId: string;
|
|
148
|
-
timeoutMs?: number;
|
|
149
|
-
intervalMs?: number;
|
|
150
|
-
}): Promise<FindLeadsSnapshot>;
|
|
151
|
-
export {};
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { getApi } from "../api.js";
|
|
2
|
-
import { getConfig } from "../auth.js";
|
|
3
|
-
function requestOptions() {
|
|
4
|
-
const config = getConfig();
|
|
5
|
-
const workspaceId = config.activeWorkspaceId || config.workspaceId || null;
|
|
6
|
-
if (!workspaceId) {
|
|
7
|
-
throw new Error("No active Sellable workspace. Run list_workspaces then set_active_workspace and retry Find Leads.");
|
|
8
|
-
}
|
|
9
|
-
return { workspaceId };
|
|
10
|
-
}
|
|
11
|
-
export const findLeadsRunToolDefinitions = [
|
|
12
|
-
{
|
|
13
|
-
name: "bootstrap_find_leads",
|
|
14
|
-
description: "Create or resume a durable campaignless Find Leads run and its lead list. No campaign or workingCampaignId is required.",
|
|
15
|
-
inputSchema: {
|
|
16
|
-
type: "object",
|
|
17
|
-
properties: { bootstrapKey: { type: "string" }, name: { type: "string" } },
|
|
18
|
-
required: ["bootstrapKey"],
|
|
19
|
-
additionalProperties: false,
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
name: "get_find_leads_run",
|
|
24
|
-
description: "Read the authoritative durable Find Leads snapshot.",
|
|
25
|
-
inputSchema: { type: "object", properties: { runId: { type: "string" } }, required: ["runId"], additionalProperties: false },
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
name: "update_find_leads_run",
|
|
29
|
-
description: "Persist a provider/source/import approval receipt using optimistic concurrency.",
|
|
30
|
-
inputSchema: {
|
|
31
|
-
type: "object",
|
|
32
|
-
properties: {
|
|
33
|
-
runId: { type: "string" }, version: { type: "number" },
|
|
34
|
-
action: { type: "string", enum: ["approve_provider", "approve_source_plan", "approve_import"] },
|
|
35
|
-
provider: { type: "string", enum: ["sales-nav", "prospeo", "signal-discovery"] },
|
|
36
|
-
receipt: { type: "object" },
|
|
37
|
-
},
|
|
38
|
-
required: ["runId", "version", "action", "receipt"],
|
|
39
|
-
additionalProperties: false,
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
name: "wait_for_find_leads_run",
|
|
44
|
-
description: "Poll durable Find Leads state until it changes or reaches a terminal state. Progress notifications are optional hints only.",
|
|
45
|
-
inputSchema: {
|
|
46
|
-
type: "object",
|
|
47
|
-
properties: { runId: { type: "string" }, timeoutMs: { type: "number" }, intervalMs: { type: "number" } },
|
|
48
|
-
required: ["runId"], additionalProperties: false,
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
name: "cancel_find_leads",
|
|
53
|
-
description: "Cancel a mutable Find Leads run with its current version.",
|
|
54
|
-
inputSchema: { type: "object", properties: { runId: { type: "string" }, version: { type: "number" } }, required: ["runId", "version"], additionalProperties: false },
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
name: "reissue_find_leads_watch_link",
|
|
58
|
-
description: "Rotate and return a fresh one-time live Find Leads watch handoff. Old links are revoked and cannot be reconstructed.",
|
|
59
|
-
inputSchema: { type: "object", properties: { runId: { type: "string" }, mode: { type: "string", enum: ["claude", "codex", "hermes"] } }, required: ["runId"], additionalProperties: false },
|
|
60
|
-
},
|
|
61
|
-
];
|
|
62
|
-
export async function bootstrapFindLeads(input) {
|
|
63
|
-
return getApi().post("/api/v3/find-leads/runs", input, requestOptions());
|
|
64
|
-
}
|
|
65
|
-
export async function getFindLeadsRun(input) {
|
|
66
|
-
return getApi().get(`/api/v3/find-leads/runs/${encodeURIComponent(input.runId)}`, requestOptions());
|
|
67
|
-
}
|
|
68
|
-
export async function updateFindLeadsRun(input) {
|
|
69
|
-
const kind = input.action === "approve_provider"
|
|
70
|
-
? "provider_prompt"
|
|
71
|
-
: input.action === "approve_source_plan"
|
|
72
|
-
? "source_plan"
|
|
73
|
-
: "import_approval";
|
|
74
|
-
const provider = input.provider?.replace(/-/g, "_");
|
|
75
|
-
return getApi().patch(`/api/v3/find-leads/runs/${encodeURIComponent(input.runId)}`, { action: "record_receipt", version: input.version, kind, receipt: input.receipt, ...(provider ? { provider } : {}) }, requestOptions());
|
|
76
|
-
}
|
|
77
|
-
export async function cancelFindLeads(input) {
|
|
78
|
-
return getApi().patch(`/api/v3/find-leads/runs/${encodeURIComponent(input.runId)}`, { action: "cancel", version: input.version }, requestOptions());
|
|
79
|
-
}
|
|
80
|
-
export async function reissueFindLeadsWatchLink(input) {
|
|
81
|
-
return getApi().post(`/api/v3/find-leads/runs/${encodeURIComponent(input.runId)}/watch-token`, { mode: input.mode ?? (process.env.CODEX_HOME ? "codex" : "claude") }, requestOptions());
|
|
82
|
-
}
|
|
83
|
-
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
84
|
-
export async function waitForFindLeadsRun(input) {
|
|
85
|
-
const timeoutMs = Math.min(Math.max(input.timeoutMs ?? 55_000, 25), 55_000);
|
|
86
|
-
const intervalMs = Math.min(Math.max(input.intervalMs ?? 2_000, 1), 10_000);
|
|
87
|
-
const startedAt = Date.now();
|
|
88
|
-
let previousVersion;
|
|
89
|
-
let snapshot = await getFindLeadsRun(input);
|
|
90
|
-
while (!snapshot.terminal && !snapshot.cancelled && Date.now() - startedAt < timeoutMs) {
|
|
91
|
-
if (previousVersion !== undefined && snapshot.version !== previousVersion)
|
|
92
|
-
return snapshot;
|
|
93
|
-
previousVersion = snapshot.version;
|
|
94
|
-
await sleep(intervalMs);
|
|
95
|
-
snapshot = await getFindLeadsRun(input);
|
|
96
|
-
}
|
|
97
|
-
return snapshot;
|
|
98
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: find-leads-v2
|
|
3
|
-
description: Canonical approval-gated campaignless lead sourcing state machine.
|
|
4
|
-
visibility: internal
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Find Leads V2
|
|
8
|
-
|
|
9
|
-
This is the canonical campaignless workflow. The durable identity invariant is
|
|
10
|
-
`runId = leadListId`. Resume from product state with `get_find_leads_run`; never
|
|
11
|
-
reconstruct progress from chat memory.
|
|
12
|
-
|
|
13
|
-
## Prerequisites and recovery
|
|
14
|
-
|
|
15
|
-
- Call `get_auth_status`. If login is required, use `start_cli_login` and
|
|
16
|
-
`wait_for_cli_login` before retrying.
|
|
17
|
-
- Require an active workspace. If none is active, use `list_workspaces` and
|
|
18
|
-
`set_active_workspace`.
|
|
19
|
-
- If lifecycle tools, this prompt, or its flow asset are missing/outdated,
|
|
20
|
-
update the Sellable MCP/plugin, restart or reload the host, and retry.
|
|
21
|
-
- Sales Nav requires a connected LinkedIn account with an active Sales Navigator search session.
|
|
22
|
-
- Prospeo requires configured access and enough Prospeo credits for the bounded
|
|
23
|
-
plan.
|
|
24
|
-
- Signal Discovery capacity must be available; otherwise wait or choose one of
|
|
25
|
-
the other providers.
|
|
26
|
-
- For hiring-led targeting, start with `Prospeo` because its job-posting filters
|
|
27
|
-
are native. Run source work in the parent thread; do not dispatch custom source-scout subagents.
|
|
28
|
-
|
|
29
|
-
## Durable flow
|
|
30
|
-
|
|
31
|
-
1. `bootstrap_find_leads({ bootstrapKey, name })`, then show the returned watch
|
|
32
|
-
URL. On restart call `get_find_leads_run({ runId })`; if the link expired use
|
|
33
|
-
`reissue_find_leads_watch_link`. A deleted run/list is terminal: start a new
|
|
34
|
-
run only after explaining that recovery.
|
|
35
|
-
2. Draft a compact source plan: target, provider, filters/signals, sample size,
|
|
36
|
-
import cap, fallback, and expected provider cost/capacity. Ask for explicit
|
|
37
|
-
source-plan approval. Persist it with `update_find_leads_run` action
|
|
38
|
-
`approve_source_plan`. This source-plan approval permits search only.
|
|
39
|
-
3. Choose exactly one provider. Load `get_provider_prompt` for the selected provider only,
|
|
40
|
-
then call `preflight_find_leads_provider` with the current
|
|
41
|
-
run version and prompt/workflow hash. A prompt loaded for another run,
|
|
42
|
-
provider, or memory wildcard is invalid.
|
|
43
|
-
4. Search/sample through `search_sales_nav`, `search_prospeo`, or
|
|
44
|
-
`search_signals`, always passing `findLeadsRunId` and current `runVersion`.
|
|
45
|
-
For Signal, persist the approved post selection with
|
|
46
|
-
`select_promising_posts` using the same run and tab.
|
|
47
|
-
5. Present the bounded import plan and ask for a distinct import approval.
|
|
48
|
-
Persist `approve_import`; never treat source-plan approval as import approval.
|
|
49
|
-
6. Call `import_leads` with exactly one target: `findLeadsRunId`. Pass the
|
|
50
|
-
current run version and provider search/tab receipt. Never pass a campaign
|
|
51
|
-
target on this path.
|
|
52
|
-
7. Call `wait_for_lead_list_ready({ findLeadsRunId })` until ready, empty,
|
|
53
|
-
failed, or cancelled. Re-read the snapshot after timeout/retry.
|
|
54
|
-
8. Review rows with `get_rows_minimal({ tableId: runId })`. For terminal empty
|
|
55
|
-
runs, export remains valid and returns a header-only CSV.
|
|
56
|
-
9. Export with `export_table_csv({ tableId: runId })`. Do not create a second
|
|
57
|
-
export tool. Export failure must not mutate the run.
|
|
58
|
-
|
|
59
|
-
An optional Add to Campaign action is only a suggestion after review when the
|
|
60
|
-
user explicitly asks. It is never an automatic MCP step.
|
|
61
|
-
|
|
62
|
-
## Terminal states
|
|
63
|
-
|
|
64
|
-
- `failed`: show stable code, retryability, and exact next action. Resume the
|
|
65
|
-
same run when retryable.
|
|
66
|
-
- `cancelled`: do not search or import again; review/export existing rows.
|
|
67
|
-
- `ready` or `empty`: review and export.
|
|
68
|
-
|
|
69
|
-
Progress extensions and background task protocols are optional host hints, not
|
|
70
|
-
dependencies. Ordinary registered tools and the durable snapshot are enough.
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"workflow": "find-leads-v2",
|
|
3
|
-
"version": 1,
|
|
4
|
-
"identity": "runId = leadListId",
|
|
5
|
-
"providers": {
|
|
6
|
-
"sales-nav": { "prompt": "sales-nav", "searchTool": "search_sales_nav" },
|
|
7
|
-
"prospeo": { "prompt": "prospeo", "searchTool": "search_prospeo" },
|
|
8
|
-
"signal-discovery": { "prompt": "signal-discovery", "searchTool": "search_signals" }
|
|
9
|
-
},
|
|
10
|
-
"invariants": [
|
|
11
|
-
"Resume every existing run with get_find_leads_run.",
|
|
12
|
-
"A current source-plan approval permits search only.",
|
|
13
|
-
"A distinct current import approval is required before materialization.",
|
|
14
|
-
"Load and preflight the selected provider only.",
|
|
15
|
-
"Export the source table with export_table_csv using tableId equal to runId."
|
|
16
|
-
],
|
|
17
|
-
"states": [
|
|
18
|
-
{ "id": "prerequisites", "tools": ["get_auth_status", "get_active_workspace"], "transitions": { "ready": "run_watch" } },
|
|
19
|
-
{ "id": "run_watch", "tools": ["bootstrap_find_leads", "get_find_leads_run", "reissue_find_leads_watch_link"], "transitions": { "new": "source_plan", "resume_search": "search_sample", "resume_import": "materializing", "terminal": "review" } },
|
|
20
|
-
{ "id": "source_plan", "transitions": { "drafted": "source_plan_approval" } },
|
|
21
|
-
{ "id": "source_plan_approval", "tools": ["update_find_leads_run"], "transitions": { "approved": "provider_preflight", "cancel": "cancelled" } },
|
|
22
|
-
{ "id": "provider_preflight", "tools": ["get_provider_prompt", "preflight_find_leads_provider"], "transitions": { "ready": "search_sample", "blocked": "failed" } },
|
|
23
|
-
{ "id": "search_sample", "tools": ["search_sales_nav", "search_prospeo", "search_signals", "select_promising_posts"], "transitions": { "sampled": "import_plan_approval", "retryable_error": "provider_preflight", "cancel": "cancelled" } },
|
|
24
|
-
{ "id": "import_plan_approval", "tools": ["update_find_leads_run"], "transitions": { "approved": "materializing", "revise": "source_plan", "cancel": "cancelled" } },
|
|
25
|
-
{ "id": "materializing", "tools": ["import_leads", "wait_for_lead_list_ready", "get_find_leads_run"], "transitions": { "ready": "review", "empty": "review", "failed": "failed", "cancelled": "cancelled" } },
|
|
26
|
-
{ "id": "review", "tools": ["get_rows_minimal"], "transitions": { "export": "export" } },
|
|
27
|
-
{ "id": "export", "tools": ["export_table_csv"], "transitions": { "done": "review" } },
|
|
28
|
-
{ "id": "failed", "tools": ["get_find_leads_run"], "transitions": { "retry": "provider_preflight", "export_existing": "export" } },
|
|
29
|
-
{ "id": "cancelled", "tools": ["get_find_leads_run"], "transitions": { "review_existing": "review", "export_existing": "export" } }
|
|
30
|
-
]
|
|
31
|
-
}
|