@sellable/mcp 0.1.511 → 0.1.513
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/api.js +15 -12
- package/dist/refill-journal.d.ts +49 -0
- package/dist/refill-journal.js +134 -0
- package/dist/refill-local-state.d.ts +31 -0
- package/dist/refill-local-state.js +96 -0
- package/dist/server.js +13 -3
- package/dist/tools/evergreen-refill-plan.d.ts +69 -0
- package/dist/tools/evergreen-refill-plan.js +273 -0
- package/dist/tools/leads.d.ts +40 -0
- package/dist/tools/leads.js +86 -31
- package/dist/tools/prompts.d.ts +4 -3
- package/dist/tools/prompts.js +7 -1
- 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 +28 -0
- package/dist/tools/refill-sends-v2.js +49 -0
- package/dist/tools/registry.d.ts +46 -106
- package/dist/tools/registry.js +6 -2
- package/package.json +1 -1
- package/skills/refill-sends-evergreen/SKILL.md +19 -0
- package/skills/refill-sends-evergreen-workflow/SKILL.md +20 -0
- package/skills/refill-sends-evergreen-workflow/core/flow.v1.json +247 -0
- package/skills/refill-sends-v2/SKILL.md +96 -0
- package/skills/refill-sends-v2-workflow/SKILL.md +127 -0
- package/skills/refill-sends-v2-workflow/core/flow.v1.json +266 -0
package/dist/api.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { getConfig, getConfigPath } from "./auth.js";
|
|
2
1
|
import { createWriteStream } from "node:fs";
|
|
3
2
|
import { mkdir, rename, rm, stat } from "node:fs/promises";
|
|
4
3
|
import path from "node:path";
|
|
5
4
|
import { Readable } from "node:stream";
|
|
6
5
|
import { pipeline } from "node:stream/promises";
|
|
6
|
+
import { getConfig, getConfigPath } from "./auth.js";
|
|
7
7
|
export class SellableApiError extends Error {
|
|
8
8
|
status;
|
|
9
9
|
body;
|
|
@@ -21,18 +21,21 @@ export class SellableApiError extends Error {
|
|
|
21
21
|
export class SellableApi {
|
|
22
22
|
buildError(status, errorText) {
|
|
23
23
|
const isAuthError = status === 401 || status === 403;
|
|
24
|
+
const isWorkspaceMembershipError = status === 403 && errorText.includes("No access to workspace");
|
|
24
25
|
const missingWorkspace = status === 400 && errorText.includes("Workspace");
|
|
25
|
-
const guidance =
|
|
26
|
-
? "
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
const guidance = isWorkspaceMembershipError
|
|
27
|
+
? "The authenticated user is not a member of this workspace. Confirm the workspaceId or ask a workspace admin to add the user; re-login will not help."
|
|
28
|
+
: isAuthError
|
|
29
|
+
? "Sellable authentication failed.\n\n" +
|
|
30
|
+
"Run the first-run Sellable login flow from a Sellable workflow, then retry.\n\n" +
|
|
31
|
+
"If the browser login page shows a manual fallback command, use:\n" +
|
|
32
|
+
"sellable auth set <token> --workspace-id <workspace_id>\n\n" +
|
|
33
|
+
`Current config path: ${getConfigPath()}\n\n` +
|
|
34
|
+
"Older copied Settings tokens can be stale, restricted, or missing write/credit permissions. Sign in again so Sellable mints the current agent token."
|
|
35
|
+
: missingWorkspace
|
|
36
|
+
? "No active workspace selected.\n\n" +
|
|
37
|
+
"Run list_workspaces then set_active_workspace to choose a workspace."
|
|
38
|
+
: undefined;
|
|
36
39
|
return new SellableApiError(status, errorText, guidance);
|
|
37
40
|
}
|
|
38
41
|
async requestResponse(method, path, body, options) {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export declare const DRY_RUN_MARKER = "**DRY RUN \u2014 no mutations performed**";
|
|
2
|
+
export declare const JOURNAL_SECTION_HEADINGS: {
|
|
3
|
+
readonly bootstrap: "## Bootstrap";
|
|
4
|
+
readonly plan: "## Plan";
|
|
5
|
+
readonly terminal: "## Terminal";
|
|
6
|
+
};
|
|
7
|
+
export declare function resolveRefillRunsRoot(): string;
|
|
8
|
+
/**
|
|
9
|
+
* Throws on path-safety and permission failures. Callers must wrap the entire
|
|
10
|
+
* journal block and degrade to journalPath: null; journal failure must never
|
|
11
|
+
* abort a plan response.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createRunJournal(params: {
|
|
14
|
+
workspaceId: string;
|
|
15
|
+
runId?: string;
|
|
16
|
+
dryRun: boolean;
|
|
17
|
+
now?: Date;
|
|
18
|
+
}): {
|
|
19
|
+
filePath: string;
|
|
20
|
+
runId: string;
|
|
21
|
+
};
|
|
22
|
+
export declare function appendJournalEvent(filePath: string, block: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* The index is a rebuildable cache. Directory listing is the source of truth;
|
|
25
|
+
* Phase 85 appends dry-run lines, Phase 86 maintains real-run entries.
|
|
26
|
+
*/
|
|
27
|
+
export declare function appendIndexLine(entry: {
|
|
28
|
+
runId: string;
|
|
29
|
+
fileName: string;
|
|
30
|
+
workspaceId: string;
|
|
31
|
+
dryRun: boolean;
|
|
32
|
+
summary: string;
|
|
33
|
+
}): void;
|
|
34
|
+
export declare function renderBootstrapSection(params: {
|
|
35
|
+
summary: string;
|
|
36
|
+
senderSummary?: string;
|
|
37
|
+
laneSummary?: string;
|
|
38
|
+
targetSummary?: string;
|
|
39
|
+
creditSummary?: string;
|
|
40
|
+
}): string;
|
|
41
|
+
export declare function renderPlanSection(params: {
|
|
42
|
+
chosenSummary: string;
|
|
43
|
+
itinerarySummaries?: string[];
|
|
44
|
+
fallbackSummary?: string;
|
|
45
|
+
}): string;
|
|
46
|
+
export declare function renderTerminalSection(params: {
|
|
47
|
+
summary: string;
|
|
48
|
+
finalNumbers?: string;
|
|
49
|
+
}): string;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
const REFILL_RUNS_ROOT_ENV = "SELLABLE_REFILL_RUNS_DIR";
|
|
6
|
+
export const DRY_RUN_MARKER = "**DRY RUN — no mutations performed**";
|
|
7
|
+
export const JOURNAL_SECTION_HEADINGS = {
|
|
8
|
+
bootstrap: "## Bootstrap",
|
|
9
|
+
plan: "## Plan",
|
|
10
|
+
terminal: "## Terminal",
|
|
11
|
+
};
|
|
12
|
+
function expandLeadingTilde(value) {
|
|
13
|
+
if (value === "~")
|
|
14
|
+
return os.homedir();
|
|
15
|
+
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
16
|
+
return path.join(os.homedir(), value.slice(2));
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
function normalizeConfiguredRoot(value, label) {
|
|
21
|
+
const expanded = expandLeadingTilde(value);
|
|
22
|
+
if (!path.isAbsolute(expanded)) {
|
|
23
|
+
throw new Error(`${label} must be an absolute path.`);
|
|
24
|
+
}
|
|
25
|
+
return path.resolve(expanded);
|
|
26
|
+
}
|
|
27
|
+
export function resolveRefillRunsRoot() {
|
|
28
|
+
const envValue = process.env[REFILL_RUNS_ROOT_ENV]?.trim();
|
|
29
|
+
if (envValue) {
|
|
30
|
+
return normalizeConfiguredRoot(envValue, REFILL_RUNS_ROOT_ENV);
|
|
31
|
+
}
|
|
32
|
+
const home = os.homedir();
|
|
33
|
+
if (!home || !path.isAbsolute(home)) {
|
|
34
|
+
throw new Error(`Unable to resolve Sellable refill runs root: ${REFILL_RUNS_ROOT_ENV} is unset and home directory is unavailable.`);
|
|
35
|
+
}
|
|
36
|
+
return path.resolve(home, ".sellable/refill/runs");
|
|
37
|
+
}
|
|
38
|
+
function isPathInside(candidate, root) {
|
|
39
|
+
const relative = path.relative(root, candidate);
|
|
40
|
+
return (Boolean(relative) &&
|
|
41
|
+
!relative.startsWith("..") &&
|
|
42
|
+
!path.isAbsolute(relative));
|
|
43
|
+
}
|
|
44
|
+
function assertSafeRunId(runId) {
|
|
45
|
+
if (!/^[A-Za-z0-9_-]+$/.test(runId) ||
|
|
46
|
+
runId.includes("..") ||
|
|
47
|
+
runId.includes("/") ||
|
|
48
|
+
runId.includes("\\") ||
|
|
49
|
+
runId.includes("\0")) {
|
|
50
|
+
throw new Error("runId must be a safe filename segment.");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function utcBasicTimestamp(now) {
|
|
54
|
+
return `${now.toISOString().slice(0, 19).replace(/[-:]/g, "")}Z`;
|
|
55
|
+
}
|
|
56
|
+
function normalizeBlock(block) {
|
|
57
|
+
return block.endsWith("\n") ? block : `${block}\n`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Throws on path-safety and permission failures. Callers must wrap the entire
|
|
61
|
+
* journal block and degrade to journalPath: null; journal failure must never
|
|
62
|
+
* abort a plan response.
|
|
63
|
+
*/
|
|
64
|
+
export function createRunJournal(params) {
|
|
65
|
+
const runId = params.runId ?? randomBytes(4).toString("hex");
|
|
66
|
+
assertSafeRunId(runId);
|
|
67
|
+
const root = resolveRefillRunsRoot();
|
|
68
|
+
fs.mkdirSync(root, { recursive: true });
|
|
69
|
+
const normalizedRoot = path.resolve(root);
|
|
70
|
+
const fileName = `${utcBasicTimestamp(params.now ?? new Date())}-${runId}${params.dryRun ? "-dry" : ""}.md`;
|
|
71
|
+
const filePath = path.resolve(normalizedRoot, fileName);
|
|
72
|
+
if (!isPathInside(filePath, normalizedRoot)) {
|
|
73
|
+
throw new Error("Resolved journal path escapes refill runs root.");
|
|
74
|
+
}
|
|
75
|
+
const startedAt = (params.now ?? new Date()).toISOString();
|
|
76
|
+
const header = [
|
|
77
|
+
`# Refill Sends V2 Run ${runId}`,
|
|
78
|
+
"",
|
|
79
|
+
`- Run ID: ${runId}`,
|
|
80
|
+
`- Workspace ID: ${params.workspaceId}`,
|
|
81
|
+
`- Started at: ${startedAt}`,
|
|
82
|
+
params.dryRun ? `- ${DRY_RUN_MARKER}` : null,
|
|
83
|
+
"",
|
|
84
|
+
]
|
|
85
|
+
.filter((line) => line !== null)
|
|
86
|
+
.join("\n");
|
|
87
|
+
fs.appendFileSync(filePath, normalizeBlock(header), "utf8");
|
|
88
|
+
return { filePath, runId };
|
|
89
|
+
}
|
|
90
|
+
export function appendJournalEvent(filePath, block) {
|
|
91
|
+
try {
|
|
92
|
+
fs.appendFileSync(filePath, normalizeBlock(block), "utf8");
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Best effort by design.
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The index is a rebuildable cache. Directory listing is the source of truth;
|
|
100
|
+
* Phase 85 appends dry-run lines, Phase 86 maintains real-run entries.
|
|
101
|
+
*/
|
|
102
|
+
export function appendIndexLine(entry) {
|
|
103
|
+
try {
|
|
104
|
+
const root = resolveRefillRunsRoot();
|
|
105
|
+
fs.mkdirSync(root, { recursive: true });
|
|
106
|
+
const marker = entry.dryRun ? " (dry)" : "";
|
|
107
|
+
fs.appendFileSync(path.join(root, "index.md"), `- ${entry.runId}${marker} [${entry.workspaceId}] ${entry.fileName} — ${entry.summary}\n`, "utf8");
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Best effort by design.
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function renderLines(heading, lines) {
|
|
114
|
+
return normalizeBlock([heading, "", ...lines, ""].join("\n"));
|
|
115
|
+
}
|
|
116
|
+
export function renderBootstrapSection(params) {
|
|
117
|
+
return renderLines(JOURNAL_SECTION_HEADINGS.bootstrap, [
|
|
118
|
+
params.summary,
|
|
119
|
+
params.senderSummary,
|
|
120
|
+
params.laneSummary,
|
|
121
|
+
params.targetSummary,
|
|
122
|
+
params.creditSummary,
|
|
123
|
+
].filter((line) => Boolean(line)));
|
|
124
|
+
}
|
|
125
|
+
export function renderPlanSection(params) {
|
|
126
|
+
return renderLines(JOURNAL_SECTION_HEADINGS.plan, [
|
|
127
|
+
`Chosen: ${params.chosenSummary}`,
|
|
128
|
+
...(params.itinerarySummaries ?? []).map((summary) => `Next: ${summary}`),
|
|
129
|
+
params.fallbackSummary ? `Fallback: ${params.fallbackSummary}` : null,
|
|
130
|
+
].filter((line) => Boolean(line)));
|
|
131
|
+
}
|
|
132
|
+
export function renderTerminalSection(params) {
|
|
133
|
+
return renderLines(JOURNAL_SECTION_HEADINGS.terminal, [params.summary, params.finalNumbers].filter((line) => Boolean(line)));
|
|
134
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface RefillLaneMemoryEntry {
|
|
2
|
+
senderId: string;
|
|
3
|
+
laneKey: string;
|
|
4
|
+
outcome: string;
|
|
5
|
+
cooldownUntil: string;
|
|
6
|
+
reason: string;
|
|
7
|
+
}
|
|
8
|
+
export interface RefillPassRateObservation {
|
|
9
|
+
campaignId: string;
|
|
10
|
+
enrichedCount: number;
|
|
11
|
+
passedCount: number;
|
|
12
|
+
observedAt: string;
|
|
13
|
+
}
|
|
14
|
+
export interface RefillRunSummaryEntry {
|
|
15
|
+
runId: string;
|
|
16
|
+
endedAt: string;
|
|
17
|
+
terminalState: string;
|
|
18
|
+
sendsLoaded: number;
|
|
19
|
+
lanesTouched: string[];
|
|
20
|
+
}
|
|
21
|
+
export interface RefillWorkspaceState {
|
|
22
|
+
laneMemory: RefillLaneMemoryEntry[];
|
|
23
|
+
passRates: RefillPassRateObservation[];
|
|
24
|
+
recentRuns: RefillRunSummaryEntry[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Advisory hints only. A missing, stale, corrupt, or malformed file means no
|
|
28
|
+
* hints; live planner reads remain the source of correctness. Phase 85 reads
|
|
29
|
+
* this section only. Phase 86 adds the writer plus writeJsonAtomic.
|
|
30
|
+
*/
|
|
31
|
+
export declare function readRefillWorkspaceState(workspaceId: string): RefillWorkspaceState | null;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { getConfig } from "./auth.js";
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
function isStringArray(value) {
|
|
6
|
+
return (Array.isArray(value) && value.every((entry) => typeof entry === "string"));
|
|
7
|
+
}
|
|
8
|
+
function readString(record, key) {
|
|
9
|
+
const value = record[key];
|
|
10
|
+
return typeof value === "string" ? value : null;
|
|
11
|
+
}
|
|
12
|
+
function readNumber(record, key) {
|
|
13
|
+
const value = record[key];
|
|
14
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
15
|
+
}
|
|
16
|
+
function parseLaneMemoryEntry(value) {
|
|
17
|
+
if (!isRecord(value))
|
|
18
|
+
return null;
|
|
19
|
+
const senderId = readString(value, "senderId");
|
|
20
|
+
const laneKey = readString(value, "laneKey");
|
|
21
|
+
const outcome = readString(value, "outcome");
|
|
22
|
+
const cooldownUntil = readString(value, "cooldownUntil");
|
|
23
|
+
const reason = readString(value, "reason");
|
|
24
|
+
if (!senderId || !laneKey || !outcome || !cooldownUntil || !reason) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return { senderId, laneKey, outcome, cooldownUntil, reason };
|
|
28
|
+
}
|
|
29
|
+
function parsePassRateObservation(value) {
|
|
30
|
+
if (!isRecord(value))
|
|
31
|
+
return null;
|
|
32
|
+
const campaignId = readString(value, "campaignId");
|
|
33
|
+
const enrichedCount = readNumber(value, "enrichedCount");
|
|
34
|
+
const passedCount = readNumber(value, "passedCount");
|
|
35
|
+
const observedAt = readString(value, "observedAt");
|
|
36
|
+
if (!campaignId ||
|
|
37
|
+
enrichedCount === null ||
|
|
38
|
+
passedCount === null ||
|
|
39
|
+
!observedAt) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return { campaignId, enrichedCount, passedCount, observedAt };
|
|
43
|
+
}
|
|
44
|
+
function parseRunSummaryEntry(value) {
|
|
45
|
+
if (!isRecord(value))
|
|
46
|
+
return null;
|
|
47
|
+
const runId = readString(value, "runId");
|
|
48
|
+
const endedAt = readString(value, "endedAt");
|
|
49
|
+
const terminalState = readString(value, "terminalState");
|
|
50
|
+
const sendsLoaded = readNumber(value, "sendsLoaded");
|
|
51
|
+
const lanesTouched = value.lanesTouched;
|
|
52
|
+
if (!runId ||
|
|
53
|
+
!endedAt ||
|
|
54
|
+
!terminalState ||
|
|
55
|
+
sendsLoaded === null ||
|
|
56
|
+
!isStringArray(lanesTouched)) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
return { runId, endedAt, terminalState, sendsLoaded, lanesTouched };
|
|
60
|
+
}
|
|
61
|
+
function parseArray(value, parser) {
|
|
62
|
+
if (!Array.isArray(value))
|
|
63
|
+
return [];
|
|
64
|
+
return value.flatMap((entry) => {
|
|
65
|
+
const parsed = parser(entry);
|
|
66
|
+
return parsed ? [parsed] : [];
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Advisory hints only. A missing, stale, corrupt, or malformed file means no
|
|
71
|
+
* hints; live planner reads remain the source of correctness. Phase 85 reads
|
|
72
|
+
* this section only. Phase 86 adds the writer plus writeJsonAtomic.
|
|
73
|
+
*/
|
|
74
|
+
export function readRefillWorkspaceState(workspaceId) {
|
|
75
|
+
try {
|
|
76
|
+
const config = getConfig();
|
|
77
|
+
const refill = config.skillState
|
|
78
|
+
?.refill;
|
|
79
|
+
if (!isRecord(refill) || refill.version !== 1)
|
|
80
|
+
return null;
|
|
81
|
+
const byWorkspace = refill.byWorkspace;
|
|
82
|
+
if (!isRecord(byWorkspace))
|
|
83
|
+
return null;
|
|
84
|
+
const workspaceState = byWorkspace[workspaceId];
|
|
85
|
+
if (!isRecord(workspaceState))
|
|
86
|
+
return null;
|
|
87
|
+
return {
|
|
88
|
+
laneMemory: parseArray(workspaceState.laneMemory, parseLaneMemoryEntry),
|
|
89
|
+
passRates: parseArray(workspaceState.passRates, parsePassRateObservation),
|
|
90
|
+
recentRuns: parseArray(workspaceState.recentRuns, parseRunSummaryEntry),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
package/dist/server.js
CHANGED
|
@@ -9,10 +9,8 @@ import { prepareCampaignAbTest } from "./tools/campaign-ab-test.js";
|
|
|
9
9
|
import { resolveCampaignFillRoute } from "./tools/campaign-fill-routing.js";
|
|
10
10
|
import { fillCampaignHorizon } from "./tools/campaign-horizon-fill.js";
|
|
11
11
|
import { cancelPrepareCampaignMessages, getPrepareCampaignMessagesStatus, startPrepareCampaignMessages, } from "./tools/campaign-message-preparation.js";
|
|
12
|
-
import { getCampaignRefillState } from "./tools/campaign-refill-state.js";
|
|
13
|
-
import { getRefillTargetPlan } from "./tools/refill-target-plan.js";
|
|
14
|
-
import { getSchedulerFillCapacity } from "./tools/scheduler-fill-capacity.js";
|
|
15
12
|
import { getCampaignTableSchema, queueCampaignCells, recordCampaignReviewBatch, reviseMessageTemplateAndRerun, selectCampaignCells, waitForCampaignProcessing, } from "./tools/campaign-processing.js";
|
|
13
|
+
import { getCampaignRefillState } from "./tools/campaign-refill-state.js";
|
|
16
14
|
import { archiveCampaign, createCampaign, duplicateCampaign, getCampaign, getCampaignMessagesPreview, getCampaigns, pauseCampaign, startCampaign, updateCampaign, updateCampaignBrief, } from "./tools/campaigns.js";
|
|
17
15
|
import { queueCells, updateCell } from "./tools/cells.js";
|
|
18
16
|
import { handleStartCliLogin, handleWaitForCliLogin, } from "./tools/cli-login.js";
|
|
@@ -29,6 +27,7 @@ import { searchEngagementPosts } from "./tools/engage-discovery.js";
|
|
|
29
27
|
import { copySenderConfigTool, getEngageMemoryTool, migrateFlatConfigsTool, recordEngageProvenSearchTool, setEngageStyleGuideTool, upsertEngageTrackedPersonTool, } from "./tools/engage-memory.js";
|
|
30
28
|
import { getEngageStateTool, setEngageStateTool, } from "./tools/engage-state.js";
|
|
31
29
|
import { bulkEnrichWithProspeo, enrichWithProspeo, getProspeoCredits, } from "./tools/enrichment.js";
|
|
30
|
+
import { getRefillPlanV2 } from "./tools/evergreen-refill-plan.js";
|
|
32
31
|
import { getCampaignFramework } from "./tools/framework.js";
|
|
33
32
|
import { confirmHarvestJobCompanies, searchHarvestJobs, } from "./tools/harvest-jobs.js";
|
|
34
33
|
import { checkInboxReplyEligibility, getInboxThread, searchInboxThreads, sendInboxDraft, sendInboxManualReply, updateInboxDraft, } from "./tools/inbox.js";
|
|
@@ -39,10 +38,13 @@ import { addOnDemandLeads, createOnDemandCampaign, createOnDemandTable, initOnDe
|
|
|
39
38
|
import { upsertRubric } from "./tools/processing.js";
|
|
40
39
|
import { completeSenderResearch, getPostFindLeadsScoutRegistry, getSourceScoutRegistry, getSubskillAsset, getSubskillPrompt, listSubskillPrompts, searchSubskillPrompts, } from "./tools/prompts.js";
|
|
41
40
|
import { waitForCampaignTableReady, waitForLeadListReady, } from "./tools/readiness.js";
|
|
41
|
+
import { refillSendsV2Command } from "./tools/refill-sends-v2.js";
|
|
42
42
|
import { executeRefillSendsCommand } from "./tools/refill-sends.js";
|
|
43
|
+
import { getRefillTargetPlan } from "./tools/refill-target-plan.js";
|
|
43
44
|
import { allTools } from "./tools/registry.js";
|
|
44
45
|
import { getRows, getTableRows, getTableRowsMinimal } from "./tools/rows.js";
|
|
45
46
|
import { addRubricItem, checkRubric, deleteRubricItem, draftRubrics, saveRubrics, selectNecessaryRubrics, updateRubricItem, waitForRubricResults, } from "./tools/rubrics.js";
|
|
47
|
+
import { getSchedulerFillCapacity } from "./tools/scheduler-fill-capacity.js";
|
|
46
48
|
import { getSenderRoutingTool, setSenderRoutingTool, } from "./tools/sender-routing.js";
|
|
47
49
|
import { getSender, listSenders, refreshPaidInmailCredits, } from "./tools/senders.js";
|
|
48
50
|
import { attachRecommendedSequence, attachSequence, createWorkflowTable, } from "./tools/sequencer.js";
|
|
@@ -223,6 +225,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
223
225
|
case "get_campaign_refill_state":
|
|
224
226
|
result = await getCampaignRefillState(args);
|
|
225
227
|
break;
|
|
228
|
+
case "get_refill_plan_v2":
|
|
229
|
+
case "get_evergreen_refill_plan":
|
|
230
|
+
result = await getRefillPlanV2(args);
|
|
231
|
+
break;
|
|
226
232
|
case "get_refill_target_plan":
|
|
227
233
|
result = await getRefillTargetPlan(args);
|
|
228
234
|
break;
|
|
@@ -232,6 +238,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
232
238
|
case "refill_sends":
|
|
233
239
|
result = await executeRefillSendsCommand(args);
|
|
234
240
|
break;
|
|
241
|
+
case "refill_sends_v2":
|
|
242
|
+
case "refill_sends_evergreen":
|
|
243
|
+
result = refillSendsV2Command(args);
|
|
244
|
+
break;
|
|
235
245
|
case "setup_evergreen_campaigns":
|
|
236
246
|
result = await setupEvergreenCampaigns(args);
|
|
237
247
|
markEvergreenSetupCampaignsDirty(args);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
type GetRefillPlanV2Input = {
|
|
2
|
+
workspaceId?: string;
|
|
3
|
+
intent?: "auto" | "evergreen" | "plain" | "active";
|
|
4
|
+
senderIds?: string[];
|
|
5
|
+
runState?: Record<string, unknown>;
|
|
6
|
+
journal?: boolean;
|
|
7
|
+
journalNote?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function sanitizeEvergreenRefillPlanResult(value: unknown): Record<string, unknown>;
|
|
10
|
+
export declare const refillPlanV2ToolDefinitions: {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
inputSchema: {
|
|
14
|
+
type: string;
|
|
15
|
+
properties: {
|
|
16
|
+
workspaceId: {
|
|
17
|
+
type: string;
|
|
18
|
+
description: string;
|
|
19
|
+
};
|
|
20
|
+
senderIds: {
|
|
21
|
+
type: string;
|
|
22
|
+
items: {
|
|
23
|
+
type: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
runState: {
|
|
27
|
+
type: string;
|
|
28
|
+
description: string;
|
|
29
|
+
};
|
|
30
|
+
intent: {
|
|
31
|
+
type: string;
|
|
32
|
+
enum: string[];
|
|
33
|
+
description: string;
|
|
34
|
+
};
|
|
35
|
+
journal: {
|
|
36
|
+
type: string;
|
|
37
|
+
description: string;
|
|
38
|
+
};
|
|
39
|
+
journalNote: {
|
|
40
|
+
type: string;
|
|
41
|
+
description: string;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
required: string[];
|
|
45
|
+
additionalProperties: boolean;
|
|
46
|
+
};
|
|
47
|
+
}[];
|
|
48
|
+
export declare function getRefillPlanV2(input: GetRefillPlanV2Input): Promise<{
|
|
49
|
+
readOnly: boolean;
|
|
50
|
+
blocker: string;
|
|
51
|
+
workspaceId: string;
|
|
52
|
+
guidance: string;
|
|
53
|
+
warnings: string[];
|
|
54
|
+
journalPath: string | null;
|
|
55
|
+
text: string;
|
|
56
|
+
workspaceResolution: string;
|
|
57
|
+
} | {
|
|
58
|
+
warnings: any[];
|
|
59
|
+
journalPath: string | null;
|
|
60
|
+
text: string;
|
|
61
|
+
workspaceId: string;
|
|
62
|
+
workspaceResolution: string;
|
|
63
|
+
readOnly?: undefined;
|
|
64
|
+
blocker?: undefined;
|
|
65
|
+
guidance?: undefined;
|
|
66
|
+
}>;
|
|
67
|
+
/** @deprecated Use getRefillPlanV2. */
|
|
68
|
+
export declare const getEvergreenRefillPlan: typeof getRefillPlanV2;
|
|
69
|
+
export {};
|