@sellable/mcp 0.1.553 → 0.1.554
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/index-dev.js +0 -0
- package/dist/index.js +0 -0
- package/dist/refill-date-window.d.ts +34 -0
- package/dist/refill-date-window.js +210 -0
- package/dist/tools/refill-executors.d.ts +0 -30
- package/dist/tools/refill-executors.js +0 -126
- package/dist/tools/refill-sends-evergreen.d.ts +28 -0
- package/dist/tools/refill-sends-evergreen.js +47 -0
- package/dist/tools/refill-sends.d.ts +39 -181
- package/dist/tools/refill-sends.js +13 -141
- package/dist/tools/refill-target-plan.js +3 -181
- package/dist/tools/registry.d.ts +0 -8
- package/dist/tools/scheduler-fill-capacity.js +1 -1
- package/dist/tools/scheduler-run.d.ts +0 -10
- package/dist/tools/scheduler-run.js +0 -20
- package/dist/tools/workspaces.d.ts +6 -4
- package/dist/tools/workspaces.js +13 -11
- package/package.json +1 -1
- package/skills/refill-sends/SKILL.md +7 -42
- package/skills/refill-sends-workflow/SKILL.md +6 -44
- package/skills/refill-sends-workflow/core/flow.v1.json +1 -63
- package/skills/research/config.json +9 -0
|
@@ -10,7 +10,6 @@ const SAFE_PACKET_ACTION_TYPES = new Set([
|
|
|
10
10
|
"approve_messages",
|
|
11
11
|
"start_paused_campaign",
|
|
12
12
|
"rerun_errored_cells",
|
|
13
|
-
"run_scheduler_sweep",
|
|
14
13
|
"wait_for_scheduler",
|
|
15
14
|
"wait_for_active_work",
|
|
16
15
|
"wait_for_source_import",
|
|
@@ -74,21 +73,6 @@ const PREP_FAILURE_RECOMMENDED_ACTIONS = new Set([
|
|
|
74
73
|
"approve_or_repair_approval_cells",
|
|
75
74
|
"inspect_rows",
|
|
76
75
|
]);
|
|
77
|
-
const SCHEDULER_SWEEP_ALLOWED_SIDE_EFFECTS = [
|
|
78
|
-
"schedule any eligible workspace cells on the approved date within scheduler gates",
|
|
79
|
-
];
|
|
80
|
-
const SCHEDULER_SWEEP_FORBIDDEN_SIDE_EFFECTS = [
|
|
81
|
-
"send directly",
|
|
82
|
-
"write scheduler fields directly",
|
|
83
|
-
"change campaign state",
|
|
84
|
-
"change sender limits",
|
|
85
|
-
"change source selection",
|
|
86
|
-
];
|
|
87
|
-
const SCHEDULER_SWEEP_RECEIPT_GROUPS = [
|
|
88
|
-
"campaignId",
|
|
89
|
-
"tableId",
|
|
90
|
-
"actionType",
|
|
91
|
-
];
|
|
92
76
|
async function postRefillTargetPlan(body, workspaceId) {
|
|
93
77
|
const api = getApi();
|
|
94
78
|
const requestOptions = workspaceRequestOptions(workspaceId);
|
|
@@ -531,7 +515,6 @@ function sanitizeStructuredAction(action, selectedBySender, mode, rank) {
|
|
|
531
515
|
: null,
|
|
532
516
|
stopCondition: stringValue(action.stopCondition) ?? "",
|
|
533
517
|
yoloEligible,
|
|
534
|
-
actionKey: stringValue(action.actionKey),
|
|
535
518
|
capSaturated: booleanValue(action.capSaturated) === true ? true : undefined,
|
|
536
519
|
prepFailureDiagnosis: sanitizePrepFailureDiagnosis(action.prepFailureDiagnosis),
|
|
537
520
|
};
|
|
@@ -831,154 +814,6 @@ function buildSanitizedGlobalActionQueue(senderRefillPlans) {
|
|
|
831
814
|
rank: index + 1,
|
|
832
815
|
}));
|
|
833
816
|
}
|
|
834
|
-
function sortedUniqueStrings(value) {
|
|
835
|
-
return [...new Set(stringArray(value))].sort();
|
|
836
|
-
}
|
|
837
|
-
function sameStrings(left, right) {
|
|
838
|
-
return (left.length === right.length &&
|
|
839
|
-
left.every((value, index) => value === right[index]));
|
|
840
|
-
}
|
|
841
|
-
function sanitizeSchedulerSweepSourceScopes(value) {
|
|
842
|
-
if (!Array.isArray(value))
|
|
843
|
-
return [];
|
|
844
|
-
const scopes = value.flatMap((entry) => {
|
|
845
|
-
if (!isRecord(entry))
|
|
846
|
-
return [];
|
|
847
|
-
const campaignId = stringValue(entry.campaignId)?.trim();
|
|
848
|
-
const tableId = stringValue(entry.tableId)?.trim();
|
|
849
|
-
const sourceLeadListId = stringValue(entry.sourceLeadListId)?.trim();
|
|
850
|
-
const leadSourceProvider = stringValue(entry.leadSourceProvider)?.trim();
|
|
851
|
-
if (!campaignId ||
|
|
852
|
-
!tableId ||
|
|
853
|
-
!sourceLeadListId ||
|
|
854
|
-
!leadSourceProvider) {
|
|
855
|
-
return [];
|
|
856
|
-
}
|
|
857
|
-
return [
|
|
858
|
-
{ campaignId, tableId, sourceLeadListId, leadSourceProvider },
|
|
859
|
-
];
|
|
860
|
-
});
|
|
861
|
-
const unique = new Map(scopes.map((scope) => [
|
|
862
|
-
[
|
|
863
|
-
scope.campaignId,
|
|
864
|
-
scope.tableId,
|
|
865
|
-
scope.sourceLeadListId,
|
|
866
|
-
scope.leadSourceProvider,
|
|
867
|
-
].join(":"),
|
|
868
|
-
scope,
|
|
869
|
-
]));
|
|
870
|
-
return [...unique.values()].sort((a, b) => {
|
|
871
|
-
if (a.campaignId !== b.campaignId) {
|
|
872
|
-
return a.campaignId.localeCompare(b.campaignId);
|
|
873
|
-
}
|
|
874
|
-
return a.tableId.localeCompare(b.tableId);
|
|
875
|
-
});
|
|
876
|
-
}
|
|
877
|
-
function sanitizeTargetSchedulerSweep(params) {
|
|
878
|
-
if (!Array.isArray(params.value) ||
|
|
879
|
-
!params.expectedWorkspaceId ||
|
|
880
|
-
!params.expectedTargetDate ||
|
|
881
|
-
!/^\d{4}-\d{2}-\d{2}$/.test(params.expectedTargetDate) ||
|
|
882
|
-
!params.expectedTargetShapeRevision ||
|
|
883
|
-
!params.expectedStateRevision ||
|
|
884
|
-
params.remainingProjectedGap <= 0 ||
|
|
885
|
-
params.remainingReadyOrProjectedGap !== 0) {
|
|
886
|
-
return null;
|
|
887
|
-
}
|
|
888
|
-
const expectedSenderIds = [...params.selectedBySender.keys()].sort();
|
|
889
|
-
const expectedActionTypes = [
|
|
890
|
-
...new Set(params.selectedBySender.values()),
|
|
891
|
-
].sort();
|
|
892
|
-
if (expectedSenderIds.length === 0 || expectedActionTypes.length === 0) {
|
|
893
|
-
return null;
|
|
894
|
-
}
|
|
895
|
-
for (const rawAction of params.value) {
|
|
896
|
-
if (!isRecord(rawAction) || rawAction.type !== "run_scheduler_sweep") {
|
|
897
|
-
continue;
|
|
898
|
-
}
|
|
899
|
-
const input = isRecord(rawAction.toolInput) ? rawAction.toolInput : {};
|
|
900
|
-
const actionKey = stringValue(rawAction.actionKey)?.trim();
|
|
901
|
-
const requestKey = stringValue(input.requestKey)?.trim();
|
|
902
|
-
const senderIds = sortedUniqueStrings(input.senderIds);
|
|
903
|
-
const actionTypes = sortedUniqueStrings(input.actionTypes).filter((actionType) => allowedActionType(actionType) === actionType);
|
|
904
|
-
const campaignIds = sortedUniqueStrings(input.campaignIds);
|
|
905
|
-
const tableIds = sortedUniqueStrings(input.tableIds);
|
|
906
|
-
const sourceScopes = sanitizeSchedulerSweepSourceScopes(input.sourceScopes);
|
|
907
|
-
const receiptRequirements = isRecord(rawAction.receiptRequirements)
|
|
908
|
-
? rawAction.receiptRequirements
|
|
909
|
-
: {};
|
|
910
|
-
const groupBy = stringArray(receiptRequirements.groupBy);
|
|
911
|
-
const allowedSideEffects = stringArray(rawAction.allowedSideEffects);
|
|
912
|
-
const forbiddenSideEffects = stringArray(rawAction.forbiddenSideEffects);
|
|
913
|
-
const rawActionType = allowedActionType(rawAction.actionType);
|
|
914
|
-
if (input.action !== "run" ||
|
|
915
|
-
input.workspaceId !== params.expectedWorkspaceId ||
|
|
916
|
-
input.targetDate !== params.expectedTargetDate ||
|
|
917
|
-
input.targetDateKey !== params.expectedTargetDate ||
|
|
918
|
-
input.targetShapeRevision !== params.expectedTargetShapeRevision ||
|
|
919
|
-
input.stateRevision !== params.expectedStateRevision ||
|
|
920
|
-
!actionKey ||
|
|
921
|
-
requestKey !== actionKey ||
|
|
922
|
-
!sameStrings(senderIds, expectedSenderIds) ||
|
|
923
|
-
!sameStrings(actionTypes, expectedActionTypes) ||
|
|
924
|
-
(expectedActionTypes.length === 1 &&
|
|
925
|
-
rawActionType !== expectedActionTypes[0]) ||
|
|
926
|
-
campaignIds.length === 0 ||
|
|
927
|
-
tableIds.length === 0 ||
|
|
928
|
-
sourceScopes.length === 0 ||
|
|
929
|
-
sourceScopes.some((scope) => !campaignIds.includes(scope.campaignId) ||
|
|
930
|
-
!tableIds.includes(scope.tableId)) ||
|
|
931
|
-
rawAction.toolName !== "run_scheduler_sweep" ||
|
|
932
|
-
rawAction.sideEffectClass !== "scheduler_placement" ||
|
|
933
|
-
rawAction.workspaceWide !== true ||
|
|
934
|
-
rawAction.yoloEligible !== true ||
|
|
935
|
-
receiptRequirements.nonTruncated !== true ||
|
|
936
|
-
!sameStrings(groupBy, SCHEDULER_SWEEP_RECEIPT_GROUPS) ||
|
|
937
|
-
!sameStrings(allowedSideEffects, SCHEDULER_SWEEP_ALLOWED_SIDE_EFFECTS) ||
|
|
938
|
-
!sameStrings(forbiddenSideEffects, SCHEDULER_SWEEP_FORBIDDEN_SIDE_EFFECTS)) {
|
|
939
|
-
continue;
|
|
940
|
-
}
|
|
941
|
-
return {
|
|
942
|
-
rank: 1,
|
|
943
|
-
type: "run_scheduler_sweep",
|
|
944
|
-
actionType: rawActionType,
|
|
945
|
-
toolName: "run_scheduler_sweep",
|
|
946
|
-
sideEffectClass: "scheduler_placement",
|
|
947
|
-
ids: {},
|
|
948
|
-
toolInput: {
|
|
949
|
-
action: "run",
|
|
950
|
-
workspaceId: params.expectedWorkspaceId,
|
|
951
|
-
targetDate: params.expectedTargetDate,
|
|
952
|
-
targetDateKey: params.expectedTargetDate,
|
|
953
|
-
senderIds,
|
|
954
|
-
actionTypes,
|
|
955
|
-
campaignIds,
|
|
956
|
-
tableIds,
|
|
957
|
-
sourceScopes,
|
|
958
|
-
targetShapeRevision: params.expectedTargetShapeRevision,
|
|
959
|
-
stateRevision: params.expectedStateRevision,
|
|
960
|
-
requestKey,
|
|
961
|
-
},
|
|
962
|
-
inputSummary: stringValue(rawAction.inputSummary) ?? "",
|
|
963
|
-
reason: stringValue(rawAction.reason) ?? "",
|
|
964
|
-
prerequisites: stringArray(rawAction.prerequisites),
|
|
965
|
-
rereadAfter: rawAction.rereadAfter === "get_refill_target_plan"
|
|
966
|
-
? "get_refill_target_plan"
|
|
967
|
-
: null,
|
|
968
|
-
stopCondition: stringValue(rawAction.stopCondition) ?? "",
|
|
969
|
-
yoloEligible: true,
|
|
970
|
-
workspaceWide: true,
|
|
971
|
-
allowedSideEffects: [...SCHEDULER_SWEEP_ALLOWED_SIDE_EFFECTS],
|
|
972
|
-
forbiddenSideEffects: [...SCHEDULER_SWEEP_FORBIDDEN_SIDE_EFFECTS],
|
|
973
|
-
receiptRequirements: {
|
|
974
|
-
nonTruncated: true,
|
|
975
|
-
groupBy: [...SCHEDULER_SWEEP_RECEIPT_GROUPS],
|
|
976
|
-
},
|
|
977
|
-
actionKey,
|
|
978
|
-
};
|
|
979
|
-
}
|
|
980
|
-
return null;
|
|
981
|
-
}
|
|
982
817
|
function paidRefreshNeededSenderIds(senderRefillPlans) {
|
|
983
818
|
const senderIds = new Set();
|
|
984
819
|
for (const plan of senderRefillPlans) {
|
|
@@ -1124,8 +959,8 @@ function sanitizeRefillTargetPlanResult(result) {
|
|
|
1124
959
|
const grossTarget = senderPlans.reduce((sum, plan) => sum + numberValue(plan.grossTarget), 0);
|
|
1125
960
|
const requestedTarget = senderPlans.reduce((sum, plan) => sum + numberValue(plan.requestedTarget), 0);
|
|
1126
961
|
const effectiveTarget = senderPlans.reduce((sum, plan) => {
|
|
1127
|
-
const target = typeof plan.
|
|
1128
|
-
? plan.
|
|
962
|
+
const target = typeof plan.schedulerCapacityTarget === "number"
|
|
963
|
+
? plan.schedulerCapacityTarget
|
|
1129
964
|
: numberValue(plan.grossTarget);
|
|
1130
965
|
return sum + target;
|
|
1131
966
|
}, 0);
|
|
@@ -1140,20 +975,7 @@ function sanitizeRefillTargetPlanResult(result) {
|
|
|
1140
975
|
const senderRefillPlans = sanitizeStructuredSenderPlans(target.senderRefillPlans, selectedBySender);
|
|
1141
976
|
const paidRefreshNeededSenderIdSet = paidRefreshNeededSenderIds(senderRefillPlans);
|
|
1142
977
|
const blockers = sanitizeBlockers(result.blockers, selectedKeys, paidRefreshNeededSenderIdSet);
|
|
1143
|
-
const
|
|
1144
|
-
const schedulerSweepAction = sanitizeTargetSchedulerSweep({
|
|
1145
|
-
value: target.globalActionQueue,
|
|
1146
|
-
selectedBySender,
|
|
1147
|
-
expectedWorkspaceId: stringValue(target.workspaceId),
|
|
1148
|
-
expectedTargetDate: stringValue(request.targetDate),
|
|
1149
|
-
expectedTargetShapeRevision: stringValue(result.targetShapeRevision),
|
|
1150
|
-
expectedStateRevision: stringValue(result.stateRevision),
|
|
1151
|
-
remainingProjectedGap,
|
|
1152
|
-
remainingReadyOrProjectedGap,
|
|
1153
|
-
});
|
|
1154
|
-
const globalActionQueue = schedulerSweepAction
|
|
1155
|
-
? [schedulerSweepAction]
|
|
1156
|
-
: buildSanitizedGlobalActionQueue(senderRefillPlans);
|
|
978
|
+
const globalActionQueue = buildSanitizedGlobalActionQueue(senderRefillPlans);
|
|
1157
979
|
const hasTerminalNoActionBlocker = globalActionQueue.length === 0 &&
|
|
1158
980
|
blockers.some((blocker) => TERMINAL_NO_ACTION_BLOCKER_CODES.has(String(blocker.code)));
|
|
1159
981
|
const status = remainingProjectedGap === 0
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -7546,14 +7546,6 @@ export declare const allTools: ({
|
|
|
7546
7546
|
type: string;
|
|
7547
7547
|
description: string;
|
|
7548
7548
|
};
|
|
7549
|
-
requestKey: {
|
|
7550
|
-
type: string;
|
|
7551
|
-
description: string;
|
|
7552
|
-
};
|
|
7553
|
-
targetShapeRevision: {
|
|
7554
|
-
type: string;
|
|
7555
|
-
description: string;
|
|
7556
|
-
};
|
|
7557
7549
|
};
|
|
7558
7550
|
required: string[];
|
|
7559
7551
|
additionalProperties: boolean;
|
|
@@ -10,7 +10,7 @@ async function postSchedulerFillCapacity(body, workspaceId) {
|
|
|
10
10
|
export const schedulerFillCapacityToolDefinitions = [
|
|
11
11
|
{
|
|
12
12
|
name: "get_scheduler_fill_capacity",
|
|
13
|
-
description: "read-only scheduler capacity query for refill-sends before any refill mutation. It asks the product scheduler model how many additional cells the scheduler will try to place for exact sender/action requests, using the default scheduler-forward horizon or one exact targetDate. It returns scheduler-fillable slots, occupied scheduled/processing slots,
|
|
13
|
+
description: "read-only scheduler capacity query for refill-sends before any refill mutation. It asks the product scheduler model how many additional cells the scheduler will try to place for exact sender/action requests, using the default scheduler-forward horizon or one exact targetDate. It returns scheduler-fillable slots, occupied scheduled/processing slots, sender sendability gates, cooldowns, Sales Navigator status for paid InMail, cached paid-InMail credit feasibility, threshold source, blockers, warnings, and explicit sideEffects false. This tool does not create rows, import leads, prepare messages, approve messages, does not schedule sends, does not refresh paid InMail credits, mutate thresholds, start campaigns, launch, or send. Use exact senderId values only; never pass sender names.",
|
|
14
14
|
inputSchema: {
|
|
15
15
|
type: "object",
|
|
16
16
|
properties: {
|
|
@@ -3,8 +3,6 @@ type RunSchedulerSweepInput = {
|
|
|
3
3
|
workspaceId: string;
|
|
4
4
|
action?: SchedulerRunAction;
|
|
5
5
|
targetDate?: string;
|
|
6
|
-
requestKey?: string;
|
|
7
|
-
targetShapeRevision?: string;
|
|
8
6
|
};
|
|
9
7
|
export declare const schedulerRunToolDefinitions: {
|
|
10
8
|
name: string;
|
|
@@ -25,14 +23,6 @@ export declare const schedulerRunToolDefinitions: {
|
|
|
25
23
|
type: string;
|
|
26
24
|
description: string;
|
|
27
25
|
};
|
|
28
|
-
requestKey: {
|
|
29
|
-
type: string;
|
|
30
|
-
description: string;
|
|
31
|
-
};
|
|
32
|
-
targetShapeRevision: {
|
|
33
|
-
type: string;
|
|
34
|
-
description: string;
|
|
35
|
-
};
|
|
36
26
|
};
|
|
37
27
|
required: string[];
|
|
38
28
|
additionalProperties: boolean;
|
|
@@ -21,14 +21,6 @@ function normalizeTargetDate(value) {
|
|
|
21
21
|
}
|
|
22
22
|
return targetDate;
|
|
23
23
|
}
|
|
24
|
-
function normalizeOptionalScopeValue(value, field) {
|
|
25
|
-
if (value === undefined || value === null)
|
|
26
|
-
return null;
|
|
27
|
-
if (typeof value !== "string" || !value.trim()) {
|
|
28
|
-
throw new Error(`${field} must be a non-empty string when provided.`);
|
|
29
|
-
}
|
|
30
|
-
return value.trim();
|
|
31
|
-
}
|
|
32
24
|
export const schedulerRunToolDefinitions = [
|
|
33
25
|
{
|
|
34
26
|
name: "run_scheduler_sweep",
|
|
@@ -49,14 +41,6 @@ export const schedulerRunToolDefinitions = [
|
|
|
49
41
|
type: "string",
|
|
50
42
|
description: "Optional one exact sender-local date (YYYY-MM-DD) to scope scheduler placement/status. The run remains workspace-wide inside that date.",
|
|
51
43
|
},
|
|
52
|
-
requestKey: {
|
|
53
|
-
type: "string",
|
|
54
|
-
description: "Optional deterministic planner action key used to attach to or replay the same exact scheduler attempt.",
|
|
55
|
-
},
|
|
56
|
-
targetShapeRevision: {
|
|
57
|
-
type: "string",
|
|
58
|
-
description: "Optional stable approved refill target-shape revision associated with requestKey.",
|
|
59
|
-
},
|
|
60
44
|
},
|
|
61
45
|
required: ["workspaceId"],
|
|
62
46
|
additionalProperties: false,
|
|
@@ -70,8 +54,6 @@ export async function runSchedulerSweep(input) {
|
|
|
70
54
|
}
|
|
71
55
|
const action = input.action ?? "run";
|
|
72
56
|
const targetDate = normalizeTargetDate(input.targetDate);
|
|
73
|
-
const requestKey = normalizeOptionalScopeValue(input.requestKey, "requestKey");
|
|
74
|
-
const targetShapeRevision = normalizeOptionalScopeValue(input.targetShapeRevision, "targetShapeRevision");
|
|
75
57
|
if (action !== "run" && action !== "status") {
|
|
76
58
|
throw new Error('action must be "run" or "status" for run_scheduler_sweep.');
|
|
77
59
|
}
|
|
@@ -79,7 +61,5 @@ export async function runSchedulerSweep(input) {
|
|
|
79
61
|
workspaceId,
|
|
80
62
|
action,
|
|
81
63
|
...(targetDate ? { targetDate } : {}),
|
|
82
|
-
...(requestKey ? { requestKey } : {}),
|
|
83
|
-
...(targetShapeRevision ? { targetShapeRevision } : {}),
|
|
84
64
|
}, workspaceId);
|
|
85
65
|
}
|
|
@@ -142,15 +142,17 @@ export declare function listWorkspaces(): Promise<{
|
|
|
142
142
|
workspaces: WorkspaceSummary[];
|
|
143
143
|
workspaceLock: {
|
|
144
144
|
enabled: boolean;
|
|
145
|
-
workspaceId
|
|
146
|
-
hiddenWorkspaceCount
|
|
145
|
+
workspaceId: string;
|
|
146
|
+
hiddenWorkspaceCount: number;
|
|
147
|
+
siblingInventoryFetched: boolean;
|
|
147
148
|
};
|
|
148
149
|
} | {
|
|
149
150
|
workspaces: WorkspaceSummary[];
|
|
150
151
|
workspaceLock: {
|
|
151
152
|
enabled: boolean;
|
|
152
|
-
workspaceId
|
|
153
|
-
hiddenWorkspaceCount
|
|
153
|
+
workspaceId?: undefined;
|
|
154
|
+
hiddenWorkspaceCount?: undefined;
|
|
155
|
+
siblingInventoryFetched?: undefined;
|
|
154
156
|
};
|
|
155
157
|
}>;
|
|
156
158
|
export declare function getActiveWorkspace(): {
|
package/dist/tools/workspaces.js
CHANGED
|
@@ -80,19 +80,21 @@ export const workspaceToolDefinitions = [
|
|
|
80
80
|
];
|
|
81
81
|
export async function listWorkspaces() {
|
|
82
82
|
const api = getApi();
|
|
83
|
-
const { workspaces } = await api.get("/api/v3/workspaces");
|
|
84
83
|
const lockedWorkspaceId = getLockedWorkspaceId();
|
|
85
|
-
if (
|
|
86
|
-
|
|
84
|
+
if (lockedWorkspaceId) {
|
|
85
|
+
const { workspace } = await api.get(`/api/v3/workspaces/${encodeURIComponent(lockedWorkspaceId)}`);
|
|
86
|
+
return {
|
|
87
|
+
workspaces: [workspace],
|
|
88
|
+
workspaceLock: {
|
|
89
|
+
enabled: true,
|
|
90
|
+
workspaceId: lockedWorkspaceId,
|
|
91
|
+
hiddenWorkspaceCount: 0,
|
|
92
|
+
siblingInventoryFetched: false,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
87
95
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
workspaceLock: {
|
|
91
|
-
enabled: true,
|
|
92
|
-
workspaceId: lockedWorkspaceId,
|
|
93
|
-
hiddenWorkspaceCount: workspaces.filter((ws) => ws.id !== lockedWorkspaceId).length,
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
+
const { workspaces } = await api.get("/api/v3/workspaces");
|
|
97
|
+
return { workspaces, workspaceLock: { enabled: false } };
|
|
96
98
|
}
|
|
97
99
|
export function getActiveWorkspace() {
|
|
98
100
|
const config = getConfig();
|
package/package.json
CHANGED
|
@@ -83,8 +83,6 @@ Accepted invocation flags in the same user request:
|
|
|
83
83
|
- `senderIds: <id>, <id>` or `senderNames: <name>, <name>`: explicit selector
|
|
84
84
|
alternatives when the host preserves natural-language arguments better than
|
|
85
85
|
shell-style flags.
|
|
86
|
-
- `actionTypes: send_invite, send_inmail_closed`: optional lane selector. Omit
|
|
87
|
-
`actionTypes` to preserve the target planner's lane inference.
|
|
88
86
|
- `untilDate: YYYY-MM-DD`: explicit date selector alternative when the host
|
|
89
87
|
preserves natural-language arguments better than shell-style flags.
|
|
90
88
|
- `targetDate: YYYY-MM-DD`: exact-date selector alternative when the host
|
|
@@ -93,7 +91,7 @@ Accepted invocation flags in the same user request:
|
|
|
93
91
|
When the host can call typed MCP tools, start with:
|
|
94
92
|
|
|
95
93
|
```text
|
|
96
|
-
refill_sends({ yolo?: boolean, executionMode?: "manual" | "scheduled" | "yolo", requireWorkspace?: boolean, workspaceId?: string, senders?: string[], senderIds?: string[], senderNames?: string[],
|
|
94
|
+
refill_sends({ yolo?: boolean, executionMode?: "manual" | "scheduled" | "yolo", requireWorkspace?: boolean, workspaceId?: string, senders?: string[], senderIds?: string[], senderNames?: string[], horizonSendDays?: number, untilDate?: "YYYY-MM-DD", targetDate?: "YYYY-MM-DD" })
|
|
97
95
|
```
|
|
98
96
|
|
|
99
97
|
That command helper normalizes arguments and returns the execution contract. In
|
|
@@ -101,22 +99,14 @@ non-yolo mode it does not mutate. In `--yolo`, it may execute exactly one safe
|
|
|
101
99
|
bounded primitive from the fresh `target.globalActionQueue[0]`, then reread and
|
|
102
100
|
return the new target plan; currently safe primitives are paid-credit refresh,
|
|
103
101
|
existing-row message preparation, generated-message approval, receipt-proven
|
|
104
|
-
same-source row copy,
|
|
105
|
-
read-only wait rereads. Same-source copy/source
|
|
102
|
+
same-source row copy, and read-only wait rereads. Same-source copy/source
|
|
106
103
|
fallback is safe only after receipt-proven exhaustion:
|
|
107
104
|
`hasMoreFrontierRows:false`, zero `approvalCandidates`, no `stuckActiveCells`,
|
|
108
|
-
and no non-terminal `approvedNotDispatched` work. It does not run unbounded
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
The approval scope is the exact `workspaceId`, `targetDate`, sender ids, action
|
|
115
|
-
types, campaign/table/source ids, `targetShapeRevision`, and `actionKey` in the
|
|
116
|
-
rendered packet. `stateRevision` and sent/scheduled/ready counts are mutable
|
|
117
|
-
progress, not approval-scope drift. Execute only
|
|
118
|
-
`target.globalActionQueue[0]`, then perform a full authoritative reread before
|
|
119
|
-
deciding any next action.
|
|
105
|
+
and no non-terminal `approvedNotDispatched` work. It does not run unbounded approval, lower
|
|
106
|
+
paid-InMail thresholds, switch source families, create campaigns, launch, send,
|
|
107
|
+
or write scheduler rows. Continue with the workflow below for route selection,
|
|
108
|
+
state rereads, approval gating, source import, preparation, and bounded
|
|
109
|
+
approval.
|
|
120
110
|
|
|
121
111
|
## Workspace Contract
|
|
122
112
|
|
|
@@ -286,27 +276,10 @@ need raw proof, call the read-only `get_scheduler_fill_capacity` query for the
|
|
|
286
276
|
same sender/action/date; it tells the MCP how many cells the product scheduler
|
|
287
277
|
will try to place and does not import, approve, schedule, refresh credits, or
|
|
288
278
|
mutate.
|
|
289
|
-
Treat `rollingWeeklyInvite.capacityFreedDuringWindow:true` as proof that
|
|
290
|
-
rolling-weekly capacity frees later in the send window and remains schedulable;
|
|
291
|
-
use its timing fields instead of treating the window-start gate as a permanent
|
|
292
|
-
full-day blocker.
|
|
293
279
|
When the refill loop has ready rows and needs scheduler pickup now, use
|
|
294
280
|
`run_scheduler_sweep` with the same explicit `workspaceId`; it can place cells
|
|
295
281
|
within existing scheduler gates and returns the receipt, but it never sends or
|
|
296
282
|
bypasses limits.
|
|
297
|
-
A scheduler sweep is a visible workspace-wide scheduling side effect. The
|
|
298
|
-
request packet limits the expected target changes to its exact date, senders,
|
|
299
|
-
action types, campaigns, tables, and stable sources, but the product scheduler
|
|
300
|
-
may also place unrelated eligible workspace work; disclose that possibility in
|
|
301
|
-
the approval packet and receipt. For an exact-date sweep action, execute it
|
|
302
|
-
once, then reread the full target plan before taking or presenting another
|
|
303
|
-
action.
|
|
304
|
-
The exact-date `run_scheduler_sweep` may schedule eligible workspace cells
|
|
305
|
-
through existing product gates; it never sends directly or raw-writes scheduler
|
|
306
|
-
fields. Only non-exact or no-sweep scheduler waits are read-only.
|
|
307
|
-
On resume, reconcile the current target plan and matching sweep status/receipt
|
|
308
|
-
before retrying. A matching same-key terminal receipt replays; an
|
|
309
|
-
`uncertain_outcome` stops for reconciliation and must not schedule again.
|
|
310
283
|
Scheduler-run receipt interpretation: `cellsConsidered is allocation-attempt
|
|
311
284
|
count`, not total ready supply, while `readyCellsFound` is ready inventory found
|
|
312
285
|
before prefilters. Inspect `campaignScopeSummary` before assuming the selected
|
|
@@ -419,14 +392,6 @@ scheduler wait loop. Do not finish the refill goal, mark it complete, or mark it
|
|
|
419
392
|
blocked only because it is still `awaiting_scheduler_after_ready_buffer`; keep
|
|
420
393
|
waiting unless Christian stops the run or the host cannot continue.
|
|
421
394
|
|
|
422
|
-
Future scheduled coverage and already sent actions are distinct; only
|
|
423
|
-
scheduler-owned future scheduled actions count as scheduled coverage. For
|
|
424
|
-
multiple target dates, finish D1 execution and the full D1 reread before
|
|
425
|
-
planning D2. Completion proof is product-native Sellable MCP evidence only:
|
|
426
|
-
target plan, campaign refill state, scheduler capacity, sweep/status, and
|
|
427
|
-
bounded receipts. Never use individual cell ids, Prisma, SQL, direct database
|
|
428
|
-
access, or production-environment scripts as completion proof.
|
|
429
|
-
|
|
430
395
|
In `--yolo`, the default fill target is the scheduler-forward 48-hour window
|
|
431
396
|
unless `--target-date`/`targetDate`, `--until`/`untilDate`, or an explicit
|
|
432
397
|
compatibility `horizonSendDays` is provided. If a target date is provided,
|
|
@@ -75,20 +75,6 @@ calls, preparation calls, approval calls, and campaign start calls. Missing
|
|
|
75
75
|
interactive workspace switching is diagnostic setup only and is not an
|
|
76
76
|
automation control path.
|
|
77
77
|
|
|
78
|
-
Typed command scope:
|
|
79
|
-
|
|
80
|
-
```text
|
|
81
|
-
refill_sends({ yolo?: boolean, executionMode?: "manual" | "scheduled" | "yolo", requireWorkspace?: boolean, workspaceId?: string, senders?: string[], senderIds?: string[], senderNames?: string[], actionTypes?: ("send_invite" | "send_inmail_closed")[], horizonSendDays?: number, untilDate?: "YYYY-MM-DD", targetDate?: "YYYY-MM-DD" })
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Omit `actionTypes` to preserve the target planner's lane inference. The
|
|
85
|
-
approval scope is the exact `workspaceId`, `targetDate`, sender ids, action
|
|
86
|
-
types, campaign/table/source ids, `targetShapeRevision`, and `actionKey` in the
|
|
87
|
-
rendered packet. `stateRevision` and sent/scheduled/ready counts are mutable
|
|
88
|
-
progress, not approval-scope drift. Execute only
|
|
89
|
-
`target.globalActionQueue[0]`, then perform a full authoritative reread before
|
|
90
|
-
deciding any next action.
|
|
91
|
-
|
|
92
78
|
Goal-mode continuation: a skill cannot create or invoke `/goal` by itself. When
|
|
93
79
|
this workflow is already running inside an active Codex goal, keep that goal
|
|
94
80
|
open until every selected sender lane is horizon-filled by projected coverage
|
|
@@ -206,19 +192,6 @@ files or memory.
|
|
|
206
192
|
`run_scheduler_sweep` with the same explicit `workspaceId` to request the
|
|
207
193
|
product scheduler placement pass now and read its receipt. This may place
|
|
208
194
|
cells within existing gates, never sends messages, and never bypasses limits.
|
|
209
|
-
A scheduler sweep is a visible workspace-wide scheduling side effect. The
|
|
210
|
-
request packet limits expected target changes to the exact date, senders,
|
|
211
|
-
action types, campaigns, tables, and stable sources, but unrelated eligible
|
|
212
|
-
workspace work may also be scheduled by the product scheduler and must be
|
|
213
|
-
disclosed. For an exact-date sweep action, execute it once and perform the
|
|
214
|
-
full target-plan reread before taking or presenting another action.
|
|
215
|
-
The exact-date `run_scheduler_sweep` may schedule eligible workspace cells
|
|
216
|
-
through existing product gates; it never sends directly or raw-writes
|
|
217
|
-
scheduler fields. Only non-exact or no-sweep scheduler waits are read-only.
|
|
218
|
-
On resume, reconcile the current target plan and matching sweep
|
|
219
|
-
status/receipt before retrying. A matching same-key terminal receipt
|
|
220
|
-
replays; an `uncertain_outcome` stops for reconciliation and must not
|
|
221
|
-
schedule again.
|
|
222
195
|
Scheduler-run receipt interpretation: `cellsConsidered is
|
|
223
196
|
allocation-attempt count`, not total ready supply, while `readyCellsFound`
|
|
224
197
|
is ready inventory found before prefilters. Inspect `campaignScopeSummary`
|
|
@@ -237,10 +210,8 @@ files or memory.
|
|
|
237
210
|
scheduled count, projected count, campaign ids, and no-op proof without
|
|
238
211
|
asking for approval or mutating.
|
|
239
212
|
If `remainingReadyOrProjectedGap:0` but `remainingProjectedGap>0`, and paid
|
|
240
|
-
InMail credit freshness is clean for every selected paid-InMail lane,
|
|
241
|
-
|
|
242
|
-
`target.globalActionQueue[0]`, then fully reread. Otherwise, run only a
|
|
243
|
-
persistent read-only scheduler wait/reread loop; do not ask for
|
|
213
|
+
InMail credit freshness is clean for every selected paid-InMail lane, run
|
|
214
|
+
only a persistent read-only scheduler wait/reread loop; do not ask for
|
|
244
215
|
prep/import/approval. Poll `get_refill_target_plan` every 60-120 seconds, or
|
|
245
216
|
on the host's next continuation interval, until projected coverage fills,
|
|
246
217
|
a concrete non-scheduler blocker appears, or Christian explicitly asks to
|
|
@@ -413,11 +384,10 @@ exceeds the sender's capacity for the selected target window. Put another way:
|
|
|
413
384
|
complete when the same daily-limit/readback model would show no remaining
|
|
414
385
|
send-day capacity for that selected lane. Ready-to-schedule rows are only buffer
|
|
415
386
|
for the product scheduler. If ready plus projected coverage covers the target
|
|
416
|
-
window but scheduled cells do not yet,
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
or asks for status only. `awaiting_scheduler_after_ready_buffer` is not
|
|
387
|
+
window but scheduled cells do not yet, run a persistent read-only scheduler wait
|
|
388
|
+
loop: wait, reread, recompute the ledger, and continue until projected coverage
|
|
389
|
+
is proved, a concrete non-scheduler blocker appears, or Christian explicitly
|
|
390
|
+
stops or asks for status only. `awaiting_scheduler_after_ready_buffer` is not
|
|
421
391
|
success and is not a terminal blocker for an active refill goal; it is the
|
|
422
392
|
loaded, awaiting scheduler poll state that keeps the thread waiting. It does not
|
|
423
393
|
need a prep/import/approval packet.
|
|
@@ -750,14 +720,6 @@ with non-null `scheduledFor`. Prepared, approved, and ready-to-schedule rows are
|
|
|
750
720
|
intermediate states; report them as awaiting scheduler unless scheduled cells
|
|
751
721
|
are present.
|
|
752
722
|
|
|
753
|
-
Future scheduled coverage and already sent actions are distinct; only
|
|
754
|
-
scheduler-owned future scheduled actions count as scheduled coverage. For
|
|
755
|
-
multiple target dates, finish D1 execution and the full D1 reread before
|
|
756
|
-
planning D2. Completion proof is product-native Sellable MCP evidence only:
|
|
757
|
-
target plan, campaign refill state, scheduler capacity, sweep/status, and
|
|
758
|
-
bounded receipts. Never use individual cell ids, Prisma, SQL, direct database
|
|
759
|
-
access, or production-environment scripts as completion proof.
|
|
760
|
-
|
|
761
723
|
preparedMessages can remain 0 while scheduler-ready state changes downstream.
|
|
762
724
|
After a prep job reaches a terminal state, run `wait_for_campaign_processing`
|
|
763
725
|
when generated/pass counts are still settling, then poll `get_campaign_refill_state` until `readyToSchedule` drops, scheduled counts increase, or the state clearly
|