@sellable/mcp 0.1.642 → 0.1.643

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.
@@ -965,8 +965,8 @@ export declare function executeRefillSendsCommand(input?: RefillSendsCommandInpu
965
965
  } | {
966
966
  ok: boolean;
967
967
  status: "blocked";
968
- code: "workspace_exact_target_unavailable" | "exact_target_config_unavailable" | "exact_target_config_mismatch" | "exact_target_projection_mismatch";
969
- blocker: "workspace_exact_target_unavailable" | "exact_target_config_unavailable" | "exact_target_config_mismatch" | "exact_target_projection_mismatch";
968
+ code: "workspace_exact_target_unavailable" | "workspace_exact_target_ambiguous" | "exact_target_config_unavailable" | "exact_target_config_mismatch" | "exact_target_projection_mismatch";
969
+ blocker: "workspace_exact_target_unavailable" | "workspace_exact_target_ambiguous" | "exact_target_config_unavailable" | "exact_target_config_mismatch" | "exact_target_projection_mismatch";
970
970
  note: string;
971
971
  targetPlan: unknown;
972
972
  exactTargetPlan: {} | null;
@@ -1454,8 +1454,8 @@ export declare function executeRefillSendsCommand(input?: RefillSendsCommandInpu
1454
1454
  } | {
1455
1455
  ok: boolean;
1456
1456
  status: "blocked";
1457
- code: "workspace_exact_target_unavailable" | "exact_target_config_unavailable" | "exact_target_config_mismatch" | "exact_target_projection_mismatch";
1458
- blocker: "workspace_exact_target_unavailable" | "exact_target_config_unavailable" | "exact_target_config_mismatch" | "exact_target_projection_mismatch";
1457
+ code: "workspace_exact_target_unavailable" | "workspace_exact_target_ambiguous" | "exact_target_config_unavailable" | "exact_target_config_mismatch" | "exact_target_projection_mismatch";
1458
+ blocker: "workspace_exact_target_unavailable" | "workspace_exact_target_ambiguous" | "exact_target_config_unavailable" | "exact_target_config_mismatch" | "exact_target_projection_mismatch";
1459
1459
  note: string;
1460
1460
  targetPlan: unknown;
1461
1461
  exactTargetPlan: {} | null;
@@ -529,15 +529,60 @@ function recordsWithExactTarget(value) {
529
529
  stringValue(candidate.tableId)))
530
530
  : [];
531
531
  }
532
- function workspaceExactTargetsFromAction(action) {
532
+ function workspaceExactActionSignature(action) {
533
+ const campaignId = actionCampaignId(action);
534
+ const tableId = actionTableId(action);
535
+ const actionKey = stringValue(action.actionKey);
536
+ const actionType = stringValue(action.actionType);
537
+ if (!campaignId || !tableId || !actionKey || !actionType)
538
+ return null;
539
+ return JSON.stringify([campaignId, tableId, actionKey, actionType]);
540
+ }
541
+ function workspaceAggregateActionSenderIds(workspacePlan) {
542
+ const target = yoloTarget(workspacePlan);
543
+ const senderPlans = Array.isArray(target?.senderRefillPlans)
544
+ ? target.senderRefillPlans
545
+ .map(recordValue)
546
+ .filter((plan) => Boolean(plan))
547
+ : [];
548
+ const senderIdsByAction = new Map();
549
+ for (const senderPlan of senderPlans) {
550
+ const senderId = stringValue(senderPlan.senderId);
551
+ const nextActions = Array.isArray(senderPlan.nextActions)
552
+ ? senderPlan.nextActions
553
+ .map(recordValue)
554
+ .filter((action) => Boolean(action))
555
+ : [];
556
+ if (!senderId)
557
+ continue;
558
+ for (const action of nextActions) {
559
+ const signature = workspaceExactActionSignature(action);
560
+ if (!signature)
561
+ continue;
562
+ const senderIds = senderIdsByAction.get(signature) ?? new Set();
563
+ senderIds.add(senderId);
564
+ senderIdsByAction.set(signature, senderIds);
565
+ }
566
+ }
567
+ return new Map([...senderIdsByAction.entries()]
568
+ .filter(([, senderIds]) => senderIds.size > 1)
569
+ .map(([signature, senderIds]) => [
570
+ signature,
571
+ [...senderIds],
572
+ ]));
573
+ }
574
+ function workspaceExactTargetsFromAction(action, aggregateSenderIdsByAction = new Map()) {
533
575
  const toolInput = recordValue(action.toolInput) ?? {};
576
+ const exactTargets = recordsWithExactTarget(toolInput.exactTargets);
534
577
  const expectedTargets = recordsWithExactTarget(toolInput.expectedTargets);
535
578
  const sourceScopes = recordsWithExactTarget(toolInput.sourceScopes);
536
- const exactEdges = expectedTargets.length > 0
537
- ? expectedTargets
538
- : sourceScopes.length > 0
539
- ? sourceScopes
540
- : [null];
579
+ const exactEdges = exactTargets.length > 0
580
+ ? exactTargets
581
+ : expectedTargets.length > 0
582
+ ? expectedTargets
583
+ : sourceScopes.length > 0
584
+ ? sourceScopes
585
+ : [null];
541
586
  const campaignIds = normalizeStrings(toolInput.campaignIds);
542
587
  const tableIds = normalizeStrings(toolInput.tableIds);
543
588
  return exactEdges.flatMap((exactEdge) => {
@@ -548,12 +593,26 @@ function workspaceExactTargetsFromAction(action) {
548
593
  if (!campaignId || !tableId)
549
594
  return [];
550
595
  const exactEdgeSenderIds = normalizeStrings(exactEdge?.senderIds);
551
- const senderId = stringValue(exactEdge?.senderId) ?? actionSenderId(action) ?? null;
552
- const senderIds = senderId
553
- ? [senderId]
554
- : exactEdgeSenderIds.length > 0
555
- ? exactEdgeSenderIds
556
- : normalizeStrings(toolInput.senderIds);
596
+ const exactEdgeSenderId = stringValue(exactEdge?.senderId);
597
+ const toolInputSenderIds = normalizeStrings(toolInput.senderIds);
598
+ const aggregateSenderIds = aggregateSenderIdsByAction.get(workspaceExactActionSignature(action) ?? "") ?? [];
599
+ const actionSenderIdValue = actionSenderId(action);
600
+ // Explicit edge/list scope is authoritative. Legacy shared campaign
601
+ // actions predate expectedTargets and can repeat the same representative
602
+ // sender action across several senderRefillPlans. Preserve that recovered
603
+ // member set instead of narrowing the exact coordinator to the complete
604
+ // representative sender and hiding another member's actionable gap.
605
+ const senderIds = exactEdgeSenderIds.length > 0
606
+ ? exactEdgeSenderIds
607
+ : exactEdgeSenderId
608
+ ? [exactEdgeSenderId]
609
+ : toolInputSenderIds.length > 0
610
+ ? toolInputSenderIds
611
+ : aggregateSenderIds.length > 0
612
+ ? aggregateSenderIds
613
+ : actionSenderIdValue
614
+ ? [actionSenderIdValue]
615
+ : [];
557
616
  const directActionType = stringValue(exactEdge?.actionType) ??
558
617
  stringValue(exactEdge?.refillLaneKey) ??
559
618
  stringValue(action.actionType);
@@ -665,7 +724,34 @@ async function selectWorkspaceExactTarget(input, workspacePlanOverride, options
665
724
  .filter((action) => Boolean(action))
666
725
  : [];
667
726
  const workspaceActions = [...globalActions, ...rankedCandidates];
668
- const actionTargets = workspaceActions.flatMap(workspaceExactTargetsFromAction);
727
+ const aggregateSenderIdsByAction = workspaceAggregateActionSenderIds(workspacePlan);
728
+ const legacyGlobalActionCounts = new Map();
729
+ for (const action of globalActions) {
730
+ const signature = workspaceExactActionSignature(action);
731
+ if (!signature)
732
+ continue;
733
+ legacyGlobalActionCounts.set(signature, (legacyGlobalActionCounts.get(signature) ?? 0) + 1);
734
+ }
735
+ const ambiguousLegacyAction = globalActions.find((action) => {
736
+ const signature = workspaceExactActionSignature(action);
737
+ if (!signature || (legacyGlobalActionCounts.get(signature) ?? 0) < 2) {
738
+ return false;
739
+ }
740
+ const toolInput = recordValue(action.toolInput) ?? {};
741
+ const hasExplicitTargets = recordsWithExactTarget(toolInput.exactTargets).length > 0 ||
742
+ recordsWithExactTarget(toolInput.expectedTargets).length > 0 ||
743
+ recordsWithExactTarget(toolInput.sourceScopes).length > 0;
744
+ return !hasExplicitTargets && !aggregateSenderIdsByAction.has(signature);
745
+ });
746
+ if (ambiguousLegacyAction) {
747
+ return {
748
+ status: "blocked",
749
+ code: "workspace_exact_target_ambiguous",
750
+ note: "The workspace planner repeated one legacy aggregate action without explicit exact targets or recoverable sender membership. No refill run or mutation was started.",
751
+ workspacePlan,
752
+ };
753
+ }
754
+ const actionTargets = workspaceActions.flatMap((action) => workspaceExactTargetsFromAction(action, aggregateSenderIdsByAction));
669
755
  const evergreenTargets = evergreenExactTargetCandidates(workspacePlan, {
670
756
  preferredSenderId: options.preferredSenderId,
671
757
  actionTypes: input.actionTypes,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.642",
3
+ "version": "0.1.643",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code, Codex, and Hermes campaign workflows",
6
6
  "main": "dist/index.js",