@sellable/install 0.1.312 → 0.1.314
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/lib/runtime-verify.mjs
CHANGED
|
@@ -45,6 +45,14 @@ export const REQUIRED_SELLABLE_MCP_TOOLS = [
|
|
|
45
45
|
|
|
46
46
|
export const FORBIDDEN_SELLABLE_MCP_TOOLS = ["refill_campaign_sends"];
|
|
47
47
|
|
|
48
|
+
const CONNECTION_ONLY_EVERGREEN_PROMPT_CHUNK_LIMIT = 48_000;
|
|
49
|
+
const CONNECTION_ONLY_EVERGREEN_MAX_PROMPT_CHUNKS = 8;
|
|
50
|
+
const CONNECTION_ONLY_EVERGREEN_PROOF_NEEDLES = {
|
|
51
|
+
campaignSequenceOptions: 'campaignSequenceOptions:{ mode:"connection_only" }',
|
|
52
|
+
templateRef: 'templateRef:"connection_only"',
|
|
53
|
+
sendInviteReceipt: 'sequenceReceipt.actionTypes:["send_invite"]',
|
|
54
|
+
};
|
|
55
|
+
|
|
48
56
|
export const CREATE_CAMPAIGN_SMOKE_CALLS = [
|
|
49
57
|
{
|
|
50
58
|
name: "get_auth_status",
|
|
@@ -89,7 +97,7 @@ export const CREATE_CAMPAIGN_SMOKE_CALLS = [
|
|
|
89
97
|
arguments: {
|
|
90
98
|
subskillName: "create-evergreen-campaigns",
|
|
91
99
|
offset: 0,
|
|
92
|
-
limit:
|
|
100
|
+
limit: CONNECTION_ONLY_EVERGREEN_PROMPT_CHUNK_LIMIT,
|
|
93
101
|
},
|
|
94
102
|
},
|
|
95
103
|
{
|
|
@@ -195,6 +203,43 @@ function parseJsonText(text) {
|
|
|
195
203
|
}
|
|
196
204
|
}
|
|
197
205
|
|
|
206
|
+
function emptyConnectionOnlyEvergreenProofs() {
|
|
207
|
+
return Object.fromEntries(
|
|
208
|
+
Object.keys(CONNECTION_ONLY_EVERGREEN_PROOF_NEEDLES).map((key) => [
|
|
209
|
+
key,
|
|
210
|
+
false,
|
|
211
|
+
])
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function getConnectionOnlyEvergreenProofs(prompt) {
|
|
216
|
+
return Object.fromEntries(
|
|
217
|
+
Object.entries(CONNECTION_ONLY_EVERGREEN_PROOF_NEEDLES).map(
|
|
218
|
+
([key, needle]) => [key, prompt.includes(needle)]
|
|
219
|
+
)
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function mergeConnectionOnlyEvergreenProofs(target, source) {
|
|
224
|
+
if (!source) return target;
|
|
225
|
+
for (const key of Object.keys(CONNECTION_ONLY_EVERGREEN_PROOF_NEEDLES)) {
|
|
226
|
+
target[key] = target[key] === true || source[key] === true;
|
|
227
|
+
}
|
|
228
|
+
return target;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function summarizeConnectionOnlyEvergreenProofs(proofs) {
|
|
232
|
+
const merged = { ...emptyConnectionOnlyEvergreenProofs(), ...(proofs || {}) };
|
|
233
|
+
const missing = Object.keys(CONNECTION_ONLY_EVERGREEN_PROOF_NEEDLES).filter(
|
|
234
|
+
(key) => merged[key] !== true
|
|
235
|
+
);
|
|
236
|
+
return {
|
|
237
|
+
ok: missing.length === 0,
|
|
238
|
+
proofs: merged,
|
|
239
|
+
missing,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
198
243
|
function summarizeToolResult(name, result) {
|
|
199
244
|
const text = redact(textFromToolResult(result));
|
|
200
245
|
const parsed = parseJsonText(text);
|
|
@@ -239,15 +284,24 @@ function summarizeToolResult(name, result) {
|
|
|
239
284
|
|
|
240
285
|
if (name === "get_subskill_prompt" && parsed) {
|
|
241
286
|
const prompt = typeof parsed.prompt === "string" ? parsed.prompt : "";
|
|
287
|
+
const connectionOnlyEvergreenProofs =
|
|
288
|
+
parsed.name === "create-evergreen-campaigns"
|
|
289
|
+
? getConnectionOnlyEvergreenProofs(prompt)
|
|
290
|
+
: null;
|
|
242
291
|
return {
|
|
243
292
|
...summary,
|
|
244
293
|
subskillName: parsed.name || null,
|
|
245
294
|
promptChars: prompt.length,
|
|
295
|
+
promptLength:
|
|
296
|
+
typeof parsed.promptLength === "number" ? parsed.promptLength : null,
|
|
297
|
+
offset: typeof parsed.offset === "number" ? parsed.offset : null,
|
|
298
|
+
limit: typeof parsed.limit === "number" ? parsed.limit : null,
|
|
299
|
+
connectionOnlyEvergreenProofs,
|
|
246
300
|
connectionOnlyEvergreenGuidance:
|
|
247
301
|
parsed.name === "create-evergreen-campaigns"
|
|
248
|
-
?
|
|
249
|
-
|
|
250
|
-
|
|
302
|
+
? summarizeConnectionOnlyEvergreenProofs(
|
|
303
|
+
connectionOnlyEvergreenProofs
|
|
304
|
+
).ok
|
|
251
305
|
: null,
|
|
252
306
|
hasMore: parsed.hasMore === true,
|
|
253
307
|
nextOffset:
|
|
@@ -282,6 +336,7 @@ async function verifyCreateCampaignSmoke({
|
|
|
282
336
|
.map((call) => call.name)
|
|
283
337
|
.filter((name) => !available.has(name));
|
|
284
338
|
const calls = [];
|
|
339
|
+
const connectionOnlyEvergreenProofs = emptyConnectionOnlyEvergreenProofs();
|
|
285
340
|
|
|
286
341
|
if (missingTools.length > 0) {
|
|
287
342
|
return {
|
|
@@ -295,76 +350,158 @@ async function verifyCreateCampaignSmoke({
|
|
|
295
350
|
}
|
|
296
351
|
|
|
297
352
|
for (const call of smokeCalls) {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
353
|
+
let nextCall = call;
|
|
354
|
+
let evergreenPromptChunks = 0;
|
|
355
|
+
const evergreenPromptOffsets = new Set();
|
|
356
|
+
|
|
357
|
+
while (nextCall) {
|
|
358
|
+
const callStartedAt = new Date().toISOString();
|
|
359
|
+
try {
|
|
360
|
+
const result = await client.callTool(
|
|
361
|
+
{ name: nextCall.name, arguments: nextCall.arguments },
|
|
362
|
+
undefined,
|
|
363
|
+
{
|
|
364
|
+
timeout: timeoutMs,
|
|
365
|
+
maxTotalTimeout: timeoutMs,
|
|
366
|
+
}
|
|
367
|
+
);
|
|
368
|
+
const summary = summarizeToolResult(nextCall.name, result);
|
|
369
|
+
calls.push({
|
|
370
|
+
name: nextCall.name,
|
|
371
|
+
arguments: nextCall.arguments,
|
|
372
|
+
ok: summary.isError !== true,
|
|
373
|
+
summary,
|
|
374
|
+
startedAt: callStartedAt,
|
|
375
|
+
completedAt: new Date().toISOString(),
|
|
376
|
+
});
|
|
377
|
+
if (summary.isError === true) {
|
|
378
|
+
return {
|
|
379
|
+
ok: false,
|
|
380
|
+
missingTools: [],
|
|
381
|
+
calls,
|
|
382
|
+
error: `${nextCall.name} returned an MCP tool error`,
|
|
383
|
+
startedAt,
|
|
384
|
+
completedAt: new Date().toISOString(),
|
|
385
|
+
};
|
|
306
386
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
387
|
+
|
|
388
|
+
const isConnectionOnlyEvergreenPrompt =
|
|
389
|
+
nextCall.name === "get_subskill_prompt" &&
|
|
390
|
+
nextCall.arguments?.subskillName === "create-evergreen-campaigns";
|
|
391
|
+
if (!isConnectionOnlyEvergreenPrompt) {
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
evergreenPromptChunks += 1;
|
|
396
|
+
evergreenPromptOffsets.add(nextCall.arguments?.offset ?? 0);
|
|
397
|
+
mergeConnectionOnlyEvergreenProofs(
|
|
398
|
+
connectionOnlyEvergreenProofs,
|
|
399
|
+
summary.connectionOnlyEvergreenProofs
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
if (summary.hasMore !== true) {
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
if (typeof summary.nextOffset !== "number") {
|
|
406
|
+
return {
|
|
407
|
+
ok: false,
|
|
408
|
+
missingTools: [],
|
|
409
|
+
calls,
|
|
410
|
+
connectionOnlyEvergreenGuidance:
|
|
411
|
+
summarizeConnectionOnlyEvergreenProofs(
|
|
412
|
+
connectionOnlyEvergreenProofs
|
|
413
|
+
),
|
|
414
|
+
error:
|
|
415
|
+
"create-evergreen-campaigns prompt chunk is missing nextOffset",
|
|
416
|
+
startedAt,
|
|
417
|
+
completedAt: new Date().toISOString(),
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
if (evergreenPromptOffsets.has(summary.nextOffset)) {
|
|
421
|
+
return {
|
|
422
|
+
ok: false,
|
|
423
|
+
missingTools: [],
|
|
424
|
+
calls,
|
|
425
|
+
connectionOnlyEvergreenGuidance:
|
|
426
|
+
summarizeConnectionOnlyEvergreenProofs(
|
|
427
|
+
connectionOnlyEvergreenProofs
|
|
428
|
+
),
|
|
429
|
+
error:
|
|
430
|
+
"create-evergreen-campaigns prompt chunk repeated nextOffset",
|
|
431
|
+
startedAt,
|
|
432
|
+
completedAt: new Date().toISOString(),
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
if (
|
|
436
|
+
evergreenPromptChunks >= CONNECTION_ONLY_EVERGREEN_MAX_PROMPT_CHUNKS
|
|
437
|
+
) {
|
|
438
|
+
return {
|
|
439
|
+
ok: false,
|
|
440
|
+
missingTools: [],
|
|
441
|
+
calls,
|
|
442
|
+
connectionOnlyEvergreenGuidance:
|
|
443
|
+
summarizeConnectionOnlyEvergreenProofs(
|
|
444
|
+
connectionOnlyEvergreenProofs
|
|
445
|
+
),
|
|
446
|
+
error:
|
|
447
|
+
"create-evergreen-campaigns prompt exceeded smoke chunk limit",
|
|
448
|
+
startedAt,
|
|
449
|
+
completedAt: new Date().toISOString(),
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
nextCall = {
|
|
454
|
+
...nextCall,
|
|
455
|
+
arguments: {
|
|
456
|
+
...nextCall.arguments,
|
|
457
|
+
offset: summary.nextOffset,
|
|
458
|
+
limit:
|
|
459
|
+
nextCall.arguments?.limit ||
|
|
460
|
+
CONNECTION_ONLY_EVERGREEN_PROMPT_CHUNK_LIMIT,
|
|
461
|
+
},
|
|
462
|
+
};
|
|
463
|
+
} catch (err) {
|
|
464
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
465
|
+
calls.push({
|
|
466
|
+
name: nextCall.name,
|
|
467
|
+
arguments: nextCall.arguments,
|
|
319
468
|
ok: false,
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
startedAt,
|
|
469
|
+
summary: null,
|
|
470
|
+
error: redact(error),
|
|
471
|
+
startedAt: callStartedAt,
|
|
324
472
|
completedAt: new Date().toISOString(),
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
if (
|
|
328
|
-
call.name === "get_subskill_prompt" &&
|
|
329
|
-
call.arguments?.subskillName === "create-evergreen-campaigns" &&
|
|
330
|
-
summary.connectionOnlyEvergreenGuidance !== true
|
|
331
|
-
) {
|
|
473
|
+
});
|
|
332
474
|
return {
|
|
333
475
|
ok: false,
|
|
334
476
|
missingTools: [],
|
|
335
477
|
calls,
|
|
336
|
-
error:
|
|
337
|
-
"create-evergreen-campaigns prompt is missing connection-only guidance",
|
|
478
|
+
error: redact(error),
|
|
338
479
|
startedAt,
|
|
339
480
|
completedAt: new Date().toISOString(),
|
|
340
481
|
};
|
|
341
482
|
}
|
|
342
|
-
} catch (err) {
|
|
343
|
-
const error = err instanceof Error ? err.message : String(err);
|
|
344
|
-
calls.push({
|
|
345
|
-
name: call.name,
|
|
346
|
-
arguments: call.arguments,
|
|
347
|
-
ok: false,
|
|
348
|
-
summary: null,
|
|
349
|
-
error: redact(error),
|
|
350
|
-
startedAt: callStartedAt,
|
|
351
|
-
completedAt: new Date().toISOString(),
|
|
352
|
-
});
|
|
353
|
-
return {
|
|
354
|
-
ok: false,
|
|
355
|
-
missingTools: [],
|
|
356
|
-
calls,
|
|
357
|
-
error: redact(error),
|
|
358
|
-
startedAt,
|
|
359
|
-
completedAt: new Date().toISOString(),
|
|
360
|
-
};
|
|
361
483
|
}
|
|
362
484
|
}
|
|
363
485
|
|
|
486
|
+
const connectionOnlyEvergreenGuidance =
|
|
487
|
+
summarizeConnectionOnlyEvergreenProofs(connectionOnlyEvergreenProofs);
|
|
488
|
+
if (connectionOnlyEvergreenGuidance.ok !== true) {
|
|
489
|
+
return {
|
|
490
|
+
ok: false,
|
|
491
|
+
missingTools: [],
|
|
492
|
+
calls,
|
|
493
|
+
connectionOnlyEvergreenGuidance,
|
|
494
|
+
error: `create-evergreen-campaigns prompt is missing connection-only guidance: ${connectionOnlyEvergreenGuidance.missing.join(", ")}`,
|
|
495
|
+
startedAt,
|
|
496
|
+
completedAt: new Date().toISOString(),
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
|
|
364
500
|
return {
|
|
365
501
|
ok: true,
|
|
366
502
|
missingTools: [],
|
|
367
503
|
calls,
|
|
504
|
+
connectionOnlyEvergreenGuidance,
|
|
368
505
|
error: null,
|
|
369
506
|
startedAt,
|
|
370
507
|
completedAt: new Date().toISOString(),
|
package/package.json
CHANGED
|
@@ -854,11 +854,11 @@ not a parent-thread summary. The receipt must include:
|
|
|
854
854
|
endpoint/tool to put the unlaunched campaign into `PAUSED` review state, then
|
|
855
855
|
reread the campaign/table. Do not raw-write `campaignStatus`, do not start or
|
|
856
856
|
launch, and do not schedule/send. Completion requires reread proof of
|
|
857
|
-
`currentStep:"send"` and `campaignStatus:"PAUSED"` for standard
|
|
858
|
-
customer-visible lanes.
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
857
|
+
`currentStep:"send"` and `campaignStatus:"PAUSED"` for standard and
|
|
858
|
+
connection-only customer-visible lanes. `send` is the product's paused
|
|
859
|
+
review step; do not use unsupported aliases such as `review` as final proof.
|
|
860
|
+
If the raw output nests this in `finalCampaignRead` or `finalTableRead`, copy
|
|
861
|
+
it to canonical
|
|
862
862
|
`finalPausedSendProof.currentStep` and
|
|
863
863
|
`finalPausedSendProof.campaignStatus`.
|
|
864
864
|
- `verifyCall`: the exact `setup_evergreen_campaigns({ mode:"verify",
|