@sellable/mcp 0.1.569-phase981.20260711223346 → 0.1.570
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/refill-run-client.d.ts +0 -10
- package/dist/refill-run-client.js +0 -22
- package/dist/refill-run-loop.d.ts +2 -14
- package/dist/refill-run-loop.js +18 -169
- package/dist/tools/campaign-message-preparation.d.ts +0 -62
- package/dist/tools/campaign-message-preparation.js +0 -41
- package/dist/tools/evergreen-refill-plan.d.ts +0 -3
- package/dist/tools/evergreen-refill-plan.js +7 -29
- package/dist/tools/prompts.js +0 -9
- package/dist/tools/refill-executors.d.ts +1 -9
- package/dist/tools/refill-executors.js +8 -101
- package/dist/tools/refill-sends-v2.d.ts +1 -118
- package/dist/tools/refill-sends-v2.js +3 -312
- package/dist/tools/refill-sends.d.ts +2 -506
- package/dist/tools/refill-sends.js +3 -136
- package/dist/tools/refill-target-plan.js +23 -317
- package/dist/tools/registry.d.ts +33 -94
- package/dist/tools/registry.js +3 -1
- package/dist/tools/scheduler-run.d.ts +0 -61
- package/dist/tools/scheduler-run.js +1 -183
- package/package.json +1 -1
- package/skills/refill-sends/SKILL.md +388 -94
- package/skills/refill-sends-v2/SKILL.md +6 -6
- package/skills/refill-sends-v2-workflow/SKILL.md +5 -5
- package/skills/refill-sends-v2-workflow/core/flow.v1.json +8 -8
- package/skills/refill-sends-workflow/SKILL.md +781 -100
- package/skills/refill-sends-workflow/core/flow.v1.json +0 -122
- package/dist/refill-contract.d.ts +0 -157
- package/dist/refill-contract.js +0 -487
- package/skills/refill-sends-workflow/core/contract.v2.json +0 -543
|
@@ -5,11 +5,6 @@ export type RefillRunBlockerResult = {
|
|
|
5
5
|
runId: string;
|
|
6
6
|
gate?: string;
|
|
7
7
|
gateSeq?: number;
|
|
8
|
-
} | {
|
|
9
|
-
blocker: "scope_drift" | "approval_expired" | "approval_fingerprint_mismatch";
|
|
10
|
-
runId: string;
|
|
11
|
-
expectedScopeHash: string | null;
|
|
12
|
-
receivedScopeHash: string | null;
|
|
13
8
|
};
|
|
14
9
|
export declare function startRefillRunRemote(input: {
|
|
15
10
|
workspaceId?: string;
|
|
@@ -29,11 +24,6 @@ export declare function heartbeatRefillRun(input: {
|
|
|
29
24
|
runId: string;
|
|
30
25
|
fence: number;
|
|
31
26
|
}): Promise<unknown>;
|
|
32
|
-
export declare function yieldRefillRun(input: {
|
|
33
|
-
workspaceId?: string;
|
|
34
|
-
runId: string;
|
|
35
|
-
fence: number;
|
|
36
|
-
}): Promise<unknown>;
|
|
37
27
|
export declare function advanceRefillRunGateRemote(input: {
|
|
38
28
|
workspaceId?: string;
|
|
39
29
|
runId: string;
|
|
@@ -15,21 +15,6 @@ function parseBlockerBody(body) {
|
|
|
15
15
|
gateSeq: typeof parsed.gateSeq === "number" ? parsed.gateSeq : undefined,
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
|
-
if ((parsed.blocker === "scope_drift" ||
|
|
19
|
-
parsed.blocker === "approval_expired" ||
|
|
20
|
-
parsed.blocker === "approval_fingerprint_mismatch") &&
|
|
21
|
-
typeof parsed.runId === "string") {
|
|
22
|
-
return {
|
|
23
|
-
blocker: parsed.blocker,
|
|
24
|
-
runId: parsed.runId,
|
|
25
|
-
expectedScopeHash: typeof parsed.expectedScopeHash === "string"
|
|
26
|
-
? parsed.expectedScopeHash
|
|
27
|
-
: null,
|
|
28
|
-
receivedScopeHash: typeof parsed.receivedScopeHash === "string"
|
|
29
|
-
? parsed.receivedScopeHash
|
|
30
|
-
: null,
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
18
|
}
|
|
34
19
|
catch {
|
|
35
20
|
return null;
|
|
@@ -70,13 +55,6 @@ export function heartbeatRefillRun(input) {
|
|
|
70
55
|
fence: input.fence,
|
|
71
56
|
});
|
|
72
57
|
}
|
|
73
|
-
export function yieldRefillRun(input) {
|
|
74
|
-
return postRefillRuns(input.workspaceId, {
|
|
75
|
-
action: "yield",
|
|
76
|
-
runId: input.runId,
|
|
77
|
-
fence: input.fence,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
58
|
export function advanceRefillRunGateRemote(input) {
|
|
81
59
|
return postRefillRuns(input.workspaceId, {
|
|
82
60
|
action: "advance-gate",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { appendIndexLine, appendJournalEvent, createRunJournal, renderBootstrapSection, renderCrashedAbandonedSection, renderExecutionEventSection, renderPlanSection, renderTerminalSection } from "./refill-journal.js";
|
|
2
|
-
import type { advanceRefillRunGateRemote, completeRefillRun, heartbeatRefillRun, recordRunOutcome, recordRunPlanned, refillRunStatus, startRefillRunRemote
|
|
3
|
-
import type { getPrepareCampaignMessagesStatus
|
|
2
|
+
import type { advanceRefillRunGateRemote, completeRefillRun, heartbeatRefillRun, recordRunOutcome, recordRunPlanned, refillRunStatus, startRefillRunRemote } from "./refill-run-client.js";
|
|
3
|
+
import type { getPrepareCampaignMessagesStatus } from "./tools/campaign-message-preparation.js";
|
|
4
4
|
import type { executeOneYoloPrimitive, executeStartCampaignPrimitive, prepareRowSelectorValue, refillPrepareRequestHash, refreshPaidInmailCreditsWithRetry } from "./tools/refill-executors.js";
|
|
5
5
|
export type RefillLoopGate = "g0_bootstrap" | "g1_plan" | "g2_execute" | "g3_verify" | "g4_terminal";
|
|
6
6
|
export interface RefillV2LoopInput {
|
|
@@ -13,12 +13,6 @@ export interface RefillV2LoopInput {
|
|
|
13
13
|
};
|
|
14
14
|
approvalMode?: "approve" | "mark_ready";
|
|
15
15
|
dryRun?: boolean;
|
|
16
|
-
targetDate?: string;
|
|
17
|
-
untilDate?: string;
|
|
18
|
-
horizonSendDays?: number;
|
|
19
|
-
scope?: Record<string, unknown>;
|
|
20
|
-
scopeHash?: string;
|
|
21
|
-
approval?: Record<string, unknown>;
|
|
22
16
|
}
|
|
23
17
|
export interface RefillV2LoopBudgets {
|
|
24
18
|
maxGateCyclesPerInvocation: number;
|
|
@@ -32,7 +26,6 @@ export interface RefillV2RunClient {
|
|
|
32
26
|
startRefillRunRemote: typeof startRefillRunRemote;
|
|
33
27
|
refillRunStatus: typeof refillRunStatus;
|
|
34
28
|
heartbeatRefillRun: typeof heartbeatRefillRun;
|
|
35
|
-
yieldRefillRun: typeof yieldRefillRun;
|
|
36
29
|
advanceRefillRunGateRemote: typeof advanceRefillRunGateRemote;
|
|
37
30
|
recordRunPlanned: typeof recordRunPlanned;
|
|
38
31
|
recordRunOutcome: typeof recordRunOutcome;
|
|
@@ -43,7 +36,6 @@ export interface RefillV2Executors {
|
|
|
43
36
|
executeStartCampaignPrimitive: typeof executeStartCampaignPrimitive;
|
|
44
37
|
refreshPaidInmailCreditsWithRetry: typeof refreshPaidInmailCreditsWithRetry;
|
|
45
38
|
getPrepareCampaignMessagesStatus?: typeof getPrepareCampaignMessagesStatus;
|
|
46
|
-
stopSatisfiedPrepareCampaignMessages?: typeof stopSatisfiedPrepareCampaignMessages;
|
|
47
39
|
refillPrepareRequestHash?: typeof refillPrepareRequestHash;
|
|
48
40
|
prepareRowSelectorValue?: typeof prepareRowSelectorValue;
|
|
49
41
|
}
|
|
@@ -69,10 +61,6 @@ export interface RefillV2LoopDeps {
|
|
|
69
61
|
senderIds?: string[];
|
|
70
62
|
runState?: Record<string, unknown>;
|
|
71
63
|
journal?: boolean;
|
|
72
|
-
targetDate?: string;
|
|
73
|
-
untilDate?: string;
|
|
74
|
-
horizonSendDays?: number;
|
|
75
|
-
scopeHash?: string;
|
|
76
64
|
}) => Promise<Record<string, unknown>>;
|
|
77
65
|
executors: RefillV2Executors;
|
|
78
66
|
journal: RefillV2JournalDeps;
|
package/dist/refill-run-loop.js
CHANGED
|
@@ -59,16 +59,6 @@ const SCHEDULER_RUN_NEXT_ACTIONS = new Set([
|
|
|
59
59
|
function isRecord(value) {
|
|
60
60
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
61
61
|
}
|
|
62
|
-
function planScopeInput(input) {
|
|
63
|
-
return {
|
|
64
|
-
...(input.targetDate ? { targetDate: input.targetDate } : {}),
|
|
65
|
-
...(input.untilDate ? { untilDate: input.untilDate } : {}),
|
|
66
|
-
...(input.horizonSendDays !== undefined
|
|
67
|
-
? { horizonSendDays: input.horizonSendDays }
|
|
68
|
-
: {}),
|
|
69
|
-
...(input.scopeHash ? { scopeHash: input.scopeHash } : {}),
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
62
|
function stringValue(value) {
|
|
73
63
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
74
64
|
}
|
|
@@ -266,8 +256,10 @@ function sanitizeSchedulerRunReceipt(raw) {
|
|
|
266
256
|
const prefilteredCells = numberValue(rawReceipt.prefilteredCells) ?? 0;
|
|
267
257
|
const tablesFilteredForSenderMismatch = numberValue(rawReceipt.tablesFilteredForSenderMismatch) ?? 0;
|
|
268
258
|
dominantSkipReason = dominantSchedulerRunSkipReason(skipReasons);
|
|
269
|
-
dominantPrefilterReason =
|
|
270
|
-
|
|
259
|
+
dominantPrefilterReason =
|
|
260
|
+
dominantSchedulerRunCountReason(prefilterReasons);
|
|
261
|
+
dominantDeferredReason =
|
|
262
|
+
dominantSchedulerRunSkipReason(deferredReasons);
|
|
271
263
|
recommendedNextAction = schedulerRunRecommendedAction({
|
|
272
264
|
rawAction: stringValue(rawReceipt.nextAction),
|
|
273
265
|
readyCellsFound,
|
|
@@ -361,17 +353,11 @@ function actionSenderId(action) {
|
|
|
361
353
|
}
|
|
362
354
|
function fingerprintFromPlan(plan) {
|
|
363
355
|
const packet = recordValue(plan.packet) ?? {};
|
|
364
|
-
const targetShapeRevision = stringValue(packet.targetShapeRevision) ??
|
|
365
|
-
stringValue(packet.targetRevision) ??
|
|
366
|
-
stringValue(plan.targetShapeRevision) ??
|
|
367
|
-
stringValue(plan.targetRevision);
|
|
368
356
|
return {
|
|
369
|
-
|
|
370
|
-
// active-campaign packets intentionally do not, so their immutable target
|
|
371
|
-
// shape is the durable planning revision for fencing and recovery.
|
|
372
|
-
planRevision: stringValue(plan.planRevision) ?? targetShapeRevision,
|
|
357
|
+
planRevision: stringValue(plan.planRevision),
|
|
373
358
|
stateRevision: stringValue(plan.stateRevision) ?? stringValue(packet.stateRevision),
|
|
374
|
-
targetShapeRevision
|
|
359
|
+
targetShapeRevision: stringValue(packet.targetShapeRevision) ??
|
|
360
|
+
stringValue(packet.targetRevision),
|
|
375
361
|
};
|
|
376
362
|
}
|
|
377
363
|
function fingerprintChanged(expected, actual) {
|
|
@@ -443,43 +429,6 @@ function normalizeDoneReason(value) {
|
|
|
443
429
|
function runStateProgress(ctx) {
|
|
444
430
|
return recordValue(ctx.runState.progress) ?? {};
|
|
445
431
|
}
|
|
446
|
-
function prepCircuitFrom(value) {
|
|
447
|
-
const root = recordValue(value);
|
|
448
|
-
const result = recordValue(root?.result);
|
|
449
|
-
const progress = recordValue(root?.progress);
|
|
450
|
-
return (recordValue(root?.circuit) ??
|
|
451
|
-
recordValue(result?.circuit) ??
|
|
452
|
-
recordValue(progress?.circuit) ??
|
|
453
|
-
null);
|
|
454
|
-
}
|
|
455
|
-
function openCircuitWaits(circuit, now) {
|
|
456
|
-
if (stringValue(circuit?.state) !== "open")
|
|
457
|
-
return false;
|
|
458
|
-
const nextProbeAt = stringValue(circuit?.nextProbeAt);
|
|
459
|
-
return Boolean(nextProbeAt && Date.parse(nextProbeAt) > now.getTime());
|
|
460
|
-
}
|
|
461
|
-
function activePreparationScopeSatisfied(plan, action) {
|
|
462
|
-
const packet = recordValue(plan.packet) ?? plan;
|
|
463
|
-
const target = recordValue(packet.target) ?? recordValue(plan.target) ?? {};
|
|
464
|
-
const senderId = actionSenderId(action);
|
|
465
|
-
const toolInput = actionToolInput(action);
|
|
466
|
-
const targetDate = stringValue(toolInput.targetDate);
|
|
467
|
-
const refillLaneKey = stringValue(toolInput.refillLaneKey);
|
|
468
|
-
const senderPlans = arrayValue(target.senderRefillPlans).filter(isRecord);
|
|
469
|
-
const ledgers = senderPlans
|
|
470
|
-
.filter((senderPlan) => !senderId || stringValue(senderPlan.senderId) === senderId)
|
|
471
|
-
.flatMap((senderPlan) => arrayValue(senderPlan.laneLedgers).filter(isRecord));
|
|
472
|
-
const matching = ledgers.filter((ledger) => (!senderId || stringValue(ledger.senderId) === senderId) &&
|
|
473
|
-
(!targetDate || stringValue(ledger.targetDate) === targetDate) &&
|
|
474
|
-
(!refillLaneKey || stringValue(ledger.refillLaneKey) === refillLaneKey));
|
|
475
|
-
return (matching.length > 0 &&
|
|
476
|
-
matching.every((ledger) => {
|
|
477
|
-
const checks = recordValue(ledger.identityChecks);
|
|
478
|
-
return (numberValue(ledger.initialAllocatablePrepDeficit) === 0 &&
|
|
479
|
-
checks != null &&
|
|
480
|
-
Object.values(checks).every((value) => value === true));
|
|
481
|
-
}));
|
|
482
|
-
}
|
|
483
432
|
function mergeProgress(ctx, updates) {
|
|
484
433
|
return {
|
|
485
434
|
...runStateProgress(ctx),
|
|
@@ -723,28 +672,14 @@ async function createJournal(input, deps, runId) {
|
|
|
723
672
|
}
|
|
724
673
|
async function startOrResume(input, deps) {
|
|
725
674
|
const initialRunState = buildRunStateFromLocalHints(input.workspaceId);
|
|
726
|
-
const scopedInitialRunState = input.scope
|
|
727
|
-
? {
|
|
728
|
-
...initialRunState,
|
|
729
|
-
scope: input.scope,
|
|
730
|
-
scopeHash: input.scopeHash,
|
|
731
|
-
approval: input.approval,
|
|
732
|
-
}
|
|
733
|
-
: initialRunState;
|
|
734
675
|
const started = await deps.runClient.startRefillRunRemote({
|
|
735
676
|
workspaceId: input.workspaceId,
|
|
736
|
-
config:
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
: {
|
|
743
|
-
intent: input.intent ?? "auto",
|
|
744
|
-
senderIds: input.senderIds,
|
|
745
|
-
approvalMode: input.approvalMode ?? "approve",
|
|
746
|
-
},
|
|
747
|
-
runState: scopedInitialRunState,
|
|
677
|
+
config: {
|
|
678
|
+
intent: input.intent ?? "auto",
|
|
679
|
+
senderIds: input.senderIds,
|
|
680
|
+
approvalMode: input.approvalMode ?? "approve",
|
|
681
|
+
},
|
|
682
|
+
runState: initialRunState,
|
|
748
683
|
resume: input.resume,
|
|
749
684
|
});
|
|
750
685
|
if (isLeaseLost(started)) {
|
|
@@ -777,7 +712,7 @@ async function startOrResume(input, deps) {
|
|
|
777
712
|
const gate = (stringValue(result.gate) ?? "g0_bootstrap");
|
|
778
713
|
const gateSeq = numberValue(result.gateSeq) ?? 0;
|
|
779
714
|
const runState = recordValue(result.runState) ??
|
|
780
|
-
recordValue(
|
|
715
|
+
recordValue(initialRunState) ??
|
|
781
716
|
{
|
|
782
717
|
version: 1,
|
|
783
718
|
senderCursors: [],
|
|
@@ -820,7 +755,6 @@ async function gateBootstrap(input, deps, ctx) {
|
|
|
820
755
|
senderIds: input.senderIds,
|
|
821
756
|
runState: ctx.runState,
|
|
822
757
|
journal: false,
|
|
823
|
-
...planScopeInput(input),
|
|
824
758
|
});
|
|
825
759
|
const paidCredit = arrayValue(recordValue(plan.bootstrap)?.paidCredit).filter(isRecord);
|
|
826
760
|
const refreshedSenderIds = new Set(arrayValue(recordValue(ctx.runState.creditTrust)?.senderIds)
|
|
@@ -967,7 +901,6 @@ async function gatePlan(input, deps, ctx) {
|
|
|
967
901
|
senderIds: input.senderIds,
|
|
968
902
|
runState: ctx.runState,
|
|
969
903
|
journal: false,
|
|
970
|
-
...planScopeInput(input),
|
|
971
904
|
});
|
|
972
905
|
if (plan.blocker === "workspace_access") {
|
|
973
906
|
return {
|
|
@@ -1027,17 +960,6 @@ async function gatePlan(input, deps, ctx) {
|
|
|
1027
960
|
fallbackSummary: line.fallbackSummary,
|
|
1028
961
|
}));
|
|
1029
962
|
const fingerprint = fingerprintFromPlan(plan);
|
|
1030
|
-
const persistedCircuit = recordValue(runStateProgress(ctx).prepCircuit);
|
|
1031
|
-
if (stringValue(action.type) === "prepare_messages" &&
|
|
1032
|
-
openCircuitWaits(persistedCircuit, deps.now?.() ?? new Date())) {
|
|
1033
|
-
const heartbeat = await heartbeatAndContinue(input, deps, ctx);
|
|
1034
|
-
if (heartbeat.status !== "in_progress")
|
|
1035
|
-
return heartbeat;
|
|
1036
|
-
return {
|
|
1037
|
-
...heartbeat,
|
|
1038
|
-
guidance: `Preparation circuit remains open until ${String(persistedCircuit?.nextProbeAt)}; re-invoke with this handle after the probe deadline.`,
|
|
1039
|
-
};
|
|
1040
|
-
}
|
|
1041
963
|
const noProgress = nextNoProgressState(ctx, plan, action);
|
|
1042
964
|
if (noProgress.repeatCount >= 3) {
|
|
1043
965
|
return completeTerminal(input, deps, ctx, "blocked", {
|
|
@@ -1048,17 +970,10 @@ async function gatePlan(input, deps, ctx) {
|
|
|
1048
970
|
guidance: "The same refill rung repeated three times with no coverage, frontier, or lane movement.",
|
|
1049
971
|
});
|
|
1050
972
|
}
|
|
1051
|
-
const circuitProgress = stringValue(action.type) === "prepare_messages" &&
|
|
1052
|
-
stringValue(persistedCircuit?.state) === "open"
|
|
1053
|
-
? { ...persistedCircuit, state: "half_open" }
|
|
1054
|
-
: persistedCircuit;
|
|
1055
973
|
const nextRunState = mergeRunState(ctx.runState, {
|
|
1056
974
|
lastPlan: fingerprint,
|
|
1057
975
|
headAction: action,
|
|
1058
|
-
progress: mergeProgress(ctx, {
|
|
1059
|
-
noProgress,
|
|
1060
|
-
...(circuitProgress ? { prepCircuit: circuitProgress } : {}),
|
|
1061
|
-
}),
|
|
976
|
+
progress: mergeProgress(ctx, { noProgress }),
|
|
1062
977
|
});
|
|
1063
978
|
const advanced = await deps.runClient.advanceRefillRunGateRemote({
|
|
1064
979
|
workspaceId: input.workspaceId,
|
|
@@ -1095,7 +1010,6 @@ async function verifyRecoveryPoint(input, deps, ctx) {
|
|
|
1095
1010
|
senderIds: input.senderIds,
|
|
1096
1011
|
runState: ctx.runState,
|
|
1097
1012
|
journal: false,
|
|
1098
|
-
...planScopeInput(input),
|
|
1099
1013
|
});
|
|
1100
1014
|
const changed = fingerprintChanged(expected, fingerprintFromPlan(fresh));
|
|
1101
1015
|
if (changed.length > 0) {
|
|
@@ -1165,9 +1079,6 @@ async function gateExecute(input, deps, ctx) {
|
|
|
1165
1079
|
dispatchKey: stringValue(action.type),
|
|
1166
1080
|
evergreenRung: stringValue(action.evergreenRung),
|
|
1167
1081
|
sideEffectClass: stringValue(action.sideEffectClass),
|
|
1168
|
-
scopeHash: input.scopeHash ?? null,
|
|
1169
|
-
expectedTargetsHash: stringValue(input.scope?.expectedTargetsHash) ?? null,
|
|
1170
|
-
dateSelector: recordValue(input.scope?.dateSelector),
|
|
1171
1082
|
};
|
|
1172
1083
|
const plannedResult = await deps.runClient.recordRunPlanned({
|
|
1173
1084
|
workspaceId: input.workspaceId,
|
|
@@ -1261,12 +1172,6 @@ async function advanceBackToPlan(input, deps, ctx, runStateUpdates = {}) {
|
|
|
1261
1172
|
async function verifyPrepareAction(input, deps, ctx, action, budgets) {
|
|
1262
1173
|
const getStatus = deps.executors.getPrepareCampaignMessagesStatus;
|
|
1263
1174
|
const jobId = activeJobIdFromOutcome(ctx.runState.lastOutcome);
|
|
1264
|
-
const executionCircuit = prepCircuitFrom(ctx.runState.lastOutcome);
|
|
1265
|
-
if (!jobId && executionCircuit) {
|
|
1266
|
-
return advanceBackToPlan(input, deps, ctx, {
|
|
1267
|
-
progress: mergeProgress(ctx, { prepCircuit: executionCircuit }),
|
|
1268
|
-
});
|
|
1269
|
-
}
|
|
1270
1175
|
if (!getStatus || !jobId) {
|
|
1271
1176
|
return {
|
|
1272
1177
|
status: "in_progress",
|
|
@@ -1306,58 +1211,6 @@ async function verifyPrepareAction(input, deps, ctx, action, budgets) {
|
|
|
1306
1211
|
}),
|
|
1307
1212
|
});
|
|
1308
1213
|
}
|
|
1309
|
-
if (ownJob &&
|
|
1310
|
-
!isTerminalJobStatus(latestStatus) &&
|
|
1311
|
-
deps.executors.stopSatisfiedPrepareCampaignMessages) {
|
|
1312
|
-
const fresh = await deps.readPlan({
|
|
1313
|
-
workspaceId: input.workspaceId,
|
|
1314
|
-
intent: input.intent,
|
|
1315
|
-
senderIds: input.senderIds,
|
|
1316
|
-
runState: ctx.runState,
|
|
1317
|
-
journal: false,
|
|
1318
|
-
...planScopeInput(input),
|
|
1319
|
-
});
|
|
1320
|
-
ctx.plan = fresh;
|
|
1321
|
-
if (activePreparationScopeSatisfied(fresh, action)) {
|
|
1322
|
-
const plannedStop = await deps.runClient.recordRunPlanned({
|
|
1323
|
-
workspaceId: input.workspaceId,
|
|
1324
|
-
runId: ctx.runId,
|
|
1325
|
-
fence: ctx.fence,
|
|
1326
|
-
gate: ctx.gate,
|
|
1327
|
-
gateSeq: ctx.gateSeq,
|
|
1328
|
-
planned: {
|
|
1329
|
-
toolName: "stop_satisfied_campaign_message_preparation",
|
|
1330
|
-
toolInput: { jobId },
|
|
1331
|
-
dispatchKey: `stop_satisfied:${jobId}`,
|
|
1332
|
-
sideEffectClass: "message_preparation_stop",
|
|
1333
|
-
scopeHash: input.scopeHash ?? null,
|
|
1334
|
-
},
|
|
1335
|
-
});
|
|
1336
|
-
if (isLeaseLost(plannedStop))
|
|
1337
|
-
return leaseLostResult(ctx);
|
|
1338
|
-
const stopEventId = stringValue(recordValue(plannedStop)?.eventId) ??
|
|
1339
|
-
`${ctx.runId}:${ctx.gateSeq}:stop`;
|
|
1340
|
-
const stopReceipt = await deps.executors.stopSatisfiedPrepareCampaignMessages({
|
|
1341
|
-
workspaceId: input.workspaceId,
|
|
1342
|
-
jobId,
|
|
1343
|
-
expectedUpdatedAt: stringValue(statusRecord.updatedAt) ?? undefined,
|
|
1344
|
-
});
|
|
1345
|
-
await deps.runClient.recordRunOutcome({
|
|
1346
|
-
workspaceId: input.workspaceId,
|
|
1347
|
-
runId: ctx.runId,
|
|
1348
|
-
fence: ctx.fence,
|
|
1349
|
-
eventId: stopEventId,
|
|
1350
|
-
did: { jobId },
|
|
1351
|
-
outcome: stopReceipt,
|
|
1352
|
-
});
|
|
1353
|
-
return advanceBackToPlan(input, deps, ctx, {
|
|
1354
|
-
progress: mergeProgress(ctx, {
|
|
1355
|
-
prepStopReceipt: stopReceipt,
|
|
1356
|
-
prepStoppedAt: (deps.now?.() ?? new Date()).toISOString(),
|
|
1357
|
-
}),
|
|
1358
|
-
});
|
|
1359
|
-
}
|
|
1360
|
-
}
|
|
1361
1214
|
if (isTerminalJobStatus(latestStatus)) {
|
|
1362
1215
|
const preparedCount = preparedCountFromStatus(latestStatus);
|
|
1363
1216
|
const checkedRows = checkedRowsFromStatus(latestStatus);
|
|
@@ -1425,7 +1278,6 @@ async function verifyReadOnlyWait(input, deps, ctx, budgets, waitKind) {
|
|
|
1425
1278
|
senderIds: input.senderIds,
|
|
1426
1279
|
runState: ctx.runState,
|
|
1427
1280
|
journal: false,
|
|
1428
|
-
...planScopeInput(input),
|
|
1429
1281
|
});
|
|
1430
1282
|
ctx.plan = fresh;
|
|
1431
1283
|
const doneReason = doneReasonFromPlan(fresh);
|
|
@@ -1508,7 +1360,6 @@ async function verifySchedulerWait(input, deps, ctx, action, budgets) {
|
|
|
1508
1360
|
senderIds: input.senderIds,
|
|
1509
1361
|
runState: ctx.runState,
|
|
1510
1362
|
journal: false,
|
|
1511
|
-
...planScopeInput(input),
|
|
1512
1363
|
});
|
|
1513
1364
|
ctx.plan = fresh;
|
|
1514
1365
|
const doneReason = normalizeDoneReason(doneReasonFromPlan(fresh));
|
|
@@ -1571,7 +1422,6 @@ async function gateVerify(input, deps, ctx, budgets) {
|
|
|
1571
1422
|
senderIds: input.senderIds,
|
|
1572
1423
|
runState: ctx.runState,
|
|
1573
1424
|
journal: false,
|
|
1574
|
-
...planScopeInput(input),
|
|
1575
1425
|
});
|
|
1576
1426
|
ctx.plan = fresh;
|
|
1577
1427
|
const doneReason = doneReasonFromPlan(fresh);
|
|
@@ -1624,19 +1474,19 @@ function classifyCaughtError(error, ctx) {
|
|
|
1624
1474
|
};
|
|
1625
1475
|
}
|
|
1626
1476
|
async function heartbeatAndContinue(input, deps, ctx) {
|
|
1627
|
-
const
|
|
1477
|
+
const heartbeat = await deps.runClient.heartbeatRefillRun({
|
|
1628
1478
|
workspaceId: input.workspaceId,
|
|
1629
1479
|
runId: ctx.runId,
|
|
1630
1480
|
fence: ctx.fence,
|
|
1631
1481
|
});
|
|
1632
|
-
if (isLeaseLost(
|
|
1482
|
+
if (isLeaseLost(heartbeat))
|
|
1633
1483
|
return leaseLostResult(ctx);
|
|
1634
1484
|
return {
|
|
1635
1485
|
status: "in_progress",
|
|
1636
1486
|
runId: ctx.runId,
|
|
1637
1487
|
fence: ctx.fence,
|
|
1638
1488
|
gate: ctx.gate,
|
|
1639
|
-
guidance: "Per-invocation gate budget reached. Re-invoke
|
|
1489
|
+
guidance: "Per-invocation gate budget reached. Re-invoke refill_sends_v2 with this runId/fence to continue.",
|
|
1640
1490
|
journalPath: ctx.journalPath,
|
|
1641
1491
|
};
|
|
1642
1492
|
}
|
|
@@ -1650,7 +1500,6 @@ export async function runRefillV2Loop(input, deps) {
|
|
|
1650
1500
|
intent: input.intent,
|
|
1651
1501
|
senderIds: input.senderIds,
|
|
1652
1502
|
journal: true,
|
|
1653
|
-
...planScopeInput(input),
|
|
1654
1503
|
});
|
|
1655
1504
|
return { status: "dry_run", plan };
|
|
1656
1505
|
}
|
|
@@ -36,16 +36,9 @@ type StartPrepareMessagesInput = PrepareMessagesBaseInput & {
|
|
|
36
36
|
requestSource?: string;
|
|
37
37
|
senderId?: string;
|
|
38
38
|
actionType?: string;
|
|
39
|
-
targetDate?: string;
|
|
40
|
-
refillLaneKey?: string;
|
|
41
|
-
sourceEpoch?: string;
|
|
42
39
|
};
|
|
43
40
|
type StatusPrepareMessagesInput = PrepareMessagesBaseInput;
|
|
44
41
|
type CancelPrepareMessagesInput = PrepareMessagesBaseInput;
|
|
45
|
-
type StopSatisfiedPrepareMessagesInput = PrepareMessagesBaseInput & {
|
|
46
|
-
jobId: string;
|
|
47
|
-
expectedUpdatedAt?: string;
|
|
48
|
-
};
|
|
49
42
|
export declare const campaignMessagePreparationToolDefinitions: ({
|
|
50
43
|
name: string;
|
|
51
44
|
description: string;
|
|
@@ -124,18 +117,6 @@ export declare const campaignMessagePreparationToolDefinitions: ({
|
|
|
124
117
|
enum: string[];
|
|
125
118
|
description: string;
|
|
126
119
|
};
|
|
127
|
-
targetDate: {
|
|
128
|
-
type: string;
|
|
129
|
-
description: string;
|
|
130
|
-
};
|
|
131
|
-
refillLaneKey: {
|
|
132
|
-
type: string;
|
|
133
|
-
description: string;
|
|
134
|
-
};
|
|
135
|
-
sourceEpoch: {
|
|
136
|
-
type: string;
|
|
137
|
-
description: string;
|
|
138
|
-
};
|
|
139
120
|
disableLowPassRateStop: {
|
|
140
121
|
type: string;
|
|
141
122
|
description: string;
|
|
@@ -145,7 +126,6 @@ export declare const campaignMessagePreparationToolDefinitions: ({
|
|
|
145
126
|
description: string;
|
|
146
127
|
};
|
|
147
128
|
jobId?: undefined;
|
|
148
|
-
expectedUpdatedAt?: undefined;
|
|
149
129
|
};
|
|
150
130
|
required: string[];
|
|
151
131
|
additionalProperties: boolean;
|
|
@@ -180,55 +160,13 @@ export declare const campaignMessagePreparationToolDefinitions: ({
|
|
|
180
160
|
autoContinue?: undefined;
|
|
181
161
|
senderId?: undefined;
|
|
182
162
|
actionType?: undefined;
|
|
183
|
-
targetDate?: undefined;
|
|
184
|
-
refillLaneKey?: undefined;
|
|
185
|
-
sourceEpoch?: undefined;
|
|
186
163
|
disableLowPassRateStop?: undefined;
|
|
187
|
-
expectedUpdatedAt?: undefined;
|
|
188
164
|
};
|
|
189
165
|
additionalProperties: boolean;
|
|
190
166
|
required?: undefined;
|
|
191
167
|
};
|
|
192
|
-
} | {
|
|
193
|
-
name: string;
|
|
194
|
-
description: string;
|
|
195
|
-
inputSchema: {
|
|
196
|
-
type: string;
|
|
197
|
-
properties: {
|
|
198
|
-
jobId: {
|
|
199
|
-
type: string;
|
|
200
|
-
};
|
|
201
|
-
expectedUpdatedAt: {
|
|
202
|
-
type: string;
|
|
203
|
-
description: string;
|
|
204
|
-
};
|
|
205
|
-
workspaceId: {
|
|
206
|
-
type: string;
|
|
207
|
-
description?: undefined;
|
|
208
|
-
};
|
|
209
|
-
campaignId?: undefined;
|
|
210
|
-
tableId?: undefined;
|
|
211
|
-
targetPreparedMessages?: undefined;
|
|
212
|
-
maxRowsToCheck?: undefined;
|
|
213
|
-
batchSize?: undefined;
|
|
214
|
-
maxBatchRows?: undefined;
|
|
215
|
-
approvalMode?: undefined;
|
|
216
|
-
rowSelector?: undefined;
|
|
217
|
-
excludeRowIds?: undefined;
|
|
218
|
-
autoContinue?: undefined;
|
|
219
|
-
senderId?: undefined;
|
|
220
|
-
actionType?: undefined;
|
|
221
|
-
targetDate?: undefined;
|
|
222
|
-
refillLaneKey?: undefined;
|
|
223
|
-
sourceEpoch?: undefined;
|
|
224
|
-
disableLowPassRateStop?: undefined;
|
|
225
|
-
};
|
|
226
|
-
required: string[];
|
|
227
|
-
additionalProperties: boolean;
|
|
228
|
-
};
|
|
229
168
|
})[];
|
|
230
169
|
export declare function startPrepareCampaignMessages(input: StartPrepareMessagesInput): Promise<unknown>;
|
|
231
170
|
export declare function getPrepareCampaignMessagesStatus(input: StatusPrepareMessagesInput): Promise<unknown>;
|
|
232
171
|
export declare function cancelPrepareCampaignMessages(input: CancelPrepareMessagesInput): Promise<unknown>;
|
|
233
|
-
export declare function stopSatisfiedPrepareCampaignMessages(input: StopSatisfiedPrepareMessagesInput): Promise<unknown>;
|
|
234
172
|
export {};
|
|
@@ -84,18 +84,6 @@ export const campaignMessagePreparationToolDefinitions = [
|
|
|
84
84
|
],
|
|
85
85
|
description: "Optional refill-scope send action. InMail scopes treat open and paid InMail as one contact-reuse family.",
|
|
86
86
|
},
|
|
87
|
-
targetDate: {
|
|
88
|
-
type: "string",
|
|
89
|
-
description: "Exact sender-local YYYY-MM-DD refill target date.",
|
|
90
|
-
},
|
|
91
|
-
refillLaneKey: {
|
|
92
|
-
type: "string",
|
|
93
|
-
description: "Normalized refill lane identity from the canonical target plan.",
|
|
94
|
-
},
|
|
95
|
-
sourceEpoch: {
|
|
96
|
-
type: "string",
|
|
97
|
-
description: "Stable source/provider epoch; only a material epoch change resets zero-yield recurrence.",
|
|
98
|
-
},
|
|
99
87
|
disableLowPassRateStop: {
|
|
100
88
|
type: "boolean",
|
|
101
89
|
description: "Operator override for explicit fill/exhaust requests. When true, keep processing eligible rows even if the enriched sample pass rate is low. Still bounded by targetPreparedMessages and maxRowsToCheck.",
|
|
@@ -123,23 +111,6 @@ export const campaignMessagePreparationToolDefinitions = [
|
|
|
123
111
|
additionalProperties: false,
|
|
124
112
|
},
|
|
125
113
|
},
|
|
126
|
-
{
|
|
127
|
-
name: "stop_satisfied_campaign_message_preparation",
|
|
128
|
-
description: "Cooperatively stop exactly one preparation job after the server rereads its persisted refill scope and proves its allocatable preparation deficit is zero. This never cancels table-wide workflow cells.",
|
|
129
|
-
inputSchema: {
|
|
130
|
-
type: "object",
|
|
131
|
-
properties: {
|
|
132
|
-
jobId: { type: "string" },
|
|
133
|
-
expectedUpdatedAt: {
|
|
134
|
-
type: "string",
|
|
135
|
-
description: "Optional optimistic job updatedAt revision from status.",
|
|
136
|
-
},
|
|
137
|
-
workspaceId: { type: "string" },
|
|
138
|
-
},
|
|
139
|
-
required: ["jobId"],
|
|
140
|
-
additionalProperties: false,
|
|
141
|
-
},
|
|
142
|
-
},
|
|
143
114
|
{
|
|
144
115
|
name: "cancel_campaign_message_preparation",
|
|
145
116
|
description: "Cancel an active campaign message preparation job and cancel the same pending workflow-table cells that the UI Cancel Pending Cells button would cancel. Launch remains a separate explicit start_campaign step.",
|
|
@@ -174,9 +145,6 @@ export function startPrepareCampaignMessages(input) {
|
|
|
174
145
|
requestSource: input.requestSource,
|
|
175
146
|
senderId: input.senderId,
|
|
176
147
|
actionType: input.actionType,
|
|
177
|
-
targetDate: input.targetDate,
|
|
178
|
-
refillLaneKey: input.refillLaneKey,
|
|
179
|
-
sourceEpoch: input.sourceEpoch,
|
|
180
148
|
...(workspaceId ? { workspaceId } : {}),
|
|
181
149
|
}, workspaceId ?? undefined);
|
|
182
150
|
}
|
|
@@ -200,12 +168,3 @@ export function cancelPrepareCampaignMessages(input) {
|
|
|
200
168
|
...(workspaceId ? { workspaceId } : {}),
|
|
201
169
|
}, workspaceId ?? undefined);
|
|
202
170
|
}
|
|
203
|
-
export function stopSatisfiedPrepareCampaignMessages(input) {
|
|
204
|
-
const workspaceId = normalizeExplicitWorkspaceId(input.workspaceId);
|
|
205
|
-
return postPrepareMessages({
|
|
206
|
-
action: "stop_if_target_satisfied",
|
|
207
|
-
jobId: input.jobId,
|
|
208
|
-
expectedUpdatedAt: input.expectedUpdatedAt,
|
|
209
|
-
...(workspaceId ? { workspaceId } : {}),
|
|
210
|
-
}, workspaceId ?? undefined);
|
|
211
|
-
}
|
|
@@ -2,9 +2,6 @@ type GetRefillPlanV2Input = {
|
|
|
2
2
|
workspaceId?: string;
|
|
3
3
|
intent?: "auto" | "evergreen" | "plain" | "active";
|
|
4
4
|
senderIds?: string[];
|
|
5
|
-
horizonSendDays?: number;
|
|
6
|
-
untilDate?: string;
|
|
7
|
-
targetDate?: string;
|
|
8
5
|
runState?: Record<string, unknown>;
|
|
9
6
|
journal?: boolean;
|
|
10
7
|
journalNote?: string;
|
|
@@ -2,7 +2,6 @@ import * as path from "node:path";
|
|
|
2
2
|
import { getApi, SellableApiError } from "../api.js";
|
|
3
3
|
import { appendIndexLine, appendJournalEvent, createRunJournal, renderBootstrapSection, renderPlanSection, renderTerminalSection, } from "../refill-journal.js";
|
|
4
4
|
import { readRefillWorkspaceState } from "../refill-local-state.js";
|
|
5
|
-
import { getRefillTargetPlan } from "./refill-target-plan.js";
|
|
6
5
|
import { normalizeExplicitWorkspaceId, workspaceRequestOptions, } from "./workspace-context.js";
|
|
7
6
|
const KNOWN_TOP_LEVEL_FIELDS = [
|
|
8
7
|
"readOnly",
|
|
@@ -200,24 +199,12 @@ export async function getRefillPlanV2(input) {
|
|
|
200
199
|
: buildRunStateFromLocalHints(workspaceId);
|
|
201
200
|
let raw;
|
|
202
201
|
try {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
input.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
intent: input.intent === "auto" ? undefined : (input.intent ?? undefined),
|
|
210
|
-
senderIds: input.senderIds,
|
|
211
|
-
targetDate: input.targetDate,
|
|
212
|
-
untilDate: input.untilDate,
|
|
213
|
-
horizonSendDays: input.horizonSendDays,
|
|
214
|
-
})
|
|
215
|
-
: await postRefillPlanV2({
|
|
216
|
-
workspaceId,
|
|
217
|
-
intent: input.intent ?? "auto",
|
|
218
|
-
senderIds: input.senderIds,
|
|
219
|
-
runState,
|
|
220
|
-
}, workspaceId);
|
|
202
|
+
raw = await postRefillPlanV2({
|
|
203
|
+
workspaceId,
|
|
204
|
+
intent: input.intent ?? "auto",
|
|
205
|
+
senderIds: input.senderIds,
|
|
206
|
+
runState,
|
|
207
|
+
}, workspaceId);
|
|
221
208
|
}
|
|
222
209
|
catch (error) {
|
|
223
210
|
if (!isWorkspaceAccessError(error))
|
|
@@ -251,16 +238,7 @@ export async function getRefillPlanV2(input) {
|
|
|
251
238
|
workspaceResolution: "explicit",
|
|
252
239
|
};
|
|
253
240
|
}
|
|
254
|
-
const
|
|
255
|
-
const target = isRecord(rawRecord.target) ? rawRecord.target : null;
|
|
256
|
-
const sanitized = sanitizeEvergreenRefillPlanResult(target
|
|
257
|
-
? {
|
|
258
|
-
...rawRecord,
|
|
259
|
-
plans: target.senderRefillPlans,
|
|
260
|
-
globalActionQueue: target.globalActionQueue,
|
|
261
|
-
packet: rawRecord,
|
|
262
|
-
}
|
|
263
|
-
: rawRecord);
|
|
241
|
+
const sanitized = sanitizeEvergreenRefillPlanResult(raw);
|
|
264
242
|
const warnings = Array.isArray(sanitized.warnings)
|
|
265
243
|
? [...sanitized.warnings]
|
|
266
244
|
: [];
|