@sellable/mcp 0.1.0

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.
Files changed (200) hide show
  1. package/.claude-plugin/plugin.json +12 -0
  2. package/.mcp.json +9 -0
  3. package/README.md +355 -0
  4. package/dist/api.d.ts +21 -0
  5. package/dist/api.js +73 -0
  6. package/dist/auth.d.ts +60 -0
  7. package/dist/auth.js +246 -0
  8. package/dist/engage-memory.d.ts +63 -0
  9. package/dist/engage-memory.js +354 -0
  10. package/dist/index-dev.d.ts +2 -0
  11. package/dist/index-dev.js +17 -0
  12. package/dist/index.d.ts +7 -0
  13. package/dist/index.js +8 -0
  14. package/dist/server.d.ts +1 -0
  15. package/dist/server.js +499 -0
  16. package/dist/skills.d.ts +11 -0
  17. package/dist/skills.js +97 -0
  18. package/dist/tools/auth.d.ts +30 -0
  19. package/dist/tools/auth.js +124 -0
  20. package/dist/tools/blueprint-commit.d.ts +174 -0
  21. package/dist/tools/blueprint-commit.js +286 -0
  22. package/dist/tools/bootstrap.d.ts +64 -0
  23. package/dist/tools/bootstrap.js +246 -0
  24. package/dist/tools/campaigns.d.ts +589 -0
  25. package/dist/tools/campaigns.js +892 -0
  26. package/dist/tools/cells.d.ts +58 -0
  27. package/dist/tools/cells.js +48 -0
  28. package/dist/tools/context.d.ts +88 -0
  29. package/dist/tools/context.js +271 -0
  30. package/dist/tools/csv-domains.d.ts +73 -0
  31. package/dist/tools/csv-domains.js +464 -0
  32. package/dist/tools/csv-linkedin.d.ts +102 -0
  33. package/dist/tools/csv-linkedin.js +712 -0
  34. package/dist/tools/direct-campaigns.d.ts +240 -0
  35. package/dist/tools/direct-campaigns.js +250 -0
  36. package/dist/tools/engage-bootstrap.d.ts +94 -0
  37. package/dist/tools/engage-bootstrap.js +205 -0
  38. package/dist/tools/engage-discovery.d.ts +78 -0
  39. package/dist/tools/engage-discovery.js +150 -0
  40. package/dist/tools/engage-memory.d.ts +181 -0
  41. package/dist/tools/engage-memory.js +143 -0
  42. package/dist/tools/engage-state.d.ts +72 -0
  43. package/dist/tools/engage-state.js +62 -0
  44. package/dist/tools/enrichment.d.ts +167 -0
  45. package/dist/tools/enrichment.js +174 -0
  46. package/dist/tools/flow-preflight.d.ts +68 -0
  47. package/dist/tools/flow-preflight.js +138 -0
  48. package/dist/tools/framework.d.ts +44 -0
  49. package/dist/tools/framework.js +153 -0
  50. package/dist/tools/interaction-mode.d.ts +27 -0
  51. package/dist/tools/interaction-mode.js +102 -0
  52. package/dist/tools/leads.d.ts +2417 -0
  53. package/dist/tools/leads.js +2307 -0
  54. package/dist/tools/linkedin.d.ts +210 -0
  55. package/dist/tools/linkedin.js +229 -0
  56. package/dist/tools/navigation.d.ts +91 -0
  57. package/dist/tools/navigation.js +381 -0
  58. package/dist/tools/one-off.d.ts +229 -0
  59. package/dist/tools/one-off.js +273 -0
  60. package/dist/tools/processing.d.ts +70 -0
  61. package/dist/tools/processing.js +56 -0
  62. package/dist/tools/prompts.d.ts +211 -0
  63. package/dist/tools/prompts.js +210 -0
  64. package/dist/tools/provider-preflight.d.ts +21 -0
  65. package/dist/tools/provider-preflight.js +59 -0
  66. package/dist/tools/readiness.d.ts +261 -0
  67. package/dist/tools/readiness.js +510 -0
  68. package/dist/tools/rows.d.ts +126 -0
  69. package/dist/tools/rows.js +105 -0
  70. package/dist/tools/rubrics.d.ts +497 -0
  71. package/dist/tools/rubrics.js +681 -0
  72. package/dist/tools/senders.d.ts +44 -0
  73. package/dist/tools/senders.js +69 -0
  74. package/dist/tools/sequencer.d.ts +127 -0
  75. package/dist/tools/sequencer.js +194 -0
  76. package/dist/tools/tables.d.ts +35 -0
  77. package/dist/tools/tables.js +36 -0
  78. package/dist/tools/verify-row.d.ts +36 -0
  79. package/dist/tools/verify-row.js +38 -0
  80. package/dist/tools/workspaces.d.ts +140 -0
  81. package/dist/tools/workspaces.js +139 -0
  82. package/dist/utils/workspace-root.d.ts +1 -0
  83. package/dist/utils/workspace-root.js +39 -0
  84. package/package.json +46 -0
  85. package/skills/building-gtm-tables/SKILL.md +216 -0
  86. package/skills/building-gtm-tables/core/auto-execute.yaml +19 -0
  87. package/skills/building-gtm-tables/core/blueprint-schema.json +72 -0
  88. package/skills/building-gtm-tables/references/brief-to-blueprint.md +334 -0
  89. package/skills/building-gtm-tables/references/column-type-catalog.md +318 -0
  90. package/skills/building-gtm-tables/references/common-blueprints.fixtures.ts +199 -0
  91. package/skills/building-gtm-tables/references/common-blueprints.md +44 -0
  92. package/skills/building-gtm-tables/references/failure-taxonomy.md +197 -0
  93. package/skills/building-gtm-tables/references/uat-seed-prompts.md +37 -0
  94. package/skills/building-gtm-tables/references/verify-loop.md +74 -0
  95. package/skills/campaign-messages/SKILL.md +173 -0
  96. package/skills/campaign-messages/flow.v1.json +75 -0
  97. package/skills/craft-message/SKILL.md +401 -0
  98. package/skills/create-campaign/ARCHITECTURE.md +232 -0
  99. package/skills/create-campaign/DISCUSS.md +296 -0
  100. package/skills/create-campaign/FLOW_ASCII.md +240 -0
  101. package/skills/create-campaign/HOST-PARITY-CHECKLIST.md +49 -0
  102. package/skills/create-campaign/README.md +142 -0
  103. package/skills/create-campaign/SKILL.md +286 -0
  104. package/skills/create-campaign/context/README.md +67 -0
  105. package/skills/create-campaign/context/_TEMPLATE.md +12 -0
  106. package/skills/create-campaign/context/context.md +35 -0
  107. package/skills/create-campaign/context/learnings.md +16 -0
  108. package/skills/create-campaign/context/registry.json +19 -0
  109. package/skills/create-campaign/core/flow.v1.json +217 -0
  110. package/skills/create-campaign/core/policy.md +191 -0
  111. package/skills/create-campaign/core/providers/apollo.json +35 -0
  112. package/skills/create-campaign/core/providers/prospeo.json +34 -0
  113. package/skills/create-campaign/core/providers/registry.json +31 -0
  114. package/skills/create-campaign/core/providers/sales-nav.json +37 -0
  115. package/skills/create-campaign/core/providers/signal-discovery.json +42 -0
  116. package/skills/create-campaign/references/brief-template.md +64 -0
  117. package/skills/create-campaign/references/campaign-quality.md +84 -0
  118. package/skills/create-campaign/references/copy-calibration-examples.md +120 -0
  119. package/skills/create-campaign/references/offer-patterns.md +108 -0
  120. package/skills/create-campaign/references/provider-selection-strategy.md +212 -0
  121. package/skills/create-campaign/references/question-examples.md +167 -0
  122. package/skills/create-campaign/references/token-fill-examples.md +81 -0
  123. package/skills/create-campaign-brief/ARCHITECTURE.md +72 -0
  124. package/skills/create-campaign-brief/DISCUSS.md +64 -0
  125. package/skills/create-campaign-brief/README.md +176 -0
  126. package/skills/create-campaign-brief/SKILL.md +537 -0
  127. package/skills/create-campaign-brief/references/brief-synthesis-rules.md +100 -0
  128. package/skills/create-campaign-brief/references/brief-template.md +220 -0
  129. package/skills/create-campaign-brief/references/campaign-idea-options.md +30 -0
  130. package/skills/create-campaign-brief/references/copy-appendix-template.md +62 -0
  131. package/skills/create-campaign-brief/references/draft-lifecycle.md +23 -0
  132. package/skills/create-campaign-brief/references/examples/MANIFEST.json +89 -0
  133. package/skills/create-campaign-brief/references/examples/briefs/clover.md +223 -0
  134. package/skills/create-campaign-brief/references/examples/briefs/galley.md +222 -0
  135. package/skills/create-campaign-brief/references/examples/briefs/gelee.md +220 -0
  136. package/skills/create-campaign-brief/references/examples/briefs/hey-digital.md +234 -0
  137. package/skills/create-campaign-brief/references/examples/briefs/persona.md +231 -0
  138. package/skills/create-campaign-brief/references/examples/briefs/revvix.md +220 -0
  139. package/skills/create-campaign-brief/references/examples/briefs/sellable-dev.md +220 -0
  140. package/skills/create-campaign-brief/references/examples/briefs/superposition.md +233 -0
  141. package/skills/create-campaign-brief/references/examples/briefs/superpower.md +219 -0
  142. package/skills/create-campaign-brief/references/examples/briefs/westpark-villas.md +220 -0
  143. package/skills/create-campaign-brief/references/icp-lock-question-bank.md +43 -0
  144. package/skills/create-campaign-brief/references/messaging-inputs.md +58 -0
  145. package/skills/create-campaign-brief/references/output-acceptance-rubric.md +62 -0
  146. package/skills/create-campaign-brief/references/phase75-active-runtime-message-pack.md +248 -0
  147. package/skills/create-campaign-brief/references/phase75-canonical-brief-template.md +319 -0
  148. package/skills/create-campaign-brief/references/phase75-good-brief-and-messaging-examples.md +445 -0
  149. package/skills/create-campaign-brief/references/quick-research-protocol.md +39 -0
  150. package/skills/create-campaign-brief/references/reference-sheet-protocol.md +60 -0
  151. package/skills/create-campaign-brief/references/zero-shot-iteration-rules.md +66 -0
  152. package/skills/create-campaign-v2/SKILL.md +1619 -0
  153. package/skills/create-campaign-v2/core/auto-execute.README.md +219 -0
  154. package/skills/create-campaign-v2/core/auto-execute.yaml +121 -0
  155. package/skills/create-campaign-v2/core/flow.v2.json +1643 -0
  156. package/skills/create-campaign-v2/core/policy.md +82 -0
  157. package/skills/create-campaign-v2/references/ai-tells.md +253 -0
  158. package/skills/create-campaign-v2/references/approval-gate-framing.md +346 -0
  159. package/skills/create-campaign-v2/references/draft-lifecycle.md +110 -0
  160. package/skills/create-campaign-v2/references/escalation-ladder.md +119 -0
  161. package/skills/create-campaign-v2/references/filter-leads.md +495 -0
  162. package/skills/create-campaign-v2/references/final-handoff-contract.md +176 -0
  163. package/skills/create-campaign-v2/references/gold-standard-message-examples.md +394 -0
  164. package/skills/create-campaign-v2/references/gold-standard-message-patterns.md +314 -0
  165. package/skills/create-campaign-v2/references/gold-standard-message-validation-example.md +212 -0
  166. package/skills/create-campaign-v2/references/lead-validation-preview.md +172 -0
  167. package/skills/create-campaign-v2/references/parallel-critique-protocol.md +368 -0
  168. package/skills/create-campaign-v2/references/sample-validation-loop.md +289 -0
  169. package/skills/create-campaign-v2/references/step-13-import-leads.md +151 -0
  170. package/skills/create-campaign-v2/references/step-15-re-cascade.md +90 -0
  171. package/skills/create-campaign-v2/references/thomas-revision-filters.md +521 -0
  172. package/skills/create-campaign-v2/references/thomas-variant-selection.md +202 -0
  173. package/skills/create-campaign-v2/references/tier-routing-matrix.md +66 -0
  174. package/skills/create-campaign-v2/references/validation-criteria.md +367 -0
  175. package/skills/create-campaign-v2/references/watch-link-handoff.md +106 -0
  176. package/skills/create-campaign-v2-validation/SKILL.md +296 -0
  177. package/skills/create-post/SKILL.md +1308 -0
  178. package/skills/create-rubric/SKILL.md +251 -0
  179. package/skills/engage/SKILL.md +549 -0
  180. package/skills/engage/core/README.md +23 -0
  181. package/skills/engage/core/proven-searches.json +11 -0
  182. package/skills/engage/core/style-guide.template.md +47 -0
  183. package/skills/engage/core/tracked-people.json +10 -0
  184. package/skills/enrich-prospects/SKILL.md +97 -0
  185. package/skills/find-leads/SKILL.md +467 -0
  186. package/skills/generate-messages/SKILL.md +2361 -0
  187. package/skills/interview/SKILL.md +132 -0
  188. package/skills/interview/core/ENGAGE_STYLE_GUIDE.template.md +54 -0
  189. package/skills/interview/core/ICP.template.md +54 -0
  190. package/skills/interview/core/VOICE_PROFILE.template.md +101 -0
  191. package/skills/providers/apollo.md +520 -0
  192. package/skills/providers/prospeo.md +398 -0
  193. package/skills/providers/sales-nav.md +372 -0
  194. package/skills/providers/signal-discovery.md +495 -0
  195. package/skills/research/SKILL.md +258 -0
  196. package/skills/research/config.json +9 -0
  197. package/skills/research/override.md +13 -0
  198. package/skills/research-prospect/SKILL.md +99 -0
  199. package/skills/research-sender/SKILL.md +158 -0
  200. package/skills/workflow-sequences/SKILL.md +85 -0
@@ -0,0 +1,381 @@
1
+ import { existsSync, readFileSync } from "fs";
2
+ import { dirname, isAbsolute, join, resolve } from "path";
3
+ import { getApi } from "../api.js";
4
+ import { resolveWorkspaceRoot } from "../utils/workspace-root.js";
5
+ import { getTableRowsMinimal } from "./rows.js";
6
+ const entryPath = process.argv[1] ? resolve(process.argv[1]) : process.cwd();
7
+ const entryDir = dirname(entryPath);
8
+ const workspaceRoot = resolveWorkspaceRoot(entryDir);
9
+ const frameworkRoot = join(workspaceRoot, "mcp/sellable/skills/create-campaign");
10
+ function isTruthyFlag(value) {
11
+ if (!value)
12
+ return false;
13
+ const normalized = value.trim().toLowerCase();
14
+ return (normalized === "1" ||
15
+ normalized === "true" ||
16
+ normalized === "yes" ||
17
+ normalized === "on" ||
18
+ normalized === "all" ||
19
+ normalized === "debug");
20
+ }
21
+ function isFalsyFlag(value) {
22
+ if (!value)
23
+ return false;
24
+ const normalized = value.trim().toLowerCase();
25
+ return (normalized === "0" ||
26
+ normalized === "false" ||
27
+ normalized === "no" ||
28
+ normalized === "off");
29
+ }
30
+ function isNavigationDebugEnabled() {
31
+ const primary = process.env.SELLABLE_NAV_DEBUG;
32
+ const secondary = process.env.SELLABLE_DEBUG_NAVIGATION;
33
+ // Keep test output stable unless explicitly requested.
34
+ if (process.env.NODE_ENV === "test") {
35
+ if (isTruthyFlag(primary) || isTruthyFlag(secondary))
36
+ return true;
37
+ if (isFalsyFlag(primary) || isFalsyFlag(secondary))
38
+ return false;
39
+ return false;
40
+ }
41
+ if (isTruthyFlag(primary) || isTruthyFlag(secondary))
42
+ return true;
43
+ if (isFalsyFlag(primary) || isFalsyFlag(secondary))
44
+ return false;
45
+ // Default-off in production; enable explicitly via env flags.
46
+ return false;
47
+ }
48
+ function getNavigationDebugCampaignFilters() {
49
+ const raw = process.env.SELLABLE_NAV_DEBUG_CAMPAIGN_IDS ||
50
+ process.env.SELLABLE_NAV_DEBUG_CAMPAIGNS ||
51
+ "";
52
+ const ids = raw
53
+ .split(",")
54
+ .map((value) => value.trim())
55
+ .filter(Boolean);
56
+ return ids.length > 0 ? new Set(ids) : null;
57
+ }
58
+ function shouldLogNavigation(campaignId) {
59
+ if (!isNavigationDebugEnabled())
60
+ return false;
61
+ const filters = getNavigationDebugCampaignFilters();
62
+ if (!filters)
63
+ return true;
64
+ if (!campaignId)
65
+ return false;
66
+ return filters.has(campaignId);
67
+ }
68
+ export function logNavigationDebug(event, payload = {}, campaignId) {
69
+ const effectiveCampaignId = campaignId ||
70
+ (typeof payload.campaignId === "string" ? payload.campaignId : null);
71
+ if (!shouldLogNavigation(effectiveCampaignId))
72
+ return;
73
+ // MCP stdio protocol uses stdout; write diagnostics to stderr only.
74
+ console.error(`[sellable:navigation] ${JSON.stringify({
75
+ ts: new Date().toISOString(),
76
+ event,
77
+ ...payload,
78
+ })}`);
79
+ }
80
+ function resolveFromRoot(filePath) {
81
+ if (isAbsolute(filePath))
82
+ return filePath;
83
+ return resolve(workspaceRoot, filePath);
84
+ }
85
+ function readJson(filePath) {
86
+ const raw = readFileSync(filePath, "utf-8");
87
+ return JSON.parse(raw);
88
+ }
89
+ function loadProviderConfigs() {
90
+ const registryPath = join(frameworkRoot, "core/providers/registry.json");
91
+ if (!existsSync(registryPath)) {
92
+ logNavigationDebug("provider_configs.registry_missing", {
93
+ registryPath,
94
+ workspaceRoot,
95
+ });
96
+ return {};
97
+ }
98
+ const registry = readJson(registryPath);
99
+ const configs = {};
100
+ const failures = [];
101
+ for (const entry of registry.providers) {
102
+ try {
103
+ const configPath = resolveFromRoot(entry.configPath);
104
+ const cfg = readJson(configPath);
105
+ configs[entry.id] = cfg;
106
+ }
107
+ catch (error) {
108
+ failures.push({
109
+ providerId: entry.id,
110
+ error: error instanceof Error ? error.message : String(error),
111
+ });
112
+ // Ignore provider config failures; diagnostics will reflect missing data.
113
+ }
114
+ }
115
+ logNavigationDebug("provider_configs.loaded", {
116
+ registryPath,
117
+ providerCount: Object.keys(configs).length,
118
+ providerIds: Object.keys(configs),
119
+ failedCount: failures.length,
120
+ failures,
121
+ });
122
+ return configs;
123
+ }
124
+ function getBriefContent(brief) {
125
+ if (!brief)
126
+ return "";
127
+ if (typeof brief === "string")
128
+ return brief;
129
+ return brief.content || "";
130
+ }
131
+ function checkCampaignCreated(campaign) {
132
+ const missing = [];
133
+ if (!campaign.id)
134
+ missing.push("campaignId");
135
+ if (!campaign.clientProspectId)
136
+ missing.push("clientProspectId");
137
+ if (!getBriefContent(campaign.campaignBrief).trim()) {
138
+ missing.push("campaignBrief.content");
139
+ }
140
+ return { stepId: "campaign-created", missing };
141
+ }
142
+ function checkPickProvider(campaign) {
143
+ const missing = [];
144
+ if (!campaign.leadSourceType) {
145
+ missing.push("leadSourceType");
146
+ }
147
+ return { stepId: "pick-provider", missing };
148
+ }
149
+ function checkProviderSearch(campaign) {
150
+ const missing = [];
151
+ if (campaign.leadSourceType !== "new") {
152
+ return { stepId: "provider-search", missing };
153
+ }
154
+ if (!campaign.leadSourceProvider)
155
+ missing.push("leadSourceProvider");
156
+ return { stepId: "provider-search", missing };
157
+ }
158
+ function checkConfirmLeadList(campaign, hasWorkflowRows, enforceRowCheck) {
159
+ const missing = [];
160
+ if (!campaign.selectedLeadListId)
161
+ missing.push("selectedLeadListId");
162
+ if (!campaign.workflowTableId)
163
+ missing.push("workflowTableId");
164
+ if (enforceRowCheck && hasWorkflowRows === false) {
165
+ missing.push("workflowTableRows");
166
+ }
167
+ return { stepId: "confirm-lead-list", missing };
168
+ }
169
+ function mapHeadlessToUiStep(step) {
170
+ if (!step)
171
+ return null;
172
+ if (step === "configure-columns" || step === "confirm-lead-list") {
173
+ return "leads";
174
+ }
175
+ if (step === "create-offer")
176
+ return "plan";
177
+ if (step === "pick-provider")
178
+ return "pick-provider";
179
+ if (step === "apollo" || step === "sales-nav" || step === "prospeo") {
180
+ return "contact-search";
181
+ }
182
+ if (step === "signal-discovery")
183
+ return "signal-discovery";
184
+ if (step === "signal-discovery-results")
185
+ return "leads";
186
+ if (step === "filter-choice")
187
+ return "filter-choice";
188
+ return null;
189
+ }
190
+ export const navigationToolDefinitions = [
191
+ {
192
+ name: "get_campaign_navigation_state",
193
+ description: "Internal/debug: compute deterministic create-campaign navigation state and diagnostics from the saved campaign plus a lightweight table row-count check.",
194
+ inputSchema: {
195
+ type: "object",
196
+ properties: {
197
+ campaignId: {
198
+ type: "string",
199
+ description: "Campaign offer ID",
200
+ },
201
+ includeTableCheck: {
202
+ type: "boolean",
203
+ description: "When true (default), check workflow table row count using a minimal query.",
204
+ },
205
+ },
206
+ required: ["campaignId"],
207
+ additionalProperties: false,
208
+ },
209
+ },
210
+ ];
211
+ export function computeCampaignNavigationStateFromCampaign(campaign, options) {
212
+ const briefContent = getBriefContent(campaign.campaignBrief);
213
+ logNavigationDebug("compute.start", {
214
+ campaignId: campaign.id,
215
+ campaign: {
216
+ id: campaign.id,
217
+ clientProspectId: campaign.clientProspectId ?? null,
218
+ hasOfferPositioning: Boolean(campaign.offerPositioning),
219
+ briefLength: briefContent.trim().length,
220
+ leadSourceType: campaign.leadSourceType ?? null,
221
+ leadSourceProvider: campaign.leadSourceProvider ?? null,
222
+ selectedLeadListId: campaign.selectedLeadListId ?? null,
223
+ workflowTableId: campaign.workflowTableId ?? null,
224
+ currentStep: campaign.currentStep ?? null,
225
+ },
226
+ options: {
227
+ includeTableCheck: options.includeTableCheck,
228
+ tableChecked: options.tableChecked,
229
+ rowCount: options.rowCount,
230
+ hasWorkflowRows: options.hasWorkflowRows,
231
+ initialWarningsCount: options.initialWarnings?.length ?? 0,
232
+ },
233
+ }, campaign.id);
234
+ const warnings = [...(options.initialWarnings || [])];
235
+ const providerConfigs = loadProviderConfigs();
236
+ const providerConfig = campaign.leadSourceProvider
237
+ ? providerConfigs[campaign.leadSourceProvider]
238
+ : undefined;
239
+ const enforceRowCheck = options.includeTableCheck && options.tableChecked;
240
+ if (options.includeTableCheck &&
241
+ campaign.workflowTableId &&
242
+ !options.tableChecked) {
243
+ warnings.push("Workflow table row count not checked.");
244
+ }
245
+ const checks = [
246
+ checkCampaignCreated(campaign),
247
+ checkPickProvider(campaign),
248
+ checkProviderSearch(campaign),
249
+ checkConfirmLeadList(campaign, options.hasWorkflowRows, enforceRowCheck),
250
+ ];
251
+ let computedStep = "campaign-created";
252
+ let blockedAt = null;
253
+ let missing = [];
254
+ for (const check of checks) {
255
+ logNavigationDebug("compute.check", {
256
+ campaignId: campaign.id,
257
+ stepId: check.stepId,
258
+ missing: check.missing,
259
+ passed: check.missing.length === 0,
260
+ }, campaign.id);
261
+ if (check.missing.length > 0) {
262
+ blockedAt = check.stepId;
263
+ missing = check.missing;
264
+ break;
265
+ }
266
+ computedStep = check.stepId;
267
+ }
268
+ const expectedHeadlessStep = computedStep === "campaign-created"
269
+ ? "create-offer"
270
+ : computedStep === "provider-search"
271
+ ? providerConfig?.currentStep || campaign.leadSourceProvider || null
272
+ : computedStep;
273
+ const stepAligned = !campaign.currentStep || !expectedHeadlessStep
274
+ ? null
275
+ : campaign.currentStep === expectedHeadlessStep;
276
+ if (stepAligned === false && campaign.currentStep && expectedHeadlessStep) {
277
+ warnings.push(`Headless step mismatch: expected "${expectedHeadlessStep}" but campaign.currentStep is "${campaign.currentStep}".`);
278
+ }
279
+ if (!providerConfig && campaign.leadSourceProvider) {
280
+ warnings.push(`Provider config not found for "${campaign.leadSourceProvider}".`);
281
+ }
282
+ const result = {
283
+ campaignId: campaign.id,
284
+ computedStep,
285
+ blockedAt,
286
+ missing,
287
+ expectedHeadlessStep,
288
+ headlessCurrentStep: campaign.currentStep ?? null,
289
+ uiStep: mapHeadlessToUiStep(campaign.currentStep),
290
+ table: {
291
+ workflowTableId: campaign.workflowTableId ?? null,
292
+ checked: options.tableChecked,
293
+ rowCount: options.rowCount,
294
+ hasRows: options.hasWorkflowRows,
295
+ },
296
+ context: {
297
+ leadSourceType: campaign.leadSourceType ?? null,
298
+ leadSourceProvider: campaign.leadSourceProvider ?? null,
299
+ selectedLeadListId: campaign.selectedLeadListId ?? null,
300
+ providerCurrentStep: providerConfig?.currentStep ?? null,
301
+ },
302
+ warnings,
303
+ };
304
+ logNavigationDebug("compute.result", {
305
+ campaignId: campaign.id,
306
+ computedStep: result.computedStep,
307
+ blockedAt: result.blockedAt,
308
+ missing: result.missing,
309
+ expectedHeadlessStep: result.expectedHeadlessStep,
310
+ headlessCurrentStep: result.headlessCurrentStep,
311
+ uiStep: result.uiStep,
312
+ table: result.table,
313
+ context: result.context,
314
+ warnings: result.warnings,
315
+ }, campaign.id);
316
+ return result;
317
+ }
318
+ export async function getCampaignNavigationState(input) {
319
+ const includeTableCheck = input.includeTableCheck !== false;
320
+ const api = getApi();
321
+ logNavigationDebug("state.fetch_campaign.start", {
322
+ campaignId: input.campaignId,
323
+ includeTableCheck,
324
+ }, input.campaignId);
325
+ const campaign = await api.get(`/api/v2/campaign-offers/${input.campaignId}`);
326
+ logNavigationDebug("state.fetch_campaign.success", {
327
+ campaignId: input.campaignId,
328
+ workflowTableId: campaign.workflowTableId ?? null,
329
+ currentStep: campaign.currentStep ?? null,
330
+ leadSourceProvider: campaign.leadSourceProvider ?? null,
331
+ selectedLeadListId: campaign.selectedLeadListId ?? null,
332
+ }, input.campaignId);
333
+ let tableRowCount = null;
334
+ let hasWorkflowRows = null;
335
+ const warnings = [];
336
+ let tableChecked = false;
337
+ if (includeTableCheck && campaign.workflowTableId) {
338
+ logNavigationDebug("state.table_check.start", {
339
+ campaignId: input.campaignId,
340
+ workflowTableId: campaign.workflowTableId,
341
+ }, input.campaignId);
342
+ try {
343
+ const rows = await getTableRowsMinimal(campaign.workflowTableId, {
344
+ limit: 1,
345
+ page: 1,
346
+ });
347
+ tableChecked = true;
348
+ tableRowCount = rows.pagination?.totalCount ?? 0;
349
+ hasWorkflowRows = tableRowCount > 0;
350
+ logNavigationDebug("state.table_check.success", {
351
+ campaignId: input.campaignId,
352
+ workflowTableId: campaign.workflowTableId,
353
+ rowCount: tableRowCount,
354
+ hasRows: hasWorkflowRows,
355
+ }, input.campaignId);
356
+ }
357
+ catch (error) {
358
+ warnings.push(`Failed to check workflow table rows: ${error instanceof Error ? error.message : String(error)}`);
359
+ logNavigationDebug("state.table_check.error", {
360
+ campaignId: input.campaignId,
361
+ workflowTableId: campaign.workflowTableId,
362
+ error: error instanceof Error ? error.message : String(error),
363
+ }, input.campaignId);
364
+ }
365
+ }
366
+ const result = computeCampaignNavigationStateFromCampaign(campaign, {
367
+ includeTableCheck,
368
+ tableChecked,
369
+ rowCount: tableRowCount,
370
+ hasWorkflowRows,
371
+ initialWarnings: warnings,
372
+ });
373
+ logNavigationDebug("state.complete", {
374
+ campaignId: input.campaignId,
375
+ computedStep: result.computedStep,
376
+ blockedAt: result.blockedAt,
377
+ missing: result.missing,
378
+ warnings: result.warnings,
379
+ }, input.campaignId);
380
+ return result;
381
+ }
@@ -0,0 +1,229 @@
1
+ export type CreateOnDemandTableInput = {
2
+ name: string;
3
+ senderIds?: string[];
4
+ clientProspectId: string;
5
+ offerPositioning?: Record<string, unknown>;
6
+ campaignBrief?: unknown;
7
+ };
8
+ export type AddOnDemandLeadsInput = {
9
+ tableId: string;
10
+ leads: Array<{
11
+ linkedinUrl: string;
12
+ name?: string;
13
+ title?: string;
14
+ companyWebsite?: string;
15
+ location?: string;
16
+ }>;
17
+ skipDuplicates?: boolean;
18
+ };
19
+ export type OnDemandTableIdInput = {
20
+ tableId: string;
21
+ };
22
+ export type InitOnDemandSequenceInput = {
23
+ tableId: string;
24
+ template?: Record<string, unknown>;
25
+ confirmed?: boolean;
26
+ };
27
+ export type CreateOnDemandCampaignInput = {
28
+ name: string;
29
+ clientProspectId: string;
30
+ senderIds: string[];
31
+ campaignBrief?: unknown;
32
+ offerPositioning?: Record<string, unknown>;
33
+ sequenceTemplate?: Record<string, unknown>;
34
+ confirmed?: boolean;
35
+ };
36
+ export declare const onDemandToolDefinitions: ({
37
+ name: string;
38
+ description: string;
39
+ inputSchema: {
40
+ type: string;
41
+ properties: {
42
+ name: {
43
+ type: string;
44
+ description: string;
45
+ };
46
+ senderIds: {
47
+ type: string;
48
+ items: {
49
+ type: string;
50
+ };
51
+ description: string;
52
+ };
53
+ clientProspectId: {
54
+ type: string;
55
+ description: string;
56
+ };
57
+ offerPositioning: {
58
+ type: string;
59
+ description: string;
60
+ };
61
+ campaignBrief: {
62
+ description: string;
63
+ };
64
+ sequenceTemplate?: undefined;
65
+ confirmed?: undefined;
66
+ tableId?: undefined;
67
+ leads?: undefined;
68
+ skipDuplicates?: undefined;
69
+ template?: undefined;
70
+ };
71
+ required: string[];
72
+ };
73
+ } | {
74
+ name: string;
75
+ description: string;
76
+ inputSchema: {
77
+ type: string;
78
+ properties: {
79
+ name: {
80
+ type: string;
81
+ description: string;
82
+ };
83
+ clientProspectId: {
84
+ type: string;
85
+ description: string;
86
+ };
87
+ senderIds: {
88
+ type: string;
89
+ items: {
90
+ type: string;
91
+ };
92
+ description: string;
93
+ };
94
+ campaignBrief: {
95
+ description: string;
96
+ };
97
+ offerPositioning: {
98
+ type: string;
99
+ description: string;
100
+ };
101
+ sequenceTemplate: {
102
+ type: string;
103
+ description: string;
104
+ };
105
+ confirmed: {
106
+ type: string;
107
+ description: string;
108
+ };
109
+ tableId?: undefined;
110
+ leads?: undefined;
111
+ skipDuplicates?: undefined;
112
+ template?: undefined;
113
+ };
114
+ required: string[];
115
+ };
116
+ } | {
117
+ name: string;
118
+ description: string;
119
+ inputSchema: {
120
+ type: string;
121
+ properties: {
122
+ tableId: {
123
+ type: string;
124
+ description: string;
125
+ };
126
+ leads: {
127
+ type: string;
128
+ description: string;
129
+ items: {
130
+ type: string;
131
+ properties: {
132
+ linkedinUrl: {
133
+ type: string;
134
+ };
135
+ name: {
136
+ type: string;
137
+ };
138
+ title: {
139
+ type: string;
140
+ };
141
+ companyWebsite: {
142
+ type: string;
143
+ };
144
+ location: {
145
+ type: string;
146
+ };
147
+ };
148
+ required: string[];
149
+ };
150
+ };
151
+ skipDuplicates: {
152
+ type: string;
153
+ description: string;
154
+ };
155
+ name?: undefined;
156
+ senderIds?: undefined;
157
+ clientProspectId?: undefined;
158
+ offerPositioning?: undefined;
159
+ campaignBrief?: undefined;
160
+ sequenceTemplate?: undefined;
161
+ confirmed?: undefined;
162
+ template?: undefined;
163
+ };
164
+ required: string[];
165
+ };
166
+ } | {
167
+ name: string;
168
+ description: string;
169
+ inputSchema: {
170
+ type: string;
171
+ properties: {
172
+ tableId: {
173
+ type: string;
174
+ description?: undefined;
175
+ };
176
+ name?: undefined;
177
+ senderIds?: undefined;
178
+ clientProspectId?: undefined;
179
+ offerPositioning?: undefined;
180
+ campaignBrief?: undefined;
181
+ sequenceTemplate?: undefined;
182
+ confirmed?: undefined;
183
+ leads?: undefined;
184
+ skipDuplicates?: undefined;
185
+ template?: undefined;
186
+ };
187
+ required: string[];
188
+ };
189
+ } | {
190
+ name: string;
191
+ description: string;
192
+ inputSchema: {
193
+ type: string;
194
+ properties: {
195
+ tableId: {
196
+ type: string;
197
+ description?: undefined;
198
+ };
199
+ template: {
200
+ type: string;
201
+ description: string;
202
+ };
203
+ confirmed: {
204
+ type: string;
205
+ description: string;
206
+ };
207
+ name?: undefined;
208
+ senderIds?: undefined;
209
+ clientProspectId?: undefined;
210
+ offerPositioning?: undefined;
211
+ campaignBrief?: undefined;
212
+ sequenceTemplate?: undefined;
213
+ leads?: undefined;
214
+ skipDuplicates?: undefined;
215
+ };
216
+ required: string[];
217
+ };
218
+ })[];
219
+ export declare function createOnDemandTable(input: CreateOnDemandTableInput): Promise<unknown>;
220
+ export declare function addOnDemandLeads(input: AddOnDemandLeadsInput): Promise<unknown>;
221
+ export declare function startOnDemandCampaign(input: OnDemandTableIdInput): Promise<unknown>;
222
+ export declare function pauseOnDemandCampaign(input: OnDemandTableIdInput): Promise<unknown>;
223
+ export declare function initOnDemandSequence(input: InitOnDemandSequenceInput): Promise<unknown>;
224
+ export declare function createOnDemandCampaign(input: CreateOnDemandCampaignInput): Promise<{
225
+ tableId: string;
226
+ campaignOfferId: string;
227
+ senderIds: string[];
228
+ sequenceInitialized: boolean;
229
+ }>;