@sellable/mcp 0.1.768 → 0.1.769

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.
@@ -35,7 +35,7 @@ function isRecord(value) {
35
35
  function deepClone(value) {
36
36
  return JSON.parse(JSON.stringify(value));
37
37
  }
38
- export function sanitizeEvergreenRefillPlanResult(value) {
38
+ export function sanitizeRefillExecutionPlanResult(value) {
39
39
  if (!isRecord(value))
40
40
  return {};
41
41
  const sanitized = {};
@@ -76,7 +76,7 @@ export function sanitizeEvergreenRefillPlanResult(value) {
76
76
  }
77
77
  return sanitized;
78
78
  }
79
- export function projectedV2Packet(packet) {
79
+ export function projectedRefillExecutionPacket(packet) {
80
80
  const target = isRecord(packet.target) ? packet.target : {};
81
81
  const reporting = sanitizeRefillReportingProjection(packet.reporting);
82
82
  const reportingContext = sanitizeRefillReportingContextProjection(packet.reportingContext);
@@ -120,7 +120,7 @@ export function buildRunStateFromLocalHints(workspaceId) {
120
120
  passRates: state?.passRates ?? [],
121
121
  };
122
122
  }
123
- async function postRefillPlanV2(body, workspaceId) {
123
+ async function postRefillExecutionPlan(body, workspaceId) {
124
124
  const api = getApi();
125
125
  const requestOptions = workspaceRequestOptions(workspaceId);
126
126
  return requestOptions
@@ -150,7 +150,7 @@ function writeDryRunJournal(params) {
150
150
  ? params.result.bootstrap
151
151
  : {};
152
152
  appendJournalEvent(created.filePath, renderBootstrapSection({
153
- summary: "Refill v2 dry-run bootstrap across managed waterfall, dashboard evergreen, and active campaign lanes",
153
+ summary: "Refill exact-run bootstrap across managed waterfall, dashboard evergreen, and active campaign lanes",
154
154
  senderSummary: JSON.stringify(bootstrap.senders ?? []),
155
155
  laneSummary: JSON.stringify(bootstrap.laneOrder ?? []),
156
156
  targetSummary: JSON.stringify(bootstrap.target ?? []),
@@ -188,7 +188,7 @@ function writeDryRunJournal(params) {
188
188
  fileName: path.basename(created.filePath),
189
189
  workspaceId: params.workspaceId,
190
190
  dryRun: true,
191
- summary: "refill v2 dry-run",
191
+ summary: "refill exact-run dry-run",
192
192
  });
193
193
  return created.filePath;
194
194
  }
@@ -198,7 +198,7 @@ function writeWorkspaceAccessJournal(params) {
198
198
  dryRun: true,
199
199
  });
200
200
  appendJournalEvent(created.filePath, renderBootstrapSection({
201
- summary: "Refill v2 dry-run bootstrap stopped at workspace access",
201
+ summary: "Refill exact-run dry-run bootstrap stopped at workspace access",
202
202
  senderSummary: "[]",
203
203
  laneSummary: "[]",
204
204
  targetSummary: `workspaceId=${params.workspaceId}`,
@@ -217,7 +217,7 @@ function writeWorkspaceAccessJournal(params) {
217
217
  fileName: path.basename(created.filePath),
218
218
  workspaceId: params.workspaceId,
219
219
  dryRun: true,
220
- summary: "refill v2 dry-run workspace_access blocker",
220
+ summary: "refill exact-run dry-run workspace_access blocker",
221
221
  });
222
222
  return created.filePath;
223
223
  }
@@ -226,60 +226,10 @@ function isWorkspaceAccessError(error) {
226
226
  error.status === 403 &&
227
227
  error.body.includes("No access to workspace"));
228
228
  }
229
- export const refillPlanV2ToolDefinitions = [
230
- {
231
- name: "get_refill_plan_v2",
232
- 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.",
233
- inputSchema: {
234
- type: "object",
235
- properties: {
236
- workspaceId: {
237
- type: "string",
238
- description: "Explicit request-scoped workspace id.",
239
- },
240
- senderIds: {
241
- type: "array",
242
- items: { type: "string" },
243
- },
244
- actionTypes: {
245
- type: "array",
246
- items: {
247
- type: "string",
248
- enum: ["send_invite", "send_inmail_closed"],
249
- },
250
- description: "Optional exact refill lane selector.",
251
- },
252
- approvalMode: {
253
- type: "string",
254
- enum: ["approve", "mark_ready"],
255
- },
256
- runState: {
257
- type: "object",
258
- description: "Optional synthetic v1 run state. When provided, replaces local lane-memory hints.",
259
- },
260
- intent: {
261
- type: "string",
262
- enum: ["auto", "evergreen", "plain", "active"],
263
- description: 'Planner intent. Defaults to "auto" for refill-sends-v2.',
264
- },
265
- journal: {
266
- type: "boolean",
267
- description: "Set false to skip the local dry-run journal write.",
268
- },
269
- journalNote: {
270
- type: "string",
271
- description: "Optional note appended to the terminal journal section.",
272
- },
273
- },
274
- required: ["workspaceId"],
275
- additionalProperties: false,
276
- },
277
- },
278
- ];
279
- export async function getRefillPlanV2(input) {
229
+ export async function getRefillExecutionPlan(input) {
280
230
  const workspaceId = normalizeExplicitWorkspaceId(input.workspaceId);
281
231
  if (!workspaceId) {
282
- throw new Error("workspaceId is required for get_refill_plan_v2.");
232
+ throw new Error("workspaceId is required for the exact refill plan.");
283
233
  }
284
234
  const runState = input.runState !== undefined
285
235
  ? input.runState
@@ -316,14 +266,14 @@ export async function getRefillPlanV2(input) {
316
266
  messageTemplateRevision,
317
267
  runState,
318
268
  }));
319
- raw = projectedV2Packet({
269
+ raw = projectedRefillExecutionPacket({
320
270
  ...packet,
321
271
  runHandle,
322
272
  ...(reportingContext ? { reportingContext } : {}),
323
273
  });
324
274
  }
325
275
  else {
326
- raw = await postRefillPlanV2({
276
+ raw = await postRefillExecutionPlan({
327
277
  workspaceId,
328
278
  intent: input.intent ?? "auto",
329
279
  senderIds: input.senderIds,
@@ -362,7 +312,7 @@ export async function getRefillPlanV2(input) {
362
312
  warnings,
363
313
  journalPath,
364
314
  text: [
365
- "Refill sends v2 dry-run blocked: workspace_access",
315
+ "Refill exact-run dry-run blocked: workspace_access",
366
316
  `Workspace: ${workspaceId}`,
367
317
  guidance,
368
318
  journalPath ? `Journal: ${journalPath}` : "Journal: not written",
@@ -370,7 +320,7 @@ export async function getRefillPlanV2(input) {
370
320
  workspaceResolution: "explicit",
371
321
  };
372
322
  }
373
- const sanitized = sanitizeEvergreenRefillPlanResult(raw);
323
+ const sanitized = sanitizeRefillExecutionPlanResult(raw);
374
324
  const warnings = Array.isArray(sanitized.warnings)
375
325
  ? [...sanitized.warnings]
376
326
  : [];
@@ -388,7 +338,7 @@ export async function getRefillPlanV2(input) {
388
338
  }
389
339
  }
390
340
  const summary = [
391
- "Refill sends v2 dry-run plan:",
341
+ "Refill exact-run dry-run plan:",
392
342
  ...planSummaryLines(sanitized),
393
343
  journalPath ? `Journal: ${journalPath}` : "Journal: not written",
394
344
  ].join("\n");
@@ -401,5 +351,3 @@ export async function getRefillPlanV2(input) {
401
351
  workspaceResolution: "explicit",
402
352
  };
403
353
  }
404
- /** @deprecated Use getRefillPlanV2. */
405
- export const getEvergreenRefillPlan = getRefillPlanV2;
@@ -659,7 +659,7 @@ export declare function refillSendsCommand(input?: RefillSendsCommandInput): {
659
659
  workspaceResolution: string;
660
660
  intent: RefillSendsIntent;
661
661
  };
662
- export declare const REFILL_FLOW_MINIMUM_VERSION = "v1.8";
662
+ export declare const REFILL_FLOW_MINIMUM_VERSION = "v1.9";
663
663
  export declare const REFILL_FLOW_COMPATIBLE_MAJOR = "v1";
664
664
  /**
665
665
  * Whether an observed flow-asset version satisfies the consumer's contract.
@@ -1,8 +1,8 @@
1
1
  import { decodeRefillReadinessAuthority, refillReadinessFingerprint, } from "../refill-readiness.js";
2
2
  import { getPrepareCampaignMessagesStatus } from "./campaign-message-preparation.js";
3
3
  import { MESSAGE_TEMPLATE_REVISION_INPUT_SCHEMA, REFILL_REPORTING_CONTEXT_INPUT_SCHEMA, REFILL_RUN_HANDLE_INPUT_SCHEMA, REFILL_TARGET_CONFIG_INPUT_SCHEMA, normalizeMessageTemplateRevision, normalizeRefillRunHandle, normalizeRefillTargetConfig, } from "./campaign-processing.js";
4
+ import { executeRefillExactRun } from "./refill-exact-run.js";
4
5
  import { actionCampaignId, actionIds, actionSenderId, classifyPaidInmailRefreshReceipt, collectPaidInmailRefreshActions, executeOneYoloPrimitive, executeStartCampaignPrimitive, firstGlobalAction, normalizeStrings, numberValue, recordValue, refreshPaidInmailCreditsWithRetry, stringValue, } from "./refill-executors.js";
5
- import { refillSendsV2Command } from "./refill-sends-v2.js";
6
6
  import { getRefillTargetPlan } from "./refill-target-plan.js";
7
7
  import { listSenders } from "./senders.js";
8
8
  import { createWorkspaceContext, normalizeExplicitWorkspaceId, } from "./workspace-context.js";
@@ -428,19 +428,11 @@ export const refillSendsToolDefinitions = [
428
428
  export function refillSendsCommand(input = {}) {
429
429
  return buildRefillSendsCommand(normalizeRefillSendsInput(input));
430
430
  }
431
- // fix(112ao-4): the refill flow contract was matched by EXACT STRING across a
432
- // release boundary the flow asset ships in the npm package (@sellable/mcp)
433
- // while the skill that verifies it is installed separately into
434
- // ~/.codex/plugins/cache. Exact equality makes EVERY contract change breaking:
435
- // bumping v1.8 -> v1.9 halted every customer-real run with
436
- // workflow_version_mismatch, and a full repo sweep could not have caught it
437
- // because the authoritative consumer is not in this repo.
438
- //
439
- // The version value itself is deliberately NOT changed here. What changes is
440
- // the comparison: consumers accept any same-major version at or above the
441
- // minimum, so additive flow changes ship without a coordinated skill release.
442
- // A breaking change still gets a major bump (v2), which correctly fails closed.
443
- export const REFILL_FLOW_MINIMUM_VERSION = "v1.8";
431
+ // The canonical refill asset is v1.9. Consumers accept later additive v1
432
+ // revisions so separately installed host wrappers do not turn v1.10 into an
433
+ // accidental breaking change. A real breaking contract still gets v2 and
434
+ // fails closed.
435
+ export const REFILL_FLOW_MINIMUM_VERSION = "v1.9";
444
436
  export const REFILL_FLOW_COMPATIBLE_MAJOR = "v1";
445
437
  function parseFlowVersion(value) {
446
438
  if (typeof value !== "string")
@@ -502,9 +494,8 @@ function buildRefillSendsCommand(input) {
502
494
  workflowAsset: {
503
495
  subskillName: "refill-sends-workflow",
504
496
  assetPath: "core/flow.v1.json",
505
- // fix(112ao-4): `expectedVersion` is retained verbatim so consumers
506
- // already installed against the exact-match contract keep working. New
507
- // consumers read the range fields instead. See REFILL_FLOW_VERSION_RANGE.
497
+ // Keep expectedVersion for older response readers; current consumers use
498
+ // the compatible same-major range fields.
508
499
  expectedVersion: REFILL_FLOW_MINIMUM_VERSION,
509
500
  minimumVersion: REFILL_FLOW_MINIMUM_VERSION,
510
501
  compatibleMajor: REFILL_FLOW_COMPATIBLE_MAJOR,
@@ -556,7 +547,7 @@ function buildRefillSendsCommand(input) {
556
547
  },
557
548
  firstOperationalSteps: [
558
549
  'Load get_subskill_prompt({ subskillName: "refill-sends-workflow" }) before any product operation.',
559
- 'Load get_subskill_asset({ subskillName: "refill-sends-workflow", assetPath: "core/flow.v1.json" }) before any product operation; continue chunks until hasMore is false, parse JSON, and require workflow:"refill-sends-workflow" plus a COMPATIBLE version: same major (v1) with minor at or above the v1.8 minimum, so v1.8, v1.9, and v1.10 all pass while v2.x does not. Report the verified version before D1. A missing, unparseable, wrong-major, or below-minimum version is workflow_version_mismatch and must stop before get_refill_target_plan or mutation. Do not compare the version by exact string equality.',
550
+ 'Load get_subskill_asset({ subskillName: "refill-sends-workflow", assetPath: "core/flow.v1.json" }) before any product operation; continue chunks until hasMore is false, parse JSON, and require workflow:"refill-sends-workflow" plus a COMPATIBLE version: same major (v1) with minor at or above the v1.9 minimum, so v1.9 and v1.10 pass while v1.8 and v2.x do not. Report the verified version before D1. A missing, unparseable, wrong-major, or below-minimum version is workflow_version_mismatch and must stop before get_refill_target_plan or mutation. Do not compare the version by exact string equality.',
560
551
  "A skill cannot create or invoke /goal by itself. If this refill is already running inside an active Codex goal, keep that goal open until every selected sender lane is horizon-filled by projected coverage (sent + scheduled), Christian explicitly stops/statuses the run, or a concrete non-scheduler blocker appears.",
561
552
  `Call get_refill_target_plan({ intent: "${intent}"${workspaceId ? `, workspaceId: "${workspaceId}"` : ""}${input.campaignId ? `, campaignId: "${input.campaignId}"` : ""}${input.tableId ? `, tableId: "${input.tableId}"` : ""}${senderIds.length > 0 ? `, senderIds: ${JSON.stringify(senderIds)}` : ""}${senderNames.length > 0
562
553
  ? `, senderNames: ${JSON.stringify(senderNames)}`
@@ -3967,7 +3958,7 @@ export async function executeRefillSendsCommand(input = {}) {
3967
3958
  // The tool contract promises that an already-approved packet's
3968
3959
  // expectedTargetShapeRevision/expectedActionKey are compared against a
3969
3960
  // fresh plan before any refresh or mutation; enforce that before handing
3970
- // control to the fenced v2 run loop.
3961
+ // control to the fenced exact-run loop.
3971
3962
  if (!isWorkspaceCoordinator &&
3972
3963
  (scopedInput.expectedTargetShapeRevision || scopedInput.expectedActionKey)) {
3973
3964
  const targetPlanBeforeDispatch = await getRefillTargetPlan(targetPlanInputFor(scopedInput));
@@ -4001,7 +3992,7 @@ export async function executeRefillSendsCommand(input = {}) {
4001
3992
  };
4002
3993
  }
4003
3994
  }
4004
- const result = await refillSendsV2Command({
3995
+ const result = await executeRefillExactRun({
4005
3996
  workspaceId,
4006
3997
  intent: targetConfigIntent(exactTargetConfig) ?? scopedInput.intent ?? "auto",
4007
3998
  senderIds: exactTargetConfig?.senderScope.senderIds ??
@@ -4034,7 +4025,7 @@ export async function executeRefillSendsCommand(input = {}) {
4034
4025
  ? { agentKeywords: scopedInput.agentKeywords }
4035
4026
  : {}),
4036
4027
  // fix(111p, CloverF): the fence ledger seed (111k) was plumbed through
4037
- // the v2 input, the loop input, and initialRunState — but THIS dispatch
4028
+ // the exact-run input, the loop input, and initialRunState — but THIS dispatch
4038
4029
  // never passed runState, so every fence still started amnesiac (fence 2
4039
4030
  // persisted zero attempts and re-resolved rung 1 while the coordinator
4040
4031
  // held the attempt ledger). Thread the freshest workspace runState in.
@@ -1835,7 +1835,7 @@ export function sanitizeRefillTargetPlanResult(result) {
1835
1835
  // The explicit template-revision primitive is fenced to an exact
1836
1836
  // campaign/table/cohort and is intentionally independent of sender lane
1837
1837
  // eligibility. get_refill_target_plan attaches it after its first strict
1838
- // sanitization; get_refill_plan_v2 then sanitizes that already-sanitized
1838
+ // sanitization; the exact refill plan then sanitizes that already-sanitized
1839
1839
  // packet a second time. Preserve only that fully normalized primitive so a
1840
1840
  // disconnected sender cannot erase approved revision authority before the
1841
1841
  // fenced loop reaches g2_execute. Every other senderless/no-lane packet