@sellable/mcp 0.1.613 → 0.1.615-phase111.20260720001632

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 (38) hide show
  1. package/dist/refill-contract.d.ts +157 -0
  2. package/dist/refill-contract.js +487 -0
  3. package/dist/refill-run-loop.d.ts +31 -0
  4. package/dist/refill-run-loop.js +121 -14
  5. package/dist/server.js +4 -1
  6. package/dist/tools/campaign-message-preparation.d.ts +409 -0
  7. package/dist/tools/campaign-message-preparation.js +46 -4
  8. package/dist/tools/campaign-processing.d.ts +614 -40
  9. package/dist/tools/campaign-processing.js +306 -35
  10. package/dist/tools/campaign-refill-state.d.ts +174 -3
  11. package/dist/tools/campaign-refill-state.js +27 -3
  12. package/dist/tools/evergreen-refill-plan.d.ts +5 -0
  13. package/dist/tools/evergreen-refill-plan.js +121 -14
  14. package/dist/tools/prompts.d.ts +25 -0
  15. package/dist/tools/prompts.js +24 -0
  16. package/dist/tools/refill-executors.d.ts +13 -0
  17. package/dist/tools/refill-executors.js +62 -0
  18. package/dist/tools/refill-sends-v2.d.ts +370 -0
  19. package/dist/tools/refill-sends-v2.js +58 -6
  20. package/dist/tools/refill-sends.d.ts +509 -0
  21. package/dist/tools/refill-sends.js +60 -0
  22. package/dist/tools/refill-target-plan.d.ts +368 -0
  23. package/dist/tools/refill-target-plan.js +191 -3
  24. package/dist/tools/registry.d.ts +1552 -307
  25. package/dist/tools/registry.js +11 -0
  26. package/dist/tools/senders.d.ts +183 -0
  27. package/dist/tools/senders.js +286 -1
  28. package/package.json +1 -1
  29. package/skills/refill-sends/SKILL.md +14 -1
  30. package/skills/refill-sends-evergreen/SKILL.md +5 -0
  31. package/skills/refill-sends-evergreen-workflow/SKILL.md +5 -0
  32. package/skills/refill-sends-evergreen-workflow/core/flow.v1.json +12 -0
  33. package/skills/refill-sends-v2/SKILL.md +23 -1
  34. package/skills/refill-sends-v2-workflow/SKILL.md +16 -1
  35. package/skills/refill-sends-v2-workflow/core/flow.v1.json +21 -0
  36. package/skills/refill-sends-workflow/SKILL.md +9 -1
  37. package/skills/refill-sends-workflow/core/flow.v1.json +24 -0
  38. package/skills/research/config.json +9 -0
@@ -1,6 +1,7 @@
1
1
  import type { appendIndexLine, appendJournalEvent, createRunJournal, renderBootstrapSection, renderCrashedAbandonedSection, renderExecutionEventSection, renderPlanSection, renderTerminalSection } from "./refill-journal.js";
2
2
  import type { advanceRefillRunGateRemote, completeRefillRun, heartbeatRefillRun, recordRunOutcome, recordRunPlanned, refillRunStatus, startRefillRunRemote } from "./refill-run-client.js";
3
3
  import type { getPrepareCampaignMessagesStatus } from "./tools/campaign-message-preparation.js";
4
+ import { type MessageTemplateRevisionV1, type RefillReportingContextV2, type RefillRunHandleV1, type RefillTargetConfigV1 } from "./tools/campaign-processing.js";
4
5
  import type { executeOneYoloPrimitive, executeStartCampaignPrimitive, prepareRowSelectorValue, refillPrepareRequestHash, refreshPaidInmailCreditsWithRetry } from "./tools/refill-executors.js";
5
6
  export type RefillLoopGate = "g0_bootstrap" | "g1_plan" | "g2_execute" | "g3_verify" | "g4_terminal";
6
7
  export interface RefillV2LoopInput {
@@ -15,6 +16,10 @@ export interface RefillV2LoopInput {
15
16
  runId: string;
16
17
  fence: number;
17
18
  };
19
+ runHandle?: RefillRunHandleV1;
20
+ targetConfig?: RefillTargetConfigV1;
21
+ reportingContext?: RefillReportingContextV2;
22
+ messageTemplateRevision?: MessageTemplateRevisionV1;
18
23
  approvalMode?: "approve" | "mark_ready";
19
24
  dryRun?: boolean;
20
25
  agentKeywords?: string[];
@@ -69,6 +74,10 @@ export interface RefillV2LoopDeps {
69
74
  targetDate?: string;
70
75
  untilDate?: string;
71
76
  horizonSendDays?: number;
77
+ targetConfig?: RefillTargetConfigV1;
78
+ runHandle?: RefillRunHandleV1;
79
+ reportingContext?: RefillReportingContextV2;
80
+ messageTemplateRevision?: MessageTemplateRevisionV1;
72
81
  runState?: Record<string, unknown>;
73
82
  journal?: boolean;
74
83
  }) => Promise<Record<string, unknown>>;
@@ -95,6 +104,9 @@ export type RefillV2LoopResult = {
95
104
  gate: RefillLoopGate;
96
105
  guidance: string;
97
106
  journalPath?: string | null;
107
+ targetConfig?: RefillTargetConfigV1;
108
+ runHandle?: RefillRunHandleV1;
109
+ refillReporting?: Record<string, unknown>;
98
110
  } | {
99
111
  status: "blocked";
100
112
  blocker: string;
@@ -105,6 +117,9 @@ export type RefillV2LoopResult = {
105
117
  holderRunId?: string;
106
118
  report?: Record<string, unknown>;
107
119
  journalPath?: string | null;
120
+ targetConfig?: RefillTargetConfigV1;
121
+ runHandle?: RefillRunHandleV1;
122
+ refillReporting?: Record<string, unknown>;
108
123
  } | {
109
124
  status: "terminal";
110
125
  doneReason: string;
@@ -112,5 +127,21 @@ export type RefillV2LoopResult = {
112
127
  runId: string;
113
128
  guidance?: string;
114
129
  journalPath?: string | null;
130
+ targetConfig?: RefillTargetConfigV1;
131
+ runHandle?: RefillRunHandleV1;
132
+ refillReporting?: Record<string, unknown>;
133
+ };
134
+ export declare function packetCoherenceFailure(plan: Record<string, unknown>): string | null;
135
+ export declare function terminalProjection(value: {
136
+ targetConfig?: unknown;
137
+ runHandle?: unknown;
138
+ refillReporting?: unknown;
139
+ reporting?: unknown;
140
+ lastOutcome?: unknown;
141
+ }): {
142
+ messageTemplateRevisionOutcome?: {} | null | undefined;
143
+ refillReporting?: Record<string, unknown> | undefined;
144
+ runHandle?: RefillRunHandleV1 | undefined;
145
+ targetConfig?: RefillTargetConfigV1 | undefined;
115
146
  };
116
147
  export declare function runRefillV2Loop(input: RefillV2LoopInput, deps: RefillV2LoopDeps): Promise<RefillV2LoopResult>;
@@ -1,7 +1,9 @@
1
1
  import { SellableApiError } from "./api.js";
2
2
  import { decodeRefillReadinessAuthority, refillReadinessExpectationInput, refillReadinessFingerprint, } from "./refill-readiness.js";
3
+ import { normalizeMessageTemplateRevision, normalizeRefillRunHandle, normalizeRefillTargetConfig, } from "./tools/campaign-processing.js";
3
4
  import { buildRunStateFromLocalHints } from "./tools/evergreen-refill-plan.js";
4
5
  import { classifyPaidInmailRefreshReceipt, prepareRowSelectorValue as defaultPrepareRowSelectorValue, refillPrepareRequestHash as defaultRefillPrepareRequestHash, validateAgentSuppliedBroadenKeywords, } from "./tools/refill-executors.js";
6
+ import { sanitizeRefillReportingProjection } from "./tools/refill-target-plan.js";
5
7
  const DEFAULT_BUDGETS = {
6
8
  maxGateCyclesPerInvocation: 4,
7
9
  pollIntervalMs: 5_000,
@@ -1320,7 +1322,7 @@ function getPlanLine(plan) {
1320
1322
  fallbackSummary: stringValue(recordValue(itinerary.fallback)?.trigger) ?? "",
1321
1323
  };
1322
1324
  }
1323
- function packetCoherenceFailure(plan) {
1325
+ export function packetCoherenceFailure(plan) {
1324
1326
  const fingerprint = fingerprintFromPlan(plan);
1325
1327
  if (!fingerprint.planRevision || !fingerprint.targetShapeRevision) {
1326
1328
  return "missing_fingerprint";
@@ -1344,8 +1346,79 @@ function packetCoherenceFailure(plan) {
1344
1346
  (!actionCampaignId(action) || !stringValue(toolInput.tableId))) {
1345
1347
  return "malformed_prepare_tool_input";
1346
1348
  }
1349
+ if (type === "revise_message_template_and_rerun") {
1350
+ try {
1351
+ const targetConfig = normalizeRefillTargetConfig(toolInput.targetConfig);
1352
+ const runHandle = normalizeRefillRunHandle(toolInput.runHandle);
1353
+ const revision = normalizeMessageTemplateRevision(toolInput.messageTemplateRevision);
1354
+ if (!revision ||
1355
+ actionCampaignId(action) !== targetConfig.campaignId ||
1356
+ actionTableId(action) !== targetConfig.tableId ||
1357
+ (isRecord(plan.targetConfig) &&
1358
+ safeJson(normalizeRefillTargetConfig(plan.targetConfig)) !==
1359
+ safeJson(targetConfig)) ||
1360
+ (typeof action.effectId === "string" &&
1361
+ action.effectId !== revision.effectId) ||
1362
+ (typeof action.requestId === "string" &&
1363
+ action.requestId !== revision.requestId) ||
1364
+ (typeof action.revisionOperationId === "string" &&
1365
+ action.revisionOperationId !== revision.revisionOperationId) ||
1366
+ runHandle.runId.trim().length === 0) {
1367
+ return "malformed_message_template_revision";
1368
+ }
1369
+ }
1370
+ catch {
1371
+ return "malformed_message_template_revision";
1372
+ }
1373
+ }
1347
1374
  return null;
1348
1375
  }
1376
+ function reportingFrom(value) {
1377
+ if (!isRecord(value))
1378
+ return undefined;
1379
+ return (sanitizeRefillReportingProjection(value.refillReporting) ??
1380
+ sanitizeRefillReportingProjection(value.reporting) ??
1381
+ (isRecord(value.packet)
1382
+ ? sanitizeRefillReportingProjection(value.packet.reporting)
1383
+ : undefined));
1384
+ }
1385
+ export function terminalProjection(value) {
1386
+ const targetConfig = value.targetConfig
1387
+ ? normalizeRefillTargetConfig(value.targetConfig)
1388
+ : undefined;
1389
+ const runHandle = value.runHandle
1390
+ ? normalizeRefillRunHandle(value.runHandle)
1391
+ : undefined;
1392
+ const refillReporting = sanitizeRefillReportingProjection(value.refillReporting) ??
1393
+ sanitizeRefillReportingProjection(value.reporting);
1394
+ return {
1395
+ ...(targetConfig ? { targetConfig } : {}),
1396
+ ...(runHandle ? { runHandle } : {}),
1397
+ ...(refillReporting ? { refillReporting } : {}),
1398
+ ...(value.lastOutcome !== undefined
1399
+ ? { messageTemplateRevisionOutcome: value.lastOutcome }
1400
+ : {}),
1401
+ };
1402
+ }
1403
+ function exactLoopProjection(input, ctx, plan = ctx.plan) {
1404
+ const planPacket = isRecord(plan?.packet) ? plan.packet : null;
1405
+ const targetConfig = input.targetConfig ??
1406
+ ctx.targetConfig ??
1407
+ (isRecord(plan?.targetConfig) ? plan.targetConfig : undefined) ??
1408
+ (isRecord(planPacket?.targetConfig) ? planPacket.targetConfig : undefined);
1409
+ const refillReporting = reportingFrom(plan) ??
1410
+ reportingFrom(planPacket) ??
1411
+ reportingFrom(ctx.runState);
1412
+ const executedRevision = stringValue(lastAction(ctx)?.type) === "revise_message_template_and_rerun"
1413
+ ? ctx.runState.lastOutcome
1414
+ : undefined;
1415
+ return terminalProjection({
1416
+ targetConfig,
1417
+ runHandle: ctx.runHandle,
1418
+ refillReporting,
1419
+ lastOutcome: executedRevision,
1420
+ });
1421
+ }
1349
1422
  async function safeJournalAppend(ctx, deps, block) {
1350
1423
  if (!ctx.journalPath)
1351
1424
  return;
@@ -1402,21 +1475,28 @@ async function createJournal(input, deps, runId) {
1402
1475
  }
1403
1476
  async function startOrResume(input, deps) {
1404
1477
  const initialRunState = buildRunStateFromLocalHints(input.workspaceId);
1478
+ const targetConfig = input.targetConfig
1479
+ ? normalizeRefillTargetConfig(input.targetConfig)
1480
+ : null;
1481
+ const requestedHandle = input.runHandle
1482
+ ? normalizeRefillRunHandle(input.runHandle)
1483
+ : input.resume;
1405
1484
  const started = await deps.runClient.startRefillRunRemote({
1406
1485
  workspaceId: input.workspaceId,
1407
- config: {
1408
- intent: input.intent ?? "auto",
1409
- senderIds: input.senderIds,
1410
- actionTypes: input.actionTypes,
1411
- approvalMode: input.approvalMode ?? "approve",
1412
- ...(input.targetDate ? { targetDate: input.targetDate } : {}),
1413
- ...(input.untilDate ? { untilDate: input.untilDate } : {}),
1414
- ...(typeof input.horizonSendDays === "number"
1415
- ? { horizonSendDays: input.horizonSendDays }
1416
- : {}),
1417
- },
1486
+ config: targetConfig ??
1487
+ {
1488
+ intent: input.intent ?? "auto",
1489
+ senderIds: input.senderIds,
1490
+ actionTypes: input.actionTypes,
1491
+ approvalMode: input.approvalMode ?? "approve",
1492
+ ...(input.targetDate ? { targetDate: input.targetDate } : {}),
1493
+ ...(input.untilDate ? { untilDate: input.untilDate } : {}),
1494
+ ...(typeof input.horizonSendDays === "number"
1495
+ ? { horizonSendDays: input.horizonSendDays }
1496
+ : {}),
1497
+ },
1418
1498
  runState: initialRunState,
1419
- resume: input.resume,
1499
+ resume: requestedHandle,
1420
1500
  });
1421
1501
  if (isLeaseLost(started)) {
1422
1502
  return {
@@ -1437,7 +1517,15 @@ async function startOrResume(input, deps) {
1437
1517
  const result = started;
1438
1518
  const runId = stringValue(result.runId);
1439
1519
  const fence = numberValue(result.fence);
1440
- if (!runId || fence == null) {
1520
+ let runHandle = null;
1521
+ try {
1522
+ runHandle = normalizeRefillRunHandle(recordValue(result.handle) ??
1523
+ (runId && fence != null ? { runId, fence } : undefined));
1524
+ }
1525
+ catch {
1526
+ runHandle = null;
1527
+ }
1528
+ if (!runId || fence == null || !runHandle) {
1441
1529
  return {
1442
1530
  status: "blocked",
1443
1531
  blocker: "bad_start_response",
@@ -1445,6 +1533,9 @@ async function startOrResume(input, deps) {
1445
1533
  report: { response: started },
1446
1534
  };
1447
1535
  }
1536
+ input.runHandle = runHandle;
1537
+ if (targetConfig)
1538
+ input.targetConfig = targetConfig;
1448
1539
  const gate = (stringValue(result.gate) ?? "g0_bootstrap");
1449
1540
  const gateSeq = numberValue(result.gateSeq) ?? 0;
1450
1541
  const runState = recordValue(result.runState) ??
@@ -1460,6 +1551,8 @@ async function startOrResume(input, deps) {
1460
1551
  workspaceId: input.workspaceId,
1461
1552
  runId,
1462
1553
  fence,
1554
+ runHandle,
1555
+ targetConfig,
1463
1556
  gate,
1464
1557
  gateSeq,
1465
1558
  runState,
@@ -1616,6 +1709,7 @@ async function completeTerminal(input, deps, ctx, doneReasonInput, reportInput =
1616
1709
  blockedContinuations: ctx.blockedContinuations,
1617
1710
  journalPath: ctx.journalPath,
1618
1711
  ...reportInput,
1712
+ ...exactLoopProjection(input, ctx),
1619
1713
  };
1620
1714
  const terminalRunState = mergeRunState(ctx.runState, {
1621
1715
  terminal: {
@@ -1676,6 +1770,7 @@ async function completeTerminal(input, deps, ctx, doneReasonInput, reportInput =
1676
1770
  report,
1677
1771
  runId: ctx.runId,
1678
1772
  journalPath: ctx.journalPath,
1773
+ ...exactLoopProjection(input, ctx),
1679
1774
  ...(doneReason === "lanes_exhausted"
1680
1775
  ? {
1681
1776
  guidance: "Lane chain exhausted. Before reporting, call resolve_campaign_fill_route for this workspace: if skippedTargets holds a non-archived DRAFT campaign blocked only by campaign_sequence_missing that already has imported prospect rows and a complete builder pipeline, finish its setup per the repairable-draft fallback (update_campaign attaching exactly the already-eligible refill senders, then attach_recommended_sequence WITHOUT currentStep so the approved-message gate stays intact) and re-invoke refill_sends --yolo with the same workspace scope; the bounded ladder then prepares/approves messages and starts the campaign through its normal gates.",
@@ -2127,6 +2222,9 @@ async function gateExecute(input, deps, ctx) {
2127
2222
  toolInput: {
2128
2223
  ...actionToolInput(action),
2129
2224
  approvalMode: input.approvalMode ?? actionToolInput(action).approvalMode,
2225
+ ...(input.reportingContext
2226
+ ? { reportingContext: input.reportingContext }
2227
+ : {}),
2130
2228
  },
2131
2229
  }, input.workspaceId);
2132
2230
  }
@@ -2250,6 +2348,7 @@ async function verifyPrepareAction(input, deps, ctx, action, budgets) {
2250
2348
  const expectedHash = expectedPrepareRequestHash(deps, action);
2251
2349
  const tableId = stringValue(actionToolInput(action).tableId) ?? undefined;
2252
2350
  const campaignId = actionCampaignId(action) ?? undefined;
2351
+ const reportingHistory = arrayValue(recordValue(input.reportingContext?.liveHistory)?.snapshots);
2253
2352
  let latestStatus = null;
2254
2353
  for (let poll = 0; poll < budgets.maxPollsPerWait; poll += 1) {
2255
2354
  latestStatus = await getStatus({
@@ -2257,6 +2356,10 @@ async function verifyPrepareAction(input, deps, ctx, action, budgets) {
2257
2356
  jobId,
2258
2357
  campaignId,
2259
2358
  tableId,
2359
+ ...(input.reportingContext
2360
+ ? { reportingContext: input.reportingContext }
2361
+ : {}),
2362
+ ...(reportingHistory.length > 0 ? { history: reportingHistory } : {}),
2260
2363
  });
2261
2364
  const statusRecord = recordValue(latestStatus) ?? {};
2262
2365
  const requestSource = stringValue(statusRecord.requestSource);
@@ -3413,6 +3516,7 @@ async function heartbeatAndContinue(input, deps, ctx) {
3413
3516
  gate: ctx.gate,
3414
3517
  guidance: "Per-invocation gate budget reached. Re-invoke refill_sends with the same arguments (including workspaceId and any targetDate/untilDate/horizonSendDays) plus this runId/fence to continue.",
3415
3518
  journalPath: ctx.journalPath,
3519
+ ...exactLoopProjection(input, ctx),
3416
3520
  };
3417
3521
  }
3418
3522
  export async function runRefillV2Loop(input, deps) {
@@ -3467,15 +3571,18 @@ export async function runRefillV2Loop(input, deps) {
3467
3571
  continue;
3468
3572
  }
3469
3573
  if (ctx.gate === "g4_terminal") {
3574
+ const projection = exactLoopProjection(input, ctx);
3470
3575
  return {
3471
3576
  status: "terminal",
3472
3577
  doneReason: normalizeDoneReason(recordValue(ctx.runState.terminal)?.doneReason),
3473
3578
  report: {
3474
3579
  doneReason: normalizeDoneReason(recordValue(ctx.runState.terminal)?.doneReason),
3475
3580
  journalPath: ctx.journalPath,
3581
+ ...projection,
3476
3582
  },
3477
3583
  runId: ctx.runId,
3478
3584
  journalPath: ctx.journalPath,
3585
+ ...projection,
3479
3586
  };
3480
3587
  }
3481
3588
  }
package/dist/server.js CHANGED
@@ -52,7 +52,7 @@ import { addRubricItem, checkRubric, deleteRubricItem, draftRubrics, saveRubrics
52
52
  import { getSchedulerFillCapacity } from "./tools/scheduler-fill-capacity.js";
53
53
  import { runSchedulerSweep } from "./tools/scheduler-run.js";
54
54
  import { getSenderRoutingTool, setSenderRoutingTool, } from "./tools/sender-routing.js";
55
- import { getSender, listSenders, refreshPaidInmailCredits, } from "./tools/senders.js";
55
+ import { getSender, listSenders, refreshPaidInmailCredits, setSenderCalendarLink, } from "./tools/senders.js";
56
56
  import { attachRecommendedSequence, attachSequence, createWorkflowTable, } from "./tools/sequencer.js";
57
57
  import { setupEvergreenCampaigns } from "./tools/setup-evergreen-campaigns.js";
58
58
  import { exportTableCsv, listTables } from "./tools/tables.js";
@@ -577,6 +577,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
577
577
  case "get_sender":
578
578
  result = await getSender(args);
579
579
  break;
580
+ case "set_sender_calendar_link":
581
+ result = await setSenderCalendarLink(args);
582
+ break;
580
583
  case "refresh_paid_inmail_credits":
581
584
  result = await refreshPaidInmailCredits(args);
582
585
  break;