@sellable/mcp 0.1.540 → 0.1.542
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 +2 -5
- package/dist/index-dev.js +0 -0
- package/dist/index.js +0 -0
- package/dist/refill-run-loop.d.ts +1 -9
- package/dist/refill-run-loop.js +91 -156
- package/dist/server.js +5 -1
- package/dist/tools/campaigns.d.ts +50 -1
- package/dist/tools/campaigns.js +6 -2
- package/dist/tools/evergreen-refill-plan.d.ts +0 -19
- package/dist/tools/evergreen-refill-plan.js +0 -19
- package/dist/tools/refill-executors.d.ts +7 -0
- package/dist/tools/refill-executors.js +23 -1
- package/dist/tools/refill-sends-v2.d.ts +0 -19
- package/dist/tools/refill-sends-v2.js +2 -31
- package/dist/tools/refill-sends.d.ts +12 -0
- package/dist/tools/refill-sends.js +58 -36
- package/dist/tools/refill-target-plan.js +6 -19
- package/dist/tools/refresh-sender-engagement.d.ts +50 -0
- package/dist/tools/refresh-sender-engagement.js +60 -0
- package/dist/tools/registry.d.ts +88 -32
- package/dist/tools/registry.js +2 -0
- package/dist/tools/scheduler-fill-capacity.js +1 -1
- package/dist/tools/scheduler-run.d.ts +1 -1
- package/dist/tools/scheduler-run.js +17 -20
- package/dist/tools/senders.d.ts +14 -8
- package/dist/tools/senders.js +21 -10
- package/package.json +1 -1
- package/skills/refill-sends/SKILL.md +1 -9
- package/skills/refill-sends-v2/SKILL.md +5 -18
- package/skills/refill-sends-v2-workflow/SKILL.md +2 -16
- package/skills/refill-sends-v2-workflow/core/flow.v1.json +3 -19
- package/skills/refill-sends-workflow/SKILL.md +3 -5
- package/skills/refill-sends-workflow/core/flow.v1.json +1 -1
- package/skills/refresh-sender-engagement/SKILL.md +25 -29
- package/dist/refill-date-window.d.ts +0 -34
- package/dist/refill-date-window.js +0 -210
- package/dist/tools/refill-sends-evergreen.d.ts +0 -28
- package/dist/tools/refill-sends-evergreen.js +0 -47
- package/skills/research/config.json +0 -9
|
@@ -19,10 +19,9 @@ allowed-tools:
|
|
|
19
19
|
- mcp__sellable__get_campaign_table_schema
|
|
20
20
|
- mcp__sellable__list_tables
|
|
21
21
|
- mcp__sellable__get_rows_minimal
|
|
22
|
+
- mcp__sellable__refresh_sender_engagement
|
|
22
23
|
- mcp__sellable__fetch_linkedin_posts
|
|
23
|
-
- mcp__sellable__select_promising_posts
|
|
24
24
|
- mcp__sellable__fetch_post_engagers
|
|
25
|
-
- mcp__sellable__add_on_demand_leads
|
|
26
25
|
---
|
|
27
26
|
|
|
28
27
|
# Refresh Sender Engagement
|
|
@@ -34,7 +33,7 @@ You are a pipeline supply agent. People who engage with a sender's LinkedIn post
|
|
|
34
33
|
<inputs>
|
|
35
34
|
The invoking prompt names the senders ("refresh sender engagement for csreyes92 and thomas"). Resolve each via `list_senders` (match name/handle/LinkedIn URL). With no names given, inspect the active workspace and refresh every connected sender that has an active/paused sender-owned Post Engagers campaign backed by Signal Discovery.
|
|
36
35
|
|
|
37
|
-
Optional:
|
|
36
|
+
Optional: target sender names/ids, `tableId` when the user wants to force a specific campaign table, maximum posts per sender (default 5, hard cap 5 unless the user explicitly asks for more), and maximum engager pages per tracked post.
|
|
38
37
|
</inputs>
|
|
39
38
|
|
|
40
39
|
<entrypoint>
|
|
@@ -53,39 +52,36 @@ suggest `refill-sends`.
|
|
|
53
52
|
<objective>
|
|
54
53
|
For each target sender/campaign:
|
|
55
54
|
|
|
56
|
-
1. **
|
|
55
|
+
1. **Authenticate and resolve workspace**:
|
|
57
56
|
- Call `get_auth_status` and confirm the active workspace.
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
|
|
61
|
-
-
|
|
62
|
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
|
|
71
|
-
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
6. **
|
|
77
|
-
- Use `add_on_demand_leads({ tableId, leads, skipDuplicates: true })` with name, headline-derived title, profile URL, and source/post context where the tool accepts it.
|
|
78
|
-
- Dedupe is mandatory. Never disable dedupe on a scheduled run.
|
|
79
|
-
- Do not generate, approve, schedule, or send messages.
|
|
80
|
-
7. **Report**: campaigns inspected, target campaigns selected, posts scanned, engagers found, ICP-passing, net-new added per sender/campaign. If a sender posted nothing in the window, say "no recent posts — nothing to refresh" (that is a truthful no-op, not a failure).
|
|
57
|
+
- If there is no active workspace or auth is missing, stop with the MCP guidance. Do not use local env files or repo scripts as a substitute for MCP auth.
|
|
58
|
+
- Resolve each target sender with `list_senders`/`get_sender`. Use the sender id returned by the product, not a guessed handle.
|
|
59
|
+
2. **Use the typed product command first**:
|
|
60
|
+
- Call `refresh_sender_engagement` in `mode:"dry_run"` for each sender.
|
|
61
|
+
- Always pass `workspaceId`, `senderId`, and any user-specified `tableId`, `maxPosts`, or `maxEngagerPages`.
|
|
62
|
+
- Treat the dry-run response as the campaign/source boundary authority. It should identify the sender-owned Post Engagers slot, campaign, workflow table, source provider `campaign-tracked-post`, source table type `tracked_post_engager_source_list`, expected tracked posts, expected engager refresh/import work, and a `dryRunFingerprint`.
|
|
63
|
+
- If the typed command reports no eligible sender-owned Post Engagers campaign, no tracked posts, no recent posts, or a workspace/sender mismatch, report that exact blocker and stop for that sender. Do not silently create campaigns or fall back to shared lanes.
|
|
64
|
+
3. **Gate writes with dry-run proof**:
|
|
65
|
+
- Never call `refresh_sender_engagement` in `mode:"apply"` before a successful dry run from this same run.
|
|
66
|
+
- For manual runs, show the target workspace, sender, campaign/table, source lead list, expected tracked posts, expected row/import impact, and `dryRunFingerprint`, then wait for explicit user approval before apply.
|
|
67
|
+
- For scheduled automations where the user has already authorized refreshes, apply is allowed only with the exact `dryRunFingerprint` from the immediately preceding dry run.
|
|
68
|
+
- If apply rejects the fingerprint as stale or mismatched, rerun dry-run and ask for approval again for manual runs.
|
|
69
|
+
4. **Apply through the typed command only**:
|
|
70
|
+
- Call `refresh_sender_engagement({ mode:"apply", workspaceId, senderId, tableId?, maxPosts?, maxEngagerPages?, dryRunFingerprint })`.
|
|
71
|
+
- The apply path must materialize/refresh tracked posts, import deduped tracked-post engagers into the campaign table, and preserve product idempotency. Do not use `add_on_demand_leads` or raw table row writes for the same operation.
|
|
72
|
+
5. **Read-only fallback is diagnostic only**:
|
|
73
|
+
- If the typed command is unavailable, use `get_subskill_prompt`/`search_subskill_prompts` and stop with `blocked: missing_refresh_sender_engagement_tool`.
|
|
74
|
+
- `fetch_linkedin_posts` and `fetch_post_engagers` may be used only to explain source availability or diagnose provider issues. They are not an alternate write path.
|
|
75
|
+
6. **Report**: campaigns inspected, target campaign/table, tracked posts materialized/refreshed, engagers scanned, ICP-passing/importable, net-new rows imported, duplicates skipped, and any no-op reason per sender/campaign. If a sender posted nothing in the window, say "no recent posts — nothing to refresh" (that is a truthful no-op, not a failure).
|
|
81
76
|
</objective>
|
|
82
77
|
|
|
83
78
|
<safety>
|
|
84
|
-
- LinkedIn operations here are read-only fetches plus
|
|
79
|
+
- LinkedIn operations here are read-only fetches plus a typed product import into a campaign table. **No messages are generated, approved, scheduled, or sent by this skill.**
|
|
85
80
|
- Respect workspace boundaries: only add leads to campaigns in the active workspace, and only for senders that belong to it.
|
|
86
81
|
- Respect campaign boundaries: only add engagers to the matched sender-owned Post Engagers campaign/table. Do not mix shared-lane engagers into sender-owned campaigns or sender-owned engagers into shared lanes.
|
|
87
82
|
- Cap provider usage per run: at most 5 posts × `fetch_post_engagers` per sender. If the invoking automation wants more, it must say so explicitly.
|
|
88
|
-
- Never call `start_campaign`, `attach_sequence`, `queue_campaign_cells`, `start_campaign_message_preparation`, approval tools,
|
|
83
|
+
- Never call `start_campaign`, `attach_sequence`, `queue_campaign_cells`, `start_campaign_message_preparation`, approval tools, send/schedule tools, or shared-lane mutation tools.
|
|
84
|
+
- Never create campaigns, change campaign status, change sender ownership, approve campaign cells, or start message prep as part of this refresh.
|
|
89
85
|
</safety>
|
|
90
86
|
|
|
91
87
|
<output>
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export type RefillDateWindowSource = "default_scheduler_forward" | "horizon_send_days" | "until_date" | "target_date";
|
|
2
|
-
export type NormalizedRefillDateSelector = {
|
|
3
|
-
source: RefillDateWindowSource;
|
|
4
|
-
targetDate: string | null;
|
|
5
|
-
untilDate: string | null;
|
|
6
|
-
horizonSendDays: number | null;
|
|
7
|
-
};
|
|
8
|
-
export type RefillRunDateWindow = NormalizedRefillDateSelector & {
|
|
9
|
-
version: 1;
|
|
10
|
-
selectedDates: string[];
|
|
11
|
-
senderWindows?: Array<{
|
|
12
|
-
senderId: string | null;
|
|
13
|
-
timeZone: string | null;
|
|
14
|
-
selectedDates: string[];
|
|
15
|
-
}>;
|
|
16
|
-
};
|
|
17
|
-
type DateSelectorInput = {
|
|
18
|
-
targetDate?: unknown;
|
|
19
|
-
untilDate?: unknown;
|
|
20
|
-
horizonSendDays?: unknown;
|
|
21
|
-
};
|
|
22
|
-
export declare function normalizeRefillDateSelector(input: DateSelectorInput): NormalizedRefillDateSelector;
|
|
23
|
-
export declare function refillDateSelectorBody(selector: NormalizedRefillDateSelector): {
|
|
24
|
-
targetDate?: string;
|
|
25
|
-
untilDate?: string;
|
|
26
|
-
horizonSendDays?: number;
|
|
27
|
-
};
|
|
28
|
-
export declare function dateWindowFromSelector(selector: NormalizedRefillDateSelector): RefillRunDateWindow;
|
|
29
|
-
export declare function dateWindowFromPlan(plan: Record<string, unknown>, selector: NormalizedRefillDateSelector): RefillRunDateWindow;
|
|
30
|
-
export declare function dateWindowFromRunState(runState: unknown): RefillRunDateWindow | null;
|
|
31
|
-
export declare function selectorFromDateWindow(window: RefillRunDateWindow): NormalizedRefillDateSelector;
|
|
32
|
-
export declare function dateSelectorMatchesWindow(selector: NormalizedRefillDateSelector, window: RefillRunDateWindow): boolean;
|
|
33
|
-
export declare function schedulerSweepTargetDates(window: RefillRunDateWindow): string[];
|
|
34
|
-
export {};
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
function isRecord(value) {
|
|
2
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3
|
-
}
|
|
4
|
-
function stringValue(value) {
|
|
5
|
-
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
6
|
-
}
|
|
7
|
-
function numberValue(value) {
|
|
8
|
-
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
9
|
-
}
|
|
10
|
-
function arrayValue(value) {
|
|
11
|
-
return Array.isArray(value) ? value : [];
|
|
12
|
-
}
|
|
13
|
-
function isValidDateKey(value) {
|
|
14
|
-
if (!/^\d{4}-\d{2}-\d{2}$/.test(value))
|
|
15
|
-
return false;
|
|
16
|
-
const [year, month, day] = value.split("-").map(Number);
|
|
17
|
-
const date = new Date(Date.UTC(year, month - 1, day));
|
|
18
|
-
return (date.getUTCFullYear() === year &&
|
|
19
|
-
date.getUTCMonth() === month - 1 &&
|
|
20
|
-
date.getUTCDate() === day);
|
|
21
|
-
}
|
|
22
|
-
function normalizeDateKey(value, field) {
|
|
23
|
-
if (value === undefined || value === null || value === "")
|
|
24
|
-
return null;
|
|
25
|
-
if (typeof value !== "string") {
|
|
26
|
-
throw new Error(`${field} must be a string in YYYY-MM-DD format.`);
|
|
27
|
-
}
|
|
28
|
-
const trimmed = value.trim();
|
|
29
|
-
if (!isValidDateKey(trimmed)) {
|
|
30
|
-
throw new Error(`${field} must be a valid YYYY-MM-DD calendar date.`);
|
|
31
|
-
}
|
|
32
|
-
return trimmed;
|
|
33
|
-
}
|
|
34
|
-
function normalizeHorizonSendDays(value) {
|
|
35
|
-
if (value === undefined)
|
|
36
|
-
return null;
|
|
37
|
-
if (typeof value !== "number" ||
|
|
38
|
-
!Number.isInteger(value) ||
|
|
39
|
-
value < 1 ||
|
|
40
|
-
value > 7) {
|
|
41
|
-
throw new Error("horizonSendDays must be an integer between 1 and 7.");
|
|
42
|
-
}
|
|
43
|
-
return value;
|
|
44
|
-
}
|
|
45
|
-
export function normalizeRefillDateSelector(input) {
|
|
46
|
-
const targetDate = normalizeDateKey(input.targetDate, "targetDate");
|
|
47
|
-
const untilDate = normalizeDateKey(input.untilDate, "untilDate");
|
|
48
|
-
const horizonSendDays = normalizeHorizonSendDays(input.horizonSendDays);
|
|
49
|
-
if (targetDate) {
|
|
50
|
-
return {
|
|
51
|
-
source: "target_date",
|
|
52
|
-
targetDate,
|
|
53
|
-
untilDate: null,
|
|
54
|
-
horizonSendDays: null,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
if (untilDate) {
|
|
58
|
-
return {
|
|
59
|
-
source: "until_date",
|
|
60
|
-
targetDate: null,
|
|
61
|
-
untilDate,
|
|
62
|
-
horizonSendDays: null,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
if (horizonSendDays !== null) {
|
|
66
|
-
return {
|
|
67
|
-
source: "horizon_send_days",
|
|
68
|
-
targetDate: null,
|
|
69
|
-
untilDate: null,
|
|
70
|
-
horizonSendDays,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
return {
|
|
74
|
-
source: "default_scheduler_forward",
|
|
75
|
-
targetDate: null,
|
|
76
|
-
untilDate: null,
|
|
77
|
-
horizonSendDays: null,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
export function refillDateSelectorBody(selector) {
|
|
81
|
-
if (selector.source === "target_date" && selector.targetDate) {
|
|
82
|
-
return { targetDate: selector.targetDate };
|
|
83
|
-
}
|
|
84
|
-
if (selector.source === "until_date" && selector.untilDate) {
|
|
85
|
-
return { untilDate: selector.untilDate };
|
|
86
|
-
}
|
|
87
|
-
if (selector.source === "horizon_send_days" &&
|
|
88
|
-
selector.horizonSendDays !== null) {
|
|
89
|
-
return { horizonSendDays: selector.horizonSendDays };
|
|
90
|
-
}
|
|
91
|
-
return {};
|
|
92
|
-
}
|
|
93
|
-
export function dateWindowFromSelector(selector) {
|
|
94
|
-
return {
|
|
95
|
-
version: 1,
|
|
96
|
-
...selector,
|
|
97
|
-
selectedDates: selector.targetDate ? [selector.targetDate] : [],
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
function selectedDatesFromPlan(plan) {
|
|
101
|
-
const packet = isRecord(plan.packet) ? plan.packet : {};
|
|
102
|
-
const target = isRecord(packet.target) ? packet.target : {};
|
|
103
|
-
const window = isRecord(target.window) ? target.window : {};
|
|
104
|
-
const senderWindows = arrayValue(window.senderWindows).filter(isRecord);
|
|
105
|
-
const fromWindows = senderWindows.flatMap((senderWindow) => arrayValue(senderWindow.selectedDates)
|
|
106
|
-
.map((entry) => stringValue(entry))
|
|
107
|
-
.filter((entry) => Boolean(entry)));
|
|
108
|
-
if (fromWindows.length > 0)
|
|
109
|
-
return Array.from(new Set(fromWindows)).sort();
|
|
110
|
-
const senderRefillPlans = arrayValue(target.senderRefillPlans).filter(isRecord);
|
|
111
|
-
return Array.from(new Set(senderRefillPlans.flatMap((senderPlan) => {
|
|
112
|
-
const horizon = isRecord(senderPlan.horizon) ? senderPlan.horizon : {};
|
|
113
|
-
return arrayValue(horizon.selectedDays)
|
|
114
|
-
.filter(isRecord)
|
|
115
|
-
.map((day) => stringValue(day.date))
|
|
116
|
-
.filter((entry) => Boolean(entry));
|
|
117
|
-
}))).sort();
|
|
118
|
-
}
|
|
119
|
-
function senderWindowsFromPlan(plan) {
|
|
120
|
-
const packet = isRecord(plan.packet) ? plan.packet : {};
|
|
121
|
-
const target = isRecord(packet.target) ? packet.target : {};
|
|
122
|
-
const window = isRecord(target.window) ? target.window : {};
|
|
123
|
-
return arrayValue(window.senderWindows)
|
|
124
|
-
.filter(isRecord)
|
|
125
|
-
.map((senderWindow) => ({
|
|
126
|
-
senderId: stringValue(senderWindow.senderId),
|
|
127
|
-
timeZone: stringValue(senderWindow.timeZone),
|
|
128
|
-
selectedDates: arrayValue(senderWindow.selectedDates)
|
|
129
|
-
.map((entry) => stringValue(entry))
|
|
130
|
-
.filter((entry) => Boolean(entry)),
|
|
131
|
-
}));
|
|
132
|
-
}
|
|
133
|
-
export function dateWindowFromPlan(plan, selector) {
|
|
134
|
-
const packet = isRecord(plan.packet) ? plan.packet : {};
|
|
135
|
-
const request = isRecord(packet.request) ? packet.request : {};
|
|
136
|
-
const targetDate = stringValue(request.targetDate) ?? selector.targetDate ?? null;
|
|
137
|
-
const untilDate = stringValue(request.untilDate) ?? selector.untilDate ?? null;
|
|
138
|
-
const horizonSendDays = numberValue(request.horizonSendDays) ?? selector.horizonSendDays ?? null;
|
|
139
|
-
const source = targetDate
|
|
140
|
-
? "target_date"
|
|
141
|
-
: untilDate
|
|
142
|
-
? "until_date"
|
|
143
|
-
: horizonSendDays !== null
|
|
144
|
-
? "horizon_send_days"
|
|
145
|
-
: selector.source;
|
|
146
|
-
const selectedDates = selectedDatesFromPlan(plan);
|
|
147
|
-
return {
|
|
148
|
-
version: 1,
|
|
149
|
-
source,
|
|
150
|
-
targetDate: source === "target_date" ? targetDate : null,
|
|
151
|
-
untilDate: source === "until_date" ? untilDate : null,
|
|
152
|
-
horizonSendDays: source === "horizon_send_days" ? horizonSendDays : null,
|
|
153
|
-
selectedDates: selectedDates.length > 0
|
|
154
|
-
? selectedDates
|
|
155
|
-
: targetDate
|
|
156
|
-
? [targetDate]
|
|
157
|
-
: [],
|
|
158
|
-
senderWindows: senderWindowsFromPlan(plan),
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
export function dateWindowFromRunState(runState) {
|
|
162
|
-
const state = isRecord(runState) ? runState : {};
|
|
163
|
-
const raw = isRecord(state.dateWindow) ? state.dateWindow : null;
|
|
164
|
-
if (!raw || raw.version !== 1)
|
|
165
|
-
return null;
|
|
166
|
-
const source = raw.source === "target_date" ||
|
|
167
|
-
raw.source === "until_date" ||
|
|
168
|
-
raw.source === "horizon_send_days" ||
|
|
169
|
-
raw.source === "default_scheduler_forward"
|
|
170
|
-
? raw.source
|
|
171
|
-
: null;
|
|
172
|
-
if (!source)
|
|
173
|
-
return null;
|
|
174
|
-
return {
|
|
175
|
-
version: 1,
|
|
176
|
-
source,
|
|
177
|
-
targetDate: source === "target_date" ? stringValue(raw.targetDate) : null,
|
|
178
|
-
untilDate: source === "until_date" ? stringValue(raw.untilDate) : null,
|
|
179
|
-
horizonSendDays: source === "horizon_send_days"
|
|
180
|
-
? numberValue(raw.horizonSendDays)
|
|
181
|
-
: null,
|
|
182
|
-
selectedDates: arrayValue(raw.selectedDates)
|
|
183
|
-
.map((entry) => stringValue(entry))
|
|
184
|
-
.filter((entry) => Boolean(entry)),
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
export function selectorFromDateWindow(window) {
|
|
188
|
-
return {
|
|
189
|
-
source: window.source,
|
|
190
|
-
targetDate: window.targetDate,
|
|
191
|
-
untilDate: window.untilDate,
|
|
192
|
-
horizonSendDays: window.horizonSendDays,
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
export function dateSelectorMatchesWindow(selector, window) {
|
|
196
|
-
return (selector.source === window.source &&
|
|
197
|
-
selector.targetDate === window.targetDate &&
|
|
198
|
-
selector.untilDate === window.untilDate &&
|
|
199
|
-
selector.horizonSendDays === window.horizonSendDays);
|
|
200
|
-
}
|
|
201
|
-
export function schedulerSweepTargetDates(window) {
|
|
202
|
-
if (window.source === "target_date" && window.targetDate) {
|
|
203
|
-
return [window.targetDate];
|
|
204
|
-
}
|
|
205
|
-
if (window.source === "until_date" ||
|
|
206
|
-
window.source === "horizon_send_days") {
|
|
207
|
-
return window.selectedDates;
|
|
208
|
-
}
|
|
209
|
-
return [];
|
|
210
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
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 {};
|
|
@@ -1,47 +0,0 @@
|
|
|
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
|
-
}
|