@sellable/mcp 0.1.511 → 0.1.513

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.
@@ -0,0 +1,273 @@
1
+ import * as path from "node:path";
2
+ import { getApi, SellableApiError } from "../api.js";
3
+ import { appendIndexLine, appendJournalEvent, createRunJournal, renderBootstrapSection, renderPlanSection, renderTerminalSection, } from "../refill-journal.js";
4
+ import { readRefillWorkspaceState } from "../refill-local-state.js";
5
+ import { normalizeExplicitWorkspaceId, workspaceRequestOptions, } from "./workspace-context.js";
6
+ const KNOWN_TOP_LEVEL_FIELDS = [
7
+ "readOnly",
8
+ "generatedAt",
9
+ "bootstrap",
10
+ "plans",
11
+ "globalActionQueue",
12
+ "evergreen",
13
+ "planRevision",
14
+ "stateRevision",
15
+ "packet",
16
+ "sideEffects",
17
+ "warnings",
18
+ ];
19
+ // MCP mirror maintenance note:
20
+ // Evergreen rung vocabulary restatements track canonical EVERGREEN_RUNG_ORDER in
21
+ // src/lib/workflow-tables/refill-target-plan.ts. pr1 token checks track
22
+ // PR1_TOKEN_REGEX in src/lib/workflow-tables/plan-revision.ts.
23
+ function isRecord(value) {
24
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
25
+ }
26
+ function deepClone(value) {
27
+ return JSON.parse(JSON.stringify(value));
28
+ }
29
+ export function sanitizeEvergreenRefillPlanResult(value) {
30
+ if (!isRecord(value))
31
+ return {};
32
+ const sanitized = {};
33
+ for (const key of KNOWN_TOP_LEVEL_FIELDS) {
34
+ if (value[key] !== undefined)
35
+ sanitized[key] = deepClone(value[key]);
36
+ }
37
+ return sanitized;
38
+ }
39
+ function buildRunStateFromLocalHints(workspaceId) {
40
+ const state = readRefillWorkspaceState(workspaceId);
41
+ return {
42
+ version: 1,
43
+ senderCursors: [],
44
+ laneCooldowns: state?.laneMemory ?? [],
45
+ passRates: state?.passRates ?? [],
46
+ };
47
+ }
48
+ async function postRefillPlanV2(body, workspaceId) {
49
+ const api = getApi();
50
+ const requestOptions = workspaceRequestOptions(workspaceId);
51
+ return requestOptions
52
+ ? api.post("/api/v3/mcp/evergreen-refill-plan", body, requestOptions)
53
+ : api.post("/api/v3/mcp/evergreen-refill-plan", body);
54
+ }
55
+ function planSummaryLines(result) {
56
+ const plans = Array.isArray(result.plans) ? result.plans : [];
57
+ return plans.flatMap((plan) => {
58
+ if (!isRecord(plan))
59
+ return [];
60
+ const itinerary = isRecord(plan.itinerary) ? plan.itinerary : null;
61
+ const chosen = isRecord(itinerary?.chosen) ? itinerary?.chosen : null;
62
+ const fallback = isRecord(itinerary?.fallback) ? itinerary?.fallback : null;
63
+ return [
64
+ `${String(plan.senderId ?? "unknown")}: ${String(chosen?.summary ?? "no chosen rung")}`,
65
+ fallback ? `fallback: ${String(fallback.trigger ?? "")}` : null,
66
+ ].filter((line) => Boolean(line));
67
+ });
68
+ }
69
+ function writeDryRunJournal(params) {
70
+ const created = createRunJournal({
71
+ workspaceId: params.workspaceId,
72
+ dryRun: true,
73
+ });
74
+ const bootstrap = isRecord(params.result.bootstrap)
75
+ ? params.result.bootstrap
76
+ : {};
77
+ appendJournalEvent(created.filePath, renderBootstrapSection({
78
+ summary: "Refill v2 dry-run bootstrap across managed waterfall, dashboard evergreen, and active campaign lanes",
79
+ senderSummary: JSON.stringify(bootstrap.senders ?? []),
80
+ laneSummary: JSON.stringify(bootstrap.laneOrder ?? []),
81
+ targetSummary: JSON.stringify(bootstrap.target ?? []),
82
+ creditSummary: JSON.stringify(bootstrap.paidCredit ?? []),
83
+ }));
84
+ const plans = Array.isArray(params.result.plans) ? params.result.plans : [];
85
+ for (const plan of plans) {
86
+ if (!isRecord(plan))
87
+ continue;
88
+ const itinerary = isRecord(plan.itinerary) ? plan.itinerary : {};
89
+ const chosen = isRecord(itinerary.chosen) ? itinerary.chosen : {};
90
+ const projected = Array.isArray(itinerary.projected)
91
+ ? itinerary.projected
92
+ : [];
93
+ const fallback = isRecord(itinerary.fallback) ? itinerary.fallback : {};
94
+ appendJournalEvent(created.filePath, renderPlanSection({
95
+ chosenSummary: String(chosen.summary ?? "No chosen rung"),
96
+ itinerarySummaries: projected
97
+ .filter(isRecord)
98
+ .map((entry) => String(entry.summary ?? "")),
99
+ fallbackSummary: String(fallback.trigger ?? ""),
100
+ }));
101
+ }
102
+ appendJournalEvent(created.filePath, renderTerminalSection({
103
+ summary: [
104
+ `planRevision=${String(params.result.planRevision ?? "")}`,
105
+ `stateRevision=${String(params.result.stateRevision ?? "")}`,
106
+ params.journalNote ?? null,
107
+ ]
108
+ .filter(Boolean)
109
+ .join(" "),
110
+ }));
111
+ appendIndexLine({
112
+ runId: created.runId,
113
+ fileName: path.basename(created.filePath),
114
+ workspaceId: params.workspaceId,
115
+ dryRun: true,
116
+ summary: "refill v2 dry-run",
117
+ });
118
+ return created.filePath;
119
+ }
120
+ function writeWorkspaceAccessJournal(params) {
121
+ const created = createRunJournal({
122
+ workspaceId: params.workspaceId,
123
+ dryRun: true,
124
+ });
125
+ appendJournalEvent(created.filePath, renderBootstrapSection({
126
+ summary: "Refill v2 dry-run bootstrap stopped at workspace access",
127
+ senderSummary: "[]",
128
+ laneSummary: "[]",
129
+ targetSummary: `workspaceId=${params.workspaceId}`,
130
+ creditSummary: "[]",
131
+ }));
132
+ appendJournalEvent(created.filePath, renderPlanSection({
133
+ chosenSummary: "workspace_access blocker",
134
+ itinerarySummaries: ["No workspace campaign state read"],
135
+ fallbackSummary: "terminal:workspace_access",
136
+ }));
137
+ appendJournalEvent(created.filePath, renderTerminalSection({
138
+ summary: `blocker=workspace_access workspaceId=${params.workspaceId} ${params.guidance}`,
139
+ }));
140
+ appendIndexLine({
141
+ runId: created.runId,
142
+ fileName: path.basename(created.filePath),
143
+ workspaceId: params.workspaceId,
144
+ dryRun: true,
145
+ summary: "refill v2 dry-run workspace_access blocker",
146
+ });
147
+ return created.filePath;
148
+ }
149
+ function isWorkspaceAccessError(error) {
150
+ return (error instanceof SellableApiError &&
151
+ error.status === 403 &&
152
+ error.body.includes("No access to workspace"));
153
+ }
154
+ export const refillPlanV2ToolDefinitions = [
155
+ {
156
+ name: "get_refill_plan_v2",
157
+ description: "Read-only refill sends v2 dry-run planner across managed waterfall, dashboard evergreen, and active campaign lanes. It performs no mutations, does not schedule, send, approve, prepare, or refresh credits, and writes a local dry-run journal file unless journal:false is passed.",
158
+ inputSchema: {
159
+ type: "object",
160
+ properties: {
161
+ workspaceId: {
162
+ type: "string",
163
+ description: "Explicit request-scoped workspace id.",
164
+ },
165
+ senderIds: {
166
+ type: "array",
167
+ items: { type: "string" },
168
+ },
169
+ runState: {
170
+ type: "object",
171
+ description: "Optional synthetic v1 run state. When provided, replaces local lane-memory hints.",
172
+ },
173
+ intent: {
174
+ type: "string",
175
+ enum: ["auto", "evergreen", "plain", "active"],
176
+ description: 'Planner intent. Defaults to "auto" for refill-sends-v2.',
177
+ },
178
+ journal: {
179
+ type: "boolean",
180
+ description: "Set false to skip the local dry-run journal write.",
181
+ },
182
+ journalNote: {
183
+ type: "string",
184
+ description: "Optional note appended to the terminal journal section.",
185
+ },
186
+ },
187
+ required: ["workspaceId"],
188
+ additionalProperties: false,
189
+ },
190
+ },
191
+ ];
192
+ export async function getRefillPlanV2(input) {
193
+ const workspaceId = normalizeExplicitWorkspaceId(input.workspaceId);
194
+ if (!workspaceId) {
195
+ throw new Error("workspaceId is required for get_refill_plan_v2.");
196
+ }
197
+ const runState = input.runState !== undefined
198
+ ? input.runState
199
+ : buildRunStateFromLocalHints(workspaceId);
200
+ let raw;
201
+ try {
202
+ raw = await postRefillPlanV2({
203
+ workspaceId,
204
+ intent: input.intent ?? "auto",
205
+ senderIds: input.senderIds,
206
+ runState,
207
+ }, workspaceId);
208
+ }
209
+ catch (error) {
210
+ if (!isWorkspaceAccessError(error))
211
+ throw error;
212
+ const guidance = error instanceof SellableApiError && error.guidance
213
+ ? error.guidance
214
+ : "The authenticated user is not a member of this workspace. Confirm the workspaceId or ask a workspace admin to add the user; re-login will not help.";
215
+ const warnings = [];
216
+ let journalPath = null;
217
+ if (input.journal !== false) {
218
+ try {
219
+ journalPath = writeWorkspaceAccessJournal({ workspaceId, guidance });
220
+ }
221
+ catch {
222
+ warnings.push("journalWriteFailed");
223
+ }
224
+ }
225
+ return {
226
+ readOnly: true,
227
+ blocker: "workspace_access",
228
+ workspaceId,
229
+ guidance,
230
+ warnings,
231
+ journalPath,
232
+ text: [
233
+ "Refill sends v2 dry-run blocked: workspace_access",
234
+ `Workspace: ${workspaceId}`,
235
+ guidance,
236
+ journalPath ? `Journal: ${journalPath}` : "Journal: not written",
237
+ ].join("\n"),
238
+ workspaceResolution: "explicit",
239
+ };
240
+ }
241
+ const sanitized = sanitizeEvergreenRefillPlanResult(raw);
242
+ const warnings = Array.isArray(sanitized.warnings)
243
+ ? [...sanitized.warnings]
244
+ : [];
245
+ let journalPath = null;
246
+ if (input.journal !== false) {
247
+ try {
248
+ journalPath = writeDryRunJournal({
249
+ workspaceId,
250
+ result: sanitized,
251
+ journalNote: input.journalNote,
252
+ });
253
+ }
254
+ catch {
255
+ warnings.push("journalWriteFailed");
256
+ }
257
+ }
258
+ const summary = [
259
+ "Refill sends v2 dry-run plan:",
260
+ ...planSummaryLines(sanitized),
261
+ journalPath ? `Journal: ${journalPath}` : "Journal: not written",
262
+ ].join("\n");
263
+ return {
264
+ ...sanitized,
265
+ warnings,
266
+ journalPath,
267
+ text: summary,
268
+ workspaceId,
269
+ workspaceResolution: "explicit",
270
+ };
271
+ }
272
+ /** @deprecated Use getRefillPlanV2. */
273
+ export const getEvergreenRefillPlan = getRefillPlanV2;
@@ -70,6 +70,7 @@ export type SalesNavSearchInput = {
70
70
  };
71
71
  export type ProspeoSearchInput = {
72
72
  filters: Record<string, unknown>;
73
+ workspaceId?: string;
73
74
  page?: number;
74
75
  searchId?: string;
75
76
  campaignOfferId?: string;
@@ -166,6 +167,7 @@ export type ImportLeadsInput = {
166
167
  };
167
168
  export type CancelLeadImportInput = {
168
169
  campaignOfferId: string;
170
+ workspaceId?: string;
169
171
  tableId: string;
170
172
  provider: "apollo" | "prospeo" | "sales-nav";
171
173
  };
@@ -278,6 +280,7 @@ export declare const leadToolDefinitions: ({
278
280
  previewOnly?: undefined;
279
281
  companySearchToken?: undefined;
280
282
  selectedCompanyIds?: undefined;
283
+ workspaceId?: undefined;
281
284
  domainFilterId?: undefined;
282
285
  type?: undefined;
283
286
  profileUrl?: undefined;
@@ -474,6 +477,7 @@ export declare const leadToolDefinitions: ({
474
477
  previewOnly?: undefined;
475
478
  companySearchToken?: undefined;
476
479
  selectedCompanyIds?: undefined;
480
+ workspaceId?: undefined;
477
481
  domainFilterId?: undefined;
478
482
  type?: undefined;
479
483
  profileUrl?: undefined;
@@ -569,6 +573,7 @@ export declare const leadToolDefinitions: ({
569
573
  previewOnly?: undefined;
570
574
  companySearchToken?: undefined;
571
575
  selectedCompanyIds?: undefined;
576
+ workspaceId?: undefined;
572
577
  domainFilterId?: undefined;
573
578
  type?: undefined;
574
579
  profileUrl?: undefined;
@@ -736,6 +741,7 @@ export declare const leadToolDefinitions: ({
736
741
  previewOnly?: undefined;
737
742
  companySearchToken?: undefined;
738
743
  selectedCompanyIds?: undefined;
744
+ workspaceId?: undefined;
739
745
  domainFilterId?: undefined;
740
746
  type?: undefined;
741
747
  profileUrl?: undefined;
@@ -845,6 +851,7 @@ export declare const leadToolDefinitions: ({
845
851
  previewOnly?: undefined;
846
852
  companySearchToken?: undefined;
847
853
  selectedCompanyIds?: undefined;
854
+ workspaceId?: undefined;
848
855
  domainFilterId?: undefined;
849
856
  type?: undefined;
850
857
  profileUrl?: undefined;
@@ -963,6 +970,7 @@ export declare const leadToolDefinitions: ({
963
970
  previewOnly?: undefined;
964
971
  companySearchToken?: undefined;
965
972
  selectedCompanyIds?: undefined;
973
+ workspaceId?: undefined;
966
974
  domainFilterId?: undefined;
967
975
  type?: undefined;
968
976
  profileUrl?: undefined;
@@ -1070,6 +1078,7 @@ export declare const leadToolDefinitions: ({
1070
1078
  previewOnly?: undefined;
1071
1079
  companySearchToken?: undefined;
1072
1080
  selectedCompanyIds?: undefined;
1081
+ workspaceId?: undefined;
1073
1082
  domainFilterId?: undefined;
1074
1083
  type?: undefined;
1075
1084
  profileUrl?: undefined;
@@ -1182,6 +1191,7 @@ export declare const leadToolDefinitions: ({
1182
1191
  previewOnly?: undefined;
1183
1192
  companySearchToken?: undefined;
1184
1193
  selectedCompanyIds?: undefined;
1194
+ workspaceId?: undefined;
1185
1195
  domainFilterId?: undefined;
1186
1196
  type?: undefined;
1187
1197
  profileUrl?: undefined;
@@ -1282,6 +1292,7 @@ export declare const leadToolDefinitions: ({
1282
1292
  previewOnly?: undefined;
1283
1293
  companySearchToken?: undefined;
1284
1294
  selectedCompanyIds?: undefined;
1295
+ workspaceId?: undefined;
1285
1296
  domainFilterId?: undefined;
1286
1297
  type?: undefined;
1287
1298
  profileUrl?: undefined;
@@ -2174,6 +2185,7 @@ export declare const leadToolDefinitions: ({
2174
2185
  exclude?: undefined;
2175
2186
  companySearchToken?: undefined;
2176
2187
  selectedCompanyIds?: undefined;
2188
+ workspaceId?: undefined;
2177
2189
  domainFilterId?: undefined;
2178
2190
  type?: undefined;
2179
2191
  profileUrl?: undefined;
@@ -2283,6 +2295,7 @@ export declare const leadToolDefinitions: ({
2283
2295
  seedDomains?: undefined;
2284
2296
  sort?: undefined;
2285
2297
  previewOnly?: undefined;
2298
+ workspaceId?: undefined;
2286
2299
  domainFilterId?: undefined;
2287
2300
  type?: undefined;
2288
2301
  profileUrl?: undefined;
@@ -3269,6 +3282,10 @@ export declare const leadToolDefinitions: ({
3269
3282
  type: string;
3270
3283
  description: string;
3271
3284
  };
3285
+ workspaceId: {
3286
+ type: string;
3287
+ description: string;
3288
+ };
3272
3289
  searchName: {
3273
3290
  type: string;
3274
3291
  description: string;
@@ -3493,6 +3510,7 @@ export declare const leadToolDefinitions: ({
3493
3510
  previewOnly?: undefined;
3494
3511
  companySearchToken?: undefined;
3495
3512
  selectedCompanyIds?: undefined;
3513
+ workspaceId?: undefined;
3496
3514
  domainFilterId?: undefined;
3497
3515
  sourceLeadListId?: undefined;
3498
3516
  targetLeadCount?: undefined;
@@ -3525,6 +3543,10 @@ export declare const leadToolDefinitions: ({
3525
3543
  type: string;
3526
3544
  description: string;
3527
3545
  };
3546
+ workspaceId: {
3547
+ type: string;
3548
+ description: string;
3549
+ };
3528
3550
  provider: {
3529
3551
  type: string;
3530
3552
  enum: string[];
@@ -3668,6 +3690,10 @@ export declare const leadToolDefinitions: ({
3668
3690
  type: string;
3669
3691
  description: string;
3670
3692
  };
3693
+ workspaceId: {
3694
+ type: string;
3695
+ description: string;
3696
+ };
3671
3697
  tableId: {
3672
3698
  type: string;
3673
3699
  description: string;
@@ -3766,6 +3792,10 @@ export declare const leadToolDefinitions: ({
3766
3792
  type: string;
3767
3793
  description: string;
3768
3794
  };
3795
+ workspaceId: {
3796
+ type: string;
3797
+ description: string;
3798
+ };
3769
3799
  sourceLeadListId: {
3770
3800
  type: string;
3771
3801
  description: string;
@@ -3998,6 +4028,7 @@ export declare const leadToolDefinitions: ({
3998
4028
  previewOnly?: undefined;
3999
4029
  companySearchToken?: undefined;
4000
4030
  selectedCompanyIds?: undefined;
4031
+ workspaceId?: undefined;
4001
4032
  domainFilterId?: undefined;
4002
4033
  type?: undefined;
4003
4034
  profileUrl?: undefined;
@@ -4095,6 +4126,7 @@ export declare const leadToolDefinitions: ({
4095
4126
  previewOnly?: undefined;
4096
4127
  companySearchToken?: undefined;
4097
4128
  selectedCompanyIds?: undefined;
4129
+ workspaceId?: undefined;
4098
4130
  domainFilterId?: undefined;
4099
4131
  type?: undefined;
4100
4132
  profileUrl?: undefined;
@@ -4554,6 +4586,7 @@ export declare function importLeads(input: ImportLeadsInput): Promise<{
4554
4586
  targetLeadCount?: undefined;
4555
4587
  existingCount?: undefined;
4556
4588
  createdLeadList?: undefined;
4589
+ selectedLeadListIdUpdated?: undefined;
4557
4590
  jobResult?: undefined;
4558
4591
  } | {
4559
4592
  error: string;
@@ -4603,6 +4636,7 @@ export declare function importLeads(input: ImportLeadsInput): Promise<{
4603
4636
  targetLeadCount?: undefined;
4604
4637
  existingCount?: undefined;
4605
4638
  createdLeadList?: undefined;
4639
+ selectedLeadListIdUpdated?: undefined;
4606
4640
  jobResult?: undefined;
4607
4641
  } | {
4608
4642
  provider: "signal-discovery" | "sales-nav" | "prospeo";
@@ -4652,6 +4686,7 @@ export declare function importLeads(input: ImportLeadsInput): Promise<{
4652
4686
  targetLeadCount?: undefined;
4653
4687
  existingCount?: undefined;
4654
4688
  createdLeadList?: undefined;
4689
+ selectedLeadListIdUpdated?: undefined;
4655
4690
  jobResult?: undefined;
4656
4691
  } | {
4657
4692
  provider: string;
@@ -4687,6 +4722,7 @@ export declare function importLeads(input: ImportLeadsInput): Promise<{
4687
4722
  targetLeadCount?: undefined;
4688
4723
  existingCount?: undefined;
4689
4724
  createdLeadList?: undefined;
4725
+ selectedLeadListIdUpdated?: undefined;
4690
4726
  jobResult?: undefined;
4691
4727
  } | {
4692
4728
  provider: string;
@@ -4742,6 +4778,7 @@ export declare function importLeads(input: ImportLeadsInput): Promise<{
4742
4778
  targetLeadCount?: undefined;
4743
4779
  existingCount?: undefined;
4744
4780
  createdLeadList?: undefined;
4781
+ selectedLeadListIdUpdated?: undefined;
4745
4782
  jobResult?: undefined;
4746
4783
  } | {
4747
4784
  provider: string;
@@ -4771,6 +4808,7 @@ export declare function importLeads(input: ImportLeadsInput): Promise<{
4771
4808
  needsInvalidPostConfirmation?: undefined;
4772
4809
  existingCount?: undefined;
4773
4810
  createdLeadList?: undefined;
4811
+ selectedLeadListIdUpdated?: undefined;
4774
4812
  jobResult?: undefined;
4775
4813
  } | {
4776
4814
  provider: "sales-nav" | "prospeo";
@@ -4820,11 +4858,13 @@ export declare function importLeads(input: ImportLeadsInput): Promise<{
4820
4858
  warnings?: undefined;
4821
4859
  targetLeadCount?: undefined;
4822
4860
  createdLeadList?: undefined;
4861
+ selectedLeadListIdUpdated?: undefined;
4823
4862
  jobResult?: undefined;
4824
4863
  } | {
4825
4864
  provider: "sales-nav" | "prospeo";
4826
4865
  leadListId: string;
4827
4866
  createdLeadList: any;
4867
+ selectedLeadListIdUpdated: boolean;
4828
4868
  jobResult: any;
4829
4869
  jobId: string | undefined;
4830
4870
  targetLeadCount: number | null;