@sellable/mcp 0.1.537 → 0.1.539
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/README.md +5 -2
- 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/refill-run-loop.d.ts +9 -1
- package/dist/refill-run-loop.js +151 -90
- package/dist/tools/evergreen-refill-plan.d.ts +19 -0
- package/dist/tools/evergreen-refill-plan.js +19 -0
- package/dist/tools/refill-executors.d.ts +0 -7
- package/dist/tools/refill-executors.js +0 -22
- package/dist/tools/refill-sends-evergreen.d.ts +28 -0
- package/dist/tools/refill-sends-evergreen.js +47 -0
- package/dist/tools/refill-sends-v2.d.ts +19 -0
- package/dist/tools/refill-sends-v2.js +31 -2
- package/dist/tools/refill-sends.d.ts +0 -12
- package/dist/tools/refill-sends.js +36 -58
- package/dist/tools/refill-target-plan.js +19 -6
- package/dist/tools/registry.d.ts +36 -0
- package/dist/tools/scheduler-fill-capacity.js +1 -1
- package/dist/tools/scheduler-run.d.ts +5 -0
- package/dist/tools/scheduler-run.js +24 -1
- package/dist/tools/senders.d.ts +8 -14
- package/dist/tools/senders.js +10 -21
- package/package.json +1 -1
- package/skills/refill-sends/SKILL.md +9 -1
- package/skills/refill-sends-v2/SKILL.md +18 -5
- package/skills/refill-sends-v2-workflow/SKILL.md +16 -2
- package/skills/refill-sends-v2-workflow/core/flow.v1.json +19 -3
- package/skills/refill-sends-workflow/SKILL.md +5 -3
- package/skills/refill-sends-workflow/core/flow.v1.json +1 -1
|
@@ -3,6 +3,9 @@ type GetRefillPlanV2Input = {
|
|
|
3
3
|
intent?: "auto" | "evergreen" | "plain" | "active";
|
|
4
4
|
senderIds?: string[];
|
|
5
5
|
runState?: Record<string, unknown>;
|
|
6
|
+
targetDate?: string | null;
|
|
7
|
+
untilDate?: string | null;
|
|
8
|
+
horizonSendDays?: number | null;
|
|
6
9
|
journal?: boolean;
|
|
7
10
|
journalNote?: string;
|
|
8
11
|
};
|
|
@@ -38,6 +41,22 @@ export declare const refillPlanV2ToolDefinitions: {
|
|
|
38
41
|
enum: string[];
|
|
39
42
|
description: string;
|
|
40
43
|
};
|
|
44
|
+
targetDate: {
|
|
45
|
+
type: string;
|
|
46
|
+
pattern: string;
|
|
47
|
+
description: string;
|
|
48
|
+
};
|
|
49
|
+
untilDate: {
|
|
50
|
+
type: string;
|
|
51
|
+
pattern: string;
|
|
52
|
+
description: string;
|
|
53
|
+
};
|
|
54
|
+
horizonSendDays: {
|
|
55
|
+
type: string;
|
|
56
|
+
minimum: number;
|
|
57
|
+
maximum: number;
|
|
58
|
+
description: string;
|
|
59
|
+
};
|
|
41
60
|
journal: {
|
|
42
61
|
type: string;
|
|
43
62
|
description: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { getApi, SellableApiError } from "../api.js";
|
|
3
|
+
import { normalizeRefillDateSelector, refillDateSelectorBody, } from "../refill-date-window.js";
|
|
3
4
|
import { appendIndexLine, appendJournalEvent, createRunJournal, renderBootstrapSection, renderPlanSection, renderTerminalSection, } from "../refill-journal.js";
|
|
4
5
|
import { readRefillWorkspaceState } from "../refill-local-state.js";
|
|
5
6
|
import { normalizeExplicitWorkspaceId, workspaceRequestOptions, } from "./workspace-context.js";
|
|
@@ -175,6 +176,22 @@ export const refillPlanV2ToolDefinitions = [
|
|
|
175
176
|
enum: ["auto", "evergreen", "plain", "active"],
|
|
176
177
|
description: 'Planner intent. Defaults to "auto" for refill-sends-v2.',
|
|
177
178
|
},
|
|
179
|
+
targetDate: {
|
|
180
|
+
type: "string",
|
|
181
|
+
pattern: "^\\d{4}-\\d{2}-\\d{2}$",
|
|
182
|
+
description: "Optional one exact sender-local date (YYYY-MM-DD) to plan. Takes precedence over untilDate and horizonSendDays.",
|
|
183
|
+
},
|
|
184
|
+
untilDate: {
|
|
185
|
+
type: "string",
|
|
186
|
+
pattern: "^\\d{4}-\\d{2}-\\d{2}$",
|
|
187
|
+
description: "Optional inclusive sender-local through-date (YYYY-MM-DD) to plan.",
|
|
188
|
+
},
|
|
189
|
+
horizonSendDays: {
|
|
190
|
+
type: "number",
|
|
191
|
+
minimum: 1,
|
|
192
|
+
maximum: 7,
|
|
193
|
+
description: "Optional explicit next N sender-local send days to plan.",
|
|
194
|
+
},
|
|
178
195
|
journal: {
|
|
179
196
|
type: "boolean",
|
|
180
197
|
description: "Set false to skip the local dry-run journal write.",
|
|
@@ -197,6 +214,7 @@ export async function getRefillPlanV2(input) {
|
|
|
197
214
|
const runState = input.runState !== undefined
|
|
198
215
|
? input.runState
|
|
199
216
|
: buildRunStateFromLocalHints(workspaceId);
|
|
217
|
+
const dateSelector = normalizeRefillDateSelector(input);
|
|
200
218
|
let raw;
|
|
201
219
|
try {
|
|
202
220
|
raw = await postRefillPlanV2({
|
|
@@ -204,6 +222,7 @@ export async function getRefillPlanV2(input) {
|
|
|
204
222
|
intent: input.intent ?? "auto",
|
|
205
223
|
senderIds: input.senderIds,
|
|
206
224
|
runState,
|
|
225
|
+
...refillDateSelectorBody(dateSelector),
|
|
207
226
|
}, workspaceId);
|
|
208
227
|
}
|
|
209
228
|
catch (error) {
|
|
@@ -14,12 +14,6 @@ export type PaidInmailCreditRefreshOptions = {
|
|
|
14
14
|
maxStalenessSeconds?: number | null;
|
|
15
15
|
paidInmailCreditsMaxStalenessSeconds?: number | null;
|
|
16
16
|
};
|
|
17
|
-
export type PaidInmailRefreshReceiptClassification = {
|
|
18
|
-
usableCurrentFacts: boolean;
|
|
19
|
-
status: string;
|
|
20
|
-
error: string | null;
|
|
21
|
-
refreshed: boolean;
|
|
22
|
-
};
|
|
23
17
|
export type YoloPrimitiveExecution = {
|
|
24
18
|
enabled: true;
|
|
25
19
|
status: "no_action" | "read_only_reread" | "executed_and_reread" | "refused" | "skipped_after_paid_refresh";
|
|
@@ -141,7 +135,6 @@ export declare function userAddedRowsLimitPayloadFromError(error: unknown): User
|
|
|
141
135
|
export declare function sourceImportInProgressPayloadFromError(error: unknown): SourceImportInProgressPayload | null;
|
|
142
136
|
export declare function paidRefreshActionFrom(value: unknown): PaidInmailRefreshAction | null;
|
|
143
137
|
export declare function collectPaidInmailRefreshActions(plan: unknown): PaidInmailRefreshAction[];
|
|
144
|
-
export declare function classifyPaidInmailRefreshReceipt(value: unknown): PaidInmailRefreshReceiptClassification;
|
|
145
138
|
export declare function firstGlobalAction(plan: unknown): Record<string, unknown> | null;
|
|
146
139
|
export declare function actionIds(action: Record<string, unknown>): Record<string, unknown>;
|
|
147
140
|
export declare function actionToolInput(action: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -10,11 +10,6 @@ const PAID_INMAIL_REFRESH_RETRY_DELAY_MS = Number(process.env.SELLABLE_MCP_PAID_
|
|
|
10
10
|
const SIGNAL_DISCOVERY_MIN_REFILL_POSTS = 3;
|
|
11
11
|
const SIGNAL_DISCOVERY_MAX_REFILL_POSTS = 10;
|
|
12
12
|
const SIGNAL_DISCOVERY_TARGET_ROWS_PER_POST = 150;
|
|
13
|
-
const USABLE_PAID_INMAIL_REFRESH_RECEIPT_STATUSES = new Set([
|
|
14
|
-
"fresh",
|
|
15
|
-
"refreshed",
|
|
16
|
-
"below_threshold",
|
|
17
|
-
]);
|
|
18
13
|
export function normalizeStrings(values) {
|
|
19
14
|
if (!Array.isArray(values))
|
|
20
15
|
return [];
|
|
@@ -211,23 +206,6 @@ export function collectPaidInmailRefreshActions(plan) {
|
|
|
211
206
|
add(action);
|
|
212
207
|
return [...bySender.values()];
|
|
213
208
|
}
|
|
214
|
-
export function classifyPaidInmailRefreshReceipt(value) {
|
|
215
|
-
const response = recordValue(value);
|
|
216
|
-
const nestedReceipt = recordValue(response?.receipt);
|
|
217
|
-
const status = stringValue(nestedReceipt?.status) ??
|
|
218
|
-
stringValue(response?.status) ??
|
|
219
|
-
(response?.refreshed === true ? "refreshed" : "not_refreshed");
|
|
220
|
-
const refreshed = response?.refreshed === true || nestedReceipt?.refreshed === true;
|
|
221
|
-
const usableCurrentFacts = refreshed || USABLE_PAID_INMAIL_REFRESH_RECEIPT_STATUSES.has(status);
|
|
222
|
-
return {
|
|
223
|
-
usableCurrentFacts,
|
|
224
|
-
status,
|
|
225
|
-
refreshed,
|
|
226
|
-
error: stringValue(response?.error) ??
|
|
227
|
-
stringValue(nestedReceipt?.error) ??
|
|
228
|
-
(usableCurrentFacts ? null : "paid InMail credit refresh did not return usable current facts"),
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
209
|
export function firstGlobalAction(plan) {
|
|
232
210
|
const root = recordValue(plan);
|
|
233
211
|
const target = recordValue(root?.target);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
type RefillSendsEvergreenInput = {
|
|
2
|
+
workspaceId?: string;
|
|
3
|
+
};
|
|
4
|
+
export declare const refillSendsEvergreenToolDefinitions: {
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: string;
|
|
9
|
+
properties: {
|
|
10
|
+
workspaceId: {
|
|
11
|
+
type: string;
|
|
12
|
+
description: string;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
required: string[];
|
|
16
|
+
additionalProperties: boolean;
|
|
17
|
+
};
|
|
18
|
+
}[];
|
|
19
|
+
export declare function refillSendsEvergreenCommand(input: RefillSendsEvergreenInput): {
|
|
20
|
+
readOnly: boolean;
|
|
21
|
+
workspaceId: string | null;
|
|
22
|
+
firstOperationalSteps: string[];
|
|
23
|
+
approvalContract: string;
|
|
24
|
+
forbiddenActions: string[];
|
|
25
|
+
fillWindow: string;
|
|
26
|
+
hostExamples: string[];
|
|
27
|
+
};
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export const refillSendsEvergreenToolDefinitions = [
|
|
2
|
+
{
|
|
3
|
+
name: "refill_sends_evergreen",
|
|
4
|
+
description: "Read-only Phase 85 evergreen refill command contract. It performs no mutations and only tells the operator to call get_evergreen_refill_plan for a dry-run packet and journal.",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
workspaceId: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Explicit request-scoped workspace id.",
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
required: ["workspaceId"],
|
|
14
|
+
additionalProperties: false,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
export function refillSendsEvergreenCommand(input) {
|
|
19
|
+
return {
|
|
20
|
+
readOnly: true,
|
|
21
|
+
workspaceId: input.workspaceId ?? null,
|
|
22
|
+
firstOperationalSteps: [
|
|
23
|
+
"Call get_evergreen_refill_plan with the explicit workspaceId.",
|
|
24
|
+
"Read the returned packet, globalActionQueue, per-sender plans, and itinerary before taking any action.",
|
|
25
|
+
"Review the dry-run journal file path returned by get_evergreen_refill_plan.",
|
|
26
|
+
"Phase 85 is PLAN-ONLY; execution arrives in Phase 86.",
|
|
27
|
+
],
|
|
28
|
+
approvalContract: "Nothing is approved or executable in Phase 85. The evergreen command is read-only; Phase 86 introduces execution approval.",
|
|
29
|
+
forbiddenActions: [
|
|
30
|
+
"Do not schedule sends.",
|
|
31
|
+
"Do not send messages.",
|
|
32
|
+
"Do not approve messages.",
|
|
33
|
+
"Do not prepare messages.",
|
|
34
|
+
"Do not start or launch campaigns.",
|
|
35
|
+
"Do not create campaigns.",
|
|
36
|
+
"Do not switch providers or source families.",
|
|
37
|
+
"Do not lower paid InMail thresholds.",
|
|
38
|
+
"Do not refresh paid InMail credits.",
|
|
39
|
+
"Do not write scheduler fields.",
|
|
40
|
+
],
|
|
41
|
+
fillWindow: "Use only the target window and caps returned by get_evergreen_refill_plan.",
|
|
42
|
+
hostExamples: [
|
|
43
|
+
"refill_sends_evergreen({ workspaceId })",
|
|
44
|
+
"get_evergreen_refill_plan({ workspaceId })",
|
|
45
|
+
],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -6,6 +6,9 @@ type RefillSendsV2Input = {
|
|
|
6
6
|
approvalMode?: "approve" | "mark_ready";
|
|
7
7
|
senderIds?: string[];
|
|
8
8
|
intent?: "auto" | "evergreen" | "plain" | "active";
|
|
9
|
+
targetDate?: string | null;
|
|
10
|
+
untilDate?: string | null;
|
|
11
|
+
horizonSendDays?: number | null;
|
|
9
12
|
};
|
|
10
13
|
export declare const refillSendsV2ToolDefinitions: {
|
|
11
14
|
name: string;
|
|
@@ -44,6 +47,22 @@ export declare const refillSendsV2ToolDefinitions: {
|
|
|
44
47
|
type: string;
|
|
45
48
|
enum: string[];
|
|
46
49
|
};
|
|
50
|
+
targetDate: {
|
|
51
|
+
type: string;
|
|
52
|
+
pattern: string;
|
|
53
|
+
description: string;
|
|
54
|
+
};
|
|
55
|
+
untilDate: {
|
|
56
|
+
type: string;
|
|
57
|
+
pattern: string;
|
|
58
|
+
description: string;
|
|
59
|
+
};
|
|
60
|
+
horizonSendDays: {
|
|
61
|
+
type: string;
|
|
62
|
+
minimum: number;
|
|
63
|
+
maximum: number;
|
|
64
|
+
description: string;
|
|
65
|
+
};
|
|
47
66
|
};
|
|
48
67
|
required: string[];
|
|
49
68
|
additionalProperties: boolean;
|
|
@@ -18,7 +18,7 @@ const BOUNDED_AUTHORITY = "Within the refill run, bounded approvals, preparation
|
|
|
18
18
|
export const refillSendsV2ToolDefinitions = [
|
|
19
19
|
{
|
|
20
20
|
name: "refill_sends_v2",
|
|
21
|
-
description: "Execute the refill sends v2 loop with run-record fencing, packet re-planning, shared refill executors, and resumable dry-run/real-run modes.",
|
|
21
|
+
description: "Execute the refill sends v2 loop with run-record fencing, packet re-planning, shared refill executors, and resumable dry-run/real-run modes. Date selectors match refill_sends: targetDate is one exact sender-local date, untilDate is inclusive, horizonSendDays is the next N sender-local send days, with precedence targetDate > untilDate > horizonSendDays > default scheduler-forward planning.",
|
|
22
22
|
inputSchema: {
|
|
23
23
|
type: "object",
|
|
24
24
|
properties: {
|
|
@@ -51,6 +51,22 @@ export const refillSendsV2ToolDefinitions = [
|
|
|
51
51
|
type: "string",
|
|
52
52
|
enum: ["auto", "evergreen", "plain", "active"],
|
|
53
53
|
},
|
|
54
|
+
targetDate: {
|
|
55
|
+
type: "string",
|
|
56
|
+
pattern: "^\\d{4}-\\d{2}-\\d{2}$",
|
|
57
|
+
description: "Optional one exact sender-local date (YYYY-MM-DD) to refill.",
|
|
58
|
+
},
|
|
59
|
+
untilDate: {
|
|
60
|
+
type: "string",
|
|
61
|
+
pattern: "^\\d{4}-\\d{2}-\\d{2}$",
|
|
62
|
+
description: "Optional inclusive sender-local through-date (YYYY-MM-DD) to refill.",
|
|
63
|
+
},
|
|
64
|
+
horizonSendDays: {
|
|
65
|
+
type: "number",
|
|
66
|
+
minimum: 1,
|
|
67
|
+
maximum: 7,
|
|
68
|
+
description: "Optional explicit next N sender-local send days to refill.",
|
|
69
|
+
},
|
|
54
70
|
},
|
|
55
71
|
required: ["workspaceId"],
|
|
56
72
|
additionalProperties: false,
|
|
@@ -99,6 +115,9 @@ export async function refillSendsV2Command(input) {
|
|
|
99
115
|
workspaceId,
|
|
100
116
|
intent: input.intent,
|
|
101
117
|
senderIds: input.senderIds,
|
|
118
|
+
targetDate: input.targetDate,
|
|
119
|
+
untilDate: input.untilDate,
|
|
120
|
+
horizonSendDays: input.horizonSendDays,
|
|
102
121
|
journal: true,
|
|
103
122
|
});
|
|
104
123
|
return {
|
|
@@ -113,6 +132,9 @@ export async function refillSendsV2Command(input) {
|
|
|
113
132
|
workspaceId,
|
|
114
133
|
intent: input.intent,
|
|
115
134
|
senderIds: input.senderIds,
|
|
135
|
+
targetDate: input.targetDate,
|
|
136
|
+
untilDate: input.untilDate,
|
|
137
|
+
horizonSendDays: input.horizonSendDays,
|
|
116
138
|
approvalMode: input.approvalMode ?? "approve",
|
|
117
139
|
resume: resumeHandle(input),
|
|
118
140
|
}, {
|
|
@@ -129,6 +151,9 @@ export async function refillSendsV2Command(input) {
|
|
|
129
151
|
workspaceId: planInput.workspaceId,
|
|
130
152
|
intent: planInput.intent,
|
|
131
153
|
senderIds: planInput.senderIds,
|
|
154
|
+
targetDate: planInput.targetDate,
|
|
155
|
+
untilDate: planInput.untilDate,
|
|
156
|
+
horizonSendDays: planInput.horizonSendDays,
|
|
132
157
|
runState: planInput.runState,
|
|
133
158
|
journal: planInput.journal,
|
|
134
159
|
}),
|
|
@@ -153,7 +178,11 @@ export async function refillSendsV2Command(input) {
|
|
|
153
178
|
localState: {
|
|
154
179
|
writeRefillWorkspaceState,
|
|
155
180
|
},
|
|
156
|
-
requestSchedulerRun: (workspaceId) => runSchedulerSweep({
|
|
181
|
+
requestSchedulerRun: (workspaceId, options) => runSchedulerSweep({
|
|
182
|
+
workspaceId,
|
|
183
|
+
action: "run",
|
|
184
|
+
targetDate: options?.targetDate,
|
|
185
|
+
}),
|
|
157
186
|
});
|
|
158
187
|
return {
|
|
159
188
|
...(await maybeAddLostFenceGuidance(result, { ...input, workspaceId })),
|
|
@@ -292,8 +292,6 @@ export declare function executeRefillSendsCommand(input?: RefillSendsCommandInpu
|
|
|
292
292
|
attempts?: number;
|
|
293
293
|
error: string;
|
|
294
294
|
errors?: string[];
|
|
295
|
-
receiptStatus?: string;
|
|
296
|
-
receipt?: unknown;
|
|
297
295
|
}[];
|
|
298
296
|
refreshReceipts: {
|
|
299
297
|
senderId: string;
|
|
@@ -303,8 +301,6 @@ export declare function executeRefillSendsCommand(input?: RefillSendsCommandInpu
|
|
|
303
301
|
approvalSource: string;
|
|
304
302
|
approvalPacket: PaidInmailRefreshApprovalPacket;
|
|
305
303
|
receipt: import("./senders.js").RefreshPaidInmailCreditsResponse;
|
|
306
|
-
receiptStatus: string;
|
|
307
|
-
usableCurrentFacts: boolean;
|
|
308
304
|
}[];
|
|
309
305
|
attemptedSenderIds: string[];
|
|
310
306
|
targetPlanReread: boolean;
|
|
@@ -313,14 +309,6 @@ export declare function executeRefillSendsCommand(input?: RefillSendsCommandInpu
|
|
|
313
309
|
note: string;
|
|
314
310
|
};
|
|
315
311
|
yoloExecution: {
|
|
316
|
-
enabled: false;
|
|
317
|
-
status: "not_run_without_yolo";
|
|
318
|
-
selectedAction: null;
|
|
319
|
-
targetPlanReread: false;
|
|
320
|
-
result?: undefined;
|
|
321
|
-
refusalReason?: undefined;
|
|
322
|
-
postActionFirstAction?: undefined;
|
|
323
|
-
} | {
|
|
324
312
|
enabled: true;
|
|
325
313
|
status: "skipped_after_paid_refresh";
|
|
326
314
|
selectedAction: null;
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import { actionIds,
|
|
1
|
+
import { actionIds, collectPaidInmailRefreshActions, executeOneYoloPrimitive, firstGlobalAction, normalizeStrings, numberValue, recordValue, refreshPaidInmailCreditsWithRetry, stringValue, } from "./refill-executors.js";
|
|
2
2
|
import { getRefillTargetPlan } from "./refill-target-plan.js";
|
|
3
3
|
import { createWorkspaceContext, normalizeExplicitWorkspaceId, } from "./workspace-context.js";
|
|
4
4
|
const DEFAULT_SCHEDULER_FORWARD_HOURS = 48;
|
|
5
5
|
const MCP_PAID_INMAIL_CREDITS_MAX_STALENESS_SECONDS = 4 * 60 * 60;
|
|
6
6
|
function normalizeHorizonSendDays(value) {
|
|
7
|
-
if (value === undefined
|
|
7
|
+
if (value === undefined)
|
|
8
8
|
return null;
|
|
9
|
-
if (typeof value !== "number" ||
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
if (typeof value !== "number" ||
|
|
10
|
+
!Number.isInteger(value) ||
|
|
11
|
+
value < 1 ||
|
|
12
|
+
value > 7) {
|
|
13
|
+
throw new Error("horizonSendDays must be an integer between 1 and 7.");
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
12
16
|
}
|
|
13
17
|
function normalizeUntilDate(value) {
|
|
14
18
|
if (value === undefined || value === null || value === "")
|
|
@@ -91,7 +95,7 @@ export const refillSendsToolDefinitions = [
|
|
|
91
95
|
type: "number",
|
|
92
96
|
minimum: 1,
|
|
93
97
|
maximum: 7,
|
|
94
|
-
description: "Compatibility override for
|
|
98
|
+
description: "Compatibility override for explicit next N sender-local send days. Omit for the default scheduler-forward 48-hour target window.",
|
|
95
99
|
},
|
|
96
100
|
untilDate: {
|
|
97
101
|
type: "string",
|
|
@@ -184,7 +188,7 @@ export function refillSendsCommand(input = {}) {
|
|
|
184
188
|
horizonHours: horizonSendDays === null ? DEFAULT_SCHEDULER_FORWARD_HOURS : null,
|
|
185
189
|
description: horizonSendDays === null
|
|
186
190
|
? "Fill the default scheduler-forward 48-hour target window."
|
|
187
|
-
:
|
|
191
|
+
: `Fill the next ${horizonSendDays} sender-local send days.`,
|
|
188
192
|
},
|
|
189
193
|
approvalMode,
|
|
190
194
|
campaignId: input.campaignId ?? null,
|
|
@@ -231,7 +235,7 @@ export function refillSendsCommand(input = {}) {
|
|
|
231
235
|
"Fresh reread get_campaign_refill_state immediately before any import, prep, approval, or horizon-fill mutation.",
|
|
232
236
|
"Maintain a target-window saturation ledger per selected sender from get_refill_target_plan: selected days, gross capacity, actual sent counts, future scheduler-owned scheduled counts, projected counts, ready-to-schedule buffer, remaining projected gap, paid InMail threshold feasibility, targetShapeRevision, stateRevision, and next MCP primitive.",
|
|
233
237
|
"Source/fallback primitives require receipt-proven exhaustion: existingRowFrontier.hasMoreFrontierRows:false, approvalCandidates:0, no fresh active prep, no stuckActiveCells, and no non-terminal approvedNotDispatched rows. Treat anomalies, stuckActiveCells, and non-terminal approvedNotDispatched as diagnose-and-report gates, not exhaustion. Terminal approvedNotDispatched blockers may be reported and then the ladder can proceed.",
|
|
234
|
-
"In
|
|
238
|
+
"In --yolo, this tool automatically maintains a run-local refreshedPaidInmailSenderIds set: when the first target plan returns refresh_paid_inmail_credits candidates for selected paid-InMail lanes, it refreshes each exact sender at most once, reruns get_refill_target_plan, and returns the post-refresh targetPlan before any prep/source-copy/bounded-approval/read-only wait action is chosen.",
|
|
235
239
|
"Freshness gate precedes scheduler wait: if any selected target.senderRefillPlans[].paidInmail.status is missing_credit_facts or stale_credit_facts, or the target plan contains refresh_paid_inmail_credits, do not enter wait_for_scheduler even when remainingReadyOrProjectedGap is 0; refresh exact sender credit facts once, reread get_refill_target_plan, then choose scheduler wait only if freshness is clean.",
|
|
236
240
|
"Scheduler-run receipt interpretation: cellsConsidered is allocation-attempt count, readyCellsFound is ready inventory before prefilters, and campaignScopeSummary must include the selected campaign/table before inferring it was ready-but-blocked. Read prefiltered, skipped, and deferred separately. For ready closed-InMail cells with stale paid-credit facts, route to refresh_paid_inmail_credits_then_rerun once, then rerun/status. wait_for_capacity_or_window means report loaded/capped/waiting and do not source or prep more rows. no_ready_cells_continue_refill_prep means return to the refill/prep ladder.",
|
|
237
241
|
"For wait_for_active_work and wait_for_scheduler, honor the receipt's absolute wait.deadlineAt when present. If the deadline is expired on this call, escalate to diagnostics with the receipt evidence instead of issuing another blind wait.",
|
|
@@ -375,11 +379,7 @@ export async function executeRefillSendsCommand(input = {}) {
|
|
|
375
379
|
? { ...input, workspaceId: workspaceContext.context.workspaceId }
|
|
376
380
|
: input;
|
|
377
381
|
const command = refillSendsCommand(scopedInput);
|
|
378
|
-
|
|
379
|
-
? workspaceContext.context.workspaceId
|
|
380
|
-
: normalizeExplicitWorkspaceId(scopedInput.workspaceId);
|
|
381
|
-
const canRefreshPaidInmailFacts = yolo || executionMode === "scheduled" || Boolean(workspaceId);
|
|
382
|
-
if (!canRefreshPaidInmailFacts) {
|
|
382
|
+
if (!yolo) {
|
|
383
383
|
return {
|
|
384
384
|
...command,
|
|
385
385
|
autoPaidInmailRefresh: {
|
|
@@ -387,7 +387,7 @@ export async function executeRefillSendsCommand(input = {}) {
|
|
|
387
387
|
status: "not_run_without_yolo",
|
|
388
388
|
refreshedPaidInmailSenderIds: [],
|
|
389
389
|
failedPaidInmailRefreshes: [],
|
|
390
|
-
note: "Automatic paid InMail credit refresh
|
|
390
|
+
note: "Automatic paid InMail credit refresh only runs for --yolo refill_sends calls.",
|
|
391
391
|
},
|
|
392
392
|
yoloExecution: {
|
|
393
393
|
enabled: false,
|
|
@@ -397,6 +397,9 @@ export async function executeRefillSendsCommand(input = {}) {
|
|
|
397
397
|
},
|
|
398
398
|
};
|
|
399
399
|
}
|
|
400
|
+
const workspaceId = workspaceContext && workspaceContext.ok
|
|
401
|
+
? workspaceContext.context.workspaceId
|
|
402
|
+
: normalizeExplicitWorkspaceId(scopedInput.workspaceId);
|
|
400
403
|
const targetPlanInput = targetPlanInputFor(scopedInput);
|
|
401
404
|
const targetPlanBeforePaidRefresh = await getRefillTargetPlan(targetPlanInput);
|
|
402
405
|
const refreshActions = collectPaidInmailRefreshActions(targetPlanBeforePaidRefresh);
|
|
@@ -422,7 +425,7 @@ export async function executeRefillSendsCommand(input = {}) {
|
|
|
422
425
|
}
|
|
423
426
|
const refreshResult = await refreshPaidInmailCreditsWithRetry(action.senderId, workspaceId, paidRefreshOptionsFromApprovalPacket(approvalPacket));
|
|
424
427
|
if (refreshResult.receipt) {
|
|
425
|
-
|
|
428
|
+
refreshedPaidInmailSenderIds.push(action.senderId);
|
|
426
429
|
refreshReceipts.push({
|
|
427
430
|
senderId: action.senderId,
|
|
428
431
|
actionKey: action.actionKey ?? null,
|
|
@@ -431,23 +434,7 @@ export async function executeRefillSendsCommand(input = {}) {
|
|
|
431
434
|
approvalSource: "explicit_yolo_flag",
|
|
432
435
|
approvalPacket,
|
|
433
436
|
receipt: refreshResult.receipt,
|
|
434
|
-
receiptStatus: classification.status,
|
|
435
|
-
usableCurrentFacts: classification.usableCurrentFacts,
|
|
436
437
|
});
|
|
437
|
-
if (classification.usableCurrentFacts) {
|
|
438
|
-
refreshedPaidInmailSenderIds.push(action.senderId);
|
|
439
|
-
}
|
|
440
|
-
else {
|
|
441
|
-
failedPaidInmailRefreshes.push({
|
|
442
|
-
senderId: action.senderId,
|
|
443
|
-
attempts: refreshResult.attempts,
|
|
444
|
-
error: classification.error ??
|
|
445
|
-
"paid InMail credit refresh did not return usable current facts",
|
|
446
|
-
errors: refreshResult.errors,
|
|
447
|
-
receiptStatus: classification.status,
|
|
448
|
-
receipt: refreshResult.receipt,
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
438
|
}
|
|
452
439
|
else {
|
|
453
440
|
failedPaidInmailRefreshes.push({
|
|
@@ -462,8 +449,8 @@ export async function executeRefillSendsCommand(input = {}) {
|
|
|
462
449
|
const targetPlan = refreshActions.length > 0
|
|
463
450
|
? await getRefillTargetPlan(targetPlanInput)
|
|
464
451
|
: targetPlanBeforePaidRefresh;
|
|
465
|
-
const selectedAction =
|
|
466
|
-
const primitiveAttempt =
|
|
452
|
+
const selectedAction = refreshActions.length > 0 ? null : firstGlobalAction(targetPlan);
|
|
453
|
+
const primitiveAttempt = refreshActions.length > 0
|
|
467
454
|
? null
|
|
468
455
|
: await executeOneYoloPrimitive(selectedAction, workspaceId ?? undefined);
|
|
469
456
|
const shouldRereadAfterPrimitive = primitiveAttempt?.status === "executed_and_reread" ||
|
|
@@ -476,9 +463,7 @@ export async function executeRefillSendsCommand(input = {}) {
|
|
|
476
463
|
...command,
|
|
477
464
|
targetPlan: finalTargetPlan,
|
|
478
465
|
targetPlanBeforePaidRefresh: refreshActions.length > 0 ? targetPlanBeforePaidRefresh : null,
|
|
479
|
-
targetPlanBeforeYoloPrimitive:
|
|
480
|
-
? targetPlan
|
|
481
|
-
: null,
|
|
466
|
+
targetPlanBeforeYoloPrimitive: refreshActions.length === 0 && postActionTargetPlan ? targetPlan : null,
|
|
482
467
|
autoPaidInmailRefresh: {
|
|
483
468
|
enabled: true,
|
|
484
469
|
status: refreshActions.length === 0
|
|
@@ -497,30 +482,23 @@ export async function executeRefillSendsCommand(input = {}) {
|
|
|
497
482
|
? "refill_sends refreshed stale paid InMail credit facts internally with bounded retries, once per sender, then returned the post-refresh targetPlan."
|
|
498
483
|
: "No stale or missing paid InMail credit refresh candidates were present in the initial target plan.",
|
|
499
484
|
},
|
|
500
|
-
yoloExecution:
|
|
485
|
+
yoloExecution: refreshActions.length > 0
|
|
501
486
|
? {
|
|
502
|
-
enabled:
|
|
503
|
-
status: "
|
|
487
|
+
enabled: true,
|
|
488
|
+
status: "skipped_after_paid_refresh",
|
|
504
489
|
selectedAction: null,
|
|
505
|
-
targetPlanReread:
|
|
490
|
+
targetPlanReread: true,
|
|
506
491
|
}
|
|
507
|
-
:
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
:
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
result: primitiveAttempt?.result,
|
|
519
|
-
targetPlanReread: shouldRereadAfterPrimitive,
|
|
520
|
-
refusalReason: primitiveAttempt?.refusalReason,
|
|
521
|
-
postActionFirstAction: postActionTargetPlan
|
|
522
|
-
? firstGlobalAction(postActionTargetPlan)
|
|
523
|
-
: null,
|
|
524
|
-
},
|
|
492
|
+
: {
|
|
493
|
+
enabled: true,
|
|
494
|
+
status: primitiveAttempt?.status ?? "no_action",
|
|
495
|
+
selectedAction,
|
|
496
|
+
result: primitiveAttempt?.result,
|
|
497
|
+
targetPlanReread: shouldRereadAfterPrimitive,
|
|
498
|
+
refusalReason: primitiveAttempt?.refusalReason,
|
|
499
|
+
postActionFirstAction: postActionTargetPlan
|
|
500
|
+
? firstGlobalAction(postActionTargetPlan)
|
|
501
|
+
: null,
|
|
502
|
+
},
|
|
525
503
|
};
|
|
526
504
|
}
|
|
@@ -1026,6 +1026,16 @@ function sanitizeRefillTargetPlanResult(result) {
|
|
|
1026
1026
|
mcpSanitizedRefillLanes: true,
|
|
1027
1027
|
};
|
|
1028
1028
|
}
|
|
1029
|
+
function stripInternalTargetDateKeys(value) {
|
|
1030
|
+
if (Array.isArray(value)) {
|
|
1031
|
+
return value.map((item) => stripInternalTargetDateKeys(item));
|
|
1032
|
+
}
|
|
1033
|
+
if (!isRecord(value))
|
|
1034
|
+
return value;
|
|
1035
|
+
return Object.fromEntries(Object.entries(value)
|
|
1036
|
+
.filter(([key]) => key !== "targetDateKey")
|
|
1037
|
+
.map(([key, nested]) => [key, stripInternalTargetDateKeys(nested)]));
|
|
1038
|
+
}
|
|
1029
1039
|
export const refillTargetPlanToolDefinitions = [
|
|
1030
1040
|
{
|
|
1031
1041
|
name: "get_refill_target_plan",
|
|
@@ -1042,7 +1052,7 @@ export const refillTargetPlanToolDefinitions = [
|
|
|
1042
1052
|
type: "number",
|
|
1043
1053
|
minimum: 1,
|
|
1044
1054
|
maximum: 7,
|
|
1045
|
-
description: "Compatibility override for explicit sender-local send
|
|
1055
|
+
description: "Compatibility override for explicit next N sender-local send days. Omit for the default scheduler-forward 48-hour target window; no-send days are skipped while choosing the requested send days.",
|
|
1046
1056
|
},
|
|
1047
1057
|
untilDate: {
|
|
1048
1058
|
type: "string",
|
|
@@ -1052,7 +1062,7 @@ export const refillTargetPlanToolDefinitions = [
|
|
|
1052
1062
|
targetDate: {
|
|
1053
1063
|
type: "string",
|
|
1054
1064
|
pattern: "^\\d{4}-\\d{2}-\\d{2}$",
|
|
1055
|
-
description: "Optional exact sender-local YYYY-MM-DD
|
|
1065
|
+
description: "Optional one exact sender-local date (YYYY-MM-DD) to fill. Distinct from untilDate: targetDate asks how many scheduler-fillable slots exist on only this date.",
|
|
1056
1066
|
},
|
|
1057
1067
|
campaignId: {
|
|
1058
1068
|
type: "string",
|
|
@@ -1102,11 +1112,14 @@ export const refillTargetPlanToolDefinitions = [
|
|
|
1102
1112
|
];
|
|
1103
1113
|
export async function getRefillTargetPlan(input = {}) {
|
|
1104
1114
|
const workspaceId = normalizeExplicitWorkspaceId(input.workspaceId);
|
|
1115
|
+
const targetDate = input.targetDate;
|
|
1116
|
+
const untilDate = targetDate ? undefined : input.untilDate;
|
|
1117
|
+
const horizonSendDays = targetDate || untilDate ? undefined : input.horizonSendDays;
|
|
1105
1118
|
const result = await postRefillTargetPlan({
|
|
1106
1119
|
intent: input.intent,
|
|
1107
|
-
horizonSendDays
|
|
1108
|
-
untilDate
|
|
1109
|
-
targetDate
|
|
1120
|
+
horizonSendDays,
|
|
1121
|
+
untilDate,
|
|
1122
|
+
targetDate,
|
|
1110
1123
|
campaignId: input.campaignId,
|
|
1111
1124
|
tableId: input.tableId,
|
|
1112
1125
|
senderIds: input.senderIds,
|
|
@@ -1117,7 +1130,7 @@ export async function getRefillTargetPlan(input = {}) {
|
|
|
1117
1130
|
paidInmailCreditsMaxStalenessSeconds: MCP_PAID_INMAIL_CREDITS_MAX_STALENESS_SECONDS,
|
|
1118
1131
|
...(workspaceId ? { workspaceId } : {}),
|
|
1119
1132
|
}, workspaceId ?? undefined);
|
|
1120
|
-
const sanitized = sanitizeRefillTargetPlanResult(result);
|
|
1133
|
+
const sanitized = stripInternalTargetDateKeys(sanitizeRefillTargetPlanResult(result));
|
|
1121
1134
|
if (!workspaceId || !isRecord(sanitized))
|
|
1122
1135
|
return sanitized;
|
|
1123
1136
|
return {
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -2758,6 +2758,22 @@ export declare const allTools: ({
|
|
|
2758
2758
|
enum: string[];
|
|
2759
2759
|
description: string;
|
|
2760
2760
|
};
|
|
2761
|
+
targetDate: {
|
|
2762
|
+
type: string;
|
|
2763
|
+
pattern: string;
|
|
2764
|
+
description: string;
|
|
2765
|
+
};
|
|
2766
|
+
untilDate: {
|
|
2767
|
+
type: string;
|
|
2768
|
+
pattern: string;
|
|
2769
|
+
description: string;
|
|
2770
|
+
};
|
|
2771
|
+
horizonSendDays: {
|
|
2772
|
+
type: string;
|
|
2773
|
+
minimum: number;
|
|
2774
|
+
maximum: number;
|
|
2775
|
+
description: string;
|
|
2776
|
+
};
|
|
2761
2777
|
journal: {
|
|
2762
2778
|
type: string;
|
|
2763
2779
|
description: string;
|
|
@@ -7385,6 +7401,10 @@ export declare const allTools: ({
|
|
|
7385
7401
|
enum: string[];
|
|
7386
7402
|
description: string;
|
|
7387
7403
|
};
|
|
7404
|
+
targetDate: {
|
|
7405
|
+
type: string;
|
|
7406
|
+
description: string;
|
|
7407
|
+
};
|
|
7388
7408
|
};
|
|
7389
7409
|
required: string[];
|
|
7390
7410
|
additionalProperties: boolean;
|
|
@@ -7426,6 +7446,22 @@ export declare const allTools: ({
|
|
|
7426
7446
|
type: string;
|
|
7427
7447
|
enum: string[];
|
|
7428
7448
|
};
|
|
7449
|
+
targetDate: {
|
|
7450
|
+
type: string;
|
|
7451
|
+
pattern: string;
|
|
7452
|
+
description: string;
|
|
7453
|
+
};
|
|
7454
|
+
untilDate: {
|
|
7455
|
+
type: string;
|
|
7456
|
+
pattern: string;
|
|
7457
|
+
description: string;
|
|
7458
|
+
};
|
|
7459
|
+
horizonSendDays: {
|
|
7460
|
+
type: string;
|
|
7461
|
+
minimum: number;
|
|
7462
|
+
maximum: number;
|
|
7463
|
+
description: string;
|
|
7464
|
+
};
|
|
7429
7465
|
};
|
|
7430
7466
|
required: string[];
|
|
7431
7467
|
additionalProperties: boolean;
|