@sellable/mcp 0.1.600 → 0.1.601-phase110.20260717111356
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/dist/tools/refill-target-plan.js +43 -56
- package/package.json +1 -1
|
@@ -224,35 +224,15 @@ function sanitizePrepFailureDiagnosis(value) {
|
|
|
224
224
|
},
|
|
225
225
|
};
|
|
226
226
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
for (const item of evidence) {
|
|
237
|
-
if (!isRecord(item))
|
|
238
|
-
continue;
|
|
239
|
-
const actionType = allowedActionType(item.actionType);
|
|
240
|
-
if (!actionType)
|
|
241
|
-
continue;
|
|
242
|
-
const current = byAction.get(actionType) ?? { count: 0, latestMs: 0 };
|
|
243
|
-
current.count += numberValue(item.count);
|
|
244
|
-
current.latestMs = Math.max(current.latestMs, evidenceLatestMs(item));
|
|
245
|
-
byAction.set(actionType, current);
|
|
246
|
-
}
|
|
247
|
-
const [best] = [...byAction.entries()].sort((a, b) => {
|
|
248
|
-
if (a[1].latestMs !== b[1].latestMs)
|
|
249
|
-
return b[1].latestMs - a[1].latestMs;
|
|
250
|
-
if (a[1].count !== b[1].count)
|
|
251
|
-
return b[1].count - a[1].count;
|
|
252
|
-
return (REFILL_TARGET_ACTION_TYPES.indexOf(a[0]) -
|
|
253
|
-
REFILL_TARGET_ACTION_TYPES.indexOf(b[0]));
|
|
254
|
-
});
|
|
255
|
-
return best?.[0] ?? fallback[0] ?? null;
|
|
227
|
+
// Phase 110: the backend planner is the single authority on lane selection —
|
|
228
|
+
// it collapses to one lane for non-cascade senders and emits BOTH lanes for
|
|
229
|
+
// invite-capable Sales Nav cascades. This wrapper must not re-collapse
|
|
230
|
+
// (zero-shot i02-clover receipt: request.actionTypes was forced to a single
|
|
231
|
+
// lane with no caller override, so paid lanes with available credits were
|
|
232
|
+
// never targeted). Lanes are ordered by REFILL_TARGET_ACTION_TYPES.
|
|
233
|
+
function orderedLanes(lanes) {
|
|
234
|
+
const laneSet = new Set(lanes);
|
|
235
|
+
return REFILL_TARGET_ACTION_TYPES.filter((lane) => laneSet.has(lane));
|
|
256
236
|
}
|
|
257
237
|
function senderActionKey(senderId, actionType) {
|
|
258
238
|
return typeof senderId === "string" && typeof actionType === "string"
|
|
@@ -650,8 +630,8 @@ function sanitizeEligibleSenderLedger(value, selectedBySender) {
|
|
|
650
630
|
return selectedBySender.has(row.senderId);
|
|
651
631
|
})
|
|
652
632
|
.map((row) => {
|
|
653
|
-
const
|
|
654
|
-
const eligibleActionTypes = actionTypesFrom(row.eligibleActionTypes).filter((actionType) => actionType
|
|
633
|
+
const selectedLanes = selectedBySender.get(row.senderId) ?? new Set();
|
|
634
|
+
const eligibleActionTypes = actionTypesFrom(row.eligibleActionTypes).filter((actionType) => selectedLanes.has(actionType));
|
|
655
635
|
return {
|
|
656
636
|
senderId: row.senderId,
|
|
657
637
|
senderName: stringValue(row.senderName) ?? "",
|
|
@@ -841,7 +821,7 @@ function sanitizeStructuredSenderPlans(value, selectedBySender) {
|
|
|
841
821
|
if (!isRecord(plan) || typeof plan.senderId !== "string")
|
|
842
822
|
return false;
|
|
843
823
|
const selectedLane = allowedActionType(plan.selectedLane);
|
|
844
|
-
return Boolean(selectedLane && selectedBySender.get(plan.senderId)
|
|
824
|
+
return Boolean(selectedLane && selectedBySender.get(plan.senderId)?.has(selectedLane));
|
|
845
825
|
})
|
|
846
826
|
.map((plan) => {
|
|
847
827
|
const paidInmail = sanitizePaidInmail(plan.paidInmail);
|
|
@@ -1038,7 +1018,7 @@ function sanitizeTargetSchedulerSweep(params) {
|
|
|
1038
1018
|
}
|
|
1039
1019
|
const expectedSenderIds = [...params.sweepEligibleBySender.keys()].sort();
|
|
1040
1020
|
const expectedActionTypes = [
|
|
1041
|
-
...new Set(params.sweepEligibleBySender.values()),
|
|
1021
|
+
...new Set([...params.sweepEligibleBySender.values()].flatMap((lanes) => [...lanes])),
|
|
1042
1022
|
].sort();
|
|
1043
1023
|
if (expectedSenderIds.length === 0 || expectedActionTypes.length === 0) {
|
|
1044
1024
|
return null;
|
|
@@ -1324,31 +1304,36 @@ function sanitizeRefillTargetPlanResult(result) {
|
|
|
1324
1304
|
const rawSenderPlans = Array.isArray(target.senderPlans)
|
|
1325
1305
|
? target.senderPlans
|
|
1326
1306
|
: [];
|
|
1307
|
+
// Phase 110: accept every senderId:actionType pair the backend emitted —
|
|
1308
|
+
// the backend planner already decided lane selection (single-lane for
|
|
1309
|
+
// non-cascades, both lanes for invite-capable cascades). Do not pick a
|
|
1310
|
+
// winner per sender here.
|
|
1327
1311
|
const selectedBySender = new Map();
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
const evidence = Array.isArray(rawSelection.evidence)
|
|
1334
|
-
? rawSelection.evidence
|
|
1335
|
-
: [];
|
|
1336
|
-
const chosen = chooseEvidenceAction(evidence, fallback);
|
|
1337
|
-
if (chosen)
|
|
1338
|
-
selectedBySender.set(rawSelection.senderId, chosen);
|
|
1339
|
-
}
|
|
1312
|
+
const addSelectedLane = (senderId, actionType) => {
|
|
1313
|
+
const lanes = selectedBySender.get(senderId) ?? new Set();
|
|
1314
|
+
lanes.add(actionType);
|
|
1315
|
+
selectedBySender.set(senderId, lanes);
|
|
1316
|
+
};
|
|
1340
1317
|
for (const rawPlan of rawSenderPlans) {
|
|
1341
|
-
if (!isRecord(rawPlan) ||
|
|
1342
|
-
typeof rawPlan.senderId !== "string" ||
|
|
1343
|
-
selectedBySender.has(rawPlan.senderId)) {
|
|
1318
|
+
if (!isRecord(rawPlan) || typeof rawPlan.senderId !== "string")
|
|
1344
1319
|
continue;
|
|
1345
|
-
}
|
|
1346
1320
|
const actionType = allowedActionType(rawPlan.actionType);
|
|
1347
1321
|
if (actionType)
|
|
1348
|
-
|
|
1322
|
+
addSelectedLane(rawPlan.senderId, actionType);
|
|
1323
|
+
}
|
|
1324
|
+
if (selectedBySender.size === 0) {
|
|
1325
|
+
for (const rawSelection of rawSelections) {
|
|
1326
|
+
if (!isRecord(rawSelection) ||
|
|
1327
|
+
typeof rawSelection.senderId !== "string") {
|
|
1328
|
+
continue;
|
|
1329
|
+
}
|
|
1330
|
+
for (const actionType of actionTypesFrom(rawSelection.actionTypes)) {
|
|
1331
|
+
addSelectedLane(rawSelection.senderId, actionType);
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1349
1334
|
}
|
|
1350
|
-
const selectedKeys = new Set([...selectedBySender.entries()].
|
|
1351
|
-
const actionTypes = [...
|
|
1335
|
+
const selectedKeys = new Set([...selectedBySender.entries()].flatMap(([senderId, lanes]) => [...lanes].map((actionType) => `${senderId}:${actionType}`)));
|
|
1336
|
+
const actionTypes = orderedLanes([...selectedBySender.values()].flatMap((lanes) => [...lanes]));
|
|
1352
1337
|
if (selectedKeys.size === 0)
|
|
1353
1338
|
return emptyUnsupportedResult(result);
|
|
1354
1339
|
const senderPlans = rawSenderPlans.filter((plan) => isRecord(plan) &&
|
|
@@ -1362,13 +1347,13 @@ function sanitizeRefillTargetPlanResult(result) {
|
|
|
1362
1347
|
typeof selection.senderId === "string" &&
|
|
1363
1348
|
selectedBySender.has(selection.senderId))
|
|
1364
1349
|
.map((selection) => {
|
|
1365
|
-
const
|
|
1350
|
+
const lanes = selectedBySender.get(selection.senderId) ?? new Set();
|
|
1366
1351
|
const evidence = Array.isArray(selection.evidence)
|
|
1367
|
-
? selection.evidence.filter((item) => isRecord(item) && item.actionType
|
|
1352
|
+
? selection.evidence.filter((item) => isRecord(item) && lanes.has(String(item.actionType)))
|
|
1368
1353
|
: [];
|
|
1369
1354
|
return {
|
|
1370
1355
|
...selection,
|
|
1371
|
-
actionTypes:
|
|
1356
|
+
actionTypes: orderedLanes(lanes),
|
|
1372
1357
|
evidence,
|
|
1373
1358
|
};
|
|
1374
1359
|
});
|
|
@@ -1401,7 +1386,9 @@ function sanitizeRefillTargetPlanResult(result) {
|
|
|
1401
1386
|
numberValue(plan.remainingProjectedGap) > 0 &&
|
|
1402
1387
|
numberValue(plan.remainingReadyOrProjectedGap) === 0 &&
|
|
1403
1388
|
numberValue(plan.readyBuffer) > 0) {
|
|
1404
|
-
sweepEligibleBySender.
|
|
1389
|
+
const lanes = sweepEligibleBySender.get(senderId) ?? new Set();
|
|
1390
|
+
lanes.add(actionType);
|
|
1391
|
+
sweepEligibleBySender.set(senderId, lanes);
|
|
1405
1392
|
}
|
|
1406
1393
|
}
|
|
1407
1394
|
const schedulerSweepAction = sanitizeTargetSchedulerSweep({
|
package/package.json
CHANGED