@sellable/mcp 0.1.539 → 0.1.541
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 +90 -151
- package/dist/server.js +1 -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/registry.d.ts +49 -32
- 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/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/README.md
CHANGED
|
@@ -74,12 +74,9 @@ sending from:
|
|
|
74
74
|
|
|
75
75
|
The refill-sends public command wrapper plans and executes approval-gated send
|
|
76
76
|
refills. It supports `--yolo` and optional sender selectors such as
|
|
77
|
-
`--sender "Christian Reyes"`,
|
|
78
|
-
`--target-date 2026-06-30`, optional through-date selectors such as
|
|
77
|
+
`--sender "Christian Reyes"`, optional through-date selectors such as
|
|
79
78
|
`--until 2026-06-30`, or typed MCP calls to `refill_sends({ yolo, senders,
|
|
80
|
-
|
|
81
|
-
`targetDate > untilDate > horizonSendDays`, where `targetDate` means one exact
|
|
82
|
-
sender-local date and `untilDate` means an inclusive through-date, from:
|
|
79
|
+
untilDate })` from:
|
|
83
80
|
|
|
84
81
|
- `mcp/sellable/skills/refill-sends/SKILL.md`
|
|
85
82
|
|
package/dist/index-dev.js
CHANGED
|
File without changes
|
package/dist/index.js
CHANGED
|
File without changes
|
|
@@ -13,9 +13,6 @@ export interface RefillV2LoopInput {
|
|
|
13
13
|
};
|
|
14
14
|
approvalMode?: "approve" | "mark_ready";
|
|
15
15
|
dryRun?: boolean;
|
|
16
|
-
targetDate?: string | null;
|
|
17
|
-
untilDate?: string | null;
|
|
18
|
-
horizonSendDays?: number | null;
|
|
19
16
|
}
|
|
20
17
|
export interface RefillV2LoopBudgets {
|
|
21
18
|
maxGateCyclesPerInvocation: number;
|
|
@@ -63,9 +60,6 @@ export interface RefillV2LoopDeps {
|
|
|
63
60
|
intent?: string;
|
|
64
61
|
senderIds?: string[];
|
|
65
62
|
runState?: Record<string, unknown>;
|
|
66
|
-
targetDate?: string;
|
|
67
|
-
untilDate?: string;
|
|
68
|
-
horizonSendDays?: number;
|
|
69
63
|
journal?: boolean;
|
|
70
64
|
}) => Promise<Record<string, unknown>>;
|
|
71
65
|
executors: RefillV2Executors;
|
|
@@ -74,9 +68,7 @@ export interface RefillV2LoopDeps {
|
|
|
74
68
|
budgets?: Partial<RefillV2LoopBudgets>;
|
|
75
69
|
now?: () => Date;
|
|
76
70
|
sleep?: (ms: number) => Promise<void>;
|
|
77
|
-
requestSchedulerRun?: (workspaceId: string
|
|
78
|
-
targetDate?: string;
|
|
79
|
-
}) => Promise<unknown>;
|
|
71
|
+
requestSchedulerRun?: (workspaceId: string) => Promise<unknown>;
|
|
80
72
|
}
|
|
81
73
|
export type RefillV2LoopResult = {
|
|
82
74
|
status: "dry_run";
|
package/dist/refill-run-loop.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { SellableApiError } from "./api.js";
|
|
2
|
-
import { dateSelectorMatchesWindow, dateWindowFromPlan, dateWindowFromRunState, dateWindowFromSelector, normalizeRefillDateSelector, refillDateSelectorBody, schedulerSweepTargetDates, selectorFromDateWindow, } from "./refill-date-window.js";
|
|
3
2
|
import { buildRunStateFromLocalHints } from "./tools/evergreen-refill-plan.js";
|
|
4
|
-
import { prepareRowSelectorValue as defaultPrepareRowSelectorValue, refillPrepareRequestHash as defaultRefillPrepareRequestHash, } from "./tools/refill-executors.js";
|
|
3
|
+
import { classifyPaidInmailRefreshReceipt, prepareRowSelectorValue as defaultPrepareRowSelectorValue, refillPrepareRequestHash as defaultRefillPrepareRequestHash, } from "./tools/refill-executors.js";
|
|
5
4
|
const DEFAULT_BUDGETS = {
|
|
6
5
|
maxGateCyclesPerInvocation: 8,
|
|
7
6
|
pollIntervalMs: 15_000,
|
|
@@ -380,16 +379,9 @@ function firstAction(plan) {
|
|
|
380
379
|
}
|
|
381
380
|
function doneReasonFromPlan(plan) {
|
|
382
381
|
const action = firstAction(plan);
|
|
383
|
-
const packet = recordValue(plan.packet) ?? {};
|
|
384
|
-
const status = stringValue(plan.status) ?? stringValue(packet.status);
|
|
385
382
|
return (stringValue(action?.doneReason) ??
|
|
386
|
-
stringValue(packet
|
|
387
|
-
stringValue(plan.doneReason)
|
|
388
|
-
(status === "complete" ? "complete" : null) ??
|
|
389
|
-
(status === "awaiting_scheduler_after_ready_buffer"
|
|
390
|
-
? "loaded_awaiting_scheduler"
|
|
391
|
-
: null) ??
|
|
392
|
-
(status === "blocked" ? "blocked" : null));
|
|
383
|
+
stringValue(recordValue(plan.packet)?.doneReason) ??
|
|
384
|
+
stringValue(plan.doneReason));
|
|
393
385
|
}
|
|
394
386
|
function selectedLaneAuthority(plan, action) {
|
|
395
387
|
const senderId = actionSenderId(action);
|
|
@@ -425,41 +417,6 @@ function mergeRunState(current, updates) {
|
|
|
425
417
|
...updates,
|
|
426
418
|
};
|
|
427
419
|
}
|
|
428
|
-
function dateSelectorFromInput(input) {
|
|
429
|
-
return normalizeRefillDateSelector({
|
|
430
|
-
targetDate: input.targetDate,
|
|
431
|
-
untilDate: input.untilDate,
|
|
432
|
-
horizonSendDays: input.horizonSendDays,
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
function runStateWithDateWindow(runState, dateWindow) {
|
|
436
|
-
return mergeRunState(runState, { dateWindow });
|
|
437
|
-
}
|
|
438
|
-
function readPlanRequest(input) {
|
|
439
|
-
return {
|
|
440
|
-
workspaceId: input.workspaceId,
|
|
441
|
-
intent: input.intent,
|
|
442
|
-
senderIds: input.senderIds,
|
|
443
|
-
runState: input.runState,
|
|
444
|
-
journal: input.journal,
|
|
445
|
-
...refillDateSelectorBody(input.dateSelector),
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
async function readLoopPlan(input, deps, ctx, journal) {
|
|
449
|
-
return deps.readPlan(readPlanRequest({
|
|
450
|
-
workspaceId: input.workspaceId,
|
|
451
|
-
intent: input.intent,
|
|
452
|
-
senderIds: input.senderIds,
|
|
453
|
-
runState: ctx.runState,
|
|
454
|
-
journal,
|
|
455
|
-
dateSelector: ctx.dateSelector,
|
|
456
|
-
}));
|
|
457
|
-
}
|
|
458
|
-
function applyPlanDateWindow(ctx, plan) {
|
|
459
|
-
ctx.dateWindow = dateWindowFromPlan(plan, ctx.dateSelector);
|
|
460
|
-
ctx.dateSelector = selectorFromDateWindow(ctx.dateWindow);
|
|
461
|
-
ctx.runState = runStateWithDateWindow(ctx.runState, ctx.dateWindow);
|
|
462
|
-
}
|
|
463
420
|
function normalizeDoneReason(value) {
|
|
464
421
|
const raw = stringValue(value);
|
|
465
422
|
if (!raw)
|
|
@@ -642,6 +599,10 @@ function getPlanLine(plan) {
|
|
|
642
599
|
};
|
|
643
600
|
}
|
|
644
601
|
function packetCoherenceFailure(plan) {
|
|
602
|
+
const fingerprint = fingerprintFromPlan(plan);
|
|
603
|
+
if (!fingerprint.planRevision || !fingerprint.targetShapeRevision) {
|
|
604
|
+
return "missing_fingerprint";
|
|
605
|
+
}
|
|
645
606
|
const action = firstAction(plan);
|
|
646
607
|
const doneReason = doneReasonFromPlan(plan);
|
|
647
608
|
if (doneReason && action && action.type !== "done") {
|
|
@@ -649,10 +610,6 @@ function packetCoherenceFailure(plan) {
|
|
|
649
610
|
}
|
|
650
611
|
if (!action)
|
|
651
612
|
return null;
|
|
652
|
-
const fingerprint = fingerprintFromPlan(plan);
|
|
653
|
-
if (!fingerprint.planRevision || !fingerprint.targetShapeRevision) {
|
|
654
|
-
return "missing_fingerprint";
|
|
655
|
-
}
|
|
656
613
|
const toolInput = actionToolInput(action);
|
|
657
614
|
const type = stringValue(action.type);
|
|
658
615
|
if (type === "prepare_messages" &&
|
|
@@ -713,63 +670,14 @@ async function createJournal(input, deps, runId) {
|
|
|
713
670
|
return null;
|
|
714
671
|
}
|
|
715
672
|
}
|
|
716
|
-
async function
|
|
717
|
-
const
|
|
718
|
-
if (!input.resume) {
|
|
719
|
-
return { ok: true, selector: requestedSelector, window: requestedWindow };
|
|
720
|
-
}
|
|
721
|
-
const status = await deps.runClient.refillRunStatus({
|
|
722
|
-
workspaceId: input.workspaceId,
|
|
723
|
-
runId: input.resume.runId,
|
|
724
|
-
});
|
|
725
|
-
if (hasBlocker(status, "lease_lost")) {
|
|
726
|
-
return {
|
|
727
|
-
status: "blocked",
|
|
728
|
-
blocker: "lease_lost",
|
|
729
|
-
runId: input.resume.runId,
|
|
730
|
-
fence: input.resume.fence,
|
|
731
|
-
guidance: "Refill run lease was lost before resume date-window preflight.",
|
|
732
|
-
};
|
|
733
|
-
}
|
|
734
|
-
const storedWindow = dateWindowFromRunState(recordValue(status)?.runState);
|
|
735
|
-
const explicitSelector = requestedSelector.source !== "default_scheduler_forward";
|
|
736
|
-
if (!storedWindow) {
|
|
737
|
-
if (explicitSelector) {
|
|
738
|
-
return {
|
|
739
|
-
status: "blocked",
|
|
740
|
-
blocker: "date_window_conflict",
|
|
741
|
-
runId: input.resume.runId,
|
|
742
|
-
fence: input.resume.fence,
|
|
743
|
-
guidance: "This legacy refill_sends_v2 run has no stored date window. Resume it without a new date selector or start a new run.",
|
|
744
|
-
report: { requestedDateWindow: requestedWindow },
|
|
745
|
-
};
|
|
746
|
-
}
|
|
747
|
-
return { ok: true, selector: requestedSelector, window: requestedWindow };
|
|
748
|
-
}
|
|
749
|
-
if (explicitSelector && !dateSelectorMatchesWindow(requestedSelector, storedWindow)) {
|
|
750
|
-
return {
|
|
751
|
-
status: "blocked",
|
|
752
|
-
blocker: "date_window_conflict",
|
|
753
|
-
runId: input.resume.runId,
|
|
754
|
-
fence: input.resume.fence,
|
|
755
|
-
guidance: "Resume date selector conflicts with the stored refill run date window.",
|
|
756
|
-
report: { requestedDateWindow: requestedWindow, storedDateWindow: storedWindow },
|
|
757
|
-
};
|
|
758
|
-
}
|
|
759
|
-
const selector = explicitSelector
|
|
760
|
-
? requestedSelector
|
|
761
|
-
: selectorFromDateWindow(storedWindow);
|
|
762
|
-
return { ok: true, selector, window: storedWindow };
|
|
763
|
-
}
|
|
764
|
-
async function startOrResume(input, deps, dateWindow) {
|
|
765
|
-
const initialRunState = runStateWithDateWindow(buildRunStateFromLocalHints(input.workspaceId), dateWindow);
|
|
673
|
+
async function startOrResume(input, deps) {
|
|
674
|
+
const initialRunState = buildRunStateFromLocalHints(input.workspaceId);
|
|
766
675
|
const started = await deps.runClient.startRefillRunRemote({
|
|
767
676
|
workspaceId: input.workspaceId,
|
|
768
677
|
config: {
|
|
769
678
|
intent: input.intent ?? "auto",
|
|
770
679
|
senderIds: input.senderIds,
|
|
771
680
|
approvalMode: input.approvalMode ?? "approve",
|
|
772
|
-
dateWindow,
|
|
773
681
|
},
|
|
774
682
|
runState: initialRunState,
|
|
775
683
|
resume: input.resume,
|
|
@@ -811,8 +719,6 @@ async function startOrResume(input, deps, dateWindow) {
|
|
|
811
719
|
laneCooldowns: [],
|
|
812
720
|
passRates: [],
|
|
813
721
|
};
|
|
814
|
-
const storedDateWindow = dateWindowFromRunState(runState) ?? dateWindow;
|
|
815
|
-
const storedDateSelector = selectorFromDateWindow(storedDateWindow);
|
|
816
722
|
const journalPath = await createJournal(input, deps, runId);
|
|
817
723
|
const ctx = {
|
|
818
724
|
workspaceId: input.workspaceId,
|
|
@@ -825,8 +731,6 @@ async function startOrResume(input, deps, dateWindow) {
|
|
|
825
731
|
plan: null,
|
|
826
732
|
headAction: null,
|
|
827
733
|
lastFingerprint: null,
|
|
828
|
-
dateSelector: storedDateSelector,
|
|
829
|
-
dateWindow: storedDateWindow,
|
|
830
734
|
recoveryPoint: recordValue(result.recoveryPoint),
|
|
831
735
|
gateCycles: 0,
|
|
832
736
|
sleptMs: 0,
|
|
@@ -845,31 +749,45 @@ async function startOrResume(input, deps, dateWindow) {
|
|
|
845
749
|
return ctx;
|
|
846
750
|
}
|
|
847
751
|
async function gateBootstrap(input, deps, ctx) {
|
|
848
|
-
const plan = await
|
|
849
|
-
|
|
752
|
+
const plan = await deps.readPlan({
|
|
753
|
+
workspaceId: input.workspaceId,
|
|
754
|
+
intent: input.intent,
|
|
755
|
+
senderIds: input.senderIds,
|
|
756
|
+
runState: ctx.runState,
|
|
757
|
+
journal: false,
|
|
758
|
+
});
|
|
850
759
|
const paidCredit = arrayValue(recordValue(plan.bootstrap)?.paidCredit).filter(isRecord);
|
|
851
760
|
const refreshedSenderIds = new Set(arrayValue(recordValue(ctx.runState.creditTrust)?.senderIds)
|
|
852
761
|
.map((entry) => stringValue(entry))
|
|
853
762
|
.filter((entry) => Boolean(entry)));
|
|
763
|
+
const attemptedSenderIds = new Set(arrayValue(recordValue(ctx.runState.creditTrust)?.attemptedSenderIds)
|
|
764
|
+
.map((entry) => stringValue(entry))
|
|
765
|
+
.filter((entry) => Boolean(entry)));
|
|
854
766
|
const receipts = [];
|
|
855
767
|
for (const entry of paidCredit) {
|
|
856
768
|
const senderId = stringValue(entry.senderId);
|
|
857
769
|
if (!senderId ||
|
|
858
770
|
!entry.plannedJitRefresh ||
|
|
859
|
-
refreshedSenderIds.has(senderId)
|
|
771
|
+
refreshedSenderIds.has(senderId) ||
|
|
772
|
+
attemptedSenderIds.has(senderId)) {
|
|
860
773
|
continue;
|
|
861
774
|
}
|
|
862
775
|
const receipt = await deps.executors.refreshPaidInmailCreditsWithRetry(senderId, input.workspaceId);
|
|
863
|
-
|
|
864
|
-
|
|
776
|
+
attemptedSenderIds.add(senderId);
|
|
777
|
+
const classification = classifyPaidInmailRefreshReceipt(receipt.receipt);
|
|
778
|
+
receipts.push({ senderId, receipt, classification });
|
|
779
|
+
if (classification.usableCurrentFacts) {
|
|
780
|
+
refreshedSenderIds.add(senderId);
|
|
781
|
+
}
|
|
865
782
|
}
|
|
866
|
-
const nextRunState =
|
|
783
|
+
const nextRunState = mergeRunState(ctx.runState, {
|
|
867
784
|
creditTrust: {
|
|
868
785
|
refreshedAt: (deps.now?.() ?? new Date()).toISOString(),
|
|
869
786
|
senderIds: [...refreshedSenderIds],
|
|
787
|
+
attemptedSenderIds: [...attemptedSenderIds],
|
|
870
788
|
receipts,
|
|
871
789
|
},
|
|
872
|
-
})
|
|
790
|
+
});
|
|
873
791
|
await safeJournalAppend(ctx, deps, deps.journal.renderBootstrapSection({
|
|
874
792
|
summary: "Refill v2 execution bootstrap",
|
|
875
793
|
senderSummary: safeJson(recordValue(plan.bootstrap)?.senders ?? []),
|
|
@@ -977,8 +895,13 @@ async function completeTerminal(input, deps, ctx, doneReasonInput, reportInput =
|
|
|
977
895
|
};
|
|
978
896
|
}
|
|
979
897
|
async function gatePlan(input, deps, ctx) {
|
|
980
|
-
const plan = await
|
|
981
|
-
|
|
898
|
+
const plan = await deps.readPlan({
|
|
899
|
+
workspaceId: input.workspaceId,
|
|
900
|
+
intent: input.intent,
|
|
901
|
+
senderIds: input.senderIds,
|
|
902
|
+
runState: ctx.runState,
|
|
903
|
+
journal: false,
|
|
904
|
+
});
|
|
982
905
|
if (plan.blocker === "workspace_access") {
|
|
983
906
|
return {
|
|
984
907
|
status: "blocked",
|
|
@@ -1081,7 +1004,13 @@ async function verifyRecoveryPoint(input, deps, ctx) {
|
|
|
1081
1004
|
stateRevision: stringValue(planned.stateRevision),
|
|
1082
1005
|
targetShapeRevision: stringValue(planned.targetShapeRevision),
|
|
1083
1006
|
};
|
|
1084
|
-
const fresh = await
|
|
1007
|
+
const fresh = await deps.readPlan({
|
|
1008
|
+
workspaceId: input.workspaceId,
|
|
1009
|
+
intent: input.intent,
|
|
1010
|
+
senderIds: input.senderIds,
|
|
1011
|
+
runState: ctx.runState,
|
|
1012
|
+
journal: false,
|
|
1013
|
+
});
|
|
1085
1014
|
const changed = fingerprintChanged(expected, fingerprintFromPlan(fresh));
|
|
1086
1015
|
if (changed.length > 0) {
|
|
1087
1016
|
await deps.runClient.recordRunOutcome({
|
|
@@ -1343,8 +1272,13 @@ async function verifyPrepareAction(input, deps, ctx, action, budgets) {
|
|
|
1343
1272
|
}
|
|
1344
1273
|
async function verifyReadOnlyWait(input, deps, ctx, budgets, waitKind) {
|
|
1345
1274
|
for (let poll = 0; poll < budgets.maxPollsPerWait; poll += 1) {
|
|
1346
|
-
const fresh = await
|
|
1347
|
-
|
|
1275
|
+
const fresh = await deps.readPlan({
|
|
1276
|
+
workspaceId: input.workspaceId,
|
|
1277
|
+
intent: input.intent,
|
|
1278
|
+
senderIds: input.senderIds,
|
|
1279
|
+
runState: ctx.runState,
|
|
1280
|
+
journal: false,
|
|
1281
|
+
});
|
|
1348
1282
|
ctx.plan = fresh;
|
|
1349
1283
|
const doneReason = doneReasonFromPlan(fresh);
|
|
1350
1284
|
if (doneReason) {
|
|
@@ -1376,30 +1310,31 @@ async function verifySchedulerWait(input, deps, ctx, action, budgets) {
|
|
|
1376
1310
|
if (!jitFired) {
|
|
1377
1311
|
const senderId = actionSenderId(action);
|
|
1378
1312
|
if (senderId) {
|
|
1379
|
-
await deps.executors.refreshPaidInmailCreditsWithRetry(senderId, input.workspaceId);
|
|
1313
|
+
const refresh = await deps.executors.refreshPaidInmailCreditsWithRetry(senderId, input.workspaceId);
|
|
1314
|
+
const classification = classifyPaidInmailRefreshReceipt(refresh.receipt);
|
|
1315
|
+
if (!classification.usableCurrentFacts) {
|
|
1316
|
+
return {
|
|
1317
|
+
status: "blocked",
|
|
1318
|
+
blocker: "paid_inmail_refresh_failed",
|
|
1319
|
+
runId: ctx.runId,
|
|
1320
|
+
fence: ctx.fence,
|
|
1321
|
+
gate: ctx.gate,
|
|
1322
|
+
guidance: "Paid InMail credit refresh did not return usable current facts, so scheduler JIT was not requested.",
|
|
1323
|
+
report: {
|
|
1324
|
+
senderId,
|
|
1325
|
+
receiptStatus: classification.status,
|
|
1326
|
+
error: classification.error,
|
|
1327
|
+
receipt: refresh.receipt,
|
|
1328
|
+
attempts: refresh.attempts,
|
|
1329
|
+
errors: refresh.errors,
|
|
1330
|
+
},
|
|
1331
|
+
journalPath: ctx.journalPath,
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1380
1334
|
}
|
|
1381
1335
|
if (deps.requestSchedulerRun) {
|
|
1382
1336
|
try {
|
|
1383
|
-
|
|
1384
|
-
const sweepReceipts = [];
|
|
1385
|
-
if (targetDates.length === 0) {
|
|
1386
|
-
schedulerRunReceipt = sanitizeSchedulerRunReceipt(await deps.requestSchedulerRun(input.workspaceId));
|
|
1387
|
-
}
|
|
1388
|
-
else {
|
|
1389
|
-
for (const targetDate of targetDates) {
|
|
1390
|
-
const receipt = sanitizeSchedulerRunReceipt(await deps.requestSchedulerRun(input.workspaceId, { targetDate }));
|
|
1391
|
-
if (receipt)
|
|
1392
|
-
sweepReceipts.push({ targetDate, ...receipt });
|
|
1393
|
-
}
|
|
1394
|
-
schedulerRunReceipt = sweepReceipts[0] ?? null;
|
|
1395
|
-
}
|
|
1396
|
-
if (sweepReceipts.length > 1) {
|
|
1397
|
-
ctx.runState = mergeRunState(ctx.runState, {
|
|
1398
|
-
progress: mergeProgress(ctx, {
|
|
1399
|
-
schedulerRunReceipts: sweepReceipts,
|
|
1400
|
-
}),
|
|
1401
|
-
});
|
|
1402
|
-
}
|
|
1337
|
+
schedulerRunReceipt = sanitizeSchedulerRunReceipt(await deps.requestSchedulerRun(input.workspaceId));
|
|
1403
1338
|
}
|
|
1404
1339
|
catch {
|
|
1405
1340
|
schedulerRunReceipt = null;
|
|
@@ -1419,8 +1354,13 @@ async function verifySchedulerWait(input, deps, ctx, action, budgets) {
|
|
|
1419
1354
|
// full wait budget when the fresh receipt says nothing was placeable now.
|
|
1420
1355
|
const readbackBudget = zeroScheduledFresh ? 1 : budgets.maxSchedulerReadbacks;
|
|
1421
1356
|
for (let poll = 0; poll < readbackBudget; poll += 1) {
|
|
1422
|
-
const fresh = await
|
|
1423
|
-
|
|
1357
|
+
const fresh = await deps.readPlan({
|
|
1358
|
+
workspaceId: input.workspaceId,
|
|
1359
|
+
intent: input.intent,
|
|
1360
|
+
senderIds: input.senderIds,
|
|
1361
|
+
runState: ctx.runState,
|
|
1362
|
+
journal: false,
|
|
1363
|
+
});
|
|
1424
1364
|
ctx.plan = fresh;
|
|
1425
1365
|
const doneReason = normalizeDoneReason(doneReasonFromPlan(fresh));
|
|
1426
1366
|
if (doneReason === "complete" || doneReason === "capped_by_scheduler") {
|
|
@@ -1476,8 +1416,13 @@ async function gateVerify(input, deps, ctx, budgets) {
|
|
|
1476
1416
|
actionType === "wait_for_source_import") {
|
|
1477
1417
|
return verifyReadOnlyWait(input, deps, ctx, budgets, actionType);
|
|
1478
1418
|
}
|
|
1479
|
-
const fresh = await
|
|
1480
|
-
|
|
1419
|
+
const fresh = await deps.readPlan({
|
|
1420
|
+
workspaceId: input.workspaceId,
|
|
1421
|
+
intent: input.intent,
|
|
1422
|
+
senderIds: input.senderIds,
|
|
1423
|
+
runState: ctx.runState,
|
|
1424
|
+
journal: false,
|
|
1425
|
+
});
|
|
1481
1426
|
ctx.plan = fresh;
|
|
1482
1427
|
const doneReason = doneReasonFromPlan(fresh);
|
|
1483
1428
|
if (doneReason) {
|
|
@@ -1550,21 +1495,15 @@ export async function runRefillV2Loop(input, deps) {
|
|
|
1550
1495
|
let ctx = null;
|
|
1551
1496
|
try {
|
|
1552
1497
|
if (input.dryRun) {
|
|
1553
|
-
const
|
|
1554
|
-
const plan = await deps.readPlan(readPlanRequest({
|
|
1498
|
+
const plan = await deps.readPlan({
|
|
1555
1499
|
workspaceId: input.workspaceId,
|
|
1556
1500
|
intent: input.intent,
|
|
1557
1501
|
senderIds: input.senderIds,
|
|
1558
1502
|
journal: true,
|
|
1559
|
-
|
|
1560
|
-
}));
|
|
1503
|
+
});
|
|
1561
1504
|
return { status: "dry_run", plan };
|
|
1562
1505
|
}
|
|
1563
|
-
const
|
|
1564
|
-
const preflight = await preflightResumeDateWindow(input, deps, requestedSelector);
|
|
1565
|
-
if ("status" in preflight)
|
|
1566
|
-
return preflight;
|
|
1567
|
-
const started = await startOrResume(input, deps, preflight.window);
|
|
1506
|
+
const started = await startOrResume(input, deps);
|
|
1568
1507
|
if ("status" in started)
|
|
1569
1508
|
return started;
|
|
1570
1509
|
ctx = started;
|
package/dist/server.js
CHANGED
|
@@ -319,7 +319,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
319
319
|
}
|
|
320
320
|
break;
|
|
321
321
|
case "start_campaign":
|
|
322
|
-
result = await startCampaign(args?.campaignId);
|
|
322
|
+
result = await startCampaign(args?.campaignId, args?.workspaceId);
|
|
323
323
|
if (args?.campaignId && result?.success) {
|
|
324
324
|
markCampaignContextDirty(args.campaignId, "start_campaign");
|
|
325
325
|
}
|
|
@@ -185,6 +185,7 @@ export declare const campaignToolDefinitions: ({
|
|
|
185
185
|
useMessagingTemplate?: undefined;
|
|
186
186
|
rubric?: undefined;
|
|
187
187
|
flowVersion?: undefined;
|
|
188
|
+
workspaceId?: undefined;
|
|
188
189
|
};
|
|
189
190
|
required: string[];
|
|
190
191
|
additionalProperties: boolean;
|
|
@@ -223,6 +224,7 @@ export declare const campaignToolDefinitions: ({
|
|
|
223
224
|
useMessagingTemplate?: undefined;
|
|
224
225
|
rubric?: undefined;
|
|
225
226
|
flowVersion?: undefined;
|
|
227
|
+
workspaceId?: undefined;
|
|
226
228
|
};
|
|
227
229
|
required: never[];
|
|
228
230
|
additionalProperties?: undefined;
|
|
@@ -261,6 +263,7 @@ export declare const campaignToolDefinitions: ({
|
|
|
261
263
|
useMessagingTemplate?: undefined;
|
|
262
264
|
rubric?: undefined;
|
|
263
265
|
flowVersion?: undefined;
|
|
266
|
+
workspaceId?: undefined;
|
|
264
267
|
};
|
|
265
268
|
required: string[];
|
|
266
269
|
additionalProperties?: undefined;
|
|
@@ -342,6 +345,7 @@ export declare const campaignToolDefinitions: ({
|
|
|
342
345
|
useMessagingTemplate?: undefined;
|
|
343
346
|
rubric?: undefined;
|
|
344
347
|
flowVersion?: undefined;
|
|
348
|
+
workspaceId?: undefined;
|
|
345
349
|
};
|
|
346
350
|
required: string[];
|
|
347
351
|
additionalProperties: boolean;
|
|
@@ -536,6 +540,7 @@ export declare const campaignToolDefinitions: ({
|
|
|
536
540
|
useMessagingTemplate?: undefined;
|
|
537
541
|
rubric?: undefined;
|
|
538
542
|
flowVersion?: undefined;
|
|
543
|
+
workspaceId?: undefined;
|
|
539
544
|
};
|
|
540
545
|
required: never[];
|
|
541
546
|
additionalProperties?: undefined;
|
|
@@ -741,6 +746,49 @@ export declare const campaignToolDefinitions: ({
|
|
|
741
746
|
clientProspectId?: undefined;
|
|
742
747
|
senderLinkedinUrl?: undefined;
|
|
743
748
|
messageGenerationMode?: undefined;
|
|
749
|
+
workspaceId?: undefined;
|
|
750
|
+
};
|
|
751
|
+
required: string[];
|
|
752
|
+
additionalProperties?: undefined;
|
|
753
|
+
};
|
|
754
|
+
} | {
|
|
755
|
+
name: string;
|
|
756
|
+
description: string;
|
|
757
|
+
inputSchema: {
|
|
758
|
+
type: string;
|
|
759
|
+
properties: {
|
|
760
|
+
campaignId: {
|
|
761
|
+
type: string;
|
|
762
|
+
description: string;
|
|
763
|
+
};
|
|
764
|
+
workspaceId: {
|
|
765
|
+
type: string;
|
|
766
|
+
description: string;
|
|
767
|
+
};
|
|
768
|
+
limit?: undefined;
|
|
769
|
+
tableId?: undefined;
|
|
770
|
+
leadLimit?: undefined;
|
|
771
|
+
page?: undefined;
|
|
772
|
+
filters?: undefined;
|
|
773
|
+
name?: undefined;
|
|
774
|
+
clientProspectId?: undefined;
|
|
775
|
+
senderLinkedinUrl?: undefined;
|
|
776
|
+
offerPositioning?: undefined;
|
|
777
|
+
campaignBrief?: undefined;
|
|
778
|
+
messageGenerationMode?: undefined;
|
|
779
|
+
currentStep?: undefined;
|
|
780
|
+
watchNarration?: undefined;
|
|
781
|
+
leadSourceType?: undefined;
|
|
782
|
+
leadSourceProvider?: undefined;
|
|
783
|
+
selectedLeadListId?: undefined;
|
|
784
|
+
senderIds?: undefined;
|
|
785
|
+
currentStepTransition?: undefined;
|
|
786
|
+
clearCurrentStepIfMatches?: undefined;
|
|
787
|
+
interactionMode?: undefined;
|
|
788
|
+
enableICPFilters?: undefined;
|
|
789
|
+
useMessagingTemplate?: undefined;
|
|
790
|
+
rubric?: undefined;
|
|
791
|
+
flowVersion?: undefined;
|
|
744
792
|
};
|
|
745
793
|
required: string[];
|
|
746
794
|
additionalProperties?: undefined;
|
|
@@ -782,6 +830,7 @@ export declare const campaignToolDefinitions: ({
|
|
|
782
830
|
useMessagingTemplate?: undefined;
|
|
783
831
|
rubric?: undefined;
|
|
784
832
|
flowVersion?: undefined;
|
|
833
|
+
workspaceId?: undefined;
|
|
785
834
|
};
|
|
786
835
|
required: string[];
|
|
787
836
|
additionalProperties?: undefined;
|
|
@@ -821,7 +870,7 @@ export interface UpdateCampaignResult {
|
|
|
821
870
|
_campaign?: CampaignOfferNavigation;
|
|
822
871
|
}
|
|
823
872
|
export declare function updateCampaign(campaignId: string, input: UpdateCampaignInput): Promise<UpdateCampaignResult>;
|
|
824
|
-
export declare function startCampaign(campaignId: string): Promise<{
|
|
873
|
+
export declare function startCampaign(campaignId: string, workspaceId?: string | null): Promise<{
|
|
825
874
|
success: boolean;
|
|
826
875
|
}>;
|
|
827
876
|
export declare function pauseCampaign(campaignId: string): Promise<{
|
package/dist/tools/campaigns.js
CHANGED
|
@@ -476,6 +476,10 @@ export const campaignToolDefinitions = [
|
|
|
476
476
|
type: "string",
|
|
477
477
|
description: "Campaign ID to start",
|
|
478
478
|
},
|
|
479
|
+
workspaceId: {
|
|
480
|
+
type: "string",
|
|
481
|
+
description: "Optional explicit request-scoped workspace id. Pass this for scheduled/yolo refill automation instead of relying on the shared active workspace.",
|
|
482
|
+
},
|
|
479
483
|
},
|
|
480
484
|
required: ["campaignId"],
|
|
481
485
|
},
|
|
@@ -1026,9 +1030,9 @@ export async function updateCampaign(campaignId, input) {
|
|
|
1026
1030
|
_campaign: result,
|
|
1027
1031
|
};
|
|
1028
1032
|
}
|
|
1029
|
-
export async function startCampaign(campaignId) {
|
|
1033
|
+
export async function startCampaign(campaignId, workspaceId) {
|
|
1030
1034
|
const api = getApi();
|
|
1031
|
-
return api.post(`/api/v3/campaigns/${campaignId}/start
|
|
1035
|
+
return api.post(`/api/v3/campaigns/${campaignId}/start`, undefined, workspaceId ? { workspaceId } : undefined);
|
|
1032
1036
|
}
|
|
1033
1037
|
export async function pauseCampaign(campaignId) {
|
|
1034
1038
|
const api = getApi();
|
|
@@ -3,9 +3,6 @@ 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;
|
|
9
6
|
journal?: boolean;
|
|
10
7
|
journalNote?: string;
|
|
11
8
|
};
|
|
@@ -41,22 +38,6 @@ export declare const refillPlanV2ToolDefinitions: {
|
|
|
41
38
|
enum: string[];
|
|
42
39
|
description: string;
|
|
43
40
|
};
|
|
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
|
-
};
|
|
60
41
|
journal: {
|
|
61
42
|
type: string;
|
|
62
43
|
description: string;
|
|
@@ -1,6 +1,5 @@
|
|
|
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";
|
|
4
3
|
import { appendIndexLine, appendJournalEvent, createRunJournal, renderBootstrapSection, renderPlanSection, renderTerminalSection, } from "../refill-journal.js";
|
|
5
4
|
import { readRefillWorkspaceState } from "../refill-local-state.js";
|
|
6
5
|
import { normalizeExplicitWorkspaceId, workspaceRequestOptions, } from "./workspace-context.js";
|
|
@@ -176,22 +175,6 @@ export const refillPlanV2ToolDefinitions = [
|
|
|
176
175
|
enum: ["auto", "evergreen", "plain", "active"],
|
|
177
176
|
description: 'Planner intent. Defaults to "auto" for refill-sends-v2.',
|
|
178
177
|
},
|
|
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
|
-
},
|
|
195
178
|
journal: {
|
|
196
179
|
type: "boolean",
|
|
197
180
|
description: "Set false to skip the local dry-run journal write.",
|
|
@@ -214,7 +197,6 @@ export async function getRefillPlanV2(input) {
|
|
|
214
197
|
const runState = input.runState !== undefined
|
|
215
198
|
? input.runState
|
|
216
199
|
: buildRunStateFromLocalHints(workspaceId);
|
|
217
|
-
const dateSelector = normalizeRefillDateSelector(input);
|
|
218
200
|
let raw;
|
|
219
201
|
try {
|
|
220
202
|
raw = await postRefillPlanV2({
|
|
@@ -222,7 +204,6 @@ export async function getRefillPlanV2(input) {
|
|
|
222
204
|
intent: input.intent ?? "auto",
|
|
223
205
|
senderIds: input.senderIds,
|
|
224
206
|
runState,
|
|
225
|
-
...refillDateSelectorBody(dateSelector),
|
|
226
207
|
}, workspaceId);
|
|
227
208
|
}
|
|
228
209
|
catch (error) {
|
|
@@ -14,6 +14,12 @@ 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
|
+
};
|
|
17
23
|
export type YoloPrimitiveExecution = {
|
|
18
24
|
enabled: true;
|
|
19
25
|
status: "no_action" | "read_only_reread" | "executed_and_reread" | "refused" | "skipped_after_paid_refresh";
|
|
@@ -135,6 +141,7 @@ export declare function userAddedRowsLimitPayloadFromError(error: unknown): User
|
|
|
135
141
|
export declare function sourceImportInProgressPayloadFromError(error: unknown): SourceImportInProgressPayload | null;
|
|
136
142
|
export declare function paidRefreshActionFrom(value: unknown): PaidInmailRefreshAction | null;
|
|
137
143
|
export declare function collectPaidInmailRefreshActions(plan: unknown): PaidInmailRefreshAction[];
|
|
144
|
+
export declare function classifyPaidInmailRefreshReceipt(value: unknown): PaidInmailRefreshReceiptClassification;
|
|
138
145
|
export declare function firstGlobalAction(plan: unknown): Record<string, unknown> | null;
|
|
139
146
|
export declare function actionIds(action: Record<string, unknown>): Record<string, unknown>;
|
|
140
147
|
export declare function actionToolInput(action: Record<string, unknown>): Record<string, unknown>;
|