@sellable/mcp 0.1.557 → 0.1.559

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.
Files changed (63) hide show
  1. package/README.md +2 -13
  2. package/agents/registry.json +2 -2
  3. package/dist/api.js +6 -3
  4. package/dist/auth.d.ts +6 -0
  5. package/dist/auth.js +44 -2
  6. package/dist/refill-contract.d.ts +157 -0
  7. package/dist/refill-contract.js +487 -0
  8. package/dist/refill-run-client.d.ts +10 -0
  9. package/dist/refill-run-client.js +22 -0
  10. package/dist/refill-run-loop.d.ts +14 -2
  11. package/dist/refill-run-loop.js +169 -18
  12. package/dist/server.js +0 -23
  13. package/dist/tools/auth.d.ts +5 -0
  14. package/dist/tools/auth.js +49 -12
  15. package/dist/tools/campaign-message-preparation.d.ts +62 -0
  16. package/dist/tools/campaign-message-preparation.js +41 -0
  17. package/dist/tools/campaigns.js +2 -2
  18. package/dist/tools/csv-dnc.js +2 -2
  19. package/dist/tools/evergreen-refill-plan.d.ts +3 -0
  20. package/dist/tools/evergreen-refill-plan.js +29 -7
  21. package/dist/tools/leads.d.ts +32 -317
  22. package/dist/tools/leads.js +10 -171
  23. package/dist/tools/model-quality.js +6 -4
  24. package/dist/tools/prompts.d.ts +3 -3
  25. package/dist/tools/prompts.js +15 -7
  26. package/dist/tools/provider-preflight.d.ts +2 -65
  27. package/dist/tools/provider-preflight.js +10 -97
  28. package/dist/tools/readiness.d.ts +5 -89
  29. package/dist/tools/readiness.js +0 -66
  30. package/dist/tools/refill-executors.d.ts +38 -0
  31. package/dist/tools/refill-executors.js +222 -3
  32. package/dist/tools/refill-sends-v2.d.ts +118 -1
  33. package/dist/tools/refill-sends-v2.js +312 -3
  34. package/dist/tools/refill-sends.d.ts +678 -32
  35. package/dist/tools/refill-sends.js +274 -13
  36. package/dist/tools/refill-target-plan.js +486 -14
  37. package/dist/tools/registry.d.ts +115 -330
  38. package/dist/tools/registry.js +1 -7
  39. package/dist/tools/scheduler-fill-capacity.js +1 -1
  40. package/dist/tools/scheduler-run.d.ts +71 -0
  41. package/dist/tools/scheduler-run.js +203 -1
  42. package/dist/tools/setup-evergreen-campaigns.js +1 -1
  43. package/dist/tools/workspace-context.d.ts +1 -1
  44. package/dist/tools/workspace-context.js +8 -3
  45. package/dist/tools/workspace-export.js +2 -2
  46. package/dist/tools/workspaces.d.ts +48 -2
  47. package/dist/tools/workspaces.js +48 -5
  48. package/package.json +1 -1
  49. package/skills/create-campaign/SKILL.md +3 -3
  50. package/skills/create-campaign-v2/SKILL.md +1 -1
  51. package/skills/create-evergreen-campaigns/SKILL.md +16 -16
  52. package/skills/find-leads/SKILL.md +630 -48
  53. package/skills/refill-sends/SKILL.md +94 -353
  54. package/skills/refill-sends-v2/SKILL.md +6 -6
  55. package/skills/refill-sends-v2-workflow/SKILL.md +5 -5
  56. package/skills/refill-sends-v2-workflow/core/flow.v1.json +8 -8
  57. package/skills/refill-sends-workflow/SKILL.md +100 -743
  58. package/skills/refill-sends-workflow/core/contract.v2.json +543 -0
  59. package/skills/refill-sends-workflow/core/flow.v1.json +185 -1
  60. package/dist/tools/find-leads-runs.d.ts +0 -151
  61. package/dist/tools/find-leads-runs.js +0 -98
  62. package/skills/find-leads-v2/SKILL.md +0 -70
  63. package/skills/find-leads-v2/core/flow.v1.json +0 -31
@@ -1,5 +1,5 @@
1
1
  import { getApi, resetApi } from "../api.js";
2
- import { getConfig, updateActiveWorkspace } from "../auth.js";
2
+ import { getConfig, getEffectiveConfiguredWorkspaceId, getLockedWorkspaceId, resolveWorkspaceIdForRequest, updateActiveWorkspace, } from "../auth.js";
3
3
  export const workspaceToolDefinitions = [
4
4
  {
5
5
  name: "list_workspaces",
@@ -81,21 +81,53 @@ export const workspaceToolDefinitions = [
81
81
  export async function listWorkspaces() {
82
82
  const api = getApi();
83
83
  const { workspaces } = await api.get("/api/v3/workspaces");
84
- return { workspaces };
84
+ const lockedWorkspaceId = getLockedWorkspaceId();
85
+ if (!lockedWorkspaceId) {
86
+ return { workspaces, workspaceLock: { enabled: false } };
87
+ }
88
+ return {
89
+ workspaces: workspaces.filter((ws) => ws.id === lockedWorkspaceId),
90
+ workspaceLock: {
91
+ enabled: true,
92
+ workspaceId: lockedWorkspaceId,
93
+ hiddenWorkspaceCount: workspaces.filter((ws) => ws.id !== lockedWorkspaceId).length,
94
+ },
95
+ };
85
96
  }
86
97
  export function getActiveWorkspace() {
87
98
  const config = getConfig();
99
+ const lockedWorkspaceId = getLockedWorkspaceId();
88
100
  return {
89
- activeWorkspaceId: config.activeWorkspaceId || config.workspaceId || null,
101
+ activeWorkspaceId: getEffectiveConfiguredWorkspaceId(config),
90
102
  activeWorkspaceName: config.activeWorkspaceName || null,
103
+ workspaceLock: lockedWorkspaceId
104
+ ? { enabled: true, workspaceId: lockedWorkspaceId }
105
+ : { enabled: false },
91
106
  };
92
107
  }
93
108
  export async function getWorkspace(workspaceId) {
109
+ const allowedWorkspaceId = resolveWorkspaceIdForRequest(workspaceId, "get_workspace");
110
+ if (!allowedWorkspaceId) {
111
+ return {
112
+ ok: false,
113
+ error: "No active workspace selected.",
114
+ };
115
+ }
94
116
  const api = getApi();
95
- const { workspace } = await api.get(`/api/v3/workspaces/${encodeURIComponent(workspaceId)}`);
117
+ const { workspace } = await api.get(`/api/v3/workspaces/${encodeURIComponent(allowedWorkspaceId)}`);
96
118
  return { workspace };
97
119
  }
98
120
  export async function setActiveWorkspace(workspaceId, userConfirmed) {
121
+ const lockedWorkspaceId = getLockedWorkspaceId();
122
+ if (lockedWorkspaceId && workspaceId !== lockedWorkspaceId) {
123
+ return {
124
+ ok: false,
125
+ code: "WORKSPACE_LOCKED",
126
+ activeWorkspaceId: lockedWorkspaceId,
127
+ requestedWorkspaceId: workspaceId,
128
+ error: "This Hermes profile is locked to its customer workspace and cannot switch workspaces.",
129
+ };
130
+ }
99
131
  const api = getApi();
100
132
  const { workspaces } = await api.get("/api/v3/workspaces");
101
133
  const match = workspaces.find((ws) => ws.id === workspaceId);
@@ -131,6 +163,15 @@ export async function setActiveWorkspace(workspaceId, userConfirmed) {
131
163
  };
132
164
  }
133
165
  export async function createWorkspace(name) {
166
+ const lockedWorkspaceId = getLockedWorkspaceId();
167
+ if (lockedWorkspaceId) {
168
+ return {
169
+ ok: false,
170
+ code: "WORKSPACE_LOCKED",
171
+ activeWorkspaceId: lockedWorkspaceId,
172
+ error: "This Hermes profile is locked to its customer workspace and cannot create or switch workspaces. Use the sellable-admin profile for provisioning.",
173
+ };
174
+ }
134
175
  const api = getApi();
135
176
  const { workspace } = await api.post("/api/v3/workspaces", { name });
136
177
  updateActiveWorkspace({
@@ -146,7 +187,9 @@ export async function createWorkspace(name) {
146
187
  export async function addTeammate(input) {
147
188
  const args = input || {};
148
189
  const config = getConfig();
149
- const workspaceId = args.workspaceId || config.activeWorkspaceId || config.workspaceId;
190
+ const workspaceId = resolveWorkspaceIdForRequest(args.workspaceId ||
191
+ getEffectiveConfiguredWorkspaceId(config) ||
192
+ undefined, "add_teammate");
150
193
  if (!workspaceId) {
151
194
  return {
152
195
  ok: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.557",
3
+ "version": "0.1.559",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code, Codex, and Hermes campaign workflows",
6
6
  "main": "dist/index.js",
@@ -721,7 +721,7 @@ Treat host capabilities as concrete functions, not prose conventions:
721
721
  import and before dispatching Message Drafting only.
722
722
  - `launch_message_drafting`: Claude Code uses `Task` with `subagent_type`
723
723
  `post-find-leads-message-scout` when listed; Codex uses the returned
724
- compatibility agent or a generic `gpt-5.5` / `xhigh` Message Drafting agent.
724
+ compatibility agent or a generic `gpt-5.6-sol` / `high` Message Drafting agent.
725
725
 
726
726
  If a required interactive question function or MCP loader is missing, stop and
727
727
  explain the Sellable install/reload problem. Source work uses product-native MCP
@@ -1082,8 +1082,8 @@ updates.
1082
1082
  In Codex, the filter-choice answer is the campaign-scoped go-ahead to use
1083
1083
  this single Message Drafting background agent in step-wise and YOLO modes.
1084
1084
  Do not ask a separate question to start it. If the named custom agent is not
1085
- available, spawn a generic background agent with `model: "gpt-5.5"` and
1086
- `reasoning_effort: "xhigh"` using the same lean campaign/table basis. If no
1085
+ available, spawn a generic background agent with `model: "gpt-5.6-sol"` and
1086
+ `reasoning_effort: "high"` using the same lean campaign/table basis. If no
1087
1087
  background-agent tool is callable, start the same full message branch inline
1088
1088
  before filter drafting or skip-filter message review and record it as
1089
1089
  `statusSource: "parent-thread-fallback"`.
@@ -291,7 +291,7 @@ in the branch read means "filters still owned by parent," not `blocked`.
291
291
 
292
292
  Keep the handoff lean: `campaignId`, `workflowTableId`, concise brief/source summary, source-use rule, and 3-5 sample rows (`rowId`, name, title, company, signal). Do not paste copied row counts, hashes, full row IDs, broad row data, or local debug artifacts.
293
293
 
294
- Route user copy feedback before `approve-message` back to Message Drafting; parent does not rewrite. The branch loads the full `generate-messages` prompt, every required asset, then `get_subskill_prompt({ subskillName: "create-campaign-v2-validation" })`; do not render `renderedFallbackSample`, concerns, or `qaReceipt` in the happy path. Generic fallback is `gpt-5.5` / `xhigh` Message Drafting. Handoff is labeled Markdown, not raw JSON.
294
+ Route user copy feedback before `approve-message` back to Message Drafting; parent does not rewrite. The branch loads the full `generate-messages` prompt, every required asset, then `get_subskill_prompt({ subskillName: "create-campaign-v2-validation" })`; do not render `renderedFallbackSample`, concerns, or `qaReceipt` in the happy path. Generic fallback is `gpt-5.6-sol` / `high` Message Drafting. Handoff is labeled Markdown, not raw JSON.
295
295
 
296
296
  ## Hard Gates
297
297
 
@@ -437,7 +437,7 @@ fallback only when app thread tools are unavailable; the receipt must include
437
437
  `fallbackReason`, or backend verify rejects it.
438
438
  When visible Codex app thread tools are unavailable but local Codex CLI is
439
439
  available, the accepted durable streaming-worker command shape is:
440
- `codex -a never -s danger-full-access -c model_reasoning_effort=xhigh exec --skip-git-repo-check -m <worker-model> -C <repo> -o <worker-final-file> -`.
440
+ `codex -a never -s danger-full-access -c model_reasoning_effort=high exec --skip-git-repo-check -m <worker-model> -C <repo> -o <worker-final-file> -`.
441
441
  The approval, sandbox, and reasoning-effort config flags must come before the
442
442
  `exec` subcommand for Codex CLI builds that expose `-a`/`-s`/`-c` only at top
443
443
  level. `--skip-git-repo-check` belongs after `exec` because current customer and VPS Codex CLI builds expose it
@@ -447,26 +447,26 @@ forms fail on current customer CLI installs. Pipe the lane packet prompt on
447
447
  stdin, require the worker to write `workerDispatch.receiptArtifactHint`, and
448
448
  pass exactly one lane packet per worker.
449
449
  When launching durable Codex CLI workers from an automation parent, pass an
450
- explicit supported worker model and explicit `xhigh` reasoning effort instead
450
+ explicit supported worker model and explicit `high` reasoning effort instead
451
451
  of relying on the Codex CLI defaults. Use the parent runtime model when known,
452
452
  for example:
453
- `codex -a never -s danger-full-access -c model_reasoning_effort=xhigh exec --skip-git-repo-check -m <worker-model> -C <repo> -o <worker-final-file> -`.
453
+ `codex -a never -s danger-full-access -c model_reasoning_effort=high exec --skip-git-repo-check -m <worker-model> -C <repo> -o <worker-final-file> -`.
454
454
  In Codex CLI, the parent runtime model is visible in the run header as
455
455
  `model: <model-name>`. Copy that exact model string into child worker launches
456
- first. If the parent header says `model: gpt-5.5`, launch workers with
457
- `-m gpt-5.5` plus `-c model_reasoning_effort=xhigh`; do not invent or probe
456
+ first. If the parent header says `model: gpt-5.6-sol`, launch workers with
457
+ `-m gpt-5.6-sol` plus `-c model_reasoning_effort=high`; do not invent or probe
458
458
  nearby aliases such as `gpt-5.3-codex`, `gpt-5.2`, `gpt-5-codex`,
459
459
  `codex-latest`, or `codex-mini-latest` before trying the exact parent model. A
460
- one-line probe must include the same `-c model_reasoning_effort=xhigh` override
460
+ one-line probe must include the same `-c model_reasoning_effort=high` override
461
461
  and count as supported only when it exits 0 and returns the requested output; a
462
462
  session header followed by a `not supported` error is rejected, not accepted.
463
463
  Do not rely on the Codex CLI default model or default reasoning effort; some
464
- customer and VPS installs default to unavailable model aliases or to `high`
465
- reasoning. `-m gpt-5.5` alone is not enough. If a child worker reports GPT 5.5
466
- with `high` reasoning, treat that as a launcher bug, relaunch with the explicit
467
- `xhigh` config before mutation, and do not ask the user to continue through the
464
+ customer and VPS installs default to unavailable model aliases or to reasoning
465
+ below `high`. `-m gpt-5.6-sol` alone is not enough. If a child worker reports GPT 5.6-Sol
466
+ with reasoning below `high`, treat that as a launcher bug, relaunch with the explicit
467
+ `high` config before mutation, and do not ask the user to continue through the
468
468
  model-quality warning. If the parent cannot identify a supported worker model
469
- and launch it with `xhigh` reasoning, stop with
469
+ and launch it with `high` reasoning, stop with
470
470
  `blocked: worker_model_unavailable` before mutation.
471
471
  When wrapping multiple local Codex CLI workers in a shell launcher, run the
472
472
  wrapper with `/bin/bash -lc` or another explicitly chosen portable shell. Do not
@@ -479,7 +479,7 @@ Do not embed `<<'WORKER_PROMPT'` heredocs inside a single quoted or double
479
479
  quoted `/bin/bash -lc '...'` command string; nested quoting is brittle and can
480
480
  truncate the first worker before mutation. For multi-worker launchers, write one
481
481
  plain prompt file per lane under the current run directory, then start each
482
- worker with `codex -a never -s danger-full-access -c model_reasoning_effort=xhigh exec --skip-git-repo-check -m "$WORKER_MODEL" -C "$REPO" -o
482
+ worker with `codex -a never -s danger-full-access -c model_reasoning_effort=high exec --skip-git-repo-check -m "$WORKER_MODEL" -C "$REPO" -o
483
483
  "$worker_final_file" - < "$worker_prompt_file"`. Keep launcher shell variables
484
484
  double-quoted and keep the prompt heredoc only in a standalone script/prompt-file
485
485
  write step, not inside an already quoted shell argument. If the first launcher
@@ -585,7 +585,7 @@ launchers, write the same prompt body to `<worker-prompt-file>` and launch the
585
585
  worker with stdin redirected from that file:
586
586
 
587
587
  ```
588
- codex -a never -s danger-full-access -c model_reasoning_effort=xhigh exec --skip-git-repo-check -m <worker-model> -C <repo> -o <worker-final-file> - <<'WORKER_PROMPT'
588
+ codex -a never -s danger-full-access -c model_reasoning_effort=high exec --skip-git-repo-check -m <worker-model> -C <repo> -o <worker-final-file> - <<'WORKER_PROMPT'
589
589
  Use $sellable:create-campaign as the governing campaign workflow for this one lane worker.
590
590
  Use the evergreen plan/packet below only for lane scope, source metadata,
591
591
  postconditions, side-effect caps, and durable receipt proof.
@@ -632,10 +632,10 @@ Do not launch, start, schedule, send, or use paid InMail.
632
632
  For filter proof, durable receipt status must be `filterDecisionReceipt.status:"applied"` only; never `completed`, `confirmed`, `done`, or aliases.
633
633
  For generated messages, `update_cell` is allowed only for the semantic Approved checkbox. Never use `update_cell` for generated message text/body/sample copy. Bad copy requires `revise_message_template_and_rerun` or brief/template revision plus Generate Message rerun. Any generated-message cell override is `blocked: generated_message_cell_override`.
634
634
  If `bootstrap_create_campaign.modelQuality.status === "warn"` because the child
635
- worker reports GPT 5.5 with `high` reasoning, that is a parent launcher
635
+ worker reports GPT 5.6-Sol with reasoning below `high`, that is a parent launcher
636
636
  configuration bug, not an operator approval path inside the worker. Stop before
637
637
  mutation, tell the parent to relaunch this lane with
638
- `-c model_reasoning_effort=xhigh`, and do not mark the worker goal complete.
638
+ `-c model_reasoning_effort=high`, and do not mark the worker goal complete.
639
639
  Complete only this lane. Do not end with narration only. Before your final
640
640
  response, run a local file-existence and JSON self-check for
641
641
  <receiptArtifactPath>. If the lane succeeded, write the canonical success
@@ -656,7 +656,7 @@ receipt, or an accepted Post Engagers no-source blocked/no-op receipt.
656
656
  WORKER_PROMPT
657
657
 
658
658
  # Multi-worker launcher equivalent:
659
- codex -a never -s danger-full-access -c model_reasoning_effort=xhigh exec --skip-git-repo-check -m <worker-model> -C <repo> -o <worker-final-file> - < <worker-prompt-file>
659
+ codex -a never -s danger-full-access -c model_reasoning_effort=high exec --skip-git-repo-check -m <worker-model> -C <repo> -o <worker-final-file> - < <worker-prompt-file>
660
660
  ```
661
661
 
662
662
  If any placeholder cannot be filled from the current plan, matching