@sellable/mcp 0.1.540 → 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 +91 -156
- 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,21 +599,17 @@ 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") {
|
|
648
|
-
|
|
649
|
-
if (!(doneReason === "loaded_awaiting_scheduler" &&
|
|
650
|
-
type === "wait_for_scheduler")) {
|
|
651
|
-
return "terminal_with_action_queue";
|
|
652
|
-
}
|
|
609
|
+
return "terminal_with_action_queue";
|
|
653
610
|
}
|
|
654
611
|
if (!action)
|
|
655
612
|
return null;
|
|
656
|
-
const fingerprint = fingerprintFromPlan(plan);
|
|
657
|
-
if (!fingerprint.planRevision || !fingerprint.targetShapeRevision) {
|
|
658
|
-
return "missing_fingerprint";
|
|
659
|
-
}
|
|
660
613
|
const toolInput = actionToolInput(action);
|
|
661
614
|
const type = stringValue(action.type);
|
|
662
615
|
if (type === "prepare_messages" &&
|
|
@@ -717,63 +670,14 @@ async function createJournal(input, deps, runId) {
|
|
|
717
670
|
return null;
|
|
718
671
|
}
|
|
719
672
|
}
|
|
720
|
-
async function
|
|
721
|
-
const
|
|
722
|
-
if (!input.resume) {
|
|
723
|
-
return { ok: true, selector: requestedSelector, window: requestedWindow };
|
|
724
|
-
}
|
|
725
|
-
const status = await deps.runClient.refillRunStatus({
|
|
726
|
-
workspaceId: input.workspaceId,
|
|
727
|
-
runId: input.resume.runId,
|
|
728
|
-
});
|
|
729
|
-
if (hasBlocker(status, "lease_lost")) {
|
|
730
|
-
return {
|
|
731
|
-
status: "blocked",
|
|
732
|
-
blocker: "lease_lost",
|
|
733
|
-
runId: input.resume.runId,
|
|
734
|
-
fence: input.resume.fence,
|
|
735
|
-
guidance: "Refill run lease was lost before resume date-window preflight.",
|
|
736
|
-
};
|
|
737
|
-
}
|
|
738
|
-
const storedWindow = dateWindowFromRunState(recordValue(status)?.runState);
|
|
739
|
-
const explicitSelector = requestedSelector.source !== "default_scheduler_forward";
|
|
740
|
-
if (!storedWindow) {
|
|
741
|
-
if (explicitSelector) {
|
|
742
|
-
return {
|
|
743
|
-
status: "blocked",
|
|
744
|
-
blocker: "date_window_conflict",
|
|
745
|
-
runId: input.resume.runId,
|
|
746
|
-
fence: input.resume.fence,
|
|
747
|
-
guidance: "This legacy refill_sends_v2 run has no stored date window. Resume it without a new date selector or start a new run.",
|
|
748
|
-
report: { requestedDateWindow: requestedWindow },
|
|
749
|
-
};
|
|
750
|
-
}
|
|
751
|
-
return { ok: true, selector: requestedSelector, window: requestedWindow };
|
|
752
|
-
}
|
|
753
|
-
if (explicitSelector && !dateSelectorMatchesWindow(requestedSelector, storedWindow)) {
|
|
754
|
-
return {
|
|
755
|
-
status: "blocked",
|
|
756
|
-
blocker: "date_window_conflict",
|
|
757
|
-
runId: input.resume.runId,
|
|
758
|
-
fence: input.resume.fence,
|
|
759
|
-
guidance: "Resume date selector conflicts with the stored refill run date window.",
|
|
760
|
-
report: { requestedDateWindow: requestedWindow, storedDateWindow: storedWindow },
|
|
761
|
-
};
|
|
762
|
-
}
|
|
763
|
-
const selector = explicitSelector
|
|
764
|
-
? requestedSelector
|
|
765
|
-
: selectorFromDateWindow(storedWindow);
|
|
766
|
-
return { ok: true, selector, window: storedWindow };
|
|
767
|
-
}
|
|
768
|
-
async function startOrResume(input, deps, dateWindow) {
|
|
769
|
-
const initialRunState = runStateWithDateWindow(buildRunStateFromLocalHints(input.workspaceId), dateWindow);
|
|
673
|
+
async function startOrResume(input, deps) {
|
|
674
|
+
const initialRunState = buildRunStateFromLocalHints(input.workspaceId);
|
|
770
675
|
const started = await deps.runClient.startRefillRunRemote({
|
|
771
676
|
workspaceId: input.workspaceId,
|
|
772
677
|
config: {
|
|
773
678
|
intent: input.intent ?? "auto",
|
|
774
679
|
senderIds: input.senderIds,
|
|
775
680
|
approvalMode: input.approvalMode ?? "approve",
|
|
776
|
-
dateWindow,
|
|
777
681
|
},
|
|
778
682
|
runState: initialRunState,
|
|
779
683
|
resume: input.resume,
|
|
@@ -815,8 +719,6 @@ async function startOrResume(input, deps, dateWindow) {
|
|
|
815
719
|
laneCooldowns: [],
|
|
816
720
|
passRates: [],
|
|
817
721
|
};
|
|
818
|
-
const storedDateWindow = dateWindowFromRunState(runState) ?? dateWindow;
|
|
819
|
-
const storedDateSelector = selectorFromDateWindow(storedDateWindow);
|
|
820
722
|
const journalPath = await createJournal(input, deps, runId);
|
|
821
723
|
const ctx = {
|
|
822
724
|
workspaceId: input.workspaceId,
|
|
@@ -829,8 +731,6 @@ async function startOrResume(input, deps, dateWindow) {
|
|
|
829
731
|
plan: null,
|
|
830
732
|
headAction: null,
|
|
831
733
|
lastFingerprint: null,
|
|
832
|
-
dateSelector: storedDateSelector,
|
|
833
|
-
dateWindow: storedDateWindow,
|
|
834
734
|
recoveryPoint: recordValue(result.recoveryPoint),
|
|
835
735
|
gateCycles: 0,
|
|
836
736
|
sleptMs: 0,
|
|
@@ -849,31 +749,45 @@ async function startOrResume(input, deps, dateWindow) {
|
|
|
849
749
|
return ctx;
|
|
850
750
|
}
|
|
851
751
|
async function gateBootstrap(input, deps, ctx) {
|
|
852
|
-
const plan = await
|
|
853
|
-
|
|
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
|
+
});
|
|
854
759
|
const paidCredit = arrayValue(recordValue(plan.bootstrap)?.paidCredit).filter(isRecord);
|
|
855
760
|
const refreshedSenderIds = new Set(arrayValue(recordValue(ctx.runState.creditTrust)?.senderIds)
|
|
856
761
|
.map((entry) => stringValue(entry))
|
|
857
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)));
|
|
858
766
|
const receipts = [];
|
|
859
767
|
for (const entry of paidCredit) {
|
|
860
768
|
const senderId = stringValue(entry.senderId);
|
|
861
769
|
if (!senderId ||
|
|
862
770
|
!entry.plannedJitRefresh ||
|
|
863
|
-
refreshedSenderIds.has(senderId)
|
|
771
|
+
refreshedSenderIds.has(senderId) ||
|
|
772
|
+
attemptedSenderIds.has(senderId)) {
|
|
864
773
|
continue;
|
|
865
774
|
}
|
|
866
775
|
const receipt = await deps.executors.refreshPaidInmailCreditsWithRetry(senderId, input.workspaceId);
|
|
867
|
-
|
|
868
|
-
|
|
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
|
+
}
|
|
869
782
|
}
|
|
870
|
-
const nextRunState =
|
|
783
|
+
const nextRunState = mergeRunState(ctx.runState, {
|
|
871
784
|
creditTrust: {
|
|
872
785
|
refreshedAt: (deps.now?.() ?? new Date()).toISOString(),
|
|
873
786
|
senderIds: [...refreshedSenderIds],
|
|
787
|
+
attemptedSenderIds: [...attemptedSenderIds],
|
|
874
788
|
receipts,
|
|
875
789
|
},
|
|
876
|
-
})
|
|
790
|
+
});
|
|
877
791
|
await safeJournalAppend(ctx, deps, deps.journal.renderBootstrapSection({
|
|
878
792
|
summary: "Refill v2 execution bootstrap",
|
|
879
793
|
senderSummary: safeJson(recordValue(plan.bootstrap)?.senders ?? []),
|
|
@@ -981,8 +895,13 @@ async function completeTerminal(input, deps, ctx, doneReasonInput, reportInput =
|
|
|
981
895
|
};
|
|
982
896
|
}
|
|
983
897
|
async function gatePlan(input, deps, ctx) {
|
|
984
|
-
const plan = await
|
|
985
|
-
|
|
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
|
+
});
|
|
986
905
|
if (plan.blocker === "workspace_access") {
|
|
987
906
|
return {
|
|
988
907
|
status: "blocked",
|
|
@@ -1085,7 +1004,13 @@ async function verifyRecoveryPoint(input, deps, ctx) {
|
|
|
1085
1004
|
stateRevision: stringValue(planned.stateRevision),
|
|
1086
1005
|
targetShapeRevision: stringValue(planned.targetShapeRevision),
|
|
1087
1006
|
};
|
|
1088
|
-
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
|
+
});
|
|
1089
1014
|
const changed = fingerprintChanged(expected, fingerprintFromPlan(fresh));
|
|
1090
1015
|
if (changed.length > 0) {
|
|
1091
1016
|
await deps.runClient.recordRunOutcome({
|
|
@@ -1347,8 +1272,13 @@ async function verifyPrepareAction(input, deps, ctx, action, budgets) {
|
|
|
1347
1272
|
}
|
|
1348
1273
|
async function verifyReadOnlyWait(input, deps, ctx, budgets, waitKind) {
|
|
1349
1274
|
for (let poll = 0; poll < budgets.maxPollsPerWait; poll += 1) {
|
|
1350
|
-
const fresh = await
|
|
1351
|
-
|
|
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
|
+
});
|
|
1352
1282
|
ctx.plan = fresh;
|
|
1353
1283
|
const doneReason = doneReasonFromPlan(fresh);
|
|
1354
1284
|
if (doneReason) {
|
|
@@ -1380,30 +1310,31 @@ async function verifySchedulerWait(input, deps, ctx, action, budgets) {
|
|
|
1380
1310
|
if (!jitFired) {
|
|
1381
1311
|
const senderId = actionSenderId(action);
|
|
1382
1312
|
if (senderId) {
|
|
1383
|
-
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
|
+
}
|
|
1384
1334
|
}
|
|
1385
1335
|
if (deps.requestSchedulerRun) {
|
|
1386
1336
|
try {
|
|
1387
|
-
|
|
1388
|
-
const sweepReceipts = [];
|
|
1389
|
-
if (targetDates.length === 0) {
|
|
1390
|
-
schedulerRunReceipt = sanitizeSchedulerRunReceipt(await deps.requestSchedulerRun(input.workspaceId));
|
|
1391
|
-
}
|
|
1392
|
-
else {
|
|
1393
|
-
for (const targetDate of targetDates) {
|
|
1394
|
-
const receipt = sanitizeSchedulerRunReceipt(await deps.requestSchedulerRun(input.workspaceId, { targetDate }));
|
|
1395
|
-
if (receipt)
|
|
1396
|
-
sweepReceipts.push({ targetDate, ...receipt });
|
|
1397
|
-
}
|
|
1398
|
-
schedulerRunReceipt = sweepReceipts[0] ?? null;
|
|
1399
|
-
}
|
|
1400
|
-
if (sweepReceipts.length > 1) {
|
|
1401
|
-
ctx.runState = mergeRunState(ctx.runState, {
|
|
1402
|
-
progress: mergeProgress(ctx, {
|
|
1403
|
-
schedulerRunReceipts: sweepReceipts,
|
|
1404
|
-
}),
|
|
1405
|
-
});
|
|
1406
|
-
}
|
|
1337
|
+
schedulerRunReceipt = sanitizeSchedulerRunReceipt(await deps.requestSchedulerRun(input.workspaceId));
|
|
1407
1338
|
}
|
|
1408
1339
|
catch {
|
|
1409
1340
|
schedulerRunReceipt = null;
|
|
@@ -1423,8 +1354,13 @@ async function verifySchedulerWait(input, deps, ctx, action, budgets) {
|
|
|
1423
1354
|
// full wait budget when the fresh receipt says nothing was placeable now.
|
|
1424
1355
|
const readbackBudget = zeroScheduledFresh ? 1 : budgets.maxSchedulerReadbacks;
|
|
1425
1356
|
for (let poll = 0; poll < readbackBudget; poll += 1) {
|
|
1426
|
-
const fresh = await
|
|
1427
|
-
|
|
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
|
+
});
|
|
1428
1364
|
ctx.plan = fresh;
|
|
1429
1365
|
const doneReason = normalizeDoneReason(doneReasonFromPlan(fresh));
|
|
1430
1366
|
if (doneReason === "complete" || doneReason === "capped_by_scheduler") {
|
|
@@ -1480,8 +1416,13 @@ async function gateVerify(input, deps, ctx, budgets) {
|
|
|
1480
1416
|
actionType === "wait_for_source_import") {
|
|
1481
1417
|
return verifyReadOnlyWait(input, deps, ctx, budgets, actionType);
|
|
1482
1418
|
}
|
|
1483
|
-
const fresh = await
|
|
1484
|
-
|
|
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
|
+
});
|
|
1485
1426
|
ctx.plan = fresh;
|
|
1486
1427
|
const doneReason = doneReasonFromPlan(fresh);
|
|
1487
1428
|
if (doneReason) {
|
|
@@ -1554,21 +1495,15 @@ export async function runRefillV2Loop(input, deps) {
|
|
|
1554
1495
|
let ctx = null;
|
|
1555
1496
|
try {
|
|
1556
1497
|
if (input.dryRun) {
|
|
1557
|
-
const
|
|
1558
|
-
const plan = await deps.readPlan(readPlanRequest({
|
|
1498
|
+
const plan = await deps.readPlan({
|
|
1559
1499
|
workspaceId: input.workspaceId,
|
|
1560
1500
|
intent: input.intent,
|
|
1561
1501
|
senderIds: input.senderIds,
|
|
1562
1502
|
journal: true,
|
|
1563
|
-
|
|
1564
|
-
}));
|
|
1503
|
+
});
|
|
1565
1504
|
return { status: "dry_run", plan };
|
|
1566
1505
|
}
|
|
1567
|
-
const
|
|
1568
|
-
const preflight = await preflightResumeDateWindow(input, deps, requestedSelector);
|
|
1569
|
-
if ("status" in preflight)
|
|
1570
|
-
return preflight;
|
|
1571
|
-
const started = await startOrResume(input, deps, preflight.window);
|
|
1506
|
+
const started = await startOrResume(input, deps);
|
|
1572
1507
|
if ("status" in started)
|
|
1573
1508
|
return started;
|
|
1574
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>;
|